Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(176)

Side by Side Diff: chrome/browser/extensions/api/web_request/web_request_api.cc

Issue 12189018: <webview>: Implement WebRequest API (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Diff from latest patch Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 "chrome/browser/extensions/api/web_request/web_request_api.h" 5 #include "chrome/browser/extensions/api/web_request/web_request_api.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 using extensions::Feature; 73 using extensions::Feature;
74 using extensions::web_navigation_api_helpers::GetFrameId; 74 using extensions::web_navigation_api_helpers::GetFrameId;
75 75
76 namespace helpers = extension_web_request_api_helpers; 76 namespace helpers = extension_web_request_api_helpers;
77 namespace keys = extension_web_request_api_constants; 77 namespace keys = extension_web_request_api_constants;
78 namespace web_request = extensions::api::web_request; 78 namespace web_request = extensions::api::web_request;
79 namespace declarative_keys = extensions::declarative_webrequest_constants; 79 namespace declarative_keys = extensions::declarative_webrequest_constants;
80 80
81 namespace { 81 namespace {
82 82
83 const char kWebRequest[] = "webRequest";
84 const char kWebView[] = "webview";
85
83 // List of all the webRequest events. 86 // List of all the webRequest events.
84 const char* const kWebRequestEvents[] = { 87 const char* const kWebRequestEvents[] = {
85 keys::kOnBeforeRedirectEvent, 88 keys::kOnBeforeRedirectEvent,
86 keys::kOnBeforeRequestEvent, 89 keys::kOnBeforeRequestEvent,
87 keys::kOnBeforeSendHeadersEvent, 90 keys::kOnBeforeSendHeadersEvent,
88 keys::kOnCompletedEvent, 91 keys::kOnCompletedEvent,
89 keys::kOnErrorOccurredEvent, 92 keys::kOnErrorOccurredEvent,
90 keys::kOnSendHeadersEvent, 93 keys::kOnSendHeadersEvent,
91 keys::kOnAuthRequiredEvent, 94 keys::kOnAuthRequiredEvent,
92 keys::kOnResponseStartedEvent, 95 keys::kOnResponseStartedEvent,
(...skipping 24 matching lines...) Expand all
117 case ExtensionWebRequestEventRouter::kOnErrorOccurred: 120 case ExtensionWebRequestEventRouter::kOnErrorOccurred:
118 return keys::kOnErrorOccurred; 121 return keys::kOnErrorOccurred;
119 case ExtensionWebRequestEventRouter::kOnCompleted: 122 case ExtensionWebRequestEventRouter::kOnCompleted:
120 return keys::kOnCompleted; 123 return keys::kOnCompleted;
121 } 124 }
122 NOTREACHED(); 125 NOTREACHED();
123 return "Not reached"; 126 return "Not reached";
124 } 127 }
125 128
126 bool IsWebRequestEvent(const std::string& event_name) { 129 bool IsWebRequestEvent(const std::string& event_name) {
130 std::string web_request_event_name(event_name);
131 if (web_request_event_name.find(kWebView) != std::string::npos)
132 web_request_event_name.replace(0, sizeof(kWebView) - 1, kWebRequest);
127 return std::find(kWebRequestEvents, ARRAYEND(kWebRequestEvents), 133 return std::find(kWebRequestEvents, ARRAYEND(kWebRequestEvents),
128 event_name) != ARRAYEND(kWebRequestEvents); 134 web_request_event_name) != ARRAYEND(kWebRequestEvents);
129 } 135 }
130 136
131 // Returns whether |request| has been triggered by an extension in 137 // Returns whether |request| has been triggered by an extension in
132 // |extension_info_map|. 138 // |extension_info_map|.
133 bool IsRequestFromExtension(const net::URLRequest* request, 139 bool IsRequestFromExtension(const net::URLRequest* request,
134 const ExtensionInfoMap* extension_info_map) { 140 const ExtensionInfoMap* extension_info_map) {
135 // |extension_info_map| is NULL for system-level requests. 141 // |extension_info_map| is NULL for system-level requests.
136 if (!extension_info_map) 142 if (!extension_info_map)
137 return false; 143 return false;
138 144
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 374
369 // Represents a single unique listener to an event, along with whatever filter 375 // Represents a single unique listener to an event, along with whatever filter
370 // parameters and extra_info_spec were specified at the time the listener was 376 // parameters and extra_info_spec were specified at the time the listener was
371 // added. 377 // added.
372 struct ExtensionWebRequestEventRouter::EventListener { 378 struct ExtensionWebRequestEventRouter::EventListener {
373 std::string extension_id; 379 std::string extension_id;
374 std::string extension_name; 380 std::string extension_name;
375 std::string sub_event_name; 381 std::string sub_event_name;
376 RequestFilter filter; 382 RequestFilter filter;
377 int extra_info_spec; 383 int extra_info_spec;
378 int target_process_id; 384 int caller_process_id;
Matt Perry 2013/02/06 22:40:24 nit: embedder_process_id
Fady Samuel 2013/05/15 21:58:53 Done.
379 int target_route_id; 385 int caller_routing_id;
386 int web_view_instance_id;
380 base::WeakPtr<IPC::Sender> ipc_sender; 387 base::WeakPtr<IPC::Sender> ipc_sender;
381 mutable std::set<uint64> blocked_requests; 388 mutable std::set<uint64> blocked_requests;
382 389
383 // Comparator to work with std::set. 390 // Comparator to work with std::set.
384 bool operator<(const EventListener& that) const { 391 bool operator<(const EventListener& that) const {
385 if (extension_id < that.extension_id) 392 if (extension_id < that.extension_id)
386 return true; 393 return true;
387 if (extension_id == that.extension_id && 394 if (extension_id == that.extension_id &&
388 sub_event_name < that.sub_event_name) 395 sub_event_name < that.sub_event_name)
389 return true; 396 return true;
(...skipping 740 matching lines...) Expand 10 before | Expand all | Expand 10 after
1130 } 1137 }
1131 1138
1132 bool ExtensionWebRequestEventRouter::AddEventListener( 1139 bool ExtensionWebRequestEventRouter::AddEventListener(
1133 void* profile, 1140 void* profile,
1134 const std::string& extension_id, 1141 const std::string& extension_id,
1135 const std::string& extension_name, 1142 const std::string& extension_name,
1136 const std::string& event_name, 1143 const std::string& event_name,
1137 const std::string& sub_event_name, 1144 const std::string& sub_event_name,
1138 const RequestFilter& filter, 1145 const RequestFilter& filter,
1139 int extra_info_spec, 1146 int extra_info_spec,
1140 int target_process_id, 1147 int caller_process_id,
1141 int target_route_id, 1148 int caller_routing_id,
1149 int web_view_instance_id,
1142 base::WeakPtr<IPC::Sender> ipc_sender) { 1150 base::WeakPtr<IPC::Sender> ipc_sender) {
1151
1143 if (!IsWebRequestEvent(event_name)) 1152 if (!IsWebRequestEvent(event_name))
1144 return false; 1153 return false;
1145 1154
1146 EventListener listener; 1155 EventListener listener;
1147 listener.extension_id = extension_id; 1156 listener.extension_id = extension_id;
1148 listener.extension_name = extension_name; 1157 listener.extension_name = extension_name;
1149 listener.sub_event_name = sub_event_name; 1158 listener.sub_event_name = sub_event_name;
1150 listener.filter = filter; 1159 listener.filter = filter;
1151 listener.extra_info_spec = extra_info_spec; 1160 listener.extra_info_spec = extra_info_spec;
1152 listener.ipc_sender = ipc_sender; 1161 listener.ipc_sender = ipc_sender;
1153 listener.target_process_id = target_process_id; 1162 listener.caller_process_id = caller_process_id;
1154 listener.target_route_id = target_route_id; 1163 listener.caller_routing_id = caller_routing_id;
1164 listener.web_view_instance_id = web_view_instance_id;
1155 1165
1156 if (listeners_[profile][event_name].count(listener) != 0u) { 1166 if (listeners_[profile][event_name].count(listener) != 0u) {
1157 // This is likely an abuse of the API by a malicious extension. 1167 // This is likely an abuse of the API by a malicious extension.
1158 return false; 1168 return false;
1159 } 1169 }
1160 listeners_[profile][event_name].insert(listener); 1170 listeners_[profile][event_name].insert(listener);
1161 return true; 1171 return true;
1162 } 1172 }
1163 1173
1164 void ExtensionWebRequestEventRouter::RemoveEventListener( 1174 void ExtensionWebRequestEventRouter::RemoveEventListener(
(...skipping 25 matching lines...) Expand all
1190 for (std::set<uint64>::iterator it = found->blocked_requests.begin(); 1200 for (std::set<uint64>::iterator it = found->blocked_requests.begin();
1191 it != found->blocked_requests.end(); ++it) { 1201 it != found->blocked_requests.end(); ++it) {
1192 DecrementBlockCount(profile, extension_id, event_name, *it, NULL); 1202 DecrementBlockCount(profile, extension_id, event_name, *it, NULL);
1193 } 1203 }
1194 1204
1195 listeners_[profile][event_name].erase(listener); 1205 listeners_[profile][event_name].erase(listener);
1196 1206
1197 helpers::ClearCacheOnNavigation(); 1207 helpers::ClearCacheOnNavigation();
1198 } 1208 }
1199 1209
1210 void ExtensionWebRequestEventRouter::RemoveWebViewEventListeners(
Matt Perry 2013/02/06 22:40:24 Are you sure this is necessary? When a context goe
Fady Samuel 2013/05/15 21:58:53 Yes, this is necessary because the listeners a <we
Matt Perry 2013/05/16 21:16:38 I don't understand what you mean. To clarify my c
1211 void* profile,
1212 const std::string& extension_id,
1213 int embedder_process_id,
1214 int embedder_routing_id,
1215 int web_view_instance_id) {
1216 // Iterate over all listeners of all WebRequest events to delete
1217 // any listeners that belong to the provided <webview>.
1218 bool found_listeners = false;
1219 ListenerMapForProfile& map_for_profile = listeners_[profile];
1220 for (ListenerMapForProfile::iterator event_iter = map_for_profile.begin();
1221 event_iter != map_for_profile.end(); ++event_iter) {
1222 std::vector<EventListener> listeners_to_delete;
1223 const std::string& event_name = event_iter->first;
1224 std::set<EventListener>& listeners = event_iter->second;
1225 for (std::set<EventListener>::iterator listener_iter = listeners.begin();
1226 listener_iter != listeners.end(); ++listener_iter) {
1227 const EventListener& listener = *listener_iter;
1228 if (listener.caller_process_id == embedder_process_id &&
1229 listener.caller_routing_id == embedder_routing_id &&
1230 listener.web_view_instance_id == web_view_instance_id)
1231 listeners_to_delete.push_back(listener);
1232 }
1233 for (size_t i = 0; i < listeners_to_delete.size(); ++i) {
1234 found_listeners = true;
1235 EventListener& listener = listeners_to_delete[i];
1236 listeners.erase(listeners_to_delete[i]);
1237 // Unblock any request that this event listener may have been blocking.
1238 for (std::set<uint64>::iterator it = listener.blocked_requests.begin();
1239 it != listener.blocked_requests.end(); ++it) {
1240 DecrementBlockCount(profile, extension_id, event_name, *it, NULL);
1241 }
1242 }
1243 }
1244 if (found_listeners)
1245 helpers::ClearCacheOnNavigation();
1246 }
1247
1200 void ExtensionWebRequestEventRouter::OnOTRProfileCreated( 1248 void ExtensionWebRequestEventRouter::OnOTRProfileCreated(
1201 void* original_profile, void* otr_profile) { 1249 void* original_profile, void* otr_profile) {
1202 cross_profile_map_[original_profile] = otr_profile; 1250 cross_profile_map_[original_profile] = otr_profile;
1203 cross_profile_map_[otr_profile] = original_profile; 1251 cross_profile_map_[otr_profile] = original_profile;
1204 } 1252 }
1205 1253
1206 void ExtensionWebRequestEventRouter::OnOTRProfileDestroyed( 1254 void ExtensionWebRequestEventRouter::OnOTRProfileDestroyed(
1207 void* original_profile, void* otr_profile) { 1255 void* original_profile, void* otr_profile) {
1208 cross_profile_map_.erase(otr_profile); 1256 cross_profile_map_.erase(otr_profile);
1209 cross_profile_map_.erase(original_profile); 1257 cross_profile_map_.erase(original_profile);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1267 int tab_id, 1315 int tab_id,
1268 int window_id, 1316 int window_id,
1269 int render_process_host_id, 1317 int render_process_host_id,
1270 int routing_id, 1318 int routing_id,
1271 ResourceType::Type resource_type, 1319 ResourceType::Type resource_type,
1272 bool is_async_request, 1320 bool is_async_request,
1273 bool is_request_from_extension, 1321 bool is_request_from_extension,
1274 int* extra_info_spec, 1322 int* extra_info_spec,
1275 std::vector<const ExtensionWebRequestEventRouter::EventListener*>* 1323 std::vector<const ExtensionWebRequestEventRouter::EventListener*>*
1276 matching_listeners) { 1324 matching_listeners) {
1325 std::string web_request_event_name(event_name);
1277 ExtensionRendererState::WebViewInfo web_view_info; 1326 ExtensionRendererState::WebViewInfo web_view_info;
1278 bool is_guest = ExtensionRendererState::GetInstance()-> 1327 bool is_guest = ExtensionRendererState::GetInstance()->
1279 GetWebViewInfo(render_process_host_id, routing_id, &web_view_info); 1328 GetWebViewInfo(render_process_host_id, routing_id, &web_view_info);
1280 std::set<EventListener>& listeners = listeners_[profile][event_name]; 1329 if (is_guest)
1330 web_request_event_name.replace(0, sizeof(kWebRequest) - 1, kWebView);
1331
1332 std::set<EventListener>& listeners =
1333 listeners_[profile][web_request_event_name];
1281 for (std::set<EventListener>::iterator it = listeners.begin(); 1334 for (std::set<EventListener>::iterator it = listeners.begin();
1282 it != listeners.end(); ++it) { 1335 it != listeners.end(); ++it) {
1283 if (!it->ipc_sender.get()) { 1336 if (!it->ipc_sender.get()) {
1284 // The IPC sender has been deleted. This listener will be removed soon 1337 // The IPC sender has been deleted. This listener will be removed soon
1285 // via a call to RemoveEventListener. For now, just skip it. 1338 // via a call to RemoveEventListener. For now, just skip it.
1286 continue; 1339 continue;
1287 } 1340 }
1288 1341
1289 if (is_guest && (it->target_process_id != render_process_host_id|| 1342 if (is_guest &&
1290 it->target_route_id != routing_id)) 1343 (it->caller_process_id != web_view_info.embedder_process_id ||
1344 it->caller_routing_id != web_view_info.embedder_routing_id ||
1345 it->web_view_instance_id != web_view_info.web_view_instance_id))
1291 continue; 1346 continue;
1292 1347
1293 if (!it->filter.urls.is_empty() && !it->filter.urls.MatchesURL(url)) 1348 if (!it->filter.urls.is_empty() && !it->filter.urls.MatchesURL(url))
1294 continue; 1349 continue;
1295 if (it->filter.tab_id != -1 && tab_id != it->filter.tab_id) 1350 if (it->filter.tab_id != -1 && tab_id != it->filter.tab_id)
1296 continue; 1351 continue;
1297 if (it->filter.window_id != -1 && window_id != it->filter.window_id) 1352 if (it->filter.window_id != -1 && window_id != it->filter.window_id)
1298 continue; 1353 continue;
1299 if (!it->filter.types.empty() && 1354 if (!it->filter.types.empty() &&
1300 std::find(it->filter.types.begin(), it->filter.types.end(), 1355 std::find(it->filter.types.begin(), it->filter.types.end(),
1301 resource_type) == it->filter.types.end()) 1356 resource_type) == it->filter.types.end())
1302 continue; 1357 continue;
1303 1358
1304 if (!WebRequestPermissions::CanExtensionAccessURL( 1359 if (!is_guest && !WebRequestPermissions::CanExtensionAccessURL(
1305 extension_info_map, it->extension_id, url, crosses_incognito, true)) 1360 extension_info_map, it->extension_id, url, crosses_incognito, true))
1306 continue; 1361 continue;
1307 1362
1308 bool blocking_listener = 1363 bool blocking_listener =
1309 (it->extra_info_spec & 1364 (it->extra_info_spec &
1310 (ExtraInfoSpec::BLOCKING | ExtraInfoSpec::ASYNC_BLOCKING)) != 0; 1365 (ExtraInfoSpec::BLOCKING | ExtraInfoSpec::ASYNC_BLOCKING)) != 0;
1311 1366
1312 // We do not want to notify extensions about XHR requests that are 1367 // We do not want to notify extensions about XHR requests that are
1313 // triggered by themselves. This is a workaround to prevent deadlocks 1368 // triggered by themselves. This is a workaround to prevent deadlocks
1314 // in case of synchronous XHR requests that block the extension renderer 1369 // in case of synchronous XHR requests that block the extension renderer
(...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after
1819 ExtensionWebRequestEventRouter::ExtraInfoSpec::InitFromValue( 1874 ExtensionWebRequestEventRouter::ExtraInfoSpec::InitFromValue(
1820 *value, &extra_info_spec)); 1875 *value, &extra_info_spec));
1821 } 1876 }
1822 1877
1823 std::string event_name; 1878 std::string event_name;
1824 EXTENSION_FUNCTION_VALIDATE(args_->GetString(3, &event_name)); 1879 EXTENSION_FUNCTION_VALIDATE(args_->GetString(3, &event_name));
1825 1880
1826 std::string sub_event_name; 1881 std::string sub_event_name;
1827 EXTENSION_FUNCTION_VALIDATE(args_->GetString(4, &sub_event_name)); 1882 EXTENSION_FUNCTION_VALIDATE(args_->GetString(4, &sub_event_name));
1828 1883
1884 int web_view_instance_id = 0;
1885 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(5, &web_view_instance_id));
1886
1887 int caller_process_id = ipc_sender()->render_process_id();
1888 int caller_routing_id = routing_id();
1889
1829 const Extension* extension = 1890 const Extension* extension =
1830 extension_info_map()->extensions().GetByID(extension_id()); 1891 extension_info_map()->extensions().GetByID(extension_id());
1831 std::string extension_name = extension ? extension->name() : extension_id(); 1892 std::string extension_name = extension ? extension->name() : extension_id();
1832 1893
1894 bool is_guest = web_view_instance_id != 0;
1833 // We check automatically whether the extension has the 'webRequest' 1895 // We check automatically whether the extension has the 'webRequest'
1834 // permission. For blocking calls we require the additional permission 1896 // permission. For blocking calls we require the additional permission
1835 // 'webRequestBlocking'. 1897 // 'webRequestBlocking'.
1836 if ((extra_info_spec & 1898 if ((!is_guest && extra_info_spec &
1837 (ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING | 1899 (ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING |
1838 ExtensionWebRequestEventRouter::ExtraInfoSpec::ASYNC_BLOCKING)) && 1900 ExtensionWebRequestEventRouter::ExtraInfoSpec::ASYNC_BLOCKING)) &&
1839 !extension->HasAPIPermission( 1901 !extension->HasAPIPermission(
1840 extensions::APIPermission::kWebRequestBlocking)) { 1902 extensions::APIPermission::kWebRequestBlocking)) {
1841 error_ = keys::kBlockingPermissionRequired; 1903 error_ = keys::kBlockingPermissionRequired;
1842 return false; 1904 return false;
1843 } 1905 }
1844 1906
1845 // We allow to subscribe to patterns that are broader than the host 1907 // We allow to subscribe to patterns that are broader than the host
1846 // permissions. E.g., we could subscribe to http://www.example.com/* 1908 // permissions. E.g., we could subscribe to http://www.example.com/*
1847 // while having host permissions for http://www.example.com/foo/* and 1909 // while having host permissions for http://www.example.com/foo/* and
1848 // http://www.example.com/bar/*. 1910 // http://www.example.com/bar/*.
1849 // For this reason we do only a coarse check here to warn the extension 1911 // For this reason we do only a coarse check here to warn the extension
1850 // developer if he does something obviously wrong. 1912 // developer if he does something obviously wrong.
1851 if (extension->GetEffectiveHostPermissions().is_empty()) { 1913 if (!is_guest && extension->GetEffectiveHostPermissions().is_empty()) {
1852 error_ = keys::kHostPermissionsRequired; 1914 error_ = keys::kHostPermissionsRequired;
1853 return false; 1915 return false;
1854 } 1916 }
1855 1917
1856 bool success = 1918 bool success =
1857 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener( 1919 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
1858 profile_id(), extension_id(), extension_name, 1920 profile_id(), extension_id(), extension_name,
1859 event_name, sub_event_name, filter, 1921 event_name, sub_event_name, filter, extra_info_spec,
1860 extra_info_spec, -1, -1, ipc_sender_weak()); 1922 caller_process_id, caller_routing_id, web_view_instance_id,
1923 ipc_sender_weak());
1861 EXTENSION_FUNCTION_VALIDATE(success); 1924 EXTENSION_FUNCTION_VALIDATE(success);
1862 1925
1863 helpers::ClearCacheOnNavigation(); 1926 helpers::ClearCacheOnNavigation();
1864 1927
1865 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( 1928 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
1866 &NotifyWebRequestAPIUsed, 1929 &NotifyWebRequestAPIUsed,
1867 profile_id(), make_scoped_refptr(GetExtension()))); 1930 profile_id(), make_scoped_refptr(GetExtension())));
1868 1931
1869 return true; 1932 return true;
1870 } 1933 }
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
2030 } else if ((*it)->name().find("AdBlock") != std::string::npos) { 2093 } else if ((*it)->name().find("AdBlock") != std::string::npos) {
2031 adblock = true; 2094 adblock = true;
2032 } else { 2095 } else {
2033 other = true; 2096 other = true;
2034 } 2097 }
2035 } 2098 }
2036 } 2099 }
2037 2100
2038 host->Send(new ExtensionMsg_UsingWebRequestAPI(adblock, adblock_plus, other)); 2101 host->Send(new ExtensionMsg_UsingWebRequestAPI(adblock, adblock_plus, other));
2039 } 2102 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698