// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <map>
#include <memory>
#include <utility>

#include "base/bind.h"
#include "base/callback.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/webshare/share_service_impl.h"
#include "chrome/browser/webshare/webshare_target.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/prefs/testing_pref_service.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"

namespace {

constexpr char kTitle[] = "My title";
constexpr char kText[] = "My text";
constexpr char kUrlSpec[] = "https://www.google.com/";

constexpr char kTargetName[] = "Share Target";
constexpr char kParamTitle[] = "my title";
constexpr char kParamText[] = "text%";
constexpr char kParamUrl[] = "url";
constexpr char kActionHigh[] = "https://www.example-high.com/target/share";
constexpr char kActionLow[] = "https://www.example-low.com/target/share";
constexpr char kActionLowWithQuery[] =
    "https://www.example-low.com/target/share?a=b&c=d";
constexpr char kActionMin[] = "https://www.example-min.com/target/share";
constexpr char kManifestUrlHigh[] =
    "https://www.example-high.com/target/manifest.json";
constexpr char kManifestUrlLow[] =
    "https://www.example-low.com/target/manifest.json";
constexpr char kManifestUrlMin[] =
    "https://www.example-min.com/target/manifest.json";

void DidShare(blink::mojom::ShareError expected_error,
              blink::mojom::ShareError error) {
  EXPECT_EQ(expected_error, error);
}

class ShareServiceTestImpl : public ShareServiceImpl {
 public:
  explicit ShareServiceTestImpl(blink::mojom::ShareServiceRequest request)
      : binding_(this) {
    binding_.Bind(std::move(request));

    pref_service_.reset(new TestingPrefServiceSimple());
    pref_service_->registry()->RegisterDictionaryPref(
        prefs::kWebShareVisitedTargets);
  }

  void AddShareTargetToPrefs(const std::string& manifest_url,
                             const std::string& name,
                             const std::string& action,
                             const std::string& text,
                             const std::string& title,
                             const std::string& url) {
    constexpr char kActionKey[] = "action";
    constexpr char kNameKey[] = "name";
    constexpr char kTextKey[] = "text";
    constexpr char kTitleKey[] = "title";
    constexpr char kUrlKey[] = "url";

    DictionaryPrefUpdate update(GetPrefService(),
                                prefs::kWebShareVisitedTargets);
    base::DictionaryValue* share_target_dict = update.Get();

    std::unique_ptr<base::DictionaryValue> origin_dict(
        new base::DictionaryValue);

    origin_dict->SetKey(kActionKey, base::Value(action));
    origin_dict->SetKey(kNameKey, base::Value(name));
    origin_dict->SetKey(kTextKey, base::Value(text));
    origin_dict->SetKey(kTitleKey, base::Value(title));
    origin_dict->SetKey(kUrlKey, base::Value(url));

    share_target_dict->SetWithoutPathExpansion(manifest_url,
                                               std::move(origin_dict));
  }

  void SetEngagementForTarget(const std::string& manifest_url,
                              blink::mojom::EngagementLevel level) {
    engagement_map_[manifest_url] = level;
  }

  void set_run_loop(base::RunLoop* run_loop) {
    quit_run_loop_ = run_loop->QuitClosure();
  }

  const std::string& GetLastUsedTargetURL() { return last_used_target_url_; }

  const std::vector<WebShareTarget>& GetTargetsInPicker() {
    return targets_in_picker_;
  }

  void PickTarget(const std::string& target_url) {
    const auto& it =
        std::find_if(targets_in_picker_.begin(), targets_in_picker_.end(),
                     [&target_url](const WebShareTarget& target) {
                       return target.manifest_url().spec() == target_url;
                     });
    DCHECK(it != targets_in_picker_.end());
    std::move(picker_callback_).Run(&*it);
  }

  chrome::WebShareTargetPickerCallback picker_callback() {
    return std::move(picker_callback_);
  }

