OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/api/declarative_content/content_action.h" | 5 #include "chrome/browser/extensions/api/declarative_content/content_action.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 | 8 |
9 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
11 #include "base/values.h" | 11 #include "base/values.h" |
12 #include "chrome/browser/extensions/api/declarative_content/content_constants.h" | 12 #include "chrome/browser/extensions/api/declarative_content/content_constants.h" |
13 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h" | 13 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h" |
14 #include "chrome/browser/extensions/declarative_user_script_master.h" | |
14 #include "chrome/browser/extensions/extension_action.h" | 15 #include "chrome/browser/extensions/extension_action.h" |
15 #include "chrome/browser/extensions/extension_action_manager.h" | 16 #include "chrome/browser/extensions/extension_action_manager.h" |
16 #include "chrome/browser/extensions/extension_tab_util.h" | 17 #include "chrome/browser/extensions/extension_tab_util.h" |
17 #include "chrome/browser/profiles/profile.h" | 18 #include "chrome/browser/profiles/profile.h" |
19 #include "chrome/browser/sessions/session_tab_helper.h" | |
Jeffrey Yasskin
2014/08/22 01:12:24
Double-check which headers you still need.
Mark Dittmer
2014/08/22 19:59:19
Done.
| |
20 #include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h" | |
18 #include "content/public/browser/invalidate_type.h" | 21 #include "content/public/browser/invalidate_type.h" |
22 #include "content/public/browser/render_process_host.h" | |
23 #include "content/public/browser/render_view_host.h" | |
19 #include "content/public/browser/web_contents.h" | 24 #include "content/public/browser/web_contents.h" |
20 #include "extensions/browser/extension_registry.h" | 25 #include "extensions/browser/extension_registry.h" |
26 #include "extensions/browser/extension_system.h" | |
21 #include "extensions/common/extension.h" | 27 #include "extensions/common/extension.h" |
28 #include "extensions/common/extension_messages.h" | |
22 | 29 |
23 namespace extensions { | 30 namespace extensions { |
24 | 31 |
25 namespace keys = declarative_content_constants; | 32 namespace keys = declarative_content_constants; |
26 | 33 |
27 namespace { | 34 namespace { |
28 // Error messages. | 35 // Error messages. |
29 const char kInvalidInstanceTypeError[] = | 36 const char kInvalidInstanceTypeError[] = |
30 "An action has an invalid instanceType: %s"; | 37 "An action has an invalid instanceType: %s"; |
31 const char kNoPageAction[] = | 38 const char kNoPageAction[] = |
32 "Can't use declarativeContent.ShowPageAction without a page action"; | 39 "Can't use declarativeContent.ShowPageAction without a page action"; |
33 const char kMissingParameter[] = "Missing parameter is required: %s"; | 40 const char kMissingParameter[] = "Missing parameter is required: %s"; |
34 | 41 |
35 #define INPUT_FORMAT_VALIDATE(test) do { \ | 42 #define INPUT_FORMAT_VALIDATE(test) do { \ |
36 if (!(test)) { \ | 43 if (!(test)) { \ |
37 *bad_message = true; \ | 44 *bad_message = true; \ |
38 return scoped_refptr<ContentAction>(NULL); \ | 45 return scoped_refptr<ContentAction>(NULL); \ |
39 } \ | 46 } \ |
40 } while (0) | 47 } while (0) |
41 | 48 |
42 // | 49 // |
43 // The following are concrete actions. | 50 // The following are concrete actions. |
44 // | 51 // |
45 | 52 |
46 // Action that instructs to show an extension's page action. | 53 // Action that instructs to show an extension's page action. |
47 class ShowPageAction : public ContentAction { | 54 class ShowPageAction : public ContentAction { |
48 public: | 55 public: |
49 ShowPageAction() {} | 56 ShowPageAction() {} |
50 | 57 |
51 static scoped_refptr<ContentAction> Create(const Extension* extension, | 58 static scoped_refptr<ContentAction> Create(Profile* profile, |
59 const Extension* extension, | |
52 const base::DictionaryValue* dict, | 60 const base::DictionaryValue* dict, |
53 std::string* error, | 61 std::string* error, |
54 bool* bad_message) { | 62 bool* bad_message) { |
55 // We can't show a page action if the extension doesn't have one. | 63 // We can't show a page action if the extension doesn't have one. |
56 if (ActionInfo::GetPageActionInfo(extension) == NULL) { | 64 if (ActionInfo::GetPageActionInfo(extension) == NULL) { |
57 *error = kNoPageAction; | 65 *error = kNoPageAction; |
58 return scoped_refptr<ContentAction>(); | 66 return scoped_refptr<ContentAction>(); |
59 } | 67 } |
60 return scoped_refptr<ContentAction>(new ShowPageAction); | 68 return scoped_refptr<ContentAction>(new ShowPageAction); |
61 } | 69 } |
(...skipping 15 matching lines...) Expand all Loading... | |
77 virtual void Revert(const std::string& extension_id, | 85 virtual void Revert(const std::string& extension_id, |
78 const base::Time& extension_install_time, | 86 const base::Time& extension_install_time, |
79 ApplyInfo* apply_info) const OVERRIDE { | 87 ApplyInfo* apply_info) const OVERRIDE { |
80 if (ExtensionAction* action = | 88 if (ExtensionAction* action = |
81 GetPageAction(apply_info->profile, extension_id)) { | 89 GetPageAction(apply_info->profile, extension_id)) { |
82 action->UndoDeclarativeShow(ExtensionTabUtil::GetTabId(apply_info->tab)); | 90 action->UndoDeclarativeShow(ExtensionTabUtil::GetTabId(apply_info->tab)); |
83 ExtensionActionAPI::Get(apply_info->profile)->NotifyChange( | 91 ExtensionActionAPI::Get(apply_info->profile)->NotifyChange( |
84 action, apply_info->tab, apply_info->profile); | 92 action, apply_info->tab, apply_info->profile); |
85 } | 93 } |
86 } | 94 } |
95 virtual void Reapply(const std::string& extension_id, | |
96 const base::Time& extension_install_time, | |
97 ApplyInfo* apply_info) const OVERRIDE { | |
98 } | |
87 | 99 |
88 private: | 100 private: |
89 static ExtensionAction* GetPageAction(Profile* profile, | 101 static ExtensionAction* GetPageAction(Profile* profile, |
90 const std::string& extension_id) { | 102 const std::string& extension_id) { |
91 const Extension* extension = | 103 const Extension* extension = |
92 ExtensionRegistry::Get(profile) | 104 ExtensionRegistry::Get(profile) |
93 ->GetExtensionById(extension_id, ExtensionRegistry::EVERYTHING); | 105 ->GetExtensionById(extension_id, ExtensionRegistry::EVERYTHING); |
94 if (!extension) | 106 if (!extension) |
95 return NULL; | 107 return NULL; |
96 return ExtensionActionManager::Get(profile)->GetPageAction(*extension); | 108 return ExtensionActionManager::Get(profile)->GetPageAction(*extension); |
97 } | 109 } |
98 virtual ~ShowPageAction() {} | 110 virtual ~ShowPageAction() {} |
99 | 111 |
100 DISALLOW_COPY_AND_ASSIGN(ShowPageAction); | 112 DISALLOW_COPY_AND_ASSIGN(ShowPageAction); |
101 }; | 113 }; |
102 | 114 |
103 // Action that injects a content script. | 115 // Action that injects a content script. |
104 class RequestContentScript : public ContentAction { | 116 class RequestContentScript : public ContentAction { |
105 public: | 117 public: |
106 RequestContentScript(const std::vector<std::string>& css_file_names, | 118 static scoped_refptr<ContentAction> Create(Profile* profile, |
107 const std::vector<std::string>& js_file_names, | 119 const Extension* extension, |
108 bool all_frames, | |
109 bool match_about_blank) | |
110 : css_file_names_(css_file_names), | |
111 js_file_names_(js_file_names), | |
112 all_frames_(all_frames), | |
113 match_about_blank_(match_about_blank) {} | |
114 | |
115 static scoped_refptr<ContentAction> Create(const Extension* extension, | |
116 const base::DictionaryValue* dict, | 120 const base::DictionaryValue* dict, |
117 std::string* error, | 121 std::string* error, |
118 bool* bad_message); | 122 bool* bad_message); |
119 | 123 |
124 RequestContentScript(Profile* profile, | |
Jeffrey Yasskin
2014/08/22 01:12:24
Try not to reorder blocks unnecessarily.
Mark Dittmer
2014/08/22 19:59:18
Done.
| |
125 const Extension* extension, | |
126 const std::vector<std::string>& css_file_names, | |
127 const std::vector<std::string>& js_file_names, | |
128 bool all_frames, | |
129 bool match_about_blank); | |
130 | |
120 // Implementation of ContentAction: | 131 // Implementation of ContentAction: |
121 virtual Type GetType() const OVERRIDE { | 132 virtual Type GetType() const OVERRIDE { |
122 return ACTION_REQUEST_CONTENT_SCRIPT; | 133 return ACTION_REQUEST_CONTENT_SCRIPT; |
123 } | 134 } |
124 | 135 |
125 virtual void Apply(const std::string& extension_id, | 136 virtual void Apply(const std::string& extension_id, |
126 const base::Time& extension_install_time, | 137 const base::Time& extension_install_time, |
127 ApplyInfo* apply_info) const OVERRIDE { | 138 ApplyInfo* apply_info) const OVERRIDE { |
128 // TODO(markdittmer): Invoke UserScriptMaster declarative script loader: | 139 InstructRenderProcessToInject(apply_info->tab, extension_id); |
129 // load new user script. | |
130 } | 140 } |
131 | 141 |
132 virtual void Reapply(const std::string& extension_id, | 142 virtual void Reapply(const std::string& extension_id, |
133 const base::Time& extension_install_time, | 143 const base::Time& extension_install_time, |
134 ApplyInfo* apply_info) const OVERRIDE { | 144 ApplyInfo* apply_info) const OVERRIDE { |
135 // TODO(markdittmer): Invoke UserScriptMaster declarative script loader: | 145 // TODO(markdittmer): Invoke UserScriptMaster declarative script loader: |
136 // load new user script. | 146 // load new user script. |
137 } | 147 } |
138 | 148 |
139 virtual void Revert(const std::string& extension_id, | 149 virtual void Revert(const std::string& extension_id, |
140 const base::Time& extension_install_time, | 150 const base::Time& extension_install_time, |
141 ApplyInfo* apply_info) const OVERRIDE { | 151 ApplyInfo* apply_info) const OVERRIDE { |
142 // TODO(markdittmer): Invoke UserScriptMaster declarative script loader: | 152 } |
143 // do not load user script if Apply() runs again on the same page. | 153 virtual void Reapply(const std::string& extension_id, |
154 const base::Time& extension_install_time, | |
155 ApplyInfo* apply_info) const OVERRIDE { | |
156 InstructRenderProcessToInject(apply_info->tab, extension_id); | |
144 } | 157 } |
145 | 158 |
146 private: | 159 private: |
147 virtual ~RequestContentScript() {} | 160 virtual ~RequestContentScript() { |
161 DCHECK(master_); | |
162 master_->RemoveScript(script_); | |
163 } | |
148 | 164 |
149 std::vector<std::string> css_file_names_; | 165 void InstructRenderProcessToInject(content::WebContents* contents, |
150 std::vector<std::string> js_file_names_; | 166 const std::string& extension_id) const; |
151 bool all_frames_; | 167 |
152 bool match_about_blank_; | 168 UserScript script_; |
169 DeclarativeUserScriptMaster* master_; | |
153 | 170 |
154 DISALLOW_COPY_AND_ASSIGN(RequestContentScript); | 171 DISALLOW_COPY_AND_ASSIGN(RequestContentScript); |
155 }; | 172 }; |
156 | 173 |
157 // Helper for getting JS collections into C++. | 174 // Helper for getting JS collections into C++. |
158 static bool AppendJSStringsToCPPStrings(const base::ListValue& append_strings, | 175 static bool AppendJSStringsToCPPStrings(const base::ListValue& append_strings, |
159 std::vector<std::string>* append_to) { | 176 std::vector<std::string>* append_to) { |
160 for (base::ListValue::const_iterator it = append_strings.begin(); | 177 for (base::ListValue::const_iterator it = append_strings.begin(); |
161 it != append_strings.end(); | 178 it != append_strings.end(); |
162 ++it) { | 179 ++it) { |
163 std::string value; | 180 std::string value; |
164 if ((*it)->GetAsString(&value)) { | 181 if ((*it)->GetAsString(&value)) { |
165 append_to->push_back(value); | 182 append_to->push_back(value); |
166 } else { | 183 } else { |
167 return false; | 184 return false; |
168 } | 185 } |
169 } | 186 } |
170 | 187 |
171 return true; | 188 return true; |
172 } | 189 } |
173 | 190 |
174 // static | 191 // static |
175 scoped_refptr<ContentAction> RequestContentScript::Create( | 192 scoped_refptr<ContentAction> RequestContentScript::Create( |
193 Profile* profile, | |
176 const Extension* extension, | 194 const Extension* extension, |
177 const base::DictionaryValue* dict, | 195 const base::DictionaryValue* dict, |
178 std::string* error, | 196 std::string* error, |
179 bool* bad_message) { | 197 bool* bad_message) { |
180 std::vector<std::string> css_file_names; | 198 std::vector<std::string> css_file_names; |
181 std::vector<std::string> js_file_names; | 199 std::vector<std::string> js_file_names; |
182 bool all_frames = false; | 200 bool all_frames = false; |
183 bool match_about_blank = false; | 201 bool match_about_blank = false; |
184 const base::ListValue* list_value; | 202 const base::ListValue* list_value; |
185 | 203 |
(...skipping 13 matching lines...) Expand all Loading... | |
199 } | 217 } |
200 if (dict->HasKey(keys::kAllFrames)) { | 218 if (dict->HasKey(keys::kAllFrames)) { |
201 INPUT_FORMAT_VALIDATE(dict->GetBoolean(keys::kAllFrames, &all_frames)); | 219 INPUT_FORMAT_VALIDATE(dict->GetBoolean(keys::kAllFrames, &all_frames)); |
202 } | 220 } |
203 if (dict->HasKey(keys::kMatchAboutBlank)) { | 221 if (dict->HasKey(keys::kMatchAboutBlank)) { |
204 INPUT_FORMAT_VALIDATE( | 222 INPUT_FORMAT_VALIDATE( |
205 dict->GetBoolean(keys::kMatchAboutBlank, &match_about_blank)); | 223 dict->GetBoolean(keys::kMatchAboutBlank, &match_about_blank)); |
206 } | 224 } |
207 | 225 |
208 return scoped_refptr<ContentAction>(new RequestContentScript( | 226 return scoped_refptr<ContentAction>(new RequestContentScript( |
209 css_file_names, js_file_names, all_frames, match_about_blank)); | 227 profile, |
228 extension, | |
229 css_file_names, | |
230 js_file_names, | |
231 all_frames, | |
232 match_about_blank)); | |
233 } | |
234 | |
235 RequestContentScript::RequestContentScript( | |
236 Profile* profile, | |
237 const Extension* extension, | |
238 const std::vector<std::string>& css_file_names, | |
239 const std::vector<std::string>& js_file_names, | |
240 bool all_frames, | |
241 bool match_about_blank) { | |
242 script_.set_id(ContentScriptsHandler::GetNextUserScriptID()); | |
243 script_.set_extension_id(extension->id()); | |
244 script_.set_run_location(UserScript::BROWSER_DRIVEN); | |
245 script_.set_match_all_frames(all_frames); | |
246 script_.set_match_about_blank(match_about_blank); | |
247 for (std::vector<std::string>::const_iterator it = css_file_names.begin(); | |
248 it != css_file_names.end(); ++it) { | |
249 GURL url = extension->GetResourceURL(*it); | |
250 ExtensionResource resource = extension->GetResource(*it); | |
251 script_.css_scripts().push_back(UserScript::File( | |
252 resource.extension_root(), resource.relative_path(), url)); | |
253 } | |
254 for (std::vector<std::string>::const_iterator it = js_file_names.begin(); | |
255 it != js_file_names.end(); ++it) { | |
256 GURL url = extension->GetResourceURL(*it); | |
257 ExtensionResource resource = extension->GetResource(*it); | |
258 script_.js_scripts().push_back(UserScript::File( | |
259 resource.extension_root(), resource.relative_path(), url)); | |
260 } | |
261 | |
262 master_ = | |
263 ExtensionSystem::Get(profile)->GetDeclarativeUserScriptMasterByExtension( | |
Jeffrey Yasskin
2014/08/22 01:12:24
Can you point to the code that shows that master_
Devlin
2014/08/22 19:25:45
Jumping in, since Mark was chatting with me about
| |
264 extension->id()); | |
265 DCHECK(master_); | |
266 master_->AddScript(script_); | |
267 } | |
268 | |
269 void RequestContentScript::InstructRenderProcessToInject( | |
270 content::WebContents* contents, | |
271 const std::string& extension_id) const { | |
272 // TODO(markdittmer): Send ExtensionMsg to renderer. | |
210 } | 273 } |
211 | 274 |
212 struct ContentActionFactory { | 275 struct ContentActionFactory { |
213 // Factory methods for ContentAction instances. |extension| is the extension | 276 // Factory methods for ContentAction instances. |extension| is the extension |
214 // for which the action is being created. |dict| contains the json dictionary | 277 // for which the action is being created. |dict| contains the json dictionary |
215 // that describes the action. |error| is used to return error messages in case | 278 // that describes the action. |error| is used to return error messages in case |
216 // the extension passed an action that was syntactically correct but | 279 // the extension passed an action that was syntactically correct but |
217 // semantically incorrect. |bad_message| is set to true in case |dict| does | 280 // semantically incorrect. |bad_message| is set to true in case |dict| does |
218 // not confirm to the validated JSON specification. | 281 // not confirm to the validated JSON specification. |
219 typedef scoped_refptr<ContentAction>(*FactoryMethod)( | 282 typedef scoped_refptr<ContentAction>(*FactoryMethod)( |
283 Profile* /* profile */, | |
220 const Extension* /* extension */, | 284 const Extension* /* extension */, |
221 const base::DictionaryValue* /* dict */, | 285 const base::DictionaryValue* /* dict */, |
222 std::string* /* error */, | 286 std::string* /* error */, |
223 bool* /* bad_message */); | 287 bool* /* bad_message */); |
224 // Maps the name of a declarativeContent action type to the factory | 288 // Maps the name of a declarativeContent action type to the factory |
225 // function creating it. | 289 // function creating it. |
226 std::map<std::string, FactoryMethod> factory_methods; | 290 std::map<std::string, FactoryMethod> factory_methods; |
227 | 291 |
228 ContentActionFactory() { | 292 ContentActionFactory() { |
229 factory_methods[keys::kShowPageAction] = | 293 factory_methods[keys::kShowPageAction] = |
(...skipping 11 matching lines...) Expand all Loading... | |
241 // | 305 // |
242 // ContentAction | 306 // ContentAction |
243 // | 307 // |
244 | 308 |
245 ContentAction::ContentAction() {} | 309 ContentAction::ContentAction() {} |
246 | 310 |
247 ContentAction::~ContentAction() {} | 311 ContentAction::~ContentAction() {} |
248 | 312 |
249 // static | 313 // static |
250 scoped_refptr<ContentAction> ContentAction::Create( | 314 scoped_refptr<ContentAction> ContentAction::Create( |
315 Profile* profile, | |
251 const Extension* extension, | 316 const Extension* extension, |
252 const base::Value& json_action, | 317 const base::Value& json_action, |
253 std::string* error, | 318 std::string* error, |
254 bool* bad_message) { | 319 bool* bad_message) { |
255 *error = ""; | 320 *error = ""; |
256 *bad_message = false; | 321 *bad_message = false; |
257 | 322 |
258 const base::DictionaryValue* action_dict = NULL; | 323 const base::DictionaryValue* action_dict = NULL; |
259 INPUT_FORMAT_VALIDATE(json_action.GetAsDictionary(&action_dict)); | 324 INPUT_FORMAT_VALIDATE(json_action.GetAsDictionary(&action_dict)); |
260 | 325 |
261 std::string instance_type; | 326 std::string instance_type; |
262 INPUT_FORMAT_VALIDATE( | 327 INPUT_FORMAT_VALIDATE( |
263 action_dict->GetString(keys::kInstanceType, &instance_type)); | 328 action_dict->GetString(keys::kInstanceType, &instance_type)); |
264 | 329 |
265 ContentActionFactory& factory = g_content_action_factory.Get(); | 330 ContentActionFactory& factory = g_content_action_factory.Get(); |
266 std::map<std::string, ContentActionFactory::FactoryMethod>::iterator | 331 std::map<std::string, ContentActionFactory::FactoryMethod>::iterator |
267 factory_method_iter = factory.factory_methods.find(instance_type); | 332 factory_method_iter = factory.factory_methods.find(instance_type); |
268 if (factory_method_iter != factory.factory_methods.end()) | 333 if (factory_method_iter != factory.factory_methods.end()) |
269 return (*factory_method_iter->second)( | 334 return (*factory_method_iter->second)( |
270 extension, action_dict, error, bad_message); | 335 profile, extension, action_dict, error, bad_message); |
271 | 336 |
272 *error = base::StringPrintf(kInvalidInstanceTypeError, instance_type.c_str()); | 337 *error = base::StringPrintf(kInvalidInstanceTypeError, instance_type.c_str()); |
273 return scoped_refptr<ContentAction>(); | 338 return scoped_refptr<ContentAction>(); |
274 } | 339 } |
275 | 340 |
276 } // namespace extensions | 341 } // namespace extensions |
OLD | NEW |