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