 private:
  void ShowPickerDialog(
      std::vector<WebShareTarget> targets,
      chrome::WebShareTargetPickerCallback callback) override {
    // Store the arguments passed to the picker dialog.
    targets_in_picker_ = std::move(targets);
    picker_callback_ = std::move(callback);

    // Quit the test's run loop. It is the test's responsibility to call the
    // callback, to simulate the user's choice.
    std::move(quit_run_loop_).Run();
  }

  void OpenTargetURL(const GURL& target_url) override {
    last_used_target_url_ = target_url.spec();
  }

  PrefService* GetPrefService() override { return pref_service_.get(); }

  blink::mojom::EngagementLevel GetEngagementLevel(const GURL& url) override {
    return engagement_map_[url.spec()];
  }

  mojo::Binding<blink::mojom::ShareService> binding_;
  std::unique_ptr<TestingPrefServiceSimple> pref_service_;

  std::map<std::string, blink::mojom::EngagementLevel> engagement_map_;
  // Closure to quit the test's run loop.
  base::OnceClosure quit_run_loop_;

  // The last URL passed to OpenTargetURL.
  std::string last_used_target_url_;
  // The targets passed to ShowPickerDialog.
  std::vector<WebShareTarget> targets_in_picker_;
  // The callback passed to ShowPickerDialog (which is supposed to be called
  // with the user's chosen result, or nullptr if cancelled).
  chrome::WebShareTargetPickerCallback picker_callback_;
};

class ShareServiceImplUnittest : public ChromeRenderViewHostTestHarness {
 public:
  ShareServiceImplUnittest() = default;
  ~ShareServiceImplUnittest() override = default;

  void SetUp() override {
    ChromeRenderViewHostTestHarness::SetUp();

    share_service_helper_ = std::make_unique<ShareServiceTestImpl>(
        mojo::MakeRequest(&share_service_));

    share_service_helper_->SetEngagementForTarget(
        kManifestUrlHigh, blink::mojom::EngagementLevel::HIGH);
    share_service_helper_->SetEngagementForTarget(
        kManifestUrlMin, blink::mojom::EngagementLevel::MINIMAL);
    share_service_helper_->SetEngagementForTarget(
        kManifestUrlLow, blink::mojom::EngagementLevel::LOW);
  }

  blink::mojom::ShareService* share_service() const {
    return share_service_.get();
  }

  ShareServiceTestImpl* share_service_helper() const {
    return share_service_helper_.get();
  }

  void DeleteShareService() { share_service_helper_.reset(); }

 private:
  blink::mojom::ShareServicePtr share_service_;
  std::unique_ptr<ShareServiceTestImpl> share_service_helper_;
};

}  // namespace

// Basic test to check the Share method calls the callback with the expected
// parameters.
TEST_F(ShareServiceImplUnittest, ShareCallbackParams) {
  share_service_helper()->AddShareTargetToPrefs(kManifestUrlLow, kTargetName,
                                                kActionLow, kParamText,
                                                kParamTitle, kParamUrl);
  share_service_helper()->AddShareTargetToPrefs(kManifestUrlHigh, kTargetName,
                                                kActionHigh, kParamText,
                                                kParamTitle, kParamUrl);
  // Expect this invalid URL to be ignored (not crash);
  // https://crbug.com/762388.
  share_service_helper()->AddShareTargetToPrefs(
      "", kTargetName, kActionHigh, kParamText, kParamTitle, kParamUrl);

  base::OnceCallback<void(blink::mojom::ShareError)> callback =
      base::BindOnce(&DidShare, blink::mojom::ShareError::OK);

  base::RunLoop run_loop;
  share_service_helper()->set_run_loop(&run_loop);

  const GURL url(kUrlSpec);
  share_service()->Share(kTitle, kText, url, std::move(callback));

  run_loop.Run();

  std::vector<WebShareTarget> expected_targets;
  expected_targets.emplace_back(GURL(kManifestUrlHigh), kTargetName,
                                GURL(kActionHigh), kParamText, kParamTitle,
                                kParamUrl);
  expected_targets.emplace_back(GURL(kManifestUrlLow), kTargetName,
                                GURL(kActionLow), kParamText, kParamTitle,
                                kParamUrl);
  EXPECT_EQ(expected_targets, share_service_helper()->GetTargetsInPicker());

  // Pick example-low.com.
  share_service_helper()->PickTarget(kManifestUrlLow);

  const char kExpectedURL[] =
      "https://www.example-low.com/target/"
      "share?my+title=My+title&text%25=My+text&url=https%3A%2F%2Fwww."
      "google.com%2F";
  EXPECT_EQ(kExpectedURL, share_service_helper()->GetLastUsedTargetURL());
}

