• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 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.
4 
5 #include "extensions/common/user_script.h"
6 
7 #include "base/atomic_sequence_num.h"
8 #include "base/command_line.h"
9 #include "base/pickle.h"
10 #include "base/strings/string_util.h"
11 #include "extensions/common/switches.h"
12 
13 namespace {
14 
15 // This cannot be a plain int or int64 because we need to generate unique IDs
16 // from multiple threads.
17 base::StaticAtomicSequenceNumber g_user_script_id_generator;
18 
UrlMatchesGlobs(const std::vector<std::string> * globs,const GURL & url)19 bool UrlMatchesGlobs(const std::vector<std::string>* globs,
20                      const GURL& url) {
21   for (std::vector<std::string>::const_iterator glob = globs->begin();
22        glob != globs->end(); ++glob) {
23     if (MatchPattern(url.spec(), *glob))
24       return true;
25   }
26 
27   return false;
28 }
29 
30 }  // namespace
31 
32 namespace extensions {
33 
34 // The bitmask for valid user script injectable schemes used by URLPattern.
35 enum {
36   kValidUserScriptSchemes = URLPattern::SCHEME_CHROMEUI |
37                             URLPattern::SCHEME_HTTP |
38                             URLPattern::SCHEME_HTTPS |
39                             URLPattern::SCHEME_FILE |
40                             URLPattern::SCHEME_FTP
41 };
42 
43 // static
44 const char UserScript::kFileExtension[] = ".user.js";
45 
46 
47 // static
GenerateUserScriptID()48 int UserScript::GenerateUserScriptID() {
49    return g_user_script_id_generator.GetNext();
50 }
51 
IsURLUserScript(const GURL & url,const std::string & mime_type)52 bool UserScript::IsURLUserScript(const GURL& url,
53                                  const std::string& mime_type) {
54   return EndsWith(url.ExtractFileName(), kFileExtension, false) &&
55       mime_type != "text/html";
56 }
57 
58 // static
ValidUserScriptSchemes(bool canExecuteScriptEverywhere)59 int UserScript::ValidUserScriptSchemes(bool canExecuteScriptEverywhere) {
60   if (canExecuteScriptEverywhere)
61     return URLPattern::SCHEME_ALL;
62   int valid_schemes = kValidUserScriptSchemes;
63   if (!CommandLine::ForCurrentProcess()->HasSwitch(
64       switches::kExtensionsOnChromeURLs)) {
65     valid_schemes &= ~URLPattern::SCHEME_CHROMEUI;
66   }
67   return valid_schemes;
68 }
69 
File(const base::FilePath & extension_root,const base::FilePath & relative_path,const GURL & url)70 UserScript::File::File(const base::FilePath& extension_root,
71                        const base::FilePath& relative_path,
72                        const GURL& url)
73     : extension_root_(extension_root),
74       relative_path_(relative_path),
75       url_(url) {
76 }
77 
File()78 UserScript::File::File() {}
79 
~File()80 UserScript::File::~File() {}
81 
UserScript()82 UserScript::UserScript()
83     : run_location_(DOCUMENT_IDLE),
84       user_script_id_(-1),
85       emulate_greasemonkey_(false),
86       match_all_frames_(false),
87       match_about_blank_(false),
88       incognito_enabled_(false) {}
89 
~UserScript()90 UserScript::~UserScript() {
91 }
92 
add_url_pattern(const URLPattern & pattern)93 void UserScript::add_url_pattern(const URLPattern& pattern) {
94   url_set_.AddPattern(pattern);
95 }
96 
add_exclude_url_pattern(const URLPattern & pattern)97 void UserScript::add_exclude_url_pattern(const URLPattern& pattern) {
98   exclude_url_set_.AddPattern(pattern);
99 }
100 
MatchesURL(const GURL & url) const101 bool UserScript::MatchesURL(const GURL& url) const {
102   if (!url_set_.is_empty()) {
103     if (!url_set_.MatchesURL(url))
104       return false;
105   }
106 
107   if (!exclude_url_set_.is_empty()) {
108     if (exclude_url_set_.MatchesURL(url))
109       return false;
110   }
111 
112   if (!globs_.empty()) {
113     if (!UrlMatchesGlobs(&globs_, url))
114       return false;
115   }
116 
117   if (!exclude_globs_.empty()) {
118     if (UrlMatchesGlobs(&exclude_globs_, url))
119       return false;
120   }
121 
122   return true;
123 }
124 
Pickle(::Pickle * pickle) const125 void UserScript::File::Pickle(::Pickle* pickle) const {
126   pickle->WriteString(url_.spec());
127   // Do not write path. It's not needed in the renderer.
128   // Do not write content. It will be serialized by other means.
129 }
130 
Unpickle(const::Pickle & pickle,PickleIterator * iter)131 void UserScript::File::Unpickle(const ::Pickle& pickle, PickleIterator* iter) {
132   // Read the url from the pickle.
133   std::string url;
134   CHECK(pickle.ReadString(iter, &url));
135   set_url(GURL(url));
136 }
137 
Pickle(::Pickle * pickle) const138 void UserScript::Pickle(::Pickle* pickle) const {
139   // Write the simple types to the pickle.
140   pickle->WriteInt(run_location());
141   pickle->WriteString(extension_id());
142   pickle->WriteInt(user_script_id_);
143   pickle->WriteBool(emulate_greasemonkey());
144   pickle->WriteBool(match_all_frames());
145   pickle->WriteBool(match_about_blank());
146   pickle->WriteBool(is_incognito_enabled());
147 
148   PickleGlobs(pickle, globs_);
149   PickleGlobs(pickle, exclude_globs_);
150   PickleURLPatternSet(pickle, url_set_);
151   PickleURLPatternSet(pickle, exclude_url_set_);
152   PickleScripts(pickle, js_scripts_);
153   PickleScripts(pickle, css_scripts_);
154 }
155 
PickleGlobs(::Pickle * pickle,const std::vector<std::string> & globs) const156 void UserScript::PickleGlobs(::Pickle* pickle,
157                              const std::vector<std::string>& globs) const {
158   pickle->WriteUInt64(globs.size());
159   for (std::vector<std::string>::const_iterator glob = globs.begin();
160        glob != globs.end(); ++glob) {
161     pickle->WriteString(*glob);
162   }
163 }
164 
PickleURLPatternSet(::Pickle * pickle,const URLPatternSet & pattern_list) const165 void UserScript::PickleURLPatternSet(::Pickle* pickle,
166                                      const URLPatternSet& pattern_list) const {
167   pickle->WriteUInt64(pattern_list.patterns().size());
168   for (URLPatternSet::const_iterator pattern = pattern_list.begin();
169        pattern != pattern_list.end(); ++pattern) {
170     pickle->WriteInt(pattern->valid_schemes());
171     pickle->WriteString(pattern->GetAsString());
172   }
173 }
174 
PickleScripts(::Pickle * pickle,const FileList & scripts) const175 void UserScript::PickleScripts(::Pickle* pickle,
176                                const FileList& scripts) const {
177   pickle->WriteUInt64(scripts.size());
178   for (FileList::const_iterator file = scripts.begin();
179        file != scripts.end(); ++file) {
180     file->Pickle(pickle);
181   }
182 }
183 
Unpickle(const::Pickle & pickle,PickleIterator * iter)184 void UserScript::Unpickle(const ::Pickle& pickle, PickleIterator* iter) {
185   // Read the run location.
186   int run_location = 0;
187   CHECK(pickle.ReadInt(iter, &run_location));
188   CHECK(run_location >= 0 && run_location < RUN_LOCATION_LAST);
189   run_location_ = static_cast<RunLocation>(run_location);
190 
191   CHECK(pickle.ReadString(iter, &extension_id_));
192   CHECK(pickle.ReadInt(iter, &user_script_id_));
193   CHECK(pickle.ReadBool(iter, &emulate_greasemonkey_));
194   CHECK(pickle.ReadBool(iter, &match_all_frames_));
195   CHECK(pickle.ReadBool(iter, &match_about_blank_));
196   CHECK(pickle.ReadBool(iter, &incognito_enabled_));
197 
198   UnpickleGlobs(pickle, iter, &globs_);
199   UnpickleGlobs(pickle, iter, &exclude_globs_);
200   UnpickleURLPatternSet(pickle, iter, &url_set_);
201   UnpickleURLPatternSet(pickle, iter, &exclude_url_set_);
202   UnpickleScripts(pickle, iter, &js_scripts_);
203   UnpickleScripts(pickle, iter, &css_scripts_);
204 }
205 
UnpickleGlobs(const::Pickle & pickle,PickleIterator * iter,std::vector<std::string> * globs)206 void UserScript::UnpickleGlobs(const ::Pickle& pickle, PickleIterator* iter,
207                                std::vector<std::string>* globs) {
208   uint64 num_globs = 0;
209   CHECK(pickle.ReadUInt64(iter, &num_globs));
210   globs->clear();
211   for (uint64 i = 0; i < num_globs; ++i) {
212     std::string glob;
213     CHECK(pickle.ReadString(iter, &glob));
214     globs->push_back(glob);
215   }
216 }
217 
UnpickleURLPatternSet(const::Pickle & pickle,PickleIterator * iter,URLPatternSet * pattern_list)218 void UserScript::UnpickleURLPatternSet(const ::Pickle& pickle,
219                                        PickleIterator* iter,
220                                        URLPatternSet* pattern_list) {
221   uint64 num_patterns = 0;
222   CHECK(pickle.ReadUInt64(iter, &num_patterns));
223 
224   pattern_list->ClearPatterns();
225   for (uint64 i = 0; i < num_patterns; ++i) {
226     int valid_schemes;
227     CHECK(pickle.ReadInt(iter, &valid_schemes));
228 
229     std::string pattern_str;
230     CHECK(pickle.ReadString(iter, &pattern_str));
231 
232     URLPattern pattern(kValidUserScriptSchemes);
233     URLPattern::ParseResult result = pattern.Parse(pattern_str);
234     CHECK(URLPattern::PARSE_SUCCESS == result) <<
235         URLPattern::GetParseResultString(result) << " " << pattern_str.c_str();
236 
237     pattern.SetValidSchemes(valid_schemes);
238     pattern_list->AddPattern(pattern);
239   }
240 }
241 
UnpickleScripts(const::Pickle & pickle,PickleIterator * iter,FileList * scripts)242 void UserScript::UnpickleScripts(const ::Pickle& pickle, PickleIterator* iter,
243                                  FileList* scripts) {
244   uint64 num_files = 0;
245   CHECK(pickle.ReadUInt64(iter, &num_files));
246   scripts->clear();
247   for (uint64 i = 0; i < num_files; ++i) {
248     File file;
249     file.Unpickle(pickle, iter);
250     scripts->push_back(file);
251   }
252 }
253 
operator <(const UserScript & script1,const UserScript & script2)254 bool operator<(const UserScript& script1, const UserScript& script2) {
255   // The only kind of script that should be compared is the kind that has its
256   // IDs initialized to a meaningful value.
257   DCHECK(script1.id() != -1 && script2.id() != -1);
258   return script1.id() < script2.id();
259 }
260 
261 }  // namespace extensions
262