summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authordarin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-30 18:01:39 +0000
committerdarin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-30 18:01:39 +0000
commit6568a9e384e0f92422c68d4f31fb401df4acbaed (patch)
tree477e1e2de4dd34d79e47a8a1e3b922ff3cecd83a /chrome
parentae5ca890de8d9f1a91f5198741c76f375146693b (diff)
downloadchromium_src-6568a9e384e0f92422c68d4f31fb401df4acbaed.zip
chromium_src-6568a9e384e0f92422c68d4f31fb401df4acbaed.tar.gz
chromium_src-6568a9e384e0f92422c68d4f31fb401df4acbaed.tar.bz2
Add plumbing for allowing the renderer to intercept and cancel redirects before
they are sent. A good portion of this CL is to support the new UI test. The IPC to notify the renderer of a redirect now includes a ResponseInfo struct allowing WebURLLoaderImpl to provide detailed response info (including response headers) to WebKit. This isn't strictly necessary, but I thought I'd include this to make the code more future proof. A cross origin restriction is added to SyncResourceHandler::OnRequestRedirected that mimics the code in WebCore/platform/network/cf/ResourceHandleCFNet.cpp. This is most unfortunate, and I filed a bug at bugs.webkit.org about the similar duplication of logic in WebCore. There seemed to be enough code paths leading to request cancellation at the ResourceDispatcher level that I couldn't easily ensure that a request only gets cancelled once. So, I added an is_cancelled flag to record if it is not necessary to send a ViewHostMsg_CancelRequest IPC. This avoids some warnings in the ResourceDispatcherHost. To support my UI test, I needed to change URLRequestMockHttpJob to know how to serve redirects. I moved URLRequestHttpJob::IsRedirectResponse to its base class, URLRequestJob so that the implementation could be shared. This revealed a minor bug in URLRequest. We were never resetting response_info_ upon following a redirect. I added this code consolidated similar code from URLRequest::Redirect and URLRequest::RestartWithJob into a new PrepareToRestart method. To support my UI test, I added a "hit count" field to URLRequestFilter, and I added an associated automation IPC to query the value. The test was a bit challenging to write because there is no way to tell the difference from JS. Before and after, it appears to JS as though the cross-origin redirect failed. However, the server can see the extra redirect request. So, I simply record the number of hits against URLs of the form http://mock.http/foo, and use that to observe if any extra requests were made. I implemented the new IPC message by extending the AutomationResourceMessageFilter. This allowed me to trap the IPC message on the IO thread where it is safe to probe the URLRequestFilter. I then changed the implementation of AutomationMsg_SetFilteredInet to work similarly. I revised URLRequestMockHTTPJob::GetOnDiskPath to support ports. This actually allowed me to reuse URLRequestMockHTTPJob to service URLs in different security origins. My test redirects from http://mock.http/ to http://mock.http:4000/. Please see the comments in cross-origin-redirect-blocked.html for details about how the test functions. R=brettw,wtc BUG=16413 TEST=covered by resource_dispatcher_host_uitest.cc Review URL: http://codereview.chromium.org/159370 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@22067 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/automation/automation_provider.cc6
-rw-r--r--chrome/browser/automation/automation_provider.h1
-rw-r--r--chrome/browser/automation/automation_resource_message_filter.cc28
-rw-r--r--chrome/browser/automation/automation_resource_message_filter.h3
-rw-r--r--chrome/browser/net/url_request_mock_http_job.cc23
-rw-r--r--chrome/browser/net/url_request_mock_http_job.h1
-rw-r--r--chrome/browser/net/url_request_mock_util.cc57
-rw-r--r--chrome/browser/renderer_host/async_resource_handler.cc10
-rw-r--r--chrome/browser/renderer_host/async_resource_handler.h3
-rw-r--r--chrome/browser/renderer_host/buffered_resource_handler.cc7
-rw-r--r--chrome/browser/renderer_host/buffered_resource_handler.h3
-rw-r--r--chrome/browser/renderer_host/cross_site_resource_handler.cc7
-rw-r--r--chrome/browser/renderer_host/cross_site_resource_handler.h3
-rw-r--r--chrome/browser/renderer_host/download_resource_handler.cc4
-rw-r--r--chrome/browser/renderer_host/download_resource_handler.h3
-rw-r--r--chrome/browser/renderer_host/download_throttling_resource_handler.cc13
-rw-r--r--chrome/browser/renderer_host/download_throttling_resource_handler.h3
-rw-r--r--chrome/browser/renderer_host/resource_dispatcher_host.cc122
-rw-r--r--chrome/browser/renderer_host/resource_dispatcher_host.h5
-rw-r--r--chrome/browser/renderer_host/resource_dispatcher_host_uitest.cc17
-rw-r--r--chrome/browser/renderer_host/resource_handler.h8
-rw-r--r--chrome/browser/renderer_host/safe_browsing_resource_handler.cc10
-rw-r--r--chrome/browser/renderer_host/safe_browsing_resource_handler.h3
-rw-r--r--chrome/browser/renderer_host/save_file_resource_handler.cc4
-rw-r--r--chrome/browser/renderer_host/save_file_resource_handler.h3
-rw-r--r--chrome/browser/renderer_host/sync_resource_handler.cc11
-rw-r--r--chrome/browser/renderer_host/sync_resource_handler.h3
-rw-r--r--chrome/common/render_messages_internal.h14
-rw-r--r--chrome/common/resource_dispatcher.cc50
-rw-r--r--chrome/common/resource_dispatcher.h40
-rw-r--r--chrome/common/resource_dispatcher_unittest.cc5
-rw-r--r--chrome/common/security_filter_peer.cc5
-rw-r--r--chrome/common/security_filter_peer.h4
-rw-r--r--chrome/plugin/chrome_plugin_host.cc5
-rw-r--r--chrome/test/automation/automation_messages_internal.h6
-rw-r--r--chrome/test/automation/automation_proxy.cc7
-rw-r--r--chrome/test/automation/automation_proxy.h4
-rw-r--r--chrome/test/data/cross-origin-redirect-blocked.html53
-rw-r--r--chrome/test/data/redirect-to-title2.html1
-rw-r--r--chrome/test/data/redirect-to-title2.html.mock-http-headers2
40 files changed, 388 insertions, 169 deletions
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc
index 3330b7d..67ee526 100644
--- a/chrome/browser/automation/automation_provider.cc
+++ b/chrome/browser/automation/automation_provider.cc
@@ -977,7 +977,6 @@ void AutomationProvider::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(AutomationMsg_GetFocusedViewID, GetFocusedViewID)
IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_InspectElement,
HandleInspectElementRequest)
- IPC_MESSAGE_HANDLER(AutomationMsg_SetFilteredInet, SetFilteredInet)
IPC_MESSAGE_HANDLER(AutomationMsg_DownloadDirectory, GetDownloadDirectory)
IPC_MESSAGE_HANDLER(AutomationMsg_SetProxyConfig, SetProxyConfig);
IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_OpenNewBrowserWindow,
@@ -2107,11 +2106,6 @@ void AutomationProvider::ReceivedInspectElementResponse(int num_resources) {
}
}
-void AutomationProvider::SetFilteredInet(const IPC::Message& message,
- bool enabled) {
- chrome_browser_net::SetUrlRequestMocksEnabled(enabled);
-}
-
class SetProxyConfigTask : public Task {
public:
explicit SetProxyConfigTask(net::ProxyService* proxy_service,
diff --git a/chrome/browser/automation/automation_provider.h b/chrome/browser/automation/automation_provider.h
index 1c92be6..0d9b08c 100644
--- a/chrome/browser/automation/automation_provider.h
+++ b/chrome/browser/automation/automation_provider.h
@@ -217,6 +217,7 @@ class AutomationProvider : public base::RefCounted<AutomationProvider>,
void GetShelfVisibility(int handle, bool* visible);
void SetShelfVisibility(int handle, bool visible);
void SetFilteredInet(const IPC::Message& message, bool enabled);
+ void GetFilteredInetHitCount(int* hit_count);
void SetProxyConfig(const std::string& new_proxy_config);
#if defined(OS_WIN)
diff --git a/chrome/browser/automation/automation_resource_message_filter.cc b/chrome/browser/automation/automation_resource_message_filter.cc
index 15e5325..46ee1e8 100644
--- a/chrome/browser/automation/automation_resource_message_filter.cc
+++ b/chrome/browser/automation/automation_resource_message_filter.cc
@@ -5,7 +5,16 @@
#include "chrome/browser/automation/automation_resource_message_filter.h"
#include "base/message_loop.h"
+#include "base/path_service.h"
#include "chrome/browser/automation/url_request_automation_job.h"
+#include "chrome/browser/net/url_request_failed_dns_job.h"
+#include "chrome/browser/net/url_request_mock_http_job.h"
+#include "chrome/browser/net/url_request_mock_util.h"
+#include "chrome/browser/net/url_request_slow_download_job.h"
+#include "chrome/browser/net/url_request_slow_http_job.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/test/automation/automation_messages.h"
+#include "net/url_request/url_request_filter.h"
MessageLoop* AutomationResourceMessageFilter::io_loop_ = NULL;
@@ -54,7 +63,16 @@ bool AutomationResourceMessageFilter::OnMessageReceived(
}
}
- return false;
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(AutomationResourceMessageFilter, message)
+ IPC_MESSAGE_HANDLER(AutomationMsg_SetFilteredInet,
+ OnSetFilteredInet)
+ IPC_MESSAGE_HANDLER(AutomationMsg_GetFilteredInetHitCount,
+ OnGetFilteredInetHitCount)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+
+ return handled;
}
// Called on the IPC thread:
@@ -142,3 +160,11 @@ bool AutomationResourceMessageFilter::LookupRegisteredRenderView(
return found;
}
+void AutomationResourceMessageFilter::OnSetFilteredInet(bool enable) {
+ chrome_browser_net::SetUrlRequestMocksEnabled(enable);
+}
+
+void AutomationResourceMessageFilter::OnGetFilteredInetHitCount(
+ int* hit_count) {
+ *hit_count = URLRequestFilter::GetInstance()->hit_count();
+}
diff --git a/chrome/browser/automation/automation_resource_message_filter.h b/chrome/browser/automation/automation_resource_message_filter.h
index 240bafb..ebd6464 100644
--- a/chrome/browser/automation/automation_resource_message_filter.h
+++ b/chrome/browser/automation/automation_resource_message_filter.h
@@ -72,6 +72,9 @@ class AutomationResourceMessageFilter
static void UnRegisterRenderViewInIOThread(int renderer_pid, int renderer_id);
private:
+ void OnSetFilteredInet(bool enable);
+ void OnGetFilteredInetHitCount(int* hit_count);
+
// A unique renderer id is a combination of renderer process id and
// it's routing id.
struct RendererId {
diff --git a/chrome/browser/net/url_request_mock_http_job.cc b/chrome/browser/net/url_request_mock_http_job.cc
index fc654be..7e0cd71 100644
--- a/chrome/browser/net/url_request_mock_http_job.cc
+++ b/chrome/browser/net/url_request_mock_http_job.cc
@@ -46,21 +46,13 @@ GURL URLRequestMockHTTPJob::GetMockUrl(const std::wstring& path) {
FilePath URLRequestMockHTTPJob::GetOnDiskPath(const std::wstring& base_path,
URLRequest* request,
const std::string& scheme) {
- std::wstring file_url(L"file:///");
- file_url += base_path;
- const std::string& url = request->url().spec();
- // Fix up the url to be the file url we're loading from disk.
- std::string host_prefix("http://");
- host_prefix.append(kMockHostname);
- size_t host_prefix_len = host_prefix.length();
- if (url.compare(0, host_prefix_len, host_prefix.data(),
- host_prefix_len) == 0) {
- file_url += UTF8ToWide(url.substr(host_prefix_len));
- }
+ std::string file_url("file:///");
+ file_url += WideToUTF8(base_path);
+ file_url += request->url().path();
// Convert the file:/// URL to a path on disk.
FilePath file_path;
- net::FileURLToFilePath(GURL(WideToUTF8(file_url)), &file_path);
+ net::FileURLToFilePath(GURL(file_url), &file_path);
return file_path;
}
@@ -74,6 +66,13 @@ void URLRequestMockHTTPJob::GetResponseInfo(net::HttpResponseInfo* info) {
GetResponseInfoConst(info);
}
+bool URLRequestMockHTTPJob::IsRedirectResponse(GURL* location,
+ int* http_status_code) {
+ // Override the URLRequestFileJob implementation to invoke the default one
+ // based on HttpResponseInfo.
+ return URLRequestJob::IsRedirectResponse(location, http_status_code);
+}
+
// Private const version.
void URLRequestMockHTTPJob::GetResponseInfoConst(
net::HttpResponseInfo* info) const {
diff --git a/chrome/browser/net/url_request_mock_http_job.h b/chrome/browser/net/url_request_mock_http_job.h
index 36e6acb..92cc359 100644
--- a/chrome/browser/net/url_request_mock_http_job.h
+++ b/chrome/browser/net/url_request_mock_http_job.h
@@ -19,6 +19,7 @@ class URLRequestMockHTTPJob : public URLRequestFileJob {
virtual bool GetMimeType(std::string* mime_type) const;
virtual bool GetCharset(std::string* charset);
virtual void GetResponseInfo(net::HttpResponseInfo* info);
+ virtual bool IsRedirectResponse(GURL* location, int* http_status_code);
static URLRequest::ProtocolFactory Factory;
diff --git a/chrome/browser/net/url_request_mock_util.cc b/chrome/browser/net/url_request_mock_util.cc
index ad0ed09..9a559b1 100644
--- a/chrome/browser/net/url_request_mock_util.cc
+++ b/chrome/browser/net/url_request_mock_util.cc
@@ -6,11 +6,8 @@
#include <string>
-#include "base/message_loop.h"
#include "base/path_service.h"
-#include "base/task.h"
-#include "base/thread.h"
-#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/net/url_request_failed_dns_job.h"
#include "chrome/browser/net/url_request_mock_http_job.h"
#include "chrome/browser/net/url_request_slow_download_job.h"
@@ -18,47 +15,27 @@
#include "chrome/common/chrome_paths.h"
#include "net/url_request/url_request_filter.h"
-namespace {
+namespace chrome_browser_net {
-// Helper class for making changes to the URLRequest ProtocolFactory on the
-// IO thread.
-class SetUrlRequestMocksEnabledTask : public Task {
- public:
- explicit SetUrlRequestMocksEnabledTask(bool enabled) : enabled_(enabled) {
- }
+void SetUrlRequestMocksEnabled(bool enabled) {
+ // Since this involves changing the URLRequest ProtocolFactory, we need to
+ // run on the IO thread.
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
- virtual void Run() {
- if (enabled_) {
- URLRequestFilter::GetInstance()->ClearHandlers();
+ if (enabled) {
+ URLRequestFilter::GetInstance()->ClearHandlers();
- URLRequestFailedDnsJob::AddUrlHandler();
- URLRequestSlowDownloadJob::AddUrlHandler();
+ URLRequestFailedDnsJob::AddUrlHandler();
+ URLRequestSlowDownloadJob::AddUrlHandler();
- std::wstring root_http;
- PathService::Get(chrome::DIR_TEST_DATA, &root_http);
- URLRequestMockHTTPJob::AddUrlHandler(root_http);
- URLRequestSlowHTTPJob::AddUrlHandler(root_http);
- } else {
- // Revert to the default handlers.
- URLRequestFilter::GetInstance()->ClearHandlers();
- }
+ std::wstring root_http;
+ PathService::Get(chrome::DIR_TEST_DATA, &root_http);
+ URLRequestMockHTTPJob::AddUrlHandler(root_http);
+ URLRequestSlowHTTPJob::AddUrlHandler(root_http);
+ } else {
+ // Revert to the default handlers.
+ URLRequestFilter::GetInstance()->ClearHandlers();
}
-
- private:
- bool enabled_;
-
- DISALLOW_COPY_AND_ASSIGN(SetUrlRequestMocksEnabledTask);
-};
-
-} // namespace
-
-namespace chrome_browser_net {
-
-void SetUrlRequestMocksEnabled(bool enabled) {
- // Since this involves changing the URLRequest ProtocolFactory, we want to
- // run on the IO thread.
- g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
- new SetUrlRequestMocksEnabledTask(enabled));
}
} // namespace chrome_browser_net
diff --git a/chrome/browser/renderer_host/async_resource_handler.cc b/chrome/browser/renderer_host/async_resource_handler.cc
index 6b69db3..dfd1f56 100644
--- a/chrome/browser/renderer_host/async_resource_handler.cc
+++ b/chrome/browser/renderer_host/async_resource_handler.cc
@@ -62,10 +62,12 @@ bool AsyncResourceHandler::OnUploadProgress(int request_id,
}
bool AsyncResourceHandler::OnRequestRedirected(int request_id,
- const GURL& new_url) {
- return receiver_->Send(new ViewMsg_Resource_ReceivedRedirect(routing_id_,
- request_id,
- new_url));
+ const GURL& new_url,
+ ResourceResponse* response,
+ bool* defer) {
+ *defer = true;
+ return receiver_->Send(new ViewMsg_Resource_ReceivedRedirect(
+ routing_id_, request_id, new_url, response->response_head));
}
bool AsyncResourceHandler::OnResponseStarted(int request_id,
diff --git a/chrome/browser/renderer_host/async_resource_handler.h b/chrome/browser/renderer_host/async_resource_handler.h
index 89ecfad..17e9260 100644
--- a/chrome/browser/renderer_host/async_resource_handler.h
+++ b/chrome/browser/renderer_host/async_resource_handler.h
@@ -26,7 +26,8 @@ class AsyncResourceHandler : public ResourceHandler {
// ResourceHandler implementation:
bool OnUploadProgress(int request_id, uint64 position, uint64 size);
- bool OnRequestRedirected(int request_id, const GURL& new_url);
+ bool OnRequestRedirected(int request_id, const GURL& new_url,
+ ResourceResponse* response, bool* defer);
bool OnResponseStarted(int request_id, ResourceResponse* response);
bool OnWillRead(int request_id, net::IOBuffer** buf, int* buf_size,
int min_size);
diff --git a/chrome/browser/renderer_host/buffered_resource_handler.cc b/chrome/browser/renderer_host/buffered_resource_handler.cc
index 8d0f17f..b1007fe 100644
--- a/chrome/browser/renderer_host/buffered_resource_handler.cc
+++ b/chrome/browser/renderer_host/buffered_resource_handler.cc
@@ -60,8 +60,11 @@ bool BufferedResourceHandler::OnUploadProgress(int request_id,
}
bool BufferedResourceHandler::OnRequestRedirected(int request_id,
- const GURL& new_url) {
- return real_handler_->OnRequestRedirected(request_id, new_url);
+ const GURL& new_url,
+ ResourceResponse* response,
+ bool* defer) {
+ return real_handler_->OnRequestRedirected(
+ request_id, new_url, response, defer);
}
bool BufferedResourceHandler::OnResponseStarted(int request_id,
diff --git a/chrome/browser/renderer_host/buffered_resource_handler.h b/chrome/browser/renderer_host/buffered_resource_handler.h
index e553aca..3799b99 100644
--- a/chrome/browser/renderer_host/buffered_resource_handler.h
+++ b/chrome/browser/renderer_host/buffered_resource_handler.h
@@ -21,7 +21,8 @@ class BufferedResourceHandler : public ResourceHandler {
// ResourceHandler implementation:
bool OnUploadProgress(int request_id, uint64 position, uint64 size);
- bool OnRequestRedirected(int request_id, const GURL& new_url);
+ bool OnRequestRedirected(int request_id, const GURL& new_url,
+ ResourceResponse* response, bool* defer);
bool OnResponseStarted(int request_id, ResourceResponse* response);
bool OnWillRead(int request_id, net::IOBuffer** buf, int* buf_size,
int min_size);
diff --git a/chrome/browser/renderer_host/cross_site_resource_handler.cc b/chrome/browser/renderer_host/cross_site_resource_handler.cc
index 7b05a72..eb688e7 100644
--- a/chrome/browser/renderer_host/cross_site_resource_handler.cc
+++ b/chrome/browser/renderer_host/cross_site_resource_handler.cc
@@ -84,10 +84,13 @@ CrossSiteResourceHandler::CrossSiteResourceHandler(
rdh_(resource_dispatcher_host) {}
bool CrossSiteResourceHandler::OnRequestRedirected(int request_id,
- const GURL& new_url) {
+ const GURL& new_url,
+ ResourceResponse* response,
+ bool* defer) {
// We should not have started the transition before being redirected.
DCHECK(!in_cross_site_transition_);
- return next_handler_->OnRequestRedirected(request_id, new_url);
+ return next_handler_->OnRequestRedirected(
+ request_id, new_url, response, defer);
}
bool CrossSiteResourceHandler::OnResponseStarted(int request_id,
diff --git a/chrome/browser/renderer_host/cross_site_resource_handler.h b/chrome/browser/renderer_host/cross_site_resource_handler.h
index b741aa0..b50e641 100644
--- a/chrome/browser/renderer_host/cross_site_resource_handler.h
+++ b/chrome/browser/renderer_host/cross_site_resource_handler.h
@@ -21,7 +21,8 @@ class CrossSiteResourceHandler : public ResourceHandler {
ResourceDispatcherHost* resource_dispatcher_host);
// ResourceHandler implementation:
- bool OnRequestRedirected(int request_id, const GURL& new_url);
+ bool OnRequestRedirected(int request_id, const GURL& new_url,
+ ResourceResponse* response, bool* defer);
bool OnResponseStarted(int request_id,
ResourceResponse* response);
bool OnWillRead(int request_id, net::IOBuffer** buf, int* buf_size,
diff --git a/chrome/browser/renderer_host/download_resource_handler.cc b/chrome/browser/renderer_host/download_resource_handler.cc
index 6661666..8b189bf 100644
--- a/chrome/browser/renderer_host/download_resource_handler.cc
+++ b/chrome/browser/renderer_host/download_resource_handler.cc
@@ -35,7 +35,9 @@ DownloadResourceHandler::DownloadResourceHandler(ResourceDispatcherHost* rdh,
// Not needed, as this event handler ought to be the final resource.
bool DownloadResourceHandler::OnRequestRedirected(int request_id,
- const GURL& url) {
+ const GURL& url,
+ ResourceResponse* response,
+ bool* defer) {
url_ = url;
return true;
}
diff --git a/chrome/browser/renderer_host/download_resource_handler.h b/chrome/browser/renderer_host/download_resource_handler.h
index d9afa42..e4613a8 100644
--- a/chrome/browser/renderer_host/download_resource_handler.h
+++ b/chrome/browser/renderer_host/download_resource_handler.h
@@ -25,7 +25,8 @@ class DownloadResourceHandler : public ResourceHandler {
bool save_as);
// Not needed, as this event handler ought to be the final resource.
- bool OnRequestRedirected(int request_id, const GURL& url);
+ bool OnRequestRedirected(int request_id, const GURL& url,
+ ResourceResponse* response, bool* defer);
// Send the download creation information to the download thread.
bool OnResponseStarted(int request_id, ResourceResponse* response);
diff --git a/chrome/browser/renderer_host/download_throttling_resource_handler.cc b/chrome/browser/renderer_host/download_throttling_resource_handler.cc
index f3ad5bb..ee286db 100644
--- a/chrome/browser/renderer_host/download_throttling_resource_handler.cc
+++ b/chrome/browser/renderer_host/download_throttling_resource_handler.cc
@@ -41,10 +41,15 @@ bool DownloadThrottlingResourceHandler::OnUploadProgress(int request_id,
return true;
}
-bool DownloadThrottlingResourceHandler::OnRequestRedirected(int request_id,
- const GURL& url) {
- if (download_handler_.get())
- return download_handler_->OnRequestRedirected(request_id, url);
+bool DownloadThrottlingResourceHandler::OnRequestRedirected(
+ int request_id,
+ const GURL& url,
+ ResourceResponse* response,
+ bool* defer) {
+ if (download_handler_.get()) {
+ return download_handler_->OnRequestRedirected(
+ request_id, url, response, defer);
+ }
url_ = url;
return true;
}
diff --git a/chrome/browser/renderer_host/download_throttling_resource_handler.h b/chrome/browser/renderer_host/download_throttling_resource_handler.h
index 5a2eea9..117b3d2 100644
--- a/chrome/browser/renderer_host/download_throttling_resource_handler.h
+++ b/chrome/browser/renderer_host/download_throttling_resource_handler.h
@@ -40,7 +40,8 @@ class DownloadThrottlingResourceHandler
virtual bool OnUploadProgress(int request_id,
uint64 position,
uint64 size);
- virtual bool OnRequestRedirected(int request_id, const GURL& url);
+ virtual bool OnRequestRedirected(int request_id, const GURL& url,
+ ResourceResponse* response, bool* defer);
virtual bool OnResponseStarted(int request_id, ResourceResponse* response);
virtual bool OnWillRead(int request_id, net::IOBuffer** buf, int* buf_size,
int min_size);
diff --git a/chrome/browser/renderer_host/resource_dispatcher_host.cc b/chrome/browser/renderer_host/resource_dispatcher_host.cc
index a626f06..94bf0b6 100644
--- a/chrome/browser/renderer_host/resource_dispatcher_host.cc
+++ b/chrome/browser/renderer_host/resource_dispatcher_host.cc
@@ -227,6 +227,20 @@ bool ShouldServiceRequest(ChildProcessInfo::ProcessType process_type,
return true;
}
+void PopulateResourceResponse(URLRequest* request,
+ FilterPolicy::Type filter_policy,
+ ResourceResponse* response) {
+ response->response_head.status = request->status();
+ response->response_head.request_time = request->request_time();
+ response->response_head.response_time = request->response_time();
+ response->response_head.headers = request->response_headers();
+ request->GetCharset(&response->response_head.charset);
+ response->response_head.filter_policy = filter_policy;
+ response->response_head.content_length = request->GetExpectedContentSize();
+ response->response_head.app_cache_id = WebAppCacheContext::kNoAppCacheId;
+ request->GetMimeType(&response->response_head.mime_type);
+}
+
} // namespace
ResourceDispatcherHost::ResourceDispatcherHost(MessageLoop* io_loop)
@@ -328,6 +342,7 @@ bool ResourceDispatcherHost::OnMessageReceived(const IPC::Message& message,
IPC_MESSAGE_HANDLER(ViewHostMsg_DataReceived_ACK, OnDataReceivedACK)
IPC_MESSAGE_HANDLER(ViewHostMsg_UploadProgress_ACK, OnUploadProgressACK)
IPC_MESSAGE_HANDLER(ViewHostMsg_CancelRequest, OnCancelRequest)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_FollowRedirect, OnFollowRedirect)
IPC_MESSAGE_HANDLER(ViewHostMsg_ClosePage_ACK, OnClosePageACK)
IPC_END_MESSAGE_MAP_EX()
@@ -571,6 +586,10 @@ void ResourceDispatcherHost::OnCancelRequest(int request_id) {
CancelRequest(receiver_->GetProcessId(), request_id, true, true);
}
+void ResourceDispatcherHost::OnFollowRedirect(int request_id) {
+ FollowDeferredRedirect(receiver_->GetProcessId(), request_id);
+}
+
void ResourceDispatcherHost::OnClosePageACK(
const ViewMsg_ClosePage_Params& params) {
if (params.for_cross_site_transition) {
@@ -731,47 +750,16 @@ void ResourceDispatcherHost::CancelRequest(int process_id,
CancelRequest(process_id, request_id, from_renderer, true);
}
-void ResourceDispatcherHost::CancelRequest(int process_id,
- int request_id,
- bool from_renderer,
- bool allow_delete) {
+void ResourceDispatcherHost::FollowDeferredRedirect(int process_id,
+ int request_id) {
PendingRequestList::iterator i = pending_requests_.find(
GlobalRequestID(process_id, request_id));
if (i == pending_requests_.end()) {
- // We probably want to remove this warning eventually, but I wanted to be
- // able to notice when this happens during initial development since it
- // should be rare and may indicate a bug.
- DLOG(WARNING) << "Canceling a request that wasn't found";
+ DLOG(WARNING) << "FollowDeferredRedirect for invalid request";
return;
}
- // WebKit will send us a cancel for downloads since it no longer handles them.
- // In this case, ignore the cancel since we handle downloads in the browser.
- ExtraRequestInfo* info = ExtraInfoForRequest(i->second);
- if (!from_renderer || !info->is_download) {
- if (info->login_handler) {
- info->login_handler->OnRequestCancelled();
- info->login_handler = NULL;
- }
- if (info->ssl_client_auth_handler) {
- info->ssl_client_auth_handler->OnRequestCancelled();
- info->ssl_client_auth_handler = NULL;
- }
- if (!i->second->is_pending() && allow_delete) {
- // No io is pending, canceling the request won't notify us of anything,
- // so we explicitly remove it.
- // TODO(sky): removing the request in this manner means we're not
- // notifying anyone. We need make sure the event handlers and others are
- // notified so that everything is cleaned up properly.
- RemovePendingRequest(info->process_id, info->request_id);
- } else {
- i->second->Cancel();
- }
- }
-
- // Do not remove from the pending requests, as the request will still
- // call AllDataReceived, and may even have more data before it does
- // that.
+ i->second->FollowDeferredRedirect();
}
bool ResourceDispatcherHost::WillSendData(int process_id,
@@ -779,7 +767,7 @@ bool ResourceDispatcherHost::WillSendData(int process_id,
PendingRequestList::iterator i = pending_requests_.find(
GlobalRequestID(process_id, request_id));
if (i == pending_requests_.end()) {
- NOTREACHED() << L"WillSendData for invalid request";
+ NOTREACHED() << "WillSendData for invalid request";
return false;
}
@@ -968,7 +956,10 @@ void ResourceDispatcherHost::OnReceivedRedirect(URLRequest* request,
return;
}
- if (!info->resource_handler->OnRequestRedirected(info->request_id, new_url))
+ scoped_refptr<ResourceResponse> response = new ResourceResponse;
+ PopulateResourceResponse(request, info->filter_policy, response);
+ if (!info->resource_handler->OnRequestRedirected(info->request_id, new_url,
+ response, defer_redirect))
CancelRequest(info->process_id, info->request_id, false);
}
@@ -1050,17 +1041,8 @@ void ResourceDispatcherHost::OnResponseStarted(URLRequest* request) {
bool ResourceDispatcherHost::CompleteResponseStarted(URLRequest* request) {
ExtraRequestInfo* info = ExtraInfoForRequest(request);
- scoped_refptr<ResourceResponse> response(new ResourceResponse);
-
- response->response_head.status = request->status();
- response->response_head.request_time = request->request_time();
- response->response_head.response_time = request->response_time();
- response->response_head.headers = request->response_headers();
- request->GetCharset(&response->response_head.charset);
- response->response_head.filter_policy = info->filter_policy;
- response->response_head.content_length = request->GetExpectedContentSize();
- response->response_head.app_cache_id = WebAppCacheContext::kNoAppCacheId;
- request->GetMimeType(&response->response_head.mime_type);
+ scoped_refptr<ResourceResponse> response = new ResourceResponse;
+ PopulateResourceResponse(request, info->filter_policy, response);
const URLRequest::UserData* d =
request->GetUserData(&Blacklist::kRequestDataKey);
@@ -1093,6 +1075,49 @@ bool ResourceDispatcherHost::CompleteResponseStarted(URLRequest* request) {
response.get());
}
+void ResourceDispatcherHost::CancelRequest(int process_id,
+ int request_id,
+ bool from_renderer,
+ bool allow_delete) {
+ PendingRequestList::iterator i = pending_requests_.find(
+ GlobalRequestID(process_id, request_id));
+ if (i == pending_requests_.end()) {
+ // We probably want to remove this warning eventually, but I wanted to be
+ // able to notice when this happens during initial development since it
+ // should be rare and may indicate a bug.
+ DLOG(WARNING) << "Canceling a request that wasn't found";
+ return;
+ }
+
+ // WebKit will send us a cancel for downloads since it no longer handles them.
+ // In this case, ignore the cancel since we handle downloads in the browser.
+ ExtraRequestInfo* info = ExtraInfoForRequest(i->second);
+ if (!from_renderer || !info->is_download) {
+ if (info->login_handler) {
+ info->login_handler->OnRequestCancelled();
+ info->login_handler = NULL;
+ }
+ if (info->ssl_client_auth_handler) {
+ info->ssl_client_auth_handler->OnRequestCancelled();
+ info->ssl_client_auth_handler = NULL;
+ }
+ if (!i->second->is_pending() && allow_delete) {
+ // No io is pending, canceling the request won't notify us of anything,
+ // so we explicitly remove it.
+ // TODO(sky): removing the request in this manner means we're not
+ // notifying anyone. We need make sure the event handlers and others are
+ // notified so that everything is cleaned up properly.
+ RemovePendingRequest(info->process_id, info->request_id);
+ } else {
+ i->second->Cancel();
+ }
+ }
+
+ // Do not remove from the pending requests, as the request will still
+ // call AllDataReceived, and may even have more data before it does
+ // that.
+}
+
int ResourceDispatcherHost::IncrementOutstandingRequestsMemoryCost(
int cost, int process_id) {
// Retrieve the previous value (defaulting to 0 if not found).
@@ -1675,6 +1700,7 @@ bool ResourceDispatcherHost::IsResourceDispatcherHostMessage(
switch (message.type()) {
case ViewHostMsg_RequestResource::ID:
case ViewHostMsg_CancelRequest::ID:
+ case ViewHostMsg_FollowRedirect::ID:
case ViewHostMsg_ClosePage_ACK::ID:
case ViewHostMsg_DataReceived_ACK::ID:
case ViewHostMsg_DownloadProgress_ACK::ID:
diff --git a/chrome/browser/renderer_host/resource_dispatcher_host.h b/chrome/browser/renderer_host/resource_dispatcher_host.h
index b75d408..5353562 100644
--- a/chrome/browser/renderer_host/resource_dispatcher_host.h
+++ b/chrome/browser/renderer_host/resource_dispatcher_host.h
@@ -250,6 +250,10 @@ class ResourceDispatcherHost : public URLRequest::Delegate {
int request_id,
bool from_renderer);
+ // Follows a deferred redirect for the given request.
+ void FollowDeferredRedirect(int process_id,
+ int request_id);
+
// Returns true if it's ok to send the data. If there are already too many
// data messages pending, it pauses the request and returns false. In this
// case the caller should not send the data.
@@ -503,6 +507,7 @@ class ResourceDispatcherHost : public URLRequest::Delegate {
void OnDataReceivedACK(int request_id);
void OnUploadProgressACK(int request_id);
void OnCancelRequest(int request_id);
+ void OnFollowRedirect(int request_id);
// Returns true if the message passed in is a resource related message.
static bool IsResourceDispatcherHostMessage(const IPC::Message&);
diff --git a/chrome/browser/renderer_host/resource_dispatcher_host_uitest.cc b/chrome/browser/renderer_host/resource_dispatcher_host_uitest.cc
index c13d3c2..d8654fd 100644
--- a/chrome/browser/renderer_host/resource_dispatcher_host_uitest.cc
+++ b/chrome/browser/renderer_host/resource_dispatcher_host_uitest.cc
@@ -314,4 +314,21 @@ TEST_F(ResourceDispatcherTest, CrossSiteNavigationErrorPage) {
EXPECT_EQ(L"Title Of Awesomeness", tab_title);
}
+TEST_F(ResourceDispatcherTest, CrossOriginRedirectBlocked) {
+ int before = automation()->GetFilteredInetHitCount();
+ CheckTitleTest(L"cross-origin-redirect-blocked.html",
+ L"done");
+ int after = automation()->GetFilteredInetHitCount();
+ //
+ // We expect the following URL requests from this test:
+ // 1- http://mock.http/cross-origin-redirect-blocked.html
+ // 2- http://mock.http/redirect-to-title2.html
+ // 3- http://mock.http/title2.html
+ //
+ // If the redirect in #2 were not blocked, we'd also see a request
+ // for http://mock.http:4000/title2.html.
+ //
+ EXPECT_EQ(3, after - before);
+}
+
} // namespace
diff --git a/chrome/browser/renderer_host/resource_handler.h b/chrome/browser/renderer_host/resource_handler.h
index df1b8a6..76851b6 100644
--- a/chrome/browser/renderer_host/resource_handler.h
+++ b/chrome/browser/renderer_host/resource_handler.h
@@ -63,8 +63,12 @@ class ResourceHandler : public base::RefCounted<ResourceHandler> {
return true;
}
- // The request was redirected to a new URL.
- virtual bool OnRequestRedirected(int request_id, const GURL& url) = 0;
+ // The request was redirected to a new URL. |*defer| has an initial value of
+ // false. Set |*defer| to true to defer the redirect. The redirect may be
+ // followed later on via ResourceDispatcherHost::FollowDeferredRedirect.
+ virtual bool OnRequestRedirected(int request_id, const GURL& url,
+ ResourceResponse* response,
+ bool* defer) = 0;
// Response headers and meta data are available.
virtual bool OnResponseStarted(int request_id,
diff --git a/chrome/browser/renderer_host/safe_browsing_resource_handler.cc b/chrome/browser/renderer_host/safe_browsing_resource_handler.cc
index 0d2af57..c215262 100644
--- a/chrome/browser/renderer_host/safe_browsing_resource_handler.cc
+++ b/chrome/browser/renderer_host/safe_browsing_resource_handler.cc
@@ -56,8 +56,11 @@ bool SafeBrowsingResourceHandler::OnUploadProgress(int request_id,
return next_handler_->OnUploadProgress(request_id, position, size);
}
-bool SafeBrowsingResourceHandler::OnRequestRedirected(int request_id,
- const GURL& new_url) {
+bool SafeBrowsingResourceHandler::OnRequestRedirected(
+ int request_id,
+ const GURL& new_url,
+ ResourceResponse* response,
+ bool* defer) {
if (in_safe_browsing_check_) {
Release();
in_safe_browsing_check_ = false;
@@ -73,7 +76,8 @@ bool SafeBrowsingResourceHandler::OnRequestRedirected(int request_id,
// Can't pause now because it's too early, so we'll do it in OnWillRead.
}
- return next_handler_->OnRequestRedirected(request_id, new_url);
+ return next_handler_->OnRequestRedirected(
+ request_id, new_url, response, defer);
}
bool SafeBrowsingResourceHandler::OnResponseStarted(
diff --git a/chrome/browser/renderer_host/safe_browsing_resource_handler.h b/chrome/browser/renderer_host/safe_browsing_resource_handler.h
index 44018b1..e2901e8 100644
--- a/chrome/browser/renderer_host/safe_browsing_resource_handler.h
+++ b/chrome/browser/renderer_host/safe_browsing_resource_handler.h
@@ -30,7 +30,8 @@ class SafeBrowsingResourceHandler : public ResourceHandler,
// ResourceHandler implementation:
bool OnUploadProgress(int request_id, uint64 position, uint64 size);
- bool OnRequestRedirected(int request_id, const GURL& new_url);
+ bool OnRequestRedirected(int request_id, const GURL& new_url,
+ ResourceResponse* response, bool* defer);
bool OnResponseStarted(int request_id, ResourceResponse* response);
void OnGetHashTimeout();
bool OnWillRead(int request_id, net::IOBuffer** buf, int* buf_size,
diff --git a/chrome/browser/renderer_host/save_file_resource_handler.cc b/chrome/browser/renderer_host/save_file_resource_handler.cc
index 3289df1..22f3441 100644
--- a/chrome/browser/renderer_host/save_file_resource_handler.cc
+++ b/chrome/browser/renderer_host/save_file_resource_handler.cc
@@ -23,7 +23,9 @@ SaveFileResourceHandler::SaveFileResourceHandler(int render_process_host_id,
}
bool SaveFileResourceHandler::OnRequestRedirected(int request_id,
- const GURL& url) {
+ const GURL& url,
+ ResourceResponse* response,
+ bool* defer) {
final_url_ = url;
return true;
}
diff --git a/chrome/browser/renderer_host/save_file_resource_handler.h b/chrome/browser/renderer_host/save_file_resource_handler.h
index bc3548c..9a976b2 100644
--- a/chrome/browser/renderer_host/save_file_resource_handler.h
+++ b/chrome/browser/renderer_host/save_file_resource_handler.h
@@ -21,7 +21,8 @@ class SaveFileResourceHandler : public ResourceHandler {
// Saves the redirected URL to final_url_, we need to use the original
// URL to match original request.
- bool OnRequestRedirected(int request_id, const GURL& url);
+ bool OnRequestRedirected(int request_id, const GURL& url,
+ ResourceResponse* response, bool* defer);
// Sends the download creation information to the download thread.
bool OnResponseStarted(int request_id, ResourceResponse* response);
diff --git a/chrome/browser/renderer_host/sync_resource_handler.cc b/chrome/browser/renderer_host/sync_resource_handler.cc
index 01d0d8f..dd279a0 100644
--- a/chrome/browser/renderer_host/sync_resource_handler.cc
+++ b/chrome/browser/renderer_host/sync_resource_handler.cc
@@ -26,7 +26,16 @@ SyncResourceHandler::~SyncResourceHandler() {
}
bool SyncResourceHandler::OnRequestRedirected(int request_id,
- const GURL& new_url) {
+ const GURL& new_url,
+ ResourceResponse* response,
+ bool* defer) {
+ // TODO(darin): It would be much better if this could live in WebCore, but
+ // doing so requires API changes at all levels. Similar code exists in
+ // WebCore/platform/network/cf/ResourceHandleCFNet.cpp :-(
+ if (new_url.GetOrigin() != result_.final_url.GetOrigin()) {
+ LOG(ERROR) << "Cross origin redirect denied";
+ return false;
+ }
result_.final_url = new_url;
return true;
}
diff --git a/chrome/browser/renderer_host/sync_resource_handler.h b/chrome/browser/renderer_host/sync_resource_handler.h
index 8aa4681..615d7473 100644
--- a/chrome/browser/renderer_host/sync_resource_handler.h
+++ b/chrome/browser/renderer_host/sync_resource_handler.h
@@ -20,7 +20,8 @@ class SyncResourceHandler : public ResourceHandler {
IPC::Message* result_message);
~SyncResourceHandler();
- bool OnRequestRedirected(int request_id, const GURL& new_url);
+ bool OnRequestRedirected(int request_id, const GURL& new_url,
+ ResourceResponse* response, bool* defer);
bool OnResponseStarted(int request_id, ResourceResponse* response);
bool OnWillRead(int request_id, net::IOBuffer** buf, int* buf_size,
int min_size);
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index 96f25e6..029b3cb 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -225,10 +225,13 @@ IPC_BEGIN_MESSAGES(View)
int64 /* position */,
int64 /* size */)
- // Sent when the request has been redirected.
- IPC_MESSAGE_ROUTED2(ViewMsg_Resource_ReceivedRedirect,
+ // Sent when the request has been redirected. The receiver is expected to
+ // respond with either a FollowRedirect message (if the redirect is to be
+ // followed) or a CancelRequest message (if it should not be followed).
+ IPC_MESSAGE_ROUTED3(ViewMsg_Resource_ReceivedRedirect,
int /* request_id */,
- GURL /* new_url */)
+ GURL /* new_url */,
+ ResourceResponseHead)
// Sent when some data from a resource request is ready. The handle should
// already be mapped into the process that receives this message.
@@ -834,6 +837,11 @@ IPC_BEGIN_MESSAGES(ViewHost)
IPC_MESSAGE_ROUTED1(ViewHostMsg_CancelRequest,
int /* request_id */)
+ // Follows a redirect that occured for the resource request with the ID given
+ // as the parameter.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_FollowRedirect,
+ int /* request_id */)
+
// Makes a synchronous resource request via the browser.
IPC_SYNC_MESSAGE_ROUTED2_1(ViewHostMsg_SyncLoad,
int /* request_id */,
diff --git a/chrome/common/resource_dispatcher.cc b/chrome/common/resource_dispatcher.cc
index d598b39..8167901 100644
--- a/chrome/common/resource_dispatcher.cc
+++ b/chrome/common/resource_dispatcher.cc
@@ -56,7 +56,7 @@ class IPCResourceLoaderBridge : public ResourceLoaderBridge {
ResourceType::Type resource_type,
uint32 request_context,
int app_cache_context_id,
- int route_id);
+ int routing_id);
virtual ~IPCResourceLoaderBridge();
// ResourceLoaderBridge
@@ -88,7 +88,7 @@ class IPCResourceLoaderBridge : public ResourceLoaderBridge {
int request_id_;
// The routing id used when sending IPC messages.
- int route_id_;
+ int routing_id_;
#ifdef LOG_RESOURCE_REQUESTS
// indicates the URL of this resource request for help debugging
@@ -110,11 +110,11 @@ IPCResourceLoaderBridge::IPCResourceLoaderBridge(
ResourceType::Type resource_type,
uint32 request_context,
int app_cache_context_id,
- int route_id)
+ int routing_id)
: peer_(NULL),
dispatcher_(dispatcher),
request_id_(-1),
- route_id_(route_id) {
+ routing_id_(routing_id) {
DCHECK(dispatcher_) << "no resource dispatcher";
request_.method = method;
request_.url = url;
@@ -189,7 +189,7 @@ bool IPCResourceLoaderBridge::Start(Peer* peer) {
request_id_ = dispatcher_->AddPendingRequest(peer_, request_.resource_type);
return dispatcher_->message_sender()->Send(
- new ViewHostMsg_RequestResource(route_id_, request_id_, request_));
+ new ViewHostMsg_RequestResource(routing_id_, request_id_, request_));
}
void IPCResourceLoaderBridge::Cancel() {
@@ -200,8 +200,7 @@ void IPCResourceLoaderBridge::Cancel() {
RESOURCE_LOG("Canceling request for " << url_);
- dispatcher_->message_sender()->Send(
- new ViewHostMsg_CancelRequest(route_id_, request_id_));
+ dispatcher_->CancelPendingRequest(routing_id_, request_id_);
// We can't remove the request ID from the resource dispatcher because more
// data might be pending. Sending the cancel message may cause more data
@@ -229,7 +228,7 @@ void IPCResourceLoaderBridge::SyncLoad(SyncLoadResponse* response) {
request_id_ = MakeRequestID();
SyncLoadResult result;
- IPC::Message* msg = new ViewHostMsg_SyncLoad(route_id_, request_id_,
+ IPC::Message* msg = new ViewHostMsg_SyncLoad(routing_id_, request_id_,
request_, &result);
if (!dispatcher_->message_sender()->Send(msg)) {
response->status.set_status(URLRequestStatus::FAILED);
@@ -351,7 +350,7 @@ void ResourceDispatcher::OnReceivedData(const IPC::Message& message,
int request_id,
base::SharedMemoryHandle shm_handle,
int data_len) {
- // Acknowlegde the reception of this data.
+ // Acknowledge the reception of this data.
message_sender()->Send(
new ViewHostMsg_DataReceived_ACK(message.routing_id(), request_id));
@@ -377,8 +376,11 @@ void ResourceDispatcher::OnReceivedData(const IPC::Message& message,
}
}
-void ResourceDispatcher::OnReceivedRedirect(int request_id,
- const GURL& new_url) {
+void ResourceDispatcher::OnReceivedRedirect(
+ const IPC::Message& message,
+ int request_id,
+ const GURL& new_url,
+ const webkit_glue::ResourceLoaderBridge::ResponseInfo& info) {
PendingRequestList::iterator it = pending_requests_.find(request_id);
if (it == pending_requests_.end()) {
// this might happen for kill()ed requests on the webkit end, so perhaps
@@ -391,7 +393,13 @@ void ResourceDispatcher::OnReceivedRedirect(int request_id,
RESOURCE_LOG("Dispatching redirect for " <<
request_info.peer->GetURLForDebugging());
- request_info.peer->OnReceivedRedirect(new_url);
+
+ if (request_info.peer->OnReceivedRedirect(new_url, info)) {
+ message_sender()->Send(
+ new ViewHostMsg_FollowRedirect(message.routing_id(), request_id));
+ } else {
+ CancelPendingRequest(message.routing_id(), request_id);
+ }
}
void ResourceDispatcher::OnRequestComplete(int request_id,
@@ -461,10 +469,26 @@ bool ResourceDispatcher::RemovePendingRequest(int request_id) {
return true;
}
+void ResourceDispatcher::CancelPendingRequest(int routing_id,
+ int request_id) {
+ PendingRequestList::iterator it = pending_requests_.find(request_id);
+ if (it == pending_requests_.end()) {
+ DLOG(ERROR) << "unknown request";
+ return;
+ }
+ PendingRequestInfo& request_info = it->second;
+ // Avoid spamming the host with cancel messages.
+ if (request_info.is_cancelled)
+ return;
+ request_info.is_cancelled = true;
+ message_sender()->Send(
+ new ViewHostMsg_CancelRequest(routing_id, request_id));
+}
+
void ResourceDispatcher::SetDefersLoading(int request_id, bool value) {
PendingRequestList::iterator it = pending_requests_.find(request_id);
if (it == pending_requests_.end()) {
- NOTREACHED() << "unknown request";
+ DLOG(ERROR) << "unknown request";
return;
}
PendingRequestInfo& request_info = it->second;
diff --git a/chrome/common/resource_dispatcher.h b/chrome/common/resource_dispatcher.h
index 2424e2d..a8a9a65 100644
--- a/chrome/common/resource_dispatcher.h
+++ b/chrome/common/resource_dispatcher.h
@@ -46,7 +46,7 @@ class ResourceDispatcher {
ResourceType::Type resource_type,
uint32 request_context /* used for plugin->browser requests */,
int app_cache_context_id,
- int route_id);
+ int routing_id);
// Adds a request from the pending_requests_ list, returning the new
// requests' ID
@@ -57,6 +57,9 @@ class ResourceDispatcher {
// request was found and removed.
bool RemovePendingRequest(int request_id);
+ // Cancels a request in the pending_requests_ list.
+ void CancelPendingRequest(int routing_id, int request_id);
+
IPC::Message::Sender* message_sender() const {
return message_sender_;
}
@@ -75,7 +78,8 @@ class ResourceDispatcher {
: peer(peer),
resource_type(resource_type),
filter_policy(FilterPolicy::DONT_FILTER),
- is_deferred(false) {
+ is_deferred(false),
+ is_cancelled(false) {
}
~PendingRequestInfo() { }
webkit_glue::ResourceLoaderBridge::Peer* peer;
@@ -83,23 +87,31 @@ class ResourceDispatcher {
FilterPolicy::Type filter_policy;
MessageQueue deferred_message_queue;
bool is_deferred;
+ bool is_cancelled;
};
typedef base::hash_map<int, PendingRequestInfo> PendingRequestList;
// Message response handlers, called by the message handler for this process.
- void OnUploadProgress(const IPC::Message& message,
- int request_id,
- int64 position,
- int64 size);
+ void OnUploadProgress(
+ const IPC::Message& message,
+ int request_id,
+ int64 position,
+ int64 size);
void OnReceivedResponse(int request_id, const ResourceResponseHead&);
- void OnReceivedRedirect(int request_id, const GURL& new_url);
- void OnReceivedData(const IPC::Message& message,
- int request_id,
- base::SharedMemoryHandle data,
- int data_len);
- void OnRequestComplete(int request_id,
- const URLRequestStatus& status,
- const std::string& security_info);
+ void OnReceivedRedirect(
+ const IPC::Message& message,
+ int request_id,
+ const GURL& new_url,
+ const webkit_glue::ResourceLoaderBridge::ResponseInfo& info);
+ void OnReceivedData(
+ const IPC::Message& message,
+ int request_id,
+ base::SharedMemoryHandle data,
+ int data_len);
+ void OnRequestComplete(
+ int request_id,
+ const URLRequestStatus& status,
+ const std::string& security_info);
// Dispatch the message to one of the message response handlers.
void DispatchMessage(const IPC::Message& message);
diff --git a/chrome/common/resource_dispatcher_unittest.cc b/chrome/common/resource_dispatcher_unittest.cc
index 5a8ebf3..e4cdf50 100644
--- a/chrome/common/resource_dispatcher_unittest.cc
+++ b/chrome/common/resource_dispatcher_unittest.cc
@@ -31,7 +31,10 @@ class TestRequestCallback : public ResourceLoaderBridge::Peer {
TestRequestCallback() : complete_(false) {
}
- virtual void OnReceivedRedirect(const GURL& new_url) {
+ virtual bool OnReceivedRedirect(
+ const GURL& new_url,
+ const ResourceLoaderBridge::ResponseInfo& info) {
+ return true;
}
virtual void OnReceivedResponse(
diff --git a/chrome/common/security_filter_peer.cc b/chrome/common/security_filter_peer.cc
index f76031f..5369199 100644
--- a/chrome/common/security_filter_peer.cc
+++ b/chrome/common/security_filter_peer.cc
@@ -103,8 +103,11 @@ void SecurityFilterPeer::OnUploadProgress(uint64 position, uint64 size) {
original_peer_->OnUploadProgress(position, size);
}
-void SecurityFilterPeer::OnReceivedRedirect(const GURL& new_url) {
+bool SecurityFilterPeer::OnReceivedRedirect(
+ const GURL& new_url,
+ const webkit_glue::ResourceLoaderBridge::ResponseInfo& info) {
NOTREACHED();
+ return false;
}
void SecurityFilterPeer::OnReceivedResponse(
diff --git a/chrome/common/security_filter_peer.h b/chrome/common/security_filter_peer.h
index ec90bb5..e9ea54f 100644
--- a/chrome/common/security_filter_peer.h
+++ b/chrome/common/security_filter_peer.h
@@ -39,7 +39,9 @@ class SecurityFilterPeer : public webkit_glue::ResourceLoaderBridge::Peer {
// ResourceLoaderBridge::Peer methods.
virtual void OnUploadProgress(uint64 position, uint64 size);
- virtual void OnReceivedRedirect(const GURL& new_url);
+ virtual bool OnReceivedRedirect(
+ const GURL& new_url,
+ const webkit_glue::ResourceLoaderBridge::ResponseInfo& info);
virtual void OnReceivedResponse(
const webkit_glue::ResourceLoaderBridge::ResponseInfo& info,
bool content_filtered);
diff --git a/chrome/plugin/chrome_plugin_host.cc b/chrome/plugin/chrome_plugin_host.cc
index 81a128a..a5c7dfa 100644
--- a/chrome/plugin/chrome_plugin_host.cc
+++ b/chrome/plugin/chrome_plugin_host.cc
@@ -66,9 +66,12 @@ class PluginRequestHandlerProxy
upload_progress(cprequest_.get(), position, size);
}
- virtual void OnReceivedRedirect(const GURL& new_url) {
+ virtual bool OnReceivedRedirect(
+ const GURL& new_url,
+ const ResourceLoaderBridge::ResponseInfo& info) {
plugin_->functions().response_funcs->received_redirect(
cprequest_.get(), new_url.spec().c_str());
+ return true;
}
virtual void OnReceivedResponse(
diff --git a/chrome/test/automation/automation_messages_internal.h b/chrome/test/automation/automation_messages_internal.h
index 9d67065..b2b3f02 100644
--- a/chrome/test/automation/automation_messages_internal.h
+++ b/chrome/test/automation/automation_messages_internal.h
@@ -982,4 +982,10 @@ IPC_BEGIN_MESSAGES(Automation)
IPC_MESSAGE_ROUTED1(AutomationMsg_StopAsync,
int /* tab handle */)
+
+ // Returns the number of times a filter was used to service an URL request.
+ // See AutomationMsg_SetFilteredInet.
+ IPC_SYNC_MESSAGE_ROUTED0_1(AutomationMsg_GetFilteredInetHitCount,
+ int /* hit_count */)
+
IPC_END_MESSAGES(Automation)
diff --git a/chrome/test/automation/automation_proxy.cc b/chrome/test/automation/automation_proxy.cc
index dc94c18..70e4b33 100644
--- a/chrome/test/automation/automation_proxy.cc
+++ b/chrome/test/automation/automation_proxy.cc
@@ -371,6 +371,13 @@ bool AutomationProxy::SetFilteredInet(bool enabled) {
return Send(new AutomationMsg_SetFilteredInet(0, enabled));
}
+int AutomationProxy::GetFilteredInetHitCount() {
+ int hit_count;
+ if (!Send(new AutomationMsg_GetFilteredInetHitCount(0, &hit_count)))
+ return -1;
+ return hit_count;
+}
+
bool AutomationProxy::SendProxyConfig(const std::string& new_proxy_config) {
return Send(new AutomationMsg_SetProxyConfig(0, new_proxy_config));
}
diff --git a/chrome/test/automation/automation_proxy.h b/chrome/test/automation/automation_proxy.h
index 186d7bf..5bb5ebf 100644
--- a/chrome/test/automation/automation_proxy.h
+++ b/chrome/test/automation/automation_proxy.h
@@ -150,6 +150,10 @@ class AutomationProxy : public IPC::Channel::Listener,
// false if the message fails to send to the browser.
bool SetFilteredInet(bool enabled);
+ // Returns the number of times a network request filter was used to service a
+ // network request. Returns -1 on error.
+ int GetFilteredInetHitCount();
+
// Sends the browser a new proxy configuration to start using. Returns true
// if the proxy config was successfully sent, false otherwise.
bool SendProxyConfig(const std::string& new_proxy_config);
diff --git a/chrome/test/data/cross-origin-redirect-blocked.html b/chrome/test/data/cross-origin-redirect-blocked.html
new file mode 100644
index 0000000..3e9cdd4
--- /dev/null
+++ b/chrome/test/data/cross-origin-redirect-blocked.html
@@ -0,0 +1,53 @@
+<html>
+<head>
+<!-- avoid an automatically generated favicon reqeuest -->
+<link rel="icon" type="image/vnd.microsoft.icon" href="data:,">
+</head>
+<body>
+<script>
+
+function NewXHR(url) {
+ var r = new XMLHttpRequest
+ r.open("GET", url);
+ return r;
+}
+
+function SignalDone() {
+ document.title = "done";
+}
+
+function CreateDummyRequest() {
+ dummy_request = NewXHR("http://mock.http/title2.html");
+ dummy_request.onload = SignalDone;
+ dummy_request.send(null);
+}
+
+function RedirectFailed() {
+ // Good, the redirect was blocked by WebKit.
+ //
+ // We also care that the underlying network stack does not send the redirect.
+ // We cannot detect that from JS, but our test harness is designed to detect
+ // that (see ResourceDispatcherTest::CrossOriginRedirectBlocked). Before
+ // calling SignalDone, we want to allow the browser time to notice a request
+ // to follow the redirect if one should exist. To do that, we just need to
+ // make another network request.
+ //
+ // The setTimeout call is intended to delay CreateDummyRequest so that any
+ // processing associated with the current "error" handler completes.
+ setTimeout(CreateDummyRequest, 0);
+}
+
+function RedirectSucceeded() {
+ // Oops, the redirect should have been denied!
+ SignalDone();
+}
+
+// Kick off a request that will attempt a cross-origin redirect.
+request = NewXHR("http://mock.http/redirect-to-title2.html");
+request.onerror = RedirectFailed;
+request.onload = RedirectSucceeded;
+request.send(null);
+
+</script>
+</body>
+</html>
diff --git a/chrome/test/data/redirect-to-title2.html b/chrome/test/data/redirect-to-title2.html
new file mode 100644
index 0000000..7898192
--- /dev/null
+++ b/chrome/test/data/redirect-to-title2.html
@@ -0,0 +1 @@
+a
diff --git a/chrome/test/data/redirect-to-title2.html.mock-http-headers b/chrome/test/data/redirect-to-title2.html.mock-http-headers
new file mode 100644
index 0000000..43a377c
--- /dev/null
+++ b/chrome/test/data/redirect-to-title2.html.mock-http-headers
@@ -0,0 +1,2 @@
+HTTP/1.1 302 Moved
+Location: http://mock.http:4000/title2.html