| 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 |