Index: extensions/browser/api/web_request/web_request_event_details.cc |
diff --git a/extensions/browser/api/web_request/web_request_event_details.cc b/extensions/browser/api/web_request/web_request_event_details.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..958faea1a50c7688e911fb7771d73d27c6f5af4d |
--- /dev/null |
+++ b/extensions/browser/api/web_request/web_request_event_details.cc |
@@ -0,0 +1,199 @@ |
+// Copyright 2016 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. |
+ |
+#include "extensions/browser/api/web_request/web_request_event_details.h" |
+ |
+#include "base/callback.h" |
+#include "base/strings/string_number_conversions.h" |
+#include "content/public/browser/browser_thread.h" |
+#include "content/public/browser/render_frame_host.h" |
+#include "content/public/browser/resource_request_info.h" |
+#include "content/public/common/child_process_host.h" |
+#include "extensions/browser/api/web_request/upload_data_presenter.h" |
+#include "extensions/browser/api/web_request/web_request_api_constants.h" |
+#include "extensions/browser/api/web_request/web_request_api_helpers.h" |
+#include "extensions/browser/extension_api_frame_id_map.h" |
+#include "ipc/ipc_message.h" |
+#include "net/base/auth.h" |
+#include "net/base/upload_data_stream.h" |
+#include "net/http/http_request_headers.h" |
+#include "net/http/http_response_headers.h" |
+#include "net/url_request/url_request.h" |
+ |
+using extension_web_request_api_helpers::ExtraInfoSpec; |
+ |
+namespace helpers = extension_web_request_api_helpers; |
+namespace keys = extension_web_request_api_constants; |
+ |
+namespace extensions { |
+ |
+WebRequestEventDetails::WebRequestEventDetails(const net::URLRequest* request, |
+ int extra_info_spec) |
+ : extra_info_spec_(extra_info_spec), |
+ render_process_id_(content::ChildProcessHost::kInvalidUniqueID), |
+ render_frame_id_(MSG_ROUTING_NONE) { |
+ content::ResourceType resource_type = content::RESOURCE_TYPE_LAST_TYPE; |
+ const content::ResourceRequestInfo* info = |
+ content::ResourceRequestInfo::ForRequest(request); |
+ if (info) { |
+ render_process_id_ = info->GetChildID(); |
+ render_frame_id_ = info->GetRenderFrameID(); |
+ resource_type = info->GetResourceType(); |
+ } |
+ |
+ dict_.SetString(keys::kMethodKey, request->method()); |
+ dict_.SetString(keys::kRequestIdKey, |
+ base::Uint64ToString(request->identifier())); |
+ dict_.SetDouble(keys::kTimeStampKey, base::Time::Now().ToDoubleT() * 1000); |
+ dict_.SetString(keys::kTypeKey, helpers::ResourceTypeToString(resource_type)); |
+ dict_.SetString(keys::kUrlKey, request->url().spec()); |
+} |
+ |
+WebRequestEventDetails::~WebRequestEventDetails() {} |
+ |
+void WebRequestEventDetails::SetRequestBody(const net::URLRequest* request) { |
+ if (!(extra_info_spec_ & ExtraInfoSpec::REQUEST_BODY)) |
+ return; |
+ |
+ const net::UploadDataStream* upload_data = request->get_upload(); |
+ if (!upload_data || |
+ (request->method() != "POST" && request->method() != "PUT")) |
+ return; |
+ |
+ base::DictionaryValue* request_body = new base::DictionaryValue(); |
+ request_body_.reset(request_body); |
+ |
+ // Get the data presenters, ordered by how specific they are. |
+ ParsedDataPresenter parsed_data_presenter(*request); |
+ RawDataPresenter raw_data_presenter; |
+ UploadDataPresenter* const presenters[] = { |
+ &parsed_data_presenter, // 1: any parseable forms? (Specific to forms.) |
+ &raw_data_presenter // 2: any data at all? (Non-specific.) |
+ }; |
+ // Keys for the results of the corresponding presenters. |
+ static const char* const kKeys[] = {keys::kRequestBodyFormDataKey, |
+ keys::kRequestBodyRawKey}; |
+ |
+ const std::vector<scoped_ptr<net::UploadElementReader>>* readers = |
+ upload_data->GetElementReaders(); |
+ bool some_succeeded = false; |
+ if (readers) { |
+ for (size_t i = 0; i < arraysize(presenters); ++i) { |
+ for (const auto& reader : *readers) |
+ presenters[i]->FeedNext(*reader); |
+ if (presenters[i]->Succeeded()) { |
+ request_body->Set(kKeys[i], presenters[i]->Result()); |
+ some_succeeded = true; |
+ break; |
+ } |
+ } |
+ } |
+ if (!some_succeeded) |
+ request_body->SetString(keys::kRequestBodyErrorKey, "Unknown error."); |
+} |
+ |
+void WebRequestEventDetails::SetRequestHeaders( |
+ const net::HttpRequestHeaders& request_headers) { |
+ if (!(extra_info_spec_ & ExtraInfoSpec::REQUEST_HEADERS)) |
+ return; |
+ |
+ base::ListValue* headers = new base::ListValue(); |
+ for (net::HttpRequestHeaders::Iterator it(request_headers); it.GetNext();) |
+ headers->Append(helpers::CreateHeaderDictionary(it.name(), it.value())); |
+ request_headers_.reset(headers); |
+} |
+ |
+void WebRequestEventDetails::SetAuthInfo( |
+ const net::AuthChallengeInfo& auth_info) { |
+ dict_.SetBoolean(keys::kIsProxyKey, auth_info.is_proxy); |
+ if (!auth_info.scheme.empty()) |
+ dict_.SetString(keys::kSchemeKey, auth_info.scheme); |
+ if (!auth_info.realm.empty()) |
+ dict_.SetString(keys::kRealmKey, auth_info.realm); |
+ base::DictionaryValue* challenger = new base::DictionaryValue(); |
+ challenger->SetString(keys::kHostKey, auth_info.challenger.host()); |
+ challenger->SetInteger(keys::kPortKey, auth_info.challenger.port()); |
+ dict_.Set(keys::kChallengerKey, challenger); |
+} |
+ |
+void WebRequestEventDetails::SetResponseHeaders( |
+ const net::URLRequest* request, |
+ const net::HttpResponseHeaders* response_headers) { |
+ if (!response_headers) { |
+ // Not all URLRequestJobs specify response headers. E.g. URLRequestFTPJob, |
+ // URLRequestFileJob and some redirects. |
+ dict_.SetInteger(keys::kStatusCodeKey, request->GetResponseCode()); |
+ dict_.SetString(keys::kStatusLineKey, ""); |
+ } else { |
+ dict_.SetInteger(keys::kStatusCodeKey, response_headers->response_code()); |
+ dict_.SetString(keys::kStatusLineKey, response_headers->GetStatusLine()); |
+ } |
+ |
+ if (extra_info_spec_ & ExtraInfoSpec::RESPONSE_HEADERS) { |
+ base::ListValue* headers = new base::ListValue(); |
+ if (response_headers) { |
+ void* iter = nullptr; |
+ std::string name; |
+ std::string value; |
+ while (response_headers->EnumerateHeaderLines(&iter, &name, &value)) |
+ headers->Append(helpers::CreateHeaderDictionary(name, value)); |
+ } |
+ response_headers_.reset(headers); |
+ } |
+} |
+ |
+void WebRequestEventDetails::SetResponseSource(const net::URLRequest* request) { |
+ dict_.SetBoolean(keys::kFromCache, request->was_cached()); |
+ const std::string response_ip = request->GetSocketAddress().host(); |
+ if (!response_ip.empty()) |
+ dict_.SetString(keys::kIpKey, response_ip); |
+} |
+ |
+void WebRequestEventDetails::DetermineFrameIdOnUI() { |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
+ content::RenderFrameHost* rfh = |
+ content::RenderFrameHost::FromID(render_process_id_, render_frame_id_); |
+ dict_.SetInteger(keys::kFrameIdKey, ExtensionApiFrameIdMap::GetFrameId(rfh)); |
+ dict_.SetInteger(keys::kParentFrameIdKey, |
+ ExtensionApiFrameIdMap::GetParentFrameId(rfh)); |
+} |
+ |
+void WebRequestEventDetails::DetermineFrameIdOnIO( |
+ const DeterminedFrameIdCallback& callback) { |
+ scoped_ptr<WebRequestEventDetails> self(this); |
+ ExtensionApiFrameIdMap::Get()->GetFrameIdOnIO( |
+ render_process_id_, render_frame_id_, |
+ base::Bind(&WebRequestEventDetails::OnDeterminedFrameId, |
+ base::Unretained(this), base::Passed(&self), callback)); |
+} |
+ |
+scoped_ptr<base::DictionaryValue> WebRequestEventDetails::GetFilteredDict( |
+ int extra_info_spec) const { |
+ scoped_ptr<base::DictionaryValue> result = dict_.CreateDeepCopy(); |
+ if ((extra_info_spec & ExtraInfoSpec::REQUEST_BODY) && request_body_) |
+ result->Set(keys::kRequestBodyKey, request_body_->CreateDeepCopy()); |
+ if ((extra_info_spec & ExtraInfoSpec::REQUEST_HEADERS) && request_headers_) |
+ result->Set(keys::kRequestHeadersKey, request_headers_->CreateDeepCopy()); |
+ if ((extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS) && response_headers_) |
+ result->Set(keys::kResponseHeadersKey, response_headers_->CreateDeepCopy()); |
+ return result; |
+} |
+ |
+scoped_ptr<base::DictionaryValue> WebRequestEventDetails::GetAndClearDict() { |
+ scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue); |
+ dict_.Swap(result.get()); |
+ return result; |
+} |
+ |
+void WebRequestEventDetails::OnDeterminedFrameId( |
+ scoped_ptr<WebRequestEventDetails> self, |
+ const DeterminedFrameIdCallback& callback, |
+ int extension_api_frame_id, |
+ int extension_api_parent_frame_id) { |
+ dict_.SetInteger(keys::kFrameIdKey, extension_api_frame_id); |
+ dict_.SetInteger(keys::kParentFrameIdKey, extension_api_parent_frame_id); |
+ callback.Run(std::move(self)); |
+} |
+ |
+} // namespace extensions |