Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / extensions / api / declarative / declarative_apitest.cc
blob01317585bcd8551f41a3638d9b676a5f55085fc1
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/bind.h"
6 #include "base/bind_helpers.h"
7 #include "base/command_line.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/test/thread_test_helper.h"
12 #include "chrome/browser/extensions/extension_apitest.h"
13 #include "chrome/browser/extensions/test_extension_dir.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/tabs/tab_strip_model.h"
16 #include "chrome/test/base/ui_test_utils.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "extensions/browser/api/declarative/rules_registry_service.h"
19 #include "extensions/browser/api/declarative_webrequest/webrequest_constants.h"
20 #include "extensions/browser/api/declarative_webrequest/webrequest_rules_registry.h"
21 #include "extensions/browser/extension_prefs.h"
22 #include "extensions/common/extension.h"
23 #include "extensions/test/extension_test_message_listener.h"
25 using content::BrowserThread;
27 namespace extensions {
29 namespace {
31 const char kArbitraryUrl[] = "http://www.example.com"; // Must be http://.
33 // The extension in "declarative/redirect_to_data" redirects every navigation to
34 // a page with title |kTestTitle|.
35 #define TEST_TITLE_STRING ":TEST:"
36 const char kTestTitle[] = TEST_TITLE_STRING;
38 // All methods and constands below containing "RedirectToData" in their names
39 // are parts of a test extension "Redirect to 'data:'".
40 std::string GetRedirectToDataManifestWithVersion(unsigned version) {
41 return base::StringPrintf(
42 "{\n"
43 " \"name\": \"Redirect to 'data:' (declarative apitest)\",\n"
44 " \"version\": \"%d\",\n"
45 " \"manifest_version\": 2,\n"
46 " \"description\": \"Redirects all requests to a fixed data: URI.\",\n"
47 " \"background\": {\n"
48 " \"scripts\": [\"background.js\"]\n"
49 " },\n"
50 " \"permissions\": [\n"
51 " \"declarativeWebRequest\", \"<all_urls>\"\n"
52 " ]\n"
53 "}\n",
54 version);
57 const char kRedirectToDataConstants[] =
58 "var redirectDataURI =\n"
59 " 'data:text/html;charset=utf-8,<html><head><title>' +\n"
60 " '" TEST_TITLE_STRING "' +\n"
61 " '<%2Ftitle><%2Fhtml>';\n";
62 #undef TEST_TITLE_STRING
64 const char kRedirectToDataRules[] =
65 "var rules = [{\n"
66 " conditions: [\n"
67 " new chrome.declarativeWebRequest.RequestMatcher({\n"
68 " url: {schemes: ['http']}})\n"
69 " ],\n"
70 " actions: [\n"
71 " new chrome.declarativeWebRequest.RedirectRequest({\n"
72 " redirectUrl: redirectDataURI\n"
73 " })\n"
74 " ]\n"
75 "}];\n";
77 const char kRedirectToDataInstallRules[] =
78 "function report(details) {\n"
79 " if (chrome.extension.lastError) {\n"
80 " chrome.test.log(chrome.extension.lastError.message);\n"
81 " } else {\n"
82 " chrome.test.sendMessage(\"ready\", function(reply) {})\n"
83 " }\n"
84 "}\n"
85 "\n"
86 "chrome.runtime.onInstalled.addListener(function(details) {\n"
87 " if (details.reason == 'install')\n"
88 " chrome.declarativeWebRequest.onRequest.addRules(rules, report);\n"
89 "});\n";
91 const char kRedirectToDataNoRules[] =
92 "chrome.runtime.onInstalled.addListener(function(details) {\n"
93 " chrome.test.sendMessage(\"ready\", function(reply) {})\n"
94 "});\n";
96 } // namespace
98 class DeclarativeApiTest : public ExtensionApiTest {
99 public:
100 std::string GetTitle() {
101 base::string16 title(
102 browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
103 return base::UTF16ToUTF8(title);
106 // Reports the number of rules registered for the |extension_id| with the
107 // non-webview rules registry.
108 size_t NumberOfRegisteredRules(const std::string& extension_id) {
109 RulesRegistryService* rules_registry_service =
110 extensions::RulesRegistryService::Get(browser()->profile());
111 scoped_refptr<RulesRegistry> rules_registry =
112 rules_registry_service->GetRulesRegistry(
113 RulesRegistryService::kDefaultRulesRegistryID,
114 extensions::declarative_webrequest_constants::kOnRequest);
116 std::vector<linked_ptr<api::events::Rule>> rules;
117 BrowserThread::PostTask(
118 BrowserThread::IO,
119 FROM_HERE,
120 base::Bind(
121 &RulesRegistry::GetAllRules, rules_registry, extension_id, &rules));
122 scoped_refptr<base::ThreadTestHelper> io_helper(new base::ThreadTestHelper(
123 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get()));
124 EXPECT_TRUE(io_helper->Run());
125 return rules.size();
129 IN_PROC_BROWSER_TEST_F(DeclarativeApiTest, DeclarativeApi) {
130 ASSERT_TRUE(RunExtensionTest("declarative/api")) << message_;
132 // Check that uninstalling the extension has removed all rules.
133 std::string extension_id = GetSingleLoadedExtension()->id();
134 UninstallExtension(extension_id);
136 // UnloadExtension posts a task to the owner thread of the extension
137 // to process this unloading. The next task to retrive all rules
138 // is therefore processed after the UnloadExtension task has been executed.
139 EXPECT_EQ(0u, NumberOfRegisteredRules(extension_id));
142 // PersistRules test first installs an extension, which registers some rules.
143 // Then after browser restart, it checks that the rules are still in effect.
144 IN_PROC_BROWSER_TEST_F(DeclarativeApiTest, PRE_PersistRules) {
145 // Note that we cannot use an extension generated by *GetRedirectToData*
146 // helpers in a TestExtensionDir, because we need the extension to persist
147 // until the PersistRules test is run.
148 ASSERT_TRUE(RunExtensionTest("declarative/redirect_to_data")) << message_;
151 IN_PROC_BROWSER_TEST_F(DeclarativeApiTest, PersistRules) {
152 ui_test_utils::NavigateToURL(browser(), GURL(kArbitraryUrl));
153 EXPECT_EQ(kTestTitle, GetTitle());
156 // Test that the rules are correctly persisted and (de)activated during
157 // changing the "installed" and "enabled" status of an extension.
158 IN_PROC_BROWSER_TEST_F(DeclarativeApiTest, ExtensionLifetimeRulesHandling) {
159 TestExtensionDir ext_dir;
161 // 1. Install the extension. Rules should become active.
162 ext_dir.WriteManifest(GetRedirectToDataManifestWithVersion(1));
163 ext_dir.WriteFile(FILE_PATH_LITERAL("background.js"),
164 base::StringPrintf("%s%s%s",
165 kRedirectToDataConstants,
166 kRedirectToDataRules,
167 kRedirectToDataInstallRules));
168 ExtensionTestMessageListener ready("ready", /*will_reply=*/false);
169 const Extension* extension = InstallExtensionWithUIAutoConfirm(
170 ext_dir.Pack(), 1 /*+1 installed extension*/, browser());
171 ASSERT_TRUE(extension);
172 std::string extension_id(extension->id());
173 ASSERT_TRUE(ready.WaitUntilSatisfied());
174 ui_test_utils::NavigateToURL(browser(), GURL(kArbitraryUrl));
175 EXPECT_EQ(kTestTitle, GetTitle());
176 EXPECT_EQ(1u, NumberOfRegisteredRules(extension_id));
178 // 2. Disable the extension. Rules are no longer active, but are still
179 // registered.
180 DisableExtension(extension_id);
181 ui_test_utils::NavigateToURL(browser(), GURL(kArbitraryUrl));
182 EXPECT_NE(kTestTitle, GetTitle());
183 EXPECT_EQ(1u, NumberOfRegisteredRules(extension_id));
185 // 3. Enable the extension again. Rules are active again.
186 EnableExtension(extension_id);
187 ui_test_utils::NavigateToURL(browser(), GURL(kArbitraryUrl));
188 EXPECT_EQ(kTestTitle, GetTitle());
189 EXPECT_EQ(1u, NumberOfRegisteredRules(extension_id));
191 // 4. Bump the version and update, without the code to add the rules. Rules
192 // are still active, because the registry does not drop them unless the
193 // extension gets uninstalled.
194 ext_dir.WriteManifest(GetRedirectToDataManifestWithVersion(2));
195 ext_dir.WriteFile(
196 FILE_PATH_LITERAL("background.js"),
197 base::StringPrintf(
198 "%s%s", kRedirectToDataConstants, kRedirectToDataNoRules));
199 ExtensionTestMessageListener ready_after_update("ready",
200 /*will_reply=*/false);
201 EXPECT_TRUE(UpdateExtension(
202 extension_id, ext_dir.Pack(), 0 /*no new installed extension*/));
203 ASSERT_TRUE(ready_after_update.WaitUntilSatisfied());
204 ui_test_utils::NavigateToURL(browser(), GURL(kArbitraryUrl));
205 EXPECT_EQ(kTestTitle, GetTitle());
206 EXPECT_EQ(1u, NumberOfRegisteredRules(extension_id));
208 // 5. Reload the extension. Rules remain active.
209 ReloadExtension(extension_id);
210 ui_test_utils::NavigateToURL(browser(), GURL(kArbitraryUrl));
211 EXPECT_EQ(kTestTitle, GetTitle());
212 EXPECT_EQ(1u, NumberOfRegisteredRules(extension_id));
214 // 6. Uninstall the extension. Rules are gone.
215 UninstallExtension(extension_id);
216 ui_test_utils::NavigateToURL(browser(), GURL(kArbitraryUrl));
217 EXPECT_NE(kTestTitle, GetTitle());
218 EXPECT_EQ(0u, NumberOfRegisteredRules(extension_id));
221 // When an extenion is uninstalled, the state store deletes all preferences
222 // stored for that extension. We need to make sure we don't store anything after
223 // that deletion occurs.
224 IN_PROC_BROWSER_TEST_F(DeclarativeApiTest, NoTracesAfterUninstalling) {
225 TestExtensionDir ext_dir;
227 // 1. Install the extension. Verify that rules become active and some prefs
228 // are stored.
229 ext_dir.WriteManifest(GetRedirectToDataManifestWithVersion(1));
230 ext_dir.WriteFile(FILE_PATH_LITERAL("background.js"),
231 base::StringPrintf("%s%s%s",
232 kRedirectToDataConstants,
233 kRedirectToDataRules,
234 kRedirectToDataInstallRules));
235 ExtensionTestMessageListener ready("ready", /*will_reply=*/false);
236 const Extension* extension = InstallExtensionWithUIAutoConfirm(
237 ext_dir.Pack(), 1 /*+1 installed extension*/, browser());
238 ASSERT_TRUE(extension);
239 std::string extension_id(extension->id());
240 ASSERT_TRUE(ready.WaitUntilSatisfied());
241 ui_test_utils::NavigateToURL(browser(), GURL(kArbitraryUrl));
242 EXPECT_EQ(kTestTitle, GetTitle());
243 EXPECT_EQ(1u, NumberOfRegisteredRules(extension_id));
244 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(browser()->profile());
245 EXPECT_TRUE(extension_prefs->HasPrefForExtension(extension_id));
247 // 2. Uninstall the extension. Rules are gone and preferences should be empty.
248 UninstallExtension(extension_id);
249 ui_test_utils::NavigateToURL(browser(), GURL(kArbitraryUrl));
250 EXPECT_NE(kTestTitle, GetTitle());
251 EXPECT_EQ(0u, NumberOfRegisteredRules(extension_id));
252 EXPECT_FALSE(extension_prefs->HasPrefForExtension(extension_id));
255 } // namespace extensions