OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/common/extensions/extension.h" | 5 #include "chrome/common/extensions/extension.h" |
6 | 6 |
7 #include "app/resource_bundle.h" | 7 #include "app/resource_bundle.h" |
8 #include "base/basictypes.h" | 8 #include "base/basictypes.h" |
9 #include "base/file_path.h" | 9 #include "base/file_path.h" |
10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 }; | 97 }; |
98 | 98 |
99 const char* Extension::kPermissionNames[] = { | 99 const char* Extension::kPermissionNames[] = { |
100 "tabs", | 100 "tabs", |
101 "bookmarks", | 101 "bookmarks", |
102 }; | 102 }; |
103 const size_t Extension::kNumPermissions = | 103 const size_t Extension::kNumPermissions = |
104 arraysize(Extension::kPermissionNames); | 104 arraysize(Extension::kPermissionNames); |
105 | 105 |
106 Extension::~Extension() { | 106 Extension::~Extension() { |
107 STLDeleteValues(&page_actions_); | |
108 } | 107 } |
109 | 108 |
110 const std::string Extension::VersionString() const { | 109 const std::string Extension::VersionString() const { |
111 return version_->GetString(); | 110 return version_->GetString(); |
112 } | 111 } |
113 | 112 |
114 // static | 113 // static |
115 bool Extension::IsExtension(const FilePath& file_name) { | 114 bool Extension::IsExtension(const FilePath& file_name) { |
116 return file_name.MatchesExtension( | 115 return file_name.MatchesExtension( |
117 FilePath::StringType(FILE_PATH_LITERAL(".")) + | 116 FilePath::StringType(FILE_PATH_LITERAL(".")) + |
(...skipping 21 matching lines...) Expand all Loading... |
139 const std::string& relative_path) { | 138 const std::string& relative_path) { |
140 DCHECK(extension_url.SchemeIs(chrome::kExtensionScheme)); | 139 DCHECK(extension_url.SchemeIs(chrome::kExtensionScheme)); |
141 DCHECK(extension_url.path() == "/"); | 140 DCHECK(extension_url.path() == "/"); |
142 | 141 |
143 GURL ret_val = GURL(extension_url.spec() + relative_path); | 142 GURL ret_val = GURL(extension_url.spec() + relative_path); |
144 DCHECK(StartsWithASCII(ret_val.spec(), extension_url.spec(), false)); | 143 DCHECK(StartsWithASCII(ret_val.spec(), extension_url.spec(), false)); |
145 | 144 |
146 return ret_val; | 145 return ret_val; |
147 } | 146 } |
148 | 147 |
149 const ExtensionAction* Extension::GetExtensionAction( | |
150 std::string id, ExtensionAction::ExtensionActionType action_type) const { | |
151 if (action_type == ExtensionAction::BROWSER_ACTION) { | |
152 DCHECK(id.empty()); // Multiple browser actions are not allowed. | |
153 return browser_action_.get(); | |
154 } else { | |
155 ExtensionActionMap::const_iterator it = page_actions_.find(id); | |
156 if (it == page_actions_.end()) | |
157 return NULL; | |
158 | |
159 return it->second; | |
160 } | |
161 } | |
162 | |
163 Extension::Location Extension::ExternalExtensionInstallType( | 148 Extension::Location Extension::ExternalExtensionInstallType( |
164 std::string registry_path) { | 149 std::string registry_path) { |
165 #if defined(OS_WIN) | 150 #if defined(OS_WIN) |
166 HKEY reg_root = HKEY_LOCAL_MACHINE; | 151 HKEY reg_root = HKEY_LOCAL_MACHINE; |
167 RegKey key; | 152 RegKey key; |
168 registry_path.append("\\"); | 153 registry_path.append("\\"); |
169 registry_path.append(id_); | 154 registry_path.append(id_); |
170 if (key.Open(reg_root, ASCIIToWide(registry_path).c_str())) | 155 if (key.Open(reg_root, ASCIIToWide(registry_path).c_str())) |
171 return Extension::EXTERNAL_REGISTRY; | 156 return Extension::EXTERNAL_REGISTRY; |
172 #endif | 157 #endif |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 result->css_scripts().push_back(UserScript::File(resource, url)); | 288 result->css_scripts().push_back(UserScript::File(resource, url)); |
304 } | 289 } |
305 } | 290 } |
306 | 291 |
307 return true; | 292 return true; |
308 } | 293 } |
309 | 294 |
310 // Helper method that loads a PageAction or BrowserAction object from a | 295 // Helper method that loads a PageAction or BrowserAction object from a |
311 // dictionary in the page_actions list or browser_action key of the manifest. | 296 // dictionary in the page_actions list or browser_action key of the manifest. |
312 ExtensionAction* Extension::LoadExtensionActionHelper( | 297 ExtensionAction* Extension::LoadExtensionActionHelper( |
313 const DictionaryValue* page_action, int definition_index, | 298 const DictionaryValue* page_action, std::string* error, |
314 std::string* error, ExtensionAction::ExtensionActionType action_type) { | 299 ExtensionAction::ExtensionActionType action_type) { |
315 scoped_ptr<ExtensionAction> result(new ExtensionAction()); | 300 scoped_ptr<ExtensionAction> result(new ExtensionAction()); |
316 result->set_extension_id(id()); | 301 result->set_extension_id(id()); |
317 result->set_type(action_type); | 302 result->set_type(action_type); |
318 | 303 |
| 304 // TODO(EXTENSIONS_DEPRECATED): icons list is obsolete. |
319 ListValue* icons = NULL; | 305 ListValue* icons = NULL; |
320 // Read the page action |icons|. | 306 if (page_action->HasKey(keys::kPageActionIcons) && |
321 if (!page_action->HasKey(keys::kPageActionIcons) || | 307 page_action->GetList(keys::kPageActionIcons, &icons)) { |
322 !page_action->GetList(keys::kPageActionIcons, &icons) || | |
323 icons->GetSize() == 0) { | |
324 // Icons are only required for page actions. | |
325 if (action_type == ExtensionAction::PAGE_ACTION) { | |
326 *error = ExtensionErrorUtils::FormatErrorMessage( | |
327 errors::kInvalidPageActionIconPaths, IntToString(definition_index)); | |
328 return NULL; | |
329 } | |
330 } | |
331 | |
332 int icon_count = 0; | |
333 if (icons) { | |
334 for (ListValue::const_iterator iter = icons->begin(); | 308 for (ListValue::const_iterator iter = icons->begin(); |
335 iter != icons->end(); ++iter) { | 309 iter != icons->end(); ++iter) { |
336 std::string path; | 310 std::string path; |
337 if (!(*iter)->GetAsString(&path) || path.empty()) { | 311 if (!(*iter)->GetAsString(&path) || path.empty()) { |
338 *error = ExtensionErrorUtils::FormatErrorMessage( | 312 *error = errors::kInvalidPageActionIconPath; |
339 errors::kInvalidPageActionIconPath, | |
340 IntToString(definition_index), IntToString(icon_count)); | |
341 return NULL; | 313 return NULL; |
342 } | 314 } |
343 | 315 |
344 result->AddIconPath(path); | 316 result->AddIconPath(path); |
345 ++icon_count; | |
346 } | 317 } |
347 } | 318 } |
348 | 319 |
349 if (action_type == ExtensionAction::BROWSER_ACTION) { | 320 // TODO(EXTENSIONS_DEPRECATED): Read the page action |id| (optional). |
350 result->set_id(""); // Not needed (only 1 browser action per extension). | 321 std::string id; |
351 } else { | 322 if (action_type == ExtensionAction::PAGE_ACTION) |
352 // Read the page action |id|. | 323 page_action->GetString(keys::kPageActionId, &id); |
353 std::string id; | 324 result->set_id(id); |
354 if (!page_action->GetString(keys::kPageActionId, &id)) { | 325 |
355 *error = ExtensionErrorUtils::FormatErrorMessage( | 326 std::string default_icon; |
356 errors::kInvalidPageActionId, IntToString(definition_index)); | 327 // Read the page action |default_icon| (optional). |
| 328 if (page_action->HasKey(keys::kPageActionDefaultIcon)) { |
| 329 if (!page_action->GetString(keys::kPageActionDefaultIcon, &default_icon) || |
| 330 default_icon.empty()) { |
| 331 *error = errors::kInvalidPageActionIconPath; |
357 return NULL; | 332 return NULL; |
358 } | 333 } |
359 result->set_id(id); | 334 // TODO(EXTENSIONS_DEPRECATED): one icon. |
| 335 result->AddIconPath(default_icon); |
360 } | 336 } |
361 | 337 |
362 // Read the page action |name|. | 338 // Read the page action |default_title|. |
363 std::string name; | 339 std::string title; |
364 if (!page_action->GetString(keys::kName, &name)) { | 340 if (!page_action->GetString(keys::kName, &title) && |
365 *error = ExtensionErrorUtils::FormatErrorMessage(errors::kInvalidName, | 341 !page_action->GetString(keys::kPageActionDefaultTitle, &title)) { |
366 IntToString(definition_index)); | 342 *error = errors::kInvalidPageActionDefaultTitle; |
367 return NULL; | 343 return NULL; |
368 } | 344 } |
369 result->set_name(name); | 345 result->set_title(title); |
370 | 346 |
371 // Read the action's |popup| (optional). | 347 // Read the action's |popup| (optional). |
372 DictionaryValue* popup = NULL; | 348 DictionaryValue* popup = NULL; |
| 349 std::string url_str; |
373 if (page_action->HasKey(keys::kPageActionPopup) && | 350 if (page_action->HasKey(keys::kPageActionPopup) && |
374 !page_action->GetDictionary(keys::kPageActionPopup, &popup)) { | 351 !page_action->GetDictionary(keys::kPageActionPopup, &popup) && |
| 352 !page_action->GetString(keys::kPageActionPopup, &url_str)) { |
375 *error = errors::kInvalidPageActionPopup; | 353 *error = errors::kInvalidPageActionPopup; |
376 return NULL; | 354 return NULL; |
377 } | 355 } |
378 if (popup) { | 356 if (popup) { |
379 std::string url_str; | 357 // TODO(EXTENSIONS_DEPRECATED): popup is a string only |
380 if (!popup->GetString(keys::kPageActionPopupPath, &url_str)) { | 358 if (!popup->GetString(keys::kPageActionPopupPath, &url_str)) { |
381 *error = ExtensionErrorUtils::FormatErrorMessage( | 359 *error = ExtensionErrorUtils::FormatErrorMessage( |
382 errors::kInvalidPageActionPopupPath, "<missing>"); | 360 errors::kInvalidPageActionPopupPath, "<missing>"); |
383 return NULL; | 361 return NULL; |
384 } | 362 } |
385 GURL url = GetResourceURL(url_str); | 363 GURL url = GetResourceURL(url_str); |
386 if (!url.is_valid()) { | 364 if (!url.is_valid()) { |
387 *error = ExtensionErrorUtils::FormatErrorMessage( | 365 *error = ExtensionErrorUtils::FormatErrorMessage( |
388 errors::kInvalidPageActionPopupPath, url_str); | 366 errors::kInvalidPageActionPopupPath, url_str); |
389 return NULL; | 367 return NULL; |
390 } | 368 } |
391 result->set_popup_url(url); | 369 result->set_popup_url(url); |
392 | 370 |
393 int height; | 371 int height; |
394 if (!popup->GetInteger(keys::kPageActionPopupHeight, &height)) { | 372 if (!popup->GetInteger(keys::kPageActionPopupHeight, &height)) { |
395 *error = ExtensionErrorUtils::FormatErrorMessage( | 373 *error = ExtensionErrorUtils::FormatErrorMessage( |
396 errors::kInvalidPageActionPopupHeight, "<missing>"); | 374 errors::kInvalidPageActionPopupHeight, "<missing>"); |
397 return NULL; | 375 return NULL; |
398 } | 376 } |
399 result->set_popup_height(height); | 377 result->set_popup_height(height); |
| 378 } else if (!url_str.empty()) { |
| 379 GURL url = GetResourceURL(url_str); |
| 380 if (!url.is_valid()) { |
| 381 *error = ExtensionErrorUtils::FormatErrorMessage( |
| 382 errors::kInvalidPageActionPopupPath, url_str); |
| 383 return NULL; |
| 384 } |
| 385 result->set_popup_url(url); |
| 386 // TODO(erikkay): Need dynamic sizing of popups. |
| 387 // http://code.google.com/p/chromium/issues/detail?id=24471 |
| 388 result->set_popup_height(100); |
400 } | 389 } |
401 | 390 |
402 return result.release(); | 391 return result.release(); |
403 } | 392 } |
404 | 393 |
405 bool Extension::ContainsNonThemeKeys(const DictionaryValue& source) { | 394 bool Extension::ContainsNonThemeKeys(const DictionaryValue& source) { |
406 // Generate a map of allowable keys | 395 // Generate a map of allowable keys |
407 static std::map<std::wstring, bool> theme_keys; | 396 static std::map<std::wstring, bool> theme_keys; |
408 static bool theme_key_mapped = false; | 397 static bool theme_key_mapped = false; |
409 if (!theme_key_mapped) { | 398 if (!theme_key_mapped) { |
(...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
922 } | 911 } |
923 | 912 |
924 UserScript script; | 913 UserScript script; |
925 if (!LoadUserScriptHelper(content_script, i, error, &script)) | 914 if (!LoadUserScriptHelper(content_script, i, error, &script)) |
926 return false; // Failed to parse script context definition | 915 return false; // Failed to parse script context definition |
927 script.set_extension_id(id()); | 916 script.set_extension_id(id()); |
928 content_scripts_.push_back(script); | 917 content_scripts_.push_back(script); |
929 } | 918 } |
930 } | 919 } |
931 | 920 |
932 // Initialize page actions (optional). | 921 // Initialize page action (optional). |
933 if (source.HasKey(keys::kPageActions)) { | 922 if (source.HasKey(keys::kPageActions)) { |
934 ListValue* list_value; | 923 ListValue* list_value; |
935 if (!source.GetList(keys::kPageActions, &list_value)) { | 924 if (!source.GetList(keys::kPageActions, &list_value)) { |
936 *error = errors::kInvalidPageActionsList; | 925 *error = errors::kInvalidPageActionsList; |
937 return false; | 926 return false; |
938 } | 927 } |
939 | 928 |
940 for (size_t i = 0; i < list_value->GetSize(); ++i) { | 929 if (list_value->GetSize() != 1u) { |
941 DictionaryValue* page_action_value; | 930 *error = errors::kInvalidPageActionsListSize; |
942 if (!list_value->GetDictionary(i, &page_action_value)) { | 931 return false; |
943 *error = ExtensionErrorUtils::FormatErrorMessage( | 932 } |
944 errors::kInvalidPageAction, IntToString(i)); | |
945 return false; | |
946 } | |
947 | 933 |
948 ExtensionAction* contextual_action = | 934 DictionaryValue* page_action_value; |
949 LoadExtensionActionHelper(page_action_value, i, error, | 935 if (!list_value->GetDictionary(0, &page_action_value)) { |
950 ExtensionAction::PAGE_ACTION); | 936 *error = errors::kInvalidPageAction; |
951 if (!contextual_action) | 937 return false; |
952 return false; // Failed to parse page action definition. | |
953 page_actions_[contextual_action->id()] = contextual_action; | |
954 } | 938 } |
| 939 |
| 940 page_action_.reset( |
| 941 LoadExtensionActionHelper(page_action_value, error, |
| 942 ExtensionAction::PAGE_ACTION)); |
| 943 if (!page_action_.get()) |
| 944 return false; // Failed to parse page action definition. |
| 945 } else if (source.HasKey(keys::kPageAction)) { |
| 946 DictionaryValue* page_action_value; |
| 947 if (!source.GetDictionary(keys::kPageAction, &page_action_value)) { |
| 948 *error = errors::kInvalidPageAction; |
| 949 return false; |
| 950 } |
| 951 |
| 952 page_action_.reset( |
| 953 LoadExtensionActionHelper(page_action_value, error, |
| 954 ExtensionAction::PAGE_ACTION)); |
| 955 if (!page_action_.get()) |
| 956 return false; // Failed to parse page action definition. |
955 } | 957 } |
956 | 958 |
| 959 // Initialize browser action (optional). |
957 if (source.HasKey(keys::kBrowserAction)) { | 960 if (source.HasKey(keys::kBrowserAction)) { |
958 DictionaryValue* browser_action_value; | 961 DictionaryValue* browser_action_value; |
959 if (!source.GetDictionary(keys::kBrowserAction, &browser_action_value)) { | 962 if (!source.GetDictionary(keys::kBrowserAction, &browser_action_value)) { |
960 *error = ExtensionErrorUtils::FormatErrorMessage( | 963 *error = errors::kInvalidBrowserAction; |
961 errors::kInvalidBrowserAction, ""); | |
962 return false; | 964 return false; |
963 } | 965 } |
964 | 966 |
965 browser_action_.reset( | 967 browser_action_.reset( |
966 LoadExtensionActionHelper(browser_action_value, 0, error, | 968 LoadExtensionActionHelper(browser_action_value, error, |
967 ExtensionAction::BROWSER_ACTION)); | 969 ExtensionAction::BROWSER_ACTION)); |
968 if (!browser_action_.get()) | 970 if (!browser_action_.get()) |
969 return false; // Failed to parse browser action definition. | 971 return false; // Failed to parse browser action definition. |
970 | 972 |
971 browser_action_state_.reset( | 973 browser_action_state_.reset( |
972 new ExtensionActionState(browser_action_->name(), 0)); | 974 new ExtensionActionState(browser_action_->title(), 0)); |
973 } | 975 } |
974 | 976 |
975 // Initialize the permissions (optional). | 977 // Initialize the permissions (optional). |
976 if (source.HasKey(keys::kPermissions)) { | 978 if (source.HasKey(keys::kPermissions)) { |
977 ListValue* permissions = NULL; | 979 ListValue* permissions = NULL; |
978 if (!source.GetList(keys::kPermissions, &permissions)) { | 980 if (!source.GetList(keys::kPermissions, &permissions)) { |
979 *error = ExtensionErrorUtils::FormatErrorMessage( | 981 *error = ExtensionErrorUtils::FormatErrorMessage( |
980 errors::kInvalidPermissions, ""); | 982 errors::kInvalidPermissions, ""); |
981 return false; | 983 return false; |
982 } | 984 } |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1068 for (DictionaryValue::key_iterator it = theme_images->begin_keys(); | 1070 for (DictionaryValue::key_iterator it = theme_images->begin_keys(); |
1069 it != theme_images->end_keys(); ++it) { | 1071 it != theme_images->end_keys(); ++it) { |
1070 std::wstring val; | 1072 std::wstring val; |
1071 if (theme_images->GetString(*it, &val)) { | 1073 if (theme_images->GetString(*it, &val)) { |
1072 image_paths.insert(FilePath::FromWStringHack(val)); | 1074 image_paths.insert(FilePath::FromWStringHack(val)); |
1073 } | 1075 } |
1074 } | 1076 } |
1075 } | 1077 } |
1076 | 1078 |
1077 // page action icons | 1079 // page action icons |
1078 for (ExtensionActionMap::const_iterator it = page_actions().begin(); | 1080 if (page_action_.get()) { |
1079 it != page_actions().end(); ++it) { | 1081 const std::vector<std::string>& icon_paths = page_action_->icon_paths(); |
1080 const std::vector<std::string>& icon_paths = it->second->icon_paths(); | |
1081 for (std::vector<std::string>::const_iterator iter = icon_paths.begin(); | 1082 for (std::vector<std::string>::const_iterator iter = icon_paths.begin(); |
1082 iter != icon_paths.end(); ++iter) { | 1083 iter != icon_paths.end(); ++iter) { |
1083 image_paths.insert(FilePath::FromWStringHack(UTF8ToWide(*iter))); | 1084 image_paths.insert(FilePath::FromWStringHack(UTF8ToWide(*iter))); |
| 1085 } |
| 1086 } |
| 1087 |
| 1088 // browser action icons |
| 1089 if (browser_action_.get()) { |
| 1090 const std::vector<std::string>& icon_paths = browser_action_->icon_paths(); |
| 1091 for (std::vector<std::string>::const_iterator iter = icon_paths.begin(); |
| 1092 iter != icon_paths.end(); ++iter) { |
| 1093 image_paths.insert(FilePath::FromWStringHack(UTF8ToWide(*iter))); |
1084 } | 1094 } |
1085 } | 1095 } |
1086 | 1096 |
1087 return image_paths; | 1097 return image_paths; |
1088 } | 1098 } |
1089 | 1099 |
1090 bool Extension::GetBackgroundPageReady() { | 1100 bool Extension::GetBackgroundPageReady() { |
1091 return background_page_ready_ || background_url().is_empty(); | 1101 return background_page_ready_ || background_url().is_empty(); |
1092 } | 1102 } |
1093 | 1103 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1148 UserScript::PatternList::const_iterator pattern = | 1158 UserScript::PatternList::const_iterator pattern = |
1149 content_script->url_patterns().begin(); | 1159 content_script->url_patterns().begin(); |
1150 for (; pattern != content_script->url_patterns().end(); ++pattern) { | 1160 for (; pattern != content_script->url_patterns().end(); ++pattern) { |
1151 if (pattern->match_subdomains() && pattern->host().empty()) | 1161 if (pattern->match_subdomains() && pattern->host().empty()) |
1152 return true; | 1162 return true; |
1153 } | 1163 } |
1154 } | 1164 } |
1155 | 1165 |
1156 return false; | 1166 return false; |
1157 } | 1167 } |
OLD | NEW |