summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
-rw-r--r--net/url_request/url_request.cc26
-rw-r--r--net/url_request/url_request.h4
-rw-r--r--net/url_request/url_request_filter.cc5
-rw-r--r--net/url_request/url_request_filter.h9
-rw-r--r--net/url_request/url_request_http_job.cc14
-rw-r--r--net/url_request/url_request_http_job.h1
-rw-r--r--net/url_request/url_request_job.cc17
-rw-r--r--net/url_request/url_request_job.h7
-rw-r--r--webkit/glue/media/buffered_data_source.cc6
-rw-r--r--webkit/glue/media/buffered_data_source.h4
-rw-r--r--webkit/glue/media/simple_data_source.cc5
-rw-r--r--webkit/glue/media/simple_data_source.h4
-rw-r--r--webkit/glue/resource_loader_bridge.h8
-rw-r--r--webkit/glue/weburlloader_impl.cc37
-rw-r--r--webkit/tools/test_shell/simple_resource_loader_bridge.cc63
55 files changed, 529 insertions, 238 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
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc
index 0f8ec34..9f6e229 100644
--- a/net/url_request/url_request.cc
+++ b/net/url_request/url_request.cc
@@ -11,6 +11,7 @@
#include "base/string_util.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
+#include "net/base/ssl_cert_request_info.h"
#include "net/base/upload_data.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
@@ -271,10 +272,7 @@ void URLRequest::Restart() {
void URLRequest::RestartWithJob(URLRequestJob *job) {
DCHECK(job->request() == this);
- job_->Kill();
- OrphanJob();
- status_ = URLRequestStatus();
- is_pending_ = false;
+ PrepareToRestart();
StartJob(job);
}
@@ -387,6 +385,17 @@ void URLRequest::ContinueDespiteLastError() {
job_->ContinueDespiteLastError();
}
+void URLRequest::PrepareToRestart() {
+ DCHECK(job_);
+
+ job_->Kill();
+ OrphanJob();
+
+ response_info_ = net::HttpResponseInfo();
+ status_ = URLRequestStatus();
+ is_pending_ = false;
+}
+
void URLRequest::OrphanJob() {
job_->Kill();
job_->DetachRequest(); // ensures that the job will not call us again
@@ -446,15 +455,10 @@ int URLRequest::Redirect(const GURL& location, int http_status_code) {
extra_request_headers_ = StripPostSpecificHeaders(extra_request_headers_);
}
- if (!final_upload_progress_) {
+ if (!final_upload_progress_)
final_upload_progress_ = job_->GetUploadProgress();
- }
- job_->Kill();
- OrphanJob();
-
- status_ = URLRequestStatus();
- is_pending_ = false;
+ PrepareToRestart();
Start();
return net::OK;
}
diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h
index b52fa3b..e9539cb 100644
--- a/net/url_request/url_request.h
+++ b/net/url_request/url_request.h
@@ -521,7 +521,11 @@ class URLRequest {
friend class URLRequestJob;
void StartJob(URLRequestJob* job);
+
+ // Restarting involves replacing the current job with a new one such as what
+ // happens when following a HTTP redirect.
void RestartWithJob(URLRequestJob *job);
+ void PrepareToRestart();
// Detaches the job from this request in preparation for this object going
// away or the job being replaced. The job will not call us back when it has
diff --git a/net/url_request/url_request_filter.cc b/net/url_request/url_request_filter.cc
index 189d8db..c62e96d 100644
--- a/net/url_request/url_request_filter.cc
+++ b/net/url_request/url_request_filter.cc
@@ -105,6 +105,7 @@ void URLRequestFilter::ClearHandlers() {
url_handler_map_.clear();
hostname_handler_map_.clear();
+ hit_count_ = 0;
}
URLRequestJob* URLRequestFilter::FindRequestHandler(URLRequest* request,
@@ -127,5 +128,9 @@ URLRequestJob* URLRequestFilter::FindRequestHandler(URLRequest* request,
job = i->second(request, scheme);
}
}
+ if (job) {
+ DLOG(INFO) << "URLRequestFilter hit for " << request->url().spec();
+ hit_count_++;
+ }
return job;
}
diff --git a/net/url_request/url_request_filter.h b/net/url_request/url_request_filter.h
index 2b74277..3f255b8 100644
--- a/net/url_request/url_request_filter.h
+++ b/net/url_request/url_request_filter.h
@@ -54,11 +54,14 @@ class URLRequestFilter {
void RemoveUrlHandler(const GURL& url);
// Clear all the existing URL handlers and unregister with the
- // ProtocolFactory.
+ // ProtocolFactory. Resets the hit count.
void ClearHandlers();
+ // Returns the number of times a handler was used to service a request.
+ int hit_count() const { return hit_count_; }
+
protected:
- URLRequestFilter() { }
+ URLRequestFilter() : hit_count_(0) { }
// Helper method that looks up the request in the url_handler_map_.
URLRequestJob* FindRequestHandler(URLRequest* request,
@@ -70,6 +73,8 @@ class URLRequestFilter {
// Maps URLs to factories.
UrlHandlerMap url_handler_map_;
+ int hit_count_;
+
private:
// Singleton instance.
static URLRequestFilter* shared_instance_;
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc
index cf2b63c..ec3301b 100644
--- a/net/url_request/url_request_http_job.cc
+++ b/net/url_request/url_request_http_job.cc
@@ -239,20 +239,6 @@ bool URLRequestHttpJob::IsSdchResponse() const {
return sdch_dictionary_advertised_;
}
-bool URLRequestHttpJob::IsRedirectResponse(GURL* location,
- int* http_status_code) {
- if (!response_info_)
- return false;
-
- std::string value;
- if (!response_info_->headers->IsRedirect(&value))
- return false;
-
- *location = request_->url().Resolve(value);
- *http_status_code = response_info_->headers->response_code();
- return true;
-}
-
bool URLRequestHttpJob::IsSafeRedirect(const GURL& location) {
// We only allow redirects to certain "safe" protocols. This does not
// restrict redirects to externally handled protocols. Our consumer would
diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h
index 3ebc05c..fdb32ae 100644
--- a/net/url_request/url_request_http_job.h
+++ b/net/url_request/url_request_http_job.h
@@ -47,7 +47,6 @@ class URLRequestHttpJob : public URLRequestJob {
std::vector<Filter::FilterType>* encoding_type);
virtual bool IsCachedContent() const { return is_cached_content_; }
virtual bool IsSdchResponse() const;
- virtual bool IsRedirectResponse(GURL* location, int* http_status_code);
virtual bool IsSafeRedirect(const GURL& location);
virtual bool NeedsAuth();
virtual void GetAuthChallengeInfo(scoped_refptr<net::AuthChallengeInfo>*);
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc
index f9043cc..4518d8a 100644
--- a/net/url_request/url_request_job.cc
+++ b/net/url_request/url_request_job.cc
@@ -10,6 +10,7 @@
#include "net/base/io_buffer.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
+#include "net/http/http_response_headers.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_job_metrics.h"
#include "net/url_request/url_request_job_tracker.h"
@@ -70,6 +71,22 @@ void URLRequestJob::SetupFilter() {
}
}
+bool URLRequestJob::IsRedirectResponse(GURL* location,
+ int* http_status_code) {
+ // For non-HTTP jobs, headers will be null.
+ net::HttpResponseHeaders* headers = request_->response_headers();
+ if (!headers)
+ return false;
+
+ std::string value;
+ if (!headers->IsRedirect(&value))
+ return false;
+
+ *location = request_->url().Resolve(value);
+ *http_status_code = headers->response_code();
+ return true;
+}
+
void URLRequestJob::GetAuthChallengeInfo(
scoped_refptr<net::AuthChallengeInfo>* auth_info) {
// This will only be called if NeedsAuth() returns true, in which
diff --git a/net/url_request/url_request_job.h b/net/url_request/url_request_job.h
index 8e56bea..60554ed 100644
--- a/net/url_request/url_request_job.h
+++ b/net/url_request/url_request_job.h
@@ -148,10 +148,9 @@ class URLRequestJob : public base::RefCountedThreadSafe<URLRequestJob>,
// The caller is responsible for following the redirect by setting up an
// appropriate replacement Job. Note that the redirected location may be
// invalid, the caller should be sure it can handle this.
- virtual bool IsRedirectResponse(GURL* location,
- int* http_status_code) {
- return false;
- }
+ //
+ // The default implementation inspects the response_info_.
+ virtual bool IsRedirectResponse(GURL* location, int* http_status_code);
// Called to determine if it is okay to redirect this job to the specified
// location. This may be used to implement protocol-specific restrictions.
diff --git a/webkit/glue/media/buffered_data_source.cc b/webkit/glue/media/buffered_data_source.cc
index 4fc3549..738f30d 100644
--- a/webkit/glue/media/buffered_data_source.cc
+++ b/webkit/glue/media/buffered_data_source.cc
@@ -194,7 +194,9 @@ void BufferedResourceLoader::Read(int64 position,
/////////////////////////////////////////////////////////////////////////////
// BufferedResourceLoader,
// webkit_glue::ResourceLoaderBridge::Peer implementations
-void BufferedResourceLoader::OnReceivedRedirect(const GURL& new_url) {
+bool BufferedResourceLoader::OnReceivedRedirect(
+ const GURL& new_url,
+ const webkit_glue::ResourceLoaderBridge::ResponseInfo& info) {
DCHECK(bridge_.get());
DCHECK(start_callback_.get());
@@ -206,6 +208,8 @@ void BufferedResourceLoader::OnReceivedRedirect(const GURL& new_url) {
DoneStart(net::ERR_ADDRESS_INVALID);
Stop();
}
+
+ return true;
}
void BufferedResourceLoader::OnReceivedResponse(
diff --git a/webkit/glue/media/buffered_data_source.h b/webkit/glue/media/buffered_data_source.h
index 6dd51a7..ef46477 100644
--- a/webkit/glue/media/buffered_data_source.h
+++ b/webkit/glue/media/buffered_data_source.h
@@ -86,7 +86,9 @@ class BufferedResourceLoader : public webkit_glue::ResourceLoaderBridge::Peer {
/////////////////////////////////////////////////////////////////////////////
// webkit_glue::ResourceLoaderBridge::Peer implementations.
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/webkit/glue/media/simple_data_source.cc b/webkit/glue/media/simple_data_source.cc
index 48c7138..639aa5f 100644
--- a/webkit/glue/media/simple_data_source.cc
+++ b/webkit/glue/media/simple_data_source.cc
@@ -109,8 +109,11 @@ void SimpleDataSource::OnDownloadProgress(uint64 position, uint64 size) {}
void SimpleDataSource::OnUploadProgress(uint64 position, uint64 size) {}
-void SimpleDataSource::OnReceivedRedirect(const GURL& new_url) {
+bool SimpleDataSource::OnReceivedRedirect(
+ const GURL& new_url,
+ const webkit_glue::ResourceLoaderBridge::ResponseInfo& info) {
SetURL(new_url);
+ return true;
}
void SimpleDataSource::OnReceivedResponse(
diff --git a/webkit/glue/media/simple_data_source.h b/webkit/glue/media/simple_data_source.h
index acfc503..e458c57 100644
--- a/webkit/glue/media/simple_data_source.h
+++ b/webkit/glue/media/simple_data_source.h
@@ -49,7 +49,9 @@ class SimpleDataSource : public media::DataSource,
// webkit_glue::ResourceLoaderBridge::Peer implementation.
virtual void OnDownloadProgress(uint64 position, uint64 size);
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/webkit/glue/resource_loader_bridge.h b/webkit/glue/resource_loader_bridge.h
index 2d7ba77..b76fd56 100644
--- a/webkit/glue/resource_loader_bridge.h
+++ b/webkit/glue/resource_loader_bridge.h
@@ -105,8 +105,12 @@ class ResourceLoaderBridge {
// note: only for requests with LOAD_ENABLE_UPLOAD_PROGRESS set
virtual void OnUploadProgress(uint64 position, uint64 size) = 0;
- // Called when a redirect occurs.
- virtual void OnReceivedRedirect(const GURL& new_url) = 0;
+ // Called when a redirect occurs. The implementation may return false to
+ // suppress the redirect. The given ResponseInfo provides complete
+ // information about the redirect, and new_url is the URL that will be
+ // loaded if this method returns true.
+ virtual bool OnReceivedRedirect(const GURL& new_url,
+ const ResponseInfo& info) = 0;
// Called when response headers are available (after all redirects have
// been followed). |content_filtered| is set to true if the contents is
diff --git a/webkit/glue/weburlloader_impl.cc b/webkit/glue/weburlloader_impl.cc
index d0158f6..3041049 100644
--- a/webkit/glue/weburlloader_impl.cc
+++ b/webkit/glue/weburlloader_impl.cc
@@ -205,7 +205,8 @@ class WebURLLoaderImpl::Context : public base::RefCounted<Context>,
// 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 ResourceLoaderBridge::ResponseInfo& info);
virtual void OnReceivedResponse(
const ResourceLoaderBridge::ResponseInfo& info, bool content_filtered);
virtual void OnReceivedData(const char* data, int len);
@@ -371,30 +372,32 @@ void WebURLLoaderImpl::Context::OnUploadProgress(uint64 position, uint64 size) {
client_->didSendData(loader_, position, size);
}
-void WebURLLoaderImpl::Context::OnReceivedRedirect(const GURL& new_url) {
+bool WebURLLoaderImpl::Context::OnReceivedRedirect(
+ const GURL& new_url,
+ const ResourceLoaderBridge::ResponseInfo& info) {
if (!client_)
- return;
+ return false;
- // TODO(darin): We lack sufficient information to construct the
- // actual redirect response, so we just simulate it here.
- WebURLResponse response(url_);
+ WebURLResponse response;
+ response.initialize();
+ PopulateURLResponse(url_, info, &response);
- // TODO(darin): We lack sufficient information to construct the
- // actual request that resulted from the redirect, so we just
- // report a GET navigation to the new location.
+ // TODO(darin): We lack sufficient information to construct the actual
+ // request that resulted from the redirect, so we just report a GET
+ // navigation to the new location.
WebURLRequest new_request(new_url);
url_ = new_url;
client_->willSendRequest(loader_, new_request, response);
- // TODO(darin): since new_request is sent as a mutable reference, it is
- // possible that willSendRequest may have modified it.
- //
- // andresca on #webkit confirms that that is intentional, so we'll need
- // to rework the ResourceLoaderBridge to give us control over what URL
- // is really loaded (and with what headers) when a redirect is encountered.
- // TODO(darin): we fail this assertion in some layout tests!
- //DCHECK(GURL(new_request.url()) == new_url);
+ // Only follow the redirect if WebKit left the URL unmodified.
+ if (url_ == new_request.url())
+ return true;
+
+ // We assume that WebKit only changes the URL to suppress a redirect, and we
+ // assume that it does so by setting it to be invalid.
+ DCHECK(!new_request.url().isValid());
+ return false;
}
void WebURLLoaderImpl::Context::OnReceivedResponse(
diff --git a/webkit/tools/test_shell/simple_resource_loader_bridge.cc b/webkit/tools/test_shell/simple_resource_loader_bridge.cc
index c11bcec..a7d27a0 100644
--- a/webkit/tools/test_shell/simple_resource_loader_bridge.cc
+++ b/webkit/tools/test_shell/simple_resource_loader_bridge.cc
@@ -151,9 +151,14 @@ class RequestProxy : public URLRequest::Delegate,
// various URLRequest callbacks. The event hooks, defined below, trigger
// these methods asynchronously.
- void NotifyReceivedRedirect(const GURL& new_url) {
- if (peer_)
- peer_->OnReceivedRedirect(new_url);
+ void NotifyReceivedRedirect(const GURL& new_url,
+ const ResourceLoaderBridge::ResponseInfo& info) {
+ if (peer_ && peer_->OnReceivedRedirect(new_url, info)) {
+ io_thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &RequestProxy::AsyncFollowDeferredRedirect));
+ } else {
+ Cancel();
+ }
}
void NotifyReceivedResponse(const ResourceLoaderBridge::ResponseInfo& info,
@@ -230,6 +235,14 @@ class RequestProxy : public URLRequest::Delegate,
Done();
}
+ void AsyncFollowDeferredRedirect() {
+ // This can be null in cases where the request is already done.
+ if (!request_.get())
+ return;
+
+ request_->FollowDeferredRedirect();
+ }
+
void AsyncReadData() {
// This can be null in cases where the request is already done.
if (!request_.get())
@@ -252,9 +265,13 @@ class RequestProxy : public URLRequest::Delegate,
// callbacks) that run on the IO thread. They are designed to be overridden
// by the SyncRequestProxy subclass.
- virtual void OnReceivedRedirect(const GURL& new_url) {
+ virtual void OnReceivedRedirect(
+ const GURL& new_url,
+ const ResourceLoaderBridge::ResponseInfo& info,
+ bool* defer_redirect) {
+ *defer_redirect = true; // See AsyncFollowDeferredRedirect
owner_loop_->PostTask(FROM_HERE, NewRunnableMethod(
- this, &RequestProxy::NotifyReceivedRedirect, new_url));
+ this, &RequestProxy::NotifyReceivedRedirect, new_url, info));
}
virtual void OnReceivedResponse(
@@ -282,19 +299,15 @@ class RequestProxy : public URLRequest::Delegate,
const GURL& new_url,
bool* defer_redirect) {
DCHECK(request->status().is_success());
- OnReceivedRedirect(new_url);
+ ResourceLoaderBridge::ResponseInfo info;
+ PopulateResponseInfo(request, &info);
+ OnReceivedRedirect(new_url, info, defer_redirect);
}
virtual void OnResponseStarted(URLRequest* request) {
if (request->status().is_success()) {
ResourceLoaderBridge::ResponseInfo info;
- info.request_time = request->request_time();
- info.response_time = request->response_time();
- info.headers = request->response_headers();
- info.app_cache_id = WebAppCacheContext::kNoAppCacheId;
- request->GetMimeType(&info.mime_type);
- request->GetCharset(&info.charset);
- info.content_length = request->GetExpectedContentSize();
+ PopulateResponseInfo(request, &info);
OnReceivedResponse(info, false);
AsyncReadData(); // start reading
} else {
@@ -358,6 +371,17 @@ class RequestProxy : public URLRequest::Delegate,
}
}
+ void PopulateResponseInfo(URLRequest* request,
+ ResourceLoaderBridge::ResponseInfo* info) const {
+ info->request_time = request->request_time();
+ info->response_time = request->response_time();
+ info->headers = request->response_headers();
+ info->app_cache_id = WebAppCacheContext::kNoAppCacheId;
+ request->GetMimeType(&info->mime_type);
+ request->GetCharset(&info->charset);
+ info->content_length = request->GetExpectedContentSize();
+ }
+
scoped_ptr<URLRequest> request_;
// Size of our async IO data buffers
@@ -397,7 +421,18 @@ class SyncRequestProxy : public RequestProxy {
// --------------------------------------------------------------------------
// Event hooks that run on the IO thread:
- virtual void OnReceivedRedirect(const GURL& new_url) {
+ virtual void OnReceivedRedirect(
+ const GURL& new_url,
+ const ResourceLoaderBridge::ResponseInfo& info,
+ bool* defer_redirect) {
+ // 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_->url.GetOrigin()) {
+ LOG(ERROR) << "Cross origin redirect denied";
+ Cancel();
+ return;
+ }
result_->url = new_url;
}