render_view_host_impl.cc revision 868fa2fe829687343ffae624259930155e16dbd8
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/browser/renderer_host/render_view_host_impl.h"
6
7#include <set>
8#include <string>
9#include <utility>
10#include <vector>
11
12#include "base/callback.h"
13#include "base/command_line.h"
14#include "base/i18n/rtl.h"
15#include "base/json/json_reader.h"
16#include "base/lazy_instance.h"
17#include "base/message_loop.h"
18#include "base/metrics/histogram.h"
19#include "base/stl_util.h"
20#include "base/strings/string_util.h"
21#include "base/strings/utf_string_conversions.h"
22#include "base/time.h"
23#include "base/values.h"
24#include "content/browser/child_process_security_policy_impl.h"
25#include "content/browser/cross_site_request_manager.h"
26#include "content/browser/dom_storage/session_storage_namespace_impl.h"
27#include "content/browser/gpu/gpu_surface_tracker.h"
28#include "content/browser/host_zoom_map_impl.h"
29#include "content/browser/renderer_host/dip_util.h"
30#include "content/browser/renderer_host/render_process_host_impl.h"
31#include "content/browser/renderer_host/render_view_host_delegate.h"
32#include "content/common/accessibility_messages.h"
33#include "content/common/browser_plugin/browser_plugin_messages.h"
34#include "content/common/desktop_notification_messages.h"
35#include "content/common/drag_messages.h"
36#include "content/common/input_messages.h"
37#include "content/common/inter_process_time_ticks_converter.h"
38#include "content/common/speech_recognition_messages.h"
39#include "content/common/swapped_out_messages.h"
40#include "content/common/view_messages.h"
41#include "content/port/browser/render_view_host_delegate_view.h"
42#include "content/port/browser/render_widget_host_view_port.h"
43#include "content/public/browser/browser_accessibility_state.h"
44#include "content/public/browser/browser_context.h"
45#include "content/public/browser/browser_message_filter.h"
46#include "content/public/browser/content_browser_client.h"
47#include "content/public/browser/dom_operation_notification_details.h"
48#include "content/public/browser/native_web_keyboard_event.h"
49#include "content/public/browser/notification_details.h"
50#include "content/public/browser/notification_service.h"
51#include "content/public/browser/notification_types.h"
52#include "content/public/browser/power_save_blocker.h"
53#include "content/public/browser/render_view_host_observer.h"
54#include "content/public/browser/user_metrics.h"
55#include "content/public/common/bindings_policy.h"
56#include "content/public/common/content_constants.h"
57#include "content/public/common/content_switches.h"
58#include "content/public/common/context_menu_params.h"
59#include "content/public/common/context_menu_source_type.h"
60#include "content/public/common/result_codes.h"
61#include "content/public/common/url_constants.h"
62#include "content/public/common/url_utils.h"
63#include "net/base/net_util.h"
64#include "net/url_request/url_request_context_getter.h"
65#include "third_party/skia/include/core/SkBitmap.h"
66#include "ui/gfx/image/image_skia.h"
67#include "ui/gfx/native_widget_types.h"
68#include "ui/shell_dialogs/selected_file_info.h"
69#include "ui/snapshot/snapshot.h"
70#include "webkit/browser/fileapi/isolated_context.h"
71#include "webkit/common/webdropdata.h"
72#include "webkit/glue/webkit_glue.h"
73
74#if defined(OS_WIN)
75#include "base/win/windows_version.h"
76#include "third_party/WebKit/Source/WebKit/chromium/public/win/WebScreenInfoFactory.h"
77#elif defined(OS_MACOSX)
78#include "content/browser/renderer_host/popup_menu_helper_mac.h"
79#elif defined(OS_ANDROID)
80#include "media/base/android/media_player_manager.h"
81#endif
82
83using base::TimeDelta;
84using WebKit::WebConsoleMessage;
85using WebKit::WebDragOperation;
86using WebKit::WebDragOperationNone;
87using WebKit::WebDragOperationsMask;
88using WebKit::WebInputEvent;
89using WebKit::WebMediaPlayerAction;
90using WebKit::WebPluginAction;
91
92namespace content {
93namespace {
94
95// Delay to wait on closing the WebContents for a beforeunload/unload handler to
96// fire.
97const int kUnloadTimeoutMS = 1000;
98
99// Translate a WebKit text direction into a base::i18n one.
100base::i18n::TextDirection WebTextDirectionToChromeTextDirection(
101    WebKit::WebTextDirection dir) {
102  switch (dir) {
103    case WebKit::WebTextDirectionLeftToRight:
104      return base::i18n::LEFT_TO_RIGHT;
105    case WebKit::WebTextDirectionRightToLeft:
106      return base::i18n::RIGHT_TO_LEFT;
107    default:
108      NOTREACHED();
109      return base::i18n::UNKNOWN_DIRECTION;
110  }
111}
112
113base::LazyInstance<std::vector<RenderViewHost::CreatedCallback> >
114g_created_callbacks = LAZY_INSTANCE_INITIALIZER;
115
116}  // namespace
117
118///////////////////////////////////////////////////////////////////////////////
119// RenderViewHost, public:
120
121// static
122RenderViewHost* RenderViewHost::FromID(int render_process_id,
123                                       int render_view_id) {
124  RenderProcessHost* process = RenderProcessHost::FromID(render_process_id);
125  if (!process)
126    return NULL;
127  RenderWidgetHost* widget = process->GetRenderWidgetHostByID(render_view_id);
128  if (!widget || !widget->IsRenderView())
129    return NULL;
130  return static_cast<RenderViewHostImpl*>(RenderWidgetHostImpl::From(widget));
131}
132
133// static
134RenderViewHost* RenderViewHost::From(RenderWidgetHost* rwh) {
135  DCHECK(rwh->IsRenderView());
136  return static_cast<RenderViewHostImpl*>(RenderWidgetHostImpl::From(rwh));
137}
138
139// static
140void RenderViewHost::FilterURL(const RenderProcessHost* process,
141                               bool empty_allowed,
142                               GURL* url) {
143  RenderViewHostImpl::FilterURL(ChildProcessSecurityPolicyImpl::GetInstance(),
144                                process, empty_allowed, url);
145}
146
147///////////////////////////////////////////////////////////////////////////////
148// RenderViewHostImpl, public:
149
150// static
151RenderViewHostImpl* RenderViewHostImpl::FromID(int render_process_id,
152                                               int render_view_id) {
153  return static_cast<RenderViewHostImpl*>(
154      RenderViewHost::FromID(render_process_id, render_view_id));
155}
156
157RenderViewHostImpl::RenderViewHostImpl(
158    SiteInstance* instance,
159    RenderViewHostDelegate* delegate,
160    RenderWidgetHostDelegate* widget_delegate,
161    int routing_id,
162    int main_frame_routing_id,
163    bool swapped_out,
164    SessionStorageNamespace* session_storage)
165    : RenderWidgetHostImpl(widget_delegate, instance->GetProcess(), routing_id),
166      delegate_(delegate),
167      instance_(static_cast<SiteInstanceImpl*>(instance)),
168      waiting_for_drag_context_response_(false),
169      enabled_bindings_(0),
170      pending_request_id_(-1),
171      navigations_suspended_(false),
172      suspended_nav_params_(NULL),
173      has_accessed_initial_document_(false),
174      is_swapped_out_(swapped_out),
175      is_subframe_(false),
176      main_frame_id_(-1),
177      run_modal_reply_msg_(NULL),
178      run_modal_opener_id_(MSG_ROUTING_NONE),
179      is_waiting_for_beforeunload_ack_(false),
180      is_waiting_for_unload_ack_(false),
181      has_timed_out_on_unload_(false),
182      unload_ack_is_for_cross_site_transition_(false),
183      are_javascript_messages_suppressed_(false),
184      accessibility_layout_callback_(base::Bind(&base::DoNothing)),
185      accessibility_load_callback_(base::Bind(&base::DoNothing)),
186      accessibility_other_callback_(base::Bind(&base::DoNothing)),
187      sudden_termination_allowed_(false),
188      session_storage_namespace_(
189          static_cast<SessionStorageNamespaceImpl*>(session_storage)),
190      save_accessibility_tree_for_testing_(false),
191      render_view_termination_status_(base::TERMINATION_STATUS_STILL_RUNNING) {
192  DCHECK(session_storage_namespace_.get());
193  DCHECK(instance_.get());
194  CHECK(delegate_);  // http://crbug.com/82827
195
196  if (main_frame_routing_id == MSG_ROUTING_NONE)
197    main_frame_routing_id = GetProcess()->GetNextRoutingID();
198
199  main_render_frame_host_.reset(
200      new RenderFrameHostImpl(this, main_frame_routing_id, is_swapped_out_));
201
202  GetProcess()->EnableSendQueue();
203
204  for (size_t i = 0; i < g_created_callbacks.Get().size(); i++)
205    g_created_callbacks.Get().at(i).Run(this);
206
207#if defined(OS_ANDROID)
208  media_player_manager_ = media::MediaPlayerManager::Create(this);
209#endif
210}
211
212RenderViewHostImpl::~RenderViewHostImpl() {
213  FOR_EACH_OBSERVER(
214      RenderViewHostObserver, observers_, RenderViewHostDestruction());
215
216  ClearPowerSaveBlockers();
217
218  GetDelegate()->RenderViewDeleted(this);
219
220  // Be sure to clean up any leftover state from cross-site requests.
221  CrossSiteRequestManager::GetInstance()->SetHasPendingCrossSiteRequest(
222      GetProcess()->GetID(), GetRoutingID(), false);
223}
224
225RenderViewHostDelegate* RenderViewHostImpl::GetDelegate() const {
226  return delegate_;
227}
228
229SiteInstance* RenderViewHostImpl::GetSiteInstance() const {
230  return instance_.get();
231}
232
233bool RenderViewHostImpl::CreateRenderView(
234    const string16& frame_name,
235    int opener_route_id,
236    int32 max_page_id) {
237  DCHECK(!IsRenderViewLive()) << "Creating view twice";
238
239  // The process may (if we're sharing a process with another host that already
240  // initialized it) or may not (we have our own process or the old process
241  // crashed) have been initialized. Calling Init multiple times will be
242  // ignored, so this is safe.
243  if (!GetProcess()->Init())
244    return false;
245  DCHECK(GetProcess()->HasConnection());
246  DCHECK(GetProcess()->GetBrowserContext());
247
248  renderer_initialized_ = true;
249
250  GpuSurfaceTracker::Get()->SetSurfaceHandle(
251      surface_id(), GetCompositingSurface());
252
253  // Ensure the RenderView starts with a next_page_id larger than any existing
254  // page ID it might be asked to render.
255  int32 next_page_id = 1;
256  if (max_page_id > -1)
257    next_page_id = max_page_id + 1;
258
259  ViewMsg_New_Params params;
260  params.renderer_preferences =
261      delegate_->GetRendererPrefs(GetProcess()->GetBrowserContext());
262  params.web_preferences = delegate_->GetWebkitPrefs();
263  params.view_id = GetRoutingID();
264  params.main_frame_routing_id = main_render_frame_host_->routing_id();
265  params.surface_id = surface_id();
266  params.session_storage_namespace_id = session_storage_namespace_->id();
267  params.frame_name = frame_name;
268  // Ensure the RenderView sets its opener correctly.
269  params.opener_route_id = opener_route_id;
270  params.swapped_out = is_swapped_out_;
271  params.next_page_id = next_page_id;
272  GetWebScreenInfo(&params.screen_info);
273  params.accessibility_mode = accessibility_mode();
274  params.allow_partial_swap = !GetProcess()->IsGuest();
275
276  Send(new ViewMsg_New(params));
277
278  // If it's enabled, tell the renderer to set up the Javascript bindings for
279  // sending messages back to the browser.
280  if (GetProcess()->IsGuest())
281    DCHECK_EQ(0, enabled_bindings_);
282  Send(new ViewMsg_AllowBindings(GetRoutingID(), enabled_bindings_));
283  // Let our delegate know that we created a RenderView.
284  delegate_->RenderViewCreated(this);
285
286  FOR_EACH_OBSERVER(
287      RenderViewHostObserver, observers_, RenderViewHostInitialized());
288
289  return true;
290}
291
292bool RenderViewHostImpl::IsRenderViewLive() const {
293  return GetProcess()->HasConnection() && renderer_initialized_;
294}
295
296bool RenderViewHostImpl::IsSubframe() const {
297  return is_subframe_;
298}
299
300void RenderViewHostImpl::SyncRendererPrefs() {
301  Send(new ViewMsg_SetRendererPrefs(GetRoutingID(),
302                                    delegate_->GetRendererPrefs(
303                                        GetProcess()->GetBrowserContext())));
304}
305
306void RenderViewHostImpl::Navigate(const ViewMsg_Navigate_Params& params) {
307  // Browser plugin guests are not allowed to navigate outside web-safe schemes,
308  // so do not grant them the ability to request additional URLs.
309  if (!GetProcess()->IsGuest()) {
310    ChildProcessSecurityPolicyImpl::GetInstance()->GrantRequestURL(
311        GetProcess()->GetID(), params.url);
312    if (params.url.SchemeIs(chrome::kDataScheme) &&
313        params.base_url_for_data_url.SchemeIs(chrome::kFileScheme)) {
314      // If 'data:' is used, and we have a 'file:' base url, grant access to
315      // local files.
316      ChildProcessSecurityPolicyImpl::GetInstance()->GrantRequestURL(
317          GetProcess()->GetID(), params.base_url_for_data_url);
318    }
319  }
320
321  // Only send the message if we aren't suspended at the start of a cross-site
322  // request.
323  if (navigations_suspended_) {
324    // Shouldn't be possible to have a second navigation while suspended, since
325    // navigations will only be suspended during a cross-site request.  If a
326    // second navigation occurs, WebContentsImpl will cancel this pending RVH
327    // create a new pending RVH.
328    DCHECK(!suspended_nav_params_.get());
329    suspended_nav_params_.reset(new ViewMsg_Navigate_Params(params));
330  } else {
331    // Get back to a clean state, in case we start a new navigation without
332    // completing a RVH swap or unload handler.
333    SetSwappedOut(false);
334
335    Send(new ViewMsg_Navigate(GetRoutingID(), params));
336  }
337
338  // Force the throbber to start. We do this because WebKit's "started
339  // loading" message will be received asynchronously from the UI of the
340  // browser. But we want to keep the throbber in sync with what's happening
341  // in the UI. For example, we want to start throbbing immediately when the
342  // user naivgates even if the renderer is delayed. There is also an issue
343  // with the throbber starting because the WebUI (which controls whether the
344  // favicon is displayed) happens synchronously. If the start loading
345  // messages was asynchronous, then the default favicon would flash in.
346  //
347  // WebKit doesn't send throb notifications for JavaScript URLs, so we
348  // don't want to either.
349  if (!params.url.SchemeIs(chrome::kJavaScriptScheme))
350    delegate_->DidStartLoading(this);
351
352  FOR_EACH_OBSERVER(RenderViewHostObserver, observers_, Navigate(params.url));
353}
354
355void RenderViewHostImpl::NavigateToURL(const GURL& url) {
356  ViewMsg_Navigate_Params params;
357  params.page_id = -1;
358  params.pending_history_list_offset = -1;
359  params.current_history_list_offset = -1;
360  params.current_history_list_length = 0;
361  params.url = url;
362  params.transition = PAGE_TRANSITION_LINK;
363  params.navigation_type = ViewMsg_Navigate_Type::NORMAL;
364  Navigate(params);
365}
366
367void RenderViewHostImpl::SetNavigationsSuspended(
368    bool suspend,
369    const base::TimeTicks& proceed_time) {
370  // This should only be called to toggle the state.
371  DCHECK(navigations_suspended_ != suspend);
372
373  navigations_suspended_ = suspend;
374  if (!suspend && suspended_nav_params_) {
375    // There's navigation message params waiting to be sent.  Now that we're not
376    // suspended anymore, resume navigation by sending them.  If we were swapped
377    // out, we should also stop filtering out the IPC messages now.
378    SetSwappedOut(false);
379
380    DCHECK(!proceed_time.is_null());
381    suspended_nav_params_->browser_navigation_start = proceed_time;
382    Send(new ViewMsg_Navigate(GetRoutingID(), *suspended_nav_params_.get()));
383    suspended_nav_params_.reset();
384  }
385}
386
387void RenderViewHostImpl::CancelSuspendedNavigations() {
388  // Clear any state if a pending navigation is canceled or pre-empted.
389  if (suspended_nav_params_)
390    suspended_nav_params_.reset();
391  navigations_suspended_ = false;
392}
393
394void RenderViewHostImpl::FirePageBeforeUnload(bool for_cross_site_transition) {
395  if (!IsRenderViewLive()) {
396    // This RenderViewHostImpl doesn't have a live renderer, so just
397    // skip running the onbeforeunload handler.
398    is_waiting_for_beforeunload_ack_ = true;  // Checked by OnShouldCloseACK.
399    unload_ack_is_for_cross_site_transition_ = for_cross_site_transition;
400    base::TimeTicks now = base::TimeTicks::Now();
401    OnShouldCloseACK(true, now, now);
402    return;
403  }
404
405  // This may be called more than once (if the user clicks the tab close button
406  // several times, or if she clicks the tab close button then the browser close
407  // button), and we only send the message once.
408  if (is_waiting_for_beforeunload_ack_) {
409    // Some of our close messages could be for the tab, others for cross-site
410    // transitions. We always want to think it's for closing the tab if any
411    // of the messages were, since otherwise it might be impossible to close
412    // (if there was a cross-site "close" request pending when the user clicked
413    // the close button). We want to keep the "for cross site" flag only if
414    // both the old and the new ones are also for cross site.
415    unload_ack_is_for_cross_site_transition_ =
416        unload_ack_is_for_cross_site_transition_ && for_cross_site_transition;
417  } else {
418    // Start the hang monitor in case the renderer hangs in the beforeunload
419    // handler.
420    is_waiting_for_beforeunload_ack_ = true;
421    unload_ack_is_for_cross_site_transition_ = for_cross_site_transition;
422    // Increment the in-flight event count, to ensure that input events won't
423    // cancel the timeout timer.
424    increment_in_flight_event_count();
425    StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
426    send_should_close_start_time_ = base::TimeTicks::Now();
427    Send(new ViewMsg_ShouldClose(GetRoutingID()));
428  }
429}
430
431void RenderViewHostImpl::SwapOut(int new_render_process_host_id,
432                                 int new_request_id) {
433  // This will be set back to false in OnSwapOutACK, just before we replace
434  // this RVH with the pending RVH.
435  is_waiting_for_unload_ack_ = true;
436  // Start the hang monitor in case the renderer hangs in the unload handler.
437  // Increment the in-flight event count, to ensure that input events won't
438  // cancel the timeout timer.
439  increment_in_flight_event_count();
440  StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
441
442  ViewMsg_SwapOut_Params params;
443  params.closing_process_id = GetProcess()->GetID();
444  params.closing_route_id = GetRoutingID();
445  params.new_render_process_host_id = new_render_process_host_id;
446  params.new_request_id = new_request_id;
447  if (IsRenderViewLive()) {
448    Send(new ViewMsg_SwapOut(GetRoutingID(), params));
449  } else {
450    // This RenderViewHost doesn't have a live renderer, so just skip the unload
451    // event.  We must notify the ResourceDispatcherHost on the IO thread,
452    // which we will do through the RenderProcessHost's widget helper.
453    GetProcess()->SimulateSwapOutACK(params);
454  }
455}
456
457void RenderViewHostImpl::OnSwapOutACK(bool timed_out) {
458  // Stop the hang monitor now that the unload handler has finished.
459  decrement_in_flight_event_count();
460  StopHangMonitorTimeout();
461  is_waiting_for_unload_ack_ = false;
462  has_timed_out_on_unload_ = timed_out;
463  delegate_->SwappedOut(this);
464}
465
466void RenderViewHostImpl::WasSwappedOut() {
467  // Don't bother reporting hung state anymore.
468  StopHangMonitorTimeout();
469
470  // If we have timed out on running the unload handler, we consider
471  // the process hung and we should terminate it if there are no other tabs
472  // using the process. If there are other views using this process, the
473  // unresponsive renderer timeout will catch it.
474  bool hung = has_timed_out_on_unload_;
475
476  // Now that we're no longer the active RVH in the tab, start filtering out
477  // most IPC messages.  Usually the renderer will have stopped sending
478  // messages as of OnSwapOutACK.  However, we may have timed out waiting
479  // for that message, and additional IPC messages may keep streaming in.
480  // We filter them out, as long as that won't cause problems (e.g., we
481  // still allow synchronous messages through).
482  SetSwappedOut(true);
483
484  // If we are not running the renderer in process and no other tab is using
485  // the hung process, consider it eligible to be killed, assuming it is a real
486  // process (unit tests don't have real processes).
487  if (hung) {
488    base::ProcessHandle process_handle = GetProcess()->GetHandle();
489    int views = 0;
490
491    // Count the number of widget hosts for the process, which is equivalent to
492    // views using the process as of this writing.
493    RenderProcessHost::RenderWidgetHostsIterator iter(
494        GetProcess()->GetRenderWidgetHostsIterator());
495    for (; !iter.IsAtEnd(); iter.Advance())
496      ++views;
497
498    if (!RenderProcessHost::run_renderer_in_process() &&
499        process_handle && views <= 1) {
500      // The process can safely be terminated, only if WebContents sets
501      // SuddenTerminationAllowed, which indicates that the timer has expired.
502      // This is not the case if we load data URLs or about:blank. The reason
503      // is that those have no network requests and this code is hit without
504      // setting the unresponsiveness timer. This allows a corner case where a
505      // navigation to a data URL will leave a process running, if the
506      // beforeunload handler completes fine, but the unload handler hangs.
507      // At this time, the complexity to solve this edge case is not worthwhile.
508      if (SuddenTerminationAllowed()) {
509        // We should kill the process, but for now, just log the data so we can
510        // diagnose the kill rate and investigate if separate timer is needed.
511        // http://crbug.com/104346.
512
513        // Log a histogram point to help us diagnose how many of those kills
514        // we have performed. 1 is the enum value for RendererType Normal for
515        // the histogram.
516        UMA_HISTOGRAM_PERCENTAGE(
517            "BrowserRenderProcessHost.ChildKillsUnresponsive", 1);
518      }
519    }
520  }
521
522  // Inform the renderer that it can exit if no one else is using it.
523  Send(new ViewMsg_WasSwappedOut(GetRoutingID()));
524}
525
526void RenderViewHostImpl::ClosePage() {
527  // Start the hang monitor in case the renderer hangs in the unload handler.
528  is_waiting_for_unload_ack_ = true;
529  StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
530
531  if (IsRenderViewLive()) {
532    // Since we are sending an IPC message to the renderer, increase the event
533    // count to prevent the hang monitor timeout from being stopped by input
534    // event acknowledgements.
535    increment_in_flight_event_count();
536
537    // TODO(creis): Should this be moved to Shutdown?  It may not be called for
538    // RenderViewHosts that have been swapped out.
539    NotificationService::current()->Notify(
540        NOTIFICATION_RENDER_VIEW_HOST_WILL_CLOSE_RENDER_VIEW,
541        Source<RenderViewHost>(this),
542        NotificationService::NoDetails());
543
544    Send(new ViewMsg_ClosePage(GetRoutingID()));
545  } else {
546    // This RenderViewHost doesn't have a live renderer, so just skip the unload
547    // event and close the page.
548    ClosePageIgnoringUnloadEvents();
549  }
550}
551
552void RenderViewHostImpl::ClosePageIgnoringUnloadEvents() {
553  StopHangMonitorTimeout();
554  is_waiting_for_beforeunload_ack_ = false;
555  is_waiting_for_unload_ack_ = false;
556
557  sudden_termination_allowed_ = true;
558  delegate_->Close(this);
559}
560
561void RenderViewHostImpl::SetHasPendingCrossSiteRequest(bool has_pending_request,
562                                                       int request_id) {
563  CrossSiteRequestManager::GetInstance()->SetHasPendingCrossSiteRequest(
564      GetProcess()->GetID(), GetRoutingID(), has_pending_request);
565  pending_request_id_ = request_id;
566}
567
568int RenderViewHostImpl::GetPendingRequestId() {
569  return pending_request_id_;
570}
571
572#if defined(OS_ANDROID)
573void RenderViewHostImpl::ActivateNearestFindResult(int request_id,
574                                                   float x,
575                                                   float y) {
576  Send(new InputMsg_ActivateNearestFindResult(GetRoutingID(),
577                                              request_id, x, y));
578}
579
580void RenderViewHostImpl::RequestFindMatchRects(int current_version) {
581  Send(new ViewMsg_FindMatchRects(GetRoutingID(), current_version));
582}
583#endif
584
585void RenderViewHostImpl::DragTargetDragEnter(
586    const WebDropData& drop_data,
587    const gfx::Point& client_pt,
588    const gfx::Point& screen_pt,
589    WebDragOperationsMask operations_allowed,
590    int key_modifiers) {
591  const int renderer_id = GetProcess()->GetID();
592  ChildProcessSecurityPolicyImpl* policy =
593      ChildProcessSecurityPolicyImpl::GetInstance();
594
595  // The URL could have been cobbled together from any highlighted text string,
596  // and can't be interpreted as a capability.
597  WebDropData filtered_data(drop_data);
598  FilterURL(policy, GetProcess(), true, &filtered_data.url);
599
600  // The filenames vector, on the other hand, does represent a capability to
601  // access the given files.
602  fileapi::IsolatedContext::FileInfoSet files;
603  for (std::vector<WebDropData::FileInfo>::iterator iter(
604           filtered_data.filenames.begin());
605       iter != filtered_data.filenames.end(); ++iter) {
606    // A dragged file may wind up as the value of an input element, or it
607    // may be used as the target of a navigation instead.  We don't know
608    // which will happen at this point, so generously grant both access
609    // and request permissions to the specific file to cover both cases.
610    // We do not give it the permission to request all file:// URLs.
611    base::FilePath path =
612        base::FilePath::FromUTF8Unsafe(UTF16ToUTF8(iter->path));
613
614    // Make sure we have the same display_name as the one we register.
615    if (iter->display_name.empty()) {
616      std::string name;
617      files.AddPath(path, &name);
618      iter->display_name = UTF8ToUTF16(name);
619    } else {
620      files.AddPathWithName(path, UTF16ToUTF8(iter->display_name));
621    }
622
623    policy->GrantRequestSpecificFileURL(renderer_id,
624                                        net::FilePathToFileURL(path));
625
626    // If the renderer already has permission to read these paths, we don't need
627    // to re-grant them. This prevents problems with DnD for files in the CrOS
628    // file manager--the file manager already had read/write access to those
629    // directories, but dragging a file would cause the read/write access to be
630    // overwritten with read-only access, making them impossible to delete or
631    // rename until the renderer was killed.
632    if (!policy->CanReadFile(renderer_id, path)) {
633      policy->GrantReadFile(renderer_id, path);
634      // Allow dragged directories to be enumerated by the child process.
635      // Note that we can't tell a file from a directory at this point.
636      policy->GrantReadDirectory(renderer_id, path);
637    }
638  }
639
640  fileapi::IsolatedContext* isolated_context =
641      fileapi::IsolatedContext::GetInstance();
642  DCHECK(isolated_context);
643  std::string filesystem_id = isolated_context->RegisterDraggedFileSystem(
644      files);
645  if (!filesystem_id.empty()) {
646    // Grant the permission iff the ID is valid.
647    policy->GrantReadFileSystem(renderer_id, filesystem_id);
648  }
649  filtered_data.filesystem_id = UTF8ToUTF16(filesystem_id);
650
651  Send(new DragMsg_TargetDragEnter(GetRoutingID(), filtered_data, client_pt,
652                                   screen_pt, operations_allowed,
653                                   key_modifiers));
654}
655
656void RenderViewHostImpl::DragTargetDragOver(
657    const gfx::Point& client_pt,
658    const gfx::Point& screen_pt,
659    WebDragOperationsMask operations_allowed,
660    int key_modifiers) {
661  Send(new DragMsg_TargetDragOver(GetRoutingID(), client_pt, screen_pt,
662                                  operations_allowed, key_modifiers));
663}
664
665void RenderViewHostImpl::DragTargetDragLeave() {
666  Send(new DragMsg_TargetDragLeave(GetRoutingID()));
667}
668
669void RenderViewHostImpl::DragTargetDrop(
670    const gfx::Point& client_pt,
671    const gfx::Point& screen_pt,
672    int key_modifiers) {
673  Send(new DragMsg_TargetDrop(GetRoutingID(), client_pt, screen_pt,
674                              key_modifiers));
675}
676
677void RenderViewHostImpl::DesktopNotificationPermissionRequestDone(
678    int callback_context) {
679  Send(new DesktopNotificationMsg_PermissionRequestDone(
680      GetRoutingID(), callback_context));
681}
682
683void RenderViewHostImpl::DesktopNotificationPostDisplay(int callback_context) {
684  Send(new DesktopNotificationMsg_PostDisplay(GetRoutingID(),
685                                              callback_context));
686}
687
688void RenderViewHostImpl::DesktopNotificationPostError(int notification_id,
689                                                      const string16& message) {
690  Send(new DesktopNotificationMsg_PostError(
691      GetRoutingID(), notification_id, message));
692}
693
694void RenderViewHostImpl::DesktopNotificationPostClose(int notification_id,
695                                                      bool by_user) {
696  Send(new DesktopNotificationMsg_PostClose(
697      GetRoutingID(), notification_id, by_user));
698}
699
700void RenderViewHostImpl::DesktopNotificationPostClick(int notification_id) {
701  Send(new DesktopNotificationMsg_PostClick(GetRoutingID(), notification_id));
702}
703
704void RenderViewHostImpl::ExecuteJavascriptInWebFrame(
705    const string16& frame_xpath,
706    const string16& jscript) {
707  Send(new ViewMsg_ScriptEvalRequest(GetRoutingID(), frame_xpath, jscript,
708                                     0, false));
709}
710
711void RenderViewHostImpl::ExecuteJavascriptInWebFrameCallbackResult(
712     const string16& frame_xpath,
713     const string16& jscript,
714     const JavascriptResultCallback& callback) {
715  static int next_id = 1;
716  int key = next_id++;
717  Send(new ViewMsg_ScriptEvalRequest(GetRoutingID(), frame_xpath, jscript,
718                                     key, true));
719  javascript_callbacks_.insert(std::make_pair(key, callback));
720}
721
722void RenderViewHostImpl::JavaScriptDialogClosed(IPC::Message* reply_msg,
723                                                bool success,
724                                                const string16& user_input) {
725  GetProcess()->SetIgnoreInputEvents(false);
726  bool is_waiting =
727      is_waiting_for_beforeunload_ack_ || is_waiting_for_unload_ack_;
728
729  // If we are executing as part of (before)unload event handling, we don't
730  // want to use the regular hung_renderer_delay_ms_ if the user has agreed to
731  // leave the current page. In this case, use the regular timeout value used
732  // during the (before)unload handling.
733  if (is_waiting) {
734    StartHangMonitorTimeout(TimeDelta::FromMilliseconds(
735        success ? kUnloadTimeoutMS : hung_renderer_delay_ms_));
736  }
737
738  ViewHostMsg_RunJavaScriptMessage::WriteReplyParams(reply_msg,
739                                                     success, user_input);
740  Send(reply_msg);
741
742  // If we are waiting for an unload or beforeunload ack and the user has
743  // suppressed messages, kill the tab immediately; a page that's spamming
744  // alerts in onbeforeunload is presumably malicious, so there's no point in
745  // continuing to run its script and dragging out the process.
746  // This must be done after sending the reply since RenderView can't close
747  // correctly while waiting for a response.
748  if (is_waiting && are_javascript_messages_suppressed_)
749    delegate_->RendererUnresponsive(this, is_waiting);
750}
751
752void RenderViewHostImpl::DragSourceEndedAt(
753    int client_x, int client_y, int screen_x, int screen_y,
754    WebDragOperation operation) {
755  Send(new DragMsg_SourceEndedOrMoved(
756      GetRoutingID(),
757      gfx::Point(client_x, client_y),
758      gfx::Point(screen_x, screen_y),
759      true, operation));
760}
761
762void RenderViewHostImpl::DragSourceMovedTo(
763    int client_x, int client_y, int screen_x, int screen_y) {
764  Send(new DragMsg_SourceEndedOrMoved(
765      GetRoutingID(),
766      gfx::Point(client_x, client_y),
767      gfx::Point(screen_x, screen_y),
768      false, WebDragOperationNone));
769}
770
771void RenderViewHostImpl::DragSourceSystemDragEnded() {
772  Send(new DragMsg_SourceSystemDragEnded(GetRoutingID()));
773}
774
775void RenderViewHostImpl::AllowBindings(int bindings_flags) {
776  // Ensure we aren't granting WebUI bindings to a process that has already
777  // been used for non-privileged views.
778  if (bindings_flags & BINDINGS_POLICY_WEB_UI &&
779      GetProcess()->HasConnection() &&
780      !ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
781          GetProcess()->GetID())) {
782    // This process has no bindings yet. Make sure it does not have more
783    // than this single active view.
784    RenderProcessHostImpl* process =
785        static_cast<RenderProcessHostImpl*>(GetProcess());
786    if (process->GetActiveViewCount() > 1)
787      return;
788  }
789
790  // Never grant any bindings to browser plugin guests.
791  if (GetProcess()->IsGuest()) {
792    NOTREACHED() << "Never grant bindings to a guest process.";
793    return;
794  }
795
796  if (bindings_flags & BINDINGS_POLICY_WEB_UI) {
797    ChildProcessSecurityPolicyImpl::GetInstance()->GrantWebUIBindings(
798        GetProcess()->GetID());
799  }
800
801  enabled_bindings_ |= bindings_flags;
802  if (renderer_initialized_)
803    Send(new ViewMsg_AllowBindings(GetRoutingID(), enabled_bindings_));
804}
805
806int RenderViewHostImpl::GetEnabledBindings() const {
807  return enabled_bindings_;
808}
809
810void RenderViewHostImpl::SetWebUIProperty(const std::string& name,
811                                          const std::string& value) {
812  // This is a sanity check before telling the renderer to enable the property.
813  // It could lie and send the corresponding IPC messages anyway, but we will
814  // not act on them if enabled_bindings_ doesn't agree. If we get here without
815  // WebUI bindings, kill the renderer process.
816  if (enabled_bindings_ & BINDINGS_POLICY_WEB_UI) {
817    Send(new ViewMsg_SetWebUIProperty(GetRoutingID(), name, value));
818  } else {
819    RecordAction(UserMetricsAction("BindingsMismatchTerminate_RVH_WebUI"));
820    base::KillProcess(
821        GetProcess()->GetHandle(), content::RESULT_CODE_KILLED, false);
822  }
823}
824
825void RenderViewHostImpl::GotFocus() {
826  RenderWidgetHostImpl::GotFocus();  // Notifies the renderer it got focus.
827
828  RenderViewHostDelegateView* view = delegate_->GetDelegateView();
829  if (view)
830    view->GotFocus();
831}
832
833void RenderViewHostImpl::LostCapture() {
834  RenderWidgetHostImpl::LostCapture();
835  delegate_->LostCapture();
836}
837
838void RenderViewHostImpl::LostMouseLock() {
839  RenderWidgetHostImpl::LostMouseLock();
840  delegate_->LostMouseLock();
841}
842
843void RenderViewHostImpl::SetInitialFocus(bool reverse) {
844  Send(new ViewMsg_SetInitialFocus(GetRoutingID(), reverse));
845}
846
847void RenderViewHostImpl::FilesSelectedInChooser(
848    const std::vector<ui::SelectedFileInfo>& files,
849    int permissions) {
850  // Grant the security access requested to the given files.
851  for (size_t i = 0; i < files.size(); ++i) {
852    const ui::SelectedFileInfo& file = files[i];
853    ChildProcessSecurityPolicyImpl::GetInstance()->GrantPermissionsForFile(
854        GetProcess()->GetID(), file.local_path, permissions);
855  }
856  Send(new ViewMsg_RunFileChooserResponse(GetRoutingID(), files));
857}
858
859void RenderViewHostImpl::DirectoryEnumerationFinished(
860    int request_id,
861    const std::vector<base::FilePath>& files) {
862  // Grant the security access requested to the given files.
863  for (std::vector<base::FilePath>::const_iterator file = files.begin();
864       file != files.end(); ++file) {
865    ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
866        GetProcess()->GetID(), *file);
867  }
868  Send(new ViewMsg_EnumerateDirectoryResponse(GetRoutingID(),
869                                              request_id,
870                                              files));
871}
872
873void RenderViewHostImpl::LoadStateChanged(
874    const GURL& url,
875    const net::LoadStateWithParam& load_state,
876    uint64 upload_position,
877    uint64 upload_size) {
878  delegate_->LoadStateChanged(url, load_state, upload_position, upload_size);
879}
880
881bool RenderViewHostImpl::SuddenTerminationAllowed() const {
882  return sudden_termination_allowed_ ||
883      GetProcess()->SuddenTerminationAllowed();
884}
885
886///////////////////////////////////////////////////////////////////////////////
887// RenderViewHostImpl, IPC message handlers:
888
889bool RenderViewHostImpl::OnMessageReceived(const IPC::Message& msg) {
890  if (!BrowserMessageFilter::CheckCanDispatchOnUI(msg, this))
891    return true;
892
893  // Filter out most IPC messages if this renderer is swapped out.
894  // We still want to handle certain ACKs to keep our state consistent.
895  if (is_swapped_out_) {
896    if (!SwappedOutMessages::CanHandleWhileSwappedOut(msg)) {
897      // If this is a synchronous message and we decided not to handle it,
898      // we must send an error reply, or else the renderer will be stuck
899      // and won't respond to future requests.
900      if (msg.is_sync()) {
901        IPC::Message* reply = IPC::SyncMessage::GenerateReply(&msg);
902        reply->set_reply_error();
903        Send(reply);
904      }
905      // Don't continue looking for someone to handle it.
906      return true;
907    }
908  }
909
910  ObserverListBase<RenderViewHostObserver>::Iterator it(observers_);
911  RenderViewHostObserver* observer;
912  while ((observer = it.GetNext()) != NULL) {
913    if (observer->OnMessageReceived(msg))
914      return true;
915  }
916
917  if (delegate_->OnMessageReceived(this, msg))
918    return true;
919
920  // TODO(jochen): Consider removing message handlers that only add a this
921  // pointer and forward the messages to the RenderViewHostDelegate. The
922  // respective delegates can handle the messages themselves in their
923  // OnMessageReceived implementation.
924  bool handled = true;
925  bool msg_is_ok = true;
926  IPC_BEGIN_MESSAGE_MAP_EX(RenderViewHostImpl, msg, msg_is_ok)
927    IPC_MESSAGE_HANDLER(ViewHostMsg_ShowView, OnShowView)
928    IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnShowWidget)
929    IPC_MESSAGE_HANDLER(ViewHostMsg_ShowFullscreenWidget,
930                        OnShowFullscreenWidget)
931    IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_RunModal, OnRunModal)
932    IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewReady, OnRenderViewReady)
933    IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewGone, OnRenderViewGone)
934    IPC_MESSAGE_HANDLER(ViewHostMsg_DidStartProvisionalLoadForFrame,
935                        OnDidStartProvisionalLoadForFrame)
936    IPC_MESSAGE_HANDLER(ViewHostMsg_DidRedirectProvisionalLoad,
937                        OnDidRedirectProvisionalLoad)
938    IPC_MESSAGE_HANDLER(ViewHostMsg_DidFailProvisionalLoadWithError,
939                        OnDidFailProvisionalLoadWithError)
940    IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_FrameNavigate, OnNavigate(msg))
941    IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateState, OnUpdateState)
942    IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateTitle, OnUpdateTitle)
943    IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateEncoding, OnUpdateEncoding)
944    IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateTargetURL, OnUpdateTargetURL)
945    IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateInspectorSetting,
946                        OnUpdateInspectorSetting)
947    IPC_MESSAGE_HANDLER(ViewHostMsg_Close, OnClose)
948    IPC_MESSAGE_HANDLER(ViewHostMsg_RequestMove, OnRequestMove)
949    IPC_MESSAGE_HANDLER(ViewHostMsg_DidStartLoading, OnDidStartLoading)
950    IPC_MESSAGE_HANDLER(ViewHostMsg_DidStopLoading, OnDidStopLoading)
951    IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeLoadProgress,
952                        OnDidChangeLoadProgress)
953    IPC_MESSAGE_HANDLER(ViewHostMsg_DidDisownOpener, OnDidDisownOpener)
954    IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentAvailableInMainFrame,
955                        OnDocumentAvailableInMainFrame)
956    IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentOnLoadCompletedInMainFrame,
957                        OnDocumentOnLoadCompletedInMainFrame)
958    IPC_MESSAGE_HANDLER(ViewHostMsg_ContextMenu, OnContextMenu)
959    IPC_MESSAGE_HANDLER(ViewHostMsg_ToggleFullscreen, OnToggleFullscreen)
960    IPC_MESSAGE_HANDLER(ViewHostMsg_OpenURL, OnOpenURL)
961    IPC_MESSAGE_HANDLER(ViewHostMsg_DidContentsPreferredSizeChange,
962                        OnDidContentsPreferredSizeChange)
963    IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeScrollOffset,
964                        OnDidChangeScrollOffset)
965    IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeScrollbarsForMainFrame,
966                        OnDidChangeScrollbarsForMainFrame)
967    IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeScrollOffsetPinningForMainFrame,
968                        OnDidChangeScrollOffsetPinningForMainFrame)
969    IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeNumWheelEvents,
970                        OnDidChangeNumWheelEvents)
971    IPC_MESSAGE_HANDLER(ViewHostMsg_RouteCloseEvent,
972                        OnRouteCloseEvent)
973    IPC_MESSAGE_HANDLER(ViewHostMsg_RouteMessageEvent, OnRouteMessageEvent)
974    IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_RunJavaScriptMessage,
975                                    OnRunJavaScriptMessage)
976    IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_RunBeforeUnloadConfirm,
977                                    OnRunBeforeUnloadConfirm)
978    IPC_MESSAGE_HANDLER(DragHostMsg_StartDragging, OnStartDragging)
979    IPC_MESSAGE_HANDLER(DragHostMsg_UpdateDragCursor, OnUpdateDragCursor)
980    IPC_MESSAGE_HANDLER(DragHostMsg_TargetDrop_ACK, OnTargetDropACK)
981    IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus, OnTakeFocus)
982    IPC_MESSAGE_HANDLER(ViewHostMsg_FocusedNodeChanged, OnFocusedNodeChanged)
983    IPC_MESSAGE_HANDLER(ViewHostMsg_AddMessageToConsole, OnAddMessageToConsole)
984    IPC_MESSAGE_HANDLER(ViewHostMsg_ShouldClose_ACK, OnShouldCloseACK)
985    IPC_MESSAGE_HANDLER(ViewHostMsg_ClosePage_ACK, OnClosePageACK)
986    IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionChanged, OnSelectionChanged)
987    IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionBoundsChanged,
988                        OnSelectionBoundsChanged)
989    IPC_MESSAGE_HANDLER(ViewHostMsg_ScriptEvalResponse, OnScriptEvalResponse)
990    IPC_MESSAGE_HANDLER(ViewHostMsg_DidZoomURL, OnDidZoomURL)
991    IPC_MESSAGE_HANDLER(ViewHostMsg_MediaNotification, OnMediaNotification)
992    IPC_MESSAGE_HANDLER(ViewHostMsg_GetWindowSnapshot, OnGetWindowSnapshot)
993    IPC_MESSAGE_HANDLER(DesktopNotificationHostMsg_RequestPermission,
994                        OnRequestDesktopNotificationPermission)
995    IPC_MESSAGE_HANDLER(DesktopNotificationHostMsg_Show,
996                        OnShowDesktopNotification)
997    IPC_MESSAGE_HANDLER(DesktopNotificationHostMsg_Cancel,
998                        OnCancelDesktopNotification)
999#if defined(OS_MACOSX) || defined(OS_ANDROID)
1000    IPC_MESSAGE_HANDLER(ViewHostMsg_ShowPopup, OnShowPopup)
1001#endif
1002    IPC_MESSAGE_HANDLER(ViewHostMsg_RunFileChooser, OnRunFileChooser)
1003    IPC_MESSAGE_HANDLER(ViewHostMsg_DidAccessInitialDocument,
1004                        OnDidAccessInitialDocument)
1005    IPC_MESSAGE_HANDLER(ViewHostMsg_DomOperationResponse,
1006                        OnDomOperationResponse)
1007    IPC_MESSAGE_HANDLER(AccessibilityHostMsg_Notifications,
1008                        OnAccessibilityNotifications)
1009    // Have the super handle all other messages.
1010    IPC_MESSAGE_UNHANDLED(
1011        handled = RenderWidgetHostImpl::OnMessageReceived(msg))
1012  IPC_END_MESSAGE_MAP_EX()
1013
1014  if (!msg_is_ok) {
1015    // The message had a handler, but its de-serialization failed.
1016    // Kill the renderer.
1017    RecordAction(UserMetricsAction("BadMessageTerminate_RVH"));
1018    GetProcess()->ReceivedBadMessage();
1019  }
1020
1021  return handled;
1022}
1023
1024void RenderViewHostImpl::Shutdown() {
1025  // If we are being run modally (see RunModal), then we need to cleanup.
1026  if (run_modal_reply_msg_) {
1027    Send(run_modal_reply_msg_);
1028    run_modal_reply_msg_ = NULL;
1029    RenderViewHostImpl* opener =
1030        RenderViewHostImpl::FromID(GetProcess()->GetID(), run_modal_opener_id_);
1031    if (opener) {
1032      opener->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(
1033          hung_renderer_delay_ms_));
1034      // Balance out the decrement when we got created.
1035      opener->increment_in_flight_event_count();
1036    }
1037    run_modal_opener_id_ = MSG_ROUTING_NONE;
1038  }
1039
1040  RenderWidgetHostImpl::Shutdown();
1041}
1042
1043bool RenderViewHostImpl::IsRenderView() const {
1044  return true;
1045}
1046
1047void RenderViewHostImpl::CreateNewWindow(
1048    int route_id,
1049    int main_frame_route_id,
1050    const ViewHostMsg_CreateWindow_Params& params,
1051    SessionStorageNamespace* session_storage_namespace) {
1052  ViewHostMsg_CreateWindow_Params validated_params(params);
1053  ChildProcessSecurityPolicyImpl* policy =
1054      ChildProcessSecurityPolicyImpl::GetInstance();
1055  FilterURL(policy, GetProcess(), false, &validated_params.target_url);
1056  FilterURL(policy, GetProcess(), false, &validated_params.opener_url);
1057  FilterURL(policy, GetProcess(), true,
1058            &validated_params.opener_security_origin);
1059
1060  delegate_->CreateNewWindow(route_id, main_frame_route_id,
1061                             validated_params, session_storage_namespace);
1062}
1063
1064void RenderViewHostImpl::CreateNewWidget(int route_id,
1065                                     WebKit::WebPopupType popup_type) {
1066  delegate_->CreateNewWidget(route_id, popup_type);
1067}
1068
1069void RenderViewHostImpl::CreateNewFullscreenWidget(int route_id) {
1070  delegate_->CreateNewFullscreenWidget(route_id);
1071}
1072
1073void RenderViewHostImpl::OnShowView(int route_id,
1074                                    WindowOpenDisposition disposition,
1075                                    const gfx::Rect& initial_pos,
1076                                    bool user_gesture) {
1077  if (!is_swapped_out_) {
1078    delegate_->ShowCreatedWindow(
1079        route_id, disposition, initial_pos, user_gesture);
1080  }
1081  Send(new ViewMsg_Move_ACK(route_id));
1082}
1083
1084void RenderViewHostImpl::OnShowWidget(int route_id,
1085                                      const gfx::Rect& initial_pos) {
1086  if (!is_swapped_out_)
1087    delegate_->ShowCreatedWidget(route_id, initial_pos);
1088  Send(new ViewMsg_Move_ACK(route_id));
1089}
1090
1091void RenderViewHostImpl::OnShowFullscreenWidget(int route_id) {
1092  if (!is_swapped_out_)
1093    delegate_->ShowCreatedFullscreenWidget(route_id);
1094  Send(new ViewMsg_Move_ACK(route_id));
1095}
1096
1097void RenderViewHostImpl::OnRunModal(int opener_id, IPC::Message* reply_msg) {
1098  DCHECK(!run_modal_reply_msg_);
1099  run_modal_reply_msg_ = reply_msg;
1100  run_modal_opener_id_ = opener_id;
1101
1102  RecordAction(UserMetricsAction("ShowModalDialog"));
1103
1104  RenderViewHostImpl* opener =
1105      RenderViewHostImpl::FromID(GetProcess()->GetID(), run_modal_opener_id_);
1106  if (opener) {
1107    opener->StopHangMonitorTimeout();
1108    // The ack for the mouse down won't come until the dialog closes, so fake it
1109    // so that we don't get a timeout.
1110    opener->decrement_in_flight_event_count();
1111  }
1112
1113  // TODO(darin): Bug 1107929: Need to inform our delegate to show this view in
1114  // an app-modal fashion.
1115}
1116
1117void RenderViewHostImpl::OnRenderViewReady() {
1118  render_view_termination_status_ = base::TERMINATION_STATUS_STILL_RUNNING;
1119  SendScreenRects();
1120  WasResized();
1121  delegate_->RenderViewReady(this);
1122}
1123
1124void RenderViewHostImpl::OnRenderViewGone(int status, int exit_code) {
1125  // Keep the termination status so we can get at it later when we
1126  // need to know why it died.
1127  render_view_termination_status_ =
1128      static_cast<base::TerminationStatus>(status);
1129
1130  // Reset state.
1131  ClearPowerSaveBlockers();
1132  main_frame_id_ = -1;
1133
1134  // Our base class RenderWidgetHost needs to reset some stuff.
1135  RendererExited(render_view_termination_status_, exit_code);
1136
1137  delegate_->RenderViewTerminated(this,
1138                                  static_cast<base::TerminationStatus>(status),
1139                                  exit_code);
1140}
1141
1142void RenderViewHostImpl::OnDidStartProvisionalLoadForFrame(
1143    int64 frame_id,
1144    int64 parent_frame_id,
1145    bool is_main_frame,
1146    const GURL& url) {
1147  delegate_->DidStartProvisionalLoadForFrame(
1148      this, frame_id, parent_frame_id, is_main_frame, url);
1149}
1150
1151void RenderViewHostImpl::OnDidRedirectProvisionalLoad(
1152    int32 page_id,
1153    const GURL& source_url,
1154    const GURL& target_url) {
1155  delegate_->DidRedirectProvisionalLoad(
1156      this, page_id, source_url, target_url);
1157}
1158
1159void RenderViewHostImpl::OnDidFailProvisionalLoadWithError(
1160    const ViewHostMsg_DidFailProvisionalLoadWithError_Params& params) {
1161  delegate_->DidFailProvisionalLoadWithError(this, params);
1162}
1163
1164// Called when the renderer navigates.  For every frame loaded, we'll get this
1165// notification containing parameters identifying the navigation.
1166//
1167// Subframes are identified by the page transition type.  For subframes loaded
1168// as part of a wider page load, the page_id will be the same as for the top
1169// level frame.  If the user explicitly requests a subframe navigation, we will
1170// get a new page_id because we need to create a new navigation entry for that
1171// action.
1172void RenderViewHostImpl::OnNavigate(const IPC::Message& msg) {
1173  // Read the parameters out of the IPC message directly to avoid making another
1174  // copy when we filter the URLs.
1175  PickleIterator iter(msg);
1176  ViewHostMsg_FrameNavigate_Params validated_params;
1177  if (!IPC::ParamTraits<ViewHostMsg_FrameNavigate_Params>::
1178      Read(&msg, &iter, &validated_params))
1179    return;
1180
1181  // If we're waiting for a cross-site beforeunload ack from this renderer and
1182  // we receive a Navigate message from the main frame, then the renderer was
1183  // navigating already and sent it before hearing the ViewMsg_Stop message.
1184  // We do not want to cancel the pending navigation in this case, since the
1185  // old page will soon be stopped.  Instead, treat this as a beforeunload ack
1186  // to allow the pending navigation to continue.
1187  if (is_waiting_for_beforeunload_ack_ &&
1188      unload_ack_is_for_cross_site_transition_ &&
1189      PageTransitionIsMainFrame(validated_params.transition)) {
1190    OnShouldCloseACK(true, send_should_close_start_time_,
1191                        base::TimeTicks::Now());
1192    return;
1193  }
1194
1195  // If we're waiting for an unload ack from this renderer and we receive a
1196  // Navigate message, then the renderer was navigating before it received the
1197  // unload request.  It will either respond to the unload request soon or our
1198  // timer will expire.  Either way, we should ignore this message, because we
1199  // have already committed to closing this renderer.
1200  if (is_waiting_for_unload_ack_)
1201    return;
1202
1203  // Cache the main frame id, so we can use it for creating the frame tree
1204  // root node when needed.
1205  if (PageTransitionIsMainFrame(validated_params.transition)) {
1206    if (main_frame_id_ == -1) {
1207      main_frame_id_ = validated_params.frame_id;
1208    } else {
1209      // TODO(nasko): We plan to remove the usage of frame_id in navigation
1210      // and move to routing ids. This is in place to ensure that a
1211      // renderer is not misbehaving and sending us incorrect data.
1212      DCHECK_EQ(main_frame_id_, validated_params.frame_id);
1213    }
1214  }
1215  RenderProcessHost* process = GetProcess();
1216
1217  // Attempts to commit certain off-limits URL should be caught more strictly
1218  // than our FilterURL checks below.  If a renderer violates this policy, it
1219  // should be killed.
1220  if (!CanCommitURL(validated_params.url)) {
1221    VLOG(1) << "Blocked URL " << validated_params.url.spec();
1222    validated_params.url = GURL(kAboutBlankURL);
1223    RecordAction(UserMetricsAction("CanCommitURL_BlockedAndKilled"));
1224    // Kills the process.
1225    process->ReceivedBadMessage();
1226  }
1227
1228  // Now that something has committed, we don't need to track whether the
1229  // initial page has been accessed.
1230  has_accessed_initial_document_ = false;
1231
1232  ChildProcessSecurityPolicyImpl* policy =
1233      ChildProcessSecurityPolicyImpl::GetInstance();
1234  // Without this check, an evil renderer can trick the browser into creating
1235  // a navigation entry for a banned URL.  If the user clicks the back button
1236  // followed by the forward button (or clicks reload, or round-trips through
1237  // session restore, etc), we'll think that the browser commanded the
1238  // renderer to load the URL and grant the renderer the privileges to request
1239  // the URL.  To prevent this attack, we block the renderer from inserting
1240  // banned URLs into the navigation controller in the first place.
1241  FilterURL(policy, process, false, &validated_params.url);
1242  FilterURL(policy, process, true, &validated_params.referrer.url);
1243  for (std::vector<GURL>::iterator it(validated_params.redirects.begin());
1244      it != validated_params.redirects.end(); ++it) {
1245    FilterURL(policy, process, false, &(*it));
1246  }
1247  FilterURL(policy, process, true, &validated_params.searchable_form_url);
1248  FilterURL(policy, process, true, &validated_params.password_form.origin);
1249  FilterURL(policy, process, true, &validated_params.password_form.action);
1250
1251  // Without this check, the renderer can trick the browser into using
1252  // filenames it can't access in a future session restore.
1253  if (!CanAccessFilesOfPageState(validated_params.page_state)) {
1254    GetProcess()->ReceivedBadMessage();
1255    return;
1256  }
1257
1258  delegate_->DidNavigate(this, validated_params);
1259}
1260
1261void RenderViewHostImpl::OnUpdateState(int32 page_id, const PageState& state) {
1262  // Without this check, the renderer can trick the browser into using
1263  // filenames it can't access in a future session restore.
1264  if (!CanAccessFilesOfPageState(state)) {
1265    GetProcess()->ReceivedBadMessage();
1266    return;
1267  }
1268
1269  delegate_->UpdateState(this, page_id, state);
1270}
1271
1272void RenderViewHostImpl::OnUpdateTitle(
1273    int32 page_id,
1274    const string16& title,
1275    WebKit::WebTextDirection title_direction) {
1276  if (title.length() > kMaxTitleChars) {
1277    NOTREACHED() << "Renderer sent too many characters in title.";
1278    return;
1279  }
1280
1281  delegate_->UpdateTitle(this, page_id, title,
1282                         WebTextDirectionToChromeTextDirection(
1283                             title_direction));
1284}
1285
1286void RenderViewHostImpl::OnUpdateEncoding(const std::string& encoding_name) {
1287  delegate_->UpdateEncoding(this, encoding_name);
1288}
1289
1290void RenderViewHostImpl::OnUpdateTargetURL(int32 page_id, const GURL& url) {
1291  if (!is_swapped_out_)
1292    delegate_->UpdateTargetURL(page_id, url);
1293
1294  // Send a notification back to the renderer that we are ready to
1295  // receive more target urls.
1296  Send(new ViewMsg_UpdateTargetURL_ACK(GetRoutingID()));
1297}
1298
1299void RenderViewHostImpl::OnUpdateInspectorSetting(
1300    const std::string& key, const std::string& value) {
1301  GetContentClient()->browser()->UpdateInspectorSetting(
1302      this, key, value);
1303}
1304
1305void RenderViewHostImpl::OnClose() {
1306  // If the renderer is telling us to close, it has already run the unload
1307  // events, and we can take the fast path.
1308  ClosePageIgnoringUnloadEvents();
1309}
1310
1311void RenderViewHostImpl::OnRequestMove(const gfx::Rect& pos) {
1312  if (!is_swapped_out_)
1313    delegate_->RequestMove(pos);
1314  Send(new ViewMsg_Move_ACK(GetRoutingID()));
1315}
1316
1317void RenderViewHostImpl::OnDidStartLoading() {
1318  delegate_->DidStartLoading(this);
1319}
1320
1321void RenderViewHostImpl::OnDidStopLoading() {
1322  delegate_->DidStopLoading(this);
1323}
1324
1325void RenderViewHostImpl::OnDidChangeLoadProgress(double load_progress) {
1326  delegate_->DidChangeLoadProgress(load_progress);
1327}
1328
1329void RenderViewHostImpl::OnDidDisownOpener() {
1330  delegate_->DidDisownOpener(this);
1331}
1332
1333void RenderViewHostImpl::OnDocumentAvailableInMainFrame() {
1334  delegate_->DocumentAvailableInMainFrame(this);
1335}
1336
1337void RenderViewHostImpl::OnDocumentOnLoadCompletedInMainFrame(
1338    int32 page_id) {
1339  delegate_->DocumentOnLoadCompletedInMainFrame(this, page_id);
1340}
1341
1342void RenderViewHostImpl::OnContextMenu(const ContextMenuParams& params) {
1343  // Validate the URLs in |params|.  If the renderer can't request the URLs
1344  // directly, don't show them in the context menu.
1345  ContextMenuParams validated_params(params);
1346  RenderProcessHost* process = GetProcess();
1347  ChildProcessSecurityPolicyImpl* policy =
1348      ChildProcessSecurityPolicyImpl::GetInstance();
1349
1350  // We don't validate |unfiltered_link_url| so that this field can be used
1351  // when users want to copy the original link URL.
1352  FilterURL(policy, process, true, &validated_params.link_url);
1353  FilterURL(policy, process, true, &validated_params.src_url);
1354  FilterURL(policy, process, false, &validated_params.page_url);
1355  FilterURL(policy, process, true, &validated_params.frame_url);
1356
1357  ContextMenuSourceType type = CONTEXT_MENU_SOURCE_MOUSE;
1358  if (!in_process_event_types_.empty()) {
1359    WebKit::WebInputEvent::Type event_type = in_process_event_types_.front();
1360    if (WebKit::WebInputEvent::isGestureEventType(event_type))
1361      type = CONTEXT_MENU_SOURCE_TOUCH;
1362    else if (WebKit::WebInputEvent::isKeyboardEventType(event_type))
1363      type = CONTEXT_MENU_SOURCE_KEYBOARD;
1364  }
1365  delegate_->ShowContextMenu(validated_params, type);
1366}
1367
1368void RenderViewHostImpl::OnToggleFullscreen(bool enter_fullscreen) {
1369  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1370  delegate_->ToggleFullscreenMode(enter_fullscreen);
1371  WasResized();
1372}
1373
1374void RenderViewHostImpl::OnOpenURL(
1375    const ViewHostMsg_OpenURL_Params& params) {
1376  GURL validated_url(params.url);
1377  FilterURL(ChildProcessSecurityPolicyImpl::GetInstance(),
1378            GetProcess(), false, &validated_url);
1379
1380  delegate_->RequestOpenURL(
1381      this, validated_url, params.referrer, params.disposition, params.frame_id,
1382      params.is_cross_site_redirect);
1383}
1384
1385void RenderViewHostImpl::OnDidContentsPreferredSizeChange(
1386    const gfx::Size& new_size) {
1387  delegate_->UpdatePreferredSize(new_size);
1388}
1389
1390void RenderViewHostImpl::OnRenderAutoResized(const gfx::Size& new_size) {
1391  delegate_->ResizeDueToAutoResize(new_size);
1392}
1393
1394void RenderViewHostImpl::OnDidChangeScrollOffset() {
1395  if (view_)
1396    view_->ScrollOffsetChanged();
1397}
1398
1399void RenderViewHostImpl::OnDidChangeScrollbarsForMainFrame(
1400    bool has_horizontal_scrollbar, bool has_vertical_scrollbar) {
1401  if (view_)
1402    view_->SetHasHorizontalScrollbar(has_horizontal_scrollbar);
1403}
1404
1405void RenderViewHostImpl::OnDidChangeScrollOffsetPinningForMainFrame(
1406    bool is_pinned_to_left, bool is_pinned_to_right) {
1407  if (view_)
1408    view_->SetScrollOffsetPinning(is_pinned_to_left, is_pinned_to_right);
1409}
1410
1411void RenderViewHostImpl::OnDidChangeNumWheelEvents(int count) {
1412}
1413
1414void RenderViewHostImpl::OnSelectionChanged(const string16& text,
1415                                            size_t offset,
1416                                            const ui::Range& range) {
1417  if (view_)
1418    view_->SelectionChanged(text, offset, range);
1419}
1420
1421void RenderViewHostImpl::OnSelectionBoundsChanged(
1422    const ViewHostMsg_SelectionBounds_Params& params) {
1423  if (view_) {
1424    view_->SelectionBoundsChanged(params);
1425  }
1426}
1427
1428void RenderViewHostImpl::OnRouteCloseEvent() {
1429  // Have the delegate route this to the active RenderViewHost.
1430  delegate_->RouteCloseEvent(this);
1431}
1432
1433void RenderViewHostImpl::OnRouteMessageEvent(
1434    const ViewMsg_PostMessage_Params& params) {
1435  // Give to the delegate to route to the active RenderViewHost.
1436  delegate_->RouteMessageEvent(this, params);
1437}
1438
1439void RenderViewHostImpl::OnRunJavaScriptMessage(
1440    const string16& message,
1441    const string16& default_prompt,
1442    const GURL& frame_url,
1443    JavaScriptMessageType type,
1444    IPC::Message* reply_msg) {
1445  // While a JS message dialog is showing, tabs in the same process shouldn't
1446  // process input events.
1447  GetProcess()->SetIgnoreInputEvents(true);
1448  StopHangMonitorTimeout();
1449  delegate_->RunJavaScriptMessage(this, message, default_prompt, frame_url,
1450                                  type, reply_msg,
1451                                  &are_javascript_messages_suppressed_);
1452}
1453
1454void RenderViewHostImpl::OnRunBeforeUnloadConfirm(const GURL& frame_url,
1455                                                  const string16& message,
1456                                                  bool is_reload,
1457                                                  IPC::Message* reply_msg) {
1458  // While a JS before unload dialog is showing, tabs in the same process
1459  // shouldn't process input events.
1460  GetProcess()->SetIgnoreInputEvents(true);
1461  StopHangMonitorTimeout();
1462  delegate_->RunBeforeUnloadConfirm(this, message, is_reload, reply_msg);
1463}
1464
1465void RenderViewHostImpl::OnStartDragging(
1466    const WebDropData& drop_data,
1467    WebDragOperationsMask drag_operations_mask,
1468    const SkBitmap& bitmap,
1469    const gfx::Vector2d& bitmap_offset_in_dip,
1470    const DragEventSourceInfo& event_info) {
1471  RenderViewHostDelegateView* view = delegate_->GetDelegateView();
1472  if (!view)
1473    return;
1474
1475  WebDropData filtered_data(drop_data);
1476  RenderProcessHost* process = GetProcess();
1477  ChildProcessSecurityPolicyImpl* policy =
1478      ChildProcessSecurityPolicyImpl::GetInstance();
1479
1480  // Allow drag of Javascript URLs to enable bookmarklet drag to bookmark bar.
1481  if (!filtered_data.url.SchemeIs(chrome::kJavaScriptScheme))
1482    FilterURL(policy, process, true, &filtered_data.url);
1483  FilterURL(policy, process, false, &filtered_data.html_base_url);
1484  // Filter out any paths that the renderer didn't have access to. This prevents
1485  // the following attack on a malicious renderer:
1486  // 1. StartDragging IPC sent with renderer-specified filesystem paths that it
1487  //    doesn't have read permissions for.
1488  // 2. We initiate a native DnD operation.
1489  // 3. DnD operation immediately ends since mouse is not held down. DnD events
1490  //    still fire though, which causes read permissions to be granted to the
1491  //    renderer for any file paths in the drop.
1492  filtered_data.filenames.clear();
1493  for (std::vector<WebDropData::FileInfo>::const_iterator it =
1494           drop_data.filenames.begin();
1495       it != drop_data.filenames.end(); ++it) {
1496    base::FilePath path(base::FilePath::FromUTF8Unsafe(UTF16ToUTF8(it->path)));
1497    if (policy->CanReadFile(GetProcess()->GetID(), path))
1498      filtered_data.filenames.push_back(*it);
1499  }
1500  ui::ScaleFactor scale_factor = GetScaleFactorForView(GetView());
1501  gfx::ImageSkia image(gfx::ImageSkiaRep(bitmap, scale_factor));
1502  view->StartDragging(filtered_data, drag_operations_mask, image,
1503      bitmap_offset_in_dip, event_info);
1504}
1505
1506void RenderViewHostImpl::OnUpdateDragCursor(WebDragOperation current_op) {
1507  RenderViewHostDelegateView* view = delegate_->GetDelegateView();
1508  if (view)
1509    view->UpdateDragCursor(current_op);
1510}
1511
1512void RenderViewHostImpl::OnTargetDropACK() {
1513  NotificationService::current()->Notify(
1514      NOTIFICATION_RENDER_VIEW_HOST_DID_RECEIVE_DRAG_TARGET_DROP_ACK,
1515      Source<RenderViewHost>(this),
1516      NotificationService::NoDetails());
1517}
1518
1519void RenderViewHostImpl::OnTakeFocus(bool reverse) {
1520  RenderViewHostDelegateView* view = delegate_->GetDelegateView();
1521  if (view)
1522    view->TakeFocus(reverse);
1523}
1524
1525void RenderViewHostImpl::OnFocusedNodeChanged(bool is_editable_node) {
1526  NotificationService::current()->Notify(
1527      NOTIFICATION_FOCUS_CHANGED_IN_PAGE,
1528      Source<RenderViewHost>(this),
1529      Details<const bool>(&is_editable_node));
1530}
1531
1532void RenderViewHostImpl::OnAddMessageToConsole(
1533    int32 level,
1534    const string16& message,
1535    int32 line_no,
1536    const string16& source_id) {
1537  if (delegate_->AddMessageToConsole(level, message, line_no, source_id))
1538    return;
1539  // Pass through log level only on WebUI pages to limit console spew.
1540  int32 resolved_level = HasWebUIScheme(delegate_->GetURL()) ? level : 0;
1541
1542  if (resolved_level >= ::logging::GetMinLogLevel()) {
1543    logging::LogMessage("CONSOLE", line_no, resolved_level).stream() << "\"" <<
1544        message << "\", source: " << source_id << " (" << line_no << ")";
1545  }
1546}
1547
1548void RenderViewHostImpl::AddObserver(RenderViewHostObserver* observer) {
1549  observers_.AddObserver(observer);
1550}
1551
1552void RenderViewHostImpl::RemoveObserver(RenderViewHostObserver* observer) {
1553  observers_.RemoveObserver(observer);
1554}
1555
1556void RenderViewHostImpl::OnUserGesture() {
1557  delegate_->OnUserGesture();
1558}
1559
1560void RenderViewHostImpl::OnShouldCloseACK(
1561    bool proceed,
1562    const base::TimeTicks& renderer_before_unload_start_time,
1563    const base::TimeTicks& renderer_before_unload_end_time) {
1564  decrement_in_flight_event_count();
1565  StopHangMonitorTimeout();
1566  // If this renderer navigated while the beforeunload request was in flight, we
1567  // may have cleared this state in OnNavigate, in which case we can ignore
1568  // this message.
1569  if (!is_waiting_for_beforeunload_ack_ || is_swapped_out_)
1570    return;
1571
1572  is_waiting_for_beforeunload_ack_ = false;
1573
1574  RenderViewHostDelegate::RendererManagement* management_delegate =
1575      delegate_->GetRendererManagementDelegate();
1576  if (management_delegate) {
1577    base::TimeTicks before_unload_end_time;
1578    if (!send_should_close_start_time_.is_null() &&
1579        !renderer_before_unload_start_time.is_null() &&
1580        !renderer_before_unload_end_time.is_null()) {
1581      // When passing TimeTicks across process boundaries, we need to compensate
1582      // for any skew between the processes. Here we are converting the
1583      // renderer's notion of before_unload_end_time to TimeTicks in the browser
1584      // process. See comments in inter_process_time_ticks_converter.h for more.
1585      InterProcessTimeTicksConverter converter(
1586          LocalTimeTicks::FromTimeTicks(send_should_close_start_time_),
1587          LocalTimeTicks::FromTimeTicks(base::TimeTicks::Now()),
1588          RemoteTimeTicks::FromTimeTicks(renderer_before_unload_start_time),
1589          RemoteTimeTicks::FromTimeTicks(renderer_before_unload_end_time));
1590      LocalTimeTicks browser_before_unload_end_time =
1591          converter.ToLocalTimeTicks(
1592              RemoteTimeTicks::FromTimeTicks(renderer_before_unload_end_time));
1593      before_unload_end_time = browser_before_unload_end_time.ToTimeTicks();
1594    }
1595    management_delegate->ShouldClosePage(
1596        unload_ack_is_for_cross_site_transition_, proceed,
1597        before_unload_end_time);
1598  }
1599
1600  // If canceled, notify the delegate to cancel its pending navigation entry.
1601  if (!proceed)
1602    delegate_->DidCancelLoading();
1603}
1604
1605void RenderViewHostImpl::OnClosePageACK() {
1606  decrement_in_flight_event_count();
1607  ClosePageIgnoringUnloadEvents();
1608}
1609
1610void RenderViewHostImpl::NotifyRendererUnresponsive() {
1611  delegate_->RendererUnresponsive(
1612      this, is_waiting_for_beforeunload_ack_ || is_waiting_for_unload_ack_);
1613}
1614
1615void RenderViewHostImpl::NotifyRendererResponsive() {
1616  delegate_->RendererResponsive(this);
1617}
1618
1619void RenderViewHostImpl::RequestToLockMouse(bool user_gesture,
1620                                            bool last_unlocked_by_target) {
1621  delegate_->RequestToLockMouse(user_gesture, last_unlocked_by_target);
1622}
1623
1624bool RenderViewHostImpl::IsFullscreen() const {
1625  return delegate_->IsFullscreenForCurrentTab();
1626}
1627
1628void RenderViewHostImpl::OnFocus() {
1629  // Note: We allow focus and blur from swapped out RenderViewHosts, even when
1630  // the active RenderViewHost is in a different BrowsingInstance (e.g., WebUI).
1631  delegate_->Activate();
1632}
1633
1634void RenderViewHostImpl::OnBlur() {
1635  delegate_->Deactivate();
1636}
1637
1638gfx::Rect RenderViewHostImpl::GetRootWindowResizerRect() const {
1639  return delegate_->GetRootWindowResizerRect();
1640}
1641
1642void RenderViewHostImpl::ForwardMouseEvent(
1643    const WebKit::WebMouseEvent& mouse_event) {
1644
1645  // We make a copy of the mouse event because
1646  // RenderWidgetHost::ForwardMouseEvent will delete |mouse_event|.
1647  WebKit::WebMouseEvent event_copy(mouse_event);
1648  RenderWidgetHostImpl::ForwardMouseEvent(event_copy);
1649
1650  switch (event_copy.type) {
1651    case WebInputEvent::MouseMove:
1652      delegate_->HandleMouseMove();
1653      break;
1654    case WebInputEvent::MouseLeave:
1655      delegate_->HandleMouseLeave();
1656      break;
1657    case WebInputEvent::MouseDown:
1658      delegate_->HandleMouseDown();
1659      break;
1660    case WebInputEvent::MouseWheel:
1661      if (ignore_input_events())
1662        delegate_->OnIgnoredUIEvent();
1663      break;
1664    case WebInputEvent::MouseUp:
1665      delegate_->HandleMouseUp();
1666    default:
1667      // For now, we don't care about the rest.
1668      break;
1669  }
1670}
1671
1672void RenderViewHostImpl::OnPointerEventActivate() {
1673  delegate_->HandlePointerActivate();
1674}
1675
1676void RenderViewHostImpl::ForwardKeyboardEvent(
1677    const NativeWebKeyboardEvent& key_event) {
1678  if (ignore_input_events()) {
1679    if (key_event.type == WebInputEvent::RawKeyDown)
1680      delegate_->OnIgnoredUIEvent();
1681    return;
1682  }
1683  RenderWidgetHostImpl::ForwardKeyboardEvent(key_event);
1684}
1685
1686#if defined(OS_ANDROID)
1687void RenderViewHostImpl::DidSelectPopupMenuItems(
1688    const std::vector<int>& selected_indices) {
1689  Send(new ViewMsg_SelectPopupMenuItems(GetRoutingID(), false,
1690                                        selected_indices));
1691}
1692
1693void RenderViewHostImpl::DidCancelPopupMenu() {
1694  Send(new ViewMsg_SelectPopupMenuItems(GetRoutingID(), true,
1695                                        std::vector<int>()));
1696}
1697#endif
1698
1699#if defined(OS_MACOSX)
1700void RenderViewHostImpl::DidSelectPopupMenuItem(int selected_index) {
1701  Send(new ViewMsg_SelectPopupMenuItem(GetRoutingID(), selected_index));
1702}
1703
1704void RenderViewHostImpl::DidCancelPopupMenu() {
1705  Send(new ViewMsg_SelectPopupMenuItem(GetRoutingID(), -1));
1706}
1707#endif
1708
1709void RenderViewHostImpl::SendOrientationChangeEvent(int orientation) {
1710  Send(new ViewMsg_OrientationChangeEvent(GetRoutingID(), orientation));
1711}
1712
1713void RenderViewHostImpl::ToggleSpeechInput() {
1714  Send(new InputTagSpeechMsg_ToggleSpeechInput(GetRoutingID()));
1715}
1716
1717bool RenderViewHostImpl::CanCommitURL(const GURL& url) {
1718  // TODO(creis): We should also check for WebUI pages here.  Also, when the
1719  // out-of-process iframes implementation is ready, we should check for
1720  // cross-site URLs that are not allowed to commit in this process.
1721
1722  // Give the client a chance to disallow URLs from committing.
1723  return GetContentClient()->browser()->CanCommitURL(GetProcess(), url);
1724}
1725
1726void RenderViewHostImpl::FilterURL(ChildProcessSecurityPolicyImpl* policy,
1727                                   const RenderProcessHost* process,
1728                                   bool empty_allowed,
1729                                   GURL* url) {
1730  if (empty_allowed && url->is_empty())
1731    return;
1732
1733  // The browser process should never hear the swappedout:// URL from any
1734  // of the renderer's messages.  Check for this in debug builds, but don't
1735  // let it crash a release browser.
1736  DCHECK(GURL(kSwappedOutURL) != *url);
1737
1738  if (!url->is_valid()) {
1739    // Have to use about:blank for the denied case, instead of an empty GURL.
1740    // This is because the browser treats navigation to an empty GURL as a
1741    // navigation to the home page. This is often a privileged page
1742    // (chrome://newtab/) which is exactly what we don't want.
1743    *url = GURL(kAboutBlankURL);
1744    RecordAction(UserMetricsAction("FilterURLTermiate_Invalid"));
1745    return;
1746  }
1747
1748  if (url->SchemeIs(chrome::kAboutScheme)) {
1749    // The renderer treats all URLs in the about: scheme as being about:blank.
1750    // Canonicalize about: URLs to about:blank.
1751    *url = GURL(kAboutBlankURL);
1752    RecordAction(UserMetricsAction("FilterURLTermiate_About"));
1753  }
1754
1755  // Do not allow browser plugin guests to navigate to non-web URLs, since they
1756  // cannot swap processes or grant bindings.
1757  bool non_web_url_in_guest = process->IsGuest() &&
1758      !(url->is_valid() && policy->IsWebSafeScheme(url->scheme()));
1759
1760  if (non_web_url_in_guest || !policy->CanRequestURL(process->GetID(), *url)) {
1761    // If this renderer is not permitted to request this URL, we invalidate the
1762    // URL.  This prevents us from storing the blocked URL and becoming confused
1763    // later.
1764    VLOG(1) << "Blocked URL " << url->spec();
1765    *url = GURL(kAboutBlankURL);
1766    RecordAction(UserMetricsAction("FilterURLTermiate_Blocked"));
1767  }
1768}
1769
1770void RenderViewHost::AddCreatedCallback(const CreatedCallback& callback) {
1771  g_created_callbacks.Get().push_back(callback);
1772}
1773
1774void RenderViewHost::RemoveCreatedCallback(const CreatedCallback& callback) {
1775  for (size_t i = 0; i < g_created_callbacks.Get().size(); ++i) {
1776    if (g_created_callbacks.Get().at(i).Equals(callback)) {
1777      g_created_callbacks.Get().erase(g_created_callbacks.Get().begin() + i);
1778      return;
1779    }
1780  }
1781}
1782
1783void RenderViewHostImpl::SetAltErrorPageURL(const GURL& url) {
1784  Send(new ViewMsg_SetAltErrorPageURL(GetRoutingID(), url));
1785}
1786
1787void RenderViewHostImpl::ExitFullscreen() {
1788  RejectMouseLockOrUnlockIfNecessary();
1789  // We need to notify the contents that its fullscreen state has changed. This
1790  // is done as part of the resize message.
1791  WasResized();
1792}
1793
1794WebPreferences RenderViewHostImpl::GetWebkitPreferences() {
1795  return delegate_->GetWebkitPrefs();
1796}
1797
1798void RenderViewHostImpl::DisownOpener() {
1799  // This should only be called when swapped out.
1800  DCHECK(is_swapped_out_);
1801
1802  Send(new ViewMsg_DisownOpener(GetRoutingID()));
1803}
1804
1805void RenderViewHostImpl::SetAccessibilityLayoutCompleteCallbackForTesting(
1806    const base::Closure& callback) {
1807  accessibility_layout_callback_ = callback;
1808}
1809
1810void RenderViewHostImpl::SetAccessibilityLoadCompleteCallbackForTesting(
1811    const base::Closure& callback) {
1812  accessibility_load_callback_ = callback;
1813}
1814
1815void RenderViewHostImpl::SetAccessibilityOtherCallbackForTesting(
1816    const base::Closure& callback) {
1817  accessibility_other_callback_ = callback;
1818}
1819
1820void RenderViewHostImpl::UpdateWebkitPreferences(const WebPreferences& prefs) {
1821  Send(new ViewMsg_UpdateWebPreferences(GetRoutingID(), prefs));
1822}
1823
1824void RenderViewHostImpl::NotifyTimezoneChange() {
1825  Send(new ViewMsg_TimezoneChange(GetRoutingID()));
1826}
1827
1828void RenderViewHostImpl::ClearFocusedNode() {
1829  Send(new ViewMsg_ClearFocusedNode(GetRoutingID()));
1830}
1831
1832void RenderViewHostImpl::SetZoomLevel(double level) {
1833  Send(new ViewMsg_SetZoomLevel(GetRoutingID(), level));
1834}
1835
1836void RenderViewHostImpl::Zoom(PageZoom zoom) {
1837  Send(new ViewMsg_Zoom(GetRoutingID(), zoom));
1838}
1839
1840void RenderViewHostImpl::ReloadFrame() {
1841  Send(new ViewMsg_ReloadFrame(GetRoutingID()));
1842}
1843
1844void RenderViewHostImpl::Find(int request_id,
1845                              const string16& search_text,
1846                              const WebKit::WebFindOptions& options) {
1847  Send(new ViewMsg_Find(GetRoutingID(), request_id, search_text, options));
1848}
1849
1850void RenderViewHostImpl::InsertCSS(const string16& frame_xpath,
1851                                   const std::string& css) {
1852  Send(new ViewMsg_CSSInsertRequest(GetRoutingID(), frame_xpath, css));
1853}
1854
1855void RenderViewHostImpl::DisableScrollbarsForThreshold(const gfx::Size& size) {
1856  Send(new ViewMsg_DisableScrollbarsForSmallWindows(GetRoutingID(), size));
1857}
1858
1859void RenderViewHostImpl::EnablePreferredSizeMode() {
1860  Send(new ViewMsg_EnablePreferredSizeChangedMode(GetRoutingID()));
1861}
1862
1863void RenderViewHostImpl::EnableAutoResize(const gfx::Size& min_size,
1864                                          const gfx::Size& max_size) {
1865  SetShouldAutoResize(true);
1866  Send(new ViewMsg_EnableAutoResize(GetRoutingID(), min_size, max_size));
1867}
1868
1869void RenderViewHostImpl::DisableAutoResize(const gfx::Size& new_size) {
1870  SetShouldAutoResize(false);
1871  Send(new ViewMsg_DisableAutoResize(GetRoutingID(), new_size));
1872}
1873
1874void RenderViewHostImpl::ExecuteCustomContextMenuCommand(
1875    int action, const CustomContextMenuContext& context) {
1876  Send(new ViewMsg_CustomContextMenuAction(GetRoutingID(), context, action));
1877}
1878
1879void RenderViewHostImpl::NotifyContextMenuClosed(
1880    const CustomContextMenuContext& context) {
1881  Send(new ViewMsg_ContextMenuClosed(GetRoutingID(), context));
1882}
1883
1884void RenderViewHostImpl::CopyImageAt(int x, int y) {
1885  Send(new ViewMsg_CopyImageAt(GetRoutingID(), x, y));
1886}
1887
1888void RenderViewHostImpl::ExecuteMediaPlayerActionAtLocation(
1889  const gfx::Point& location, const WebKit::WebMediaPlayerAction& action) {
1890  Send(new ViewMsg_MediaPlayerActionAt(GetRoutingID(), location, action));
1891}
1892
1893void RenderViewHostImpl::ExecutePluginActionAtLocation(
1894  const gfx::Point& location, const WebKit::WebPluginAction& action) {
1895  Send(new ViewMsg_PluginActionAt(GetRoutingID(), location, action));
1896}
1897
1898void RenderViewHostImpl::DisassociateFromPopupCount() {
1899  Send(new ViewMsg_DisassociateFromPopupCount(GetRoutingID()));
1900}
1901
1902void RenderViewHostImpl::NotifyMoveOrResizeStarted() {
1903  Send(new ViewMsg_MoveOrResizeStarted(GetRoutingID()));
1904}
1905
1906void RenderViewHostImpl::StopFinding(StopFindAction action) {
1907  Send(new ViewMsg_StopFinding(GetRoutingID(), action));
1908}
1909
1910void RenderViewHostImpl::OnAccessibilityNotifications(
1911    const std::vector<AccessibilityHostMsg_NotificationParams>& params) {
1912  if (view_ && !is_swapped_out_)
1913    view_->OnAccessibilityNotifications(params);
1914
1915  for (unsigned i = 0; i < params.size(); i++) {
1916    const AccessibilityHostMsg_NotificationParams& param = params[i];
1917    AccessibilityNotification src_type = param.notification_type;
1918
1919    if ((src_type == AccessibilityNotificationLayoutComplete ||
1920         src_type == AccessibilityNotificationLoadComplete) &&
1921        save_accessibility_tree_for_testing_) {
1922      MakeAccessibilityNodeDataTree(param.nodes, &accessibility_tree_);
1923    }
1924
1925    if (src_type == AccessibilityNotificationLayoutComplete) {
1926      accessibility_layout_callback_.Run();
1927    } else if (src_type == AccessibilityNotificationLoadComplete) {
1928      accessibility_load_callback_.Run();
1929    } else {
1930      accessibility_other_callback_.Run();
1931    }
1932  }
1933
1934  Send(new AccessibilityMsg_Notifications_ACK(GetRoutingID()));
1935}
1936
1937void RenderViewHostImpl::OnScriptEvalResponse(int id,
1938                                              const base::ListValue& result) {
1939  const base::Value* result_value;
1940  if (!result.Get(0, &result_value)) {
1941    // Programming error or rogue renderer.
1942    NOTREACHED() << "Got bad arguments for OnScriptEvalResponse";
1943    return;
1944  }
1945
1946  std::map<int, JavascriptResultCallback>::iterator it =
1947      javascript_callbacks_.find(id);
1948  if (it != javascript_callbacks_.end()) {
1949    // ExecuteJavascriptInWebFrameCallbackResult was used; do callback.
1950    it->second.Run(result_value);
1951    javascript_callbacks_.erase(it);
1952  } else {
1953    NOTREACHED() << "Received script response for unknown request";
1954  }
1955}
1956
1957void RenderViewHostImpl::OnDidZoomURL(double zoom_level,
1958                                      bool remember,
1959                                      const GURL& url) {
1960  HostZoomMapImpl* host_zoom_map = static_cast<HostZoomMapImpl*>(
1961      HostZoomMap::GetForBrowserContext(GetProcess()->GetBrowserContext()));
1962  if (remember) {
1963    host_zoom_map->
1964        SetZoomLevelForHost(net::GetHostOrSpecFromURL(url), zoom_level);
1965  } else {
1966    host_zoom_map->SetTemporaryZoomLevel(
1967        GetProcess()->GetID(), GetRoutingID(), zoom_level);
1968  }
1969}
1970
1971void RenderViewHostImpl::OnMediaNotification(int64 player_cookie,
1972                                             bool has_video,
1973                                             bool has_audio,
1974                                             bool is_playing) {
1975  // Chrome OS does its own detection of audio and video.
1976#if !defined(OS_CHROMEOS)
1977  if (is_playing) {
1978    scoped_ptr<PowerSaveBlocker> blocker;
1979    if (has_video) {
1980      blocker = PowerSaveBlocker::Create(
1981          PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
1982          "Playing video");
1983    } else if (has_audio) {
1984      blocker = PowerSaveBlocker::Create(
1985          PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
1986          "Playing audio");
1987    }
1988
1989    if (blocker)
1990      power_save_blockers_[player_cookie] = blocker.release();
1991  } else {
1992    delete power_save_blockers_[player_cookie];
1993    power_save_blockers_.erase(player_cookie);
1994  }
1995#endif
1996}
1997
1998void RenderViewHostImpl::OnRequestDesktopNotificationPermission(
1999    const GURL& source_origin, int callback_context) {
2000  GetContentClient()->browser()->RequestDesktopNotificationPermission(
2001      source_origin, callback_context, GetProcess()->GetID(), GetRoutingID());
2002}
2003
2004void RenderViewHostImpl::OnShowDesktopNotification(
2005    const ShowDesktopNotificationHostMsgParams& params) {
2006  // Disallow HTML notifications from javascript: and file: schemes as this
2007  // allows unwanted cross-domain access.
2008  GURL url = params.contents_url;
2009  if (params.is_html &&
2010      (url.SchemeIs(chrome::kJavaScriptScheme) ||
2011       url.SchemeIs(chrome::kFileScheme))) {
2012    return;
2013  }
2014
2015  GetContentClient()->browser()->ShowDesktopNotification(
2016      params, GetProcess()->GetID(), GetRoutingID(), false);
2017}
2018
2019void RenderViewHostImpl::OnCancelDesktopNotification(int notification_id) {
2020  GetContentClient()->browser()->CancelDesktopNotification(
2021      GetProcess()->GetID(), GetRoutingID(), notification_id);
2022}
2023
2024void RenderViewHostImpl::OnRunFileChooser(const FileChooserParams& params) {
2025  delegate_->RunFileChooser(this, params);
2026}
2027
2028void RenderViewHostImpl::OnDidAccessInitialDocument() {
2029  has_accessed_initial_document_ = true;
2030  delegate_->DidAccessInitialDocument();
2031}
2032
2033void RenderViewHostImpl::OnDomOperationResponse(
2034    const std::string& json_string, int automation_id) {
2035  DomOperationNotificationDetails details(json_string, automation_id);
2036  NotificationService::current()->Notify(
2037      NOTIFICATION_DOM_OPERATION_RESPONSE,
2038      Source<RenderViewHost>(this),
2039      Details<DomOperationNotificationDetails>(&details));
2040}
2041
2042void RenderViewHostImpl::OnGetWindowSnapshot(const int snapshot_id) {
2043  std::vector<unsigned char> png;
2044
2045  // This feature is behind the kEnableGpuBenchmarking command line switch
2046  // because it poses security concerns and should only be used for testing.
2047  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
2048  if (command_line.HasSwitch(switches::kEnableGpuBenchmarking)) {
2049    gfx::Rect view_bounds = GetView()->GetViewBounds();
2050    gfx::Rect snapshot_bounds(view_bounds.size());
2051    gfx::Size snapshot_size = snapshot_bounds.size();
2052
2053    if (ui::GrabViewSnapshot(GetView()->GetNativeView(),
2054                             &png, snapshot_bounds)) {
2055      Send(new ViewMsg_WindowSnapshotCompleted(
2056          GetRoutingID(), snapshot_id, snapshot_size, png));
2057      return;
2058    }
2059  }
2060
2061  Send(new ViewMsg_WindowSnapshotCompleted(
2062      GetRoutingID(), snapshot_id, gfx::Size(), png));
2063}
2064
2065#if defined(OS_MACOSX) || defined(OS_ANDROID)
2066void RenderViewHostImpl::OnShowPopup(
2067    const ViewHostMsg_ShowPopup_Params& params) {
2068  RenderViewHostDelegateView* view = delegate_->GetDelegateView();
2069  if (view) {
2070    view->ShowPopupMenu(params.bounds,
2071                        params.item_height,
2072                        params.item_font_size,
2073                        params.selected_item,
2074                        params.popup_items,
2075                        params.right_aligned,
2076                        params.allow_multiple_selection);
2077  }
2078}
2079#endif
2080
2081void RenderViewHostImpl::SetSwappedOut(bool is_swapped_out) {
2082  is_swapped_out_ = is_swapped_out;
2083
2084  // Whenever we change swap out state, we should not be waiting for
2085  // beforeunload or unload acks.  We clear them here to be safe, since they
2086  // can cause navigations to be ignored in OnNavigate.
2087  is_waiting_for_beforeunload_ack_ = false;
2088  is_waiting_for_unload_ack_ = false;
2089  has_timed_out_on_unload_ = false;
2090}
2091
2092void RenderViewHostImpl::ClearPowerSaveBlockers() {
2093  STLDeleteValues(&power_save_blockers_);
2094}
2095
2096bool RenderViewHostImpl::CanAccessFilesOfPageState(
2097    const PageState& state) const {
2098  ChildProcessSecurityPolicyImpl* policy =
2099      ChildProcessSecurityPolicyImpl::GetInstance();
2100
2101  const std::vector<base::FilePath>& file_paths = state.GetReferencedFiles();
2102  for (std::vector<base::FilePath>::const_iterator file = file_paths.begin();
2103       file != file_paths.end(); ++file) {
2104    if (!policy->CanReadFile(GetProcess()->GetID(), *file))
2105      return false;
2106  }
2107  return true;
2108}
2109
2110}  // namespace content
2111