| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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 "base/base64.h" | 7 #include "base/base64.h" |
| 8 #include "base/basictypes.h" | 8 #include "base/basictypes.h" |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
| (...skipping 961 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 972 // show packaged apps and platform apps because there are some pieces of | 972 // show packaged apps and platform apps because there are some pieces of |
| 973 // functionality that are only available in chrome://extensions/ but which | 973 // functionality that are only available in chrome://extensions/ but which |
| 974 // are needed for packaged and platform apps. For example, inspecting | 974 // are needed for packaged and platform apps. For example, inspecting |
| 975 // background pages. See http://crbug.com/116134. | 975 // background pages. See http://crbug.com/116134. |
| 976 if (is_hosted_app()) | 976 if (is_hosted_app()) |
| 977 return false; | 977 return false; |
| 978 | 978 |
| 979 return true; | 979 return true; |
| 980 } | 980 } |
| 981 | 981 |
| 982 bool Extension::HasContentScriptAtURL(const GURL& url) const { | |
| 983 for (UserScriptList::const_iterator it = content_scripts_.begin(); | |
| 984 it != content_scripts_.end(); ++it) { | |
| 985 if (it->MatchesURL(url)) | |
| 986 return true; | |
| 987 } | |
| 988 return false; | |
| 989 } | |
| 990 | |
| 991 scoped_refptr<const PermissionSet> Extension::GetTabSpecificPermissions( | 982 scoped_refptr<const PermissionSet> Extension::GetTabSpecificPermissions( |
| 992 int tab_id) const { | 983 int tab_id) const { |
| 993 base::AutoLock auto_lock(runtime_data_lock_); | 984 base::AutoLock auto_lock(runtime_data_lock_); |
| 994 return runtime_data_.GetTabSpecificPermissions(tab_id); | 985 return runtime_data_.GetTabSpecificPermissions(tab_id); |
| 995 } | 986 } |
| 996 | 987 |
| 997 void Extension::UpdateTabSpecificPermissions( | 988 void Extension::UpdateTabSpecificPermissions( |
| 998 int tab_id, | 989 int tab_id, |
| 999 scoped_refptr<const PermissionSet> permissions) const { | 990 scoped_refptr<const PermissionSet> permissions) const { |
| 1000 base::AutoLock auto_lock(runtime_data_lock_); | 991 base::AutoLock auto_lock(runtime_data_lock_); |
| (...skipping 919 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1920 return false; | 1911 return false; |
| 1921 } | 1912 } |
| 1922 return true; | 1913 return true; |
| 1923 } | 1914 } |
| 1924 | 1915 |
| 1925 bool Extension::LoadExtensionFeatures(string16* error) { | 1916 bool Extension::LoadExtensionFeatures(string16* error) { |
| 1926 if (manifest_->HasKey(keys::kConvertedFromUserScript)) | 1917 if (manifest_->HasKey(keys::kConvertedFromUserScript)) |
| 1927 manifest_->GetBoolean(keys::kConvertedFromUserScript, | 1918 manifest_->GetBoolean(keys::kConvertedFromUserScript, |
| 1928 &converted_from_user_script_); | 1919 &converted_from_user_script_); |
| 1929 | 1920 |
| 1930 if (!LoadContentScripts(error) || | 1921 if (!LoadSystemIndicator(error) || |
| 1931 !LoadSystemIndicator(error) || | |
| 1932 !LoadIncognitoMode(error)) | 1922 !LoadIncognitoMode(error)) |
| 1933 return false; | 1923 return false; |
| 1934 | 1924 |
| 1935 return true; | 1925 return true; |
| 1936 } | 1926 } |
| 1937 | 1927 |
| 1938 bool Extension::LoadContentScripts(string16* error) { | |
| 1939 if (!manifest_->HasKey(keys::kContentScripts)) | |
| 1940 return true; | |
| 1941 | |
| 1942 const ListValue* list_value; | |
| 1943 if (!manifest_->GetList(keys::kContentScripts, &list_value)) { | |
| 1944 *error = ASCIIToUTF16(errors::kInvalidContentScriptsList); | |
| 1945 return false; | |
| 1946 } | |
| 1947 | |
| 1948 for (size_t i = 0; i < list_value->GetSize(); ++i) { | |
| 1949 const DictionaryValue* content_script = NULL; | |
| 1950 if (!list_value->GetDictionary(i, &content_script)) { | |
| 1951 *error = ErrorUtils::FormatErrorMessageUTF16( | |
| 1952 errors::kInvalidContentScript, base::IntToString(i)); | |
| 1953 return false; | |
| 1954 } | |
| 1955 | |
| 1956 UserScript script; | |
| 1957 if (!LoadUserScriptHelper(content_script, i, error, &script)) | |
| 1958 return false; // Failed to parse script context definition. | |
| 1959 | |
| 1960 script.set_extension_id(id()); | |
| 1961 if (converted_from_user_script_) { | |
| 1962 script.set_emulate_greasemonkey(true); | |
| 1963 script.set_match_all_frames(true); // Greasemonkey matches all frames. | |
| 1964 } | |
| 1965 content_scripts_.push_back(script); | |
| 1966 } | |
| 1967 return true; | |
| 1968 } | |
| 1969 | |
| 1970 bool Extension::LoadSystemIndicator(string16* error) { | 1928 bool Extension::LoadSystemIndicator(string16* error) { |
| 1971 if (!manifest_->HasKey(keys::kSystemIndicator)) { | 1929 if (!manifest_->HasKey(keys::kSystemIndicator)) { |
| 1972 // There was no manifest entry for the system indicator. | 1930 // There was no manifest entry for the system indicator. |
| 1973 return true; | 1931 return true; |
| 1974 } | 1932 } |
| 1975 | 1933 |
| 1976 const DictionaryValue* system_indicator_value = NULL; | 1934 const DictionaryValue* system_indicator_value = NULL; |
| 1977 if (!manifest_->GetDictionary(keys::kSystemIndicator, | 1935 if (!manifest_->GetDictionary(keys::kSystemIndicator, |
| 1978 &system_indicator_value)) { | 1936 &system_indicator_value)) { |
| 1979 *error = ASCIIToUTF16(errors::kInvalidSystemIndicator); | 1937 *error = ASCIIToUTF16(errors::kInvalidSystemIndicator); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 2008 incognito_split_mode_ = false; | 1966 incognito_split_mode_ = false; |
| 2009 } else if (value == values::kIncognitoSplit) { | 1967 } else if (value == values::kIncognitoSplit) { |
| 2010 incognito_split_mode_ = true; | 1968 incognito_split_mode_ = true; |
| 2011 } else { | 1969 } else { |
| 2012 *error = ASCIIToUTF16(errors::kInvalidIncognitoBehavior); | 1970 *error = ASCIIToUTF16(errors::kInvalidIncognitoBehavior); |
| 2013 return false; | 1971 return false; |
| 2014 } | 1972 } |
| 2015 return true; | 1973 return true; |
| 2016 } | 1974 } |
| 2017 | 1975 |
| 2018 // Helper method that loads a UserScript object from a dictionary in the | |
| 2019 // content_script list of the manifest. | |
| 2020 bool Extension::LoadUserScriptHelper(const DictionaryValue* content_script, | |
| 2021 int definition_index, | |
| 2022 string16* error, | |
| 2023 UserScript* result) { | |
| 2024 // run_at | |
| 2025 if (content_script->HasKey(keys::kRunAt)) { | |
| 2026 std::string run_location; | |
| 2027 if (!content_script->GetString(keys::kRunAt, &run_location)) { | |
| 2028 *error = ErrorUtils::FormatErrorMessageUTF16( | |
| 2029 errors::kInvalidRunAt, | |
| 2030 base::IntToString(definition_index)); | |
| 2031 return false; | |
| 2032 } | |
| 2033 | |
| 2034 if (run_location == values::kRunAtDocumentStart) { | |
| 2035 result->set_run_location(UserScript::DOCUMENT_START); | |
| 2036 } else if (run_location == values::kRunAtDocumentEnd) { | |
| 2037 result->set_run_location(UserScript::DOCUMENT_END); | |
| 2038 } else if (run_location == values::kRunAtDocumentIdle) { | |
| 2039 result->set_run_location(UserScript::DOCUMENT_IDLE); | |
| 2040 } else { | |
| 2041 *error = ErrorUtils::FormatErrorMessageUTF16( | |
| 2042 errors::kInvalidRunAt, | |
| 2043 base::IntToString(definition_index)); | |
| 2044 return false; | |
| 2045 } | |
| 2046 } | |
| 2047 | |
| 2048 // all frames | |
| 2049 if (content_script->HasKey(keys::kAllFrames)) { | |
| 2050 bool all_frames = false; | |
| 2051 if (!content_script->GetBoolean(keys::kAllFrames, &all_frames)) { | |
| 2052 *error = ErrorUtils::FormatErrorMessageUTF16( | |
| 2053 errors::kInvalidAllFrames, base::IntToString(definition_index)); | |
| 2054 return false; | |
| 2055 } | |
| 2056 result->set_match_all_frames(all_frames); | |
| 2057 } | |
| 2058 | |
| 2059 // matches (required) | |
| 2060 const ListValue* matches = NULL; | |
| 2061 if (!content_script->GetList(keys::kMatches, &matches)) { | |
| 2062 *error = ErrorUtils::FormatErrorMessageUTF16( | |
| 2063 errors::kInvalidMatches, | |
| 2064 base::IntToString(definition_index)); | |
| 2065 return false; | |
| 2066 } | |
| 2067 | |
| 2068 if (matches->GetSize() == 0) { | |
| 2069 *error = ErrorUtils::FormatErrorMessageUTF16( | |
| 2070 errors::kInvalidMatchCount, | |
| 2071 base::IntToString(definition_index)); | |
| 2072 return false; | |
| 2073 } | |
| 2074 for (size_t j = 0; j < matches->GetSize(); ++j) { | |
| 2075 std::string match_str; | |
| 2076 if (!matches->GetString(j, &match_str)) { | |
| 2077 *error = ErrorUtils::FormatErrorMessageUTF16( | |
| 2078 errors::kInvalidMatch, | |
| 2079 base::IntToString(definition_index), | |
| 2080 base::IntToString(j), | |
| 2081 errors::kExpectString); | |
| 2082 return false; | |
| 2083 } | |
| 2084 | |
| 2085 URLPattern pattern( | |
| 2086 UserScript::ValidUserScriptSchemes(CanExecuteScriptEverywhere())); | |
| 2087 | |
| 2088 URLPattern::ParseResult parse_result = pattern.Parse(match_str); | |
| 2089 if (parse_result != URLPattern::PARSE_SUCCESS) { | |
| 2090 *error = ErrorUtils::FormatErrorMessageUTF16( | |
| 2091 errors::kInvalidMatch, | |
| 2092 base::IntToString(definition_index), | |
| 2093 base::IntToString(j), | |
| 2094 URLPattern::GetParseResultString(parse_result)); | |
| 2095 return false; | |
| 2096 } | |
| 2097 | |
| 2098 // TODO(aboxhall): check for webstore | |
| 2099 if (!CanExecuteScriptEverywhere() && | |
| 2100 pattern.scheme() != chrome::kChromeUIScheme) { | |
| 2101 // Exclude SCHEME_CHROMEUI unless it's been explicitly requested. | |
| 2102 // If the --extensions-on-chrome-urls flag has not been passed, requesting | |
| 2103 // a chrome:// url will cause a parse failure above, so there's no need to | |
| 2104 // check the flag here. | |
| 2105 pattern.SetValidSchemes( | |
| 2106 pattern.valid_schemes() & ~URLPattern::SCHEME_CHROMEUI); | |
| 2107 } | |
| 2108 | |
| 2109 if (pattern.MatchesScheme(chrome::kFileScheme) && | |
| 2110 !CanExecuteScriptEverywhere()) { | |
| 2111 wants_file_access_ = true; | |
| 2112 if (!(creation_flags_ & ALLOW_FILE_ACCESS)) { | |
| 2113 pattern.SetValidSchemes( | |
| 2114 pattern.valid_schemes() & ~URLPattern::SCHEME_FILE); | |
| 2115 } | |
| 2116 } | |
| 2117 | |
| 2118 result->add_url_pattern(pattern); | |
| 2119 } | |
| 2120 | |
| 2121 // exclude_matches | |
| 2122 if (content_script->HasKey(keys::kExcludeMatches)) { // optional | |
| 2123 const ListValue* exclude_matches = NULL; | |
| 2124 if (!content_script->GetList(keys::kExcludeMatches, &exclude_matches)) { | |
| 2125 *error = ErrorUtils::FormatErrorMessageUTF16( | |
| 2126 errors::kInvalidExcludeMatches, | |
| 2127 base::IntToString(definition_index)); | |
| 2128 return false; | |
| 2129 } | |
| 2130 | |
| 2131 for (size_t j = 0; j < exclude_matches->GetSize(); ++j) { | |
| 2132 std::string match_str; | |
| 2133 if (!exclude_matches->GetString(j, &match_str)) { | |
| 2134 *error = ErrorUtils::FormatErrorMessageUTF16( | |
| 2135 errors::kInvalidExcludeMatch, | |
| 2136 base::IntToString(definition_index), | |
| 2137 base::IntToString(j), | |
| 2138 errors::kExpectString); | |
| 2139 return false; | |
| 2140 } | |
| 2141 | |
| 2142 int valid_schemes = | |
| 2143 UserScript::ValidUserScriptSchemes(CanExecuteScriptEverywhere()); | |
| 2144 URLPattern pattern(valid_schemes); | |
| 2145 URLPattern::ParseResult parse_result = pattern.Parse(match_str); | |
| 2146 if (parse_result != URLPattern::PARSE_SUCCESS) { | |
| 2147 *error = ErrorUtils::FormatErrorMessageUTF16( | |
| 2148 errors::kInvalidExcludeMatch, | |
| 2149 base::IntToString(definition_index), base::IntToString(j), | |
| 2150 URLPattern::GetParseResultString(parse_result)); | |
| 2151 return false; | |
| 2152 } | |
| 2153 | |
| 2154 result->add_exclude_url_pattern(pattern); | |
| 2155 } | |
| 2156 } | |
| 2157 | |
| 2158 // include/exclude globs (mostly for Greasemonkey compatibility) | |
| 2159 if (!LoadGlobsHelper(content_script, definition_index, keys::kIncludeGlobs, | |
| 2160 error, &UserScript::add_glob, result)) { | |
| 2161 return false; | |
| 2162 } | |
| 2163 | |
| 2164 if (!LoadGlobsHelper(content_script, definition_index, keys::kExcludeGlobs, | |
| 2165 error, &UserScript::add_exclude_glob, result)) { | |
| 2166 return false; | |
| 2167 } | |
| 2168 | |
| 2169 // js and css keys | |
| 2170 const ListValue* js = NULL; | |
| 2171 if (content_script->HasKey(keys::kJs) && | |
| 2172 !content_script->GetList(keys::kJs, &js)) { | |
| 2173 *error = ErrorUtils::FormatErrorMessageUTF16( | |
| 2174 errors::kInvalidJsList, | |
| 2175 base::IntToString(definition_index)); | |
| 2176 return false; | |
| 2177 } | |
| 2178 | |
| 2179 const ListValue* css = NULL; | |
| 2180 if (content_script->HasKey(keys::kCss) && | |
| 2181 !content_script->GetList(keys::kCss, &css)) { | |
| 2182 *error = ErrorUtils:: | |
| 2183 FormatErrorMessageUTF16(errors::kInvalidCssList, | |
| 2184 base::IntToString(definition_index)); | |
| 2185 return false; | |
| 2186 } | |
| 2187 | |
| 2188 // The manifest needs to have at least one js or css user script definition. | |
| 2189 if (((js ? js->GetSize() : 0) + (css ? css->GetSize() : 0)) == 0) { | |
| 2190 *error = ErrorUtils::FormatErrorMessageUTF16( | |
| 2191 errors::kMissingFile, | |
| 2192 base::IntToString(definition_index)); | |
| 2193 return false; | |
| 2194 } | |
| 2195 | |
| 2196 if (js) { | |
| 2197 for (size_t script_index = 0; script_index < js->GetSize(); | |
| 2198 ++script_index) { | |
| 2199 const Value* value; | |
| 2200 std::string relative; | |
| 2201 if (!js->Get(script_index, &value) || !value->GetAsString(&relative)) { | |
| 2202 *error = ErrorUtils::FormatErrorMessageUTF16( | |
| 2203 errors::kInvalidJs, | |
| 2204 base::IntToString(definition_index), | |
| 2205 base::IntToString(script_index)); | |
| 2206 return false; | |
| 2207 } | |
| 2208 GURL url = GetResourceURL(relative); | |
| 2209 ExtensionResource resource = GetResource(relative); | |
| 2210 result->js_scripts().push_back(UserScript::File( | |
| 2211 resource.extension_root(), resource.relative_path(), url)); | |
| 2212 } | |
| 2213 } | |
| 2214 | |
| 2215 if (css) { | |
| 2216 for (size_t script_index = 0; script_index < css->GetSize(); | |
| 2217 ++script_index) { | |
| 2218 const Value* value; | |
| 2219 std::string relative; | |
| 2220 if (!css->Get(script_index, &value) || !value->GetAsString(&relative)) { | |
| 2221 *error = ErrorUtils::FormatErrorMessageUTF16( | |
| 2222 errors::kInvalidCss, | |
| 2223 base::IntToString(definition_index), | |
| 2224 base::IntToString(script_index)); | |
| 2225 return false; | |
| 2226 } | |
| 2227 GURL url = GetResourceURL(relative); | |
| 2228 ExtensionResource resource = GetResource(relative); | |
| 2229 result->css_scripts().push_back(UserScript::File( | |
| 2230 resource.extension_root(), resource.relative_path(), url)); | |
| 2231 } | |
| 2232 } | |
| 2233 | |
| 2234 return true; | |
| 2235 } | |
| 2236 | |
| 2237 bool Extension::LoadGlobsHelper( | |
| 2238 const DictionaryValue* content_script, | |
| 2239 int content_script_index, | |
| 2240 const char* globs_property_name, | |
| 2241 string16* error, | |
| 2242 void(UserScript::*add_method)(const std::string& glob), | |
| 2243 UserScript* instance) { | |
| 2244 if (!content_script->HasKey(globs_property_name)) | |
| 2245 return true; // they are optional | |
| 2246 | |
| 2247 const ListValue* list = NULL; | |
| 2248 if (!content_script->GetList(globs_property_name, &list)) { | |
| 2249 *error = ErrorUtils::FormatErrorMessageUTF16( | |
| 2250 errors::kInvalidGlobList, | |
| 2251 base::IntToString(content_script_index), | |
| 2252 globs_property_name); | |
| 2253 return false; | |
| 2254 } | |
| 2255 | |
| 2256 for (size_t i = 0; i < list->GetSize(); ++i) { | |
| 2257 std::string glob; | |
| 2258 if (!list->GetString(i, &glob)) { | |
| 2259 *error = ErrorUtils::FormatErrorMessageUTF16( | |
| 2260 errors::kInvalidGlob, | |
| 2261 base::IntToString(content_script_index), | |
| 2262 globs_property_name, | |
| 2263 base::IntToString(i)); | |
| 2264 return false; | |
| 2265 } | |
| 2266 | |
| 2267 (instance->*add_method)(glob); | |
| 2268 } | |
| 2269 | |
| 2270 return true; | |
| 2271 } | |
| 2272 | |
| 2273 bool Extension::HasMultipleUISurfaces() const { | 1976 bool Extension::HasMultipleUISurfaces() const { |
| 2274 int num_surfaces = 0; | 1977 int num_surfaces = 0; |
| 2275 | 1978 |
| 2276 if (ActionInfo::GetPageActionInfo(this)) | 1979 if (ActionInfo::GetPageActionInfo(this)) |
| 2277 ++num_surfaces; | 1980 ++num_surfaces; |
| 2278 | 1981 |
| 2279 if (ActionInfo::GetBrowserActionInfo(this)) | 1982 if (ActionInfo::GetBrowserActionInfo(this)) |
| 2280 ++num_surfaces; | 1983 ++num_surfaces; |
| 2281 | 1984 |
| 2282 if (is_app()) | 1985 if (is_app()) |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2445 | 2148 |
| 2446 UpdatedExtensionPermissionsInfo::UpdatedExtensionPermissionsInfo( | 2149 UpdatedExtensionPermissionsInfo::UpdatedExtensionPermissionsInfo( |
| 2447 const Extension* extension, | 2150 const Extension* extension, |
| 2448 const PermissionSet* permissions, | 2151 const PermissionSet* permissions, |
| 2449 Reason reason) | 2152 Reason reason) |
| 2450 : reason(reason), | 2153 : reason(reason), |
| 2451 extension(extension), | 2154 extension(extension), |
| 2452 permissions(permissions) {} | 2155 permissions(permissions) {} |
| 2453 | 2156 |
| 2454 } // namespace extensions | 2157 } // namespace extensions |
| OLD | NEW |