Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(539)

Unified Diff: chrome/browser/webshare/share_service_impl_unittest.cc

Issue 2688413006: Fixed crash if tab closes while WebShare picker dialog is open. (Closed)
Patch Set: Fix comments. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/webshare/share_service_impl.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/webshare/share_service_impl_unittest.cc
diff --git a/chrome/browser/webshare/share_service_impl_unittest.cc b/chrome/browser/webshare/share_service_impl_unittest.cc
index 11f4be7dfe7e6b408da294bd3794c6e1f50d1f04..7f41bc4a4878f46ce10895e3fa8ed92ca29c7882 100644
--- a/chrome/browser/webshare/share_service_impl_unittest.cc
+++ b/chrome/browser/webshare/share_service_impl_unittest.cc
@@ -34,6 +34,11 @@ constexpr char kManifestUrlLow[] =
constexpr char kManifestUrlMin[] =
"https://www.example-min.com/target/manifest.json";
+void DidShare(const base::Optional<std::string>& expected_error,
+ const base::Optional<std::string>& error) {
+ EXPECT_EQ(expected_error, error);
+}
+
class ShareServiceTestImpl : public ShareServiceImpl {
public:
explicit ShareServiceTestImpl(blink::mojom::ShareServiceRequest request)
@@ -45,10 +50,6 @@ class ShareServiceTestImpl : public ShareServiceImpl {
prefs::kWebShareVisitedTargets);
}
- void set_picker_result(base::Optional<std::string> result) {
- picker_result_ = result;
- }
-
void AddShareTargetToPrefs(const std::string& manifest_url,
const std::string& name,
const std::string& url_template) {
@@ -74,19 +75,32 @@ class ShareServiceTestImpl : public ShareServiceImpl {
engagement_map_[manifest_url] = level;
}
+ void set_runloop(base::RunLoop* runloop) {
Sam McNally 2017/02/16 02:12:24 run_loop
Matt Giuca 2017/02/16 02:25:38 Done.
+ quit_runloop_ = runloop->QuitClosure();
+ }
+
const std::string& GetLastUsedTargetURL() { return last_used_target_url_; }
const std::vector<std::pair<base::string16, GURL>>& GetTargetsInPicker() {
return targets_in_picker_;
}
+ const base::Callback<void(base::Optional<std::string>)>& picker_callback() {
+ return picker_callback_;
+ }
+
private:
void ShowPickerDialog(
const std::vector<std::pair<base::string16, GURL>>& targets,
const base::Callback<void(base::Optional<std::string>)>& callback)
override {
+ // Store the arguments passed to the picker dialog.
targets_in_picker_ = targets;
- callback.Run(picker_result_);
+ picker_callback_ = callback;
+
+ // Quit the test's run loop. It is the test's responsibility to call the
+ // callback, to simulate the user's choice.
+ quit_runloop_.Run();
}
void OpenTargetURL(const GURL& target_url) override {
@@ -100,12 +114,19 @@ class ShareServiceTestImpl : public ShareServiceImpl {
}
mojo::Binding<blink::mojom::ShareService> binding_;
-
- base::Optional<std::string> picker_result_;
- std::string last_used_target_url_;
std::unique_ptr<TestingPrefServiceSimple> pref_service_;
+
std::map<std::string, blink::mojom::EngagementLevel> engagement_map_;
+ // Closure to quit the test's run loop.
+ base::Closure quit_runloop_;
Sam McNally 2017/02/16 02:12:24 quit_run_loop_
Matt Giuca 2017/02/16 02:25:39 Done.
+
+ // The last URL passed to OpenTargetURL.
+ std::string last_used_target_url_;
+ // The targets passed to ShowPickerDialog.
std::vector<std::pair<base::string16, GURL>> targets_in_picker_;
+ // The callback passed to ShowPickerDialog (which is supposed to be called
+ // with the user's chosen result, or nullopt if cancelled).
+ base::Callback<void(base::Optional<std::string>)> picker_callback_;
};
class ShareServiceImplUnittest : public ChromeRenderViewHostTestHarness {
@@ -129,27 +150,19 @@ class ShareServiceImplUnittest : public ChromeRenderViewHostTestHarness {
void TearDown() override { ChromeRenderViewHostTestHarness::TearDown(); }
- void DidShare(const std::vector<std::pair<base::string16, GURL>>&
- expected_targets_in_picker,
- const std::string& expected_target_url,
- const base::Optional<std::string>& expected_error,
- const base::Optional<std::string>& error) {
- std::vector<std::pair<base::string16, GURL>> targets_in_picker =
- share_service_helper_->GetTargetsInPicker();
- EXPECT_EQ(expected_targets_in_picker, targets_in_picker);
-
- std::string target_url = share_service_helper_->GetLastUsedTargetURL();
- EXPECT_EQ(expected_target_url, target_url);
-
- EXPECT_EQ(expected_error, error);
+ blink::mojom::ShareService* share_service() const {
+ return share_service_.get();
+ }
- if (!on_callback_.is_null())
- on_callback_.Run();
+ 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_;
- base::Closure on_callback_;
};
} // namespace
@@ -157,80 +170,92 @@ class ShareServiceImplUnittest : public ChromeRenderViewHostTestHarness {
// Basic test to check the Share method calls the callback with the expected
// parameters.
TEST_F(ShareServiceImplUnittest, ShareCallbackParams) {
- share_service_helper_->set_picker_result(
- base::Optional<std::string>(kManifestUrlLow));
-
- share_service_helper_->AddShareTargetToPrefs(kManifestUrlLow, kTargetName,
- kUrlTemplate);
- share_service_helper_->AddShareTargetToPrefs(kManifestUrlHigh, kTargetName,
- kUrlTemplate);
+ share_service_helper()->AddShareTargetToPrefs(kManifestUrlLow, kTargetName,
+ kUrlTemplate);
+ share_service_helper()->AddShareTargetToPrefs(kManifestUrlHigh, kTargetName,
+ kUrlTemplate);
std::string expected_url =
"https://www.example-low.com/target/"
"share?title=My%20title&text=My%20text&url=https%3A%2F%2Fwww."
"google.com%2F";
-
std::vector<std::pair<base::string16, GURL>> expected_targets{
Sam McNally 2017/02/16 02:12:24 Create these closer to where they're used. Also co
Matt Giuca 2017/02/16 02:25:39 Done.
make_pair(base::UTF8ToUTF16(kTargetName), GURL(kManifestUrlHigh)),
make_pair(base::UTF8ToUTF16(kTargetName), GURL(kManifestUrlLow))};
+
base::Callback<void(const base::Optional<std::string>&)> callback =
- base::Bind(&ShareServiceImplUnittest::DidShare, base::Unretained(this),
- expected_targets, expected_url, base::Optional<std::string>());
+ base::Bind(&DidShare, base::Optional<std::string>());
base::RunLoop run_loop;
- on_callback_ = run_loop.QuitClosure();
+ share_service_helper()->set_runloop(&run_loop);
const GURL url(kUrlSpec);
- share_service_->Share(kTitle, kText, url, callback);
+ share_service()->Share(kTitle, kText, url, callback);
run_loop.Run();
+
+ EXPECT_EQ(expected_targets, share_service_helper()->GetTargetsInPicker());
+
+ // Pick example-low.com.
+ share_service_helper()->picker_callback().Run(
+ base::Optional<std::string>(kManifestUrlLow));
+
+ EXPECT_EQ(expected_url, 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) {
- // picker_result_ is set to nullopt by default, so this imitates the user
- // cancelling a share.
// Expect an error message in response.
base::Callback<void(const base::Optional<std::string>&)> callback =
- base::Bind(&ShareServiceImplUnittest::DidShare, base::Unretained(this),
- std::vector<std::pair<base::string16, GURL>>(), std::string(),
- base::Optional<std::string>("Share was cancelled"));
+ base::Bind(&DidShare, base::Optional<std::string>("Share was cancelled"));
base::RunLoop run_loop;
- on_callback_ = run_loop.QuitClosure();
+ share_service_helper()->set_runloop(&run_loop);
const GURL url(kUrlSpec);
- share_service_->Share(kTitle, kText, url, callback);
+ share_service()->Share(kTitle, kText, url, callback);
run_loop.Run();
+
+ std::vector<std::pair<base::string16, GURL>> expected_targets; // Empty.
+ EXPECT_EQ(expected_targets, share_service_helper()->GetTargetsInPicker());
Sam McNally 2017/02/16 02:12:24 EXPECT_TRUE(share_service_helper()->GetTargetsInPi
Matt Giuca 2017/02/16 02:25:39 Done.
+
+ // Cancel the dialog.
+ share_service_helper()->picker_callback().Run(base::nullopt);
+
+ EXPECT_EQ(GURL(), share_service_helper()->GetLastUsedTargetURL());
}
// Tests the result of cancelling the share in the picker UI, that has targets.
TEST_F(ShareServiceImplUnittest, ShareCancelWithTargets) {
- // picker_result_ is set to nullopt by default, so this imitates the user
- // cancelling a share.
- share_service_helper_->AddShareTargetToPrefs(kManifestUrlHigh, kTargetName,
- kUrlTemplate);
- share_service_helper_->AddShareTargetToPrefs(kManifestUrlLow, kTargetName,
- kUrlTemplate);
+ share_service_helper()->AddShareTargetToPrefs(kManifestUrlHigh, kTargetName,
+ kUrlTemplate);
+ share_service_helper()->AddShareTargetToPrefs(kManifestUrlLow, kTargetName,
+ kUrlTemplate);
std::vector<std::pair<base::string16, GURL>> expected_targets{
make_pair(base::UTF8ToUTF16(kTargetName), GURL(kManifestUrlHigh)),
make_pair(base::UTF8ToUTF16(kTargetName), GURL(kManifestUrlLow))};
+
// Expect an error message in response.
base::Callback<void(const base::Optional<std::string>&)> callback =
- base::Bind(&ShareServiceImplUnittest::DidShare, base::Unretained(this),
- expected_targets, std::string(),
- base::Optional<std::string>("Share was cancelled"));
+ base::Bind(&DidShare, base::Optional<std::string>("Share was cancelled"));
base::RunLoop run_loop;
- on_callback_ = run_loop.QuitClosure();
+ share_service_helper()->set_runloop(&run_loop);
const GURL url(kUrlSpec);
- share_service_->Share(kTitle, kText, url, callback);
+ share_service()->Share(kTitle, kText, url, callback);
run_loop.Run();
+
+ EXPECT_EQ(expected_targets, share_service_helper()->GetTargetsInPicker());
+
+ // Cancel the dialog.
+ share_service_helper()->picker_callback().Run(base::nullopt);
+
+ EXPECT_EQ(GURL(), share_service_helper()->GetLastUsedTargetURL());
Sam McNally 2017/02/16 02:12:24 EXPECT_TRUE(share_service_helper()->GetLastUsedTar
Matt Giuca 2017/02/16 02:25:39 Done.
}
// Test to check that only targets with enough engagement were in picker.
@@ -239,28 +264,66 @@ TEST_F(ShareServiceImplUnittest, ShareWithSomeInsufficientlyEngagedTargets) {
"https://www.example-low.com/target/"
"share?title=My%20title&text=My%20text&url=https%3A%2F%2Fwww."
"google.com%2F";
+ std::vector<std::pair<base::string16, GURL>> expected_targets{
+ make_pair(base::UTF8ToUTF16(kTargetName), GURL(kManifestUrlLow))};
+
+ share_service_helper()->AddShareTargetToPrefs(kManifestUrlMin, kTargetName,
+ kUrlTemplate);
+ share_service_helper()->AddShareTargetToPrefs(kManifestUrlLow, kTargetName,
+ kUrlTemplate);
+
+ base::Callback<void(const base::Optional<std::string>&)> callback =
+ base::Bind(&DidShare, base::Optional<std::string>());
+
+ base::RunLoop run_loop;
+ share_service_helper()->set_runloop(&run_loop);
- share_service_helper_->set_picker_result(
+ const GURL url(kUrlSpec);
+ share_service()->Share(kTitle, kText, url, callback);
+
+ run_loop.Run();
+
+ EXPECT_EQ(expected_targets, share_service_helper()->GetTargetsInPicker());
+
+ // Pick example-low.com.
+ share_service_helper()->picker_callback().Run(
base::Optional<std::string>(kManifestUrlLow));
- share_service_helper_->AddShareTargetToPrefs(kManifestUrlMin, kTargetName,
- kUrlTemplate);
- share_service_helper_->AddShareTargetToPrefs(kManifestUrlLow, kTargetName,
- kUrlTemplate);
+ EXPECT_EQ(expected_url, 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) {
std::vector<std::pair<base::string16, GURL>> expected_targets{
make_pair(base::UTF8ToUTF16(kTargetName), GURL(kManifestUrlLow))};
- base::Callback<void(const base::Optional<std::string>&)> callback =
- base::Bind(&ShareServiceImplUnittest::DidShare, base::Unretained(this),
- expected_targets, expected_url, base::Optional<std::string>());
+
+ share_service_helper()->AddShareTargetToPrefs(kManifestUrlLow, kTargetName,
+ kUrlTemplate);
base::RunLoop run_loop;
- on_callback_ = run_loop.QuitClosure();
+ share_service_helper()->set_runloop(&run_loop);
const GURL url(kUrlSpec);
- share_service_->Share(kTitle, kText, url, callback);
+ // 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::Callback<void(const base::Optional<std::string>&)> callback =
+ base::Bind([](const base::Optional<std::string>& error) { FAIL(); });
+ share_service()->Share(kTitle, kText, url, callback);
run_loop.Run();
+
+ EXPECT_EQ(expected_targets, share_service_helper()->GetTargetsInPicker());
+
+ const base::Callback<void(base::Optional<std::string>)> picker_callback =
+ share_service_helper()->picker_callback();
+
+ DeleteShareService();
+
+ // Pick example-low.com.
+ picker_callback.Run(base::Optional<std::string>(kManifestUrlLow));
}
// Replace various numbers of placeholders in various orders. Placeholders are
« no previous file with comments | « chrome/browser/webshare/share_service_impl.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698