Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / extensions / extension_user_script_loader_unittest.cc
blob02de7812a67e8913288b35d86327c8a7de17c1cf
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
3 // found in the LICENSE file.
5 #include "extensions/browser/extension_user_script_loader.h"
7 #include <set>
8 #include <string>
10 #include "base/files/file_path.h"
11 #include "base/files/file_util.h"
12 #include "base/files/scoped_temp_dir.h"
13 #include "base/location.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/strings/string_util.h"
16 #include "chrome/browser/chrome_notification_types.h"
17 #include "chrome/test/base/testing_profile.h"
18 #include "content/public/browser/notification_observer.h"
19 #include "content/public/browser/notification_registrar.h"
20 #include "content/public/browser/notification_service.h"
21 #include "content/public/test/test_browser_thread.h"
22 #include "extensions/common/host_id.h"
23 #include "testing/gtest/include/gtest/gtest.h"
25 using content::BrowserThread;
26 using extensions::URLPatternSet;
28 namespace {
30 static void AddPattern(URLPatternSet* extent, const std::string& pattern) {
31 int schemes = URLPattern::SCHEME_ALL;
32 extent->AddPattern(URLPattern(schemes, pattern));
36 namespace extensions {
38 // Test bringing up a script loader on a specific directory, putting a script
39 // in there, etc.
41 class ExtensionUserScriptLoaderTest : public testing::Test,
42 public content::NotificationObserver {
43 public:
44 ExtensionUserScriptLoaderTest() : shared_memory_(NULL) {}
46 void SetUp() override {
47 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
49 // Register for all user script notifications.
50 registrar_.Add(this,
51 extensions::NOTIFICATION_USER_SCRIPTS_UPDATED,
52 content::NotificationService::AllSources());
54 // ExtensionUserScriptLoader posts tasks to the file thread so make the
55 // current thread look like one.
56 file_thread_.reset(new content::TestBrowserThread(
57 BrowserThread::FILE, base::MessageLoop::current()));
58 ui_thread_.reset(new content::TestBrowserThread(
59 BrowserThread::UI, base::MessageLoop::current()));
62 void TearDown() override {
63 file_thread_.reset();
64 ui_thread_.reset();
67 void Observe(int type,
68 const content::NotificationSource& source,
69 const content::NotificationDetails& details) override {
70 DCHECK(type == extensions::NOTIFICATION_USER_SCRIPTS_UPDATED);
72 shared_memory_ = content::Details<base::SharedMemory>(details).ptr();
73 if (base::MessageLoop::current() == &message_loop_)
74 base::MessageLoop::current()->Quit();
77 // Directory containing user scripts.
78 base::ScopedTempDir temp_dir_;
80 content::NotificationRegistrar registrar_;
82 // MessageLoop used in tests.
83 base::MessageLoopForUI message_loop_;
85 scoped_ptr<content::TestBrowserThread> file_thread_;
86 scoped_ptr<content::TestBrowserThread> ui_thread_;
88 // Updated to the script shared memory when we get notified.
89 base::SharedMemory* shared_memory_;
92 // Test that we get notified even when there are no scripts.
93 TEST_F(ExtensionUserScriptLoaderTest, NoScripts) {
94 TestingProfile profile;
95 ExtensionUserScriptLoader loader(
96 &profile,
97 HostID(),
98 true /* listen_for_extension_system_loaded */);
99 loader.StartLoad();
100 message_loop_.task_runner()->PostTask(FROM_HERE,
101 base::MessageLoop::QuitClosure());
102 message_loop_.Run();
104 ASSERT_TRUE(shared_memory_ != NULL);
107 TEST_F(ExtensionUserScriptLoaderTest, Parse1) {
108 const std::string text(
109 "// This is my awesome script\n"
110 "// It does stuff.\n"
111 "// ==UserScript== trailing garbage\n"
112 "// @name foobar script\n"
113 "// @namespace http://www.google.com/\n"
114 "// @include *mail.google.com*\n"
115 "// \n"
116 "// @othergarbage\n"
117 "// @include *mail.yahoo.com*\r\n"
118 "// @include \t *mail.msn.com*\n" // extra spaces after "@include" OK
119 "//@include not-recognized\n" // must have one space after "//"
120 "// ==/UserScript== trailing garbage\n"
121 "\n"
122 "\n"
123 "alert('hoo!');\n");
125 UserScript script;
126 EXPECT_TRUE(ExtensionUserScriptLoader::ParseMetadataHeader(text, &script));
127 ASSERT_EQ(3U, script.globs().size());
128 EXPECT_EQ("*mail.google.com*", script.globs()[0]);
129 EXPECT_EQ("*mail.yahoo.com*", script.globs()[1]);
130 EXPECT_EQ("*mail.msn.com*", script.globs()[2]);
133 TEST_F(ExtensionUserScriptLoaderTest, Parse2) {
134 const std::string text("default to @include *");
136 UserScript script;
137 EXPECT_TRUE(ExtensionUserScriptLoader::ParseMetadataHeader(text, &script));
138 ASSERT_EQ(1U, script.globs().size());
139 EXPECT_EQ("*", script.globs()[0]);
142 TEST_F(ExtensionUserScriptLoaderTest, Parse3) {
143 const std::string text(
144 "// ==UserScript==\n"
145 "// @include *foo*\n"
146 "// ==/UserScript=="); // no trailing newline
148 UserScript script;
149 ExtensionUserScriptLoader::ParseMetadataHeader(text, &script);
150 ASSERT_EQ(1U, script.globs().size());
151 EXPECT_EQ("*foo*", script.globs()[0]);
154 TEST_F(ExtensionUserScriptLoaderTest, Parse4) {
155 const std::string text(
156 "// ==UserScript==\n"
157 "// @match http://*.mail.google.com/*\n"
158 "// @match \t http://mail.yahoo.com/*\n"
159 "// ==/UserScript==\n");
161 URLPatternSet expected_patterns;
162 AddPattern(&expected_patterns, "http://*.mail.google.com/*");
163 AddPattern(&expected_patterns, "http://mail.yahoo.com/*");
165 UserScript script;
166 EXPECT_TRUE(ExtensionUserScriptLoader::ParseMetadataHeader(text, &script));
167 EXPECT_EQ(0U, script.globs().size());
168 EXPECT_EQ(expected_patterns, script.url_patterns());
171 TEST_F(ExtensionUserScriptLoaderTest, Parse5) {
172 const std::string text(
173 "// ==UserScript==\n"
174 "// @match http://*mail.google.com/*\n"
175 "// ==/UserScript==\n");
177 // Invalid @match value.
178 UserScript script;
179 EXPECT_FALSE(ExtensionUserScriptLoader::ParseMetadataHeader(text, &script));
182 TEST_F(ExtensionUserScriptLoaderTest, Parse6) {
183 const std::string text(
184 "// ==UserScript==\n"
185 "// @include http://*.mail.google.com/*\n"
186 "// @match \t http://mail.yahoo.com/*\n"
187 "// ==/UserScript==\n");
189 // Allowed to match @include and @match.
190 UserScript script;
191 EXPECT_TRUE(ExtensionUserScriptLoader::ParseMetadataHeader(text, &script));
194 TEST_F(ExtensionUserScriptLoaderTest, Parse7) {
195 // Greasemonkey allows there to be any leading text before the comment marker.
196 const std::string text(
197 "// ==UserScript==\n"
198 "adsasdfasf// @name hello\n"
199 " // @description\twiggity woo\n"
200 "\t// @match \t http://mail.yahoo.com/*\n"
201 "// ==/UserScript==\n");
203 UserScript script;
204 EXPECT_TRUE(ExtensionUserScriptLoader::ParseMetadataHeader(text, &script));
205 ASSERT_EQ("hello", script.name());
206 ASSERT_EQ("wiggity woo", script.description());
207 ASSERT_EQ(1U, script.url_patterns().patterns().size());
208 EXPECT_EQ("http://mail.yahoo.com/*",
209 script.url_patterns().begin()->GetAsString());
212 TEST_F(ExtensionUserScriptLoaderTest, Parse8) {
213 const std::string text(
214 "// ==UserScript==\n"
215 "// @name myscript\n"
216 "// @match http://www.google.com/*\n"
217 "// @exclude_match http://www.google.com/foo*\n"
218 "// ==/UserScript==\n");
220 UserScript script;
221 EXPECT_TRUE(ExtensionUserScriptLoader::ParseMetadataHeader(text, &script));
222 ASSERT_EQ("myscript", script.name());
223 ASSERT_EQ(1U, script.url_patterns().patterns().size());
224 EXPECT_EQ("http://www.google.com/*",
225 script.url_patterns().begin()->GetAsString());
226 ASSERT_EQ(1U, script.exclude_url_patterns().patterns().size());
227 EXPECT_EQ("http://www.google.com/foo*",
228 script.exclude_url_patterns().begin()->GetAsString());
231 TEST_F(ExtensionUserScriptLoaderTest, SkipBOMAtTheBeginning) {
232 base::FilePath path = temp_dir_.path().AppendASCII("script.user.js");
233 const std::string content("\xEF\xBB\xBF alert('hello');");
234 size_t written = base::WriteFile(path, content.c_str(), content.size());
235 ASSERT_EQ(written, content.size());
237 UserScript user_script;
238 user_script.js_scripts().push_back(
239 UserScript::File(temp_dir_.path(), path.BaseName(), GURL()));
241 UserScriptList user_scripts;
242 user_scripts.push_back(user_script);
244 TestingProfile profile;
245 ExtensionUserScriptLoader loader(
246 &profile,
247 HostID(),
248 true /* listen_for_extension_system_loaded */);
249 loader.LoadScriptsForTest(&user_scripts);
251 EXPECT_EQ(content.substr(3),
252 user_scripts[0].js_scripts()[0].GetContent().as_string());
255 TEST_F(ExtensionUserScriptLoaderTest, LeaveBOMNotAtTheBeginning) {
256 base::FilePath path = temp_dir_.path().AppendASCII("script.user.js");
257 const std::string content("alert('here's a BOOM: \xEF\xBB\xBF');");
258 size_t written = base::WriteFile(path, content.c_str(), content.size());
259 ASSERT_EQ(written, content.size());
261 UserScript user_script;
262 user_script.js_scripts().push_back(UserScript::File(
263 temp_dir_.path(), path.BaseName(), GURL()));
265 UserScriptList user_scripts;
266 user_scripts.push_back(user_script);
268 TestingProfile profile;
269 ExtensionUserScriptLoader loader(
270 &profile,
271 HostID(),
272 true /* listen_for_extension_system_loaded */);
273 loader.LoadScriptsForTest(&user_scripts);
275 EXPECT_EQ(content, user_scripts[0].js_scripts()[0].GetContent().as_string());
278 } // namespace extensions