| 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 "extensions/browser/api/web_request/web_request_api.h" | 5 #include "extensions/browser/api/web_request/web_request_api.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <memory> | 10 #include <memory> |
| (...skipping 1969 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1980 // We only check whether tokens are left here. Deducting a token happens in | 1980 // We only check whether tokens are left here. Deducting a token happens in |
| 1981 // OnPageLoad(). | 1981 // OnPageLoad(). |
| 1982 return bucket->has_tokens(); | 1982 return bucket->has_tokens(); |
| 1983 } | 1983 } |
| 1984 | 1984 |
| 1985 void ClearCacheQuotaHeuristic::OnPageLoad(Bucket* bucket) { | 1985 void ClearCacheQuotaHeuristic::OnPageLoad(Bucket* bucket) { |
| 1986 callback_registered_ = false; | 1986 callback_registered_ = false; |
| 1987 bucket->DeductToken(); | 1987 bucket->DeductToken(); |
| 1988 } | 1988 } |
| 1989 | 1989 |
| 1990 bool WebRequestInternalAddEventListenerFunction::RunSync() { | 1990 ExtensionFunction::ResponseAction |
| 1991 WebRequestInternalAddEventListenerFunction::Run() { |
| 1991 // Argument 0 is the callback, which we don't use here. | 1992 // Argument 0 is the callback, which we don't use here. |
| 1992 ExtensionWebRequestEventRouter::RequestFilter filter; | 1993 ExtensionWebRequestEventRouter::RequestFilter filter; |
| 1993 base::DictionaryValue* value = NULL; | 1994 base::DictionaryValue* value = NULL; |
| 1994 error_.clear(); | 1995 error_.clear(); |
| 1995 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &value)); | 1996 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &value)); |
| 1996 // Failure + an empty error string means a fatal error. | 1997 // Failure + an empty error string means a fatal error. |
| 1997 EXTENSION_FUNCTION_VALIDATE(filter.InitFromValue(*value, &error_) || | 1998 EXTENSION_FUNCTION_VALIDATE(filter.InitFromValue(*value, &error_) || |
| 1998 !error_.empty()); | 1999 !error_.empty()); |
| 1999 if (!error_.empty()) | 2000 if (!error_.empty()) |
| 2000 return false; | 2001 return RespondNow(Error(error_)); |
| 2001 | 2002 |
| 2002 int extra_info_spec = 0; | 2003 int extra_info_spec = 0; |
| 2003 if (HasOptionalArgument(2)) { | 2004 if (HasOptionalArgument(2)) { |
| 2004 base::ListValue* value = NULL; | 2005 base::ListValue* value = NULL; |
| 2005 EXTENSION_FUNCTION_VALIDATE(args_->GetList(2, &value)); | 2006 EXTENSION_FUNCTION_VALIDATE(args_->GetList(2, &value)); |
| 2006 EXTENSION_FUNCTION_VALIDATE( | 2007 EXTENSION_FUNCTION_VALIDATE( |
| 2007 ExtraInfoSpec::InitFromValue(*value, &extra_info_spec)); | 2008 ExtraInfoSpec::InitFromValue(*value, &extra_info_spec)); |
| 2008 } | 2009 } |
| 2009 | 2010 |
| 2010 std::string event_name; | 2011 std::string event_name; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2025 extension ? extension->name() : extension_id_safe(); | 2026 extension ? extension->name() : extension_id_safe(); |
| 2026 | 2027 |
| 2027 if (!web_view_instance_id) { | 2028 if (!web_view_instance_id) { |
| 2028 // We check automatically whether the extension has the 'webRequest' | 2029 // We check automatically whether the extension has the 'webRequest' |
| 2029 // permission. For blocking calls we require the additional permission | 2030 // permission. For blocking calls we require the additional permission |
| 2030 // 'webRequestBlocking'. | 2031 // 'webRequestBlocking'. |
| 2031 if ((extra_info_spec & | 2032 if ((extra_info_spec & |
| 2032 (ExtraInfoSpec::BLOCKING | ExtraInfoSpec::ASYNC_BLOCKING)) && | 2033 (ExtraInfoSpec::BLOCKING | ExtraInfoSpec::ASYNC_BLOCKING)) && |
| 2033 !extension->permissions_data()->HasAPIPermission( | 2034 !extension->permissions_data()->HasAPIPermission( |
| 2034 APIPermission::kWebRequestBlocking)) { | 2035 APIPermission::kWebRequestBlocking)) { |
| 2035 error_ = keys::kBlockingPermissionRequired; | 2036 return RespondNow(Error(keys::kBlockingPermissionRequired)); |
| 2036 return false; | |
| 2037 } | 2037 } |
| 2038 | 2038 |
| 2039 // We allow to subscribe to patterns that are broader than the host | 2039 // We allow to subscribe to patterns that are broader than the host |
| 2040 // permissions. E.g., we could subscribe to http://www.example.com/* | 2040 // permissions. E.g., we could subscribe to http://www.example.com/* |
| 2041 // while having host permissions for http://www.example.com/foo/* and | 2041 // while having host permissions for http://www.example.com/foo/* and |
| 2042 // http://www.example.com/bar/*. | 2042 // http://www.example.com/bar/*. |
| 2043 // For this reason we do only a coarse check here to warn the extension | 2043 // For this reason we do only a coarse check here to warn the extension |
| 2044 // developer if they do something obviously wrong. | 2044 // developer if they do something obviously wrong. |
| 2045 if (extension->permissions_data() | 2045 if (extension->permissions_data() |
| 2046 ->GetEffectiveHostPermissions() | 2046 ->GetEffectiveHostPermissions() |
| 2047 .is_empty() && | 2047 .is_empty() && |
| 2048 extension->permissions_data() | 2048 extension->permissions_data() |
| 2049 ->withheld_permissions() | 2049 ->withheld_permissions() |
| 2050 .explicit_hosts() | 2050 .explicit_hosts() |
| 2051 .is_empty()) { | 2051 .is_empty()) { |
| 2052 error_ = keys::kHostPermissionsRequired; | 2052 return RespondNow(Error(keys::kHostPermissionsRequired)); |
| 2053 return false; | |
| 2054 } | 2053 } |
| 2055 } | 2054 } |
| 2056 | 2055 |
| 2057 bool success = | 2056 bool success = |
| 2058 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener( | 2057 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener( |
| 2059 profile_id(), extension_id_safe(), extension_name, | 2058 profile_id(), extension_id_safe(), extension_name, |
| 2060 GetEventHistogramValue(event_name), event_name, sub_event_name, | 2059 GetEventHistogramValue(event_name), event_name, sub_event_name, |
| 2061 filter, extra_info_spec, embedder_process_id, web_view_instance_id, | 2060 filter, extra_info_spec, embedder_process_id, web_view_instance_id, |
| 2062 ipc_sender_weak()); | 2061 ipc_sender_weak()); |
| 2063 EXTENSION_FUNCTION_VALIDATE(success); | 2062 EXTENSION_FUNCTION_VALIDATE(success); |
| 2064 | 2063 |
| 2065 helpers::ClearCacheOnNavigation(); | 2064 helpers::ClearCacheOnNavigation(); |
| 2066 | 2065 |
| 2067 if (!extension_id_safe().empty()) { | 2066 if (!extension_id_safe().empty()) { |
| 2068 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 2067 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 2069 base::Bind(&helpers::NotifyWebRequestAPIUsed, | 2068 base::Bind(&helpers::NotifyWebRequestAPIUsed, |
| 2070 profile_id(), extension_id_safe())); | 2069 profile_id(), extension_id_safe())); |
| 2071 } | 2070 } |
| 2072 | 2071 |
| 2073 return true; | 2072 return RespondNow(NoArguments()); |
| 2074 } | 2073 } |
| 2075 | 2074 |
| 2076 void WebRequestInternalEventHandledFunction::RespondWithError( | 2075 void WebRequestInternalEventHandledFunction::OnError( |
| 2077 const std::string& event_name, | 2076 const std::string& event_name, |
| 2078 const std::string& sub_event_name, | 2077 const std::string& sub_event_name, |
| 2079 uint64_t request_id, | 2078 uint64_t request_id, |
| 2080 std::unique_ptr<ExtensionWebRequestEventRouter::EventResponse> response, | 2079 std::unique_ptr<ExtensionWebRequestEventRouter::EventResponse> response) { |
| 2081 const std::string& error) { | |
| 2082 error_ = error; | |
| 2083 ExtensionWebRequestEventRouter::GetInstance()->OnEventHandled( | 2080 ExtensionWebRequestEventRouter::GetInstance()->OnEventHandled( |
| 2084 profile_id(), | 2081 profile_id(), |
| 2085 extension_id_safe(), | 2082 extension_id_safe(), |
| 2086 event_name, | 2083 event_name, |
| 2087 sub_event_name, | 2084 sub_event_name, |
| 2088 request_id, | 2085 request_id, |
| 2089 response.release()); | 2086 response.release()); |
| 2090 } | 2087 } |
| 2091 | 2088 |
| 2092 bool WebRequestInternalEventHandledFunction::RunSync() { | 2089 ExtensionFunction::ResponseAction |
| 2090 WebRequestInternalEventHandledFunction::Run() { |
| 2093 std::string event_name; | 2091 std::string event_name; |
| 2094 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &event_name)); | 2092 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &event_name)); |
| 2095 | 2093 |
| 2096 std::string sub_event_name; | 2094 std::string sub_event_name; |
| 2097 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &sub_event_name)); | 2095 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &sub_event_name)); |
| 2098 | 2096 |
| 2099 std::string request_id_str; | 2097 std::string request_id_str; |
| 2100 EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &request_id_str)); | 2098 EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &request_id_str)); |
| 2101 uint64_t request_id; | 2099 uint64_t request_id; |
| 2102 EXTENSION_FUNCTION_VALIDATE(base::StringToUint64(request_id_str, | 2100 EXTENSION_FUNCTION_VALIDATE(base::StringToUint64(request_id_str, |
| 2103 &request_id)); | 2101 &request_id)); |
| 2104 | 2102 |
| 2105 std::unique_ptr<ExtensionWebRequestEventRouter::EventResponse> response; | 2103 std::unique_ptr<ExtensionWebRequestEventRouter::EventResponse> response; |
| 2106 if (HasOptionalArgument(3)) { | 2104 if (HasOptionalArgument(3)) { |
| 2107 base::DictionaryValue* value = NULL; | 2105 base::DictionaryValue* value = NULL; |
| 2108 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(3, &value)); | 2106 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(3, &value)); |
| 2109 | 2107 |
| 2110 if (!value->empty()) { | 2108 if (!value->empty()) { |
| 2111 base::Time install_time = | 2109 base::Time install_time = |
| 2112 extension_info_map()->GetInstallTime(extension_id_safe()); | 2110 extension_info_map()->GetInstallTime(extension_id_safe()); |
| 2113 response.reset(new ExtensionWebRequestEventRouter::EventResponse( | 2111 response.reset(new ExtensionWebRequestEventRouter::EventResponse( |
| 2114 extension_id_safe(), install_time)); | 2112 extension_id_safe(), install_time)); |
| 2115 } | 2113 } |
| 2116 | 2114 |
| 2117 if (value->HasKey("cancel")) { | 2115 if (value->HasKey("cancel")) { |
| 2118 // Don't allow cancel mixed with other keys. | 2116 // Don't allow cancel mixed with other keys. |
| 2119 if (value->size() != 1) { | 2117 if (value->size() != 1) { |
| 2120 RespondWithError(event_name, sub_event_name, request_id, | 2118 OnError(event_name, sub_event_name, request_id, std::move(response)); |
| 2121 std::move(response), keys::kInvalidBlockingResponse); | 2119 return RespondNow(Error(keys::kInvalidBlockingResponse)); |
| 2122 return false; | |
| 2123 } | 2120 } |
| 2124 | 2121 |
| 2125 bool cancel = false; | 2122 bool cancel = false; |
| 2126 EXTENSION_FUNCTION_VALIDATE(value->GetBoolean("cancel", &cancel)); | 2123 EXTENSION_FUNCTION_VALIDATE(value->GetBoolean("cancel", &cancel)); |
| 2127 response->cancel = cancel; | 2124 response->cancel = cancel; |
| 2128 } | 2125 } |
| 2129 | 2126 |
| 2130 if (value->HasKey("redirectUrl")) { | 2127 if (value->HasKey("redirectUrl")) { |
| 2131 std::string new_url_str; | 2128 std::string new_url_str; |
| 2132 EXTENSION_FUNCTION_VALIDATE(value->GetString("redirectUrl", | 2129 EXTENSION_FUNCTION_VALIDATE(value->GetString("redirectUrl", |
| 2133 &new_url_str)); | 2130 &new_url_str)); |
| 2134 response->new_url = GURL(new_url_str); | 2131 response->new_url = GURL(new_url_str); |
| 2135 if (!response->new_url.is_valid()) { | 2132 if (!response->new_url.is_valid()) { |
| 2136 RespondWithError(event_name, sub_event_name, request_id, | 2133 OnError(event_name, sub_event_name, request_id, std::move(response)); |
| 2137 std::move(response), | 2134 return RespondNow(Error(keys::kInvalidRedirectUrl, new_url_str)); |
| 2138 ErrorUtils::FormatErrorMessage( | |
| 2139 keys::kInvalidRedirectUrl, new_url_str)); | |
| 2140 return false; | |
| 2141 } | 2135 } |
| 2142 } | 2136 } |
| 2143 | 2137 |
| 2144 const bool has_request_headers = value->HasKey("requestHeaders"); | 2138 const bool has_request_headers = value->HasKey("requestHeaders"); |
| 2145 const bool has_response_headers = value->HasKey("responseHeaders"); | 2139 const bool has_response_headers = value->HasKey("responseHeaders"); |
| 2146 if (has_request_headers || has_response_headers) { | 2140 if (has_request_headers || has_response_headers) { |
| 2147 if (has_request_headers && has_response_headers) { | 2141 if (has_request_headers && has_response_headers) { |
| 2148 // Allow only one of the keys, not both. | 2142 // Allow only one of the keys, not both. |
| 2149 RespondWithError(event_name, sub_event_name, request_id, | 2143 OnError(event_name, sub_event_name, request_id, std::move(response)); |
| 2150 std::move(response), | 2144 return RespondNow(Error(keys::kInvalidHeaderKeyCombination)); |
| 2151 keys::kInvalidHeaderKeyCombination); | |
| 2152 return false; | |
| 2153 } | 2145 } |
| 2154 | 2146 |
| 2155 base::ListValue* headers_value = NULL; | 2147 base::ListValue* headers_value = NULL; |
| 2156 std::unique_ptr<net::HttpRequestHeaders> request_headers; | 2148 std::unique_ptr<net::HttpRequestHeaders> request_headers; |
| 2157 std::unique_ptr<helpers::ResponseHeaders> response_headers; | 2149 std::unique_ptr<helpers::ResponseHeaders> response_headers; |
| 2158 if (has_request_headers) { | 2150 if (has_request_headers) { |
| 2159 request_headers.reset(new net::HttpRequestHeaders()); | 2151 request_headers.reset(new net::HttpRequestHeaders()); |
| 2160 EXTENSION_FUNCTION_VALIDATE(value->GetList(keys::kRequestHeadersKey, | 2152 EXTENSION_FUNCTION_VALIDATE(value->GetList(keys::kRequestHeadersKey, |
| 2161 &headers_value)); | 2153 &headers_value)); |
| 2162 } else { | 2154 } else { |
| 2163 response_headers.reset(new helpers::ResponseHeaders()); | 2155 response_headers.reset(new helpers::ResponseHeaders()); |
| 2164 EXTENSION_FUNCTION_VALIDATE(value->GetList(keys::kResponseHeadersKey, | 2156 EXTENSION_FUNCTION_VALIDATE(value->GetList(keys::kResponseHeadersKey, |
| 2165 &headers_value)); | 2157 &headers_value)); |
| 2166 } | 2158 } |
| 2167 | 2159 |
| 2168 for (size_t i = 0; i < headers_value->GetSize(); ++i) { | 2160 for (size_t i = 0; i < headers_value->GetSize(); ++i) { |
| 2169 base::DictionaryValue* header_value = NULL; | 2161 base::DictionaryValue* header_value = NULL; |
| 2170 std::string name; | 2162 std::string name; |
| 2171 std::string value; | 2163 std::string value; |
| 2172 EXTENSION_FUNCTION_VALIDATE( | 2164 EXTENSION_FUNCTION_VALIDATE( |
| 2173 headers_value->GetDictionary(i, &header_value)); | 2165 headers_value->GetDictionary(i, &header_value)); |
| 2174 if (!FromHeaderDictionary(header_value, &name, &value)) { | 2166 if (!FromHeaderDictionary(header_value, &name, &value)) { |
| 2175 std::string serialized_header; | 2167 std::string serialized_header; |
| 2176 base::JSONWriter::Write(*header_value, &serialized_header); | 2168 base::JSONWriter::Write(*header_value, &serialized_header); |
| 2177 RespondWithError(event_name, sub_event_name, request_id, | 2169 OnError(event_name, sub_event_name, request_id, std::move(response)); |
| 2178 std::move(response), | 2170 return RespondNow(Error(keys::kInvalidHeader, serialized_header)); |
| 2179 ErrorUtils::FormatErrorMessage(keys::kInvalidHeader, | |
| 2180 serialized_header)); | |
| 2181 return false; | |
| 2182 } | 2171 } |
| 2183 if (!net::HttpUtil::IsValidHeaderName(name)) { | 2172 if (!net::HttpUtil::IsValidHeaderName(name)) { |
| 2184 RespondWithError(event_name, sub_event_name, request_id, | 2173 OnError(event_name, sub_event_name, request_id, std::move(response)); |
| 2185 std::move(response), keys::kInvalidHeaderName); | 2174 return RespondNow(Error(keys::kInvalidHeaderName)); |
| 2186 return false; | |
| 2187 } | 2175 } |
| 2188 if (!net::HttpUtil::IsValidHeaderValue(value)) { | 2176 if (!net::HttpUtil::IsValidHeaderValue(value)) { |
| 2189 RespondWithError( | 2177 OnError(event_name, sub_event_name, request_id, std::move(response)); |
| 2190 event_name, sub_event_name, request_id, std::move(response), | 2178 return RespondNow(Error(keys::kInvalidHeaderValue, name)); |
| 2191 ErrorUtils::FormatErrorMessage(keys::kInvalidHeaderValue, name)); | |
| 2192 return false; | |
| 2193 } | 2179 } |
| 2194 if (has_request_headers) | 2180 if (has_request_headers) |
| 2195 request_headers->SetHeader(name, value); | 2181 request_headers->SetHeader(name, value); |
| 2196 else | 2182 else |
| 2197 response_headers->push_back(helpers::ResponseHeader(name, value)); | 2183 response_headers->push_back(helpers::ResponseHeader(name, value)); |
| 2198 } | 2184 } |
| 2199 if (has_request_headers) | 2185 if (has_request_headers) |
| 2200 response->request_headers.reset(request_headers.release()); | 2186 response->request_headers.reset(request_headers.release()); |
| 2201 else | 2187 else |
| 2202 response->response_headers.reset(response_headers.release()); | 2188 response->response_headers.reset(response_headers.release()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2215 credentials_value->GetString(keys::kPasswordKey, &password)); | 2201 credentials_value->GetString(keys::kPasswordKey, &password)); |
| 2216 response->auth_credentials.reset( | 2202 response->auth_credentials.reset( |
| 2217 new net::AuthCredentials(username, password)); | 2203 new net::AuthCredentials(username, password)); |
| 2218 } | 2204 } |
| 2219 } | 2205 } |
| 2220 | 2206 |
| 2221 ExtensionWebRequestEventRouter::GetInstance()->OnEventHandled( | 2207 ExtensionWebRequestEventRouter::GetInstance()->OnEventHandled( |
| 2222 profile_id(), extension_id_safe(), event_name, sub_event_name, request_id, | 2208 profile_id(), extension_id_safe(), event_name, sub_event_name, request_id, |
| 2223 response.release()); | 2209 response.release()); |
| 2224 | 2210 |
| 2225 return true; | 2211 return RespondNow(NoArguments()); |
| 2226 } | 2212 } |
| 2227 | 2213 |
| 2228 void WebRequestHandlerBehaviorChangedFunction::GetQuotaLimitHeuristics( | 2214 void WebRequestHandlerBehaviorChangedFunction::GetQuotaLimitHeuristics( |
| 2229 QuotaLimitHeuristics* heuristics) const { | 2215 QuotaLimitHeuristics* heuristics) const { |
| 2230 QuotaLimitHeuristic::Config config = { | 2216 QuotaLimitHeuristic::Config config = { |
| 2231 // See web_request.json for current value. | 2217 // See web_request.json for current value. |
| 2232 web_request::MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES, | 2218 web_request::MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES, |
| 2233 base::TimeDelta::FromMinutes(10)}; | 2219 base::TimeDelta::FromMinutes(10)}; |
| 2234 QuotaLimitHeuristic::BucketMapper* bucket_mapper = | 2220 QuotaLimitHeuristic::BucketMapper* bucket_mapper = |
| 2235 new QuotaLimitHeuristic::SingletonBucketMapper(); | 2221 new QuotaLimitHeuristic::SingletonBucketMapper(); |
| 2236 ClearCacheQuotaHeuristic* heuristic = | 2222 ClearCacheQuotaHeuristic* heuristic = |
| 2237 new ClearCacheQuotaHeuristic(config, bucket_mapper); | 2223 new ClearCacheQuotaHeuristic(config, bucket_mapper); |
| 2238 heuristics->push_back(heuristic); | 2224 heuristics->push_back(heuristic); |
| 2239 } | 2225 } |
| 2240 | 2226 |
| 2241 void WebRequestHandlerBehaviorChangedFunction::OnQuotaExceeded( | 2227 void WebRequestHandlerBehaviorChangedFunction::OnQuotaExceeded( |
| 2242 const std::string& violation_error) { | 2228 const std::string& violation_error) { |
| 2243 // Post warning message. | 2229 // Post warning message. |
| 2244 WarningSet warnings; | 2230 WarningSet warnings; |
| 2245 warnings.insert( | 2231 warnings.insert( |
| 2246 Warning::CreateRepeatedCacheFlushesWarning(extension_id_safe())); | 2232 Warning::CreateRepeatedCacheFlushesWarning(extension_id_safe())); |
| 2247 BrowserThread::PostTask( | 2233 BrowserThread::PostTask( |
| 2248 BrowserThread::UI, | 2234 BrowserThread::UI, |
| 2249 FROM_HERE, | 2235 FROM_HERE, |
| 2250 base::Bind(&WarningService::NotifyWarningsOnUI, profile_id(), warnings)); | 2236 base::Bind(&WarningService::NotifyWarningsOnUI, profile_id(), warnings)); |
| 2251 | 2237 |
| 2252 // Continue gracefully. | 2238 // Continue gracefully. |
| 2253 RunSync(); | 2239 RunWithValidation()->Execute(); |
| 2254 } | 2240 } |
| 2255 | 2241 |
| 2256 bool WebRequestHandlerBehaviorChangedFunction::RunSync() { | 2242 ExtensionFunction::ResponseAction |
| 2243 WebRequestHandlerBehaviorChangedFunction::Run() { |
| 2257 helpers::ClearCacheOnNavigation(); | 2244 helpers::ClearCacheOnNavigation(); |
| 2258 return true; | 2245 return RespondNow(NoArguments()); |
| 2259 } | 2246 } |
| 2260 | 2247 |
| 2261 } // namespace extensions | 2248 } // namespace extensions |
| OLD | NEW |