| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/base64.h" | 9 #include "base/base64.h" |
| 10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 257 const size_t Extension::kNumHostedAppPermissions = | 257 const size_t Extension::kNumHostedAppPermissions = |
| 258 arraysize(Extension::kHostedAppPermissionNames); | 258 arraysize(Extension::kHostedAppPermissionNames); |
| 259 | 259 |
| 260 // We purposefully don't put this into kPermissionNames. | 260 // We purposefully don't put this into kPermissionNames. |
| 261 const char Extension::kOldUnlimitedStoragePermission[] = "unlimited_storage"; | 261 const char Extension::kOldUnlimitedStoragePermission[] = "unlimited_storage"; |
| 262 | 262 |
| 263 const int Extension::kValidWebExtentSchemes = | 263 const int Extension::kValidWebExtentSchemes = |
| 264 URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS; | 264 URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS; |
| 265 | 265 |
| 266 const int Extension::kValidHostPermissionSchemes = | 266 const int Extension::kValidHostPermissionSchemes = |
| 267 (UserScript::kValidUserScriptSchemes | | 267 UserScript::kValidUserScriptSchemes | URLPattern::SCHEME_CHROMEUI; |
| 268 URLPattern::SCHEME_CHROMEUI) & ~URLPattern::SCHEME_FILE; | |
| 269 | 268 |
| 270 // | 269 // |
| 271 // Extension | 270 // Extension |
| 272 // | 271 // |
| 273 | 272 |
| 274 // static | 273 // static |
| 275 scoped_refptr<Extension> Extension::Create(const FilePath& path, | 274 scoped_refptr<Extension> Extension::Create(const FilePath& path, |
| 276 Location location, | 275 Location location, |
| 277 const DictionaryValue& value, | 276 const DictionaryValue& value, |
| 278 int flags, | 277 int flags, |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 549 *output = StringToLowerASCII(base::HexEncode(hash, sizeof(hash))); | 548 *output = StringToLowerASCII(base::HexEncode(hash, sizeof(hash))); |
| 550 ConvertHexadecimalToIDAlphabet(output); | 549 ConvertHexadecimalToIDAlphabet(output); |
| 551 | 550 |
| 552 return true; | 551 return true; |
| 553 } | 552 } |
| 554 | 553 |
| 555 // Helper method that loads a UserScript object from a dictionary in the | 554 // Helper method that loads a UserScript object from a dictionary in the |
| 556 // content_script list of the manifest. | 555 // content_script list of the manifest. |
| 557 bool Extension::LoadUserScriptHelper(const DictionaryValue* content_script, | 556 bool Extension::LoadUserScriptHelper(const DictionaryValue* content_script, |
| 558 int definition_index, | 557 int definition_index, |
| 559 URLPattern::ParseOption parse_strictness, | 558 int flags, |
| 560 std::string* error, | 559 std::string* error, |
| 561 UserScript* result) { | 560 UserScript* result) { |
| 561 // When strict error checks are enabled, make URL pattern parsing strict. |
| 562 URLPattern::ParseOption parse_strictness = |
| 563 (flags & STRICT_ERROR_CHECKS ? URLPattern::PARSE_STRICT |
| 564 : URLPattern::PARSE_LENIENT); |
| 565 |
| 562 // run_at | 566 // run_at |
| 563 if (content_script->HasKey(keys::kRunAt)) { | 567 if (content_script->HasKey(keys::kRunAt)) { |
| 564 std::string run_location; | 568 std::string run_location; |
| 565 if (!content_script->GetString(keys::kRunAt, &run_location)) { | 569 if (!content_script->GetString(keys::kRunAt, &run_location)) { |
| 566 *error = ExtensionErrorUtils::FormatErrorMessage(errors::kInvalidRunAt, | 570 *error = ExtensionErrorUtils::FormatErrorMessage(errors::kInvalidRunAt, |
| 567 base::IntToString(definition_index)); | 571 base::IntToString(definition_index)); |
| 568 return false; | 572 return false; |
| 569 } | 573 } |
| 570 | 574 |
| 571 if (run_location == values::kRunAtDocumentStart) { | 575 if (run_location == values::kRunAtDocumentStart) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 609 std::string match_str; | 613 std::string match_str; |
| 610 if (!matches->GetString(j, &match_str)) { | 614 if (!matches->GetString(j, &match_str)) { |
| 611 *error = ExtensionErrorUtils::FormatErrorMessage( | 615 *error = ExtensionErrorUtils::FormatErrorMessage( |
| 612 errors::kInvalidMatch, | 616 errors::kInvalidMatch, |
| 613 base::IntToString(definition_index), | 617 base::IntToString(definition_index), |
| 614 base::IntToString(j), | 618 base::IntToString(j), |
| 615 errors::kExpectString); | 619 errors::kExpectString); |
| 616 return false; | 620 return false; |
| 617 } | 621 } |
| 618 | 622 |
| 619 URLPattern pattern(UserScript::kValidUserScriptSchemes); | 623 InitWantsFileAccess(match_str, parse_strictness); |
| 620 if (CanExecuteScriptEverywhere()) | |
| 621 pattern.set_valid_schemes(URLPattern::SCHEME_ALL); | |
| 622 | 624 |
| 625 int valid_user_script_schemes = CanExecuteScriptEverywhere() ? |
| 626 URLPattern::SCHEME_ALL : UserScript::kValidUserScriptSchemes; |
| 627 if (flags & ALLOW_FILE_ACCESS) |
| 628 valid_user_script_schemes |= URLPattern::SCHEME_FILE; |
| 629 |
| 630 URLPattern pattern(valid_user_script_schemes); |
| 623 URLPattern::ParseResult parse_result = pattern.Parse(match_str, | 631 URLPattern::ParseResult parse_result = pattern.Parse(match_str, |
| 624 parse_strictness); | 632 parse_strictness); |
| 625 if (parse_result != URLPattern::PARSE_SUCCESS) { | 633 if (parse_result != URLPattern::PARSE_SUCCESS) { |
| 634 // Normally invalid URL patterns result in errors, but if a script is |
| 635 // requesting file:/// access before it has been granted, we silently |
| 636 // skip over that pattern. |
| 637 if (parse_result == URLPattern::PARSE_ERROR_INVALID_SCHEME && |
| 638 !(flags & ALLOW_FILE_ACCESS)) { |
| 639 URLPattern temp_pattern(URLPattern::SCHEME_FILE); |
| 640 URLPattern::ParseResult temp_parse_result = |
| 641 temp_pattern.Parse(match_str, parse_strictness); |
| 642 if (temp_parse_result == URLPattern::PARSE_SUCCESS) |
| 643 continue; |
| 644 } |
| 645 |
| 626 *error = ExtensionErrorUtils::FormatErrorMessage( | 646 *error = ExtensionErrorUtils::FormatErrorMessage( |
| 627 errors::kInvalidMatch, | 647 errors::kInvalidMatch, |
| 628 base::IntToString(definition_index), | 648 base::IntToString(definition_index), |
| 629 base::IntToString(j), | 649 base::IntToString(j), |
| 630 URLPattern::GetParseResultString(parse_result)); | 650 URLPattern::GetParseResultString(parse_result)); |
| 631 return false; | 651 return false; |
| 632 } | 652 } |
| 633 | 653 |
| 634 result->add_url_pattern(pattern); | 654 result->add_url_pattern(pattern); |
| 635 } | 655 } |
| (...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1205 | 1225 |
| 1206 Extension::Extension(const FilePath& path, Location location) | 1226 Extension::Extension(const FilePath& path, Location location) |
| 1207 : incognito_split_mode_(false), | 1227 : incognito_split_mode_(false), |
| 1208 location_(location), | 1228 location_(location), |
| 1209 converted_from_user_script_(false), | 1229 converted_from_user_script_(false), |
| 1210 is_theme_(false), | 1230 is_theme_(false), |
| 1211 is_app_(false), | 1231 is_app_(false), |
| 1212 is_storage_isolated_(false), | 1232 is_storage_isolated_(false), |
| 1213 launch_container_(extension_misc::LAUNCH_TAB), | 1233 launch_container_(extension_misc::LAUNCH_TAB), |
| 1214 launch_width_(0), | 1234 launch_width_(0), |
| 1215 launch_height_(0) { | 1235 launch_height_(0), |
| 1236 wants_file_access_(false) { |
| 1216 DCHECK(path.IsAbsolute()); | 1237 DCHECK(path.IsAbsolute()); |
| 1217 path_ = MaybeNormalizePath(path); | 1238 path_ = MaybeNormalizePath(path); |
| 1218 } | 1239 } |
| 1219 Extension::~Extension() { | 1240 Extension::~Extension() { |
| 1220 } | 1241 } |
| 1221 ExtensionResource Extension::GetResource( | 1242 ExtensionResource Extension::GetResource( |
| 1222 const std::string& relative_path) const { | 1243 const std::string& relative_path) const { |
| 1223 #if defined(OS_POSIX) | 1244 #if defined(OS_POSIX) |
| 1224 FilePath relative_file_path(relative_path); | 1245 FilePath relative_file_path(relative_path); |
| 1225 #elif defined(OS_WIN) | 1246 #elif defined(OS_WIN) |
| (...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1767 | 1788 |
| 1768 for (size_t i = 0; i < list_value->GetSize(); ++i) { | 1789 for (size_t i = 0; i < list_value->GetSize(); ++i) { |
| 1769 DictionaryValue* content_script; | 1790 DictionaryValue* content_script; |
| 1770 if (!list_value->GetDictionary(i, &content_script)) { | 1791 if (!list_value->GetDictionary(i, &content_script)) { |
| 1771 *error = ExtensionErrorUtils::FormatErrorMessage( | 1792 *error = ExtensionErrorUtils::FormatErrorMessage( |
| 1772 errors::kInvalidContentScript, base::IntToString(i)); | 1793 errors::kInvalidContentScript, base::IntToString(i)); |
| 1773 return false; | 1794 return false; |
| 1774 } | 1795 } |
| 1775 | 1796 |
| 1776 UserScript script; | 1797 UserScript script; |
| 1777 if (!LoadUserScriptHelper(content_script, i, parse_strictness, error, | 1798 if (!LoadUserScriptHelper(content_script, i, flags, error, &script)) |
| 1778 &script)) | |
| 1779 return false; // Failed to parse script context definition. | 1799 return false; // Failed to parse script context definition. |
| 1780 script.set_extension_id(id()); | 1800 script.set_extension_id(id()); |
| 1781 if (converted_from_user_script_) { | 1801 if (converted_from_user_script_) { |
| 1782 script.set_emulate_greasemonkey(true); | 1802 script.set_emulate_greasemonkey(true); |
| 1783 script.set_match_all_frames(true); // Greasemonkey matches all frames. | 1803 script.set_match_all_frames(true); // Greasemonkey matches all frames. |
| 1784 } | 1804 } |
| 1785 content_scripts_.push_back(script); | 1805 content_scripts_.push_back(script); |
| 1786 } | 1806 } |
| 1787 } | 1807 } |
| 1788 | 1808 |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1938 } | 1958 } |
| 1939 } else { | 1959 } else { |
| 1940 // Hosted apps only get access to a subset of the valid permissions. | 1960 // Hosted apps only get access to a subset of the valid permissions. |
| 1941 if (IsHostedAppPermission(permission_str)) { | 1961 if (IsHostedAppPermission(permission_str)) { |
| 1942 api_permissions_.insert(permission_str); | 1962 api_permissions_.insert(permission_str); |
| 1943 continue; | 1963 continue; |
| 1944 } | 1964 } |
| 1945 } | 1965 } |
| 1946 | 1966 |
| 1947 // Check if it's a host pattern permission. | 1967 // Check if it's a host pattern permission. |
| 1948 URLPattern pattern = URLPattern(CanExecuteScriptEverywhere() ? | 1968 int valid_host_permission_schemes = CanExecuteScriptEverywhere() ? |
| 1949 URLPattern::SCHEME_ALL : kValidHostPermissionSchemes); | 1969 URLPattern::SCHEME_ALL : kValidHostPermissionSchemes; |
| 1970 if (flags & ALLOW_FILE_ACCESS) |
| 1971 valid_host_permission_schemes |= URLPattern::SCHEME_FILE; |
| 1950 | 1972 |
| 1973 URLPattern pattern = URLPattern(valid_host_permission_schemes); |
| 1951 URLPattern::ParseResult parse_result = pattern.Parse(permission_str, | 1974 URLPattern::ParseResult parse_result = pattern.Parse(permission_str, |
| 1952 parse_strictness); | 1975 parse_strictness); |
| 1953 if (parse_result == URLPattern::PARSE_SUCCESS) { | 1976 if (parse_result == URLPattern::PARSE_SUCCESS) { |
| 1954 if (!CanSpecifyHostPermission(pattern)) { | 1977 if (!CanSpecifyHostPermission(pattern)) { |
| 1955 *error = ExtensionErrorUtils::FormatErrorMessage( | 1978 *error = ExtensionErrorUtils::FormatErrorMessage( |
| 1956 errors::kInvalidPermissionScheme, base::IntToString(i)); | 1979 errors::kInvalidPermissionScheme, base::IntToString(i)); |
| 1957 return false; | 1980 return false; |
| 1958 } | 1981 } |
| 1959 | 1982 |
| 1960 // The path component is not used for host permissions, so we force it | 1983 // The path component is not used for host permissions, so we force it |
| 1961 // to match all paths. | 1984 // to match all paths. |
| 1962 pattern.SetPath("/*"); | 1985 pattern.SetPath("/*"); |
| 1963 | 1986 |
| 1964 host_permissions_.push_back(pattern); | 1987 host_permissions_.push_back(pattern); |
| 1965 } | 1988 } |
| 1966 | 1989 |
| 1990 InitWantsFileAccess(permission_str, parse_strictness); |
| 1991 |
| 1967 // If it's not a host permission, then it's probably an unknown API | 1992 // If it's not a host permission, then it's probably an unknown API |
| 1968 // permission. Do not throw an error so extensions can retain | 1993 // permission. Do not throw an error so extensions can retain |
| 1969 // backwards compatability (http://crbug.com/42742). | 1994 // backwards compatability (http://crbug.com/42742). |
| 1970 // TODO(jstritar): We can improve error messages by adding better | 1995 // TODO(jstritar): We can improve error messages by adding better |
| 1971 // validation of API permissions here. | 1996 // validation of API permissions here. |
| 1972 // TODO(skerner): Consider showing the reason |permission_str| is not | 1997 // TODO(skerner): Consider showing the reason |permission_str| is not |
| 1973 // a valid URL pattern if it is almost valid. For example, if it has | 1998 // a valid URL pattern if it is almost valid. For example, if it has |
| 1974 // a valid scheme, and failed to parse because it has a port, show an | 1999 // a valid scheme, and failed to parse because it has a port, show an |
| 1975 // error. | 2000 // error. |
| 1976 } | 2001 } |
| (...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2364 | 2389 |
| 2365 bool Extension::HasHostPermission(const GURL& url) const { | 2390 bool Extension::HasHostPermission(const GURL& url) const { |
| 2366 for (URLPatternList::const_iterator host = host_permissions().begin(); | 2391 for (URLPatternList::const_iterator host = host_permissions().begin(); |
| 2367 host != host_permissions().end(); ++host) { | 2392 host != host_permissions().end(); ++host) { |
| 2368 if (host->MatchesUrl(url)) | 2393 if (host->MatchesUrl(url)) |
| 2369 return true; | 2394 return true; |
| 2370 } | 2395 } |
| 2371 return false; | 2396 return false; |
| 2372 } | 2397 } |
| 2373 | 2398 |
| 2399 void Extension::InitWantsFileAccess(const std::string& host_str, |
| 2400 URLPattern::ParseOption parse_strictness) { |
| 2401 URLPattern pattern = URLPattern(URLPattern::SCHEME_ALL); |
| 2402 URLPattern::ParseResult parse_result = pattern.Parse(host_str, |
| 2403 parse_strictness); |
| 2404 if (parse_result == URLPattern::PARSE_SUCCESS && |
| 2405 pattern.MatchesScheme(chrome::kFileScheme)) { |
| 2406 wants_file_access_ = true; |
| 2407 } |
| 2408 } |
| 2409 |
| 2374 void Extension::InitEffectiveHostPermissions() { | 2410 void Extension::InitEffectiveHostPermissions() { |
| 2375 for (URLPatternList::const_iterator host = host_permissions().begin(); | 2411 for (URLPatternList::const_iterator host = host_permissions().begin(); |
| 2376 host != host_permissions().end(); ++host) | 2412 host != host_permissions().end(); ++host) |
| 2377 effective_host_permissions_.AddPattern(*host); | 2413 effective_host_permissions_.AddPattern(*host); |
| 2378 | 2414 |
| 2379 for (UserScriptList::const_iterator content_script = | 2415 for (UserScriptList::const_iterator content_script = |
| 2380 content_scripts().begin(); | 2416 content_scripts().begin(); |
| 2381 content_script != content_scripts().end(); ++content_script) { | 2417 content_script != content_scripts().end(); ++content_script) { |
| 2382 UserScript::PatternList::const_iterator pattern = | 2418 UserScript::PatternList::const_iterator pattern = |
| 2383 content_script->url_patterns().begin(); | 2419 content_script->url_patterns().begin(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2395 if (browser_action()) | 2431 if (browser_action()) |
| 2396 ++num_surfaces; | 2432 ++num_surfaces; |
| 2397 | 2433 |
| 2398 if (is_app()) | 2434 if (is_app()) |
| 2399 ++num_surfaces; | 2435 ++num_surfaces; |
| 2400 | 2436 |
| 2401 return num_surfaces > 1; | 2437 return num_surfaces > 1; |
| 2402 } | 2438 } |
| 2403 | 2439 |
| 2404 bool Extension::CanExecuteScriptOnPage(const GURL& page_url, | 2440 bool Extension::CanExecuteScriptOnPage(const GURL& page_url, |
| 2405 UserScript* script, | 2441 const UserScript* script, |
| 2406 std::string* error) const { | 2442 std::string* error) const { |
| 2407 // The gallery is special-cased as a restricted URL for scripting to prevent | 2443 // The gallery is special-cased as a restricted URL for scripting to prevent |
| 2408 // access to special JS bindings we expose to the gallery (and avoid things | 2444 // access to special JS bindings we expose to the gallery (and avoid things |
| 2409 // like extensions removing the "report abuse" link). | 2445 // like extensions removing the "report abuse" link). |
| 2410 // TODO(erikkay): This seems like the wrong test. Shouldn't we we testing | 2446 // TODO(erikkay): This seems like the wrong test. Shouldn't we we testing |
| 2411 // against the store app extent? | 2447 // against the store app extent? |
| 2412 if ((page_url.host() == GURL(Extension::ChromeStoreLaunchURL()).host()) && | 2448 if ((page_url.host() == GURL(Extension::ChromeStoreLaunchURL()).host()) && |
| 2413 !CanExecuteScriptEverywhere() && | 2449 !CanExecuteScriptEverywhere() && |
| 2414 !CommandLine::ForCurrentProcess()->HasSwitch( | 2450 !CommandLine::ForCurrentProcess()->HasSwitch( |
| 2415 switches::kAllowScriptingGallery)) { | 2451 switches::kAllowScriptingGallery)) { |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2558 | 2594 |
| 2559 UninstalledExtensionInfo::~UninstalledExtensionInfo() {} | 2595 UninstalledExtensionInfo::~UninstalledExtensionInfo() {} |
| 2560 | 2596 |
| 2561 | 2597 |
| 2562 UnloadedExtensionInfo::UnloadedExtensionInfo( | 2598 UnloadedExtensionInfo::UnloadedExtensionInfo( |
| 2563 const Extension* extension, | 2599 const Extension* extension, |
| 2564 Reason reason) | 2600 Reason reason) |
| 2565 : reason(reason), | 2601 : reason(reason), |
| 2566 already_disabled(false), | 2602 already_disabled(false), |
| 2567 extension(extension) {} | 2603 extension(extension) {} |
| OLD | NEW |