| Index: chrome/browser/extensions/extension_webrequest_api.cc
|
| diff --git a/chrome/browser/extensions/extension_webrequest_api.cc b/chrome/browser/extensions/extension_webrequest_api.cc
|
| index 208554ab237ce310128d47b92956e1261391a06e..a225112177130fa49cf5f796ef697dd00031f01c 100644
|
| --- a/chrome/browser/extensions/extension_webrequest_api.cc
|
| +++ b/chrome/browser/extensions/extension_webrequest_api.cc
|
| @@ -338,6 +338,15 @@ struct ExtensionWebRequestEventRouter::BlockedRequest {
|
| // OnHeadersReceived.
|
| scoped_refptr<net::HttpResponseHeaders>* override_response_headers;
|
|
|
| + // If non-empty, this contains the auth credentials that may be filled in.
|
| + // Only valid for OnAuthRequired.
|
| + net::AuthCredentials* auth_credentials;
|
| +
|
| + // The callback to invoke for auth. If |auth_callback.is_null()| is false,
|
| + // |callback| must be NULL.
|
| + // Only valid for OnAuthRequired.
|
| + net::NetworkDelegate::AuthCallback auth_callback;
|
| +
|
| // Time the request was paused. Used for logging purposes.
|
| base::Time blocking_time;
|
|
|
| @@ -352,7 +361,8 @@ struct ExtensionWebRequestEventRouter::BlockedRequest {
|
| callback(NULL),
|
| new_url(NULL),
|
| request_headers(NULL),
|
| - override_response_headers(NULL) {}
|
| + override_response_headers(NULL),
|
| + auth_credentials(NULL) {}
|
| };
|
|
|
| bool ExtensionWebRequestEventRouter::RequestFilter::InitFromValue(
|
| @@ -636,23 +646,28 @@ int ExtensionWebRequestEventRouter::OnHeadersReceived(
|
| return net::OK;
|
| }
|
|
|
| -void ExtensionWebRequestEventRouter::OnAuthRequired(
|
| +net::NetworkDelegate::AuthRequiredResponse
|
| +ExtensionWebRequestEventRouter::OnAuthRequired(
|
| void* profile,
|
| ExtensionInfoMap* extension_info_map,
|
| net::URLRequest* request,
|
| - const net::AuthChallengeInfo& auth_info) {
|
| + const net::AuthChallengeInfo& auth_info,
|
| + const net::NetworkDelegate::AuthCallback& callback,
|
| + net::AuthCredentials* credentials) {
|
| + // No profile means that this is for authentication challenges in the
|
| + // system context. Skip in that case.
|
| if (!profile)
|
| - return;
|
| + return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
|
|
|
| if (!HasWebRequestScheme(request->url()))
|
| - return;
|
| + return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
|
|
|
| int extra_info_spec = 0;
|
| std::vector<const EventListener*> listeners =
|
| GetMatchingListeners(profile, extension_info_map,
|
| keys::kOnAuthRequired, request, &extra_info_spec);
|
| if (listeners.empty())
|
| - return;
|
| + return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
|
|
|
| ListValue args;
|
| DictionaryValue* dict = new DictionaryValue();
|
| @@ -673,7 +688,14 @@ void ExtensionWebRequestEventRouter::OnAuthRequired(
|
| }
|
| args.Append(dict);
|
|
|
| - DispatchEvent(profile, request, listeners, args);
|
| + if (DispatchEvent(profile, request, listeners, args)) {
|
| + blocked_requests_[request->identifier()].event = kOnAuthRequired;
|
| + blocked_requests_[request->identifier()].auth_callback = callback;
|
| + blocked_requests_[request->identifier()].auth_credentials = credentials;
|
| + blocked_requests_[request->identifier()].net_log = &request->net_log();
|
| + return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_IO_PENDING;
|
| + }
|
| + return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
|
| }
|
|
|
| void ExtensionWebRequestEventRouter::OnBeforeRedirect(
|
| @@ -1147,6 +1169,9 @@ linked_ptr<ExtensionWebRequestEventRouter::EventResponseDelta>
|
| }
|
| }
|
|
|
| + if (blocked_request->event == kOnAuthRequired)
|
| + result->auth_credentials.swap(response->auth_credentials);
|
| +
|
| return result;
|
| }
|
|
|
| @@ -1191,7 +1216,6 @@ void ExtensionWebRequestEventRouter::MergeOnBeforeSendHeadersResponses(
|
| // We assume here that the deltas are sorted in decreasing extension
|
| // precedence (i.e. decreasing extension installation time).
|
| for (delta = deltas.begin(); delta != deltas.end(); ++delta) {
|
| -
|
| if ((*delta)->modified_request_headers.IsEmpty() &&
|
| (*delta)->deleted_request_headers.empty()) {
|
| continue;
|
| @@ -1314,6 +1338,37 @@ void ExtensionWebRequestEventRouter::MergeOnHeadersReceivedResponses(
|
| }
|
| }
|
|
|
| +bool ExtensionWebRequestEventRouter::MergeOnAuthRequiredResponses(
|
| + BlockedRequest* request,
|
| + std::list<std::string>* conflicting_extensions) const {
|
| + CHECK(request);
|
| + CHECK(request->auth_credentials);
|
| + bool credentials_set = false;
|
| +
|
| + const EventResponseDeltas& deltas = request->response_deltas;
|
| + for (EventResponseDeltas::const_iterator delta = deltas.begin();
|
| + delta != deltas.end();
|
| + ++delta) {
|
| + if (!(*delta)->auth_credentials.get())
|
| + continue;
|
| + if (credentials_set) {
|
| + conflicting_extensions->push_back((*delta)->extension_id);
|
| + request->net_log->AddEvent(
|
| + net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT,
|
| + make_scoped_refptr(
|
| + new NetLogExtensionIdParameter((*delta)->extension_id)));
|
| + } else {
|
| + request->net_log->AddEvent(
|
| + net::NetLog::TYPE_CHROME_EXTENSION_PROVIDE_AUTH_CREDENTIALS,
|
| + make_scoped_refptr(
|
| + new NetLogExtensionIdParameter((*delta)->extension_id)));
|
| + *request->auth_credentials = *(*delta)->auth_credentials;
|
| + credentials_set = true;
|
| + }
|
| + }
|
| + return credentials_set;
|
| +}
|
| +
|
| void ExtensionWebRequestEventRouter::DecrementBlockCount(
|
| void* profile,
|
| const std::string& extension_id,
|
| @@ -1344,14 +1399,14 @@ void ExtensionWebRequestEventRouter::DecrementBlockCount(
|
| if (num_handlers_blocking == 0) {
|
| request_time_tracker_->IncrementTotalBlockTime(request_id, block_time);
|
|
|
| - EventResponseDeltas::iterator i;
|
| EventResponseDeltas& deltas = blocked_request.response_deltas;
|
| -
|
| bool canceled = false;
|
| - for (i = deltas.begin(); i != deltas.end(); ++i) {
|
| + bool credentials_set = false;
|
| + for (EventResponseDeltas::const_iterator i = deltas.begin();
|
| + i != deltas.end(); ++i) {
|
| if ((*i)->cancel) {
|
| - canceled = true;
|
| - blocked_request.net_log->AddEvent(
|
| + canceled = true;
|
| + blocked_request.net_log->AddEvent(
|
| net::NetLog::TYPE_CHROME_EXTENSION_ABORTED_REQUEST,
|
| make_scoped_refptr(
|
| new NetLogExtensionIdParameter((*i)->extension_id)));
|
| @@ -1364,7 +1419,8 @@ void ExtensionWebRequestEventRouter::DecrementBlockCount(
|
|
|
| if (blocked_request.event == kOnBeforeRequest) {
|
| CHECK(blocked_request.callback);
|
| - MergeOnBeforeRequestResponses(&blocked_request, &conflicting_extensions);
|
| + MergeOnBeforeRequestResponses(&blocked_request,
|
| + &conflicting_extensions);
|
| } else if (blocked_request.event == kOnBeforeSendHeaders) {
|
| CHECK(blocked_request.callback);
|
| MergeOnBeforeSendHeadersResponses(&blocked_request,
|
| @@ -1373,6 +1429,12 @@ void ExtensionWebRequestEventRouter::DecrementBlockCount(
|
| CHECK(blocked_request.callback);
|
| MergeOnHeadersReceivedResponses(&blocked_request,
|
| &conflicting_extensions);
|
| + } else if (blocked_request.event == kOnAuthRequired) {
|
| + CHECK(!blocked_request.callback);
|
| + CHECK(!blocked_request.auth_callback.is_null());
|
| + credentials_set = MergeOnAuthRequiredResponses(
|
| + &blocked_request,
|
| + &conflicting_extensions);
|
| } else {
|
| NOTREACHED();
|
| }
|
| @@ -1403,6 +1465,18 @@ void ExtensionWebRequestEventRouter::DecrementBlockCount(
|
| // might trigger the next event.
|
| blocked_requests_.erase(request_id);
|
| callback->Run(rv);
|
| + } else if (!blocked_request.auth_callback.is_null()) {
|
| + net::NetworkDelegate::AuthRequiredResponse response =
|
| + net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
|
| + if (canceled) {
|
| + response = net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_CANCEL_AUTH;
|
| + } else if (credentials_set) {
|
| + response = net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_SET_AUTH;
|
| + }
|
| + net::NetworkDelegate::AuthCallback callback =
|
| + blocked_request.auth_callback;
|
| + blocked_requests_.erase(request_id);
|
| + callback.Run(response);
|
| } else {
|
| blocked_requests_.erase(request_id);
|
| }
|
| @@ -1575,6 +1649,20 @@ bool WebRequestEventHandled::RunImpl() {
|
| response_headers_string += '\n';
|
| response->response_headers_string.swap(response_headers_string);
|
| }
|
| +
|
| + if (value->HasKey(keys::kAuthCredentialsKey)) {
|
| + DictionaryValue* credentials_value = NULL;
|
| + EXTENSION_FUNCTION_VALIDATE(value->GetDictionary(
|
| + keys::kAuthCredentialsKey,
|
| + &credentials_value));
|
| + response->auth_credentials.reset(new net::AuthCredentials());
|
| + EXTENSION_FUNCTION_VALIDATE(
|
| + credentials_value->GetString(keys::kUsernameKey,
|
| + &response->auth_credentials->username));
|
| + EXTENSION_FUNCTION_VALIDATE(
|
| + credentials_value->GetString(keys::kPasswordKey,
|
| + &response->auth_credentials->password));
|
| + }
|
| }
|
|
|
| ExtensionWebRequestEventRouter::GetInstance()->OnEventHandled(
|
|
|