Chromium Code Reviews| 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" |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |