| 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" |
| 18 #include "content/public/browser/invalidate_type.h" | 19 #include "content/public/browser/invalidate_type.h" |
| 19 #include "content/public/browser/web_contents.h" | 20 #include "content/public/browser/web_contents.h" |
| 20 #include "extensions/browser/extension_registry.h" | 21 #include "extensions/browser/extension_registry.h" |
| 22 #include "extensions/browser/extension_system.h" |
| 21 #include "extensions/common/extension.h" | 23 #include "extensions/common/extension.h" |
| 22 | 24 |
| 23 namespace extensions { | 25 namespace extensions { |
| 24 | 26 |
| 25 namespace keys = declarative_content_constants; | 27 namespace keys = declarative_content_constants; |
| 26 | 28 |
| 27 namespace { | 29 namespace { |
| 28 // Error messages. | 30 // Error messages. |
| 29 const char kInvalidInstanceTypeError[] = | 31 const char kInvalidInstanceTypeError[] = |
| 30 "An action has an invalid instanceType: %s"; | 32 "An action has an invalid instanceType: %s"; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 41 | 43 |
| 42 // | 44 // |
| 43 // The following are concrete actions. | 45 // The following are concrete actions. |
| 44 // | 46 // |
| 45 | 47 |
| 46 // Action that instructs to show an extension's page action. | 48 // Action that instructs to show an extension's page action. |
| 47 class ShowPageAction : public ContentAction { | 49 class ShowPageAction : public ContentAction { |
| 48 public: | 50 public: |
| 49 ShowPageAction() {} | 51 ShowPageAction() {} |
| 50 | 52 |
| 51 static scoped_refptr<ContentAction> Create(const Extension* extension, | 53 static scoped_refptr<ContentAction> Create( |
| 52 const base::DictionaryValue* dict, | 54 content::BrowserContext* browser_context, |
| 53 std::string* error, | 55 const Extension* extension, |
| 54 bool* bad_message) { | 56 const base::DictionaryValue* dict, |
| 57 std::string* error, |
| 58 bool* bad_message) { |
| 55 // We can't show a page action if the extension doesn't have one. | 59 // We can't show a page action if the extension doesn't have one. |
| 56 if (ActionInfo::GetPageActionInfo(extension) == NULL) { | 60 if (ActionInfo::GetPageActionInfo(extension) == NULL) { |
| 57 *error = kNoPageAction; | 61 *error = kNoPageAction; |
| 58 return scoped_refptr<ContentAction>(); | 62 return scoped_refptr<ContentAction>(); |
| 59 } | 63 } |
| 60 return scoped_refptr<ContentAction>(new ShowPageAction); | 64 return scoped_refptr<ContentAction>(new ShowPageAction); |
| 61 } | 65 } |
| 62 | 66 |
| 63 // Implementation of ContentAction: | 67 // Implementation of ContentAction: |
| 64 virtual Type GetType() const OVERRIDE { return ACTION_SHOW_PAGE_ACTION; } | 68 virtual Type GetType() const OVERRIDE { return ACTION_SHOW_PAGE_ACTION; } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 return ExtensionActionManager::Get(profile)->GetPageAction(*extension); | 100 return ExtensionActionManager::Get(profile)->GetPageAction(*extension); |
| 97 } | 101 } |
| 98 virtual ~ShowPageAction() {} | 102 virtual ~ShowPageAction() {} |
| 99 | 103 |
| 100 DISALLOW_COPY_AND_ASSIGN(ShowPageAction); | 104 DISALLOW_COPY_AND_ASSIGN(ShowPageAction); |
| 101 }; | 105 }; |
| 102 | 106 |
| 103 // Action that injects a content script. | 107 // Action that injects a content script. |
| 104 class RequestContentScript : public ContentAction { | 108 class RequestContentScript : public ContentAction { |
| 105 public: | 109 public: |
| 106 RequestContentScript(const std::vector<std::string>& css_file_names, | 110 RequestContentScript(content::BrowserContext* browser_context, |
| 111 const Extension* extension, |
| 112 const std::vector<std::string>& css_file_names, |
| 107 const std::vector<std::string>& js_file_names, | 113 const std::vector<std::string>& js_file_names, |
| 108 bool all_frames, | 114 bool all_frames, |
| 109 bool match_about_blank) | 115 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 | 116 |
| 115 static scoped_refptr<ContentAction> Create(const Extension* extension, | 117 static scoped_refptr<ContentAction> Create( |
| 116 const base::DictionaryValue* dict, | 118 content::BrowserContext* browser_context, |
| 117 std::string* error, | 119 const Extension* extension, |
| 118 bool* bad_message); | 120 const base::DictionaryValue* dict, |
| 121 std::string* error, |
| 122 bool* bad_message); |
| 119 | 123 |
| 120 // Implementation of ContentAction: | 124 // Implementation of ContentAction: |
| 121 virtual Type GetType() const OVERRIDE { | 125 virtual Type GetType() const OVERRIDE { |
| 122 return ACTION_REQUEST_CONTENT_SCRIPT; | 126 return ACTION_REQUEST_CONTENT_SCRIPT; |
| 123 } | 127 } |
| 124 | 128 |
| 125 virtual void Apply(const std::string& extension_id, | 129 virtual void Apply(const std::string& extension_id, |
| 126 const base::Time& extension_install_time, | 130 const base::Time& extension_install_time, |
| 127 ApplyInfo* apply_info) const OVERRIDE { | 131 ApplyInfo* apply_info) const OVERRIDE { |
| 128 // TODO(markdittmer): Invoke UserScriptMaster declarative script loader: | 132 InstructRenderProcessToInject(apply_info->tab, extension_id); |
| 129 // load new user script. | |
| 130 } | 133 } |
| 131 | 134 |
| 132 virtual void Reapply(const std::string& extension_id, | 135 virtual void Reapply(const std::string& extension_id, |
| 133 const base::Time& extension_install_time, | 136 const base::Time& extension_install_time, |
| 134 ApplyInfo* apply_info) const OVERRIDE { | 137 ApplyInfo* apply_info) const OVERRIDE { |
| 135 // TODO(markdittmer): Invoke UserScriptMaster declarative script loader: | 138 InstructRenderProcessToInject(apply_info->tab, extension_id); |
| 136 // load new user script. | |
| 137 } | 139 } |
| 138 | 140 |
| 139 virtual void Revert(const std::string& extension_id, | 141 virtual void Revert(const std::string& extension_id, |
| 140 const base::Time& extension_install_time, | 142 const base::Time& extension_install_time, |
| 141 ApplyInfo* apply_info) const OVERRIDE { | 143 ApplyInfo* apply_info) const OVERRIDE { |
| 142 // TODO(markdittmer): Invoke UserScriptMaster declarative script loader: | |
| 143 // do not load user script if Apply() runs again on the same page. | |
| 144 } | 144 } |
| 145 | 145 |
| 146 private: | 146 private: |
| 147 virtual ~RequestContentScript() {} | 147 virtual ~RequestContentScript() { |
| 148 DCHECK(master_); |
| 149 master_->RemoveScript(script_); |
| 150 } |
| 148 | 151 |
| 149 std::vector<std::string> css_file_names_; | 152 void InstructRenderProcessToInject(content::WebContents* contents, |
| 150 std::vector<std::string> js_file_names_; | 153 const std::string& extension_id) const; |
| 151 bool all_frames_; | 154 |
| 152 bool match_about_blank_; | 155 UserScript script_; |
| 156 DeclarativeUserScriptMaster* master_; |
| 153 | 157 |
| 154 DISALLOW_COPY_AND_ASSIGN(RequestContentScript); | 158 DISALLOW_COPY_AND_ASSIGN(RequestContentScript); |
| 155 }; | 159 }; |
| 156 | 160 |
| 157 // Helper for getting JS collections into C++. | 161 // Helper for getting JS collections into C++. |
| 158 static bool AppendJSStringsToCPPStrings(const base::ListValue& append_strings, | 162 static bool AppendJSStringsToCPPStrings(const base::ListValue& append_strings, |
| 159 std::vector<std::string>* append_to) { | 163 std::vector<std::string>* append_to) { |
| 160 for (base::ListValue::const_iterator it = append_strings.begin(); | 164 for (base::ListValue::const_iterator it = append_strings.begin(); |
| 161 it != append_strings.end(); | 165 it != append_strings.end(); |
| 162 ++it) { | 166 ++it) { |
| 163 std::string value; | 167 std::string value; |
| 164 if ((*it)->GetAsString(&value)) { | 168 if ((*it)->GetAsString(&value)) { |
| 165 append_to->push_back(value); | 169 append_to->push_back(value); |
| 166 } else { | 170 } else { |
| 167 return false; | 171 return false; |
| 168 } | 172 } |
| 169 } | 173 } |
| 170 | 174 |
| 171 return true; | 175 return true; |
| 172 } | 176 } |
| 173 | 177 |
| 174 // static | 178 // static |
| 175 scoped_refptr<ContentAction> RequestContentScript::Create( | 179 scoped_refptr<ContentAction> RequestContentScript::Create( |
| 180 content::BrowserContext* browser_context, |
| 176 const Extension* extension, | 181 const Extension* extension, |
| 177 const base::DictionaryValue* dict, | 182 const base::DictionaryValue* dict, |
| 178 std::string* error, | 183 std::string* error, |
| 179 bool* bad_message) { | 184 bool* bad_message) { |
| 180 std::vector<std::string> css_file_names; | 185 std::vector<std::string> css_file_names; |
| 181 std::vector<std::string> js_file_names; | 186 std::vector<std::string> js_file_names; |
| 182 bool all_frames = false; | 187 bool all_frames = false; |
| 183 bool match_about_blank = false; | 188 bool match_about_blank = false; |
| 184 const base::ListValue* list_value; | 189 const base::ListValue* list_value; |
| 185 | 190 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 199 } | 204 } |
| 200 if (dict->HasKey(keys::kAllFrames)) { | 205 if (dict->HasKey(keys::kAllFrames)) { |
| 201 INPUT_FORMAT_VALIDATE(dict->GetBoolean(keys::kAllFrames, &all_frames)); | 206 INPUT_FORMAT_VALIDATE(dict->GetBoolean(keys::kAllFrames, &all_frames)); |
| 202 } | 207 } |
| 203 if (dict->HasKey(keys::kMatchAboutBlank)) { | 208 if (dict->HasKey(keys::kMatchAboutBlank)) { |
| 204 INPUT_FORMAT_VALIDATE( | 209 INPUT_FORMAT_VALIDATE( |
| 205 dict->GetBoolean(keys::kMatchAboutBlank, &match_about_blank)); | 210 dict->GetBoolean(keys::kMatchAboutBlank, &match_about_blank)); |
| 206 } | 211 } |
| 207 | 212 |
| 208 return scoped_refptr<ContentAction>(new RequestContentScript( | 213 return scoped_refptr<ContentAction>(new RequestContentScript( |
| 209 css_file_names, js_file_names, all_frames, match_about_blank)); | 214 browser_context, |
| 215 extension, |
| 216 css_file_names, |
| 217 js_file_names, |
| 218 all_frames, |
| 219 match_about_blank)); |
| 220 } |
| 221 |
| 222 RequestContentScript::RequestContentScript( |
| 223 content::BrowserContext* browser_context, |
| 224 const Extension* extension, |
| 225 const std::vector<std::string>& css_file_names, |
| 226 const std::vector<std::string>& js_file_names, |
| 227 bool all_frames, |
| 228 bool match_about_blank) { |
| 229 script_.set_id(UserScript::GenerateUserScriptID()); |
| 230 script_.set_extension_id(extension->id()); |
| 231 script_.set_run_location(UserScript::BROWSER_DRIVEN); |
| 232 script_.set_match_all_frames(all_frames); |
| 233 script_.set_match_about_blank(match_about_blank); |
| 234 for (std::vector<std::string>::const_iterator it = css_file_names.begin(); |
| 235 it != css_file_names.end(); ++it) { |
| 236 GURL url = extension->GetResourceURL(*it); |
| 237 ExtensionResource resource = extension->GetResource(*it); |
| 238 script_.css_scripts().push_back(UserScript::File( |
| 239 resource.extension_root(), resource.relative_path(), url)); |
| 240 } |
| 241 for (std::vector<std::string>::const_iterator it = js_file_names.begin(); |
| 242 it != js_file_names.end(); ++it) { |
| 243 GURL url = extension->GetResourceURL(*it); |
| 244 ExtensionResource resource = extension->GetResource(*it); |
| 245 script_.js_scripts().push_back(UserScript::File( |
| 246 resource.extension_root(), resource.relative_path(), url)); |
| 247 } |
| 248 |
| 249 master_ = |
| 250 ExtensionSystem::Get(browser_context)-> |
| 251 GetDeclarativeUserScriptMasterByExtension(extension->id()); |
| 252 DCHECK(master_); |
| 253 master_->AddScript(script_); |
| 254 } |
| 255 |
| 256 void RequestContentScript::InstructRenderProcessToInject( |
| 257 content::WebContents* contents, |
| 258 const std::string& extension_id) const { |
| 259 // TODO(markdittmer): Send ExtensionMsg to renderer. |
| 210 } | 260 } |
| 211 | 261 |
| 212 struct ContentActionFactory { | 262 struct ContentActionFactory { |
| 213 // Factory methods for ContentAction instances. |extension| is the extension | 263 // Factory methods for ContentAction instances. |extension| is the extension |
| 214 // for which the action is being created. |dict| contains the json dictionary | 264 // 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 | 265 // that describes the action. |error| is used to return error messages in case |
| 216 // the extension passed an action that was syntactically correct but | 266 // the extension passed an action that was syntactically correct but |
| 217 // semantically incorrect. |bad_message| is set to true in case |dict| does | 267 // semantically incorrect. |bad_message| is set to true in case |dict| does |
| 218 // not confirm to the validated JSON specification. | 268 // not confirm to the validated JSON specification. |
| 219 typedef scoped_refptr<ContentAction>(*FactoryMethod)( | 269 typedef scoped_refptr<ContentAction>(*FactoryMethod)( |
| 270 content::BrowserContext* /* browser_context */, |
| 220 const Extension* /* extension */, | 271 const Extension* /* extension */, |
| 221 const base::DictionaryValue* /* dict */, | 272 const base::DictionaryValue* /* dict */, |
| 222 std::string* /* error */, | 273 std::string* /* error */, |
| 223 bool* /* bad_message */); | 274 bool* /* bad_message */); |
| 224 // Maps the name of a declarativeContent action type to the factory | 275 // Maps the name of a declarativeContent action type to the factory |
| 225 // function creating it. | 276 // function creating it. |
| 226 std::map<std::string, FactoryMethod> factory_methods; | 277 std::map<std::string, FactoryMethod> factory_methods; |
| 227 | 278 |
| 228 ContentActionFactory() { | 279 ContentActionFactory() { |
| 229 factory_methods[keys::kShowPageAction] = | 280 factory_methods[keys::kShowPageAction] = |
| (...skipping 11 matching lines...) Expand all Loading... |
| 241 // | 292 // |
| 242 // ContentAction | 293 // ContentAction |
| 243 // | 294 // |
| 244 | 295 |
| 245 ContentAction::ContentAction() {} | 296 ContentAction::ContentAction() {} |
| 246 | 297 |
| 247 ContentAction::~ContentAction() {} | 298 ContentAction::~ContentAction() {} |
| 248 | 299 |
| 249 // static | 300 // static |
| 250 scoped_refptr<ContentAction> ContentAction::Create( | 301 scoped_refptr<ContentAction> ContentAction::Create( |
| 302 content::BrowserContext* browser_context, |
| 251 const Extension* extension, | 303 const Extension* extension, |
| 252 const base::Value& json_action, | 304 const base::Value& json_action, |
| 253 std::string* error, | 305 std::string* error, |
| 254 bool* bad_message) { | 306 bool* bad_message) { |
| 255 *error = ""; | 307 *error = ""; |
| 256 *bad_message = false; | 308 *bad_message = false; |
| 257 | 309 |
| 258 const base::DictionaryValue* action_dict = NULL; | 310 const base::DictionaryValue* action_dict = NULL; |
| 259 INPUT_FORMAT_VALIDATE(json_action.GetAsDictionary(&action_dict)); | 311 INPUT_FORMAT_VALIDATE(json_action.GetAsDictionary(&action_dict)); |
| 260 | 312 |
| 261 std::string instance_type; | 313 std::string instance_type; |
| 262 INPUT_FORMAT_VALIDATE( | 314 INPUT_FORMAT_VALIDATE( |
| 263 action_dict->GetString(keys::kInstanceType, &instance_type)); | 315 action_dict->GetString(keys::kInstanceType, &instance_type)); |
| 264 | 316 |
| 265 ContentActionFactory& factory = g_content_action_factory.Get(); | 317 ContentActionFactory& factory = g_content_action_factory.Get(); |
| 266 std::map<std::string, ContentActionFactory::FactoryMethod>::iterator | 318 std::map<std::string, ContentActionFactory::FactoryMethod>::iterator |
| 267 factory_method_iter = factory.factory_methods.find(instance_type); | 319 factory_method_iter = factory.factory_methods.find(instance_type); |
| 268 if (factory_method_iter != factory.factory_methods.end()) | 320 if (factory_method_iter != factory.factory_methods.end()) |
| 269 return (*factory_method_iter->second)( | 321 return (*factory_method_iter->second)( |
| 270 extension, action_dict, error, bad_message); | 322 browser_context, extension, action_dict, error, bad_message); |
| 271 | 323 |
| 272 *error = base::StringPrintf(kInvalidInstanceTypeError, instance_type.c_str()); | 324 *error = base::StringPrintf(kInvalidInstanceTypeError, instance_type.c_str()); |
| 273 return scoped_refptr<ContentAction>(); | 325 return scoped_refptr<ContentAction>(); |
| 274 } | 326 } |
| 275 | 327 |
| 276 } // namespace extensions | 328 } // namespace extensions |
| OLD | NEW |