| 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 "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" |
| 11 #include "base/json/json_writer.h" | 11 #include "base/json/json_writer.h" |
| 12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
| 13 #include "base/string_util.h" | 13 #include "base/string_util.h" |
| 14 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
| 15 #include "base/time.h" | 15 #include "base/time.h" |
| 16 #include "base/utf_string_conversions.h" | 16 #include "base/utf_string_conversions.h" |
| 17 #include "base/values.h" | 17 #include "base/values.h" |
| 18 #include "chrome/browser/browser_process.h" | 18 #include "chrome/browser/browser_process.h" |
| 19 #include "chrome/browser/chrome_content_browser_client.h" | 19 #include "chrome/browser/chrome_content_browser_client.h" |
| 20 #include "chrome/browser/extensions/activity_log.h" | |
| 21 #include "chrome/browser/extensions/activity_log_web_request_constants.h" | |
| 22 #include "chrome/browser/extensions/api/declarative_webrequest/request_stage.h" | 20 #include "chrome/browser/extensions/api/declarative_webrequest/request_stage.h" |
| 23 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_consta
nts.h" | 21 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_consta
nts.h" |
| 24 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_
registry.h" | 22 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_
registry.h" |
| 25 #include "chrome/browser/extensions/api/web_navigation/web_navigation_api_helper
s.h" | 23 #include "chrome/browser/extensions/api/web_navigation/web_navigation_api_helper
s.h" |
| 26 #include "chrome/browser/extensions/api/web_request/upload_data_presenter.h" | 24 #include "chrome/browser/extensions/api/web_request/upload_data_presenter.h" |
| 27 #include "chrome/browser/extensions/api/web_request/web_request_api_constants.h" | 25 #include "chrome/browser/extensions/api/web_request/web_request_api_constants.h" |
| 28 #include "chrome/browser/extensions/api/web_request/web_request_api_helpers.h" | 26 #include "chrome/browser/extensions/api/web_request/web_request_api_helpers.h" |
| 29 #include "chrome/browser/extensions/api/web_request/web_request_time_tracker.h" | 27 #include "chrome/browser/extensions/api/web_request/web_request_time_tracker.h" |
| 30 #include "chrome/browser/extensions/event_router.h" | 28 #include "chrome/browser/extensions/event_router.h" |
| 31 #include "chrome/browser/extensions/extension_info_map.h" | 29 #include "chrome/browser/extensions/extension_info_map.h" |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 72 using extensions::ExtensionWarning; | 70 using extensions::ExtensionWarning; |
| 73 using extensions::ExtensionWarningService; | 71 using extensions::ExtensionWarningService; |
| 74 using extensions::ExtensionWarningSet; | 72 using extensions::ExtensionWarningSet; |
| 75 using extensions::Feature; | 73 using extensions::Feature; |
| 76 using extensions::web_navigation_api_helpers::GetFrameId; | 74 using extensions::web_navigation_api_helpers::GetFrameId; |
| 77 | 75 |
| 78 namespace helpers = extension_web_request_api_helpers; | 76 namespace helpers = extension_web_request_api_helpers; |
| 79 namespace keys = extension_web_request_api_constants; | 77 namespace keys = extension_web_request_api_constants; |
| 80 namespace web_request = extensions::api::web_request; | 78 namespace web_request = extensions::api::web_request; |
| 81 namespace declarative_keys = extensions::declarative_webrequest_constants; | 79 namespace declarative_keys = extensions::declarative_webrequest_constants; |
| 82 namespace activitylog = activity_log_web_request_constants; | |
| 83 | 80 |
| 84 namespace { | 81 namespace { |
| 85 | 82 |
| 86 // List of all the webRequest events. | 83 // List of all the webRequest events. |
| 87 const char* const kWebRequestEvents[] = { | 84 const char* const kWebRequestEvents[] = { |
| 88 keys::kOnBeforeRedirectEvent, | 85 keys::kOnBeforeRedirectEvent, |
| 89 keys::kOnBeforeRequestEvent, | 86 keys::kOnBeforeRequestEvent, |
| 90 keys::kOnBeforeSendHeadersEvent, | 87 keys::kOnBeforeSendHeadersEvent, |
| 91 keys::kOnCompletedEvent, | 88 keys::kOnCompletedEvent, |
| 92 keys::kOnErrorOccurredEvent, | 89 keys::kOnErrorOccurredEvent, |
| (...skipping 1304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1397 return helpers::CalculateOnAuthRequiredDelta( | 1394 return helpers::CalculateOnAuthRequiredDelta( |
| 1398 response->extension_id, response->extension_install_time, | 1395 response->extension_id, response->extension_install_time, |
| 1399 response->cancel, &response->auth_credentials); | 1396 response->cancel, &response->auth_credentials); |
| 1400 default: | 1397 default: |
| 1401 NOTREACHED(); | 1398 NOTREACHED(); |
| 1402 break; | 1399 break; |
| 1403 } | 1400 } |
| 1404 return NULL; | 1401 return NULL; |
| 1405 } | 1402 } |
| 1406 | 1403 |
| 1407 Value* SerializeResponseHeaders(const helpers::ResponseHeaders& headers) { | |
| 1408 scoped_ptr<ListValue> serialized_headers(new ListValue()); | |
| 1409 for (helpers::ResponseHeaders::const_iterator i = headers.begin(); | |
| 1410 i != headers.end(); ++i) { | |
| 1411 serialized_headers->Append(ToHeaderDictionary(i->first, i->second)); | |
| 1412 } | |
| 1413 return serialized_headers.release(); | |
| 1414 } | |
| 1415 | |
| 1416 // Convert a RequestCookieModifications/ResponseCookieModifications object to a | |
| 1417 // ListValue which summarizes the changes made. This is templated since the | |
| 1418 // two types (request/response) are different but contain essentially the same | |
| 1419 // fields. | |
| 1420 template<typename CookieType> | |
| 1421 ListValue* SummarizeCookieModifications( | |
| 1422 const std::vector<linked_ptr<CookieType> >& modifications) { | |
| 1423 scoped_ptr<ListValue> cookie_modifications(new ListValue()); | |
| 1424 for (typename std::vector<linked_ptr<CookieType> >::const_iterator i = | |
| 1425 modifications.begin(); | |
| 1426 i != modifications.end(); ++i) { | |
| 1427 scoped_ptr<DictionaryValue> summary(new DictionaryValue()); | |
| 1428 const CookieType& mod = *i->get(); | |
| 1429 switch (mod.type) { | |
| 1430 case helpers::ADD: | |
| 1431 summary->SetString(activitylog::kCookieModificationTypeKey, | |
| 1432 activitylog::kCookieModificationAdd); | |
| 1433 break; | |
| 1434 case helpers::EDIT: | |
| 1435 summary->SetString(activitylog::kCookieModificationTypeKey, | |
| 1436 activitylog::kCookieModificationEdit); | |
| 1437 break; | |
| 1438 case helpers::REMOVE: | |
| 1439 summary->SetString(activitylog::kCookieModificationTypeKey, | |
| 1440 activitylog::kCookieModificationRemove); | |
| 1441 break; | |
| 1442 } | |
| 1443 if (mod.filter) { | |
| 1444 if (mod.filter->name) | |
| 1445 summary->SetString(activitylog::kCookieFilterNameKey, | |
| 1446 *mod.modification->name); | |
| 1447 if (mod.filter->domain) | |
| 1448 summary->SetString(activitylog::kCookieFilterDomainKey, | |
| 1449 *mod.modification->name); | |
| 1450 } | |
| 1451 if (mod.modification) { | |
| 1452 if (mod.modification->name) | |
| 1453 summary->SetString(activitylog::kCookieModDomainKey, | |
| 1454 *mod.modification->name); | |
| 1455 if (mod.modification->domain) | |
| 1456 summary->SetString(activitylog::kCookieModDomainKey, | |
| 1457 *mod.modification->name); | |
| 1458 } | |
| 1459 cookie_modifications->Append(summary.release()); | |
| 1460 } | |
| 1461 return cookie_modifications.release(); | |
| 1462 } | |
| 1463 | |
| 1464 // Converts an EventResponseDelta object to a dictionary value suitable for the | |
| 1465 // activity log. The caller takes ownership of the returned DictionaryValue | |
| 1466 // object. | |
| 1467 DictionaryValue* SummarizeResponseDelta( | |
| 1468 const std::string& event_name, | |
| 1469 const helpers::EventResponseDelta& delta) { | |
| 1470 scoped_ptr<DictionaryValue> details(new DictionaryValue()); | |
| 1471 if (delta.cancel) { | |
| 1472 details->SetBoolean(activitylog::kCancelKey, true); | |
| 1473 } | |
| 1474 if (!delta.new_url.is_empty()) { | |
| 1475 details->SetString(activitylog::kNewUrlKey, delta.new_url.spec()); | |
| 1476 } | |
| 1477 | |
| 1478 scoped_ptr<ListValue> modified_headers(new ListValue()); | |
| 1479 net::HttpRequestHeaders::Iterator iter(delta.modified_request_headers); | |
| 1480 while (iter.GetNext()) { | |
| 1481 modified_headers->Append(ToHeaderDictionary(iter.name(), iter.value())); | |
| 1482 } | |
| 1483 if (!modified_headers->empty()) { | |
| 1484 details->Set(activitylog::kModifiedRequestHeadersKey, | |
| 1485 modified_headers.release()); | |
| 1486 } | |
| 1487 | |
| 1488 scoped_ptr<ListValue> deleted_headers(new ListValue()); | |
| 1489 deleted_headers->AppendStrings(delta.deleted_request_headers); | |
| 1490 if (!deleted_headers->empty()) { | |
| 1491 details->Set(activitylog::kDeletedRequestHeadersKey, | |
| 1492 deleted_headers.release()); | |
| 1493 } | |
| 1494 | |
| 1495 if (!delta.added_response_headers.empty()) { | |
| 1496 details->Set(activitylog::kAddedRequestHeadersKey, | |
| 1497 SerializeResponseHeaders(delta.added_response_headers)); | |
| 1498 } | |
| 1499 if (!delta.deleted_response_headers.empty()) { | |
| 1500 details->Set(activitylog::kDeletedResponseHeadersKey, | |
| 1501 SerializeResponseHeaders(delta.deleted_response_headers)); | |
| 1502 } | |
| 1503 if (delta.auth_credentials) { | |
| 1504 details->SetString(activitylog::kAuthCredentialsKey, | |
| 1505 UTF16ToUTF8(delta.auth_credentials->username()) + ":*"); | |
| 1506 } | |
| 1507 | |
| 1508 if (!delta.response_cookie_modifications.empty()) { | |
| 1509 details->Set( | |
| 1510 activitylog::kResponseCookieModificationsKey, | |
| 1511 SummarizeCookieModifications(delta.response_cookie_modifications)); | |
| 1512 } | |
| 1513 | |
| 1514 return details.release(); | |
| 1515 } | |
| 1516 | |
| 1517 void LogExtensionActivity(Profile* profile, | |
| 1518 const std::string& extension_id, | |
| 1519 const GURL& url, | |
| 1520 const std::string& api_call, | |
| 1521 DictionaryValue* details) { | |
| 1522 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
| 1523 BrowserThread::PostTask(BrowserThread::UI, | |
| 1524 FROM_HERE, | |
| 1525 base::Bind(&LogExtensionActivity, | |
| 1526 profile, | |
| 1527 extension_id, | |
| 1528 url, | |
| 1529 api_call, | |
| 1530 details)); | |
| 1531 } else { | |
| 1532 // An ExtensionService might not be running during unit tests, or an | |
| 1533 // extension might have been unloadd by the time we get to logging it. In | |
| 1534 // those cases log a warning. | |
| 1535 ExtensionService* extension_service = | |
| 1536 extensions::ExtensionSystem::Get(profile)->extension_service(); | |
| 1537 if (!extension_service) { | |
| 1538 LOG(WARNING) << "ExtensionService does not seem to be available " | |
| 1539 << "(this may be normal for unit tests)"; | |
| 1540 } else { | |
| 1541 const Extension* extension = | |
| 1542 extension_service->extensions()->GetByID(extension_id); | |
| 1543 if (!extension) { | |
| 1544 LOG(WARNING) << "Extension " << extension_id << " not found!"; | |
| 1545 } else { | |
| 1546 extensions::ActivityLog::GetInstance(profile)->LogWebRequestAction( | |
| 1547 extension, | |
| 1548 url, | |
| 1549 api_call, | |
| 1550 scoped_ptr<DictionaryValue>(details), | |
| 1551 ""); | |
| 1552 } | |
| 1553 } | |
| 1554 } | |
| 1555 } | |
| 1556 | |
| 1557 } // namespace | 1404 } // namespace |
| 1558 | 1405 |
| 1559 void ExtensionWebRequestEventRouter::DecrementBlockCount( | 1406 void ExtensionWebRequestEventRouter::DecrementBlockCount( |
| 1560 void* profile, | 1407 void* profile, |
| 1561 const std::string& extension_id, | 1408 const std::string& extension_id, |
| 1562 const std::string& event_name, | 1409 const std::string& event_name, |
| 1563 uint64 request_id, | 1410 uint64 request_id, |
| 1564 EventResponse* response) { | 1411 EventResponse* response) { |
| 1565 scoped_ptr<EventResponse> response_scoped(response); | 1412 scoped_ptr<EventResponse> response_scoped(response); |
| 1566 | 1413 |
| 1567 // It's possible that this request was deleted, or cancelled by a previous | 1414 // It's possible that this request was deleted, or cancelled by a previous |
| 1568 // event handler. If so, ignore this response. | 1415 // event handler. If so, ignore this response. |
| 1569 if (blocked_requests_.find(request_id) == blocked_requests_.end()) | 1416 if (blocked_requests_.find(request_id) == blocked_requests_.end()) |
| 1570 return; | 1417 return; |
| 1571 | 1418 |
| 1572 BlockedRequest& blocked_request = blocked_requests_[request_id]; | 1419 BlockedRequest& blocked_request = blocked_requests_[request_id]; |
| 1573 int num_handlers_blocking = --blocked_request.num_handlers_blocking; | 1420 int num_handlers_blocking = --blocked_request.num_handlers_blocking; |
| 1574 CHECK_GE(num_handlers_blocking, 0); | 1421 CHECK_GE(num_handlers_blocking, 0); |
| 1575 | 1422 |
| 1576 if (response) { | 1423 if (response) { |
| 1577 helpers::EventResponseDelta* delta = | |
| 1578 CalculateDelta(&blocked_request, response); | |
| 1579 | |
| 1580 if (extensions::ActivityLog::IsLogEnabled()) { | |
| 1581 LogExtensionActivity(static_cast<Profile*>(profile), | |
| 1582 extension_id, | |
| 1583 blocked_request.request->url(), | |
| 1584 event_name, | |
| 1585 SummarizeResponseDelta(event_name, *delta)); | |
| 1586 } | |
| 1587 | |
| 1588 blocked_request.response_deltas.push_back( | 1424 blocked_request.response_deltas.push_back( |
| 1589 linked_ptr<helpers::EventResponseDelta>(delta)); | 1425 linked_ptr<helpers::EventResponseDelta>( |
| 1426 CalculateDelta(&blocked_request, response))); |
| 1590 } | 1427 } |
| 1591 | 1428 |
| 1592 base::TimeDelta block_time = | 1429 base::TimeDelta block_time = |
| 1593 base::Time::Now() - blocked_request.blocking_time; | 1430 base::Time::Now() - blocked_request.blocking_time; |
| 1594 if (!extension_id.empty()) { | 1431 if (!extension_id.empty()) { |
| 1595 request_time_tracker_->IncrementExtensionBlockTime( | 1432 request_time_tracker_->IncrementExtensionBlockTime( |
| 1596 extension_id, request_id, block_time); | 1433 extension_id, request_id, block_time); |
| 1597 } else { | 1434 } else { |
| 1598 // |extension_id| is empty for requests blocked on startup waiting for the | 1435 // |extension_id| is empty for requests blocked on startup waiting for the |
| 1599 // declarative rules to be read from disk. | 1436 // declarative rules to be read from disk. |
| (...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2177 } else if ((*it)->name().find("AdBlock") != std::string::npos) { | 2014 } else if ((*it)->name().find("AdBlock") != std::string::npos) { |
| 2178 adblock = true; | 2015 adblock = true; |
| 2179 } else { | 2016 } else { |
| 2180 other = true; | 2017 other = true; |
| 2181 } | 2018 } |
| 2182 } | 2019 } |
| 2183 } | 2020 } |
| 2184 | 2021 |
| 2185 host->Send(new ExtensionMsg_UsingWebRequestAPI(adblock, adblock_plus, other)); | 2022 host->Send(new ExtensionMsg_UsingWebRequestAPI(adblock, adblock_plus, other)); |
| 2186 } | 2023 } |
| OLD | NEW |