summaryrefslogtreecommitdiffstats
path: root/chrome/browser/renderer_host/render_view_host.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/renderer_host/render_view_host.cc')
-rw-r--r--chrome/browser/renderer_host/render_view_host.cc1310
1 files changed, 1310 insertions, 0 deletions
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc
new file mode 100644
index 0000000..dca1a1d
--- /dev/null
+++ b/chrome/browser/renderer_host/render_view_host.cc
@@ -0,0 +1,1310 @@
+// Copyright (c) 2006-2008 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/renderer_host/render_view_host.h"
+
+#include <string>
+#include <vector>
+
+#include "base/string_util.h"
+#include "base/waitable_event.h"
+#include "chrome/app/result_codes.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/cross_site_request_manager.h"
+#include "chrome/browser/debugger/debugger_wrapper.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/renderer_host/render_process_host.h"
+#include "chrome/browser/renderer_host/render_view_host_delegate.h"
+#include "chrome/browser/renderer_host/render_widget_host.h"
+#include "chrome/browser/renderer_host/render_widget_host_view.h"
+#include "chrome/browser/renderer_host/renderer_security_policy.h"
+#include "chrome/browser/tab_contents/navigation_entry.h"
+#include "chrome/browser/tab_contents/site_instance.h"
+#include "chrome/browser/tab_contents/web_contents.h"
+#include "chrome/common/resource_bundle.h"
+#include "chrome/common/thumbnail_score.h"
+#include "net/base/net_util.h"
+#include "skia/include/SkBitmap.h"
+
+using base::TimeDelta;
+
+namespace {
+
+void FilterURL(RendererSecurityPolicy* policy, int renderer_id, GURL* url) {
+ if (!url->is_valid())
+ return; // We don't need to block invalid URLs.
+
+ if (url->SchemeIs("about")) {
+ // The renderer treats all URLs in the about: scheme as being about:blank.
+ // Canonicalize about: URLs to about:blank.
+ *url = GURL("about:blank");
+ }
+
+ if (!policy->CanRequestURL(renderer_id, *url)) {
+ // If this renderer is not permitted to request this URL, we invalidate the
+ // URL. This prevents us from storing the blocked URL and becoming confused
+ // later.
+ LOG(INFO) << "Blocked URL " << url->spec();
+ *url = GURL();
+ }
+}
+
+// Delay to wait on closing the tab for a beforeunload/unload handler to fire.
+const int kUnloadTimeoutMS = 1000;
+
+} // namespace
+
+///////////////////////////////////////////////////////////////////////////////
+// RenderViewHost, public:
+
+// static
+RenderViewHost* RenderViewHost::FromID(int render_process_id,
+ int render_view_id) {
+ RenderProcessHost* process = RenderProcessHost::FromID(render_process_id);
+ if (!process)
+ return NULL;
+ RenderWidgetHost* widget = static_cast<RenderWidgetHost*>(
+ process->GetListenerByID(render_view_id));
+ if (!widget || !widget->IsRenderView())
+ return NULL;
+ return static_cast<RenderViewHost*>(widget);
+}
+
+RenderViewHost::RenderViewHost(SiteInstance* instance,
+ RenderViewHostDelegate* delegate,
+ int routing_id,
+ base::WaitableEvent* modal_dialog_event)
+ : RenderWidgetHost(instance->GetProcess(), routing_id),
+ instance_(instance),
+ enable_dom_ui_bindings_(false),
+ enable_external_host_bindings_(false),
+ delegate_(delegate),
+ renderer_initialized_(false),
+ waiting_for_drag_context_response_(false),
+ debugger_attached_(false),
+ modal_dialog_count_(0),
+ navigations_suspended_(false),
+ suspended_nav_message_(NULL),
+ run_modal_reply_msg_(NULL),
+ has_unload_listener_(false),
+ is_waiting_for_unload_ack_(false),
+ are_javascript_messages_suppressed_(false) {
+ DCHECK(instance_);
+ DCHECK(delegate_);
+ if (modal_dialog_event == NULL)
+ modal_dialog_event = new base::WaitableEvent(true, false);
+
+ modal_dialog_event_.reset(modal_dialog_event);
+#ifdef CHROME_PERSONALIZATION
+ personalization_ = Personalization::CreateHostPersonalization(this);
+#endif
+}
+
+RenderViewHost::~RenderViewHost() {
+ OnDebugDisconnect();
+
+#ifdef CHROME_PERSONALIZATION
+ Personalization::CleanupHostPersonalization(personalization_);
+ personalization_ = NULL;
+#endif
+
+ // Be sure to clean up any leftover state from cross-site requests.
+ Singleton<CrossSiteRequestManager>()->SetHasPendingCrossSiteRequest(
+ process()->host_id(), routing_id_, false);
+}
+
+bool RenderViewHost::CreateRenderView() {
+ DCHECK(!IsRenderViewLive()) << "Creating view twice";
+
+ // The process may (if we're sharing a process with another host that already
+ // initialized it) or may not (we have our own process or the old process
+ // crashed) have been initialized. Calling Init multiple times will be
+ // ignored, so this is safe.
+ if (!process_->Init())
+ return false;
+ DCHECK(process_->channel());
+ DCHECK(process_->profile());
+
+ renderer_initialized_ = true;
+
+ HANDLE modal_dialog_event;
+ HANDLE renderer_process_handle = process()->process().handle();
+ if (renderer_process_handle == NULL)
+ renderer_process_handle = GetCurrentProcess();
+
+ BOOL result = DuplicateHandle(GetCurrentProcess(),
+ modal_dialog_event_->handle(),
+ renderer_process_handle,
+ &modal_dialog_event,
+ SYNCHRONIZE,
+ FALSE,
+ 0);
+ DCHECK(result) << "Couldn't duplicate the modal dialog handle for the renderer.";
+
+ DCHECK(view_);
+ Send(new ViewMsg_New(view_->GetPluginHWND(),
+ modal_dialog_event,
+ delegate_->GetWebkitPrefs(),
+ routing_id_));
+
+ // Set the alternate error page, which is profile specific, in the renderer.
+ GURL url = delegate_->GetAlternateErrorPageURL();
+ SetAlternateErrorPageURL(url);
+
+ // If it's enabled, tell the renderer to set up the Javascript bindings for
+ // sending messages back to the browser.
+ Send(new ViewMsg_AllowBindings(
+ routing_id_, enable_dom_ui_bindings_, enable_external_host_bindings_));
+
+ // Let our delegate know that we created a RenderView.
+ delegate_->RendererCreated(this);
+
+ return true;
+}
+
+bool RenderViewHost::IsRenderViewLive() const {
+ return process_->channel() && renderer_initialized_;
+}
+
+void RenderViewHost::Init() {
+ RenderWidgetHost::Init();
+ renderer_initialized_ = true;
+}
+
+void RenderViewHost::NavigateToEntry(const NavigationEntry& entry,
+ bool is_reload) {
+ ViewMsg_Navigate_Params params;
+ MakeNavigateParams(entry, is_reload, &params);
+
+ RendererSecurityPolicy::GetInstance()->GrantRequestURL(
+ process()->host_id(), params.url);
+
+ DoNavigate(new ViewMsg_Navigate(routing_id_, params));
+}
+
+void RenderViewHost::NavigateToURL(const GURL& url) {
+ ViewMsg_Navigate_Params params;
+ params.page_id = -1;
+ params.url = url;
+ params.transition = PageTransition::LINK;
+ params.reload = false;
+
+ RendererSecurityPolicy::GetInstance()->GrantRequestURL(
+ process()->host_id(), params.url);
+
+ DoNavigate(new ViewMsg_Navigate(routing_id_, params));
+}
+
+void RenderViewHost::DoNavigate(ViewMsg_Navigate* nav_message) {
+ // Only send the message if we aren't suspended at the start of a cross-site
+ // request.
+ if (navigations_suspended_) {
+ // Shouldn't be possible to have a second navigation while suspended, since
+ // navigations will only be suspended during a cross-site request. If a
+ // second navigation occurs, WebContents will cancel this pending RVH
+ // create a new pending RVH.
+ DCHECK(!suspended_nav_message_.get());
+ suspended_nav_message_.reset(nav_message);
+ } else {
+ Send(nav_message);
+ }
+}
+
+void RenderViewHost::LoadAlternateHTMLString(const std::string& html_text,
+ bool new_navigation,
+ const GURL& display_url,
+ const std::string& security_info) {
+ Send(new ViewMsg_LoadAlternateHTMLText(routing_id_, html_text,
+ new_navigation, display_url,
+ security_info));
+}
+
+void RenderViewHost::SetNavigationsSuspended(bool suspend) {
+ DCHECK(navigations_suspended_ != suspend);
+ navigations_suspended_ = suspend;
+ if (!suspend && suspended_nav_message_.get()) {
+ // Resume navigation
+ Send(suspended_nav_message_.release());
+ }
+}
+
+void RenderViewHost::FirePageBeforeUnload() {
+ if (!IsRenderViewLive()) {
+ // This RenderViewHost doesn't have a live renderer, so just skip running
+ // the onbeforeunload handler.
+ OnMsgShouldCloseACK(true);
+ return;
+ }
+
+ // This may be called more than once (if the user clicks the tab close button
+ // several times, or if she clicks the tab close button than the browser close
+ // button), so this test makes sure we only send the message once.
+ if (!is_waiting_for_unload_ack_) {
+ // Start the hang monitor in case the renderer hangs in the beforeunload
+ // handler.
+ is_waiting_for_unload_ack_ = true;
+ StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
+ Send(new ViewMsg_ShouldClose(routing_id_));
+ }
+}
+
+void RenderViewHost::FirePageUnload() {
+ ClosePage(site_instance()->process_host_id(),
+ routing_id());
+}
+
+// static
+void RenderViewHost::ClosePageIgnoringUnloadEvents(int render_process_host_id,
+ int request_id) {
+ RenderViewHost* rvh = RenderViewHost::FromID(render_process_host_id,
+ request_id);
+ if (!rvh)
+ return;
+
+ rvh->StopHangMonitorTimeout();
+ rvh->is_waiting_for_unload_ack_ = false;
+
+ rvh->UnloadListenerHasFired();
+ rvh->delegate()->Close(rvh);
+}
+
+void RenderViewHost::ClosePage(int new_render_process_host_id,
+ int new_request_id) {
+ // Start the hang monitor in case the renderer hangs in the unload handler.
+ is_waiting_for_unload_ack_ = true;
+ StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
+
+ if (IsRenderViewLive()) {
+ Send(new ViewMsg_ClosePage(routing_id_,
+ new_render_process_host_id,
+ new_request_id));
+ } else {
+ // This RenderViewHost doesn't have a live renderer, so just skip closing
+ // the page. We must notify the ResourceDispatcherHost on the IO thread,
+ // which we will do through the RenderProcessHost's widget helper.
+ process()->CrossSiteClosePageACK(new_render_process_host_id,
+ new_request_id);
+ }
+}
+
+void RenderViewHost::SetHasPendingCrossSiteRequest(bool has_pending_request,
+ int request_id) {
+ Singleton<CrossSiteRequestManager>()->SetHasPendingCrossSiteRequest(
+ process()->host_id(), routing_id_, has_pending_request);
+ pending_request_id_ = request_id;
+}
+
+int RenderViewHost::GetPendingRequestId() {
+ return pending_request_id_;
+}
+
+void RenderViewHost::OnCrossSiteResponse(int new_render_process_host_id,
+ int new_request_id) {
+ delegate_->OnCrossSiteResponse(new_render_process_host_id, new_request_id);
+}
+
+void RenderViewHost::Stop() {
+ Send(new ViewMsg_Stop(routing_id_));
+}
+
+bool RenderViewHost::GetPrintedPagesCount(const ViewMsg_Print_Params& params) {
+ return Send(new ViewMsg_GetPrintedPagesCount(routing_id_, params));
+}
+
+bool RenderViewHost::PrintPages(const ViewMsg_PrintPages_Params& params) {
+ return Send(new ViewMsg_PrintPages(routing_id_, params));
+}
+
+void RenderViewHost::StartFinding(int request_id,
+ const std::wstring& search_string,
+ bool forward,
+ bool match_case,
+ bool find_next) {
+ if (search_string.empty())
+ return;
+
+ FindInPageRequest request;
+ request.request_id = request_id;
+ request.search_string = search_string;
+ request.forward = forward;
+ request.match_case = match_case;
+ request.find_next = find_next;
+ Send(new ViewMsg_Find(routing_id_, request));
+
+ // This call is asynchronous and returns immediately.
+ // The result of the search is sent as a notification message by the renderer.
+}
+
+void RenderViewHost::StopFinding(bool clear_selection) {
+ Send(new ViewMsg_StopFinding(routing_id_, clear_selection));
+}
+
+void RenderViewHost::Zoom(PageZoom::Function function) {
+ Send(new ViewMsg_Zoom(routing_id_, function));
+}
+
+void RenderViewHost::SetPageEncoding(const std::wstring& encoding_name) {
+ Send(new ViewMsg_SetPageEncoding(routing_id_, encoding_name));
+}
+
+void RenderViewHost::SetAlternateErrorPageURL(const GURL& url) {
+ Send(new ViewMsg_SetAltErrorPageURL(routing_id_, url));
+}
+
+void RenderViewHost::FillForm(const FormData& form_data) {
+ Send(new ViewMsg_FormFill(routing_id_, form_data));
+}
+
+void RenderViewHost::FillPasswordForm(
+ const PasswordFormDomManager::FillData& form_data) {
+ Send(new ViewMsg_FillPasswordForm(routing_id_, form_data));
+}
+
+void RenderViewHost::DragTargetDragEnter(const WebDropData& drop_data,
+ const gfx::Point& client_pt, const gfx::Point& screen_pt) {
+ // Grant the renderer the ability to load the drop_data.
+ RendererSecurityPolicy* policy = RendererSecurityPolicy::GetInstance();
+ policy->GrantRequestURL(process()->host_id(), drop_data.url);
+ for (std::vector<std::wstring>::const_iterator iter(drop_data.filenames.begin());
+ iter != drop_data.filenames.end(); ++iter) {
+ policy->GrantRequestURL(process()->host_id(),
+ net::FilePathToFileURL(*iter));
+ policy->GrantUploadFile(process()->host_id(), *iter);
+ }
+ Send(new ViewMsg_DragTargetDragEnter(routing_id_, drop_data, client_pt,
+ screen_pt));
+}
+
+void RenderViewHost::DragTargetDragOver(
+ const gfx::Point& client_pt, const gfx::Point& screen_pt) {
+ Send(new ViewMsg_DragTargetDragOver(routing_id_, client_pt, screen_pt));
+}
+
+void RenderViewHost::DragTargetDragLeave() {
+ Send(new ViewMsg_DragTargetDragLeave(routing_id_));
+}
+
+void RenderViewHost::DragTargetDrop(
+ const gfx::Point& client_pt, const gfx::Point& screen_pt) {
+ Send(new ViewMsg_DragTargetDrop(routing_id_, client_pt, screen_pt));
+}
+
+void RenderViewHost::ReservePageIDRange(int size) {
+ Send(new ViewMsg_ReservePageIDRange(routing_id_, size));
+}
+
+void RenderViewHost::ExecuteJavascriptInWebFrame(
+ const std::wstring& frame_xpath, const std::wstring& jscript) {
+ Send(new ViewMsg_ScriptEvalRequest(routing_id_, frame_xpath, jscript));
+}
+
+void RenderViewHost::AddMessageToConsole(
+ const std::wstring& frame_xpath, const std::wstring& msg,
+ ConsoleMessageLevel level) {
+ Send(new ViewMsg_AddMessageToConsole(routing_id_, frame_xpath, msg, level));
+}
+
+void RenderViewHost::DebugCommand(const std::wstring& cmd) {
+ Send(new ViewMsg_DebugCommand(routing_id_, cmd));
+}
+
+void RenderViewHost::DebugAttach() {
+ if (!debugger_attached_)
+ Send(new ViewMsg_DebugAttach(routing_id_));
+}
+
+void RenderViewHost::DebugDetach() {
+ if (debugger_attached_) {
+ Send(new ViewMsg_DebugDetach(routing_id_));
+ debugger_attached_ = false;
+ }
+}
+
+void RenderViewHost::DebugBreak(bool force) {
+ if (debugger_attached_)
+ Send(new ViewMsg_DebugBreak(routing_id_, force));
+}
+
+void RenderViewHost::Undo() {
+ Send(new ViewMsg_Undo(routing_id_));
+}
+
+void RenderViewHost::Redo() {
+ Send(new ViewMsg_Redo(routing_id_));
+}
+
+void RenderViewHost::Cut() {
+ Send(new ViewMsg_Cut(routing_id_));
+}
+
+void RenderViewHost::Copy() {
+ Send(new ViewMsg_Copy(routing_id_));
+}
+
+void RenderViewHost::Paste() {
+ Send(new ViewMsg_Paste(routing_id_));
+}
+
+void RenderViewHost::Replace(const std::wstring& text_to_replace) {
+ Send(new ViewMsg_Replace(routing_id_, text_to_replace));
+}
+
+void RenderViewHost::ToggleSpellCheck() {
+ Send(new ViewMsg_ToggleSpellCheck(routing_id_));
+}
+
+void RenderViewHost::AddToDictionary(const std::wstring& word) {
+ process_->AddWord(word);
+}
+
+void RenderViewHost::Delete() {
+ Send(new ViewMsg_Delete(routing_id_));
+}
+
+void RenderViewHost::SelectAll() {
+ Send(new ViewMsg_SelectAll(routing_id_));
+}
+
+int RenderViewHost::DownloadImage(const GURL& url, int image_size) {
+ if (!url.is_valid()) {
+ NOTREACHED();
+ return 0;
+ }
+ static int next_id = 1;
+ int id = next_id++;
+ Send(new ViewMsg_DownloadImage(routing_id_, id, url, image_size));
+ return id;
+}
+
+void RenderViewHost::GetApplicationInfo(int32 page_id) {
+ Send(new ViewMsg_GetApplicationInfo(routing_id_, page_id));
+}
+
+void RenderViewHost::CaptureThumbnail() {
+ Send(new ViewMsg_CaptureThumbnail(routing_id_));
+}
+
+void RenderViewHost::JavaScriptMessageBoxClosed(IPC::Message* reply_msg,
+ bool success,
+ const std::wstring& prompt) {
+ if (is_waiting_for_unload_ack_) {
+ if (are_javascript_messages_suppressed_) {
+ delegate_->RendererUnresponsive(this, is_waiting_for_unload_ack_);
+ return;
+ }
+
+ StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
+ }
+
+ if (--modal_dialog_count_ == 0)
+ modal_dialog_event_->Reset();
+ ViewHostMsg_RunJavaScriptMessage::WriteReplyParams(reply_msg, success, prompt);
+ Send(reply_msg);
+}
+
+void RenderViewHost::ModalHTMLDialogClosed(IPC::Message* reply_msg,
+ const std::string& json_retval) {
+ if (is_waiting_for_unload_ack_)
+ StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
+
+ if (--modal_dialog_count_ == 0)
+ modal_dialog_event_->Reset();
+
+ ViewHostMsg_ShowModalHTMLDialog::WriteReplyParams(reply_msg, json_retval);
+ Send(reply_msg);
+}
+
+void RenderViewHost::CopyImageAt(int x, int y) {
+ Send(new ViewMsg_CopyImageAt(routing_id_, x, y));
+}
+
+void RenderViewHost::InspectElementAt(int x, int y) {
+ RendererSecurityPolicy::GetInstance()->GrantInspectElement(
+ process()->host_id());
+ Send(new ViewMsg_InspectElement(routing_id_, x, y));
+}
+
+void RenderViewHost::ShowJavaScriptConsole() {
+ RendererSecurityPolicy::GetInstance()->GrantInspectElement(
+ process()->host_id());
+
+ Send(new ViewMsg_ShowJavaScriptConsole(routing_id_));
+}
+
+void RenderViewHost::DragSourceEndedAt(
+ int client_x, int client_y, int screen_x, int screen_y) {
+ Send(new ViewMsg_DragSourceEndedOrMoved(
+ routing_id_, client_x, client_y, screen_x, screen_y, true));
+}
+
+void RenderViewHost::DragSourceMovedTo(
+ int client_x, int client_y, int screen_x, int screen_y) {
+ Send(new ViewMsg_DragSourceEndedOrMoved(
+ routing_id_, client_x, client_y, screen_x, screen_y, false));
+}
+
+void RenderViewHost::DragSourceSystemDragEnded() {
+ Send(new ViewMsg_DragSourceSystemDragEnded(routing_id_));
+}
+
+void RenderViewHost::AllowDomAutomationBindings() {
+ // Expose the binding that allows the DOM to send messages here.
+ Send(new ViewMsg_AllowDomAutomationBindings(routing_id_, true));
+}
+
+void RenderViewHost::AllowDOMUIBindings() {
+ DCHECK(!renderer_initialized_);
+ enable_dom_ui_bindings_ = true;
+ RendererSecurityPolicy::GetInstance()->GrantDOMUIBindings(process()->host_id());
+}
+
+void RenderViewHost::AllowExternalHostBindings() {
+ enable_external_host_bindings_ = true;
+}
+
+void RenderViewHost::SetDOMUIProperty(const std::string& name,
+ const std::string& value) {
+ DCHECK(enable_dom_ui_bindings_);
+ Send(new ViewMsg_SetDOMUIProperty(routing_id_, name, value));
+}
+
+// static
+void RenderViewHost::MakeNavigateParams(const NavigationEntry& entry,
+ bool reload,
+ ViewMsg_Navigate_Params* params) {
+ params->page_id = entry.page_id();
+ params->url = entry.url();
+ params->referrer = entry.referrer();
+ params->transition = entry.transition_type();
+ params->state = entry.content_state();
+ params->reload = reload;
+}
+
+bool RenderViewHost::CanBlur() const {
+ return delegate_->CanBlur();
+}
+
+void RenderViewHost::SetInitialFocus(bool reverse) {
+ Send(new ViewMsg_SetInitialFocus(routing_id_, reverse));
+}
+
+void RenderViewHost::UpdateWebPreferences(const WebPreferences& prefs) {
+ Send(new ViewMsg_UpdateWebPreferences(routing_id_, prefs));
+}
+
+void RenderViewHost::InstallMissingPlugin() {
+ Send(new ViewMsg_InstallMissingPlugin(routing_id_));
+}
+
+void RenderViewHost::FileSelected(const std::wstring& path) {
+ RendererSecurityPolicy::GetInstance()->GrantUploadFile(process()->host_id(),
+ path);
+ std::vector<std::wstring> files;
+ files.push_back(path);
+ Send(new ViewMsg_RunFileChooserResponse(routing_id_, files));
+}
+
+void RenderViewHost::MultiFilesSelected(
+ const std::vector<std::wstring>& files) {
+ for (std::vector<std::wstring>::const_iterator file = files.begin();
+ file != files.end(); ++file) {
+ RendererSecurityPolicy::GetInstance()->GrantUploadFile(
+ process()->host_id(), *file);
+ }
+ Send(new ViewMsg_RunFileChooserResponse(routing_id_, files));
+}
+
+void RenderViewHost::LoadStateChanged(const GURL& url,
+ net::LoadState load_state) {
+ delegate_->LoadStateChanged(url, load_state);
+}
+
+bool RenderViewHost::CanTerminate() const {
+ if (!delegate_->CanTerminate())
+ return false;
+
+ return has_unload_listener_;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// RenderViewHost, IPC message handlers:
+
+void RenderViewHost::OnMessageReceived(const IPC::Message& msg) {
+ if (msg.is_sync() && !msg.is_caller_pumping_messages()) {
+ NOTREACHED() << "Can't send sync messages to UI thread without pumping " \
+ "messages in the renderer or else deadlocks can occur if the page" \
+ "has windowed plugins!";
+ IPC::Message* reply = IPC::SyncMessage::GenerateReply(&msg);
+ reply->set_reply_error();
+ Send(reply);
+ return;
+ }
+
+ bool msg_is_ok = true;
+ IPC_BEGIN_MESSAGE_MAP_EX(RenderViewHost, msg, msg_is_ok)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWindowWithRoute, OnMsgCreateWindow)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWidgetWithRoute, OnMsgCreateWidget)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_ShowView, OnMsgShowView)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnMsgShowWidget)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_RunModal, OnMsgRunModal)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_RendererReady, OnMsgRendererReady)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_RendererGone, OnMsgRendererGone)
+ IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_FrameNavigate, OnMsgNavigate(msg))
+ IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateState, OnMsgUpdateState)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateTitle, OnMsgUpdateTitle)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateEncoding, OnMsgUpdateEncoding)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateTargetURL, OnMsgUpdateTargetURL)
+ IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_Thumbnail, OnMsgThumbnail(msg))
+ IPC_MESSAGE_HANDLER(ViewHostMsg_Close, OnMsgClose)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_RequestMove, OnMsgRequestMove)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DidStartLoading, OnMsgDidStartLoading)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DidStopLoading, OnMsgDidStopLoading)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DidLoadResourceFromMemoryCache,
+ OnMsgDidLoadResourceFromMemoryCache)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DidRedirectProvisionalLoad,
+ OnMsgDidRedirectProvisionalLoad)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DidStartProvisionalLoadForFrame,
+ OnMsgDidStartProvisionalLoadForFrame)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DidFailProvisionalLoadWithError,
+ OnMsgDidFailProvisionalLoadWithError)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_Find_Reply, OnMsgFindReply)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateFavIconURL, OnMsgUpdateFavIconURL)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DidDownloadImage, OnMsgDidDownloadImage)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_ContextMenu, OnMsgContextMenu)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_OpenURL, OnMsgOpenURL)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DomOperationResponse,
+ OnMsgDomOperationResponse)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DOMUISend,
+ OnMsgDOMUISend)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_ForwardMessageToExternalHost,
+ OnMsgForwardMessageToExternalHost)
+#ifdef CHROME_PERSONALIZATION
+ IPC_MESSAGE_HANDLER(ViewHostMsg_PersonalizationEvent,
+ OnPersonalizationEvent)
+#endif
+ IPC_MESSAGE_HANDLER(ViewHostMsg_GoToEntryAtOffset,
+ OnMsgGoToEntryAtOffset)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_SetTooltipText, OnMsgSetTooltipText)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_RunFileChooser, OnMsgRunFileChooser)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_RunJavaScriptMessage,
+ OnMsgRunJavaScriptMessage)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_RunBeforeUnloadConfirm,
+ OnMsgRunBeforeUnloadConfirm)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ShowModalHTMLDialog,
+ OnMsgShowModalHTMLDialog)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_PasswordFormsSeen, OnMsgPasswordFormsSeen)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_AutofillFormSubmitted,
+ OnMsgAutofillFormSubmitted)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_StartDragging, OnMsgStartDragging)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateDragCursor, OnUpdateDragCursor)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus, OnTakeFocus)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_PageHasOSDD, OnMsgPageHasOSDD)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_InspectElement_Reply,
+ OnMsgInspectElementReply)
+ IPC_MESSAGE_FORWARD(ViewHostMsg_DidGetPrintedPagesCount,
+ delegate_,
+ RenderViewHostDelegate::DidGetPrintedPagesCount)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DidPrintPage, DidPrintPage)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_AddMessageToConsole, OnAddMessageToConsole)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DebuggerOutput, OnDebuggerOutput);
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DidDebugAttach, DidDebugAttach);
+ IPC_MESSAGE_HANDLER(ViewHostMsg_UserMetricsRecordAction,
+ OnUserMetricsRecordAction)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_MissingPluginStatus, OnMissingPluginStatus);
+ IPC_MESSAGE_FORWARD(ViewHostMsg_CrashedPlugin, delegate_,
+ RenderViewHostDelegate::OnCrashedPlugin);
+ IPC_MESSAGE_HANDLER(ViewHostMsg_SendCurrentPageAllSavableResourceLinks,
+ OnReceivedSavableResourceLinksForCurrentPage);
+ IPC_MESSAGE_HANDLER(ViewHostMsg_SendSerializedHtmlData,
+ OnReceivedSerializedHtmlData);
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DidGetApplicationInfo,
+ OnDidGetApplicationInfo);
+ IPC_MESSAGE_FORWARD(ViewHostMsg_JSOutOfMemory, delegate_,
+ RenderViewHostDelegate::OnJSOutOfMemory);
+ IPC_MESSAGE_HANDLER(ViewHostMsg_ShouldClose_ACK, OnMsgShouldCloseACK);
+ IPC_MESSAGE_HANDLER(ViewHostMsg_UnloadListenerChanged,
+ OnUnloadListenerChanged);
+ IPC_MESSAGE_HANDLER(ViewHostMsg_QueryFormFieldAutofill,
+ OnQueryFormFieldAutofill)
+ // Have the super handle all other messages.
+ IPC_MESSAGE_UNHANDLED(RenderWidgetHost::OnMessageReceived(msg))
+ IPC_END_MESSAGE_MAP_EX()
+
+ if (!msg_is_ok) {
+ // The message had a handler, but its de-serialization failed.
+ // Kill the renderer.
+ process()->ReceivedBadMessage(msg.type());
+ }
+}
+
+void RenderViewHost::Shutdown() {
+ // If we are being run modally (see RunModal), then we need to cleanup.
+ if (run_modal_reply_msg_) {
+ if (--modal_dialog_count_ == 0)
+ modal_dialog_event_->Reset();
+ Send(run_modal_reply_msg_);
+ run_modal_reply_msg_ = NULL;
+ }
+ RenderWidgetHost::Shutdown();
+}
+
+void RenderViewHost::OnMsgCreateWindow(int route_id,
+ HANDLE modal_dialog_event) {
+ RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
+ if (view)
+ view->CreateNewWindow(route_id,
+ new base::WaitableEvent(modal_dialog_event));
+}
+
+void RenderViewHost::OnMsgCreateWidget(int route_id, bool activatable) {
+ RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
+ if (view)
+ view->CreateNewWidget(route_id, activatable);
+}
+
+void RenderViewHost::OnMsgShowView(int route_id,
+ WindowOpenDisposition disposition,
+ const gfx::Rect& initial_pos,
+ bool user_gesture) {
+ RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
+ if (view)
+ view->ShowCreatedWindow(route_id, disposition, initial_pos, user_gesture);
+}
+
+void RenderViewHost::OnMsgShowWidget(int route_id,
+ const gfx::Rect& initial_pos) {
+ RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
+ if (view)
+ view->ShowCreatedWidget(route_id, initial_pos);
+}
+
+void RenderViewHost::OnMsgRunModal(IPC::Message* reply_msg) {
+ DCHECK(!run_modal_reply_msg_);
+ if (modal_dialog_count_++ == 0)
+ modal_dialog_event_->Reset();
+ run_modal_reply_msg_ = reply_msg;
+
+ // TODO(darin): Bug 1107929: Need to inform our delegate to show this view in
+ // an app-modal fashion.
+}
+
+void RenderViewHost::OnMsgRendererReady() {
+ WasResized();
+ delegate_->RendererReady(this);
+}
+
+void RenderViewHost::OnMsgRendererGone() {
+ // Must reset these to ensure that mouse move events work with a new renderer.
+ mouse_move_pending_ = false;
+ next_mouse_move_.reset();
+
+ // Clearing this flag causes us to re-create the renderer when recovering
+ // from a crashed renderer.
+ renderer_initialized_ = false;
+
+ // Reset some fields in preparation for recovering from a crash.
+ resize_ack_pending_ = false;
+ current_size_ = gfx::Size();
+ is_hidden_ = false;
+
+ RendererExited();
+
+ if (view_) {
+ view_->RendererGone();
+ view_ = NULL; // The View should be deleted by RendererGone.
+ }
+ delegate_->RendererGone(this);
+ OnDebugDisconnect();
+}
+
+// Called when the renderer navigates. For every frame loaded, we'll get this
+// notification containing parameters identifying the navigation.
+//
+// Subframes are identified by the page transition type. For subframes loaded
+// as part of a wider page load, the page_id will be the same as for the top
+// level frame. If the user explicitly requests a subframe navigation, we will
+// get a new page_id because we need to create a new navigation entry for that
+// action.
+void RenderViewHost::OnMsgNavigate(const IPC::Message& msg) {
+ // Read the parameters out of the IPC message directly to avoid making another
+ // copy when we filter the URLs.
+ void* iter = NULL;
+ ViewHostMsg_FrameNavigate_Params validated_params;
+ if (!IPC::ParamTraits<ViewHostMsg_FrameNavigate_Params>::
+ Read(&msg, &iter, &validated_params))
+ return;
+
+ const int renderer_id = process()->host_id();
+ RendererSecurityPolicy* policy = RendererSecurityPolicy::GetInstance();
+ // Without this check, an evil renderer can trick the browser into creating
+ // a navigation entry for a banned URL. If the user clicks the back button
+ // followed by the forward button (or clicks reload, or round-trips through
+ // session restore, etc), we'll think that the browser commanded the
+ // renderer to load the URL and grant the renderer the privileges to request
+ // the URL. To prevent this attack, we block the renderer from inserting
+ // banned URLs into the navigation controller in the first place.
+ FilterURL(policy, renderer_id, &validated_params.url);
+ FilterURL(policy, renderer_id, &validated_params.referrer);
+ for (std::vector<GURL>::iterator it(validated_params.redirects.begin());
+ it != validated_params.redirects.end(); ++it) {
+ FilterURL(policy, renderer_id, &(*it));
+ }
+ FilterURL(policy, renderer_id, &validated_params.searchable_form_url);
+ FilterURL(policy, renderer_id, &validated_params.password_form.origin);
+ FilterURL(policy, renderer_id, &validated_params.password_form.action);
+
+ delegate_->DidNavigate(this, validated_params);
+
+ UpdateBackForwardListCount();
+}
+
+void RenderViewHost::OnMsgUpdateState(int32 page_id,
+ const std::string& state) {
+ delegate_->UpdateState(this, page_id, state);
+}
+
+void RenderViewHost::OnMsgUpdateTitle(int32 page_id,
+ const std::wstring& title) {
+ delegate_->UpdateTitle(this, page_id, title);
+}
+
+void RenderViewHost::OnMsgUpdateEncoding(const std::wstring& encoding_name) {
+ delegate_->UpdateEncoding(this, encoding_name);
+}
+
+void RenderViewHost::OnMsgUpdateTargetURL(int32 page_id,
+ const GURL& url) {
+ delegate_->UpdateTargetURL(page_id, url);
+
+ // Send a notification back to the renderer that we are ready to
+ // receive more target urls.
+ Send(new ViewMsg_UpdateTargetURL_ACK(routing_id_));
+}
+
+void RenderViewHost::OnMsgThumbnail(const IPC::Message& msg) {
+ // crack the message
+ void* iter = NULL;
+ GURL url;
+ if (!IPC::ParamTraits<GURL>::Read(&msg, &iter, &url))
+ return;
+
+ ThumbnailScore score;
+ if (!IPC::ParamTraits<ThumbnailScore>::Read(&msg, &iter, &score))
+ return;
+
+ // thumbnail data
+ SkBitmap bitmap;
+ if (!IPC::ParamTraits<SkBitmap>::Read(&msg, &iter, &bitmap))
+ return;
+
+ delegate_->UpdateThumbnail(url, bitmap, score);
+}
+
+void RenderViewHost::OnMsgClose() {
+ delegate_->Close(this);
+}
+
+void RenderViewHost::OnMsgRequestMove(const gfx::Rect& pos) {
+ delegate_->RequestMove(pos);
+}
+
+void RenderViewHost::OnMsgDidRedirectProvisionalLoad(int32 page_id,
+ const GURL& source_url,
+ const GURL& target_url) {
+ delegate_->DidRedirectProvisionalLoad(page_id, source_url, target_url);
+}
+
+void RenderViewHost::OnMsgDidStartLoading(int32 page_id) {
+ delegate_->DidStartLoading(this, page_id);
+
+ if (view_) {
+ view_->UpdateCursorIfOverSelf();
+ }
+}
+
+void RenderViewHost::OnMsgDidStopLoading(int32 page_id) {
+ delegate_->DidStopLoading(this, page_id);
+
+ if (view_) {
+ view_->UpdateCursorIfOverSelf();
+ }
+}
+
+void RenderViewHost::OnMsgDidLoadResourceFromMemoryCache(
+ const GURL& url,
+ const std::string& security_info) {
+ delegate_->DidLoadResourceFromMemoryCache(url, security_info);
+}
+
+void RenderViewHost::OnMsgDidStartProvisionalLoadForFrame(bool is_main_frame,
+ const GURL& url) {
+ GURL validated_url(url);
+ FilterURL(RendererSecurityPolicy::GetInstance(),
+ process()->host_id(), &validated_url);
+
+ delegate_->DidStartProvisionalLoadForFrame(this, is_main_frame, validated_url);
+}
+
+void RenderViewHost::OnMsgDidFailProvisionalLoadWithError(
+ bool is_main_frame,
+ int error_code,
+ const GURL& url,
+ bool showing_repost_interstitial) {
+ GURL validated_url(url);
+ FilterURL(RendererSecurityPolicy::GetInstance(),
+ process()->host_id(), &validated_url);
+
+ delegate_->DidFailProvisionalLoadWithError(this, is_main_frame,
+ error_code, validated_url,
+ showing_repost_interstitial);
+}
+
+void RenderViewHost::OnMsgFindReply(int request_id,
+ int number_of_matches,
+ const gfx::Rect& selection_rect,
+ int active_match_ordinal,
+ bool final_update) {
+ RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
+ if (!view)
+ return;
+ view->OnFindReply(request_id, number_of_matches, selection_rect,
+ active_match_ordinal, final_update);
+
+ // Send a notification to the renderer that we are ready to receive more
+ // results from the scoping effort of the Find operation. The FindInPage
+ // scoping is asynchronous and periodically sends results back up to the
+ // browser using IPC. In an effort to not spam the browser we have the
+ // browser send an ACK for each FindReply message and have the renderer
+ // queue up the latest status message while waiting for this ACK.
+ Send(new ViewMsg_FindReplyACK(routing_id_));
+}
+
+void RenderViewHost::OnMsgUpdateFavIconURL(int32 page_id,
+ const GURL& icon_url) {
+ delegate_->UpdateFavIconURL(this, page_id, icon_url);
+}
+
+void RenderViewHost::OnMsgDidDownloadImage(
+ int id,
+ const GURL& image_url,
+ bool errored,
+ const SkBitmap& image) {
+ delegate_->DidDownloadImage(this, id, image_url, errored, image);
+}
+
+void RenderViewHost::OnMsgContextMenu(
+ const ViewHostMsg_ContextMenu_Params& params) {
+ RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
+ if (!view)
+ return;
+
+ // Validate the URLs in |params|. If the renderer can't request the URLs
+ // directly, don't show them in the context menu.
+ ViewHostMsg_ContextMenu_Params validated_params(params);
+ const int renderer_id = process()->host_id();
+ RendererSecurityPolicy* policy = RendererSecurityPolicy::GetInstance();
+
+ FilterURL(policy, renderer_id, &validated_params.link_url);
+ FilterURL(policy, renderer_id, &validated_params.image_url);
+ FilterURL(policy, renderer_id, &validated_params.page_url);
+ FilterURL(policy, renderer_id, &validated_params.frame_url);
+
+ view->ShowContextMenu(validated_params);
+}
+
+void RenderViewHost::OnMsgOpenURL(const GURL& url,
+ const GURL& referrer,
+ WindowOpenDisposition disposition) {
+ GURL validated_url(url);
+ FilterURL(RendererSecurityPolicy::GetInstance(),
+ process()->host_id(), &validated_url);
+
+ delegate_->RequestOpenURL(validated_url, referrer, disposition);
+}
+
+void RenderViewHost::OnMsgDomOperationResponse(
+ const std::string& json_string, int automation_id) {
+ delegate_->DomOperationResponse(json_string, automation_id);
+}
+
+void RenderViewHost::OnMsgDOMUISend(
+ const std::string& message, const std::string& content) {
+ if (!RendererSecurityPolicy::GetInstance()->
+ HasDOMUIBindings(process()->host_id())) {
+ NOTREACHED() << "Blocked unauthorized use of DOMUIBindings.";
+ return;
+ }
+ delegate_->ProcessDOMUIMessage(message, content);
+}
+
+void RenderViewHost::OnMsgForwardMessageToExternalHost(
+ const std::string& receiver,
+ const std::string& message) {
+ delegate_->ProcessExternalHostMessage(receiver, message);
+}
+
+#ifdef CHROME_PERSONALIZATION
+void RenderViewHost::OnPersonalizationEvent(const std::string& message,
+ const std::string& content) {
+ Personalization::HandlePersonalizationEvent(this, message, content);
+}
+#endif
+
+void RenderViewHost::DisassociateFromPopupCount() {
+ Send(new ViewMsg_DisassociateFromPopupCount(routing_id_));
+}
+
+void RenderViewHost::PopupNotificationVisibilityChanged(bool visible) {
+ Send(new ViewMsg_PopupNotificationVisiblityChanged(routing_id_, visible));
+}
+
+void RenderViewHost::OnMsgGoToEntryAtOffset(int offset) {
+ delegate_->GoToEntryAtOffset(offset);
+}
+
+void RenderViewHost::OnMsgSetTooltipText(const std::wstring& tooltip_text) {
+ if (view_) {
+ view_->SetTooltipText(tooltip_text);
+ }
+}
+
+void RenderViewHost::OnMsgRunFileChooser(bool multiple_files,
+ const std::wstring& title,
+ const std::wstring& default_file,
+ const std::wstring& filter) {
+ std::wstring real_filter = filter;
+ std::replace(real_filter.begin(), real_filter.end(), '|', '\0');
+ delegate_->RunFileChooser(multiple_files, title, default_file, real_filter);
+}
+
+void RenderViewHost::OnMsgRunJavaScriptMessage(
+ const std::wstring& message,
+ const std::wstring& default_prompt,
+ const int flags,
+ IPC::Message* reply_msg) {
+ StopHangMonitorTimeout();
+ if (modal_dialog_count_++ == 0)
+ modal_dialog_event_->Signal();
+ bool did_suppress_message = false;
+ delegate_->RunJavaScriptMessage(message, default_prompt, flags, reply_msg,
+ &are_javascript_messages_suppressed_);
+}
+
+void RenderViewHost::OnMsgRunBeforeUnloadConfirm(const std::wstring& message,
+ IPC::Message* reply_msg) {
+ StopHangMonitorTimeout();
+ if (modal_dialog_count_++ == 0)
+ modal_dialog_event_->Signal();
+ delegate_->RunBeforeUnloadConfirm(message, reply_msg);
+}
+
+void RenderViewHost::OnMsgShowModalHTMLDialog(
+ const GURL& url, int width, int height, const std::string& json_arguments,
+ IPC::Message* reply_msg) {
+ StopHangMonitorTimeout();
+ if (modal_dialog_count_++ == 0)
+ modal_dialog_event_->Signal();
+ delegate_->ShowModalHTMLDialog(url, width, height, json_arguments, reply_msg);
+}
+
+void RenderViewHost::OnMsgPasswordFormsSeen(
+ const std::vector<PasswordForm>& forms) {
+ delegate_->PasswordFormsSeen(forms);
+}
+
+void RenderViewHost::OnMsgAutofillFormSubmitted(
+ const AutofillForm& form) {
+ delegate_->AutofillFormSubmitted(form);
+}
+
+void RenderViewHost::OnMsgStartDragging(
+ const WebDropData& drop_data) {
+ RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
+ if (view)
+ view->StartDragging(drop_data);
+}
+
+void RenderViewHost::OnUpdateDragCursor(bool is_drop_target) {
+ RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
+ if (view)
+ view->UpdateDragCursor(is_drop_target);
+}
+
+void RenderViewHost::OnTakeFocus(bool reverse) {
+ RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
+ if (view)
+ view->TakeFocus(reverse);
+}
+
+void RenderViewHost::OnMsgPageHasOSDD(int32 page_id, const GURL& doc_url,
+ bool autodetected) {
+ delegate_->PageHasOSDD(this, page_id, doc_url, autodetected);
+}
+
+void RenderViewHost::OnMsgInspectElementReply(int num_resources) {
+ delegate_->InspectElementReply(num_resources);
+}
+
+void RenderViewHost::DidPrintPage(
+ const ViewHostMsg_DidPrintPage_Params& params) {
+ delegate_->DidPrintPage(params);
+}
+
+void RenderViewHost::OnAddMessageToConsole(const std::wstring& message,
+ int32 line_no,
+ const std::wstring& source_id) {
+ std::wstring msg = StringPrintf(L"\"%ls,\" source: %ls (%d)", message.c_str(),
+ source_id.c_str(), line_no);
+ logging::LogMessage("CONSOLE", 0).stream() << msg;
+ if (debugger_attached_)
+ g_browser_process->debugger_wrapper()->DebugMessage(msg);
+}
+
+void RenderViewHost::OnDebuggerOutput(const std::wstring& output) {
+ if (debugger_attached_)
+ g_browser_process->debugger_wrapper()->DebugMessage(output);
+}
+
+void RenderViewHost::DidDebugAttach() {
+ if (!debugger_attached_) {
+ debugger_attached_ = true;
+ g_browser_process->debugger_wrapper()->OnDebugAttach();
+ }
+}
+
+void RenderViewHost::OnUserMetricsRecordAction(const std::wstring& action) {
+ UserMetrics::RecordComputedAction(action.c_str(), process_->profile());
+}
+
+void RenderViewHost::UnhandledInputEvent(const WebInputEvent& event) {
+ RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
+ if (view) {
+ // TODO(brettw) why do we have to filter these types of events here. Can't
+ // the renderer just send us the ones we care abount, or maybe the view
+ // should be able to decide which ones it wants or not?
+ if ((event.type == WebInputEvent::KEY_DOWN) ||
+ (event.type == WebInputEvent::CHAR)) {
+ view->HandleKeyboardEvent(
+ static_cast<const WebKeyboardEvent&>(event));
+ }
+ }
+}
+
+void RenderViewHost::ForwardKeyboardEvent(const WebKeyboardEvent& key_event) {
+ if (key_event.type == WebKeyboardEvent::CHAR &&
+ (key_event.key_code == VK_RETURN || key_event.key_code == VK_SPACE)) {
+ delegate_->OnEnterOrSpace();
+ }
+ RenderWidgetHost::ForwardKeyboardEvent(key_event);
+}
+
+void RenderViewHost::OnMissingPluginStatus(int status) {
+ delegate_->OnMissingPluginStatus(status);
+}
+
+void RenderViewHost::UpdateBackForwardListCount() {
+ int back_list_count, forward_list_count;
+ delegate_->GetHistoryListCount(&back_list_count, &forward_list_count);
+ Send(new ViewMsg_UpdateBackForwardListCount(
+ routing_id_, back_list_count, forward_list_count));
+}
+
+void RenderViewHost::GetAllSavableResourceLinksForCurrentPage(
+ const GURL& page_url) {
+ Send(new ViewMsg_GetAllSavableResourceLinksForCurrentPage(routing_id_,
+ page_url));
+}
+
+void RenderViewHost::OnReceivedSavableResourceLinksForCurrentPage(
+ const std::vector<GURL>& resources_list,
+ const std::vector<GURL>& referrers_list,
+ const std::vector<GURL>& frames_list) {
+ RenderViewHostDelegate::Save* save_delegate = delegate_->GetSaveDelegate();
+ if (save_delegate) {
+ save_delegate->OnReceivedSavableResourceLinksForCurrentPage(
+ resources_list, referrers_list, frames_list);
+ }
+}
+
+void RenderViewHost::OnDidGetApplicationInfo(
+ int32 page_id,
+ const webkit_glue::WebApplicationInfo& info) {
+ delegate_->OnDidGetApplicationInfo(page_id, info);
+}
+
+void RenderViewHost::GetSerializedHtmlDataForCurrentPageWithLocalLinks(
+ const std::vector<std::wstring>& links,
+ const std::vector<std::wstring>& local_paths,
+ const std::wstring& local_directory_name) {
+ Send(new ViewMsg_GetSerializedHtmlDataForCurrentPageWithLocalLinks(
+ routing_id_, links, local_paths, local_directory_name));
+}
+
+void RenderViewHost::OnReceivedSerializedHtmlData(const GURL& frame_url,
+ const std::string& data,
+ int32 status) {
+ RenderViewHostDelegate::Save* save_delegate = delegate_->GetSaveDelegate();
+ if (save_delegate)
+ save_delegate->OnReceivedSerializedHtmlData(frame_url, data, status);
+}
+
+void RenderViewHost::OnMsgShouldCloseACK(bool proceed) {
+ StopHangMonitorTimeout();
+ DCHECK(is_waiting_for_unload_ack_);
+ is_waiting_for_unload_ack_ = false;
+ delegate_->ShouldClosePage(proceed);
+}
+
+void RenderViewHost::OnUnloadListenerChanged(bool has_listener) {
+ has_unload_listener_ = has_listener;
+}
+
+void RenderViewHost::OnQueryFormFieldAutofill(const std::wstring& field_name,
+ const std::wstring& user_text,
+ int64 node_id,
+ int request_id) {
+ delegate_->GetAutofillSuggestions(field_name, user_text, node_id, request_id);
+}
+
+void RenderViewHost::AutofillSuggestionsReturned(
+ const std::vector<std::wstring>& suggestions,
+ int64 node_id, int request_id, int default_suggestion_index) {
+ Send(new ViewMsg_AutofillSuggestions(routing_id_, node_id,
+ request_id, suggestions, -1));
+ // Default index -1 means no default suggestion.
+}
+
+void RenderViewHost::NotifyRendererUnresponsive() {
+ // If the debugger is attached, we're going to be unresponsive anytime it's
+ // stopped at a breakpoint.
+ if (!debugger_attached_) {
+ delegate_->RendererUnresponsive(this, is_waiting_for_unload_ack_);
+ }
+}
+
+void RenderViewHost::NotifyRendererResponsive() {
+ delegate_->RendererResponsive(this);
+}
+
+void RenderViewHost::OnDebugDisconnect() {
+ if (debugger_attached_) {
+ debugger_attached_ = false;
+ g_browser_process->debugger_wrapper()->OnDebugDisconnect();
+ }
+}
+
+#ifdef CHROME_PERSONALIZATION
+void RenderViewHost::RaisePersonalizationEvent(std::string event_name,
+ std::string event_arg) {
+ Send(new ViewMsg_PersonalizationEvent(routing_id_,
+ event_name,
+ event_arg));
+}
+#endif
+
+void RenderViewHost::ForwardMessageFromExternalHost(
+ const std::string& target, const std::string& message) {
+ Send(new ViewMsg_HandleMessageFromExternalHost(routing_id_, target, message));
+}