diff options
Diffstat (limited to 'chrome/browser/extensions')
-rw-r--r-- | chrome/browser/extensions/activity_log.cc | 44 | ||||
-rw-r--r-- | chrome/browser/extensions/activity_log.h | 8 | ||||
-rw-r--r-- | chrome/browser/extensions/activity_log_web_request_constants.cc | 33 | ||||
-rw-r--r-- | chrome/browser/extensions/activity_log_web_request_constants.h | 36 | ||||
-rw-r--r-- | chrome/browser/extensions/api/web_request/web_request_api.cc | 168 | ||||
-rw-r--r-- | chrome/browser/extensions/dom_actions.cc | 4 | ||||
-rw-r--r-- | chrome/browser/extensions/dom_actions.h | 9 |
7 files changed, 296 insertions, 6 deletions
diff --git a/chrome/browser/extensions/activity_log.cc b/chrome/browser/extensions/activity_log.cc index 92c46d3..6fe5f52 100644 --- a/chrome/browser/extensions/activity_log.cc +++ b/chrome/browser/extensions/activity_log.cc @@ -356,6 +356,50 @@ void ActivityLog::LogDOMAction(const Extension* extension, DOMAction::MODIFIED); } +void ActivityLog::LogWebRequestAction(const Extension* extension, + const GURL& url, + const std::string& api_call, + scoped_ptr<DictionaryValue> details, + const std::string& extra) { + string16 null_title; + if (!IsLogEnabled()) return; + + // Strip details of the web request modifications (for privacy reasons), + // unless testing is enabled. + if (!testing_mode_) { + DictionaryValue::Iterator details_iterator(*details); + while (!details_iterator.IsAtEnd()) { + details->SetBoolean(details_iterator.key(), true); + details_iterator.Advance(); + } + } + std::string details_string; + JSONStringValueSerializer serializer(&details_string); + serializer.SerializeAndOmitBinaryValues(*details); + + scoped_refptr<DOMAction> action = new DOMAction( + extension->id(), + base::Time::Now(), + DOMAction::WEBREQUEST, + url, + null_title, + api_call, + details_string, + extra); + ScheduleAndForget(&ActivityDatabase::RecordAction, action); + + // Display the action. + ObserverMap::const_iterator iter = observers_.find(extension); + if (iter != observers_.end()) { + iter->second->Notify(&Observer::OnExtensionActivity, + extension, + ActivityLog::ACTIVITY_CONTENT_SCRIPT, + action->PrettyPrintForDebug()); + } + if (log_activity_to_stdout_) + LOG(INFO) << action->PrettyPrintForDebug(); +} + void ActivityLog::GetActions( const std::string& extension_id, const int day, diff --git a/chrome/browser/extensions/activity_log.h b/chrome/browser/extensions/activity_log.h index 55c7b18..2095d7a 100644 --- a/chrome/browser/extensions/activity_log.h +++ b/chrome/browser/extensions/activity_log.h @@ -109,6 +109,14 @@ class ActivityLog : public ProfileKeyedService, const ListValue* args, // arguments const std::string& extra); // extra logging info + // Log a use of the WebRequest API to redirect, cancel, or modify page + // headers. + void LogWebRequestAction(const Extension* extension, + const GURL& url, + const std::string& api_call, + scoped_ptr<base::DictionaryValue> details, + const std::string& extra); + // Retrieves the list of actions for a given extension on a specific day. // Today is 0, yesterday is 1, etc. Returns one day at a time. // Response is sent to the method/function in the callback. diff --git a/chrome/browser/extensions/activity_log_web_request_constants.cc b/chrome/browser/extensions/activity_log_web_request_constants.cc new file mode 100644 index 0000000..97c65a2 --- /dev/null +++ b/chrome/browser/extensions/activity_log_web_request_constants.cc @@ -0,0 +1,33 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Constants used when describing request modifications via the WebRequest API +// in the activity log. + +#include "chrome/browser/extensions/activity_log_web_request_constants.h" + +namespace activity_log_web_request_constants { + +// Keys used in the dictionary summarizing an EventResponseDelta for the +// extension activity log. +const char kCancelKey[] = "cancel"; +const char kNewUrlKey[] = "new_url"; +const char kModifiedRequestHeadersKey[] = "modified_request_headers"; +const char kDeletedRequestHeadersKey[] = "deleted_request_headers"; +const char kAddedRequestHeadersKey[] = "added_request_headers"; +const char kDeletedResponseHeadersKey[] = "deleted_response_headers"; +const char kAuthCredentialsKey[] = "auth_credentials"; +const char kResponseCookieModificationsKey[] = "response_cookie_modifications"; + +// Keys and values used for describing cookie modifications. +const char kCookieModificationTypeKey[] = "type"; +const char kCookieModificationAdd[] = "ADD"; +const char kCookieModificationEdit[] = "EDIT"; +const char kCookieModificationRemove[] = "REMOVE"; +const char kCookieFilterNameKey[] = "filter_name"; +const char kCookieFilterDomainKey[] = "filter_domain"; +const char kCookieModNameKey[] = "mod_name"; +const char kCookieModDomainKey[] = "mod_domain"; + +} // namespace activity_log_web_request_constants diff --git a/chrome/browser/extensions/activity_log_web_request_constants.h b/chrome/browser/extensions/activity_log_web_request_constants.h new file mode 100644 index 0000000..f94385c --- /dev/null +++ b/chrome/browser/extensions/activity_log_web_request_constants.h @@ -0,0 +1,36 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Constants used when describing request modifications via the WebRequest API +// in the activity log. + +#ifndef CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_WEB_REQUEST_CONSTANTS_H_ +#define CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_WEB_REQUEST_CONSTANTS_H_ + +namespace activity_log_web_request_constants { + +// Keys used in the dictionary summarizing an EventResponseDelta for the +// extension activity log. +extern const char kCancelKey[]; +extern const char kNewUrlKey[]; +extern const char kModifiedRequestHeadersKey[]; +extern const char kDeletedRequestHeadersKey[]; +extern const char kAddedRequestHeadersKey[]; +extern const char kDeletedResponseHeadersKey[]; +extern const char kAuthCredentialsKey[]; +extern const char kResponseCookieModificationsKey[]; + +// Keys and values used for describing cookie modifications. +extern const char kCookieModificationTypeKey[]; +extern const char kCookieModificationAdd[]; +extern const char kCookieModificationEdit[]; +extern const char kCookieModificationRemove[]; +extern const char kCookieFilterNameKey[]; +extern const char kCookieFilterDomainKey[]; +extern const char kCookieModNameKey[]; +extern const char kCookieModDomainKey[]; + +} // namespace activity_log_web_request_constants + +#endif // CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_WEB_REQUEST_CONSTANTS_H_ diff --git a/chrome/browser/extensions/api/web_request/web_request_api.cc b/chrome/browser/extensions/api/web_request/web_request_api.cc index 623af7f..27ef5a3 100644 --- a/chrome/browser/extensions/api/web_request/web_request_api.cc +++ b/chrome/browser/extensions/api/web_request/web_request_api.cc @@ -17,6 +17,8 @@ #include "base/values.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_content_browser_client.h" +#include "chrome/browser/extensions/activity_log.h" +#include "chrome/browser/extensions/activity_log_web_request_constants.h" #include "chrome/browser/extensions/api/declarative_webrequest/request_stage.h" #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.h" #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.h" @@ -77,6 +79,7 @@ namespace helpers = extension_web_request_api_helpers; namespace keys = extension_web_request_api_constants; namespace web_request = extensions::api::web_request; namespace declarative_keys = extensions::declarative_webrequest_constants; +namespace activitylog = activity_log_web_request_constants; namespace { @@ -1401,6 +1404,157 @@ helpers::EventResponseDelta* CalculateDelta( return NULL; } +Value* SerializeResponseHeaders(const helpers::ResponseHeaders& headers) { + scoped_ptr<ListValue> serialized_headers(new ListValue()); + for (helpers::ResponseHeaders::const_iterator i = headers.begin(); + i != headers.end(); ++i) { + serialized_headers->Append(ToHeaderDictionary(i->first, i->second)); + } + return serialized_headers.release(); +} + +// Convert a RequestCookieModifications/ResponseCookieModifications object to a +// ListValue which summarizes the changes made. This is templated since the +// two types (request/response) are different but contain essentially the same +// fields. +template<typename CookieType> +ListValue* SummarizeCookieModifications( + const std::vector<linked_ptr<CookieType> >& modifications) { + scoped_ptr<ListValue> cookie_modifications(new ListValue()); + for (typename std::vector<linked_ptr<CookieType> >::const_iterator i = + modifications.begin(); + i != modifications.end(); ++i) { + scoped_ptr<DictionaryValue> summary(new DictionaryValue()); + const CookieType& mod = *i->get(); + switch (mod.type) { + case helpers::ADD: + summary->SetString(activitylog::kCookieModificationTypeKey, + activitylog::kCookieModificationAdd); + break; + case helpers::EDIT: + summary->SetString(activitylog::kCookieModificationTypeKey, + activitylog::kCookieModificationEdit); + break; + case helpers::REMOVE: + summary->SetString(activitylog::kCookieModificationTypeKey, + activitylog::kCookieModificationRemove); + break; + } + if (mod.filter) { + if (mod.filter->name) + summary->SetString(activitylog::kCookieFilterNameKey, + *mod.modification->name); + if (mod.filter->domain) + summary->SetString(activitylog::kCookieFilterDomainKey, + *mod.modification->name); + } + if (mod.modification) { + if (mod.modification->name) + summary->SetString(activitylog::kCookieModDomainKey, + *mod.modification->name); + if (mod.modification->domain) + summary->SetString(activitylog::kCookieModDomainKey, + *mod.modification->name); + } + cookie_modifications->Append(summary.release()); + } + return cookie_modifications.release(); +} + +// Converts an EventResponseDelta object to a dictionary value suitable for the +// activity log. The caller takes ownership of the returned DictionaryValue +// object. +DictionaryValue* SummarizeResponseDelta( + const std::string& event_name, + const helpers::EventResponseDelta& delta) { + scoped_ptr<DictionaryValue> details(new DictionaryValue()); + if (delta.cancel) { + details->SetBoolean(activitylog::kCancelKey, true); + } + if (!delta.new_url.is_empty()) { + details->SetString(activitylog::kNewUrlKey, delta.new_url.spec()); + } + + scoped_ptr<ListValue> modified_headers(new ListValue()); + net::HttpRequestHeaders::Iterator iter(delta.modified_request_headers); + while (iter.GetNext()) { + modified_headers->Append(ToHeaderDictionary(iter.name(), iter.value())); + } + if (!modified_headers->empty()) { + details->Set(activitylog::kModifiedRequestHeadersKey, + modified_headers.release()); + } + + scoped_ptr<ListValue> deleted_headers(new ListValue()); + deleted_headers->AppendStrings(delta.deleted_request_headers); + if (!deleted_headers->empty()) { + details->Set(activitylog::kDeletedRequestHeadersKey, + deleted_headers.release()); + } + + if (!delta.added_response_headers.empty()) { + details->Set(activitylog::kAddedRequestHeadersKey, + SerializeResponseHeaders(delta.added_response_headers)); + } + if (!delta.deleted_response_headers.empty()) { + details->Set(activitylog::kDeletedResponseHeadersKey, + SerializeResponseHeaders(delta.deleted_response_headers)); + } + if (delta.auth_credentials) { + details->SetString(activitylog::kAuthCredentialsKey, + UTF16ToUTF8(delta.auth_credentials->username()) + ":*"); + } + + if (!delta.response_cookie_modifications.empty()) { + details->Set( + activitylog::kResponseCookieModificationsKey, + SummarizeCookieModifications(delta.response_cookie_modifications)); + } + + return details.release(); +} + +void LogExtensionActivity(Profile* profile, + const std::string& extension_id, + const GURL& url, + const std::string& api_call, + DictionaryValue* details_raw) { + scoped_ptr<DictionaryValue> details(details_raw); + if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { + BrowserThread::PostTask(BrowserThread::UI, + FROM_HERE, + base::Bind(&LogExtensionActivity, + profile, + extension_id, + url, + api_call, + details.release())); + } else { + // An ExtensionService might not be running during unit tests, or an + // extension might have been unloadd by the time we get to logging it. In + // those cases log a warning. + ExtensionService* extension_service = + extensions::ExtensionSystem::Get(profile)->extension_service(); + if (!extension_service) { + LOG(WARNING) << "ExtensionService does not seem to be available " + << "(this may be normal for unit tests)"; + } else { + const Extension* extension = + extension_service->extensions()->GetByID(extension_id); + if (!extension) { + LOG(WARNING) << "Extension " << extension_id << " not found!"; + } else { + extensions::ActivityLog::GetInstance(profile)->LogWebRequestAction( + extension, + url, + api_call, + details.Pass(), + ""); + } + } + } +} + } // namespace void ExtensionWebRequestEventRouter::DecrementBlockCount( @@ -1421,9 +1575,19 @@ void ExtensionWebRequestEventRouter::DecrementBlockCount( CHECK_GE(num_handlers_blocking, 0); if (response) { + helpers::EventResponseDelta* delta = + CalculateDelta(&blocked_request, response); + + if (extensions::ActivityLog::IsLogEnabled()) { + LogExtensionActivity(static_cast<Profile*>(profile), + extension_id, + blocked_request.request->url(), + event_name, + SummarizeResponseDelta(event_name, *delta)); + } + blocked_request.response_deltas.push_back( - linked_ptr<helpers::EventResponseDelta>( - CalculateDelta(&blocked_request, response))); + linked_ptr<helpers::EventResponseDelta>(delta)); } base::TimeDelta block_time = diff --git a/chrome/browser/extensions/dom_actions.cc b/chrome/browser/extensions/dom_actions.cc index 2d3b6f4..ffb8665 100644 --- a/chrome/browser/extensions/dom_actions.cc +++ b/chrome/browser/extensions/dom_actions.cc @@ -108,6 +108,8 @@ std::string DOMAction::VerbAsString() const { return "INSERTED"; case XHR: return "XHR"; + case WEBREQUEST: + return "WEBREQUEST"; default: NOTREACHED(); return NULL; @@ -124,6 +126,8 @@ DOMAction::DOMActionType DOMAction::StringAsDOMActionType( return INSERTED; } else if (str == "XHR") { return XHR; + } else if (str == "WEBREQUEST") { + return WEBREQUEST; } else { NOTREACHED(); return MODIFIED; // this should never happen! diff --git a/chrome/browser/extensions/dom_actions.h b/chrome/browser/extensions/dom_actions.h index a4a238b..13d5e07 100644 --- a/chrome/browser/extensions/dom_actions.h +++ b/chrome/browser/extensions/dom_actions.h @@ -16,10 +16,11 @@ namespace extensions { class DOMAction : public Action { public: enum DOMActionType { - MODIFIED, // For Content Script DOM manipulations - READ, // For Content Script DOM manipulations - INSERTED, // For when Content Scripts are added to pages - XHR, // When an extension core sends an XHR + MODIFIED, // For Content Script DOM manipulations + READ, // For Content Script DOM manipulations + INSERTED, // For when Content Scripts are added to pages + XHR, // When an extension core sends an XHR + WEBREQUEST, // When a page request is modified with the WebRequest API }; static const char* kTableName; |