// Adds URL already containing query parameters.
TEST_F(ShareServiceImplUnittest, ShareCallbackWithQueryString) {
  share_service_helper()->AddShareTargetToPrefs(kManifestUrlLow, kTargetName,
                                                kActionLowWithQuery, kParamText,
                                                kParamTitle, kParamUrl);
  base::OnceCallback<void(blink::mojom::ShareError)> callback =
      base::BindOnce(&DidShare, blink::mojom::ShareError::OK);

  base::RunLoop run_loop;
  share_service_helper()->set_run_loop(&run_loop);

  const GURL url(kUrlSpec);
  share_service()->Share(kTitle, kText, url, std::move(callback));

  run_loop.Run();

  std::vector<WebShareTarget> expected_targets;
  expected_targets.emplace_back(GURL(kManifestUrlLow), kTargetName,
                                GURL(kActionLowWithQuery), kParamText,
                                kParamTitle, kParamUrl);
  EXPECT_EQ(expected_targets, share_service_helper()->GetTargetsInPicker());

  // Pick example-low.com.
  share_service_helper()->PickTarget(kManifestUrlLow);

  const char kExpectedURL[] =
      "https://www.example-low.com/target/"
      "share?my+title=My+title&text%25=My+text&url=https%3A%2F%2Fwww."
      "google.com%2F";
  EXPECT_EQ(kExpectedURL, share_service_helper()->GetLastUsedTargetURL());
}

// Tests the result of cancelling the share in the picker UI, that doesn't have
// any targets.
TEST_F(ShareServiceImplUnittest, ShareCancelNoTargets) {
  // Expect an error message in response.
  base::OnceCallback<void(blink::mojom::ShareError)> callback =
      base::BindOnce(&DidShare, blink::mojom::ShareError::CANCELED);

  base::RunLoop run_loop;
  share_service_helper()->set_run_loop(&run_loop);

  const GURL url(kUrlSpec);
  share_service()->Share(kTitle, kText, url, std::move(callback));

  run_loop.Run();

  EXPECT_TRUE(share_service_helper()->GetTargetsInPicker().empty());

  // Cancel the dialog.
  share_service_helper()->picker_callback().Run(nullptr);

  EXPECT_TRUE(share_service_helper()->GetLastUsedTargetURL().empty());
}

// Tests the result of cancelling the share in the picker UI, that has targets.
TEST_F(ShareServiceImplUnittest, ShareCancelWithTargets) {
  share_service_helper()->AddShareTargetToPrefs(kManifestUrlHigh, kTargetName,
                                                kActionHigh, kParamText,
                                                kParamTitle, kParamUrl);
  share_service_helper()->AddShareTargetToPrefs(kManifestUrlLow, kTargetName,
                                                kActionLow, kParamText,
                                                kParamTitle, kParamUrl);

  // Expect an error message in response.
  base::OnceCallback<void(blink::mojom::ShareError)> callback =
      base::BindOnce(&DidShare, blink::mojom::ShareError::CANCELED);

  base::RunLoop run_loop;
  share_service_helper()->set_run_loop(&run_loop);

  const GURL url(kUrlSpec);
  share_service()->Share(kTitle, kText, url, std::move(callback));

  run_loop.Run();

  std::vector<WebShareTarget> expected_targets;
  expected_targets.emplace_back(GURL(kManifestUrlHigh), kTargetName,
                                GURL(kActionHigh), kParamText, kParamTitle,
                                kParamUrl);
  expected_targets.emplace_back(GURL(kManifestUrlLow), kTargetName,
                                GURL(kActionLow), kParamText, kParamTitle,
                                kParamUrl);
  EXPECT_EQ(expected_targets, share_service_helper()->GetTargetsInPicker());

  // Cancel the dialog.
  share_service_helper()->picker_callback().Run(nullptr);

  EXPECT_TRUE(share_service_helper()->GetLastUsedTargetURL().empty());
}

