| 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 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 ProgrammableInstallPrompt::g_done_callback = nullptr; | 111 ProgrammableInstallPrompt::g_done_callback = nullptr; |
| 112 | 112 |
| 113 // Fake inline installer which creates a programmable prompt in place of | 113 // Fake inline installer which creates a programmable prompt in place of |
| 114 // the normal dialog UI. | 114 // the normal dialog UI. |
| 115 class WebstoreInlineInstallerForTest : public WebstoreInlineInstaller { | 115 class WebstoreInlineInstallerForTest : public WebstoreInlineInstaller { |
| 116 public: | 116 public: |
| 117 WebstoreInlineInstallerForTest(WebContents* contents, | 117 WebstoreInlineInstallerForTest(WebContents* contents, |
| 118 content::RenderFrameHost* host, | 118 content::RenderFrameHost* host, |
| 119 const std::string& extension_id, | 119 const std::string& extension_id, |
| 120 const GURL& requestor_url, | 120 const GURL& requestor_url, |
| 121 const Callback& callback) | 121 const Callback& callback, |
| 122 bool enable_safebrowsing_redirects) |
| 122 : WebstoreInlineInstaller( | 123 : WebstoreInlineInstaller( |
| 123 contents, | 124 contents, |
| 124 host, | 125 host, |
| 125 kTestExtensionId, | 126 kTestExtensionId, |
| 126 requestor_url, | 127 requestor_url, |
| 127 base::Bind(&WebstoreInlineInstallerForTest::InstallCallback, | 128 base::Bind(&WebstoreInlineInstallerForTest::InstallCallback, |
| 128 base::Unretained(this))), | 129 base::Unretained(this))), |
| 129 install_result_target_(nullptr), | 130 install_result_target_(nullptr), |
| 130 programmable_prompt_(nullptr) {} | 131 programmable_prompt_(nullptr) {} |
| 131 | 132 |
| 132 std::unique_ptr<ExtensionInstallPrompt> CreateInstallUI() override { | 133 std::unique_ptr<ExtensionInstallPrompt> CreateInstallUI() override { |
| 133 programmable_prompt_ = new ProgrammableInstallPrompt(web_contents()); | 134 programmable_prompt_ = new ProgrammableInstallPrompt(web_contents()); |
| 134 return base::WrapUnique(programmable_prompt_); | 135 return base::WrapUnique(programmable_prompt_); |
| 135 } | 136 } |
| 136 | 137 |
| 137 // Added here to make it public so that test cases can call it below. | 138 // Added here to make it public so that test cases can call it below. |
| 138 bool CheckRequestorAlive() const override { | 139 bool CheckRequestorAlive() const override { |
| 139 return WebstoreInlineInstaller::CheckRequestorAlive(); | 140 return WebstoreInlineInstaller::CheckRequestorAlive(); |
| 140 } | 141 } |
| 141 | 142 |
| 143 bool SafeBrowsingNavigationEventsEnabled() const override { |
| 144 return enable_safebrowsing_redirects_; |
| 145 } |
| 146 |
| 142 // Tests that care about the actual arguments to the install callback can use | 147 // Tests that care about the actual arguments to the install callback can use |
| 143 // this to receive a copy in |install_result_target|. | 148 // this to receive a copy in |install_result_target|. |
| 144 void set_install_result_target( | 149 void set_install_result_target( |
| 145 std::unique_ptr<InstallResult>* install_result_target) { | 150 std::unique_ptr<InstallResult>* install_result_target) { |
| 146 install_result_target_ = install_result_target; | 151 install_result_target_ = install_result_target; |
| 147 } | 152 } |
| 148 | 153 |
| 149 private: | 154 private: |
| 150 ~WebstoreInlineInstallerForTest() override {} | 155 ~WebstoreInlineInstallerForTest() override {} |
| 151 | 156 |
| 152 friend class base::RefCountedThreadSafe<WebstoreStandaloneInstaller>; | 157 friend class base::RefCountedThreadSafe<WebstoreStandaloneInstaller>; |
| 153 | 158 |
| 154 void InstallCallback(bool success, | 159 void InstallCallback(bool success, |
| 155 const std::string& error, | 160 const std::string& error, |
| 156 webstore_install::Result result) { | 161 webstore_install::Result result) { |
| 157 if (install_result_target_) { | 162 if (install_result_target_) { |
| 158 install_result_target_->reset(new InstallResult); | 163 install_result_target_->reset(new InstallResult); |
| 159 (*install_result_target_)->success = success; | 164 (*install_result_target_)->success = success; |
| 160 (*install_result_target_)->error = error; | 165 (*install_result_target_)->error = error; |
| 161 (*install_result_target_)->result = result; | 166 (*install_result_target_)->result = result; |
| 162 } | 167 } |
| 163 } | 168 } |
| 164 | 169 |
| 165 // This can be set by tests that want to get the actual install callback | 170 // This can be set by tests that want to get the actual install callback |
| 166 // arguments. | 171 // arguments. |
| 167 std::unique_ptr<InstallResult>* install_result_target_; | 172 std::unique_ptr<InstallResult>* install_result_target_; |
| 168 | 173 |
| 174 // This can be set by tests that want to use the new SafeBrowsing redirect |
| 175 // tracker. |
| 176 bool enable_safebrowsing_redirects_; |
| 177 |
| 169 ProgrammableInstallPrompt* programmable_prompt_; | 178 ProgrammableInstallPrompt* programmable_prompt_; |
| 170 }; | 179 }; |
| 171 | 180 |
| 172 class WebstoreInlineInstallerForTestFactory : | 181 class WebstoreInlineInstallerForTestFactory : |
| 173 public WebstoreInlineInstallerFactory { | 182 public WebstoreInlineInstallerFactory { |
| 174 public: | 183 public: |
| 175 WebstoreInlineInstallerForTestFactory() : last_installer_(nullptr) {} | 184 WebstoreInlineInstallerForTestFactory() |
| 185 : last_installer_(nullptr), enable_safebrowsing_redirects_(false) {} |
| 186 explicit WebstoreInlineInstallerForTestFactory( |
| 187 bool enable_safebrowsing_redirects) |
| 188 : last_installer_(nullptr), |
| 189 enable_safebrowsing_redirects_(enable_safebrowsing_redirects) {} |
| 176 ~WebstoreInlineInstallerForTestFactory() override {} | 190 ~WebstoreInlineInstallerForTestFactory() override {} |
| 177 | 191 |
| 178 WebstoreInlineInstallerForTest* last_installer() { return last_installer_; } | 192 WebstoreInlineInstallerForTest* last_installer() { return last_installer_; } |
| 179 | 193 |
| 180 WebstoreInlineInstaller* CreateInstaller( | 194 WebstoreInlineInstaller* CreateInstaller( |
| 181 WebContents* contents, | 195 WebContents* contents, |
| 182 content::RenderFrameHost* host, | 196 content::RenderFrameHost* host, |
| 183 const std::string& webstore_item_id, | 197 const std::string& webstore_item_id, |
| 184 const GURL& requestor_url, | 198 const GURL& requestor_url, |
| 185 const WebstoreStandaloneInstaller::Callback& callback) override { | 199 const WebstoreStandaloneInstaller::Callback& callback) override { |
| 186 last_installer_ = new WebstoreInlineInstallerForTest( | 200 last_installer_ = new WebstoreInlineInstallerForTest( |
| 187 contents, host, webstore_item_id, requestor_url, callback); | 201 contents, host, webstore_item_id, requestor_url, callback, |
| 202 enable_safebrowsing_redirects_); |
| 188 return last_installer_; | 203 return last_installer_; |
| 189 } | 204 } |
| 190 | 205 |
| 191 private: | 206 private: |
| 192 // The last installer that was created. | 207 // The last installer that was created. |
| 193 WebstoreInlineInstallerForTest* last_installer_; | 208 WebstoreInlineInstallerForTest* last_installer_; |
| 209 |
| 210 bool enable_safebrowsing_redirects_; |
| 194 }; | 211 }; |
| 195 | 212 |
| 196 IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerTest, | 213 IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerTest, |
| 197 CloseTabBeforeInstallConfirmation) { | 214 CloseTabBeforeInstallConfirmation) { |
| 198 GURL install_url = GenerateTestServerUrl(kAppDomain, "install.html"); | 215 GURL install_url = GenerateTestServerUrl(kAppDomain, "install.html"); |
| 199 ui_test_utils::NavigateToURL(browser(), install_url); | 216 ui_test_utils::NavigateToURL(browser(), install_url); |
| 200 WebContents* web_contents = | 217 WebContents* web_contents = |
| 201 browser()->tab_strip_model()->GetActiveWebContents(); | 218 browser()->tab_strip_model()->GetActiveWebContents(); |
| 202 TabHelper* tab_helper = TabHelper::FromWebContents(web_contents); | 219 TabHelper* tab_helper = TabHelper::FromWebContents(web_contents); |
| 203 tab_helper->SetWebstoreInlineInstallerFactoryForTests( | 220 tab_helper->SetWebstoreInlineInstallerFactoryForTests( |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 } | 383 } |
| 367 | 384 |
| 368 // Test calling chrome.webstore.install() twice without waiting for the first to | 385 // Test calling chrome.webstore.install() twice without waiting for the first to |
| 369 // finish. | 386 // finish. |
| 370 IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerTest, DoubleInlineInstallTest) { | 387 IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerTest, DoubleInlineInstallTest) { |
| 371 ui_test_utils::NavigateToURL( | 388 ui_test_utils::NavigateToURL( |
| 372 browser(), GenerateTestServerUrl(kAppDomain, "double_install.html")); | 389 browser(), GenerateTestServerUrl(kAppDomain, "double_install.html")); |
| 373 RunTest("runTest"); | 390 RunTest("runTest"); |
| 374 } | 391 } |
| 375 | 392 |
| 376 class WebstoreInlineInstallerRedirectTest : public WebstoreInlineInstallerTest { | 393 class WebstoreInlineInstallerRedirectTest |
| 394 : public WebstoreInlineInstallerTest, |
| 395 public ::testing::WithParamInterface<bool> { |
| 377 public: | 396 public: |
| 378 WebstoreInlineInstallerRedirectTest() : cws_request_received_(false) {} | 397 WebstoreInlineInstallerRedirectTest() : cws_request_received_(false) {} |
| 379 ~WebstoreInlineInstallerRedirectTest() override {} | 398 ~WebstoreInlineInstallerRedirectTest() override {} |
| 380 | 399 |
| 381 void SetUpInProcessBrowserTestFixture() override { | 400 void SetUpInProcessBrowserTestFixture() override { |
| 382 WebstoreInstallerTest::SetUpInProcessBrowserTestFixture(); | 401 WebstoreInstallerTest::SetUpInProcessBrowserTestFixture(); |
| 383 host_resolver()->AddRule(kRedirect1Domain, "127.0.0.1"); | 402 host_resolver()->AddRule(kRedirect1Domain, "127.0.0.1"); |
| 384 host_resolver()->AddRule(kRedirect2Domain, "127.0.0.1"); | 403 host_resolver()->AddRule(kRedirect2Domain, "127.0.0.1"); |
| 385 } | 404 } |
| 386 | 405 |
| 387 void ProcessServerRequest( | 406 void ProcessServerRequest( |
| 388 const net::test_server::HttpRequest& request) override { | 407 const net::test_server::HttpRequest& request) override { |
| 389 cws_request_received_ = true; | 408 cws_request_received_ = true; |
| 390 if (request.content.find("redirect_chain") != std::string::npos) { | 409 if (request.content.find("redirect_chain") != std::string::npos) { |
| 391 std::unique_ptr<base::Value> contents = | 410 std::unique_ptr<base::Value> contents = |
| 392 base::JSONReader::Read(request.content); | 411 base::JSONReader::Read(request.content); |
| 393 ASSERT_EQ(base::Value::Type::DICTIONARY, contents->GetType()); | 412 ASSERT_EQ(base::Value::Type::DICTIONARY, contents->GetType()); |
| 394 cws_request_json_data_ = base::DictionaryValue::From(std::move(contents)); | 413 cws_request_json_data_ = base::DictionaryValue::From(std::move(contents)); |
| 395 } | 414 } |
| 396 } | 415 } |
| 397 | 416 |
| 398 bool cws_request_received_; | 417 bool cws_request_received_; |
| 399 std::unique_ptr<base::DictionaryValue> cws_request_json_data_; | 418 std::unique_ptr<base::DictionaryValue> cws_request_json_data_; |
| 400 }; | 419 }; |
| 401 | 420 |
| 402 // Test that an install from a page arrived at via redirects includes the | 421 // Test that an install from a page arrived at via redirects includes the |
| 403 // redirect information in the webstore request. | 422 // redirect information in the webstore request. |
| 404 IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerRedirectTest, | 423 IN_PROC_BROWSER_TEST_P(WebstoreInlineInstallerRedirectTest, |
| 405 IncludesRedirectData) { | 424 IncludesRedirectData) { |
| 425 const bool using_safe_browsing_tracker = GetParam(); |
| 426 WebContents* web_contents = |
| 427 browser()->tab_strip_model()->GetActiveWebContents(); |
| 428 TabHelper* tab_helper = TabHelper::FromWebContents(web_contents); |
| 429 WebstoreInlineInstallerForTestFactory* factory = |
| 430 new WebstoreInlineInstallerForTestFactory(using_safe_browsing_tracker); |
| 431 tab_helper->SetWebstoreInlineInstallerFactoryForTests(factory); |
| 432 |
| 406 // Hand craft a url that will cause the test server to issue redirects. | 433 // Hand craft a url that will cause the test server to issue redirects. |
| 407 const std::vector<std::string> redirects = {kRedirect1Domain, | 434 const std::vector<std::string> redirects = {kRedirect1Domain, |
| 408 kRedirect2Domain}; | 435 kRedirect2Domain}; |
| 409 net::HostPortPair host_port = embedded_test_server()->host_port_pair(); | 436 net::HostPortPair host_port = embedded_test_server()->host_port_pair(); |
| 410 std::string redirect_chain; | 437 std::string redirect_chain; |
| 411 for (const auto& redirect : redirects) { | 438 for (const auto& redirect : redirects) { |
| 412 std::string redirect_url = base::StringPrintf( | 439 std::string redirect_url = base::StringPrintf( |
| 413 "http://%s:%d/server-redirect?", redirect.c_str(), host_port.port()); | 440 "http://%s:%d/server-redirect?", redirect.c_str(), host_port.port()); |
| 414 redirect_chain += redirect_url; | 441 redirect_chain += redirect_url; |
| 415 } | 442 } |
| 416 const GURL install_url = | 443 const GURL install_url = |
| 417 GURL(redirect_chain + | 444 GURL(redirect_chain + |
| 418 GenerateTestServerUrl(kAppDomain, "install.html").spec()); | 445 GenerateTestServerUrl(kAppDomain, "install.html").spec()); |
| 419 | 446 |
| 420 AutoAcceptInstall(); | 447 AutoAcceptInstall(); |
| 421 ui_test_utils::NavigateToURL(browser(), install_url); | 448 ui_test_utils::NavigateToURL(browser(), install_url); |
| 422 RunTest("runTest"); | 449 |
| 450 RunTestAsync("runTest"); |
| 451 while (!ProgrammableInstallPrompt::Ready()) |
| 452 base::RunLoop().RunUntilIdle(); |
| 453 web_contents->Close(); |
| 423 | 454 |
| 424 EXPECT_TRUE(cws_request_received_); | 455 EXPECT_TRUE(cws_request_received_); |
| 425 ASSERT_NE(nullptr, cws_request_json_data_); | 456 ASSERT_NE(nullptr, cws_request_json_data_); |
| 426 | 457 |
| 427 base::ListValue* redirect_list = nullptr; | 458 base::ListValue* redirect_list = nullptr; |
| 428 cws_request_json_data_->GetList("redirect_chain", &redirect_list); | 459 cws_request_json_data_->GetList("redirect_chain", &redirect_list); |
| 429 ASSERT_NE(nullptr, redirect_list); | 460 ASSERT_NE(nullptr, redirect_list); |
| 430 | 461 |
| 431 // Check that the expected domains are in the redirect list. | 462 // Check that the expected domains are in the redirect list. |
| 432 const std::vector<std::string> expected_redirect_domains = { | 463 const std::set<std::string> expected_redirect_domains = { |
| 433 kRedirect1Domain, kRedirect2Domain, kAppDomain}; | 464 kRedirect1Domain, kRedirect2Domain, kAppDomain}; |
| 434 ASSERT_EQ(expected_redirect_domains.size(), redirect_list->GetSize()); | 465 |
| 435 int i = 0; | 466 // The SafeBrowsing tracker has a much more liberal definition of "redirect" |
| 467 // and it may (based on timing) pick up additional navigations that occur |
| 468 // shortly before the navigation we mainly care about here. Be somewhat |
| 469 // permissive in what we accept as redirect results. |
| 470 ASSERT_LE(expected_redirect_domains.size(), redirect_list->GetSize()); |
| 471 |
| 436 for (const auto& value : *redirect_list) { | 472 for (const auto& value : *redirect_list) { |
| 437 std::string value_string; | 473 std::string value_string; |
| 438 ASSERT_TRUE(value.GetAsString(&value_string)); | 474 ASSERT_TRUE(value.GetAsString(&value_string)); |
| 439 GURL redirect_url(value_string); | 475 GURL redirect_url(value_string); |
| 440 EXPECT_EQ(expected_redirect_domains[i++], redirect_url.host()); | 476 EXPECT_TRUE(expected_redirect_domains.find(redirect_url.host()) != |
| 477 expected_redirect_domains.end()); |
| 441 } | 478 } |
| 442 } | 479 } |
| 443 | 480 |
| 444 // Test that an install from a page arrived at via redirects does not include | 481 // Test that an install from a page arrived at via redirects does not include |
| 445 // redirect information when SafeBrowsing is disabled. | 482 // redirect information when SafeBrowsing is disabled. |
| 446 IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerRedirectTest, | 483 IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerRedirectTest, |
| 447 NoRedirectDataWhenSafeBrowsingDisabled) { | 484 NoRedirectDataWhenSafeBrowsingDisabled) { |
| 448 PrefService* pref_service = browser()->profile()->GetPrefs(); | 485 PrefService* pref_service = browser()->profile()->GetPrefs(); |
| 449 EXPECT_TRUE(pref_service->GetBoolean(prefs::kSafeBrowsingEnabled)); | 486 EXPECT_TRUE(pref_service->GetBoolean(prefs::kSafeBrowsingEnabled)); |
| 450 | 487 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 466 GenerateTestServerUrl(kAppDomain, "install.html").spec()); | 503 GenerateTestServerUrl(kAppDomain, "install.html").spec()); |
| 467 | 504 |
| 468 AutoAcceptInstall(); | 505 AutoAcceptInstall(); |
| 469 ui_test_utils::NavigateToURL(browser(), install_url); | 506 ui_test_utils::NavigateToURL(browser(), install_url); |
| 470 RunTest("runTest"); | 507 RunTest("runTest"); |
| 471 | 508 |
| 472 EXPECT_TRUE(cws_request_received_); | 509 EXPECT_TRUE(cws_request_received_); |
| 473 ASSERT_EQ(nullptr, cws_request_json_data_); | 510 ASSERT_EQ(nullptr, cws_request_json_data_); |
| 474 } | 511 } |
| 475 | 512 |
| 513 INSTANTIATE_TEST_CASE_P(NetRedirectTracking, |
| 514 WebstoreInlineInstallerRedirectTest, |
| 515 testing::Values(false)); |
| 516 INSTANTIATE_TEST_CASE_P(SafeBrowsingRedirectTracking, |
| 517 WebstoreInlineInstallerRedirectTest, |
| 518 testing::Values(true)); |
| 519 |
| 476 class WebstoreInlineInstallerListenerTest : public WebstoreInlineInstallerTest { | 520 class WebstoreInlineInstallerListenerTest : public WebstoreInlineInstallerTest { |
| 477 public: | 521 public: |
| 478 WebstoreInlineInstallerListenerTest() {} | 522 WebstoreInlineInstallerListenerTest() {} |
| 479 ~WebstoreInlineInstallerListenerTest() override {} | 523 ~WebstoreInlineInstallerListenerTest() override {} |
| 480 | 524 |
| 481 protected: | 525 protected: |
| 482 void RunTest(const std::string& file_name) { | 526 void RunTest(const std::string& file_name) { |
| 483 AutoAcceptInstall(); | 527 AutoAcceptInstall(); |
| 484 ui_test_utils::NavigateToURL(browser(), | 528 ui_test_utils::NavigateToURL(browser(), |
| 485 GenerateTestServerUrl(kAppDomain, file_name)); | 529 GenerateTestServerUrl(kAppDomain, file_name)); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 516 WindowOpenDisposition::NEW_FOREGROUND_TAB, | 560 WindowOpenDisposition::NEW_FOREGROUND_TAB, |
| 517 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | 561 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); |
| 518 DCHECK_NE(old_tab_index, browser()->tab_strip_model()->active_index()); | 562 DCHECK_NE(old_tab_index, browser()->tab_strip_model()->active_index()); |
| 519 browser()->tab_strip_model()->CloseWebContentsAt(old_tab_index, | 563 browser()->tab_strip_model()->CloseWebContentsAt(old_tab_index, |
| 520 TabStripModel::CLOSE_NONE); | 564 TabStripModel::CLOSE_NONE); |
| 521 WebstoreInstallerTest::RunTest("runTest"); | 565 WebstoreInstallerTest::RunTest("runTest"); |
| 522 EXPECT_TRUE(registry->enabled_extensions().GetByID(kTestExtensionId)); | 566 EXPECT_TRUE(registry->enabled_extensions().GetByID(kTestExtensionId)); |
| 523 } | 567 } |
| 524 | 568 |
| 525 } // namespace extensions | 569 } // namespace extensions |
| OLD | NEW |