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/browser/extensions/extension_webrequest_api.h" | 5 #include "chrome/browser/extensions/extension_webrequest_api.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/json/json_writer.h" | 9 #include "base/json/json_writer.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 net::CompletionCallback* callback; | 296 net::CompletionCallback* callback; |
297 | 297 |
298 // If non-empty, this contains the new URL that the request will redirect to. | 298 // If non-empty, this contains the new URL that the request will redirect to. |
299 // Only valid for OnBeforeRequest. | 299 // Only valid for OnBeforeRequest. |
300 GURL* new_url; | 300 GURL* new_url; |
301 | 301 |
302 // The request headers that will be issued along with this request. Only valid | 302 // The request headers that will be issued along with this request. Only valid |
303 // for OnBeforeSendHeaders. | 303 // for OnBeforeSendHeaders. |
304 net::HttpRequestHeaders* request_headers; | 304 net::HttpRequestHeaders* request_headers; |
305 | 305 |
| 306 // If non-empty, this contains the auth credentials that may be filled in. |
| 307 // Only valid for OnAuthRequired. |
| 308 net::AuthCredentials* auth_credentials; |
| 309 |
306 // Time the request was paused. Used for logging purposes. | 310 // Time the request was paused. Used for logging purposes. |
307 base::Time blocking_time; | 311 base::Time blocking_time; |
308 | 312 |
309 // Changes requested by extensions. | 313 // Changes requested by extensions. |
310 EventResponseDeltas response_deltas; | 314 EventResponseDeltas response_deltas; |
311 | 315 |
312 BlockedRequest() | 316 BlockedRequest() |
313 : request(NULL), | 317 : request(NULL), |
314 event(kInvalidEvent), | 318 event(kInvalidEvent), |
315 num_handlers_blocking(0), | 319 num_handlers_blocking(0), |
316 net_log(NULL), | 320 net_log(NULL), |
317 callback(NULL), | 321 callback(NULL), |
318 new_url(NULL), | 322 new_url(NULL), |
319 request_headers(NULL) {} | 323 request_headers(NULL), |
| 324 auth_credentials(NULL) {} |
320 }; | 325 }; |
321 | 326 |
322 bool ExtensionWebRequestEventRouter::RequestFilter::InitFromValue( | 327 bool ExtensionWebRequestEventRouter::RequestFilter::InitFromValue( |
323 const DictionaryValue& value, std::string* error) { | 328 const DictionaryValue& value, std::string* error) { |
324 for (DictionaryValue::key_iterator key = value.begin_keys(); | 329 for (DictionaryValue::key_iterator key = value.begin_keys(); |
325 key != value.end_keys(); ++key) { | 330 key != value.end_keys(); ++key) { |
326 if (*key == "urls") { | 331 if (*key == "urls") { |
327 ListValue* urls_value = NULL; | 332 ListValue* urls_value = NULL; |
328 if (!value.GetList("urls", &urls_value)) | 333 if (!value.GetList("urls", &urls_value)) |
329 return false; | 334 return false; |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
578 dict->SetString(keys::kUrlKey, request->url().spec()); | 583 dict->SetString(keys::kUrlKey, request->url().spec()); |
579 dict->SetDouble(keys::kTimeStampKey, time.ToDoubleT() * 1000); | 584 dict->SetDouble(keys::kTimeStampKey, time.ToDoubleT() * 1000); |
580 if (extra_info_spec & ExtraInfoSpec::REQUEST_HEADERS) | 585 if (extra_info_spec & ExtraInfoSpec::REQUEST_HEADERS) |
581 dict->Set(keys::kRequestHeadersKey, GetRequestHeadersList(headers)); | 586 dict->Set(keys::kRequestHeadersKey, GetRequestHeadersList(headers)); |
582 // TODO(battre): support "request line". | 587 // TODO(battre): support "request line". |
583 args.Append(dict); | 588 args.Append(dict); |
584 | 589 |
585 DispatchEvent(profile, request, listeners, args); | 590 DispatchEvent(profile, request, listeners, args); |
586 } | 591 } |
587 | 592 |
588 void ExtensionWebRequestEventRouter::OnAuthRequired( | 593 int ExtensionWebRequestEventRouter::OnAuthRequired( |
589 void* profile, | 594 void* profile, |
590 ExtensionInfoMap* extension_info_map, | 595 ExtensionInfoMap* extension_info_map, |
591 net::URLRequest* request, | 596 net::URLRequest* request, |
592 const net::AuthChallengeInfo& auth_info) { | 597 const net::AuthChallengeInfo& auth_info, |
| 598 net::CompletionCallback* callback, |
| 599 net::AuthCredentials* credentials) { |
| 600 // No profile means that this is for authentication challenges in the |
| 601 // system context. Skip in that case. |
593 if (!profile) | 602 if (!profile) |
594 return; | 603 return net::OK; |
595 | 604 |
596 base::Time time(base::Time::Now()); | 605 base::Time time(base::Time::Now()); |
597 | 606 |
598 if (!HasWebRequestScheme(request->url())) | 607 if (!HasWebRequestScheme(request->url())) |
599 return; | 608 return net::OK; |
600 | 609 |
601 int extra_info_spec = 0; | 610 int extra_info_spec = 0; |
602 std::vector<const EventListener*> listeners = | 611 std::vector<const EventListener*> listeners = |
603 GetMatchingListeners(profile, extension_info_map, | 612 GetMatchingListeners(profile, extension_info_map, |
604 keys::kOnAuthRequired, request, &extra_info_spec); | 613 keys::kOnAuthRequired, request, &extra_info_spec); |
605 if (listeners.empty()) | 614 if (listeners.empty()) |
606 return; | 615 return net::OK; |
607 | 616 |
608 ListValue args; | 617 ListValue args; |
609 DictionaryValue* dict = new DictionaryValue(); | 618 DictionaryValue* dict = new DictionaryValue(); |
610 dict->SetString(keys::kRequestIdKey, | 619 dict->SetString(keys::kRequestIdKey, |
611 base::Uint64ToString(request->identifier())); | 620 base::Uint64ToString(request->identifier())); |
612 dict->SetString(keys::kUrlKey, request->url().spec()); | 621 dict->SetString(keys::kUrlKey, request->url().spec()); |
613 dict->SetBoolean(keys::kIsProxyKey, auth_info.is_proxy); | 622 dict->SetBoolean(keys::kIsProxyKey, auth_info.is_proxy); |
614 if (!auth_info.scheme.empty()) | 623 if (!auth_info.scheme.empty()) |
615 dict->SetString(keys::kSchemeKey, auth_info.scheme); | 624 dict->SetString(keys::kSchemeKey, auth_info.scheme); |
616 if (!auth_info.realm.empty()) | 625 if (!auth_info.realm.empty()) |
617 dict->SetString(keys::kRealmKey, auth_info.realm); | 626 dict->SetString(keys::kRealmKey, auth_info.realm); |
618 DictionaryValue* challenger = new DictionaryValue(); | 627 DictionaryValue* challenger = new DictionaryValue(); |
619 challenger->SetString(keys::kHostKey, auth_info.challenger.host()); | 628 challenger->SetString(keys::kHostKey, auth_info.challenger.host()); |
620 challenger->SetInteger(keys::kPortKey, auth_info.challenger.port()); | 629 challenger->SetInteger(keys::kPortKey, auth_info.challenger.port()); |
621 dict->Set(keys::kChallengerKey, challenger); | 630 dict->Set(keys::kChallengerKey, challenger); |
622 dict->SetDouble(keys::kTimeStampKey, time.ToDoubleT() * 1000); | 631 dict->SetDouble(keys::kTimeStampKey, time.ToDoubleT() * 1000); |
623 if (extra_info_spec & ExtraInfoSpec::REQUEST_HEADERS) { | 632 if (extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS) { |
624 dict->Set(keys::kResponseHeadersKey, | 633 dict->Set(keys::kResponseHeadersKey, |
625 GetResponseHeadersList(request->response_headers())); | 634 GetResponseHeadersList(request->response_headers())); |
626 } | 635 } |
627 if (extra_info_spec & ExtraInfoSpec::STATUS_LINE) | 636 if (extra_info_spec & ExtraInfoSpec::STATUS_LINE) |
628 dict->Set(keys::kStatusLineKey, GetStatusLine(request->response_headers())); | 637 dict->Set(keys::kStatusLineKey, GetStatusLine(request->response_headers())); |
629 args.Append(dict); | 638 args.Append(dict); |
630 | 639 |
631 DispatchEvent(profile, request, listeners, args); | 640 if (DispatchEvent(profile, request, listeners, args)) { |
| 641 blocked_requests_[request->identifier()].event = kOnAuthRequired; |
| 642 blocked_requests_[request->identifier()].callback = callback; |
| 643 blocked_requests_[request->identifier()].auth_credentials = credentials; |
| 644 return net::ERR_IO_PENDING; |
| 645 } |
| 646 return net::OK; |
632 } | 647 } |
633 | 648 |
634 void ExtensionWebRequestEventRouter::OnBeforeRedirect( | 649 void ExtensionWebRequestEventRouter::OnBeforeRedirect( |
635 void* profile, | 650 void* profile, |
636 ExtensionInfoMap* extension_info_map, | 651 ExtensionInfoMap* extension_info_map, |
637 net::URLRequest* request, | 652 net::URLRequest* request, |
638 const GURL& new_location) { | 653 const GURL& new_location) { |
639 if (!profile) | 654 if (!profile) |
640 return; | 655 return; |
641 | 656 |
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1117 net::HttpRequestHeaders::Iterator i(*new_headers); | 1132 net::HttpRequestHeaders::Iterator i(*new_headers); |
1118 while (i.GetNext()) { | 1133 while (i.GetNext()) { |
1119 std::string value; | 1134 std::string value; |
1120 if (!old_headers->GetHeader(i.name(), &value) || i.value() != value) { | 1135 if (!old_headers->GetHeader(i.name(), &value) || i.value() != value) { |
1121 result->modified_request_headers.SetHeader(i.name(), i.value()); | 1136 result->modified_request_headers.SetHeader(i.name(), i.value()); |
1122 } | 1137 } |
1123 } | 1138 } |
1124 } | 1139 } |
1125 } | 1140 } |
1126 | 1141 |
| 1142 if (blocked_request->event == kOnAuthRequired) |
| 1143 result->auth_credentials.swap(response->auth_credentials); |
| 1144 |
1127 return result; | 1145 return result; |
1128 } | 1146 } |
1129 | 1147 |
1130 void ExtensionWebRequestEventRouter::MergeOnBeforeRequestResponses( | 1148 void ExtensionWebRequestEventRouter::MergeOnBeforeRequestResponses( |
1131 BlockedRequest* request, | 1149 BlockedRequest* request, |
1132 std::list<std::string>* conflicting_extensions) const { | 1150 std::list<std::string>* conflicting_extensions) const { |
1133 EventResponseDeltas::iterator delta; | 1151 EventResponseDeltas::iterator delta; |
1134 EventResponseDeltas& deltas = request->response_deltas; | 1152 EventResponseDeltas& deltas = request->response_deltas; |
1135 | 1153 |
1136 bool redirected = false; | 1154 bool redirected = false; |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1248 } else { | 1266 } else { |
1249 conflicting_extensions->push_back((*delta)->extension_id); | 1267 conflicting_extensions->push_back((*delta)->extension_id); |
1250 request->net_log->AddEvent( | 1268 request->net_log->AddEvent( |
1251 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, | 1269 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, |
1252 make_scoped_refptr( | 1270 make_scoped_refptr( |
1253 new NetLogExtensionIdParameter((*delta)->extension_id))); | 1271 new NetLogExtensionIdParameter((*delta)->extension_id))); |
1254 } | 1272 } |
1255 } | 1273 } |
1256 } | 1274 } |
1257 | 1275 |
| 1276 void ExtensionWebRequestEventRouter::MergeOnAuthRequiredResponses( |
| 1277 BlockedRequest* request, |
| 1278 std::list<std::string>* conflicting_extensions) const { |
| 1279 CHECK(request); |
| 1280 CHECK(request->auth_credentials); |
| 1281 bool credentials_set = false; |
| 1282 |
| 1283 const EventResponseDeltas& deltas = request->response_deltas; |
| 1284 for (EventResponseDeltas::const_iterator it = deltas.begin(); |
| 1285 it != deltas.end(); |
| 1286 ++it) { |
| 1287 if (!(*it)->auth_credentials.get()) |
| 1288 continue; |
| 1289 if (credentials_set) { |
| 1290 conflicting_extensions->push_back((*it)->extension_id); |
| 1291 } else { |
| 1292 *request->auth_credentials = *(*it)->auth_credentials; |
| 1293 credentials_set = true; |
| 1294 } |
| 1295 } |
| 1296 } |
| 1297 |
1258 void ExtensionWebRequestEventRouter::DecrementBlockCount( | 1298 void ExtensionWebRequestEventRouter::DecrementBlockCount( |
1259 void* profile, | 1299 void* profile, |
1260 const std::string& extension_id, | 1300 const std::string& extension_id, |
1261 const std::string& event_name, | 1301 const std::string& event_name, |
1262 uint64 request_id, | 1302 uint64 request_id, |
1263 EventResponse* response) { | 1303 EventResponse* response) { |
1264 scoped_ptr<EventResponse> response_scoped(response); | 1304 scoped_ptr<EventResponse> response_scoped(response); |
1265 | 1305 |
1266 // It's possible that this request was deleted, or cancelled by a previous | 1306 // It's possible that this request was deleted, or cancelled by a previous |
1267 // event handler. If so, ignore this response. | 1307 // event handler. If so, ignore this response. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1303 deltas.sort(&InDecreasingExtensionInstallationTimeOrder); | 1343 deltas.sort(&InDecreasingExtensionInstallationTimeOrder); |
1304 std::list<std::string> conflicting_extensions; | 1344 std::list<std::string> conflicting_extensions; |
1305 | 1345 |
1306 if (blocked_request.event == kOnBeforeRequest) { | 1346 if (blocked_request.event == kOnBeforeRequest) { |
1307 CHECK(blocked_request.callback); | 1347 CHECK(blocked_request.callback); |
1308 MergeOnBeforeRequestResponses(&blocked_request, &conflicting_extensions); | 1348 MergeOnBeforeRequestResponses(&blocked_request, &conflicting_extensions); |
1309 } else if (blocked_request.event == kOnBeforeSendHeaders) { | 1349 } else if (blocked_request.event == kOnBeforeSendHeaders) { |
1310 CHECK(blocked_request.callback); | 1350 CHECK(blocked_request.callback); |
1311 MergeOnBeforeSendHeadersResponses(&blocked_request, | 1351 MergeOnBeforeSendHeadersResponses(&blocked_request, |
1312 &conflicting_extensions); | 1352 &conflicting_extensions); |
| 1353 } else if (blocked_request.event == kOnAuthRequired) { |
| 1354 CHECK(blocked_request.callback); |
| 1355 MergeOnAuthRequiredResponses(&blocked_request, &conflicting_extensions); |
1313 } else { | 1356 } else { |
1314 NOTREACHED(); | 1357 NOTREACHED(); |
1315 } | 1358 } |
1316 std::list<std::string>::iterator conflict_iter; | 1359 std::list<std::string>::iterator conflict_iter; |
1317 for (conflict_iter = conflicting_extensions.begin(); | 1360 for (conflict_iter = conflicting_extensions.begin(); |
1318 conflict_iter != conflicting_extensions.end(); | 1361 conflict_iter != conflicting_extensions.end(); |
1319 ++conflict_iter) { | 1362 ++conflict_iter) { |
1320 // TODO(mpcomplete): Do some fancy notification in the UI. | 1363 // TODO(mpcomplete): Do some fancy notification in the UI. |
1321 LOG(ERROR) << "Extension " << *conflict_iter << " was ignored in " | 1364 LOG(ERROR) << "Extension " << *conflict_iter << " was ignored in " |
1322 "webRequest API because of conflicting request " | 1365 "webRequest API because of conflicting request " |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1483 EXTENSION_FUNCTION_VALIDATE( | 1526 EXTENSION_FUNCTION_VALIDATE( |
1484 request_headers_value->GetDictionary(i, &header_value)); | 1527 request_headers_value->GetDictionary(i, &header_value)); |
1485 EXTENSION_FUNCTION_VALIDATE( | 1528 EXTENSION_FUNCTION_VALIDATE( |
1486 header_value->GetString(keys::kHeaderNameKey, &name)); | 1529 header_value->GetString(keys::kHeaderNameKey, &name)); |
1487 EXTENSION_FUNCTION_VALIDATE( | 1530 EXTENSION_FUNCTION_VALIDATE( |
1488 header_value->GetString(keys::kHeaderValueKey, &value)); | 1531 header_value->GetString(keys::kHeaderValueKey, &value)); |
1489 | 1532 |
1490 response->request_headers->SetHeader(name, value); | 1533 response->request_headers->SetHeader(name, value); |
1491 } | 1534 } |
1492 } | 1535 } |
| 1536 |
| 1537 if (value->HasKey(keys::kAuthCredentialsKey)) { |
| 1538 DictionaryValue* credentials_value = NULL; |
| 1539 EXTENSION_FUNCTION_VALIDATE(value->GetDictionary( |
| 1540 keys::kAuthCredentialsKey, |
| 1541 &credentials_value)); |
| 1542 response->auth_credentials.reset(new net::AuthCredentials()); |
| 1543 EXTENSION_FUNCTION_VALIDATE( |
| 1544 credentials_value->GetString(keys::kUsernameKey, |
| 1545 &response->auth_credentials->username)); |
| 1546 EXTENSION_FUNCTION_VALIDATE( |
| 1547 credentials_value->GetString(keys::kPasswordKey, |
| 1548 &response->auth_credentials->password)); |
| 1549 response->auth_credentials->is_valid = true; |
| 1550 } |
1493 } | 1551 } |
1494 | 1552 |
1495 ExtensionWebRequestEventRouter::GetInstance()->OnEventHandled( | 1553 ExtensionWebRequestEventRouter::GetInstance()->OnEventHandled( |
1496 profile(), extension_id(), event_name, sub_event_name, request_id, | 1554 profile(), extension_id(), event_name, sub_event_name, request_id, |
1497 response.release()); | 1555 response.release()); |
1498 | 1556 |
1499 return true; | 1557 return true; |
1500 } | 1558 } |
OLD | NEW |