// Test to check that only targets with enough engagement were in picker.
TEST_F(ShareServiceImplUnittest, ShareWithSomeInsufficientlyEngagedTargets) {
  share_service_helper()->AddShareTargetToPrefs(kManifestUrlMin, kTargetName,
                                                kActionMin, kParamText,
                                                kParamTitle, kParamUrl);
  share_service_helper()->AddShareTargetToPrefs(kManifestUrlLow, kTargetName,
                                                kActionLow, kParamText,
                                                kParamTitle, kParamUrl);

  base::OnceCallback<void(blink::mojom::ShareError)> callback =
      base::BindOnce(&DidShare, blink::mojom::ShareError::OK);

  base::RunLoop run_loop;
  share_service_helper()->set_run_loop(&run_loop);

  const GURL url(kUrlSpec);
  share_service()->Share(kTitle, kText, url, std::move(callback));

  run_loop.Run();

  std::vector<WebShareTarget> expected_targets;
  expected_targets.emplace_back(GURL(kManifestUrlLow), kTargetName,
                                GURL(kActionLow), kParamText, kParamTitle,
                                kParamUrl);
  EXPECT_EQ(expected_targets, share_service_helper()->GetTargetsInPicker());

  // Pick example-low.com.
  share_service_helper()->PickTarget(kManifestUrlLow);

  const char kExpectedURL[] =
      "https://www.example-low.com/target/"
      "share?my+title=My+title&text%25=My+text&url=https%3A%2F%2Fwww."
      "google.com%2F";
  EXPECT_EQ(kExpectedURL, share_service_helper()->GetLastUsedTargetURL());
}

// Test that deleting the share service while the picker is open does not crash
// (https://crbug.com/690775).
TEST_F(ShareServiceImplUnittest, ShareServiceDeletion) {
  share_service_helper()->AddShareTargetToPrefs(kManifestUrlLow, kTargetName,
                                                kActionLow, kParamText,
                                                kParamTitle, kParamUrl);

  base::RunLoop run_loop;
  share_service_helper()->set_run_loop(&run_loop);

  const GURL url(kUrlSpec);
  // Expect the callback to never be called (since the share service is
  // destroyed before the picker is closed).
  // TODO(mgiuca): This probably should still complete the share, if not
  // cancelled, even if the underlying tab is closed.
  base::OnceCallback<void(blink::mojom::ShareError)> callback =
      base::BindOnce([](blink::mojom::ShareError error) { FAIL(); });
  share_service()->Share(kTitle, kText, url, std::move(callback));

  run_loop.Run();

  std::vector<WebShareTarget> expected_targets;
  expected_targets.emplace_back(GURL(kManifestUrlLow), kTargetName,
                                GURL(kActionLow), kParamText, kParamTitle,
                                kParamUrl);
  EXPECT_EQ(expected_targets, share_service_helper()->GetTargetsInPicker());

  chrome::WebShareTargetPickerCallback picker_callback =
      share_service_helper()->picker_callback();

  DeleteShareService();

  // Pick example-low.com.
  std::move(picker_callback).Run(&expected_targets[0]);
}
