Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 <stddef.h> | 5 #include <stddef.h> |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
| 11 #include "base/macros.h" | 11 #include "base/macros.h" |
| 12 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
| 13 #include "base/strings/stringprintf.h" | 13 #include "base/strings/stringprintf.h" |
| 14 #include "chrome/browser/extensions/extension_action.h" | 14 #include "chrome/browser/extensions/extension_action.h" |
| 15 #include "chrome/browser/extensions/extension_action_runner.h" | 15 #include "chrome/browser/extensions/extension_action_runner.h" |
| 16 #include "chrome/browser/extensions/extension_browsertest.h" | 16 #include "chrome/browser/extensions/extension_browsertest.h" |
| 17 #include "chrome/browser/extensions/extension_util.h" | 17 #include "chrome/browser/extensions/extension_util.h" |
| 18 #include "chrome/browser/extensions/tab_helper.h" | 18 #include "chrome/browser/extensions/tab_helper.h" |
| 19 #include "chrome/browser/extensions/test_extension_dir.h" | 19 #include "chrome/browser/extensions/test_extension_dir.h" |
| 20 #include "chrome/browser/ui/browser.h" | 20 #include "chrome/browser/ui/browser.h" |
| 21 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 21 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 22 #include "chrome/test/base/ui_test_utils.h" | 22 #include "chrome/test/base/ui_test_utils.h" |
| 23 #include "content/public/browser/navigation_entry.h" | |
| 24 #include "content/public/browser/web_contents.h" | |
| 23 #include "content/public/test/browser_test_utils.h" | 25 #include "content/public/test/browser_test_utils.h" |
| 24 #include "extensions/common/feature_switch.h" | 26 #include "extensions/common/feature_switch.h" |
| 25 #include "extensions/common/switches.h" | 27 #include "extensions/common/switches.h" |
| 26 #include "extensions/test/extension_test_message_listener.h" | 28 #include "extensions/test/extension_test_message_listener.h" |
| 27 #include "net/test/embedded_test_server/embedded_test_server.h" | 29 #include "net/test/embedded_test_server/embedded_test_server.h" |
| 28 #include "testing/gtest/include/gtest/gtest.h" | 30 #include "testing/gtest/include/gtest/gtest.h" |
| 29 | 31 |
| 30 namespace extensions { | 32 namespace extensions { |
| 31 | 33 |
| 32 namespace { | 34 namespace { |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 56 | 58 |
| 57 // Runs all pending tasks in the renderer associated with |web_contents|. | 59 // Runs all pending tasks in the renderer associated with |web_contents|. |
| 58 // Returns true on success. | 60 // Returns true on success. |
| 59 bool RunAllPendingInRenderer(content::WebContents* web_contents) { | 61 bool RunAllPendingInRenderer(content::WebContents* web_contents) { |
| 60 // This is slight hack to achieve a RunPendingInRenderer() method. Since IPCs | 62 // This is slight hack to achieve a RunPendingInRenderer() method. Since IPCs |
| 61 // are sent synchronously, anything started prior to this method will finish | 63 // are sent synchronously, anything started prior to this method will finish |
| 62 // before this method returns (as content::ExecuteScript() is synchronous). | 64 // before this method returns (as content::ExecuteScript() is synchronous). |
| 63 return content::ExecuteScript(web_contents, "1 == 1;"); | 65 return content::ExecuteScript(web_contents, "1 == 1;"); |
| 64 } | 66 } |
| 65 | 67 |
| 68 // For use with blocked actions browsertests that put the result in | |
| 69 // window.localStorage. Returns the result or "undefined" if the result is not | |
| 70 // set. | |
| 71 std::string GetValue(content::WebContents* web_contents) { | |
| 72 std::string out; | |
| 73 if (!content::ExecuteScriptAndExtractString( | |
| 74 web_contents, | |
| 75 "var res = window.localStorage.getItem('extResult') || 'undefined';" | |
| 76 "window.localStorage.removeItem('extResult');" | |
| 77 "window.domAutomationController.send(res);", | |
| 78 &out)) { | |
| 79 out = "Failed to inject script"; | |
| 80 } | |
| 81 return out; | |
| 82 } | |
| 83 | |
| 66 } // namespace | 84 } // namespace |
| 67 | 85 |
| 68 class ExtensionActionRunnerBrowserTest : public ExtensionBrowserTest { | 86 class ExtensionActionRunnerBrowserTest : public ExtensionBrowserTest { |
| 69 public: | 87 public: |
| 70 ExtensionActionRunnerBrowserTest() {} | 88 ExtensionActionRunnerBrowserTest() {} |
| 71 | 89 |
| 72 void SetUpCommandLine(base::CommandLine* command_line) override; | 90 void SetUpCommandLine(base::CommandLine* command_line) override; |
| 73 void TearDownOnMainThread() override; | 91 void TearDownOnMainThread() override; |
| 74 | 92 |
| 75 // Returns an extension with the given |host_type| and |injection_type|. If | 93 // Returns an extension with the given |host_type| and |injection_type|. If |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 112 "\"permissions\": [\"tabs\", \"%s\"]", permission_scheme); | 130 "\"permissions\": [\"tabs\", \"%s\"]", permission_scheme); |
| 113 | 131 |
| 114 std::string scripts; | 132 std::string scripts; |
| 115 std::string script_source; | 133 std::string script_source; |
| 116 if (injection_type == CONTENT_SCRIPT) { | 134 if (injection_type == CONTENT_SCRIPT) { |
| 117 scripts = base::StringPrintf( | 135 scripts = base::StringPrintf( |
| 118 "\"content_scripts\": [" | 136 "\"content_scripts\": [" |
| 119 " {" | 137 " {" |
| 120 " \"matches\": [\"%s\"]," | 138 " \"matches\": [\"%s\"]," |
| 121 " \"js\": [\"script.js\"]," | 139 " \"js\": [\"script.js\"]," |
| 122 " \"run_at\": \"document_start\"" | 140 " \"run_at\": \"document_end\"" |
| 123 " }" | 141 " }" |
| 124 "]", | 142 "]", |
| 125 permission_scheme); | 143 permission_scheme); |
| 126 } else { | 144 } else { |
| 127 scripts = kBackgroundScript; | 145 scripts = kBackgroundScript; |
| 128 } | 146 } |
| 129 | 147 |
| 130 std::string manifest = base::StringPrintf( | 148 std::string manifest = base::StringPrintf( |
| 131 "{" | 149 "{" |
| 132 " \"name\": \"%s\"," | 150 " \"name\": \"%s\"," |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 420 util::SetAllowedScriptingOnAllUrls(extension->id(), profile(), false); | 438 util::SetAllowedScriptingOnAllUrls(extension->id(), profile(), false); |
| 421 EXPECT_TRUE(RunAllPendingInRenderer(web_contents)); | 439 EXPECT_TRUE(RunAllPendingInRenderer(web_contents)); |
| 422 | 440 |
| 423 // Re-navigate; the extension should again need permission to run. | 441 // Re-navigate; the extension should again need permission to run. |
| 424 ui_test_utils::NavigateToURL(browser(), url); | 442 ui_test_utils::NavigateToURL(browser(), url); |
| 425 EXPECT_TRUE(action_runner->WantsToRun(extension)); | 443 EXPECT_TRUE(action_runner->WantsToRun(extension)); |
| 426 EXPECT_EQ(1, action_runner->num_page_requests()); | 444 EXPECT_EQ(1, action_runner->num_page_requests()); |
| 427 EXPECT_FALSE(inject_success_listener.was_satisfied()); | 445 EXPECT_FALSE(inject_success_listener.was_satisfied()); |
| 428 } | 446 } |
| 429 | 447 |
| 448 IN_PROC_BROWSER_TEST_F(ExtensionActionRunnerBrowserTest, | |
| 449 BlockedActionBrowserTest) { | |
| 450 // Load an extension that wants to run on every page at document start, and | |
| 451 // load a test page. | |
| 452 ASSERT_TRUE(embedded_test_server()->Start()); | |
| 453 const GURL kUrl = embedded_test_server()->GetURL("/simple.html"); | |
|
asargent_no_longer_on_chrome
2016/03/21 23:31:15
optional: it seems a little unusual to use the "k"
Devlin
2016/03/23 21:48:46
I know we do it elsewhere, but I'm not sure if the
| |
| 454 const Extension* extension = LoadExtension( | |
| 455 test_data_dir_.AppendASCII("blocked_actions/content_scripts")); | |
| 456 ASSERT_TRUE(extension); | |
| 457 ui_test_utils::NavigateToURL(browser(), kUrl); | |
| 458 content::WebContents* web_contents = | |
| 459 browser()->tab_strip_model()->GetActiveWebContents(); | |
| 460 EXPECT_TRUE(content::WaitForLoadStop(web_contents)); | |
| 461 | |
| 462 // The extension should want to run on the page, and should not have | |
| 463 // injected. | |
| 464 ExtensionActionRunner* runner = | |
| 465 ExtensionActionRunner::GetForWebContents(web_contents); | |
| 466 ASSERT_TRUE(runner); | |
| 467 EXPECT_TRUE(runner->WantsToRun(extension)); | |
| 468 EXPECT_EQ("undefined", GetValue(web_contents)); | |
| 469 | |
| 470 // Wire up the runner to automatically accept the bubble to prompt for page | |
| 471 // refresh. | |
| 472 runner->set_default_bubble_close_action_for_testing( | |
| 473 make_scoped_ptr(new ToolbarActionsBarBubbleDelegate::CloseAction( | |
| 474 ToolbarActionsBarBubbleDelegate::CLOSE_EXECUTE))); | |
| 475 | |
| 476 content::NavigationEntry* entry = | |
| 477 web_contents->GetController().GetLastCommittedEntry(); | |
| 478 ASSERT_TRUE(entry); | |
| 479 const int first_nav_id = entry->GetUniqueID(); | |
| 480 | |
| 481 // Run the extension action, which should cause a page refresh (since we | |
| 482 // automatically accepted the bubble prompting us), and the extension should | |
| 483 // have injected at document start. | |
| 484 runner->RunAction(extension, true); | |
| 485 base::RunLoop().RunUntilIdle(); | |
| 486 EXPECT_TRUE(content::WaitForLoadStop(web_contents)); | |
| 487 entry = web_contents->GetController().GetLastCommittedEntry(); | |
| 488 ASSERT_TRUE(entry); | |
| 489 // Confirm that we refreshed the page. | |
| 490 EXPECT_GE(entry->GetUniqueID(), first_nav_id); | |
| 491 EXPECT_EQ("success", GetValue(web_contents)); | |
| 492 EXPECT_FALSE(runner->WantsToRun(extension)); | |
| 493 | |
| 494 // Revoke permission and reload to try different bubble options. | |
| 495 ActiveTabPermissionGranter* active_tab_granter = | |
| 496 TabHelper::FromWebContents(web_contents)->active_tab_permission_granter(); | |
| 497 ASSERT_TRUE(active_tab_granter); | |
| 498 active_tab_granter->RevokeForTesting(); | |
| 499 web_contents->GetController().Reload(true); | |
| 500 EXPECT_TRUE(content::WaitForLoadStop(web_contents)); | |
| 501 | |
| 502 // The extension should again want to run. Automatically dismiss the bubble | |
| 503 // that pops up prompting for page refresh. | |
| 504 EXPECT_TRUE(runner->WantsToRun(extension)); | |
| 505 EXPECT_EQ("undefined", GetValue(web_contents)); | |
| 506 const int next_nav_id = | |
| 507 web_contents->GetController().GetLastCommittedEntry()->GetUniqueID(); | |
| 508 runner->set_default_bubble_close_action_for_testing( | |
| 509 make_scoped_ptr(new ToolbarActionsBarBubbleDelegate::CloseAction( | |
| 510 ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS_USER_ACTION))); | |
| 511 | |
| 512 // Try running the extension. Nothing should happen, because the user | |
| 513 // didn't agree to refresh the page. The extension should still want to run. | |
| 514 runner->RunAction(extension, true); | |
| 515 base::RunLoop().RunUntilIdle(); | |
| 516 EXPECT_TRUE(content::WaitForLoadStop(web_contents)); | |
| 517 EXPECT_EQ("undefined", GetValue(web_contents)); | |
| 518 EXPECT_EQ( | |
| 519 next_nav_id, | |
| 520 web_contents->GetController().GetLastCommittedEntry()->GetUniqueID()); | |
| 521 | |
| 522 // Repeat with a dismissal from bubble deactivation - same story. | |
| 523 runner->set_default_bubble_close_action_for_testing( | |
| 524 make_scoped_ptr(new ToolbarActionsBarBubbleDelegate::CloseAction( | |
| 525 ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS_DEACTIVATION))); | |
| 526 runner->RunAction(extension, true); | |
| 527 base::RunLoop().RunUntilIdle(); | |
| 528 EXPECT_TRUE(content::WaitForLoadStop(web_contents)); | |
| 529 EXPECT_EQ("undefined", GetValue(web_contents)); | |
| 530 EXPECT_EQ( | |
| 531 next_nav_id, | |
| 532 web_contents->GetController().GetLastCommittedEntry()->GetUniqueID()); | |
| 533 } | |
| 534 | |
| 430 // A version of the test with the flag off, in order to test that everything | 535 // A version of the test with the flag off, in order to test that everything |
| 431 // still works as expected. | 536 // still works as expected. |
| 432 class FlagOffExtensionActionRunnerBrowserTest | 537 class FlagOffExtensionActionRunnerBrowserTest |
| 433 : public ExtensionActionRunnerBrowserTest { | 538 : public ExtensionActionRunnerBrowserTest { |
| 434 private: | 539 private: |
| 435 // Simply don't append the flag. | 540 // Simply don't append the flag. |
| 436 void SetUpCommandLine(base::CommandLine* command_line) override { | 541 void SetUpCommandLine(base::CommandLine* command_line) override { |
| 437 ExtensionBrowserTest::SetUpCommandLine(command_line); | 542 ExtensionBrowserTest::SetUpCommandLine(command_line); |
| 438 } | 543 } |
| 439 }; | 544 }; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 454 | 559 |
| 455 ASSERT_TRUE(embedded_test_server()->Start()); | 560 ASSERT_TRUE(embedded_test_server()->Start()); |
| 456 ui_test_utils::NavigateToURL( | 561 ui_test_utils::NavigateToURL( |
| 457 browser(), embedded_test_server()->GetURL("/extensions/test_file.html")); | 562 browser(), embedded_test_server()->GetURL("/extensions/test_file.html")); |
| 458 | 563 |
| 459 for (size_t i = 0u; i < arraysize(testers); ++i) | 564 for (size_t i = 0u; i < arraysize(testers); ++i) |
| 460 EXPECT_TRUE(testers[i].Verify()) << kExtensionNames[i]; | 565 EXPECT_TRUE(testers[i].Verify()) << kExtensionNames[i]; |
| 461 } | 566 } |
| 462 | 567 |
| 463 } // namespace extensions | 568 } // namespace extensions |
| OLD | NEW |