user_script.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  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. #ifndef EXTENSIONS_COMMON_USER_SCRIPT_H_
  5. #define EXTENSIONS_COMMON_USER_SCRIPT_H_
  6. #include <memory>
  7. #include <string>
  8. #include <vector>
  9. #include "base/files/file_path.h"
  10. #include "base/strings/string_piece.h"
  11. #include "extensions/common/mojom/execution_world.mojom-shared.h"
  12. #include "extensions/common/mojom/host_id.mojom.h"
  13. #include "extensions/common/mojom/run_location.mojom-shared.h"
  14. #include "extensions/common/script_constants.h"
  15. #include "extensions/common/url_pattern.h"
  16. #include "extensions/common/url_pattern_set.h"
  17. #include "url/gurl.h"
  18. namespace base {
  19. class Pickle;
  20. class PickleIterator;
  21. }
  22. namespace extensions {
  23. // Represents a user script, either a standalone one, or one that is part of an
  24. // extension.
  25. class UserScript {
  26. public:
  27. // The file extension for standalone user scripts.
  28. static const char kFileExtension[];
  29. // The prefix for all generated user script IDs (i.e. the ID is not provided
  30. // by the extension).
  31. static const char kGeneratedIDPrefix;
  32. static std::string GenerateUserScriptID();
  33. // Check if a URL should be treated as a user script and converted to an
  34. // extension.
  35. static bool IsURLUserScript(const GURL& url, const std::string& mime_type);
  36. // Get the valid user script schemes for the current process. If
  37. // `can_execute_script_everywhere` is true, this will return ALL_SCHEMES.
  38. static int ValidUserScriptSchemes(bool can_execute_script_everywhere = false);
  39. // Returns if a user script's ID is generated.
  40. static bool IsIDGenerated(const std::string& id);
  41. // Holds script file info.
  42. class File {
  43. public:
  44. File(const base::FilePath& extension_root,
  45. const base::FilePath& relative_path,
  46. const GURL& url);
  47. File();
  48. File(const File& other);
  49. ~File();
  50. const base::FilePath& extension_root() const { return extension_root_; }
  51. const base::FilePath& relative_path() const { return relative_path_; }
  52. const GURL& url() const { return url_; }
  53. void set_url(const GURL& url) { url_ = url; }
  54. // If external_content_ is set returns it as content otherwise it returns
  55. // content_
  56. const base::StringPiece GetContent() const {
  57. if (external_content_.data())
  58. return external_content_;
  59. else
  60. return content_;
  61. }
  62. void set_external_content(const base::StringPiece& content) {
  63. external_content_ = content;
  64. }
  65. void set_content(const base::StringPiece& content) {
  66. content_.assign(content.begin(), content.end());
  67. }
  68. // Serialization support. The content and FilePath members will not be
  69. // serialized!
  70. void Pickle(base::Pickle* pickle) const;
  71. void Unpickle(const base::Pickle& pickle, base::PickleIterator* iter);
  72. private:
  73. // Where the script file lives on the disk. We keep the path split so that
  74. // it can be localized at will.
  75. base::FilePath extension_root_;
  76. base::FilePath relative_path_;
  77. // The url to this script file.
  78. GURL url_;
  79. // The script content. It can be set to either loaded_content_ or
  80. // externally allocated string.
  81. base::StringPiece external_content_;
  82. // Set when the content is loaded by LoadContent
  83. std::string content_;
  84. };
  85. using FileList = std::vector<std::unique_ptr<File>>;
  86. // Type of a API consumer instance that user scripts will be injected on.
  87. enum ConsumerInstanceType { TAB, WEBVIEW };
  88. // Constructor. Default the run location to document end, which is like
  89. // Greasemonkey and probably more useful for typical scripts.
  90. UserScript();
  91. UserScript(const UserScript&) = delete;
  92. UserScript& operator=(const UserScript&) = delete;
  93. ~UserScript();
  94. // Performs a copy of all fields except file contents.
  95. static std::unique_ptr<UserScript> CopyMetadataFrom(const UserScript& other);
  96. const std::string& name_space() const { return name_space_; }
  97. void set_name_space(const std::string& name_space) {
  98. name_space_ = name_space;
  99. }
  100. const std::string& name() const { return name_; }
  101. void set_name(const std::string& name) { name_ = name; }
  102. const std::string& version() const { return version_; }
  103. void set_version(const std::string& version) {
  104. version_ = version;
  105. }
  106. const std::string& description() const { return description_; }
  107. void set_description(const std::string& description) {
  108. description_ = description;
  109. }
  110. // The place in the document to run the script.
  111. mojom::RunLocation run_location() const { return run_location_; }
  112. void set_run_location(mojom::RunLocation location) {
  113. run_location_ = location;
  114. }
  115. // Whether to emulate greasemonkey when running this script.
  116. bool emulate_greasemonkey() const { return emulate_greasemonkey_; }
  117. void set_emulate_greasemonkey(bool val) { emulate_greasemonkey_ = val; }
  118. // Whether to match all frames, or only the top one.
  119. bool match_all_frames() const { return match_all_frames_; }
  120. void set_match_all_frames(bool val) { match_all_frames_ = val; }
  121. // Whether to match the origin as a fallback if the URL cannot be used
  122. // directly.
  123. MatchOriginAsFallbackBehavior match_origin_as_fallback() const {
  124. return match_origin_as_fallback_;
  125. }
  126. void set_match_origin_as_fallback(MatchOriginAsFallbackBehavior val) {
  127. match_origin_as_fallback_ = val;
  128. }
  129. // The globs, if any, that determine which pages this script runs against.
  130. // These are only used with "standalone" Greasemonkey-like user scripts.
  131. const std::vector<std::string>& globs() const { return globs_; }
  132. void add_glob(const std::string& glob) { globs_.push_back(glob); }
  133. void clear_globs() { globs_.clear(); }
  134. const std::vector<std::string>& exclude_globs() const {
  135. return exclude_globs_;
  136. }
  137. void add_exclude_glob(const std::string& glob) {
  138. exclude_globs_.push_back(glob);
  139. }
  140. void clear_exclude_globs() { exclude_globs_.clear(); }
  141. // The URLPatterns, if any, that determine which pages this script runs
  142. // against.
  143. const URLPatternSet& url_patterns() const { return url_set_; }
  144. void add_url_pattern(const URLPattern& pattern);
  145. const URLPatternSet& exclude_url_patterns() const {
  146. return exclude_url_set_;
  147. }
  148. void add_exclude_url_pattern(const URLPattern& pattern);
  149. // List of js scripts for this user script
  150. FileList& js_scripts() { return js_scripts_; }
  151. const FileList& js_scripts() const { return js_scripts_; }
  152. // List of css scripts for this user script
  153. FileList& css_scripts() { return css_scripts_; }
  154. const FileList& css_scripts() const { return css_scripts_; }
  155. const std::string& extension_id() const { return host_id_.id; }
  156. const mojom::HostID& host_id() const { return host_id_; }
  157. void set_host_id(const mojom::HostID& host_id) { host_id_ = host_id; }
  158. const ConsumerInstanceType& consumer_instance_type() const {
  159. return consumer_instance_type_;
  160. }
  161. void set_consumer_instance_type(
  162. const ConsumerInstanceType& consumer_instance_type) {
  163. consumer_instance_type_ = consumer_instance_type;
  164. }
  165. const std::string& id() const { return user_script_id_; }
  166. void set_id(std::string id) { user_script_id_ = std::move(id); }
  167. // TODO(lazyboy): Incognito information is extension specific, it doesn't
  168. // belong here. We should be able to determine this in the renderer/ where it
  169. // is used.
  170. bool is_incognito_enabled() const { return incognito_enabled_; }
  171. void set_incognito_enabled(bool enabled) { incognito_enabled_ = enabled; }
  172. mojom::ExecutionWorld execution_world() const { return execution_world_; }
  173. void set_execution_world(mojom::ExecutionWorld world) {
  174. execution_world_ = world;
  175. }
  176. // Returns true if the script should be applied to the specified URL, false
  177. // otherwise.
  178. bool MatchesURL(const GURL& url) const;
  179. // Returns true if the script should be applied to the given
  180. // |effective_document_url|. It is the caller's responsibility to calculate
  181. // |effective_document_url| based on match_origin_as_fallback().
  182. bool MatchesDocument(const GURL& effective_document_url,
  183. bool is_subframe) const;
  184. // Serializes the UserScript into a pickle. The content of the scripts and
  185. // paths to UserScript::Files will not be serialized!
  186. void Pickle(base::Pickle* pickle) const;
  187. // Deserializes the script from a pickle. Note that this always succeeds
  188. // because presumably we were the one that pickled it, and we did it
  189. // correctly.
  190. void Unpickle(const base::Pickle& pickle, base::PickleIterator* iter);
  191. // Returns if this script's ID is generated.
  192. bool IsIDGenerated() const;
  193. private:
  194. // base::Pickle helper functions used to pickle the individual types of
  195. // components.
  196. void PickleGlobs(base::Pickle* pickle,
  197. const std::vector<std::string>& globs) const;
  198. void PickleHostID(base::Pickle* pickle, const mojom::HostID& host_id) const;
  199. void PickleURLPatternSet(base::Pickle* pickle,
  200. const URLPatternSet& pattern_list) const;
  201. void PickleScripts(base::Pickle* pickle, const FileList& scripts) const;
  202. // Unpickle helper functions used to unpickle individual types of components.
  203. void UnpickleGlobs(const base::Pickle& pickle,
  204. base::PickleIterator* iter,
  205. std::vector<std::string>* globs);
  206. void UnpickleHostID(const base::Pickle& pickle,
  207. base::PickleIterator* iter,
  208. mojom::HostID* host_id);
  209. void UnpickleURLPatternSet(const base::Pickle& pickle,
  210. base::PickleIterator* iter,
  211. URLPatternSet* pattern_list);
  212. void UnpickleScripts(const base::Pickle& pickle,
  213. base::PickleIterator* iter,
  214. FileList* scripts);
  215. // The location to run the script inside the document.
  216. mojom::RunLocation run_location_ = mojom::RunLocation::kDocumentIdle;
  217. // The namespace of the script. This is used by Greasemonkey in the same way
  218. // as XML namespaces. Only used when parsing Greasemonkey-style scripts.
  219. std::string name_space_;
  220. // The script's name. Only used when parsing Greasemonkey-style scripts.
  221. std::string name_;
  222. // A longer description. Only used when parsing Greasemonkey-style scripts.
  223. std::string description_;
  224. // A version number of the script. Only used when parsing Greasemonkey-style
  225. // scripts.
  226. std::string version_;
  227. // Greasemonkey-style globs that determine pages to inject the script into.
  228. // These are only used with standalone scripts.
  229. std::vector<std::string> globs_;
  230. std::vector<std::string> exclude_globs_;
  231. // URLPatterns that determine pages to inject the script into. These are
  232. // only used with scripts that are part of extensions.
  233. URLPatternSet url_set_;
  234. URLPatternSet exclude_url_set_;
  235. // List of js scripts defined in content_scripts
  236. FileList js_scripts_;
  237. // List of css scripts defined in content_scripts
  238. FileList css_scripts_;
  239. // The ID of the host this script is a part of. The |ID| of the
  240. // |host_id| can be empty if the script is a "standlone" user script.
  241. mojom::HostID host_id_;
  242. // The type of the consumer instance that the script will be injected.
  243. ConsumerInstanceType consumer_instance_type_ = TAB;
  244. // The globally-unique id associated with this user script. An empty string
  245. // indicates an invalid id.
  246. std::string user_script_id_;
  247. // Whether we should try to emulate Greasemonkey's APIs when running this
  248. // script.
  249. bool emulate_greasemonkey_ = false;
  250. // Whether the user script should run in all frames, or only just the top one.
  251. bool match_all_frames_ = false;
  252. // Whether the user script should run in frames whose initiator / precursor
  253. // origin matches a match pattern, if an appropriate URL cannot be found for
  254. // the frame for matching purposes, such as in the case of about:, data:, and
  255. // other schemes.
  256. MatchOriginAsFallbackBehavior match_origin_as_fallback_ =
  257. MatchOriginAsFallbackBehavior::kNever;
  258. // True if the script should be injected into an incognito tab.
  259. bool incognito_enabled_ = false;
  260. mojom::ExecutionWorld execution_world_ = mojom::ExecutionWorld::kIsolated;
  261. };
  262. using UserScriptList = std::vector<std::unique_ptr<UserScript>>;
  263. } // namespace extensions
  264. #endif // EXTENSIONS_COMMON_USER_SCRIPT_H_