summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/extensions')
-rw-r--r--chrome/browser/extensions/activity_log.cc44
-rw-r--r--chrome/browser/extensions/activity_log.h8
-rw-r--r--chrome/browser/extensions/activity_log_web_request_constants.cc33
-rw-r--r--chrome/browser/extensions/activity_log_web_request_constants.h36
-rw-r--r--chrome/browser/extensions/api/web_request/web_request_api.cc168
-rw-r--r--chrome/browser/extensions/dom_actions.cc4
-rw-r--r--chrome/browser/extensions/dom_actions.h9
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;