summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rwxr-xr-xchrome/browser/automation/automation_provider.cc12
-rw-r--r--chrome/browser/automation/automation_provider.h3
-rw-r--r--chrome/browser/automation/automation_resource_message_filter.cc144
-rw-r--r--chrome/browser/automation/automation_resource_message_filter.h110
-rw-r--r--chrome/browser/automation/url_request_automation_job.cc289
-rw-r--r--chrome/browser/automation/url_request_automation_job.h79
-rw-r--r--chrome/browser/external_tab_container.cc33
-rw-r--r--chrome/browser/external_tab_container.h10
-rw-r--r--chrome/browser/renderer_host/render_view_host.cc7
-rw-r--r--chrome/browser/renderer_host/render_view_host_delegate.h4
-rw-r--r--chrome/browser/tab_contents/render_view_host_manager.cc15
-rw-r--r--chrome/browser/tab_contents/render_view_host_manager.h6
-rw-r--r--chrome/browser/tab_contents/tab_contents.cc12
-rw-r--r--chrome/browser/tab_contents/tab_contents.h1
-rw-r--r--chrome/chrome.gyp4
-rw-r--r--chrome/common/ipc_message_utils.h53
-rw-r--r--chrome/common/net/url_request_intercept_job.cc23
-rw-r--r--chrome/common/net/url_request_intercept_job.h8
-rw-r--r--chrome/common/notification_type.h12
-rw-r--r--chrome/common/render_messages.h53
-rw-r--r--chrome/test/automation/automation_messages.h72
-rw-r--r--chrome/test/automation/automation_messages_internal.h29
22 files changed, 881 insertions, 98 deletions
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc
index 1217c1a..f386960 100755
--- a/chrome/browser/automation/automation_provider.cc
+++ b/chrome/browser/automation/automation_provider.cc
@@ -806,10 +806,12 @@ AutomationProvider::~AutomationProvider() {
}
void AutomationProvider::ConnectToChannel(const std::string& channel_id) {
+ automation_resource_message_filter_ = new AutomationResourceMessageFilter;
channel_.reset(
- new IPC::SyncChannel(channel_id, IPC::Channel::MODE_CLIENT, this, NULL,
- g_browser_process->io_thread()->message_loop(),
- true, g_browser_process->shutdown_event()));
+ new IPC::SyncChannel(channel_id, IPC::Channel::MODE_CLIENT, this,
+ automation_resource_message_filter_,
+ g_browser_process->io_thread()->message_loop(),
+ true, g_browser_process->shutdown_event()));
scoped_ptr<FileVersionInfo> file_version_info(
FileVersionInfo::CreateFileVersionInfoForCurrentModule());
std::string version_string;
@@ -2390,8 +2392,8 @@ void AutomationProvider::CreateExternalTab(HWND parent,
*tab_handle = 0;
*tab_container_window = NULL;
*tab_window = NULL;
- ExternalTabContainer *external_tab_container =
- new ExternalTabContainer(this);
+ ExternalTabContainer* external_tab_container =
+ new ExternalTabContainer(this, automation_resource_message_filter_);
Profile* profile = incognito? profile_->GetOffTheRecordProfile() : profile_;
external_tab_container->Init(profile, parent, dimensions, style);
TabContents* tab_contents = external_tab_container->tab_contents();
diff --git a/chrome/browser/automation/automation_provider.h b/chrome/browser/automation/automation_provider.h
index c83eaaa..3d90d04 100644
--- a/chrome/browser/automation/automation_provider.h
+++ b/chrome/browser/automation/automation_provider.h
@@ -19,6 +19,7 @@
#include "base/scoped_ptr.h"
#include "chrome/browser/automation/automation_autocomplete_edit_tracker.h"
#include "chrome/browser/automation/automation_browser_tracker.h"
+#include "chrome/browser/automation/automation_resource_message_filter.h"
#include "chrome/browser/automation/automation_tab_tracker.h"
#include "chrome/browser/automation/automation_window_tracker.h"
#include "chrome/browser/browser_list.h"
@@ -487,6 +488,8 @@ class AutomationProvider : public base::RefCounted<AutomationProvider>,
LoginHandlerMap login_handler_map_;
PortContainerMap port_containers_;
NotificationObserverList notification_observer_list_;
+ scoped_refptr<AutomationResourceMessageFilter>
+ automation_resource_message_filter_;
// Handle for an in-process redirect query. We expect only one redirect query
// at a time (we should have only one caller, and it will block while waiting
diff --git a/chrome/browser/automation/automation_resource_message_filter.cc b/chrome/browser/automation/automation_resource_message_filter.cc
new file mode 100644
index 0000000..15e5325
--- /dev/null
+++ b/chrome/browser/automation/automation_resource_message_filter.cc
@@ -0,0 +1,144 @@
+// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/automation/automation_resource_message_filter.h"
+
+#include "base/message_loop.h"
+#include "chrome/browser/automation/url_request_automation_job.h"
+
+
+MessageLoop* AutomationResourceMessageFilter::io_loop_ = NULL;
+AutomationResourceMessageFilter::RenderViewMap
+ AutomationResourceMessageFilter::filtered_render_views_;
+
+AutomationResourceMessageFilter::AutomationResourceMessageFilter()
+ : channel_(NULL), unique_request_id_(1) {
+ URLRequestAutomationJob::InitializeInterceptor();
+}
+
+AutomationResourceMessageFilter::~AutomationResourceMessageFilter() {
+}
+
+// Called on the IPC thread:
+void AutomationResourceMessageFilter::OnFilterAdded(IPC::Channel* channel) {
+ DCHECK(channel_ == NULL);
+ channel_ = channel;
+ io_loop_ = MessageLoop::current();
+}
+
+// Called on the IPC thread:
+void AutomationResourceMessageFilter::OnChannelConnected(int32 peer_pid) {
+}
+
+// Called on the IPC thread:
+void AutomationResourceMessageFilter::OnChannelClosing() {
+ channel_ = NULL;
+ request_map_.clear();
+ filtered_render_views_.clear();
+}
+
+// Called on the IPC thread:
+bool AutomationResourceMessageFilter::OnMessageReceived(
+ const IPC::Message& message) {
+ int request_id = URLRequestAutomationJob::MayFilterMessage(message);
+ if (request_id) {
+ RequestMap::iterator it = request_map_.find(request_id);
+ if (it != request_map_.end()) {
+ URLRequestAutomationJob* job = it->second;
+ DCHECK(job);
+ if (job) {
+ job->OnMessage(message);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+// Called on the IPC thread:
+bool AutomationResourceMessageFilter::Send(IPC::Message* message) {
+ // This has to be called on the IO thread.
+ DCHECK_EQ(io_loop_, MessageLoop::current());
+ if (!channel_) {
+ delete message;
+ return false;
+ }
+
+ return channel_->Send(message);
+}
+
+bool AutomationResourceMessageFilter::RegisterRequest(
+ URLRequestAutomationJob* job) {
+ if (!job) {
+ NOTREACHED();
+ return false;
+ }
+
+ DCHECK_EQ(io_loop_, MessageLoop::current());
+ DCHECK(request_map_.end() == request_map_.find(job->id()));
+ request_map_[job->id()] = job;
+ return true;
+}
+
+void AutomationResourceMessageFilter::UnRegisterRequest(
+ URLRequestAutomationJob* job) {
+ DCHECK_EQ(io_loop_, MessageLoop::current());
+ DCHECK(request_map_.find(job->id()) != request_map_.end());
+ request_map_.erase(job->id());
+}
+
+bool AutomationResourceMessageFilter::RegisterRenderView(
+ int renderer_pid, int renderer_id, int tab_handle,
+ AutomationResourceMessageFilter* filter) {
+ if (!renderer_pid || !renderer_id || !tab_handle) {
+ NOTREACHED();
+ return false;
+ }
+
+ DCHECK(io_loop_);
+ io_loop_->PostTask(FROM_HERE, NewRunnableFunction(
+ AutomationResourceMessageFilter::RegisterRenderViewInIOThread,
+ renderer_pid, renderer_id, tab_handle, filter));
+ return true;
+}
+
+void AutomationResourceMessageFilter::UnRegisterRenderView(
+ int renderer_pid, int renderer_id) {
+ DCHECK(io_loop_);
+ io_loop_->PostTask(FROM_HERE, NewRunnableFunction(
+ AutomationResourceMessageFilter::UnRegisterRenderViewInIOThread,
+ renderer_pid, renderer_id));
+}
+
+void AutomationResourceMessageFilter::RegisterRenderViewInIOThread(
+ int renderer_pid, int renderer_id,
+ int tab_handle, AutomationResourceMessageFilter* filter) {
+ DCHECK(filtered_render_views_.find(RendererId(renderer_pid, renderer_id)) ==
+ filtered_render_views_.end());
+ filtered_render_views_[RendererId(renderer_pid, renderer_id)] =
+ AutomationDetails(tab_handle, filter);
+}
+
+void AutomationResourceMessageFilter::UnRegisterRenderViewInIOThread(
+ int renderer_pid, int renderer_id) {
+ DCHECK(filtered_render_views_.find(RendererId(renderer_pid, renderer_id)) !=
+ filtered_render_views_.end());
+ filtered_render_views_.erase(RendererId(renderer_pid, renderer_id));
+}
+
+bool AutomationResourceMessageFilter::LookupRegisteredRenderView(
+ int renderer_pid, int renderer_id, AutomationDetails* details) {
+ bool found = false;
+ RenderViewMap::iterator it = filtered_render_views_.find(RendererId(
+ renderer_pid, renderer_id));
+ if (it != filtered_render_views_.end()) {
+ found = true;
+ if (details)
+ *details = it->second;
+ }
+
+ return found;
+}
+
diff --git a/chrome/browser/automation/automation_resource_message_filter.h b/chrome/browser/automation/automation_resource_message_filter.h
new file mode 100644
index 0000000..7bec5ca
--- /dev/null
+++ b/chrome/browser/automation/automation_resource_message_filter.h
@@ -0,0 +1,110 @@
+// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_AUTOMATION_AUTOMATION_RESOURCE_MSG_FILTER_H_
+#define CHROME_BROWSER_AUTOMATION_AUTOMATION_RESOURCE_MSG_FILTER_H_
+
+#include <map>
+
+#include "base/lock.h"
+#include "base/platform_thread.h"
+#include "chrome/common/ipc_channel_proxy.h"
+
+class URLRequestAutomationJob;
+class MessageLoop;
+
+// This class filters out incoming automation IPC messages for network
+// requests and processes them on the IPC thread. As a result, network
+// requests are not delayed by costly UI processing that may be occurring
+// on the main thread of the browser. It also means that any hangs in
+// starting a network request will not interfere with browser UI.
+class AutomationResourceMessageFilter
+ : public IPC::ChannelProxy::MessageFilter,
+ public IPC::Message::Sender {
+ public:
+ // Information needed to send IPCs through automation.
+ struct AutomationDetails {
+ AutomationDetails() : tab_handle(0) {}
+ AutomationDetails(int tab, AutomationResourceMessageFilter* flt)
+ : tab_handle(tab), filter(flt) {
+ }
+
+ int tab_handle;
+ scoped_refptr<AutomationResourceMessageFilter> filter;
+ };
+
+ // Create the filter.
+ AutomationResourceMessageFilter();
+ virtual ~AutomationResourceMessageFilter();
+
+ int NewRequestId() {
+ return unique_request_id_++;
+ }
+
+ // IPC::ChannelProxy::MessageFilter methods:
+ virtual void OnFilterAdded(IPC::Channel* channel);
+ virtual void OnChannelConnected(int32 peer_pid);
+ virtual void OnChannelClosing();
+ virtual bool OnMessageReceived(const IPC::Message& message);
+
+ // ResourceDispatcherHost::Receiver methods:
+ virtual bool Send(IPC::Message* message);
+
+ // Add request to the list of outstanding requests.
+ bool RegisterRequest(URLRequestAutomationJob* job);
+
+ // Remove request from the list of outstanding requests.
+ void UnRegisterRequest(URLRequestAutomationJob* job);
+
+ // Can be called from the UI thread.
+ static bool RegisterRenderView(int renderer_pid, int renderer_id,
+ int tab_handle, AutomationResourceMessageFilter* filter);
+ static void UnRegisterRenderView(int renderer_pid, int renderer_id);
+
+ // Called only on the IO thread.
+ static bool LookupRegisteredRenderView(
+ int renderer_pid, int renderer_id, AutomationDetails* details);
+
+ protected:
+ static void RegisterRenderViewInIOThread(int renderer_pid, int renderer_id,
+ int tab_handle, AutomationResourceMessageFilter* filter);
+ static void UnRegisterRenderViewInIOThread(int renderer_pid, int renderer_id);
+
+ private:
+ // A unique renderer id is a combination of renderer process id and
+ // it's routing id.
+ struct RendererId {
+ int pid_;
+ int id_;
+
+ RendererId() : pid_(0), id_(0) {}
+ RendererId(int pid, int id) : pid_(pid), id_(id) {}
+
+ bool operator < (const RendererId& rhs) const {
+ return ((pid_ == rhs.pid_) ? (id_ < rhs.id_) : (pid_ < rhs.pid_));
+ }
+ };
+
+ typedef std::map<RendererId, AutomationDetails> RenderViewMap;
+ typedef std::map<int, scoped_refptr<URLRequestAutomationJob> > RequestMap;
+
+ // The channel associated with the automation connection. This pointer is not
+ // owned by this class.
+ IPC::Channel* channel_;
+ static MessageLoop* io_loop_;
+
+ // A unique request id per automation channel.
+ int unique_request_id_;
+
+ // Map of outstanding requests.
+ RequestMap request_map_;
+
+ // Map of render views interested in diverting url requests over automation.
+ static RenderViewMap filtered_render_views_;
+
+ DISALLOW_COPY_AND_ASSIGN(AutomationResourceMessageFilter);
+};
+
+#endif // CHROME_BROWSER_AUTOMATION_AUTOMATION_RESOURCE_MSG_FILTER_H_
+
diff --git a/chrome/browser/automation/url_request_automation_job.cc b/chrome/browser/automation/url_request_automation_job.cc
new file mode 100644
index 0000000..6ab7f87
--- /dev/null
+++ b/chrome/browser/automation/url_request_automation_job.cc
@@ -0,0 +1,289 @@
+// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/automation/url_request_automation_job.h"
+
+#include "base/message_loop.h"
+#include "chrome/browser/automation/automation_resource_message_filter.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
+#include "chrome/test/automation/automation_messages.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/url_request/url_request.h"
+
+
+// This class manages the interception of network requests for automation.
+// It looks at the request, and creates an intercept job if it indicates
+// that it should use automation channel.
+// NOTE: All methods must be called on the IO thread.
+class AutomationRequestInterceptor : public URLRequest::Interceptor {
+ public:
+ AutomationRequestInterceptor() {
+ URLRequest::RegisterRequestInterceptor(this);
+ }
+
+ virtual ~AutomationRequestInterceptor() {
+ URLRequest::UnregisterRequestInterceptor(this);
+ }
+
+ // URLRequest::Interceptor
+ virtual URLRequestJob* MaybeIntercept(URLRequest* request);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AutomationRequestInterceptor);
+};
+
+URLRequestJob* AutomationRequestInterceptor::MaybeIntercept(
+ URLRequest* request) {
+ ResourceDispatcherHost::ExtraRequestInfo* request_info =
+ ResourceDispatcherHost::ExtraInfoForRequest(request);
+ if (request_info) {
+ AutomationResourceMessageFilter::AutomationDetails details;
+ if (AutomationResourceMessageFilter::LookupRegisteredRenderView(
+ request_info->process_id, request_info->route_id, &details)) {
+ URLRequestAutomationJob* job = new URLRequestAutomationJob(request,
+ details.tab_handle, details.filter);
+ return job;
+ }
+ }
+
+ return NULL;
+}
+
+static URLRequest::Interceptor* GetAutomationRequestInterceptor() {
+ return Singleton<AutomationRequestInterceptor>::get();
+}
+
+int URLRequestAutomationJob::instance_count_ = 0;
+
+URLRequestAutomationJob::URLRequestAutomationJob(
+ URLRequest* request, int tab, AutomationResourceMessageFilter* filter)
+ : URLRequestJob(request), id_(0), tab_(tab), message_filter_(filter),
+ pending_buf_size_(0) {
+ DLOG(INFO) << "URLRequestAutomationJob create. Count: " << ++instance_count_;
+ if (message_filter_) {
+ id_ = message_filter_->NewRequestId();
+ DCHECK(id_);
+ } else {
+ NOTREACHED();
+ }
+}
+
+URLRequestAutomationJob::~URLRequestAutomationJob() {
+ DLOG(INFO) << "URLRequestAutomationJob delete. Count: " << --instance_count_;
+ Cleanup();
+}
+
+bool URLRequestAutomationJob::InitializeInterceptor() {
+ // AutomationRequestInterceptor will register itself when it
+ // is first created.
+ URLRequest::Interceptor* interceptor = GetAutomationRequestInterceptor();
+ return (interceptor != NULL);
+}
+
+// URLRequestJob Implementation.
+void URLRequestAutomationJob::Start() {
+ // Start reading asynchronously so that all error reporting and data
+ // callbacks happen as they would for network requests.
+ MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &URLRequestAutomationJob::StartAsync));
+}
+
+void URLRequestAutomationJob::Kill() {
+ message_filter_->Send(new AutomationMsg_RequestEnd(0, tab_, id_,
+ URLRequestStatus(URLRequestStatus::CANCELED, 0)));
+ DisconnectFromMessageFilter();
+ URLRequestJob::Kill();
+}
+
+bool URLRequestAutomationJob::ReadRawData(
+ net::IOBuffer* buf, int buf_size, int* bytes_read) {
+ DLOG(INFO) << "URLRequestAutomationJob: " <<
+ request_->url().spec() << " - read pending: " << buf_size;
+ pending_buf_ = buf;
+ pending_buf_size_ = buf_size;
+
+ message_filter_->Send(new AutomationMsg_RequestRead(0, tab_, id_,
+ buf_size));
+ SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
+ return false;
+}
+
+bool URLRequestAutomationJob::GetMimeType(std::string* mime_type) const {
+ if (!mime_type_.empty()) {
+ *mime_type = mime_type_;
+ } else if (headers_) {
+ headers_->GetMimeType(mime_type);
+ }
+
+ return (!mime_type->empty());
+}
+
+bool URLRequestAutomationJob::GetCharset(std::string* charset) {
+ if (headers_)
+ return headers_->GetCharset(charset);
+ return false;
+}
+
+void URLRequestAutomationJob::GetResponseInfo(net::HttpResponseInfo* info) {
+ if (headers_)
+ info->headers = headers_;
+ if (request_->url().SchemeIsSecure()) {
+ // TODO(joshia): fill up SSL related fields.
+ }
+}
+
+int URLRequestAutomationJob::GetResponseCode() const {
+ if (headers_)
+ return headers_->response_code();
+
+ static const int kDefaultResponseCode = 200;
+ return kDefaultResponseCode;
+}
+
+bool URLRequestAutomationJob::IsRedirectResponse(
+ GURL* location, int* http_status_code) {
+ if (!request_->response_headers())
+ return false;
+
+ std::string value;
+ if (!request_->response_headers()->IsRedirect(&value))
+ return false;
+
+ *location = request_->url().Resolve(value);
+ *http_status_code = request_->response_headers()->response_code();
+ return true;
+}
+
+int URLRequestAutomationJob::MayFilterMessage(const IPC::Message& message) {
+ switch (message.type()) {
+ case AutomationMsg_RequestStarted::ID:
+ case AutomationMsg_RequestData::ID:
+ case AutomationMsg_RequestEnd::ID: {
+ void* iter = NULL;
+ int tab = 0;
+ int id = 0;
+ if (message.ReadInt(&iter, &tab) && message.ReadInt(&iter, &id)) {
+ DCHECK(id);
+ return id;
+ }
+ break;
+ }
+ }
+
+ return 0;
+}
+
+void URLRequestAutomationJob::OnMessage(const IPC::Message& message) {
+ IPC_BEGIN_MESSAGE_MAP(URLRequestAutomationJob, message)
+ IPC_MESSAGE_HANDLER(AutomationMsg_RequestStarted, OnRequestStarted)
+ IPC_MESSAGE_HANDLER(AutomationMsg_RequestData, OnDataAvailable)
+ IPC_MESSAGE_HANDLER(AutomationMsg_RequestEnd, OnRequestEnd)
+ IPC_END_MESSAGE_MAP()
+}
+
+void URLRequestAutomationJob::OnRequestStarted(
+ int tab, int id, const IPC::AutomationURLResponse& response) {
+ DLOG(INFO) << "URLRequestAutomationJob: " <<
+ request_->url().spec() << " - response started.";
+ set_expected_content_size(response.content_length);
+ mime_type_ = response.mime_type;
+
+ if (!response.headers.empty())
+ headers_ = new net::HttpResponseHeaders(response.headers);
+
+ NotifyHeadersComplete();
+}
+
+void URLRequestAutomationJob::OnDataAvailable(
+ int tab, int id, const std::string& bytes) {
+ DLOG(INFO) << "URLRequestAutomationJob: " <<
+ request_->url().spec() << " - data available, Size: " << bytes.size();
+ DCHECK(!bytes.empty());
+
+ // The request completed, and we have all the data.
+ // Clear any IO pending status.
+ SetStatus(URLRequestStatus());
+
+ if (pending_buf_ && pending_buf_->data()) {
+ DCHECK_GE(pending_buf_size_, bytes.size());
+ const int bytes_to_copy = std::min(bytes.size(), pending_buf_size_);
+ memcpy(pending_buf_->data(), &bytes[0], bytes_to_copy);
+
+ pending_buf_ = NULL;
+ pending_buf_size_ = 0;
+
+ NotifyReadComplete(bytes_to_copy);
+ }
+}
+
+void URLRequestAutomationJob::OnRequestEnd(
+ int tab, int id, const URLRequestStatus& status) {
+ DLOG(INFO) << "URLRequestAutomationJob: " <<
+ request_->url().spec() << " - request end. Status: " << status.status();
+
+ DisconnectFromMessageFilter();
+ NotifyDone(status);
+
+ // Reset any pending reads.
+ if (pending_buf_) {
+ pending_buf_ = NULL;
+ pending_buf_size_ = 0;
+ NotifyReadComplete(0);
+ }
+}
+
+void URLRequestAutomationJob::Cleanup() {
+ headers_ = NULL;
+ mime_type_.erase();
+
+ id_ = 0;
+ tab_ = 0;
+
+ DCHECK(message_filter_ == NULL);
+ DisconnectFromMessageFilter();
+
+ pending_buf_ = NULL;
+ pending_buf_size_ = 0;
+}
+
+void URLRequestAutomationJob::StartAsync() {
+ DLOG(INFO) << "URLRequestAutomationJob: start request: " <<
+ request_->url().spec();
+
+ // If the job is cancelled before we got a chance to start it
+ // we have nothing much to do here.
+ if (is_done())
+ return;
+
+ if (!request_) {
+ NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED,
+ net::ERR_FAILED));
+ return;
+ }
+
+ // Register this request with automation message filter.
+ message_filter_->RegisterRequest(this);
+
+ // Ask automation to start this request.
+ IPC::AutomationURLRequest automation_request = {
+ request_->url().spec(),
+ request_->method(),
+ request_->referrer(),
+ request_->extra_request_headers()
+ };
+
+ DCHECK(message_filter_);
+ message_filter_->Send(new AutomationMsg_RequestStart(0, tab_, id_,
+ automation_request));
+}
+
+void URLRequestAutomationJob::DisconnectFromMessageFilter() {
+ if (message_filter_) {
+ message_filter_->UnRegisterRequest(this);
+ message_filter_ = NULL;
+ }
+}
+
diff --git a/chrome/browser/automation/url_request_automation_job.h b/chrome/browser/automation/url_request_automation_job.h
new file mode 100644
index 0000000..db61781
--- /dev/null
+++ b/chrome/browser/automation/url_request_automation_job.h
@@ -0,0 +1,79 @@
+// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+// This class simulates what wininet does when a dns lookup fails.
+
+#ifndef CHROME_BROWSER_AUTOMATION_AUTOMATION_URL_REQUEST_JOB_H_
+#define CHROME_BROWSER_AUTOMATION_AUTOMATION_URL_REQUEST_JOB_H_
+
+#include "chrome/common/ref_counted_util.h"
+#include "net/http/http_response_headers.h"
+#include "net/url_request/url_request_job.h"
+
+class AutomationResourceMessageFilter;
+
+namespace IPC {
+class Message;
+struct AutomationURLResponse;
+};
+
+// URLRequestJob implementation that loads the resources using
+// automation.
+class URLRequestAutomationJob : public URLRequestJob {
+ public:
+ URLRequestAutomationJob(
+ URLRequest* request, int tab, AutomationResourceMessageFilter* filter);
+ virtual ~URLRequestAutomationJob();
+
+ // Register an interceptor for URL requests.
+ static bool InitializeInterceptor();
+
+ // URLRequestJob methods.
+ virtual void Start();
+ virtual void Kill();
+ virtual bool GetMimeType(std::string* mime_type) const;
+ virtual bool GetCharset(std::string* charset);
+ virtual void GetResponseInfo(net::HttpResponseInfo* info);
+ virtual int GetResponseCode() const;
+ virtual bool IsRedirectResponse(GURL* location, int* http_status_code);
+
+ // Peek and process automation messages for URL requests.
+ static int MayFilterMessage(const IPC::Message& message);
+ void OnMessage(const IPC::Message& message);
+
+ int id() const {
+ return id_;
+ }
+
+ protected:
+ // Protected URLRequestJob override.
+ virtual bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read);
+
+ void StartAsync();
+ void Cleanup();
+ void DisconnectFromMessageFilter();
+
+ // IPC message handlers.
+ void OnRequestStarted(int tab, int id,
+ const IPC::AutomationURLResponse& response);
+ void OnDataAvailable(int tab, int id, const std::string& bytes);
+ void OnRequestEnd(int tab, int id, const URLRequestStatus& status);
+
+ private:
+ int id_;
+ int tab_;
+ scoped_refptr<AutomationResourceMessageFilter> message_filter_;
+
+ scoped_refptr<net::IOBuffer> pending_buf_;
+ size_t pending_buf_size_;
+
+ std::string mime_type_;
+ scoped_refptr<net::HttpResponseHeaders> headers_;
+
+ static int instance_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(URLRequestAutomationJob);
+};
+
+#endif // CHROME_BROWSER_AUTOMATION_AUTOMATION_URL_REQUEST_JOB_H_
+
diff --git a/chrome/browser/external_tab_container.cc b/chrome/browser/external_tab_container.cc
index 62b6a3f..732aead 100644
--- a/chrome/browser/external_tab_container.cc
+++ b/chrome/browser/external_tab_container.cc
@@ -31,14 +31,16 @@ static const wchar_t kWindowObjectKey[] = L"ChromeWindowObject";
// member variables are now obsolete and we don't use them.
// We need to remove them.
ExternalTabContainer::ExternalTabContainer(
- AutomationProvider* automation)
+ AutomationProvider* automation, AutomationResourceMessageFilter* filter)
: automation_(automation),
tab_contents_(NULL),
external_accel_table_(NULL),
external_accel_entry_count_(0),
tab_contents_container_(NULL),
tab_handle_(0),
- ignore_next_load_notification_(false) {
+ ignore_next_load_notification_(false),
+ automation_resource_message_filter_(filter),
+ load_requests_via_automation_(false) {
}
ExternalTabContainer::~ExternalTabContainer() {
@@ -86,6 +88,11 @@ bool ExternalTabContainer::Init(Profile* profile,
Source<NavigationController>(controller));
registrar_.Add(this, NotificationType::LOAD_STOP,
Source<NavigationController>(controller));
+ registrar_.Add(this, NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB,
+ Source<TabContents>(tab_contents_));
+ registrar_.Add(this, NotificationType::RENDER_VIEW_HOST_DELETED,
+ Source<TabContents>(tab_contents_));
+
NotificationService::current()->Notify(
NotificationType::EXTERNAL_TAB_CREATED,
Source<NavigationController>(controller),
@@ -350,6 +357,27 @@ void ExternalTabContainer::Observe(NotificationType type,
ignore_next_load_notification_ = true;
break;
}
+ case NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB: {
+ if (load_requests_via_automation_) {
+ RenderViewHost* rvh = Details<RenderViewHost>(details).ptr();
+ if (rvh) {
+ AutomationResourceMessageFilter::RegisterRenderView(
+ rvh->process()->pid(), rvh->routing_id(), tab_handle_,
+ automation_resource_message_filter_);
+ }
+ }
+ break;
+ }
+ case NotificationType::RENDER_VIEW_HOST_DELETED: {
+ if (load_requests_via_automation_) {
+ RenderViewHost* rvh = Details<RenderViewHost>(details).ptr();
+ if (rvh) {
+ AutomationResourceMessageFilter::UnRegisterRenderView(
+ rvh->process()->pid(), rvh->routing_id());
+ }
+ }
+ break;
+ }
default:
NOTREACHED();
}
@@ -407,6 +435,7 @@ bool ExternalTabContainer::ProcessKeyStroke(HWND window, UINT message,
// ExternalTabContainer, private:
void ExternalTabContainer::Uninitialize(HWND window) {
+ registrar_.RemoveAll();
if (tab_contents_) {
NotificationService::current()->Notify(
NotificationType::EXTERNAL_TAB_CLOSED,
diff --git a/chrome/browser/external_tab_container.h b/chrome/browser/external_tab_container.h
index 3037847..e69283c 100644
--- a/chrome/browser/external_tab_container.h
+++ b/chrome/browser/external_tab_container.h
@@ -7,6 +7,7 @@
#include <vector>
+#include "chrome/browser/automation/automation_resource_message_filter.h"
#include "chrome/browser/tab_contents/tab_contents_delegate.h"
#include "chrome/common/notification_observer.h"
#include "chrome/common/notification_registrar.h"
@@ -27,7 +28,8 @@ class ExternalTabContainer : public TabContentsDelegate,
public views::WidgetWin,
public views::KeystrokeListener {
public:
- explicit ExternalTabContainer(AutomationProvider* automation);
+ ExternalTabContainer(AutomationProvider* automation,
+ AutomationResourceMessageFilter* filter);
~ExternalTabContainer();
TabContents* tab_contents() const { return tab_contents_; }
@@ -140,6 +142,12 @@ class ExternalTabContainer : public TabContentsDelegate,
scoped_ptr<RenderViewContextMenuExternalWin> external_context_menu_;
+ // A message filter to load resources via automation
+ AutomationResourceMessageFilter* automation_resource_message_filter_;
+
+ // If all the url requests for this tab are to be loaded via automation.
+ bool load_requests_via_automation_;
+
DISALLOW_COPY_AND_ASSIGN(ExternalTabContainer);
};
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc
index 43de151..84f13d6 100644
--- a/chrome/browser/renderer_host/render_view_host.cc
+++ b/chrome/browser/renderer_host/render_view_host.cc
@@ -123,6 +123,8 @@ RenderViewHost::RenderViewHost(SiteInstance* instance,
}
RenderViewHost::~RenderViewHost() {
+ delegate()->RenderViewDeleted(this);
+
DevToolsManager* devtools_manager = DevToolsManager::GetInstance();
if (devtools_manager) // NULL in tests
devtools_manager->UnregisterDevToolsClientHostFor(this);
@@ -130,11 +132,6 @@ RenderViewHost::~RenderViewHost() {
// Be sure to clean up any leftover state from cross-site requests.
Singleton<CrossSiteRequestManager>()->SetHasPendingCrossSiteRequest(
process()->pid(), routing_id(), false);
-
- NotificationService::current()->Notify(
- NotificationType::RENDER_VIEW_HOST_DELETED,
- Source<RenderViewHost>(this),
- NotificationService::NoDetails());
}
void RenderViewHost::Observe(NotificationType type,
diff --git a/chrome/browser/renderer_host/render_view_host_delegate.h b/chrome/browser/renderer_host/render_view_host_delegate.h
index b1992e8..28e9fdc 100644
--- a/chrome/browser/renderer_host/render_view_host_delegate.h
+++ b/chrome/browser/renderer_host/render_view_host_delegate.h
@@ -315,6 +315,10 @@ class RenderViewHostDelegate {
// The RenderView died somehow (crashed or was killed by the user).
virtual void RenderViewGone(RenderViewHost* render_view_host) {}
+ // The RenderView is going to be deleted. This is called when each
+ // RenderView is going to be destroyed
+ virtual void RenderViewDeleted(RenderViewHost* render_view_host) { }
+
// The RenderView was navigated to a different page.
virtual void DidNavigate(RenderViewHost* render_view_host,
const ViewHostMsg_FrameNavigate_Params& params) {}
diff --git a/chrome/browser/tab_contents/render_view_host_manager.cc b/chrome/browser/tab_contents/render_view_host_manager.cc
index fba410d..28f5a95 100644
--- a/chrome/browser/tab_contents/render_view_host_manager.cc
+++ b/chrome/browser/tab_contents/render_view_host_manager.cc
@@ -34,8 +34,6 @@ RenderViewHostManager::RenderViewHostManager(
render_view_host_(NULL),
pending_render_view_host_(NULL),
interstitial_page_(NULL) {
- registrar_.Add(this, NotificationType::RENDER_VIEW_HOST_DELETED,
- NotificationService::AllSources());
}
RenderViewHostManager::~RenderViewHostManager() {
@@ -258,18 +256,6 @@ void RenderViewHostManager::OnJavaScriptMessageBoxWindowDestroyed() {
render_view_host_->JavaScriptMessageBoxWindowDestroyed();
}
-void RenderViewHostManager::Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- // Debugging code to help isolate
- // http://code.google.com/p/chromium/issues/detail?id=6316 . We should never
- // reference a RVH that is about to be deleted.
- RenderViewHost* deleted_rvh = Source<RenderViewHost>(source).ptr();
- CHECK(deleted_rvh);
- CHECK(render_view_host_ != deleted_rvh);
- CHECK(pending_render_view_host_ != deleted_rvh);
-}
-
bool RenderViewHostManager::ShouldTransitionCrossSite() {
// True if we are using process-per-site-instance (default) or
// process-per-site (kProcessPerSite).
@@ -301,7 +287,6 @@ bool RenderViewHostManager::ShouldSwapProcessesForNavigation(
new_entry->url().SchemeIs(chrome::kExtensionScheme))
if (cur_entry->url().GetOrigin() != new_entry->url().GetOrigin())
return true;
-
return false;
}
diff --git a/chrome/browser/tab_contents/render_view_host_manager.h b/chrome/browser/tab_contents/render_view_host_manager.h
index 6823512..a725d16 100644
--- a/chrome/browser/tab_contents/render_view_host_manager.h
+++ b/chrome/browser/tab_contents/render_view_host_manager.h
@@ -23,7 +23,7 @@ class SiteInstance;
// Manages RenderViewHosts for a TabContents. Normally there is only one and
// it is easy to do. But we can also have transitions of processes (and hence
// RenderViewHosts) that can get complex.
-class RenderViewHostManager : public NotificationObserver {
+class RenderViewHostManager {
public:
// Functions implemented by our owner that we need.
//
@@ -172,10 +172,6 @@ class RenderViewHostManager : public NotificationObserver {
return interstitial_page_;
}
- virtual void Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details);
-
private:
friend class TestTabContents;
diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc
index de13654..b417f34 100644
--- a/chrome/browser/tab_contents/tab_contents.cc
+++ b/chrome/browser/tab_contents/tab_contents.cc
@@ -1714,6 +1714,11 @@ TabContents* TabContents::GetAsTabContents() {
}
void TabContents::RenderViewCreated(RenderViewHost* render_view_host) {
+ NotificationService::current()->Notify(
+ NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB,
+ Source<TabContents>(this),
+ Details<RenderViewHost>(render_view_host));
+
NavigationEntry* entry = controller_.GetActiveEntry();
if (!entry)
return;
@@ -1764,6 +1769,13 @@ void TabContents::RenderViewGone(RenderViewHost* rvh) {
HungRendererDialog::HideForTabContents(this);
}
+void TabContents::RenderViewDeleted(RenderViewHost* rvh) {
+ NotificationService::current()->Notify(
+ NotificationType::RENDER_VIEW_HOST_DELETED,
+ Source<TabContents>(this),
+ Details<RenderViewHost>(rvh));
+}
+
void TabContents::DidNavigate(RenderViewHost* rvh,
const ViewHostMsg_FrameNavigate_Params& params) {
if (PageTransition::IsMainFrame(params.transition))
diff --git a/chrome/browser/tab_contents/tab_contents.h b/chrome/browser/tab_contents/tab_contents.h
index 7597003..6b8f417 100644
--- a/chrome/browser/tab_contents/tab_contents.h
+++ b/chrome/browser/tab_contents/tab_contents.h
@@ -781,6 +781,7 @@ class TabContents : public PageNavigator,
virtual void RenderViewCreated(RenderViewHost* render_view_host);
virtual void RenderViewReady(RenderViewHost* render_view_host);
virtual void RenderViewGone(RenderViewHost* render_view_host);
+ virtual void RenderViewDeleted(RenderViewHost* render_view_host);
virtual void DidNavigate(RenderViewHost* render_view_host,
const ViewHostMsg_FrameNavigate_Params& params);
virtual void UpdateState(RenderViewHost* render_view_host,
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 8dcb0fa..4eb8b1f 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -616,9 +616,13 @@
'browser/automation/automation_provider_list_generic.cc',
'browser/automation/automation_provider_list_mac.mm',
'browser/automation/automation_provider_list.h',
+ 'browser/automation/automation_resource_message_filter.cc',
+ 'browser/automation/automation_resource_message_filter.h',
'browser/automation/automation_resource_tracker.cc',
'browser/automation/automation_resource_tracker.h',
'browser/automation/automation_tab_tracker.h',
+ 'browser/automation/url_request_automation_job.cc',
+ 'browser/automation/url_request_automation_job.h',
'browser/automation/automation_window_tracker.h',
'browser/automation/extension_port_container.cc',
'browser/automation/extension_port_container.h',
diff --git a/chrome/common/ipc_message_utils.h b/chrome/common/ipc_message_utils.h
index 53c7974..c63eb6c 100644
--- a/chrome/common/ipc_message_utils.h
+++ b/chrome/common/ipc_message_utils.h
@@ -21,6 +21,7 @@
#include "chrome/common/ipc_sync_message.h"
#include "chrome/common/thumbnail_score.h"
#include "chrome/common/transport_dib.h"
+#include "net/url_request/url_request_status.h"
#include "webkit/glue/webcursor.h"
#include "webkit/glue/window_open_disposition.h"
@@ -943,6 +944,58 @@ struct ParamTraits<TransportDIB::Id> {
};
#endif
+// Traits for URLRequestStatus
+template <>
+struct ParamTraits<URLRequestStatus> {
+ typedef URLRequestStatus param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, static_cast<int>(p.status()));
+ WriteParam(m, p.os_error());
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ int status, os_error;
+ if (!ReadParam(m, iter, &status) ||
+ !ReadParam(m, iter, &os_error))
+ return false;
+ r->set_status(static_cast<URLRequestStatus::Status>(status));
+ r->set_os_error(os_error);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ std::wstring status;
+ switch (p.status()) {
+ case URLRequestStatus::SUCCESS:
+ status = L"SUCCESS";
+ break;
+ case URLRequestStatus::IO_PENDING:
+ status = L"IO_PENDING ";
+ break;
+ case URLRequestStatus::HANDLED_EXTERNALLY:
+ status = L"HANDLED_EXTERNALLY";
+ break;
+ case URLRequestStatus::CANCELED:
+ status = L"CANCELED";
+ break;
+ case URLRequestStatus::FAILED:
+ status = L"FAILED";
+ break;
+ default:
+ status = L"UNKNOWN";
+ break;
+ }
+ if (p.status() == URLRequestStatus::FAILED)
+ l->append(L"(");
+
+ LogParam(status, l);
+
+ if (p.status() == URLRequestStatus::FAILED) {
+ l->append(L", ");
+ LogParam(p.os_error(), l);
+ l->append(L")");
+ }
+ }
+};
+
template <>
struct ParamTraits<Message> {
static void Write(Message* m, const Message& p) {
diff --git a/chrome/common/net/url_request_intercept_job.cc b/chrome/common/net/url_request_intercept_job.cc
index bb5dd8c..af1c8c7 100644
--- a/chrome/common/net/url_request_intercept_job.cc
+++ b/chrome/common/net/url_request_intercept_job.cc
@@ -101,10 +101,25 @@ bool URLRequestInterceptJob::GetCharset(std::string* charset) {
return request_->response_headers()->GetCharset(charset);
}
-bool URLRequestInterceptJob::GetContentEncoding(std::string* encoding_type) {
- // TODO(darin): what if there are multiple content encodings?
- return request_->response_headers()->EnumerateHeader(NULL, "Content-Encoding",
- encoding_type);
+bool URLRequestInterceptJob::GetContentEncodings(
+ std::vector<Filter::FilterType>* encoding_types) {
+ DCHECK(encoding_types->empty());
+ if (!request_->response_headers())
+ return false;
+
+ std::string encoding_type;
+ void* iter = NULL;
+ while (request_->response_headers()->EnumerateHeader(
+ &iter, "Content-Encoding", &encoding_type)) {
+ encoding_types->push_back(Filter::ConvertEncodingToType(encoding_type));
+ }
+
+ // Even if encoding types are empty, there is a chance that we need to add
+ // some decoding, as some proxies strip encoding completely. In such cases,
+ // we may need to add (for example) SDCH filtering (when the context suggests
+ // it is appropriate).
+ Filter::FixupEncodingTypes(*this, encoding_types);
+ return !encoding_types->empty();
}
void URLRequestInterceptJob::GetResponseInfo(net::HttpResponseInfo* info) {
diff --git a/chrome/common/net/url_request_intercept_job.h b/chrome/common/net/url_request_intercept_job.h
index 73f354d..07db154 100644
--- a/chrome/common/net/url_request_intercept_job.h
+++ b/chrome/common/net/url_request_intercept_job.h
@@ -35,18 +35,22 @@ class URLRequestInterceptJob
// URLRequestJob
virtual void Start();
virtual void Kill();
- virtual bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read);
virtual bool GetMimeType(std::string* mime_type) const;
virtual bool GetCharset(std::string* charset);
virtual void GetResponseInfo(net::HttpResponseInfo* info);
virtual int GetResponseCode() const;
- virtual bool GetContentEncoding(std::string* encoding_type);
+ virtual bool GetContentEncodings(
+ std::vector<Filter::FilterType>* encoding_types);
virtual bool IsRedirectResponse(GURL* location, int* http_status_code);
// NotificationObserver
virtual void Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details);
+
+ protected:
+ virtual bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read);
+
private:
void StartAsync();
void DetachPlugin();
diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h
index f8e6a81..f222972 100644
--- a/chrome/common/notification_type.h
+++ b/chrome/common/notification_type.h
@@ -284,11 +284,11 @@ class NotificationType {
TAB_CONTENTS_DESTROYED,
// A RenderViewHost was created for a TabContents. The source is the
- // RenderViewHostManager who owns it, and the details is the RenderViewHost
- // pointer. Note that the source will be NULL in some cases for testing,
- // when there is no RVHManager.
+ // associated TabContents, and the details is the RenderViewHost
+ // pointer.
RENDER_VIEW_HOST_CREATED_FOR_TAB,
+
// Stuff inside the tabs ---------------------------------------------------
// This message is sent after a constrained window has been closed. The
@@ -329,6 +329,9 @@ class NotificationType {
// the RenderWidgetHost, the details are not used.
RENDER_WIDGET_HOST_DESTROYED,
+ // Sent from ~RenderViewHost. The source is the RenderViewHost.
+ RENDER_VIEW_HOST_DELETED,
+
// Indicates a RenderWidgetHost has been hidden or restored. The source is
// the RWH whose visibility changed, the details is a bool set to true if
// the new state is "visible."
@@ -592,9 +595,6 @@ class NotificationType {
// Debugging ---------------------------------------------------------------
- // Sent from ~RenderViewHost. The source is the RenderViewHost.
- RENDER_VIEW_HOST_DELETED,
-
// Count (must be last) ----------------------------------------------------
// Used to determine the number of notification types. Not valid as
// a type parameter when registering for or posting notifications.
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index b2fd1f9..829a8ed 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -25,7 +25,6 @@
#include "media/audio/audio_output.h"
#include "net/base/upload_data.h"
#include "net/http/http_response_headers.h"
-#include "net/url_request/url_request_status.h"
#include "webkit/glue/autofill_form.h"
#include "webkit/glue/context_menu.h"
#include "webkit/glue/form_data.h"
@@ -1246,58 +1245,6 @@ struct ParamTraits<ViewHostMsg_Resource_Request> {
}
};
-// Traits for URLRequestStatus
-template <>
-struct ParamTraits<URLRequestStatus> {
- typedef URLRequestStatus param_type;
- static void Write(Message* m, const param_type& p) {
- WriteParam(m, static_cast<int>(p.status()));
- WriteParam(m, p.os_error());
- }
- static bool Read(const Message* m, void** iter, param_type* r) {
- int status, os_error;
- if (!ReadParam(m, iter, &status) ||
- !ReadParam(m, iter, &os_error))
- return false;
- r->set_status(static_cast<URLRequestStatus::Status>(status));
- r->set_os_error(os_error);
- return true;
- }
- static void Log(const param_type& p, std::wstring* l) {
- std::wstring status;
- switch (p.status()) {
- case URLRequestStatus::SUCCESS:
- status = L"SUCCESS";
- break;
- case URLRequestStatus::IO_PENDING:
- status = L"IO_PENDING ";
- break;
- case URLRequestStatus::HANDLED_EXTERNALLY:
- status = L"HANDLED_EXTERNALLY";
- break;
- case URLRequestStatus::CANCELED:
- status = L"CANCELED";
- break;
- case URLRequestStatus::FAILED:
- status = L"FAILED";
- break;
- default:
- status = L"UNKNOWN";
- break;
- }
- if (p.status() == URLRequestStatus::FAILED)
- l->append(L"(");
-
- LogParam(status, l);
-
- if (p.status() == URLRequestStatus::FAILED) {
- l->append(L", ");
- LogParam(p.os_error(), l);
- l->append(L")");
- }
- }
-};
-
template <>
struct ParamTraits<scoped_refptr<net::HttpResponseHeaders> > {
typedef scoped_refptr<net::HttpResponseHeaders> param_type;
diff --git a/chrome/test/automation/automation_messages.h b/chrome/test/automation/automation_messages.h
index 6c198c9..f19a74f 100644
--- a/chrome/test/automation/automation_messages.h
+++ b/chrome/test/automation/automation_messages.h
@@ -223,6 +223,78 @@ struct ParamTraits<Reposition_Params> {
};
#endif // defined(OS_WIN)
+struct AutomationURLRequest {
+ std::string url;
+ std::string method;
+ std::string referrer;
+ std::string extra_request_headers;
+};
+
+// Traits for AutomationURLRequest structure to pack/unpack.
+template <>
+struct ParamTraits<AutomationURLRequest> {
+ typedef AutomationURLRequest param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.url);
+ WriteParam(m, p.method);
+ WriteParam(m, p.referrer);
+ WriteParam(m, p.extra_request_headers);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return ReadParam(m, iter, &p->url) &&
+ ReadParam(m, iter, &p->method) &&
+ ReadParam(m, iter, &p->referrer) &&
+ ReadParam(m, iter, &p->extra_request_headers);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.url, l);
+ l->append(L", ");
+ LogParam(p.method, l);
+ l->append(L", ");
+ LogParam(p.referrer, l);
+ l->append(L", ");
+ LogParam(p.extra_request_headers, l);
+ l->append(L")");
+ }
+};
+
+struct AutomationURLResponse {
+ std::string mime_type;
+ std::string headers;
+ int64 content_length;
+ base::Time last_modified;
+};
+
+// Traits for AutomationURLRequest structure to pack/unpack.
+template <>
+struct ParamTraits<AutomationURLResponse> {
+ typedef AutomationURLResponse param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.mime_type);
+ WriteParam(m, p.headers);
+ WriteParam(m, p.content_length);
+ WriteParam(m, p.last_modified);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return ReadParam(m, iter, &p->mime_type) &&
+ ReadParam(m, iter, &p->headers) &&
+ ReadParam(m, iter, &p->content_length) &&
+ ReadParam(m, iter, &p->last_modified);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.mime_type, l);
+ l->append(L", ");
+ LogParam(p.headers, l);
+ l->append(L", ");
+ LogParam(p.content_length, l);
+ l->append(L", ");
+ LogParam(p.last_modified, l);
+ l->append(L")");
+ }
+};
+
} // namespace IPC
#define MESSAGES_INTERNAL_FILE \
diff --git a/chrome/test/automation/automation_messages_internal.h b/chrome/test/automation/automation_messages_internal.h
index 66b898e..1eac286 100644
--- a/chrome/test/automation/automation_messages_internal.h
+++ b/chrome/test/automation/automation_messages_internal.h
@@ -944,4 +944,33 @@ IPC_BEGIN_MESSAGES(Automation)
int /* selected_command */)
#endif // OS_WIN
+ // A URL request to be fetched via automation
+ IPC_MESSAGE_ROUTED3(AutomationMsg_RequestStart,
+ int /* tab_handle */,
+ int /* request_id */,
+ IPC::AutomationURLRequest /* request */)
+
+ // Read data from a URL request to be fetched via automation
+ IPC_MESSAGE_ROUTED3(AutomationMsg_RequestRead,
+ int /* tab_handle */,
+ int /* request_id */,
+ int /* bytes_to_read */)
+
+ // Response to a AutomationMsg_RequestStart message
+ IPC_MESSAGE_ROUTED3(AutomationMsg_RequestStarted,
+ int /* tab_handle */,
+ int /* request_id */,
+ IPC::AutomationURLResponse /* response */)
+
+ // Data read via automation
+ IPC_MESSAGE_ROUTED3(AutomationMsg_RequestData,
+ int /* tab_handle */,
+ int /* request_id */,
+ std::string /* data */)
+
+ IPC_MESSAGE_ROUTED3(AutomationMsg_RequestEnd,
+ int /* tab_handle */,
+ int /* request_id */,
+ URLRequestStatus /* status */)
+
IPC_END_MESSAGES(Automation)