diff options
author | jochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-03 20:46:35 +0000 |
---|---|---|
committer | jochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-03 20:46:35 +0000 |
commit | 7efc582d60227aa473c77c3309a96b2dfed52351 (patch) | |
tree | 4431c6c5355dcb71aba481c52a799acbfaaa66e4 | |
parent | ab3c20b28bf4712dffb4ae38d0d7762f71842a69 (diff) | |
download | chromium_src-7efc582d60227aa473c77c3309a96b2dfed52351.zip chromium_src-7efc582d60227aa473c77c3309a96b2dfed52351.tar.gz chromium_src-7efc582d60227aa473c77c3309a96b2dfed52351.tar.bz2 |
Add onAuthRequired signal to the webRequest API
BUG=none
TEST=api test
Review URL: http://codereview.chromium.org/7538024
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@95308 0039d316-1c4b-4281-b951-d872f2087c98
17 files changed, 1044 insertions, 4 deletions
diff --git a/chrome/browser/extensions/extension_webrequest_api.cc b/chrome/browser/extensions/extension_webrequest_api.cc index f619f61..bc978a7 100644 --- a/chrome/browser/extensions/extension_webrequest_api.cc +++ b/chrome/browser/extensions/extension_webrequest_api.cc @@ -9,6 +9,7 @@ #include "base/json/json_writer.h" #include "base/metrics/histogram.h" #include "base/string_number_conversions.h" +#include "base/utf_string_conversions.h" #include "base/values.h" #include "chrome/browser/extensions/extension_event_router.h" #include "chrome/browser/extensions/extension_info_map.h" @@ -26,6 +27,7 @@ #include "content/browser/browser_thread.h" #include "content/browser/renderer_host/resource_dispatcher_host.h" #include "content/browser/renderer_host/resource_dispatcher_host_request_info.h" +#include "net/base/auth.h" #include "net/base/net_errors.h" #include "net/base/net_log.h" #include "net/http/http_response_headers.h" @@ -44,7 +46,8 @@ static const char* const kWebRequestEvents[] = { keys::kOnCompleted, keys::kOnErrorOccurred, keys::kOnSendHeaders, - keys::kOnResponseStarted + keys::kOnAuthRequired, + keys::kOnResponseStarted, }; static const char* kResourceTypeStrings[] = { @@ -560,6 +563,47 @@ void ExtensionWebRequestEventRouter::OnSendHeaders( DispatchEvent(profile, request, listeners, args); } +void ExtensionWebRequestEventRouter::OnAuthRequired( + void* profile, + ExtensionInfoMap* extension_info_map, + net::URLRequest* request, + const net::AuthChallengeInfo& auth_info) { + if (!profile) + return; + + base::Time time(base::Time::Now()); + + if (!HasWebRequestScheme(request->url())) + return; + + 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; + + ListValue args; + DictionaryValue* dict = new DictionaryValue(); + dict->SetString(keys::kRequestIdKey, + base::Uint64ToString(request->identifier())); + dict->SetString(keys::kUrlKey, request->url().spec()); + dict->SetBoolean(keys::kIsProxyKey, auth_info.is_proxy); + dict->SetString(keys::kSchemeKey, WideToUTF8(auth_info.scheme)); + if (!auth_info.realm.empty()) + dict->SetString(keys::kRealmKey, WideToUTF8(auth_info.realm)); + dict->SetDouble(keys::kTimeStampKey, time.ToDoubleT() * 1000); + if (extra_info_spec & ExtraInfoSpec::REQUEST_HEADERS) { + dict->Set(keys::kResponseHeadersKey, + GetResponseHeadersList(request->response_headers())); + } + if (extra_info_spec & ExtraInfoSpec::STATUS_LINE) + dict->Set(keys::kStatusLineKey, GetStatusLine(request->response_headers())); + args.Append(dict); + + DispatchEvent(profile, request, listeners, args); +} + void ExtensionWebRequestEventRouter::OnBeforeRedirect( void* profile, ExtensionInfoMap* extension_info_map, diff --git a/chrome/browser/extensions/extension_webrequest_api.h b/chrome/browser/extensions/extension_webrequest_api.h index 5790c7e..7492bc9 100644 --- a/chrome/browser/extensions/extension_webrequest_api.h +++ b/chrome/browser/extensions/extension_webrequest_api.h @@ -31,6 +31,7 @@ class StringValue; } namespace net { +class AuthChallengeInfo; class HostPortPair; class HttpRequestHeaders; class HttpResponseHeaders; @@ -48,9 +49,10 @@ class ExtensionWebRequestEventRouter { kOnBeforeSendHeaders = 1 << 1, kOnSendHeaders = 1 << 2, kOnBeforeRedirect = 1 << 3, - kOnResponseStarted = 1 << 4, - kOnErrorOccurred = 1 << 5, - kOnCompleted = 1 << 6, + kOnAuthRequired = 1 << 4, + kOnResponseStarted = 1 << 5, + kOnErrorOccurred = 1 << 6, + kOnCompleted = 1 << 7, }; // Internal representation of the webRequest.RequestFilter type, used to @@ -168,6 +170,12 @@ class ExtensionWebRequestEventRouter { net::URLRequest* request, const net::HttpRequestHeaders& headers); + // Dispatches the onAuthRequired event. + void OnAuthRequired(void* profile, + ExtensionInfoMap* extension_info_map, + net::URLRequest* request, + const net::AuthChallengeInfo& auth_info); + // Dispatches the onBeforeRedirect event. This is fired for HTTP(s) requests // only. void OnBeforeRedirect(void* profile, diff --git a/chrome/browser/extensions/extension_webrequest_api_constants.cc b/chrome/browser/extensions/extension_webrequest_api_constants.cc index efa5b2f..dec2a05 100644 --- a/chrome/browser/extensions/extension_webrequest_api_constants.cc +++ b/chrome/browser/extensions/extension_webrequest_api_constants.cc @@ -23,6 +23,9 @@ const char kRequestHeadersKey[] = "requestHeaders"; const char kResponseHeadersKey[] = "responseHeaders"; const char kHeaderNameKey[] = "name"; const char kHeaderValueKey[] = "value"; +const char kIsProxyKey[] = "isProxy"; +const char kSchemeKey[] = "scheme"; +const char kRealmKey[] = "realm"; const char kOnBeforeRedirect[] = "experimental.webRequest.onBeforeRedirect"; const char kOnBeforeRequest[] = "experimental.webRequest.onBeforeRequest"; @@ -32,6 +35,8 @@ const char kOnCompleted[] = "experimental.webRequest.onCompleted"; const char kOnErrorOccurred[] = "experimental.webRequest.onErrorOccurred"; const char kOnResponseStarted[] = "experimental.webRequest.onResponseStarted"; const char kOnSendHeaders[] = "experimental.webRequest.onSendHeaders"; +const char kOnAuthRequired[] = "experimental.webRequest.onAuthRequired"; + const char kInvalidRedirectUrl[] = "redirectUrl '*' is not a valid URL."; const char kInvalidBlockingResponse[] = diff --git a/chrome/browser/extensions/extension_webrequest_api_constants.h b/chrome/browser/extensions/extension_webrequest_api_constants.h index 964c9bf..a0ad13d 100644 --- a/chrome/browser/extensions/extension_webrequest_api_constants.h +++ b/chrome/browser/extensions/extension_webrequest_api_constants.h @@ -29,8 +29,12 @@ extern const char kResponseHeadersKey[]; extern const char kHeadersKey[]; extern const char kHeaderNameKey[]; extern const char kHeaderValueKey[]; +extern const char kIsProxyKey[]; +extern const char kSchemeKey[]; +extern const char kRealmKey[]; // Events. +extern const char kOnAuthRequired[]; extern const char kOnBeforeRedirect[]; extern const char kOnBeforeRequest[]; extern const char kOnBeforeSendHeaders[]; diff --git a/chrome/browser/extensions/extension_webrequest_apitest.cc b/chrome/browser/extensions/extension_webrequest_apitest.cc index 3002959..aace273 100644 --- a/chrome/browser/extensions/extension_webrequest_apitest.cc +++ b/chrome/browser/extensions/extension_webrequest_apitest.cc @@ -5,9 +5,41 @@ #include "base/command_line.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/extensions/extension_webrequest_api.h" +#include "chrome/browser/ui/login/login_prompt.h" +#include "chrome/common/chrome_notification_types.h" #include "chrome/common/chrome_switches.h" +#include "content/common/notification_registrar.h" +#include "content/common/notification_service.h" #include "net/base/mock_host_resolver.h" +namespace { + +class CancelLoginDialog : public NotificationObserver { + public: + CancelLoginDialog() { + registrar_.Add(this, + chrome::NOTIFICATION_AUTH_NEEDED, + NotificationService::AllSources()); + } + + virtual ~CancelLoginDialog() {} + + virtual void Observe(int type, + const NotificationSource& source, + const NotificationDetails& details) { + LoginHandler* handler = + Details<LoginNotificationDetails>(details).ptr()->handler(); + handler->CancelAuth(); + } + + private: + NotificationRegistrar registrar_; + + DISALLOW_COPY_AND_ASSIGN(CancelLoginDialog); +}; + +} // namespace + class ExtensionWebRequestApiTest : public ExtensionApiTest { public: virtual void SetUpInProcessBrowserTestFixture() { @@ -29,5 +61,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, WebRequestEvents) { CommandLine::ForCurrentProcess()->AppendSwitch( switches::kEnableExperimentalExtensionApis); + CancelLoginDialog login_dialog_helper; + ASSERT_TRUE(RunExtensionTest("webrequest/events")) << message_; } diff --git a/chrome/browser/net/chrome_network_delegate.cc b/chrome/browser/net/chrome_network_delegate.cc index d5a27ce..41cedf3 100644 --- a/chrome/browser/net/chrome_network_delegate.cc +++ b/chrome/browser/net/chrome_network_delegate.cc @@ -137,3 +137,10 @@ void ChromeNetworkDelegate::OnPACScriptError(int line_number, ExtensionProxyEventRouter::GetInstance()->OnPACScriptError( event_router_.get(), profile_, line_number, error); } + +void ChromeNetworkDelegate::OnAuthRequired( + net::URLRequest* request, + const net::AuthChallengeInfo& auth_info) { + ExtensionWebRequestEventRouter::GetInstance()->OnAuthRequired( + profile_, extension_info_map_.get(), request, auth_info); +} diff --git a/chrome/browser/net/chrome_network_delegate.h b/chrome/browser/net/chrome_network_delegate.h index 182b069..980a26b 100644 --- a/chrome/browser/net/chrome_network_delegate.h +++ b/chrome/browser/net/chrome_network_delegate.h @@ -58,6 +58,8 @@ class ChromeNetworkDelegate : public net::NetworkDelegate { virtual void OnURLRequestDestroyed(net::URLRequest* request) OVERRIDE; virtual void OnPACScriptError(int line_number, const string16& error) OVERRIDE; + virtual void OnAuthRequired(net::URLRequest* request, + const net::AuthChallengeInfo& auth_info) OVERRIDE; scoped_refptr<ExtensionEventRouterForwarder> event_router_; void* profile_; diff --git a/chrome/common/extensions/api/extension_api.json b/chrome/common/extensions/api/extension_api.json index dcfbf30..ada7737 100644 --- a/chrome/common/extensions/api/extension_api.json +++ b/chrome/common/extensions/api/extension_api.json @@ -4837,6 +4837,45 @@ ] }, { + "name": "onAuthRequired", + "type": "function", + "description": "Fired when an authentication failure was received. Depending on whether the user provides credentials, the request is either reissued or cancelled.", + "parameters": [ + { + "type": "object", + "name": "details", + "properties": { + "requestId": {"type": "string", "description": "The ID of the request."}, + "url": {"type": "string"}, + "scheme": {"type": "string", "description": "The authentication scheme, e.g. Basic or Digest."}, + "realm": {"type": "string", "description": "The authentication realm provided by the server, if there is one.", "optional": true}, + "isProxy": {"type": "boolean", "description": "True for Proxy-Authenticate, false for WWW-Authenticate."}, + "timeStamp": {"type": "number", "description": "The time when the status line and response headers were received, in milliseconds since the epoch."}, + "responseHeaders": {"$ref": "HttpHeaders", "optional": true, "description": "The HTTP response headers that were received along with this response."}, + "statusLine": {"type": "string", "optional": true, "description": "HTTP status line of the response"} + } + } + ], + "extraParameters": [ + { + "$ref": "RequestFilter", + "optional": true, + "name": "filter", + "description": "A set of filters that restricts the events that will be sent to this listener." + }, + { + "type": "array", + "optional": true, + "name": "extraInfoSpec", + "description": "Array of extra information that should be passed to the listener function.", + "items": { + "type": "string", + "enum": ["statusLine", "responseHeaders"] + } + } + ] + }, + { "name": "onResponseStarted", "type": "function", "description": "Fired when the first byte of the response body is received. For HTTP requests, this means that the status line and response headers are available.", diff --git a/chrome/common/extensions/docs/experimental.webRequest.html b/chrome/common/extensions/docs/experimental.webRequest.html index de078bf..410c3c4 100644 --- a/chrome/common/extensions/docs/experimental.webRequest.html +++ b/chrome/common/extensions/docs/experimental.webRequest.html @@ -327,6 +327,8 @@ <a href="#global-events">Events</a> <ol> <li> + <a href="#event-onAuthRequired">onAuthRequired</a> + </li><li> <a href="#event-onBeforeRedirect">onBeforeRedirect</a> </li><li> <a href="#event-onBeforeRequest">onBeforeRequest</a> @@ -815,6 +817,805 @@ chrome.windows.onRemoved.addListener( <h3>Events</h3> <!-- iterates over all events --> <div class="apiItem"> + <a name="event-onAuthRequired"></a> + <h4>onAuthRequired</h4> + + <div class="summary"> + <!-- Note: intentionally longer 80 columns --> + <span class="subdued">chrome.experimental.webRequest.</span><span>onAuthRequired</span><span class="subdued">.addListener</span>(function(<span>object details</span>) <span class="subdued">{...}</span><span>, RequestFilter filter, array of string extraInfoSpec</span>)); + </div> + + <div class="description"> + <p class="todo" style="display: none; ">Undocumented.</p> + <p>Fired when an authentication failure was received. Depending on whether the user provides credentials, the request is either reissued or cancelled.</p> + + <!-- LISTENER PARAMETERS --> + <div> + <h4>Listener parameters</h4> + <dl> + <div> + <div> + <dt> + <var>details</var> + <em> + + <!-- TYPE --> + <div style="display:inline"> + ( + <span class="optional" style="display: none; ">optional</span> + <span class="enum" style="display: none; ">enumerated</span> + <span id="typeTemplate"> + <span style="display: none; "> + <a> Type</a> + </span> + <span> + <span style="display: none; "> + array of <span><span></span></span> + </span> + <span>object</span> + <span style="display: none; "></span> + </span> + </span> + ) + </div> + + </em> + </dt> + <dd class="todo"> + Undocumented. + </dd> + <dd style="display: none; "> + Description of this parameter from the json schema. + </dd> + <dd style="display: none; "> + This parameter was added in version + <b><span></span></b>. + You must omit this parameter in earlier versions, + and you may omit it in any version. If you require this + parameter, the manifest key + <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a> + can ensure that your extension won't be run in an earlier browser version. + </dd> + + <!-- OBJECT PROPERTIES --> + <dd> + <dl> + <div> + <div> + <dt> + <var>requestId</var> + <em> + + <!-- TYPE --> + <div style="display:inline"> + ( + <span class="optional" style="display: none; ">optional</span> + <span class="enum" style="display: none; ">enumerated</span> + <span id="typeTemplate"> + <span style="display: none; "> + <a> Type</a> + </span> + <span> + <span style="display: none; "> + array of <span><span></span></span> + </span> + <span>string</span> + <span style="display: none; "></span> + </span> + </span> + ) + </div> + + </em> + </dt> + <dd class="todo" style="display: none; "> + Undocumented. + </dd> + <dd>The ID of the request.</dd> + <dd style="display: none; "> + This parameter was added in version + <b><span></span></b>. + You must omit this parameter in earlier versions, + and you may omit it in any version. If you require this + parameter, the manifest key + <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a> + can ensure that your extension won't be run in an earlier browser version. + </dd> + + <!-- OBJECT PROPERTIES --> + <dd style="display: none; "> + <dl> + <div> + <div> + </div> + </div> + </dl> + </dd> + + <!-- OBJECT METHODS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- OBJECT EVENT FIELDS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- FUNCTION PARAMETERS --> + <dd style="display: none; "> + <div></div> + </dd> + + </div> + </div><div> + <div> + <dt> + <var>url</var> + <em> + + <!-- TYPE --> + <div style="display:inline"> + ( + <span class="optional" style="display: none; ">optional</span> + <span class="enum" style="display: none; ">enumerated</span> + <span id="typeTemplate"> + <span style="display: none; "> + <a> Type</a> + </span> + <span> + <span style="display: none; "> + array of <span><span></span></span> + </span> + <span>string</span> + <span style="display: none; "></span> + </span> + </span> + ) + </div> + + </em> + </dt> + <dd class="todo"> + Undocumented. + </dd> + <dd style="display: none; "> + Description of this parameter from the json schema. + </dd> + <dd style="display: none; "> + This parameter was added in version + <b><span></span></b>. + You must omit this parameter in earlier versions, + and you may omit it in any version. If you require this + parameter, the manifest key + <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a> + can ensure that your extension won't be run in an earlier browser version. + </dd> + + <!-- OBJECT PROPERTIES --> + <dd style="display: none; "> + <dl> + <div> + <div> + </div> + </div> + </dl> + </dd> + + <!-- OBJECT METHODS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- OBJECT EVENT FIELDS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- FUNCTION PARAMETERS --> + <dd style="display: none; "> + <div></div> + </dd> + + </div> + </div><div> + <div> + <dt> + <var>scheme</var> + <em> + + <!-- TYPE --> + <div style="display:inline"> + ( + <span class="optional" style="display: none; ">optional</span> + <span class="enum" style="display: none; ">enumerated</span> + <span id="typeTemplate"> + <span style="display: none; "> + <a> Type</a> + </span> + <span> + <span style="display: none; "> + array of <span><span></span></span> + </span> + <span>string</span> + <span style="display: none; "></span> + </span> + </span> + ) + </div> + + </em> + </dt> + <dd class="todo" style="display: none; "> + Undocumented. + </dd> + <dd>The authentication scheme, e.g. Basic or Digest.</dd> + <dd style="display: none; "> + This parameter was added in version + <b><span></span></b>. + You must omit this parameter in earlier versions, + and you may omit it in any version. If you require this + parameter, the manifest key + <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a> + can ensure that your extension won't be run in an earlier browser version. + </dd> + + <!-- OBJECT PROPERTIES --> + <dd style="display: none; "> + <dl> + <div> + <div> + </div> + </div> + </dl> + </dd> + + <!-- OBJECT METHODS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- OBJECT EVENT FIELDS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- FUNCTION PARAMETERS --> + <dd style="display: none; "> + <div></div> + </dd> + + </div> + </div><div> + <div> + <dt> + <var>realm</var> + <em> + + <!-- TYPE --> + <div style="display:inline"> + ( + <span class="optional">optional</span> + <span class="enum" style="display: none; ">enumerated</span> + <span id="typeTemplate"> + <span style="display: none; "> + <a> Type</a> + </span> + <span> + <span style="display: none; "> + array of <span><span></span></span> + </span> + <span>string</span> + <span style="display: none; "></span> + </span> + </span> + ) + </div> + + </em> + </dt> + <dd class="todo" style="display: none; "> + Undocumented. + </dd> + <dd>The authentication realm provided by the server, if there is one.</dd> + <dd style="display: none; "> + This parameter was added in version + <b><span></span></b>. + You must omit this parameter in earlier versions, + and you may omit it in any version. If you require this + parameter, the manifest key + <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a> + can ensure that your extension won't be run in an earlier browser version. + </dd> + + <!-- OBJECT PROPERTIES --> + <dd style="display: none; "> + <dl> + <div> + <div> + </div> + </div> + </dl> + </dd> + + <!-- OBJECT METHODS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- OBJECT EVENT FIELDS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- FUNCTION PARAMETERS --> + <dd style="display: none; "> + <div></div> + </dd> + + </div> + </div><div> + <div> + <dt> + <var>isProxy</var> + <em> + + <!-- TYPE --> + <div style="display:inline"> + ( + <span class="optional" style="display: none; ">optional</span> + <span class="enum" style="display: none; ">enumerated</span> + <span id="typeTemplate"> + <span style="display: none; "> + <a> Type</a> + </span> + <span> + <span style="display: none; "> + array of <span><span></span></span> + </span> + <span>boolean</span> + <span style="display: none; "></span> + </span> + </span> + ) + </div> + + </em> + </dt> + <dd class="todo" style="display: none; "> + Undocumented. + </dd> + <dd>True for Proxy-Authenticate, false for WWW-Authenticate.</dd> + <dd style="display: none; "> + This parameter was added in version + <b><span></span></b>. + You must omit this parameter in earlier versions, + and you may omit it in any version. If you require this + parameter, the manifest key + <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a> + can ensure that your extension won't be run in an earlier browser version. + </dd> + + <!-- OBJECT PROPERTIES --> + <dd style="display: none; "> + <dl> + <div> + <div> + </div> + </div> + </dl> + </dd> + + <!-- OBJECT METHODS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- OBJECT EVENT FIELDS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- FUNCTION PARAMETERS --> + <dd style="display: none; "> + <div></div> + </dd> + + </div> + </div><div> + <div> + <dt> + <var>timeStamp</var> + <em> + + <!-- TYPE --> + <div style="display:inline"> + ( + <span class="optional" style="display: none; ">optional</span> + <span class="enum" style="display: none; ">enumerated</span> + <span id="typeTemplate"> + <span style="display: none; "> + <a> Type</a> + </span> + <span> + <span style="display: none; "> + array of <span><span></span></span> + </span> + <span>number</span> + <span style="display: none; "></span> + </span> + </span> + ) + </div> + + </em> + </dt> + <dd class="todo" style="display: none; "> + Undocumented. + </dd> + <dd>The time when the status line and response headers were received, in milliseconds since the epoch.</dd> + <dd style="display: none; "> + This parameter was added in version + <b><span></span></b>. + You must omit this parameter in earlier versions, + and you may omit it in any version. If you require this + parameter, the manifest key + <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a> + can ensure that your extension won't be run in an earlier browser version. + </dd> + + <!-- OBJECT PROPERTIES --> + <dd style="display: none; "> + <dl> + <div> + <div> + </div> + </div> + </dl> + </dd> + + <!-- OBJECT METHODS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- OBJECT EVENT FIELDS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- FUNCTION PARAMETERS --> + <dd style="display: none; "> + <div></div> + </dd> + + </div> + </div><div> + <div> + <dt> + <var>responseHeaders</var> + <em> + + <!-- TYPE --> + <div style="display:inline"> + ( + <span class="optional">optional</span> + <span class="enum" style="display: none; ">enumerated</span> + <span id="typeTemplate"> + <span> + <a href="experimental.webRequest.html#type-HttpHeaders">HttpHeaders</a> + </span> + <span style="display: none; "> + <span> + array of <span><span></span></span> + </span> + <span>paramType</span> + <span></span> + </span> + </span> + ) + </div> + + </em> + </dt> + <dd class="todo" style="display: none; "> + Undocumented. + </dd> + <dd>The HTTP response headers that were received along with this response.</dd> + <dd style="display: none; "> + This parameter was added in version + <b><span></span></b>. + You must omit this parameter in earlier versions, + and you may omit it in any version. If you require this + parameter, the manifest key + <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a> + can ensure that your extension won't be run in an earlier browser version. + </dd> + + <!-- OBJECT PROPERTIES --> + <dd style="display: none; "> + <dl> + <div> + <div> + </div> + </div> + </dl> + </dd> + + <!-- OBJECT METHODS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- OBJECT EVENT FIELDS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- FUNCTION PARAMETERS --> + <dd style="display: none; "> + <div></div> + </dd> + + </div> + </div><div> + <div> + <dt> + <var>statusLine</var> + <em> + + <!-- TYPE --> + <div style="display:inline"> + ( + <span class="optional">optional</span> + <span class="enum" style="display: none; ">enumerated</span> + <span id="typeTemplate"> + <span style="display: none; "> + <a> Type</a> + </span> + <span> + <span style="display: none; "> + array of <span><span></span></span> + </span> + <span>string</span> + <span style="display: none; "></span> + </span> + </span> + ) + </div> + + </em> + </dt> + <dd class="todo" style="display: none; "> + Undocumented. + </dd> + <dd>HTTP status line of the response</dd> + <dd style="display: none; "> + This parameter was added in version + <b><span></span></b>. + You must omit this parameter in earlier versions, + and you may omit it in any version. If you require this + parameter, the manifest key + <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a> + can ensure that your extension won't be run in an earlier browser version. + </dd> + + <!-- OBJECT PROPERTIES --> + <dd style="display: none; "> + <dl> + <div> + <div> + </div> + </div> + </dl> + </dd> + + <!-- OBJECT METHODS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- OBJECT EVENT FIELDS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- FUNCTION PARAMETERS --> + <dd style="display: none; "> + <div></div> + </dd> + + </div> + </div> + </dl> + </dd> + + <!-- OBJECT METHODS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- OBJECT EVENT FIELDS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- FUNCTION PARAMETERS --> + <dd style="display: none; "> + <div></div> + </dd> + + </div> + </div> + </dl> + </div> + + <!-- EXTRA PARAMETERS --> + <div> + <h4>Extra parameters to addListener</h4> + <dl> + <div> + <div> + <dt> + <var>filter</var> + <em> + + <!-- TYPE --> + <div style="display:inline"> + ( + <span class="optional">optional</span> + <span class="enum" style="display: none; ">enumerated</span> + <span id="typeTemplate"> + <span> + <a href="experimental.webRequest.html#type-RequestFilter">RequestFilter</a> + </span> + <span style="display: none; "> + <span> + array of <span><span></span></span> + </span> + <span>paramType</span> + <span></span> + </span> + </span> + ) + </div> + + </em> + </dt> + <dd class="todo" style="display: none; "> + Undocumented. + </dd> + <dd>A set of filters that restricts the events that will be sent to this listener.</dd> + <dd style="display: none; "> + This parameter was added in version + <b><span></span></b>. + You must omit this parameter in earlier versions, + and you may omit it in any version. If you require this + parameter, the manifest key + <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a> + can ensure that your extension won't be run in an earlier browser version. + </dd> + + <!-- OBJECT PROPERTIES --> + <dd style="display: none; "> + <dl> + <div> + <div> + </div> + </div> + </dl> + </dd> + + <!-- OBJECT METHODS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- OBJECT EVENT FIELDS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- FUNCTION PARAMETERS --> + <dd style="display: none; "> + <div></div> + </dd> + + </div> + </div><div> + <div> + <dt> + <var>extraInfoSpec</var> + <em> + + <!-- TYPE --> + <div style="display:inline"> + ( + <span class="optional">optional</span> + <span class="enum" style="display: none; ">enumerated</span> + <span id="typeTemplate"> + <span style="display: none; "> + <a> Type</a> + </span> + <span> + <span> + array of <span><span> + <span style="display: none; "> + <a> Type</a> + </span> + <span> + <span style="display: none; "> + array of <span><span></span></span> + </span> + <span>string</span> + <span>["statusLine", "responseHeaders"]</span> + </span> + </span></span> + </span> + <span style="display: none; ">paramType</span> + <span style="display: none; "></span> + </span> + </span> + ) + </div> + + </em> + </dt> + <dd class="todo" style="display: none; "> + Undocumented. + </dd> + <dd>Array of extra information that should be passed to the listener function.</dd> + <dd style="display: none; "> + This parameter was added in version + <b><span></span></b>. + You must omit this parameter in earlier versions, + and you may omit it in any version. If you require this + parameter, the manifest key + <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a> + can ensure that your extension won't be run in an earlier browser version. + </dd> + + <!-- OBJECT PROPERTIES --> + <dd style="display: none; "> + <dl> + <div> + <div> + </div> + </div> + </dl> + </dd> + + <!-- OBJECT METHODS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- OBJECT EVENT FIELDS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- FUNCTION PARAMETERS --> + <dd style="display: none; "> + <div></div> + </dd> + + </div> + </div> + </dl> + </div> + + <!-- LISTENER RETURN VALUE --> + <h4 style="display: none; ">Listener returns</h4> + <dl> + <div style="display: none; "> + <div> + </div> + </div> + </dl> + + </div> <!-- /description --> + </div><div class="apiItem"> <a name="event-onBeforeRedirect"></a> <h4>onBeforeRedirect</h4> diff --git a/chrome/common/extensions/docs/samples.json b/chrome/common/extensions/docs/samples.json index b93c3a9..943c75e 100644 --- a/chrome/common/extensions/docs/samples.json +++ b/chrome/common/extensions/docs/samples.json @@ -80,6 +80,7 @@ "chrome.experimental.webNavigation.onErrorOccurred": "experimental.webNavigation.html#event-onErrorOccurred", "chrome.experimental.webRequest.addEventListener": "experimental.webRequest.html#method-addEventListener", "chrome.experimental.webRequest.eventHandled": "experimental.webRequest.html#method-eventHandled", + "chrome.experimental.webRequest.onAuthRequired": "experimental.webRequest.html#event-onAuthRequired", "chrome.experimental.webRequest.onBeforeRedirect": "experimental.webRequest.html#event-onBeforeRedirect", "chrome.experimental.webRequest.onBeforeRequest": "experimental.webRequest.html#event-onBeforeRequest", "chrome.experimental.webRequest.onBeforeSendHeaders": "experimental.webRequest.html#event-onBeforeSendHeaders", diff --git a/chrome/test/data/extensions/api_test/webrequest/events/test.html b/chrome/test/data/extensions/api_test/webrequest/events/test.html index eeece94..e7fcb96 100644 --- a/chrome/test/data/extensions/api_test/webrequest/events/test.html +++ b/chrome/test/data/extensions/api_test/webrequest/events/test.html @@ -14,6 +14,8 @@ var URL_HTTP_SIMPLE_LOAD_REDIRECT = 'http://www.a.com:PORT/server-redirect?'+URL_HTTP_SIMPLE_LOAD; var URL_ECHO_USER_AGENT = 'http://www.a.com:PORT/echoheader?User-Agent'; +var URL_AUTH_REQUIRED = + 'http://www.a.com:PORT/auth-basic'; function runTests(tests) { chrome.tabs.getSelected(null, function(tab) { @@ -25,6 +27,7 @@ function runTests(tests) { URL_HTTP_SIMPLE_LOAD = fixPort(URL_HTTP_SIMPLE_LOAD); URL_HTTP_SIMPLE_LOAD_REDIRECT = fixPort(URL_HTTP_SIMPLE_LOAD_REDIRECT); URL_ECHO_USER_AGENT = fixPort(URL_ECHO_USER_AGENT); + URL_AUTH_REQUIRED = fixPort(URL_AUTH_REQUIRED); chrome.test.runTests(tests); }); @@ -200,6 +203,10 @@ function initListeners(filter, extraInfoSpec) { function(details) { return captureEvent("onSendHeaders", details); }, filter, intersect(extraInfoSpec, ["requestHeaders"])); + chrome.experimental.webRequest.onAuthRequired.addListener( + function(details) { + return captureEvent("onAuthRequired", details); + }, filter, intersect(extraInfoSpec, ["responseHeaders", "statusLine"])); chrome.experimental.webRequest.onResponseStarted.addListener( function(details) { return captureEvent("onResponseStarted", details); @@ -230,6 +237,7 @@ function removeListeners() { } helper(chrome.experimental.webRequest.onBeforeRequest); helper(chrome.experimental.webRequest.onBeforeSendHeaders); + helper(chrome.experimental.webRequest.onAuthRequired); helper(chrome.experimental.webRequest.onSendHeaders); helper(chrome.experimental.webRequest.onResponseStarted); helper(chrome.experimental.webRequest.onBeforeRedirect); @@ -753,5 +761,68 @@ runTests([ }); }); }, + + // Loads a testserver page that requires authentication. + function authRequired() { + expect( + [ // events + { label: "onBeforeRequest", + event: "onBeforeRequest", + details: { + method: "GET", + tabId: tabId, + type: "main_frame", + url: URL_AUTH_REQUIRED, + frameUrl: URL_AUTH_REQUIRED + } + }, + { label: "onBeforeSendHeaders", + event: "onBeforeSendHeaders", + details: { + url: URL_AUTH_REQUIRED, + // Note: no requestHeaders because we don't ask for them. + }, + }, + { label: "onSendHeaders", + event: "onSendHeaders", + details: { + url: URL_AUTH_REQUIRED, + } + }, + { label: "onAuthRequired", + event: "onAuthRequired", + details: { + url: URL_AUTH_REQUIRED, + isProxy: false, + scheme: "basic", + realm: "testrealm", + } + }, + { label: "onResponseStarted", + event: "onResponseStarted", + details: { + url: URL_AUTH_REQUIRED, + fromCache: false, + statusCode: 401, + ip: "127.0.0.1" + } + }, + { label: "onCompleted", + event: "onCompleted", + details: { + url: URL_AUTH_REQUIRED, + fromCache: false, + statusCode: 401, + ip: "127.0.0.1" + } + }, + ], + [ // event order + ["onBeforeRequest", "onBeforeSendHeaders", "onSendHeaders", + "onAuthRequired", "onResponseStarted", "onCompleted"] + ], + {}, []); + navigateAndWait(URL_AUTH_REQUIRED); + }, ]); </script> diff --git a/net/base/network_delegate.cc b/net/base/network_delegate.cc index fc4ff57..28d0b31 100644 --- a/net/base/network_delegate.cc +++ b/net/base/network_delegate.cc @@ -69,4 +69,10 @@ void NetworkDelegate::NotifyPACScriptError(int line_number, OnPACScriptError(line_number, error); } +void NetworkDelegate::NotifyAuthRequired(URLRequest* request, + const AuthChallengeInfo& auth_info) { + DCHECK(CalledOnValidThread()); + OnAuthRequired(request, auth_info); +} + } // namespace net diff --git a/net/base/network_delegate.h b/net/base/network_delegate.h index 0c0c556..2506788 100644 --- a/net/base/network_delegate.h +++ b/net/base/network_delegate.h @@ -24,6 +24,7 @@ namespace net { // NOTE: It is not okay to add any compile-time dependencies on symbols outside // of net/base here, because we have a net_base library. Forward declarations // are ok. +class AuthChallengeInfo; class HostPortPair; class HttpRequestHeaders; class URLRequest; @@ -52,6 +53,8 @@ class NetworkDelegate : public base::NonThreadSafe { void NotifyCompleted(URLRequest* request); void NotifyURLRequestDestroyed(URLRequest* request); void NotifyPACScriptError(int line_number, const string16& error); + void NotifyAuthRequired(URLRequest* request, + const AuthChallengeInfo& auth_info); private: // This is the interface for subclasses of NetworkDelegate to implement. This @@ -99,6 +102,10 @@ class NetworkDelegate : public base::NonThreadSafe { // Corresponds to ProxyResolverJSBindings::OnError. virtual void OnPACScriptError(int line_number, const string16& error) = 0; + + // Corresponds to URLRequest::Delegate::OnAuthRequired. + virtual void OnAuthRequired(URLRequest* reqest, + const AuthChallengeInfo& auth_info) = 0; }; } // namespace net diff --git a/net/proxy/network_delegate_error_observer_unittest.cc b/net/proxy/network_delegate_error_observer_unittest.cc index 1cb9790..4eec44d 100644 --- a/net/proxy/network_delegate_error_observer_unittest.cc +++ b/net/proxy/network_delegate_error_observer_unittest.cc @@ -49,6 +49,8 @@ class TestNetworkDelegate : public net::NetworkDelegate { const string16& error) OVERRIDE { got_pac_error_ = true; } + virtual void OnAuthRequired(URLRequest* request, + const AuthChallengeInfo& auth_info) OVERRIDE {} bool got_pac_error_; }; diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc index 97c4d06..b71b36b 100644 --- a/net/url_request/url_request.cc +++ b/net/url_request/url_request.cc @@ -748,6 +748,8 @@ void URLRequest::NotifyAuthRequired(AuthChallengeInfo* auth_info) { // URLRequestTestHTTP.BasicAuthWithCookies. In both cases we observe a // call sequence of OnBeforeSendHeaders -> OnSendHeaders -> // OnBeforeSendHeaders. + if (context_ && context_->network_delegate()) + context_->network_delegate()->NotifyAuthRequired(this, *auth_info); if (delegate_) delegate_->OnAuthRequired(this, auth_info); diff --git a/net/url_request/url_request_test_util.cc b/net/url_request/url_request_test_util.cc index 8c1a4fe..7dca50f 100644 --- a/net/url_request/url_request_test_util.cc +++ b/net/url_request/url_request_test_util.cc @@ -456,3 +456,8 @@ net::URLRequestJob* TestNetworkDelegate::OnMaybeCreateURLRequestJob( void TestNetworkDelegate::OnPACScriptError(int line_number, const string16& error) { } + +void TestNetworkDelegate::OnAuthRequired( + net::URLRequest* reqest, + const net::AuthChallengeInfo& auth_info) { +} diff --git a/net/url_request/url_request_test_util.h b/net/url_request/url_request_test_util.h index 8b3206ea..226163e 100644 --- a/net/url_request/url_request_test_util.h +++ b/net/url_request/url_request_test_util.h @@ -207,6 +207,8 @@ class TestNetworkDelegate : public net::NetworkDelegate { virtual net::URLRequestJob* OnMaybeCreateURLRequestJob( net::URLRequest* request); virtual void OnPACScriptError(int line_number, const string16& error); + virtual void OnAuthRequired(net::URLRequest* request, + const net::AuthChallengeInfo& auth_info); void InitRequestStatesIfNew(int request_id); |