X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fchrome%2Fbrowser%2Fextensions%2Factive_script_controller_unittest.cc;h=f40286bef8ad90e16baf771cf2c7db9dc915ecc7;hb=4a1a0bdd01eef90b0826a0e761d3379d3715c10f;hp=0b40328c14329891aeb22953d731e3e46710b495;hpb=b1be5ca53587d23e7aeb77b26861fdc0a181ffd8;p=platform%2Fframework%2Fweb%2Fcrosswalk.git diff --git a/src/chrome/browser/extensions/active_script_controller_unittest.cc b/src/chrome/browser/extensions/active_script_controller_unittest.cc index 0b40328..f40286b 100644 --- a/src/chrome/browser/extensions/active_script_controller_unittest.cc +++ b/src/chrome/browser/extensions/active_script_controller_unittest.cc @@ -8,6 +8,7 @@ #include "chrome/browser/extensions/active_script_controller.h" #include "chrome/browser/extensions/active_tab_permission_granter.h" #include "chrome/browser/extensions/extension_util.h" +#include "chrome/browser/extensions/permissions_updater.h" #include "chrome/browser/extensions/tab_helper.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/testing_profile.h" @@ -20,6 +21,7 @@ #include "extensions/common/feature_switch.h" #include "extensions/common/id_util.h" #include "extensions/common/manifest.h" +#include "extensions/common/user_script.h" #include "extensions/common/value_builder.h" namespace extensions { @@ -43,19 +45,28 @@ class ActiveScriptControllerUnitTest : public ChromeRenderViewHostTestHarness { // Creates an extension with all hosts permission and adds it to the registry. const Extension* AddExtension(); - // Returns the current page id. - int GetPageId(); + // Reloads |extension_| by removing it from the registry and recreating it. + const Extension* ReloadExtension(); - // Returns a closure to use as a script execution for a given extension. - base::Closure GetExecutionCallbackForExtension( - const std::string& extension_id); + // Returns true if the |extension| requires user consent before injecting + // a script. + bool RequiresUserConsent(const Extension* extension) const; + + // Request an injection for the given |extension|. + void RequestInjection(const Extension* extension); // Returns the number of times a given extension has had a script execute. size_t GetExecutionCountForExtension(const std::string& extension_id) const; - ActiveScriptController* controller() { return active_script_controller_; } + ActiveScriptController* controller() const { + return active_script_controller_; + } private: + // Returns a closure to use as a script execution for a given extension. + base::Closure GetExecutionCallbackForExtension( + const std::string& extension_id); + // Increment the number of executions for the given |extension_id|. void IncrementExecutionCount(const std::string& extension_id); @@ -70,6 +81,8 @@ class ActiveScriptControllerUnitTest : public ChromeRenderViewHostTestHarness { // The map of observed executions, keyed by extension id. std::map extension_executions_; + + scoped_refptr extension_; }; ActiveScriptControllerUnitTest::ActiveScriptControllerUnitTest() @@ -83,38 +96,44 @@ ActiveScriptControllerUnitTest::~ActiveScriptControllerUnitTest() { const Extension* ActiveScriptControllerUnitTest::AddExtension() { const std::string kId = id_util::GenerateId("all_hosts_extension"); - scoped_refptr extension = - ExtensionBuilder() - .SetManifest( - DictionaryBuilder() - .Set("name", "all_hosts_extension") - .Set("description", "an extension") - .Set("manifest_version", 2) - .Set("version", "1.0.0") - .Set("permissions", - ListBuilder().Append(kAllHostsPermission))) - .SetLocation(Manifest::INTERNAL) - .SetID(kId) - .Build(); - - ExtensionRegistry::Get(profile())->AddEnabled(extension); - return extension; + extension_ = ExtensionBuilder() + .SetManifest( + DictionaryBuilder() + .Set("name", "all_hosts_extension") + .Set("description", "an extension") + .Set("manifest_version", 2) + .Set("version", "1.0.0") + .Set("permissions", + ListBuilder().Append(kAllHostsPermission))) + .SetLocation(Manifest::INTERNAL) + .SetID(kId) + .Build(); + + ExtensionRegistry::Get(profile())->AddEnabled(extension_); + PermissionsUpdater(profile()).InitializePermissions(extension_); + return extension_; } -int ActiveScriptControllerUnitTest::GetPageId() { - content::NavigationEntry* navigation_entry = - web_contents()->GetController().GetVisibleEntry(); - DCHECK(navigation_entry); // This should never be NULL. - return navigation_entry->GetPageID(); +const Extension* ActiveScriptControllerUnitTest::ReloadExtension() { + ExtensionRegistry::Get(profile())->RemoveEnabled(extension_->id()); + return AddExtension(); } -base::Closure ActiveScriptControllerUnitTest::GetExecutionCallbackForExtension( - const std::string& extension_id) { - // We use base unretained here, but if this ever gets executed outside of - // this test's lifetime, we have a major problem anyway. - return base::Bind(&ActiveScriptControllerUnitTest::IncrementExecutionCount, - base::Unretained(this), - extension_id); +bool ActiveScriptControllerUnitTest::RequiresUserConsent( + const Extension* extension) const { + PermissionsData::AccessType access_type = + controller()->RequiresUserConsentForScriptInjectionForTesting( + extension, UserScript::PROGRAMMATIC_SCRIPT); + // We should never downright refuse access in these tests. + DCHECK_NE(PermissionsData::ACCESS_DENIED, access_type); + return access_type == PermissionsData::ACCESS_WITHHELD; +} + +void ActiveScriptControllerUnitTest::RequestInjection( + const Extension* extension) { + controller()->RequestScriptInjectionForTesting( + extension, + GetExecutionCallbackForExtension(extension->id())); } size_t ActiveScriptControllerUnitTest::GetExecutionCountForExtension( @@ -126,6 +145,15 @@ size_t ActiveScriptControllerUnitTest::GetExecutionCountForExtension( return 0u; } +base::Closure ActiveScriptControllerUnitTest::GetExecutionCallbackForExtension( + const std::string& extension_id) { + // We use base unretained here, but if this ever gets executed outside of + // this test's lifetime, we have a major problem anyway. + return base::Bind(&ActiveScriptControllerUnitTest::IncrementExecutionCount, + base::Unretained(this), + extension_id); +} + void ActiveScriptControllerUnitTest::IncrementExecutionCount( const std::string& extension_id) { ++extension_executions_[extension_id]; @@ -157,14 +185,10 @@ TEST_F(ActiveScriptControllerUnitTest, RequestPermissionAndExecute) { ASSERT_FALSE(controller()->GetActionForExtension(extension)); // Since the extension requests all_hosts, we should require user consent. - EXPECT_TRUE( - controller()->RequiresUserConsentForScriptInjection(extension)); + EXPECT_TRUE(RequiresUserConsent(extension)); // Request an injection. There should be an action visible, but no executions. - controller()->RequestScriptInjection( - extension, - GetPageId(), - GetExecutionCallbackForExtension(extension->id())); + RequestInjection(extension); EXPECT_TRUE(controller()->GetActionForExtension(extension)); EXPECT_EQ(0u, GetExecutionCountForExtension(extension->id())); @@ -177,28 +201,22 @@ TEST_F(ActiveScriptControllerUnitTest, RequestPermissionAndExecute) { // Since we already executed on the given page, we shouldn't need permission // for a second time. - EXPECT_FALSE( - controller()->RequiresUserConsentForScriptInjection(extension)); + EXPECT_FALSE(RequiresUserConsent(extension)); // Reloading should clear those permissions, and we should again require user // consent. Reload(); - EXPECT_TRUE( - controller()->RequiresUserConsentForScriptInjection(extension)); + EXPECT_TRUE(RequiresUserConsent(extension)); // Grant access. - controller()->RequestScriptInjection( - extension, - GetPageId(), - GetExecutionCallbackForExtension(extension->id())); + RequestInjection(extension); controller()->OnClicked(extension); EXPECT_EQ(2u, GetExecutionCountForExtension(extension->id())); EXPECT_FALSE(controller()->GetActionForExtension(extension)); // Navigating to another site should also clear the permissions. NavigateAndCommit(GURL("https://www.foo.com")); - EXPECT_TRUE( - controller()->RequiresUserConsentForScriptInjection(extension)); + EXPECT_TRUE(RequiresUserConsent(extension)); } // Test that injections that are not executed by the time the user navigates are @@ -212,10 +230,7 @@ TEST_F(ActiveScriptControllerUnitTest, PendingInjectionsRemovedAtNavigation) { ASSERT_EQ(0u, GetExecutionCountForExtension(extension->id())); // Request an injection. There should be an action visible, but no executions. - controller()->RequestScriptInjection( - extension, - GetPageId(), - GetExecutionCallbackForExtension(extension->id())); + RequestInjection(extension); EXPECT_TRUE(controller()->GetActionForExtension(extension)); EXPECT_EQ(0u, GetExecutionCountForExtension(extension->id())); @@ -226,10 +241,7 @@ TEST_F(ActiveScriptControllerUnitTest, PendingInjectionsRemovedAtNavigation) { EXPECT_EQ(0u, GetExecutionCountForExtension(extension->id())); // Request and accept a new injection. - controller()->RequestScriptInjection( - extension, - GetPageId(), - GetExecutionCallbackForExtension(extension->id())); + RequestInjection(extension); controller()->OnClicked(extension); // The extension should only have executed once, even though a grand total @@ -249,12 +261,9 @@ TEST_F(ActiveScriptControllerUnitTest, MultiplePendingInjection) { const size_t kNumInjections = 3u; // Queue multiple pending injections. - for (size_t i = 0u; i < kNumInjections; ++i) { - controller()->RequestScriptInjection( - extension, - GetPageId(), - GetExecutionCallbackForExtension(extension->id())); - } + for (size_t i = 0u; i < kNumInjections; ++i) + RequestInjection(extension); + EXPECT_EQ(0u, GetExecutionCountForExtension(extension->id())); controller()->OnClicked(extension); @@ -278,17 +287,14 @@ TEST_F(ActiveScriptControllerUnitTest, ActiveScriptsUseActiveTabPermissions) { // Since we have active tab permissions, we shouldn't need user consent // anymore. - EXPECT_FALSE(controller()->RequiresUserConsentForScriptInjection(extension)); + EXPECT_FALSE(RequiresUserConsent(extension)); // Also test that granting active tab runs any pending tasks. Reload(); // Navigating should mean we need permission again. - EXPECT_TRUE(controller()->RequiresUserConsentForScriptInjection(extension)); + EXPECT_TRUE(RequiresUserConsent(extension)); - controller()->RequestScriptInjection( - extension, - GetPageId(), - GetExecutionCallbackForExtension(extension->id())); + RequestInjection(extension); EXPECT_TRUE(controller()->GetActionForExtension(extension)); EXPECT_EQ(0u, GetExecutionCountForExtension(extension->id())); @@ -306,23 +312,80 @@ TEST_F(ActiveScriptControllerUnitTest, ActiveScriptsCanHaveAllUrlsPref) { ASSERT_TRUE(extension); NavigateAndCommit(GURL("https://www.google.com")); - EXPECT_TRUE(controller()->RequiresUserConsentForScriptInjection(extension)); + EXPECT_TRUE(RequiresUserConsent(extension)); // Enable the extension on all urls. util::SetAllowedScriptingOnAllUrls(extension->id(), profile(), true); - EXPECT_FALSE(controller()->RequiresUserConsentForScriptInjection(extension)); + EXPECT_FALSE(RequiresUserConsent(extension)); // This should carry across navigations, and websites. NavigateAndCommit(GURL("http://www.foo.com")); - EXPECT_FALSE(controller()->RequiresUserConsentForScriptInjection(extension)); + EXPECT_FALSE(RequiresUserConsent(extension)); // Turning off the preference should have instant effect. util::SetAllowedScriptingOnAllUrls(extension->id(), profile(), false); - EXPECT_TRUE(controller()->RequiresUserConsentForScriptInjection(extension)); + EXPECT_TRUE(RequiresUserConsent(extension)); // And should also persist across navigations and websites. NavigateAndCommit(GURL("http://www.bar.com")); - EXPECT_TRUE(controller()->RequiresUserConsentForScriptInjection(extension)); + EXPECT_TRUE(RequiresUserConsent(extension)); +} + +TEST_F(ActiveScriptControllerUnitTest, TestAlwaysRun) { + const Extension* extension = AddExtension(); + ASSERT_TRUE(extension); + + NavigateAndCommit(GURL("https://www.google.com/?gws_rd=ssl")); + + // Ensure that there aren't any executions pending. + ASSERT_EQ(0u, GetExecutionCountForExtension(extension->id())); + ASSERT_FALSE(controller()->GetActionForExtension(extension)); + + // Since the extension requests all_hosts, we should require user consent. + EXPECT_TRUE(RequiresUserConsent(extension)); + + // Request an injection. There should be an action visible, but no executions. + RequestInjection(extension); + EXPECT_TRUE(controller()->GetActionForExtension(extension)); + EXPECT_EQ(0u, GetExecutionCountForExtension(extension->id())); + + // Allow the extension to always run on this origin. + controller()->AlwaysRunOnVisibleOrigin(extension); + + // The extension should execute, and the action should go away. + EXPECT_EQ(1u, GetExecutionCountForExtension(extension->id())); + EXPECT_FALSE(controller()->GetActionForExtension(extension)); + + // Since we already executed on the given page, we shouldn't need permission + // for a second time. + EXPECT_FALSE(RequiresUserConsent(extension)); + + // Navigating to another site that hasn't been granted a persisted permission + // should necessitate user consent. + NavigateAndCommit(GURL("https://www.foo.com/bar")); + EXPECT_TRUE(RequiresUserConsent(extension)); + + // We shouldn't need user permission upon returning to the original origin. + NavigateAndCommit(GURL("https://www.google.com/foo/bar")); + EXPECT_FALSE(RequiresUserConsent(extension)); + + // Reloading the extension should not clear any granted host permissions. + extension = ReloadExtension(); + Reload(); + EXPECT_FALSE(RequiresUserConsent(extension)); + + // Different host... + NavigateAndCommit(GURL("https://www.foo.com/bar")); + EXPECT_TRUE(RequiresUserConsent(extension)); + // Different scheme... + NavigateAndCommit(GURL("http://www.google.com/foo/bar")); + EXPECT_TRUE(RequiresUserConsent(extension)); + // Different subdomain... + NavigateAndCommit(GURL("https://en.google.com/foo/bar")); + EXPECT_TRUE(RequiresUserConsent(extension)); + // Only the "always run" origin should be allowed to run without user consent. + NavigateAndCommit(GURL("https://www.google.com/foo/bar")); + EXPECT_FALSE(RequiresUserConsent(extension)); } } // namespace extensions