Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(162)

Side by Side Diff: chrome/browser/extensions/api/declarative_content/content_action.cc

Issue 344433003: Prepare declarativeContent API for new script injection feature. Added Javascript types and functio… (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Implement fixes from comments and add unit tests Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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"
(...skipping 11 matching lines...) Expand all
22 namespace extensions { 22 namespace extensions {
23 23
24 namespace keys = declarative_content_constants; 24 namespace keys = declarative_content_constants;
25 25
26 namespace { 26 namespace {
27 // Error messages. 27 // Error messages.
28 const char kInvalidInstanceTypeError[] = 28 const char kInvalidInstanceTypeError[] =
29 "An action has an invalid instanceType: %s"; 29 "An action has an invalid instanceType: %s";
30 const char kNoPageAction[] = 30 const char kNoPageAction[] =
31 "Can't use declarativeContent.ShowPageAction without a page action"; 31 "Can't use declarativeContent.ShowPageAction without a page action";
32 const char kMissingParameter[] = "Missing parameter is required: %s";
33 const char kInvalidTypeOfParameter[] = "Attribute '%s' has an invalid type. "
34 "Expected type: %s";
32 35
33 #define INPUT_FORMAT_VALIDATE(test) do { \ 36 #define INPUT_FORMAT_VALIDATE(test) do { \
34 if (!(test)) { \ 37 if (!(test)) { \
35 *bad_message = true; \ 38 *bad_message = true; \
36 return scoped_refptr<ContentAction>(NULL); \ 39 return scoped_refptr<ContentAction>(NULL); \
37 } \ 40 } \
38 } while (0) 41 } while (0)
39 42
40 // 43 //
41 // The following are concrete actions. 44 // The following are concrete actions.
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 ->GetExtensionById(extension_id, ExtensionRegistry::EVERYTHING); 90 ->GetExtensionById(extension_id, ExtensionRegistry::EVERYTHING);
88 if (!extension) 91 if (!extension)
89 return NULL; 92 return NULL;
90 return ExtensionActionManager::Get(profile)->GetPageAction(*extension); 93 return ExtensionActionManager::Get(profile)->GetPageAction(*extension);
91 } 94 }
92 virtual ~ShowPageAction() {} 95 virtual ~ShowPageAction() {}
93 96
94 DISALLOW_COPY_AND_ASSIGN(ShowPageAction); 97 DISALLOW_COPY_AND_ASSIGN(ShowPageAction);
95 }; 98 };
96 99
100 // Action that injects a content script.
101 class RequestContentScript : public ContentAction {
102 public:
103 RequestContentScript(const std::vector<std::string>& css_file_names,
104 const std::vector<std::string>& js_file_names,
105 const bool all_frames,
106 const bool match_about_blank)
107 : css_file_names_(css_file_names),
108 js_file_names_(js_file_names),
109 all_frames_(all_frames),
110 match_about_blank_(match_about_blank) {}
111
112 static scoped_refptr<ContentAction> Create(const Extension* extension,
113 const base::DictionaryValue* dict,
114 std::string* error,
115 bool* bad_message);
116
117 // Implementation of ContentAction:
118 virtual Type GetType() const OVERRIDE {
119 return ACTION_REQUEST_CONTENT_SCRIPT;
120 }
121
122 virtual void Apply(const std::string& extension_id,
123 const base::Time& extension_install_time,
124 ApplyInfo* apply_info) const OVERRIDE {
125 // TODO(markdittmer): Invoke UserScriptMaster declarative script loader:
126 // load new user script.
127 }
128
129 virtual void Revert(const std::string& extension_id,
130 const base::Time& extension_install_time,
131 ApplyInfo* apply_info) const OVERRIDE {
132 // TODO(markdittmer): Invoke UserScriptMaster declarative script loader:
133 // do not load user script if Apply() runs again on the same page.
134 }
135
136 private:
137 virtual ~RequestContentScript() {}
138
139 std::vector<std::string> css_file_names_;
140 std::vector<std::string> js_file_names_;
141 bool all_frames_;
142 bool match_about_blank_;
143
144 DISALLOW_COPY_AND_ASSIGN(RequestContentScript);
145 };
146
147 // Helper for getting JS collections into C++.
148 static bool AppendJSStringsToCPPStrings(const base::ListValue& append_strings,
149 std::vector<std::string>* append_to) {
150 for (base::ListValue::const_iterator it = append_strings.begin();
151 it != append_strings.end(); ++it) {
152 std::string value;
153 if ((*it)->GetAsString(&value)) {
154 append_to->push_back(value);
155 } else {
156 return false;
157 }
158 }
159
160 return true;
161 }
162
163 // static
164 scoped_refptr<ContentAction> RequestContentScript::Create(
165 const Extension* extension,
166 const base::DictionaryValue* dict,
167 std::string* error,
168 bool* bad_message) {
169 std::vector<std::string> css_file_names;
170 std::vector<std::string> js_file_names;
171 bool all_frames = false;
172 bool match_about_blank = false;
173 const base::ListValue* list_value;
174
175 if (!dict->HasKey(keys::kCss) && !dict->HasKey(keys::kJs)) {
176 *error = base::StringPrintf(kMissingParameter, "css or js");
177 *bad_message = true;
not at google - send to devlin 2014/07/16 16:51:14 FYI there's not much point setting both bad_messag
Mark Dittmer 2014/07/16 19:40:45 Done. I use error instead of bad_message for "has
178 return scoped_refptr<ContentAction>();
179 }
180
181 if (dict->HasKey(keys::kCss)) {
182 if (!dict->GetList(keys::kCss, &list_value) ||
183 !AppendJSStringsToCPPStrings(*list_value, &css_file_names)) {
184 *error = base::StringPrintf(kInvalidTypeOfParameter,
185 keys::kCss,
186 "Array of strings");
187 *bad_message = true;
188 return scoped_refptr<ContentAction>();
not at google - send to devlin 2014/07/16 16:51:14 indentation is off here, you should run "git cl fo
Mark Dittmer 2014/07/16 19:40:45 Done.
189 }
190 }
191
192 if (dict->HasKey(keys::kJs)) {
193 if (!dict->GetList(keys::kJs, &list_value) ||
194 !AppendJSStringsToCPPStrings(*list_value, &js_file_names)) {
195 *error = base::StringPrintf(kInvalidTypeOfParameter,
196 keys::kJs,
197 "Array of strings");
198 *bad_message = true;
199 return scoped_refptr<ContentAction>();
200 }
201 }
202
203 if (dict->HasKey(keys::kAllFrames) &&
204 !dict->GetBoolean(keys::kAllFrames, &all_frames)) {
205 *error = base::StringPrintf(kInvalidTypeOfParameter,
206 keys::kAllFrames,
207 "Boolean");
208 *bad_message = true;
209 return scoped_refptr<ContentAction>();
210 }
211
212 if (dict->HasKey(keys::kMatchAboutBlank) &&
213 !dict->GetBoolean(keys::kMatchAboutBlank, &match_about_blank)) {
214 *error = base::StringPrintf(kInvalidTypeOfParameter,
215 keys::kMatchAboutBlank,
216 "Boolean");
217 *bad_message = true;
218 return scoped_refptr<ContentAction>();
219 }
220
221 return scoped_refptr<ContentAction>(new RequestContentScript(
222 css_file_names,
223 js_file_names,
224 all_frames,
225 match_about_blank));
226 }
227
97 struct ContentActionFactory { 228 struct ContentActionFactory {
98 // Factory methods for ContentAction instances. |extension| is the extension 229 // Factory methods for ContentAction instances. |extension| is the extension
99 // for which the action is being created. |dict| contains the json dictionary 230 // for which the action is being created. |dict| contains the json dictionary
100 // that describes the action. |error| is used to return error messages in case 231 // that describes the action. |error| is used to return error messages in case
101 // the extension passed an action that was syntactically correct but 232 // the extension passed an action that was syntactically correct but
102 // semantically incorrect. |bad_message| is set to true in case |dict| does 233 // semantically incorrect. |bad_message| is set to true in case |dict| does
103 // not confirm to the validated JSON specification. 234 // not confirm to the validated JSON specification.
104 typedef scoped_refptr<ContentAction>(*FactoryMethod)( 235 typedef scoped_refptr<ContentAction>(*FactoryMethod)(
105 const Extension* /* extension */, 236 const Extension* /* extension */,
106 const base::DictionaryValue* /* dict */, 237 const base::DictionaryValue* /* dict */,
107 std::string* /* error */, 238 std::string* /* error */,
108 bool* /* bad_message */); 239 bool* /* bad_message */);
109 // Maps the name of a declarativeContent action type to the factory 240 // Maps the name of a declarativeContent action type to the factory
110 // function creating it. 241 // function creating it.
111 std::map<std::string, FactoryMethod> factory_methods; 242 std::map<std::string, FactoryMethod> factory_methods;
112 243
113 ContentActionFactory() { 244 ContentActionFactory() {
114 factory_methods[keys::kShowPageAction] = 245 factory_methods[keys::kShowPageAction] =
115 &ShowPageAction::Create; 246 &ShowPageAction::Create;
247 factory_methods[keys::kRequestContentScript] =
248 &RequestContentScript::Create;
116 } 249 }
117 }; 250 };
118 251
119 base::LazyInstance<ContentActionFactory>::Leaky 252 base::LazyInstance<ContentActionFactory>::Leaky
120 g_content_action_factory = LAZY_INSTANCE_INITIALIZER; 253 g_content_action_factory = LAZY_INSTANCE_INITIALIZER;
121 254
122 } // namespace 255 } // namespace
123 256
124 // 257 //
125 // ContentAction 258 // ContentAction
(...skipping 24 matching lines...) Expand all
150 factory_method_iter = factory.factory_methods.find(instance_type); 283 factory_method_iter = factory.factory_methods.find(instance_type);
151 if (factory_method_iter != factory.factory_methods.end()) 284 if (factory_method_iter != factory.factory_methods.end())
152 return (*factory_method_iter->second)( 285 return (*factory_method_iter->second)(
153 extension, action_dict, error, bad_message); 286 extension, action_dict, error, bad_message);
154 287
155 *error = base::StringPrintf(kInvalidInstanceTypeError, instance_type.c_str()); 288 *error = base::StringPrintf(kInvalidInstanceTypeError, instance_type.c_str());
156 return scoped_refptr<ContentAction>(); 289 return scoped_refptr<ContentAction>();
157 } 290 }
158 291
159 } // namespace extensions 292 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698