Chromium Code Reviews| Index: chrome/browser/extensions/api/declarative_content/request_content_script_browsertest.cc |
| diff --git a/chrome/browser/extensions/api/declarative_content/request_content_script_browsertest.cc b/chrome/browser/extensions/api/declarative_content/request_content_script_browsertest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..a14ccbc960711ae9d12d1b6d4135d61c3e07d860 |
| --- /dev/null |
| +++ b/chrome/browser/extensions/api/declarative_content/request_content_script_browsertest.cc |
| @@ -0,0 +1,297 @@ |
| +// Copyright 2014 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 "base/files/file_path.h" |
| +#include "base/macros.h" |
| +#include "base/strings/stringprintf.h" |
| +#include "chrome/browser/extensions/active_script_controller.h" |
| +#include "chrome/browser/extensions/extension_action.h" |
| +#include "chrome/browser/extensions/extension_browsertest.h" |
| +#include "chrome/browser/extensions/extension_test_message_listener.h" |
| +#include "chrome/browser/extensions/location_bar_controller.h" |
| +#include "chrome/browser/extensions/tab_helper.h" |
| +#include "chrome/browser/extensions/test_extension_dir.h" |
| +#include "chrome/browser/ui/browser.h" |
| +#include "chrome/browser/ui/tabs/tab_strip_model.h" |
| +#include "chrome/test/base/ui_test_utils.h" |
| +#include "content/public/test/browser_test_utils.h" |
| +#include "extensions/common/feature_switch.h" |
| +#include "extensions/common/switches.h" |
| +#include "net/test/embedded_test_server/embedded_test_server.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| + |
| +namespace extensions { |
| + |
| +namespace { |
| + |
| +// Within manifest permissions: |
| +const char kAllPermission[] = "*://*/*"; |
| +const char kParticularPermission[] = "http://127.0.0.1/*"; |
| +const char kNowherePermission[] = "http://nowhere.com/*"; |
| + |
| +// Within declarative condition: |
| +const char kAllMatcher[] = "{ pageUrl: { hostContains: '' } }"; |
| +const char kParticularMatcher[] = "{ pageUrl: { hostEquals: '127.0.0.1' } }"; |
| +const char kNowhereMatcher[] = "{ pageUrl: { hostEquals: 'nowhere.com' } }"; |
| + |
| +// Within |kManifest| below: %s -> |kAllPermission| or |kParticularPermission|. |
| +const char kManifest[] = |
| + "{\n" |
| + " \"name\": \"Test DeclarativeContentScript\",\n" |
| + " \"manifest_version\": 2,\n" |
| + " \"version\": \"1.0\",\n" |
| + " \"description\": \"Test declarative content script interface\",\n" |
| + " \"permissions\": [\"declarativeContent\", \"%s\"],\n" |
| + " \"background\": {\n" |
| + " \"scripts\": [\"background.js\"]\n" |
| + " }\n" |
| + "}\n"; |
| + |
| +// Script sources: |
| +// Within kBackgroundScriptSource below: %s -> |kAllMatcher| or |
| +// |kParticularMatcher|. |
| +const char kBackgroundScriptSource[] = |
| + "var declarativeContent = chrome.declarativeContent;\n" |
| + "var PageStateMatcher = declarativeContent.PageStateMatcher;\n" |
| + "var RequestContentScript = declarativeContent.RequestContentScript;\n" |
| + "var ShowPageAction = declarativeContent.ShowPageAction;\n" |
| + "var onPageChanged = declarativeContent.onPageChanged;\n" |
| + "onPageChanged.removeRules(undefined, function() {\n" |
| + " onPageChanged.addRules(\n" |
| + " [{\n" |
| + " conditions: [new PageStateMatcher(%s)],\n" |
| + " actions: [new RequestContentScript({js: ['script.js']}\n" |
| + " )]\n" |
| + " }],\n" |
| + " function(details) {\n" |
| + " if (!chrome.runtime.lastError)\n" |
| + " chrome.test.sendMessage('injection setup');\n" |
| + " }\n" |
| + " );\n" |
| + "});\n"; |
| +const char kContentScriptSource[] = |
| + "chrome.test.sendMessage('injection succeeded');"; |
| + |
| +// Messages from scripts: |
| +const char kInjectionSetup[] = "injection setup"; |
| +const char kInjectionSucceeded[] = "injection succeeded"; |
| + |
| +enum ManifestPermissionType { |
| + MP_ALL, |
| + MP_PARTICULAR, |
| + MP_NOWHERE |
| +}; |
| + |
| +enum ScriptMatcherType { |
| + SM_ALL, |
| + SM_PARTICULAR, |
| + SM_NOWHERE |
| +}; |
| + |
| +// Runs all pending tasks in the renderer associated with |web_contents|. |
| +// Returns true on success. |
| +bool RunAllPendingInRenderer(content::WebContents* web_contents) { |
|
Devlin
2014/08/25 22:31:05
// TODO(devlin): If too many tests start to need t
Mark Dittmer
2014/08/26 17:53:58
Done.
|
| + // This is slight hack to achieve a RunPendingInRenderer() method. Since IPCs |
| + // are sent synchronously, anything started prior to this method will finish |
| + // before this method returns (as content::ExecuteScript() is synchronous). |
| + return content::ExecuteScript(web_contents, "1 == 1;"); |
| +} |
| + |
| +} // namespace |
| + |
| +class RequestContentScriptBrowserTest : public ExtensionBrowserTest { |
| + public: |
| + RequestContentScriptBrowserTest(); |
| + |
| + // Associates this test with a new extension, the given |manifest_permission| |
| + // and |script_matcher|. |
| + testing::AssertionResult Init(ManifestPermissionType manifest_permission, |
| + ScriptMatcherType script_matcher); |
| + |
| + // Performs script injection test on a common local URL. Does not return until |
| + // the renderer should have completed its task and any browser-side reactions |
| + // have been cleared from the task queue. |
| + testing::AssertionResult RunTest(); |
| + |
| + ExtensionTestMessageListener* injection_setup_listener() { |
| + return injection_setup_listener_.get(); |
| + } |
| + ExtensionTestMessageListener* injection_succeeded_listener() { |
| + return injection_succeeded_listener_.get(); |
| + } |
| + |
| + private: |
| + scoped_ptr<TestExtensionDir> test_extension_dir_; |
| + const Extension* extension_; |
| + content::WebContents* web_contents_; |
| + scoped_ptr<ExtensionTestMessageListener> injection_setup_listener_; |
| + scoped_ptr<ExtensionTestMessageListener> injection_succeeded_listener_; |
| +}; |
| + |
| +RequestContentScriptBrowserTest::RequestContentScriptBrowserTest() |
| + : extension_(NULL), |
| + web_contents_(NULL) {} |
| + |
| +testing::AssertionResult RequestContentScriptBrowserTest::Init( |
| + ManifestPermissionType manifest_permission, |
| + ScriptMatcherType script_matcher) { |
| + const char* permission; |
| + switch (manifest_permission) { |
| + case MP_ALL: |
| + permission = kAllPermission; |
|
Devlin
2014/08/25 22:31:05
How about making a const char* kPermissions[] {
|
| + break; |
| + case MP_PARTICULAR: |
| + permission = kParticularPermission; |
| + break; |
| + case MP_NOWHERE: |
| + permission = kNowherePermission; |
| + break; |
| + } |
| + std::string manifest = base::StringPrintf(kManifest, permission); |
| + |
| + const char* matcher; |
|
Devlin
2014/08/25 22:31:05
ditto for matcher. Although if ManifestPermission
Mark Dittmer
2014/08/26 17:53:58
I was thinking that they may not remain the same s
|
| + switch (script_matcher) { |
| + case SM_ALL: |
| + matcher = kAllMatcher; |
| + break; |
| + case SM_PARTICULAR: |
| + matcher = kParticularMatcher; |
| + break; |
| + case SM_NOWHERE: |
| + matcher = kNowhereMatcher; |
| + break; |
| + } |
| + std::string background_src = base::StringPrintf(kBackgroundScriptSource, |
| + matcher); |
| + |
| + scoped_ptr<TestExtensionDir> dir(new TestExtensionDir); |
| + dir->WriteManifest(manifest); |
| + dir->WriteFile(FILE_PATH_LITERAL("background.js"), background_src); |
| + dir->WriteFile(FILE_PATH_LITERAL("script.js"), |
| + kContentScriptSource); |
| + |
| + const Extension* extension = LoadExtension(dir->unpacked_path()); |
| + if (!extension) |
| + return testing::AssertionFailure() << "Failed to load extension."; |
| + |
| + test_extension_dir_.reset(dir.release()); |
| + extension_ = extension; |
| + |
| + injection_setup_listener_.reset(new ExtensionTestMessageListener( |
| + kInjectionSetup, |
| + false /* won't reply */)); |
| + injection_succeeded_listener_.reset(new ExtensionTestMessageListener( |
| + kInjectionSucceeded, |
| + false /* won't reply */)); |
| + |
| + injection_setup_listener_->set_extension_id(extension->id()); |
| + injection_succeeded_listener_->set_extension_id(extension->id()); |
| + return testing::AssertionSuccess(); |
| +} |
| + |
| +testing::AssertionResult RequestContentScriptBrowserTest::RunTest() { |
| + if (!embedded_test_server()->InitializeAndWaitUntilReady()) { |
| + return testing::AssertionFailure() << |
| + "Could not initialize embedded test server."; |
| + } |
| + ui_test_utils::NavigateToURL( |
| + browser(), embedded_test_server()->GetURL("/extensions/test_file.html")); |
| + |
| + web_contents_ = |
| + browser() ? browser()->tab_strip_model()->GetActiveWebContents() : NULL; |
| + if (!web_contents_) |
| + return testing::AssertionFailure() << "No web contents."; |
| + |
|
Devlin
2014/08/25 22:31:05
Since we never ever ever expect our Injection Setu
Mark Dittmer
2014/08/26 17:53:58
Done.
|
| + // Give the extension plenty of time to inject. |
| + if (!RunAllPendingInRenderer(web_contents_)) |
| + return testing::AssertionFailure() << "Could not run pending in renderer."; |
| + |
| + // Make sure all running tasks are complete. |
| + content::RunAllPendingInMessageLoop(); |
| + |
| + return testing::AssertionSuccess(); |
| +} |
| + |
| +IN_PROC_BROWSER_TEST_F(RequestContentScriptBrowserTest, |
| + AllPermissionAllMatcherInject) { |
| + EXPECT_TRUE(Init(MP_ALL, SM_ALL)); |
| + EXPECT_TRUE(RunTest()); |
|
Devlin
2014/08/25 22:31:05
This is a *lot* of browsertests. Unfortunately, b
|
| + |
| + ASSERT_TRUE(injection_setup_listener()->was_satisfied()); |
| + ASSERT_TRUE(injection_succeeded_listener()->was_satisfied()); |
| +} |
| + |
| +IN_PROC_BROWSER_TEST_F(RequestContentScriptBrowserTest, |
| + AllPermissionParticularMatcherInject) { |
| + EXPECT_TRUE(Init(MP_ALL, SM_PARTICULAR)); |
| + EXPECT_TRUE(RunTest()); |
| + |
| + ASSERT_TRUE(injection_setup_listener()->was_satisfied()); |
| + ASSERT_TRUE(injection_succeeded_listener()->was_satisfied()); |
| +} |
| + |
| +IN_PROC_BROWSER_TEST_F(RequestContentScriptBrowserTest, |
| + ParticularPermissionAllMatcherInject) { |
| + EXPECT_TRUE(Init(MP_PARTICULAR, SM_ALL)); |
| + EXPECT_TRUE(RunTest()); |
| + |
| + ASSERT_TRUE(injection_setup_listener()->was_satisfied()); |
| + ASSERT_TRUE(injection_succeeded_listener()->was_satisfied()); |
| +} |
| + |
| +IN_PROC_BROWSER_TEST_F(RequestContentScriptBrowserTest, |
| + ParticularPermissionParticularMatcherInject) { |
| + EXPECT_TRUE(Init(MP_PARTICULAR, SM_PARTICULAR)); |
| + EXPECT_TRUE(RunTest()); |
| + |
| + ASSERT_TRUE(injection_setup_listener()->was_satisfied()); |
| + ASSERT_TRUE(injection_succeeded_listener()->was_satisfied()); |
| +} |
| + |
| +IN_PROC_BROWSER_TEST_F(RequestContentScriptBrowserTest, |
| + NowherePermissionAllMatcherNoInject) { |
| + EXPECT_TRUE(Init(MP_NOWHERE, SM_ALL)); |
| + EXPECT_TRUE(RunTest()); |
| + |
| + ASSERT_TRUE(injection_setup_listener()->was_satisfied()); |
| + ASSERT_FALSE(injection_succeeded_listener()->was_satisfied()); |
| +} |
| + |
| +IN_PROC_BROWSER_TEST_F(RequestContentScriptBrowserTest, |
| + NowherePermissionParticularMatcherNoInject) { |
| + EXPECT_TRUE(Init(MP_NOWHERE, SM_PARTICULAR)); |
| + EXPECT_TRUE(RunTest()); |
| + |
| + ASSERT_TRUE(injection_setup_listener()->was_satisfied()); |
| + ASSERT_FALSE(injection_succeeded_listener()->was_satisfied()); |
| +} |
| + |
| +IN_PROC_BROWSER_TEST_F(RequestContentScriptBrowserTest, |
| + NowherePermissionNowhereMatcherNoInject) { |
| + EXPECT_TRUE(Init(MP_NOWHERE, SM_NOWHERE)); |
| + EXPECT_TRUE(RunTest()); |
| + |
| + ASSERT_TRUE(injection_setup_listener()->was_satisfied()); |
| + ASSERT_FALSE(injection_succeeded_listener()->was_satisfied()); |
| +} |
| + |
| +IN_PROC_BROWSER_TEST_F(RequestContentScriptBrowserTest, |
| + AllPermissionNowhereMatcherNoInject) { |
| + EXPECT_TRUE(Init(MP_ALL, SM_NOWHERE)); |
| + EXPECT_TRUE(RunTest()); |
| + |
| + ASSERT_TRUE(injection_setup_listener()->was_satisfied()); |
| + ASSERT_FALSE(injection_succeeded_listener()->was_satisfied()); |
| +} |
| + |
| +IN_PROC_BROWSER_TEST_F(RequestContentScriptBrowserTest, |
| + ParticularPermissionNowhereMatcherNoInject) { |
| + EXPECT_TRUE(Init(MP_PARTICULAR, SM_NOWHERE)); |
| + EXPECT_TRUE(RunTest()); |
| + |
| + ASSERT_TRUE(injection_setup_listener()->was_satisfied()); |
| + ASSERT_FALSE(injection_succeeded_listener()->was_satisfied()); |
| +} |
| + |
| +} // namespace extensions |