Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/webstore_inline_installer.h" | 5 #include "chrome/browser/extensions/webstore_inline_installer.h" |
| 6 | 6 |
| 7 #include "base/json/json_reader.h" | 7 #include "base/json/json_reader.h" |
| 8 #include "base/macros.h" | 8 #include "base/macros.h" |
| 9 #include "base/memory/ptr_util.h" | 9 #include "base/memory/ptr_util.h" |
| 10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 109 ProgrammableInstallPrompt::g_done_callback = nullptr; | 109 ProgrammableInstallPrompt::g_done_callback = nullptr; |
| 110 | 110 |
| 111 // Fake inline installer which creates a programmable prompt in place of | 111 // Fake inline installer which creates a programmable prompt in place of |
| 112 // the normal dialog UI. | 112 // the normal dialog UI. |
| 113 class WebstoreInlineInstallerForTest : public WebstoreInlineInstaller { | 113 class WebstoreInlineInstallerForTest : public WebstoreInlineInstaller { |
| 114 public: | 114 public: |
| 115 WebstoreInlineInstallerForTest(WebContents* contents, | 115 WebstoreInlineInstallerForTest(WebContents* contents, |
| 116 content::RenderFrameHost* host, | 116 content::RenderFrameHost* host, |
| 117 const std::string& extension_id, | 117 const std::string& extension_id, |
| 118 const GURL& requestor_url, | 118 const GURL& requestor_url, |
| 119 const Callback& callback) | 119 const Callback& callback, |
| 120 bool enable_safebrowsing_redirects) | |
| 120 : WebstoreInlineInstaller( | 121 : WebstoreInlineInstaller( |
| 121 contents, | 122 contents, |
| 122 host, | 123 host, |
| 123 kTestExtensionId, | 124 kTestExtensionId, |
| 124 requestor_url, | 125 requestor_url, |
| 125 base::Bind(&WebstoreInlineInstallerForTest::InstallCallback, | 126 base::Bind(&WebstoreInlineInstallerForTest::InstallCallback, |
| 126 base::Unretained(this))), | 127 base::Unretained(this))), |
| 127 install_result_target_(nullptr), | 128 install_result_target_(nullptr), |
| 128 programmable_prompt_(nullptr) {} | 129 programmable_prompt_(nullptr) {} |
| 129 | 130 |
| 130 std::unique_ptr<ExtensionInstallPrompt> CreateInstallUI() override { | 131 std::unique_ptr<ExtensionInstallPrompt> CreateInstallUI() override { |
| 131 programmable_prompt_ = new ProgrammableInstallPrompt(web_contents()); | 132 programmable_prompt_ = new ProgrammableInstallPrompt(web_contents()); |
| 132 return base::WrapUnique(programmable_prompt_); | 133 return base::WrapUnique(programmable_prompt_); |
| 133 } | 134 } |
| 134 | 135 |
| 135 // Added here to make it public so that test cases can call it below. | 136 // Added here to make it public so that test cases can call it below. |
| 136 bool CheckRequestorAlive() const override { | 137 bool CheckRequestorAlive() const override { |
| 137 return WebstoreInlineInstaller::CheckRequestorAlive(); | 138 return WebstoreInlineInstaller::CheckRequestorAlive(); |
| 138 } | 139 } |
| 139 | 140 |
| 141 bool SafeBrowsingNavigationEventsEnabled() const override { | |
| 142 return enable_safebrowsing_redirects_; | |
| 143 } | |
| 144 | |
| 140 // Tests that care about the actual arguments to the install callback can use | 145 // Tests that care about the actual arguments to the install callback can use |
| 141 // this to receive a copy in |install_result_target|. | 146 // this to receive a copy in |install_result_target|. |
| 142 void set_install_result_target( | 147 void set_install_result_target( |
| 143 std::unique_ptr<InstallResult>* install_result_target) { | 148 std::unique_ptr<InstallResult>* install_result_target) { |
| 144 install_result_target_ = install_result_target; | 149 install_result_target_ = install_result_target; |
| 145 } | 150 } |
| 146 | 151 |
| 147 private: | 152 private: |
| 148 ~WebstoreInlineInstallerForTest() override {} | 153 ~WebstoreInlineInstallerForTest() override {} |
| 149 | 154 |
| 150 friend class base::RefCountedThreadSafe<WebstoreStandaloneInstaller>; | 155 friend class base::RefCountedThreadSafe<WebstoreStandaloneInstaller>; |
| 151 | 156 |
| 152 void InstallCallback(bool success, | 157 void InstallCallback(bool success, |
| 153 const std::string& error, | 158 const std::string& error, |
| 154 webstore_install::Result result) { | 159 webstore_install::Result result) { |
| 155 if (install_result_target_) { | 160 if (install_result_target_) { |
| 156 install_result_target_->reset(new InstallResult); | 161 install_result_target_->reset(new InstallResult); |
| 157 (*install_result_target_)->success = success; | 162 (*install_result_target_)->success = success; |
| 158 (*install_result_target_)->error = error; | 163 (*install_result_target_)->error = error; |
| 159 (*install_result_target_)->result = result; | 164 (*install_result_target_)->result = result; |
| 160 } | 165 } |
| 161 } | 166 } |
| 162 | 167 |
| 163 // This can be set by tests that want to get the actual install callback | 168 // This can be set by tests that want to get the actual install callback |
| 164 // arguments. | 169 // arguments. |
| 165 std::unique_ptr<InstallResult>* install_result_target_; | 170 std::unique_ptr<InstallResult>* install_result_target_; |
| 166 | 171 |
| 172 // This can be set by tests that want to use the new SafeBrowsing redirect | |
| 173 // tracker. | |
| 174 bool enable_safebrowsing_redirects_; | |
| 175 | |
| 167 ProgrammableInstallPrompt* programmable_prompt_; | 176 ProgrammableInstallPrompt* programmable_prompt_; |
| 168 }; | 177 }; |
| 169 | 178 |
| 170 class WebstoreInlineInstallerForTestFactory : | 179 class WebstoreInlineInstallerForTestFactory : |
| 171 public WebstoreInlineInstallerFactory { | 180 public WebstoreInlineInstallerFactory { |
| 172 public: | 181 public: |
| 173 WebstoreInlineInstallerForTestFactory() : last_installer_(nullptr) {} | 182 WebstoreInlineInstallerForTestFactory() |
| 183 : last_installer_(nullptr), enable_safebrowsing_redirects_(false) {} | |
| 184 explicit WebstoreInlineInstallerForTestFactory( | |
| 185 bool enable_safebrowsing_redirects) | |
| 186 : last_installer_(nullptr), | |
| 187 enable_safebrowsing_redirects_(enable_safebrowsing_redirects) {} | |
| 174 ~WebstoreInlineInstallerForTestFactory() override {} | 188 ~WebstoreInlineInstallerForTestFactory() override {} |
| 175 | 189 |
| 176 WebstoreInlineInstallerForTest* last_installer() { return last_installer_; } | 190 WebstoreInlineInstallerForTest* last_installer() { return last_installer_; } |
| 177 | 191 |
| 178 WebstoreInlineInstaller* CreateInstaller( | 192 WebstoreInlineInstaller* CreateInstaller( |
| 179 WebContents* contents, | 193 WebContents* contents, |
| 180 content::RenderFrameHost* host, | 194 content::RenderFrameHost* host, |
| 181 const std::string& webstore_item_id, | 195 const std::string& webstore_item_id, |
| 182 const GURL& requestor_url, | 196 const GURL& requestor_url, |
| 183 const WebstoreStandaloneInstaller::Callback& callback) override { | 197 const WebstoreStandaloneInstaller::Callback& callback) override { |
| 184 last_installer_ = new WebstoreInlineInstallerForTest( | 198 last_installer_ = new WebstoreInlineInstallerForTest( |
| 185 contents, host, webstore_item_id, requestor_url, callback); | 199 contents, host, webstore_item_id, requestor_url, callback, |
| 200 enable_safebrowsing_redirects_); | |
| 186 return last_installer_; | 201 return last_installer_; |
| 187 } | 202 } |
| 188 | 203 |
| 189 private: | 204 private: |
| 190 // The last installer that was created. | 205 // The last installer that was created. |
| 191 WebstoreInlineInstallerForTest* last_installer_; | 206 WebstoreInlineInstallerForTest* last_installer_; |
| 207 | |
| 208 bool enable_safebrowsing_redirects_; | |
| 192 }; | 209 }; |
| 193 | 210 |
| 194 IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerTest, | 211 IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerTest, |
| 195 CloseTabBeforeInstallConfirmation) { | 212 CloseTabBeforeInstallConfirmation) { |
| 196 GURL install_url = GenerateTestServerUrl(kAppDomain, "install.html"); | 213 GURL install_url = GenerateTestServerUrl(kAppDomain, "install.html"); |
| 197 ui_test_utils::NavigateToURL(browser(), install_url); | 214 ui_test_utils::NavigateToURL(browser(), install_url); |
| 198 WebContents* web_contents = | 215 WebContents* web_contents = |
| 199 browser()->tab_strip_model()->GetActiveWebContents(); | 216 browser()->tab_strip_model()->GetActiveWebContents(); |
| 200 TabHelper* tab_helper = TabHelper::FromWebContents(web_contents); | 217 TabHelper* tab_helper = TabHelper::FromWebContents(web_contents); |
| 201 tab_helper->SetWebstoreInlineInstallerFactoryForTests( | 218 tab_helper->SetWebstoreInlineInstallerFactoryForTests( |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 364 } | 381 } |
| 365 | 382 |
| 366 // Test calling chrome.webstore.install() twice without waiting for the first to | 383 // Test calling chrome.webstore.install() twice without waiting for the first to |
| 367 // finish. | 384 // finish. |
| 368 IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerTest, DoubleInlineInstallTest) { | 385 IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerTest, DoubleInlineInstallTest) { |
| 369 ui_test_utils::NavigateToURL( | 386 ui_test_utils::NavigateToURL( |
| 370 browser(), GenerateTestServerUrl(kAppDomain, "double_install.html")); | 387 browser(), GenerateTestServerUrl(kAppDomain, "double_install.html")); |
| 371 RunTest("runTest"); | 388 RunTest("runTest"); |
| 372 } | 389 } |
| 373 | 390 |
| 374 class WebstoreInlineInstallerRedirectTest : public WebstoreInlineInstallerTest { | 391 class WebstoreInlineInstallerRedirectTest |
| 392 : public WebstoreInlineInstallerTest, | |
| 393 public ::testing::WithParamInterface<bool> { | |
| 375 public: | 394 public: |
| 376 WebstoreInlineInstallerRedirectTest() : cws_request_received_(false) {} | 395 WebstoreInlineInstallerRedirectTest() : cws_request_received_(false) {} |
| 377 ~WebstoreInlineInstallerRedirectTest() override {} | 396 ~WebstoreInlineInstallerRedirectTest() override {} |
| 378 | 397 |
| 379 void SetUpInProcessBrowserTestFixture() override { | 398 void SetUpInProcessBrowserTestFixture() override { |
| 380 WebstoreInstallerTest::SetUpInProcessBrowserTestFixture(); | 399 WebstoreInstallerTest::SetUpInProcessBrowserTestFixture(); |
| 381 host_resolver()->AddRule(kRedirect1Domain, "127.0.0.1"); | 400 host_resolver()->AddRule(kRedirect1Domain, "127.0.0.1"); |
| 382 host_resolver()->AddRule(kRedirect2Domain, "127.0.0.1"); | 401 host_resolver()->AddRule(kRedirect2Domain, "127.0.0.1"); |
| 383 } | 402 } |
| 384 | 403 |
| 385 void ProcessServerRequest( | 404 void ProcessServerRequest( |
| 386 const net::test_server::HttpRequest& request) override { | 405 const net::test_server::HttpRequest& request) override { |
| 387 if (request.content.find("redirect_chain") != std::string::npos) { | 406 if (request.content.find("redirect_chain") != std::string::npos) { |
| 388 cws_request_received_ = true; | 407 cws_request_received_ = true; |
| 389 | 408 |
| 390 std::unique_ptr<base::Value> contents = | 409 std::unique_ptr<base::Value> contents = |
| 391 base::JSONReader::Read(request.content); | 410 base::JSONReader::Read(request.content); |
| 392 ASSERT_EQ(base::Value::Type::DICTIONARY, contents->GetType()); | 411 ASSERT_EQ(base::Value::Type::DICTIONARY, contents->GetType()); |
| 393 cws_request_json_data_ = base::DictionaryValue::From(std::move(contents)); | 412 cws_request_json_data_ = base::DictionaryValue::From(std::move(contents)); |
| 394 } | 413 } |
| 395 } | 414 } |
| 396 | 415 |
| 397 bool cws_request_received_; | 416 bool cws_request_received_; |
| 398 std::unique_ptr<base::DictionaryValue> cws_request_json_data_; | 417 std::unique_ptr<base::DictionaryValue> cws_request_json_data_; |
| 399 }; | 418 }; |
| 400 | 419 |
| 401 // Test that an install from a page arrived at via redirects includes the | 420 // Test that an install from a page arrived at via redirects includes the |
| 402 // redirect information in the webstore request. | 421 // redirect information in the webstore request. |
| 403 IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerRedirectTest, | 422 IN_PROC_BROWSER_TEST_P(WebstoreInlineInstallerRedirectTest, |
| 404 IncludesRedirectData) { | 423 IncludesRedirectData) { |
| 424 const bool using_safe_browsing_tracker = GetParam(); | |
| 425 | |
| 426 // GURL pre_navigate_url = GenerateTestServerUrl(kAppDomain, "install.html"); | |
|
Devlin
2017/04/13 15:03:07
dead code?
robertshield
2017/04/21 00:40:41
Oops, yes, thanks.
| |
| 427 // ui_test_utils::NavigateToURL(browser(), pre_navigate_url); | |
| 428 WebContents* web_contents = | |
| 429 browser()->tab_strip_model()->GetActiveWebContents(); | |
| 430 TabHelper* tab_helper = TabHelper::FromWebContents(web_contents); | |
| 431 WebstoreInlineInstallerForTestFactory* factory = | |
| 432 new WebstoreInlineInstallerForTestFactory(using_safe_browsing_tracker); | |
| 433 tab_helper->SetWebstoreInlineInstallerFactoryForTests(factory); | |
| 434 | |
| 405 // Hand craft a url that will cause the test server to issue redirects. | 435 // Hand craft a url that will cause the test server to issue redirects. |
| 406 const std::vector<std::string> redirects = {kRedirect1Domain, | 436 const std::vector<std::string> redirects = {kRedirect1Domain, |
| 407 kRedirect2Domain}; | 437 kRedirect2Domain}; |
| 408 net::HostPortPair host_port = embedded_test_server()->host_port_pair(); | 438 net::HostPortPair host_port = embedded_test_server()->host_port_pair(); |
| 409 std::string redirect_chain; | 439 std::string redirect_chain; |
| 410 for (const auto& redirect : redirects) { | 440 for (const auto& redirect : redirects) { |
| 411 std::string redirect_url = base::StringPrintf( | 441 std::string redirect_url = base::StringPrintf( |
| 412 "http://%s:%d/server-redirect?", redirect.c_str(), host_port.port()); | 442 "http://%s:%d/server-redirect?", redirect.c_str(), host_port.port()); |
| 413 redirect_chain += redirect_url; | 443 redirect_chain += redirect_url; |
| 414 } | 444 } |
| 415 const GURL install_url = | 445 const GURL install_url = |
| 416 GURL(redirect_chain + | 446 GURL(redirect_chain + |
| 417 GenerateTestServerUrl(kAppDomain, "install.html").spec()); | 447 GenerateTestServerUrl(kAppDomain, "install.html").spec()); |
| 418 | 448 |
| 419 AutoAcceptInstall(); | 449 AutoAcceptInstall(); |
| 420 ui_test_utils::NavigateToURL(browser(), install_url); | 450 ui_test_utils::NavigateToURL(browser(), install_url); |
| 421 RunTest("runTest"); | 451 |
| 452 RunTestAsync("runTest"); | |
|
Devlin
2017/04/13 15:03:07
Do we need to make this an async run?
robertshield
2017/04/21 00:40:41
It seems to hang if we don't. This became true whe
| |
| 453 while (!ProgrammableInstallPrompt::Ready()) | |
| 454 base::RunLoop().RunUntilIdle(); | |
| 455 web_contents->Close(); | |
| 422 | 456 |
| 423 EXPECT_TRUE(cws_request_received_); | 457 EXPECT_TRUE(cws_request_received_); |
| 424 ASSERT_NE(nullptr, cws_request_json_data_); | 458 ASSERT_NE(nullptr, cws_request_json_data_); |
| 425 | 459 |
| 426 base::ListValue* redirect_list = nullptr; | 460 base::ListValue* redirect_list = nullptr; |
| 427 cws_request_json_data_->GetList("redirect_chain", &redirect_list); | 461 cws_request_json_data_->GetList("redirect_chain", &redirect_list); |
| 428 ASSERT_NE(nullptr, redirect_list); | 462 ASSERT_NE(nullptr, redirect_list); |
| 429 | 463 |
| 430 // Check that the expected domains are in the redirect list. | 464 // Check that the expected domains are in the redirect list. |
| 431 const std::vector<std::string> expected_redirect_domains = { | 465 const std::set<std::string> expected_redirect_domains = { |
| 432 kRedirect1Domain, kRedirect2Domain, kAppDomain}; | 466 kRedirect1Domain, kRedirect2Domain, kAppDomain}; |
| 433 ASSERT_EQ(expected_redirect_domains.size(), redirect_list->GetSize()); | 467 |
| 434 int i = 0; | 468 // The SafeBrowsing tracker has a much more liberal definition of "redirect" |
| 469 // and it may (based on timing) pick up additional navigations that occur | |
| 470 // shortly before the navigation we mainly care about here. Be somewhat | |
| 471 // permissive in what we accept as redirect results. | |
| 472 ASSERT_LE(expected_redirect_domains.size(), redirect_list->GetSize()); | |
| 473 | |
| 435 for (const auto& value : *redirect_list) { | 474 for (const auto& value : *redirect_list) { |
| 436 std::string value_string; | 475 std::string value_string; |
| 437 ASSERT_TRUE(value->GetAsString(&value_string)); | 476 ASSERT_TRUE(value->GetAsString(&value_string)); |
| 438 GURL redirect_url(value_string); | 477 GURL redirect_url(value_string); |
| 439 EXPECT_EQ(expected_redirect_domains[i++], redirect_url.host()); | 478 EXPECT_TRUE(expected_redirect_domains.find(redirect_url.host()) != |
| 479 expected_redirect_domains.end()); | |
| 440 } | 480 } |
| 441 } | 481 } |
| 442 | 482 |
| 483 INSTANTIATE_TEST_CASE_P(NetRedirectTracking, | |
| 484 WebstoreInlineInstallerRedirectTest, | |
| 485 testing::Values(false)); | |
|
Devlin
2017/04/13 15:03:07
Optional: If you don't care much about the naming,
robertshield
2017/04/21 00:40:41
Ah, true.. I think on the balance having the two m
| |
| 486 INSTANTIATE_TEST_CASE_P(SafeBrowsingRedirectTracking, | |
| 487 WebstoreInlineInstallerRedirectTest, | |
| 488 testing::Values(true)); | |
| 489 | |
| 443 class WebstoreInlineInstallerListenerTest : public WebstoreInlineInstallerTest { | 490 class WebstoreInlineInstallerListenerTest : public WebstoreInlineInstallerTest { |
| 444 public: | 491 public: |
| 445 WebstoreInlineInstallerListenerTest() {} | 492 WebstoreInlineInstallerListenerTest() {} |
| 446 ~WebstoreInlineInstallerListenerTest() override {} | 493 ~WebstoreInlineInstallerListenerTest() override {} |
| 447 | 494 |
| 448 protected: | 495 protected: |
| 449 void RunTest(const std::string& file_name) { | 496 void RunTest(const std::string& file_name) { |
| 450 AutoAcceptInstall(); | 497 AutoAcceptInstall(); |
| 451 ui_test_utils::NavigateToURL(browser(), | 498 ui_test_utils::NavigateToURL(browser(), |
| 452 GenerateTestServerUrl(kAppDomain, file_name)); | 499 GenerateTestServerUrl(kAppDomain, file_name)); |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 483 WindowOpenDisposition::NEW_FOREGROUND_TAB, | 530 WindowOpenDisposition::NEW_FOREGROUND_TAB, |
| 484 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | 531 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); |
| 485 DCHECK_NE(old_tab_index, browser()->tab_strip_model()->active_index()); | 532 DCHECK_NE(old_tab_index, browser()->tab_strip_model()->active_index()); |
| 486 browser()->tab_strip_model()->CloseWebContentsAt(old_tab_index, | 533 browser()->tab_strip_model()->CloseWebContentsAt(old_tab_index, |
| 487 TabStripModel::CLOSE_NONE); | 534 TabStripModel::CLOSE_NONE); |
| 488 WebstoreInstallerTest::RunTest("runTest"); | 535 WebstoreInstallerTest::RunTest("runTest"); |
| 489 EXPECT_TRUE(registry->enabled_extensions().GetByID(kTestExtensionId)); | 536 EXPECT_TRUE(registry->enabled_extensions().GetByID(kTestExtensionId)); |
| 490 } | 537 } |
| 491 | 538 |
| 492 } // namespace extensions | 539 } // namespace extensions |
| OLD | NEW |