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