Home | History | Annotate | Download | only in renderer
      1 // Copyright 2013 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/renderer/render_frame_impl.h"
      6 
      7 #include <map>
      8 #include <string>
      9 
     10 #include "base/auto_reset.h"
     11 #include "base/command_line.h"
     12 #include "base/debug/alias.h"
     13 #include "base/debug/asan_invalid_access.h"
     14 #include "base/debug/dump_without_crashing.h"
     15 #include "base/i18n/char_iterator.h"
     16 #include "base/metrics/histogram.h"
     17 #include "base/process/kill.h"
     18 #include "base/process/process.h"
     19 #include "base/strings/string16.h"
     20 #include "base/strings/utf_string_conversions.h"
     21 #include "base/time/time.h"
     22 #include "content/child/appcache/appcache_dispatcher.h"
     23 #include "content/child/plugin_messages.h"
     24 #include "content/child/quota_dispatcher.h"
     25 #include "content/child/request_extra_data.h"
     26 #include "content/child/service_worker/service_worker_network_provider.h"
     27 #include "content/child/service_worker/service_worker_provider_context.h"
     28 #include "content/child/service_worker/web_service_worker_provider_impl.h"
     29 #include "content/child/web_socket_stream_handle_impl.h"
     30 #include "content/child/web_url_request_util.h"
     31 #include "content/child/webmessageportchannel_impl.h"
     32 #include "content/child/websocket_bridge.h"
     33 #include "content/child/weburlresponse_extradata_impl.h"
     34 #include "content/common/clipboard_messages.h"
     35 #include "content/common/frame_messages.h"
     36 #include "content/common/input_messages.h"
     37 #include "content/common/service_worker/service_worker_types.h"
     38 #include "content/common/socket_stream_handle_data.h"
     39 #include "content/common/swapped_out_messages.h"
     40 #include "content/common/view_messages.h"
     41 #include "content/public/common/bindings_policy.h"
     42 #include "content/public/common/content_constants.h"
     43 #include "content/public/common/content_switches.h"
     44 #include "content/public/common/context_menu_params.h"
     45 #include "content/public/common/url_constants.h"
     46 #include "content/public/common/url_utils.h"
     47 #include "content/public/renderer/browser_plugin_delegate.h"
     48 #include "content/public/renderer/content_renderer_client.h"
     49 #include "content/public/renderer/context_menu_client.h"
     50 #include "content/public/renderer/document_state.h"
     51 #include "content/public/renderer/navigation_state.h"
     52 #include "content/public/renderer/render_frame_observer.h"
     53 #include "content/renderer/accessibility/renderer_accessibility.h"
     54 #include "content/renderer/accessibility/renderer_accessibility_complete.h"
     55 #include "content/renderer/accessibility/renderer_accessibility_focus_only.h"
     56 #include "content/renderer/browser_plugin/browser_plugin.h"
     57 #include "content/renderer/browser_plugin/browser_plugin_manager.h"
     58 #include "content/renderer/child_frame_compositing_helper.h"
     59 #include "content/renderer/context_menu_params_builder.h"
     60 #include "content/renderer/devtools/devtools_agent.h"
     61 #include "content/renderer/dom_automation_controller.h"
     62 #include "content/renderer/dom_utils.h"
     63 #include "content/renderer/external_popup_menu.h"
     64 #include "content/renderer/geolocation_dispatcher.h"
     65 #include "content/renderer/history_controller.h"
     66 #include "content/renderer/history_serialization.h"
     67 #include "content/renderer/image_loading_helper.h"
     68 #include "content/renderer/ime_event_guard.h"
     69 #include "content/renderer/internal_document_state_data.h"
     70 #include "content/renderer/manifest/manifest_manager.h"
     71 #include "content/renderer/media/audio_renderer_mixer_manager.h"
     72 #include "content/renderer/media/crypto/encrypted_media_player_support_impl.h"
     73 #include "content/renderer/media/media_stream_dispatcher.h"
     74 #include "content/renderer/media/media_stream_renderer_factory.h"
     75 #include "content/renderer/media/midi_dispatcher.h"
     76 #include "content/renderer/media/render_media_log.h"
     77 #include "content/renderer/media/user_media_client_impl.h"
     78 #include "content/renderer/media/webcontentdecryptionmodule_impl.h"
     79 #include "content/renderer/media/webmediaplayer_ms.h"
     80 #include "content/renderer/notification_permission_dispatcher.h"
     81 #include "content/renderer/notification_provider.h"
     82 #include "content/renderer/npapi/plugin_channel_host.h"
     83 #include "content/renderer/push_messaging_dispatcher.h"
     84 #include "content/renderer/render_frame_proxy.h"
     85 #include "content/renderer/render_process.h"
     86 #include "content/renderer/render_thread_impl.h"
     87 #include "content/renderer/render_view_impl.h"
     88 #include "content/renderer/render_widget_fullscreen_pepper.h"
     89 #include "content/renderer/renderer_webapplicationcachehost_impl.h"
     90 #include "content/renderer/renderer_webcolorchooser_impl.h"
     91 #include "content/renderer/screen_orientation/screen_orientation_dispatcher.h"
     92 #include "content/renderer/shared_worker_repository.h"
     93 #include "content/renderer/v8_value_converter_impl.h"
     94 #include "content/renderer/websharedworker_proxy.h"
     95 #include "media/base/audio_renderer_mixer_input.h"
     96 #include "media/blink/webmediaplayer_impl.h"
     97 #include "media/blink/webmediaplayer_params.h"
     98 #include "media/filters/gpu_video_accelerator_factories.h"
     99 #include "net/base/data_url.h"
    100 #include "net/base/net_errors.h"
    101 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
    102 #include "net/http/http_util.h"
    103 #include "third_party/WebKit/public/platform/WebStorageQuotaCallbacks.h"
    104 #include "third_party/WebKit/public/platform/WebString.h"
    105 #include "third_party/WebKit/public/platform/WebURL.h"
    106 #include "third_party/WebKit/public/platform/WebURLError.h"
    107 #include "third_party/WebKit/public/platform/WebURLResponse.h"
    108 #include "third_party/WebKit/public/platform/WebVector.h"
    109 #include "third_party/WebKit/public/web/WebColorSuggestion.h"
    110 #include "third_party/WebKit/public/web/WebDocument.h"
    111 #include "third_party/WebKit/public/web/WebGlyphCache.h"
    112 #include "third_party/WebKit/public/web/WebLocalFrame.h"
    113 #include "third_party/WebKit/public/web/WebMediaStreamRegistry.h"
    114 #include "third_party/WebKit/public/web/WebNavigationPolicy.h"
    115 #include "third_party/WebKit/public/web/WebPlugin.h"
    116 #include "third_party/WebKit/public/web/WebPluginParams.h"
    117 #include "third_party/WebKit/public/web/WebRange.h"
    118 #include "third_party/WebKit/public/web/WebScriptSource.h"
    119 #include "third_party/WebKit/public/web/WebSearchableFormData.h"
    120 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
    121 #include "third_party/WebKit/public/web/WebSecurityPolicy.h"
    122 #include "third_party/WebKit/public/web/WebSurroundingText.h"
    123 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
    124 #include "third_party/WebKit/public/web/WebView.h"
    125 
    126 #if defined(ENABLE_PLUGINS)
    127 #include "content/renderer/npapi/webplugin_impl.h"
    128 #include "content/renderer/pepper/pepper_browser_connection.h"
    129 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
    130 #include "content/renderer/pepper/pepper_webplugin_impl.h"
    131 #include "content/renderer/pepper/plugin_module.h"
    132 #endif
    133 
    134 #if defined(ENABLE_WEBRTC)
    135 #include "content/renderer/media/rtc_peer_connection_handler.h"
    136 #endif
    137 
    138 #if defined(OS_ANDROID)
    139 #include <cpu-features.h>
    140 
    141 #include "content/common/gpu/client/context_provider_command_buffer.h"
    142 #include "content/renderer/android/synchronous_compositor_factory.h"
    143 #include "content/renderer/java/gin_java_bridge_dispatcher.h"
    144 #include "content/renderer/media/android/renderer_media_player_manager.h"
    145 #include "content/renderer/media/android/stream_texture_factory_impl.h"
    146 #include "content/renderer/media/android/webmediaplayer_android.h"
    147 #endif
    148 
    149 #if defined(ENABLE_BROWSER_CDMS)
    150 #include "content/renderer/media/crypto/renderer_cdm_manager.h"
    151 #endif
    152 
    153 using blink::WebContextMenuData;
    154 using blink::WebData;
    155 using blink::WebDataSource;
    156 using blink::WebDocument;
    157 using blink::WebElement;
    158 using blink::WebExternalPopupMenu;
    159 using blink::WebExternalPopupMenuClient;
    160 using blink::WebFrame;
    161 using blink::WebHistoryItem;
    162 using blink::WebHTTPBody;
    163 using blink::WebLocalFrame;
    164 using blink::WebMediaPlayer;
    165 using blink::WebMediaPlayerClient;
    166 using blink::WebNavigationPolicy;
    167 using blink::WebNavigationType;
    168 using blink::WebNode;
    169 using blink::WebPluginParams;
    170 using blink::WebPopupMenuInfo;
    171 using blink::WebRange;
    172 using blink::WebReferrerPolicy;
    173 using blink::WebScriptSource;
    174 using blink::WebSearchableFormData;
    175 using blink::WebSecurityOrigin;
    176 using blink::WebSecurityPolicy;
    177 using blink::WebServiceWorkerProvider;
    178 using blink::WebStorageQuotaCallbacks;
    179 using blink::WebString;
    180 using blink::WebURL;
    181 using blink::WebURLError;
    182 using blink::WebURLRequest;
    183 using blink::WebURLResponse;
    184 using blink::WebUserGestureIndicator;
    185 using blink::WebVector;
    186 using blink::WebView;
    187 using base::Time;
    188 using base::TimeDelta;
    189 
    190 namespace content {
    191 
    192 namespace {
    193 
    194 const char kDefaultAcceptHeader[] =
    195     "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/"
    196     "*;q=0.8";
    197 const char kAcceptHeader[] = "Accept";
    198 
    199 const size_t kExtraCharsBeforeAndAfterSelection = 100;
    200 
    201 typedef std::map<int, RenderFrameImpl*> RoutingIDFrameMap;
    202 static base::LazyInstance<RoutingIDFrameMap> g_routing_id_frame_map =
    203     LAZY_INSTANCE_INITIALIZER;
    204 
    205 typedef std::map<blink::WebFrame*, RenderFrameImpl*> FrameMap;
    206 base::LazyInstance<FrameMap> g_frame_map = LAZY_INSTANCE_INITIALIZER;
    207 
    208 int64 ExtractPostId(const WebHistoryItem& item) {
    209   if (item.isNull())
    210     return -1;
    211 
    212   if (item.httpBody().isNull())
    213     return -1;
    214 
    215   return item.httpBody().identifier();
    216 }
    217 
    218 WebURLResponseExtraDataImpl* GetExtraDataFromResponse(
    219     const WebURLResponse& response) {
    220   return static_cast<WebURLResponseExtraDataImpl*>(response.extraData());
    221 }
    222 
    223 void GetRedirectChain(WebDataSource* ds, std::vector<GURL>* result) {
    224   // Replace any occurrences of swappedout:// with about:blank.
    225   const WebURL& blank_url = GURL(url::kAboutBlankURL);
    226   WebVector<WebURL> urls;
    227   ds->redirectChain(urls);
    228   result->reserve(urls.size());
    229   for (size_t i = 0; i < urls.size(); ++i) {
    230     if (urls[i] != GURL(kSwappedOutURL))
    231       result->push_back(urls[i]);
    232     else
    233       result->push_back(blank_url);
    234   }
    235 }
    236 
    237 // Returns the original request url. If there is no redirect, the original
    238 // url is the same as ds->request()->url(). If the WebDataSource belongs to a
    239 // frame was loaded by loadData, the original url will be ds->unreachableURL()
    240 static GURL GetOriginalRequestURL(WebDataSource* ds) {
    241   // WebDataSource has unreachable URL means that the frame is loaded through
    242   // blink::WebFrame::loadData(), and the base URL will be in the redirect
    243   // chain. However, we never visited the baseURL. So in this case, we should
    244   // use the unreachable URL as the original URL.
    245   if (ds->hasUnreachableURL())
    246     return ds->unreachableURL();
    247 
    248   std::vector<GURL> redirects;
    249   GetRedirectChain(ds, &redirects);
    250   if (!redirects.empty())
    251     return redirects.at(0);
    252 
    253   return ds->originalRequest().url();
    254 }
    255 
    256 NOINLINE static void CrashIntentionally() {
    257   // NOTE(shess): Crash directly rather than using NOTREACHED() so
    258   // that the signature is easier to triage in crash reports.
    259   volatile int* zero = NULL;
    260   *zero = 0;
    261 }
    262 
    263 #if defined(ADDRESS_SANITIZER) || defined(SYZYASAN)
    264 NOINLINE static void MaybeTriggerAsanError(const GURL& url) {
    265   // NOTE(rogerm): We intentionally perform an invalid heap access here in
    266   //     order to trigger an Address Sanitizer (ASAN) error report.
    267   const char kCrashDomain[] = "crash";
    268   const char kHeapOverflow[] = "/heap-overflow";
    269   const char kHeapUnderflow[] = "/heap-underflow";
    270   const char kUseAfterFree[] = "/use-after-free";
    271 #if defined(SYZYASAN)
    272   const char kCorruptHeapBlock[] = "/corrupt-heap-block";
    273   const char kCorruptHeap[] = "/corrupt-heap";
    274 #endif
    275 
    276   if (!url.DomainIs(kCrashDomain, sizeof(kCrashDomain) - 1))
    277     return;
    278 
    279   if (!url.has_path())
    280     return;
    281 
    282   std::string crash_type(url.path());
    283   if (crash_type == kHeapOverflow) {
    284     base::debug::AsanHeapOverflow();
    285   } else if (crash_type == kHeapUnderflow ) {
    286     base::debug::AsanHeapUnderflow();
    287   } else if (crash_type == kUseAfterFree) {
    288     base::debug::AsanHeapUseAfterFree();
    289 #if defined(SYZYASAN)
    290   } else if (crash_type == kCorruptHeapBlock) {
    291     base::debug::AsanCorruptHeapBlock();
    292   } else if (crash_type == kCorruptHeap) {
    293     base::debug::AsanCorruptHeap();
    294 #endif
    295   }
    296 }
    297 #endif  // ADDRESS_SANITIZER || SYZYASAN
    298 
    299 static void MaybeHandleDebugURL(const GURL& url) {
    300   if (!url.SchemeIs(kChromeUIScheme))
    301     return;
    302   if (url == GURL(kChromeUICrashURL)) {
    303     CrashIntentionally();
    304   } else if (url == GURL(kChromeUIDumpURL)) {
    305     // This URL will only correctly create a crash dump file if content is
    306     // hosted in a process that has correctly called
    307     // base::debug::SetDumpWithoutCrashingFunction.  Refer to the documentation
    308     // of base::debug::DumpWithoutCrashing for more details.
    309     base::debug::DumpWithoutCrashing();
    310   } else if (url == GURL(kChromeUIKillURL)) {
    311     base::KillProcess(base::GetCurrentProcessHandle(), 1, false);
    312   } else if (url == GURL(kChromeUIHangURL)) {
    313     for (;;) {
    314       base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
    315     }
    316   } else if (url == GURL(kChromeUIShorthangURL)) {
    317     base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(20));
    318   }
    319 
    320 #if defined(ADDRESS_SANITIZER) || defined(SYZYASAN)
    321   MaybeTriggerAsanError(url);
    322 #endif  // ADDRESS_SANITIZER || SYZYASAN
    323 }
    324 
    325 // Returns false unless this is a top-level navigation.
    326 static bool IsTopLevelNavigation(WebFrame* frame) {
    327   return frame->parent() == NULL;
    328 }
    329 
    330 // Returns false unless this is a top-level navigation that crosses origins.
    331 static bool IsNonLocalTopLevelNavigation(const GURL& url,
    332                                          WebFrame* frame,
    333                                          WebNavigationType type,
    334                                          bool is_form_post) {
    335   if (!IsTopLevelNavigation(frame))
    336     return false;
    337 
    338   // Navigations initiated within Webkit are not sent out to the external host
    339   // in the following cases.
    340   // 1. The url scheme is not http/https
    341   // 2. The origin of the url and the opener is the same in which case the
    342   //    opener relationship is maintained.
    343   // 3. Reloads/form submits/back forward navigations
    344   if (!url.SchemeIs(url::kHttpScheme) && !url.SchemeIs(url::kHttpsScheme))
    345     return false;
    346 
    347   if (type != blink::WebNavigationTypeReload &&
    348       type != blink::WebNavigationTypeBackForward && !is_form_post) {
    349     // The opener relationship between the new window and the parent allows the
    350     // new window to script the parent and vice versa. This is not allowed if
    351     // the origins of the two domains are different. This can be treated as a
    352     // top level navigation and routed back to the host.
    353     blink::WebFrame* opener = frame->opener();
    354     if (!opener)
    355       return true;
    356 
    357     if (url.GetOrigin() != GURL(opener->document().url()).GetOrigin())
    358       return true;
    359   }
    360   return false;
    361 }
    362 
    363 }  // namespace
    364 
    365 static RenderFrameImpl* (*g_create_render_frame_impl)(RenderViewImpl*, int32) =
    366     NULL;
    367 
    368 // static
    369 RenderFrameImpl* RenderFrameImpl::Create(RenderViewImpl* render_view,
    370                                          int32 routing_id) {
    371   DCHECK(routing_id != MSG_ROUTING_NONE);
    372 
    373   if (g_create_render_frame_impl)
    374     return g_create_render_frame_impl(render_view, routing_id);
    375   else
    376     return new RenderFrameImpl(render_view, routing_id);
    377 }
    378 
    379 // static
    380 RenderFrameImpl* RenderFrameImpl::FromRoutingID(int32 routing_id) {
    381   RoutingIDFrameMap::iterator iter =
    382       g_routing_id_frame_map.Get().find(routing_id);
    383   if (iter != g_routing_id_frame_map.Get().end())
    384     return iter->second;
    385   return NULL;
    386 }
    387 
    388 // static
    389 void RenderFrameImpl::CreateFrame(int routing_id, int parent_routing_id) {
    390   // TODO(nasko): For now, this message is only sent for subframes, as the
    391   // top level frame is created when the RenderView is created through the
    392   // ViewMsg_New IPC.
    393   CHECK_NE(MSG_ROUTING_NONE, parent_routing_id);
    394 
    395   RenderFrameProxy* proxy = RenderFrameProxy::FromRoutingID(parent_routing_id);
    396 
    397   // If the browser is sending a valid parent routing id, it should already be
    398   // created and registered.
    399   CHECK(proxy);
    400   blink::WebRemoteFrame* parent_web_frame = proxy->web_frame();
    401 
    402   // Create the RenderFrame and WebLocalFrame, linking the two.
    403   RenderFrameImpl* render_frame =
    404       RenderFrameImpl::Create(proxy->render_view(), routing_id);
    405   blink::WebLocalFrame* web_frame =
    406       parent_web_frame->createLocalChild("", render_frame);
    407   render_frame->SetWebFrame(web_frame);
    408   render_frame->Initialize();
    409 }
    410 
    411 // static
    412 RenderFrame* RenderFrame::FromWebFrame(blink::WebFrame* web_frame) {
    413   return RenderFrameImpl::FromWebFrame(web_frame);
    414 }
    415 
    416 // static
    417 RenderFrameImpl* RenderFrameImpl::FromWebFrame(blink::WebFrame* web_frame) {
    418   FrameMap::iterator iter = g_frame_map.Get().find(web_frame);
    419   if (iter != g_frame_map.Get().end())
    420     return iter->second;
    421   return NULL;
    422 }
    423 
    424 // static
    425 void RenderFrameImpl::InstallCreateHook(
    426     RenderFrameImpl* (*create_render_frame_impl)(RenderViewImpl*, int32)) {
    427   CHECK(!g_create_render_frame_impl);
    428   g_create_render_frame_impl = create_render_frame_impl;
    429 }
    430 
    431 // RenderFrameImpl ----------------------------------------------------------
    432 RenderFrameImpl::RenderFrameImpl(RenderViewImpl* render_view, int routing_id)
    433     : frame_(NULL),
    434       render_view_(render_view->AsWeakPtr()),
    435       routing_id_(routing_id),
    436       is_swapped_out_(false),
    437       render_frame_proxy_(NULL),
    438       is_detaching_(false),
    439       cookie_jar_(this),
    440       selection_text_offset_(0),
    441       selection_range_(gfx::Range::InvalidRange()),
    442       handling_select_range_(false),
    443       notification_permission_dispatcher_(NULL),
    444       notification_provider_(NULL),
    445       web_user_media_client_(NULL),
    446       midi_dispatcher_(NULL),
    447 #if defined(OS_ANDROID)
    448       media_player_manager_(NULL),
    449 #endif
    450 #if defined(ENABLE_BROWSER_CDMS)
    451       cdm_manager_(NULL),
    452 #endif
    453 #if defined(VIDEO_HOLE)
    454       contains_media_player_(false),
    455 #endif
    456       geolocation_dispatcher_(NULL),
    457       push_messaging_dispatcher_(NULL),
    458       screen_orientation_dispatcher_(NULL),
    459       manifest_manager_(NULL),
    460       accessibility_mode_(AccessibilityModeOff),
    461       renderer_accessibility_(NULL),
    462       weak_factory_(this) {
    463   std::pair<RoutingIDFrameMap::iterator, bool> result =
    464       g_routing_id_frame_map.Get().insert(std::make_pair(routing_id_, this));
    465   CHECK(result.second) << "Inserting a duplicate item.";
    466 
    467   RenderThread::Get()->AddRoute(routing_id_, this);
    468 
    469   render_view_->RegisterRenderFrame(this);
    470 
    471 #if defined(OS_ANDROID)
    472   new GinJavaBridgeDispatcher(this);
    473 #endif
    474 
    475 #if defined(ENABLE_NOTIFICATIONS)
    476   notification_provider_ = new NotificationProvider(this);
    477 #endif
    478 
    479   manifest_manager_ = new ManifestManager(this);
    480 }
    481 
    482 RenderFrameImpl::~RenderFrameImpl() {
    483   FOR_EACH_OBSERVER(RenderFrameObserver, observers_, RenderFrameGone());
    484   FOR_EACH_OBSERVER(RenderFrameObserver, observers_, OnDestruct());
    485 
    486 #if defined(VIDEO_HOLE)
    487   if (contains_media_player_)
    488     render_view_->UnregisterVideoHoleFrame(this);
    489 #endif
    490 
    491   render_view_->UnregisterRenderFrame(this);
    492   g_routing_id_frame_map.Get().erase(routing_id_);
    493   RenderThread::Get()->RemoveRoute(routing_id_);
    494 }
    495 
    496 void RenderFrameImpl::SetWebFrame(blink::WebLocalFrame* web_frame) {
    497   DCHECK(!frame_);
    498 
    499   std::pair<FrameMap::iterator, bool> result = g_frame_map.Get().insert(
    500       std::make_pair(web_frame, this));
    501   CHECK(result.second) << "Inserting a duplicate item.";
    502 
    503   frame_ = web_frame;
    504 }
    505 
    506 void RenderFrameImpl::Initialize() {
    507 #if defined(ENABLE_PLUGINS)
    508   new PepperBrowserConnection(this);
    509 #endif
    510   new SharedWorkerRepository(this);
    511 
    512   if (!frame_->parent())
    513     new ImageLoadingHelper(this);
    514 
    515   // We delay calling this until we have the WebFrame so that any observer or
    516   // embedder can call GetWebFrame on any RenderFrame.
    517   GetContentClient()->renderer()->RenderFrameCreated(this);
    518 }
    519 
    520 RenderWidget* RenderFrameImpl::GetRenderWidget() {
    521   return render_view_.get();
    522 }
    523 
    524 #if defined(ENABLE_PLUGINS)
    525 void RenderFrameImpl::PepperPluginCreated(RendererPpapiHost* host) {
    526   FOR_EACH_OBSERVER(RenderFrameObserver, observers_,
    527                     DidCreatePepperPlugin(host));
    528 }
    529 
    530 void RenderFrameImpl::PepperDidChangeCursor(
    531     PepperPluginInstanceImpl* instance,
    532     const blink::WebCursorInfo& cursor) {
    533   // Update the cursor appearance immediately if the requesting plugin is the
    534   // one which receives the last mouse event. Otherwise, the new cursor won't be
    535   // picked up until the plugin gets the next input event. That is bad if, e.g.,
    536   // the plugin would like to set an invisible cursor when there isn't any user
    537   // input for a while.
    538   if (instance == render_view_->pepper_last_mouse_event_target())
    539     GetRenderWidget()->didChangeCursor(cursor);
    540 }
    541 
    542 void RenderFrameImpl::PepperDidReceiveMouseEvent(
    543     PepperPluginInstanceImpl* instance) {
    544   render_view_->set_pepper_last_mouse_event_target(instance);
    545 }
    546 
    547 void RenderFrameImpl::PepperTextInputTypeChanged(
    548     PepperPluginInstanceImpl* instance) {
    549   if (instance != render_view_->focused_pepper_plugin())
    550     return;
    551 
    552   GetRenderWidget()->UpdateTextInputType();
    553   if (renderer_accessibility())
    554     renderer_accessibility()->FocusedNodeChanged(WebNode());
    555 }
    556 
    557 void RenderFrameImpl::PepperCaretPositionChanged(
    558     PepperPluginInstanceImpl* instance) {
    559   if (instance != render_view_->focused_pepper_plugin())
    560     return;
    561   GetRenderWidget()->UpdateSelectionBounds();
    562 }
    563 
    564 void RenderFrameImpl::PepperCancelComposition(
    565     PepperPluginInstanceImpl* instance) {
    566   if (instance != render_view_->focused_pepper_plugin())
    567     return;
    568   Send(new InputHostMsg_ImeCancelComposition(render_view_->GetRoutingID()));;
    569 #if defined(OS_MACOSX) || defined(USE_AURA)
    570   GetRenderWidget()->UpdateCompositionInfo(true);
    571 #endif
    572 }
    573 
    574 void RenderFrameImpl::PepperSelectionChanged(
    575     PepperPluginInstanceImpl* instance) {
    576   if (instance != render_view_->focused_pepper_plugin())
    577     return;
    578   SyncSelectionIfRequired();
    579 }
    580 
    581 RenderWidgetFullscreenPepper* RenderFrameImpl::CreatePepperFullscreenContainer(
    582     PepperPluginInstanceImpl* plugin) {
    583   GURL active_url;
    584   if (render_view_->webview() && render_view_->webview()->mainFrame())
    585     active_url = GURL(render_view_->webview()->mainFrame()->document().url());
    586   RenderWidgetFullscreenPepper* widget = RenderWidgetFullscreenPepper::Create(
    587       GetRenderWidget()->routing_id(), plugin, active_url,
    588       GetRenderWidget()->screenInfo());
    589   widget->show(blink::WebNavigationPolicyIgnore);
    590   return widget;
    591 }
    592 
    593 bool RenderFrameImpl::IsPepperAcceptingCompositionEvents() const {
    594   if (!render_view_->focused_pepper_plugin())
    595     return false;
    596   return render_view_->focused_pepper_plugin()->
    597       IsPluginAcceptingCompositionEvents();
    598 }
    599 
    600 void RenderFrameImpl::PluginCrashed(const base::FilePath& plugin_path,
    601                                    base::ProcessId plugin_pid) {
    602   // TODO(jam): dispatch this IPC in RenderFrameHost and switch to use
    603   // routing_id_ as a result.
    604   Send(new FrameHostMsg_PluginCrashed(routing_id_, plugin_path, plugin_pid));
    605 }
    606 
    607 void RenderFrameImpl::SimulateImeSetComposition(
    608     const base::string16& text,
    609     const std::vector<blink::WebCompositionUnderline>& underlines,
    610     int selection_start,
    611     int selection_end) {
    612   render_view_->OnImeSetComposition(
    613       text, underlines, selection_start, selection_end);
    614 }
    615 
    616 void RenderFrameImpl::SimulateImeConfirmComposition(
    617     const base::string16& text,
    618     const gfx::Range& replacement_range) {
    619   render_view_->OnImeConfirmComposition(text, replacement_range, false);
    620 }
    621 
    622 
    623 void RenderFrameImpl::OnImeSetComposition(
    624     const base::string16& text,
    625     const std::vector<blink::WebCompositionUnderline>& underlines,
    626     int selection_start,
    627     int selection_end) {
    628   // When a PPAPI plugin has focus, we bypass WebKit.
    629   if (!IsPepperAcceptingCompositionEvents()) {
    630     pepper_composition_text_ = text;
    631   } else {
    632     // TODO(kinaba) currently all composition events are sent directly to
    633     // plugins. Use DOM event mechanism after WebKit is made aware about
    634     // plugins that support composition.
    635     // The code below mimics the behavior of WebCore::Editor::setComposition.
    636 
    637     // Empty -> nonempty: composition started.
    638     if (pepper_composition_text_.empty() && !text.empty()) {
    639       render_view_->focused_pepper_plugin()->HandleCompositionStart(
    640           base::string16());
    641     }
    642     // Nonempty -> empty: composition canceled.
    643     if (!pepper_composition_text_.empty() && text.empty()) {
    644       render_view_->focused_pepper_plugin()->HandleCompositionEnd(
    645           base::string16());
    646     }
    647     pepper_composition_text_ = text;
    648     // Nonempty: composition is ongoing.
    649     if (!pepper_composition_text_.empty()) {
    650       render_view_->focused_pepper_plugin()->HandleCompositionUpdate(
    651           pepper_composition_text_, underlines, selection_start,
    652           selection_end);
    653     }
    654   }
    655 }
    656 
    657 void RenderFrameImpl::OnImeConfirmComposition(
    658     const base::string16& text,
    659     const gfx::Range& replacement_range,
    660     bool keep_selection) {
    661   // When a PPAPI plugin has focus, we bypass WebKit.
    662   // Here, text.empty() has a special meaning. It means to commit the last
    663   // update of composition text (see
    664   // RenderWidgetHost::ImeConfirmComposition()).
    665   const base::string16& last_text = text.empty() ? pepper_composition_text_
    666                                                  : text;
    667 
    668   // last_text is empty only when both text and pepper_composition_text_ is.
    669   // Ignore it.
    670   if (last_text.empty())
    671     return;
    672 
    673   if (!IsPepperAcceptingCompositionEvents()) {
    674     base::i18n::UTF16CharIterator iterator(&last_text);
    675     int32 i = 0;
    676     while (iterator.Advance()) {
    677       blink::WebKeyboardEvent char_event;
    678       char_event.type = blink::WebInputEvent::Char;
    679       char_event.timeStampSeconds = base::Time::Now().ToDoubleT();
    680       char_event.modifiers = 0;
    681       char_event.windowsKeyCode = last_text[i];
    682       char_event.nativeKeyCode = last_text[i];
    683 
    684       const int32 char_start = i;
    685       for (; i < iterator.array_pos(); ++i) {
    686         char_event.text[i - char_start] = last_text[i];
    687         char_event.unmodifiedText[i - char_start] = last_text[i];
    688       }
    689 
    690       if (GetRenderWidget()->webwidget())
    691         GetRenderWidget()->webwidget()->handleInputEvent(char_event);
    692     }
    693   } else {
    694     // Mimics the order of events sent by WebKit.
    695     // See WebCore::Editor::setComposition() for the corresponding code.
    696     render_view_->focused_pepper_plugin()->HandleCompositionEnd(last_text);
    697     render_view_->focused_pepper_plugin()->HandleTextInput(last_text);
    698   }
    699   pepper_composition_text_.clear();
    700 }
    701 
    702 #endif  // ENABLE_PLUGINS
    703 
    704 MediaStreamDispatcher* RenderFrameImpl::GetMediaStreamDispatcher() {
    705   if (!web_user_media_client_)
    706     InitializeUserMediaClient();
    707   return web_user_media_client_ ?
    708       web_user_media_client_->media_stream_dispatcher() : NULL;
    709 }
    710 
    711 bool RenderFrameImpl::Send(IPC::Message* message) {
    712   if (is_detaching_) {
    713     delete message;
    714     return false;
    715   }
    716   if (frame_->parent() == NULL &&
    717       (is_swapped_out_ || render_view_->is_swapped_out())) {
    718     if (!SwappedOutMessages::CanSendWhileSwappedOut(message)) {
    719       delete message;
    720       return false;
    721     }
    722 
    723     // In most cases, send IPCs through the proxy when swapped out. In some
    724     // calls the associated RenderViewImpl routing id is used to send
    725     // messages, so don't use the proxy.
    726     if (render_frame_proxy_ && message->routing_id() == routing_id_)
    727       return render_frame_proxy_->Send(message);
    728   }
    729 
    730   return RenderThread::Get()->Send(message);
    731 }
    732 
    733 #if defined(OS_MACOSX) || defined(OS_ANDROID)
    734 void RenderFrameImpl::DidHideExternalPopupMenu() {
    735   // We need to clear external_popup_menu_ as soon as ExternalPopupMenu::close
    736   // is called. Otherwise, createExternalPopupMenu() for new popup will fail.
    737   external_popup_menu_.reset();
    738 }
    739 #endif
    740 
    741 bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) {
    742   // TODO(kenrb): document() should not be null, but as a transitional step
    743   // we have RenderFrameProxy 'wrapping' a RenderFrameImpl, passing messages
    744   // to this method. This happens for a top-level remote frame, where a
    745   // document-less RenderFrame is replaced by a RenderFrameProxy but kept
    746   // around and is still able to receive messages.
    747   if (!frame_->document().isNull())
    748     GetContentClient()->SetActiveURL(frame_->document().url());
    749 
    750   ObserverListBase<RenderFrameObserver>::Iterator it(observers_);
    751   RenderFrameObserver* observer;
    752   while ((observer = it.GetNext()) != NULL) {
    753     if (observer->OnMessageReceived(msg))
    754       return true;
    755   }
    756 
    757   bool handled = true;
    758   IPC_BEGIN_MESSAGE_MAP(RenderFrameImpl, msg)
    759     IPC_MESSAGE_HANDLER(FrameMsg_Navigate, OnNavigate)
    760     IPC_MESSAGE_HANDLER(FrameMsg_BeforeUnload, OnBeforeUnload)
    761     IPC_MESSAGE_HANDLER(FrameMsg_SwapOut, OnSwapOut)
    762     IPC_MESSAGE_HANDLER(FrameMsg_Stop, OnStop)
    763     IPC_MESSAGE_HANDLER(FrameMsg_ContextMenuClosed, OnContextMenuClosed)
    764     IPC_MESSAGE_HANDLER(FrameMsg_CustomContextMenuAction,
    765                         OnCustomContextMenuAction)
    766     IPC_MESSAGE_HANDLER(InputMsg_Undo, OnUndo)
    767     IPC_MESSAGE_HANDLER(InputMsg_Redo, OnRedo)
    768     IPC_MESSAGE_HANDLER(InputMsg_Cut, OnCut)
    769     IPC_MESSAGE_HANDLER(InputMsg_Copy, OnCopy)
    770     IPC_MESSAGE_HANDLER(InputMsg_Paste, OnPaste)
    771     IPC_MESSAGE_HANDLER(InputMsg_PasteAndMatchStyle, OnPasteAndMatchStyle)
    772     IPC_MESSAGE_HANDLER(InputMsg_Delete, OnDelete)
    773     IPC_MESSAGE_HANDLER(InputMsg_SelectAll, OnSelectAll)
    774     IPC_MESSAGE_HANDLER(InputMsg_SelectRange, OnSelectRange)
    775     IPC_MESSAGE_HANDLER(InputMsg_Unselect, OnUnselect)
    776     IPC_MESSAGE_HANDLER(InputMsg_Replace, OnReplace)
    777     IPC_MESSAGE_HANDLER(InputMsg_ReplaceMisspelling, OnReplaceMisspelling)
    778     IPC_MESSAGE_HANDLER(InputMsg_ExtendSelectionAndDelete,
    779                         OnExtendSelectionAndDelete)
    780     IPC_MESSAGE_HANDLER(InputMsg_SetCompositionFromExistingText,
    781                         OnSetCompositionFromExistingText)
    782     IPC_MESSAGE_HANDLER(FrameMsg_CSSInsertRequest, OnCSSInsertRequest)
    783     IPC_MESSAGE_HANDLER(FrameMsg_JavaScriptExecuteRequest,
    784                         OnJavaScriptExecuteRequest)
    785     IPC_MESSAGE_HANDLER(FrameMsg_JavaScriptExecuteRequestForTests,
    786                         OnJavaScriptExecuteRequestForTests)
    787     IPC_MESSAGE_HANDLER(FrameMsg_SetEditableSelectionOffsets,
    788                         OnSetEditableSelectionOffsets)
    789     IPC_MESSAGE_HANDLER(FrameMsg_SetupTransitionView, OnSetupTransitionView)
    790     IPC_MESSAGE_HANDLER(FrameMsg_BeginExitTransition, OnBeginExitTransition)
    791     IPC_MESSAGE_HANDLER(FrameMsg_Reload, OnReload)
    792     IPC_MESSAGE_HANDLER(FrameMsg_TextSurroundingSelectionRequest,
    793                         OnTextSurroundingSelectionRequest)
    794     IPC_MESSAGE_HANDLER(FrameMsg_AddStyleSheetByURL,
    795                         OnAddStyleSheetByURL)
    796     IPC_MESSAGE_HANDLER(FrameMsg_SetAccessibilityMode,
    797                         OnSetAccessibilityMode)
    798     IPC_MESSAGE_HANDLER(FrameMsg_DisownOpener, OnDisownOpener)
    799 #if defined(OS_ANDROID)
    800     IPC_MESSAGE_HANDLER(FrameMsg_SelectPopupMenuItems, OnSelectPopupMenuItems)
    801 #elif defined(OS_MACOSX)
    802     IPC_MESSAGE_HANDLER(FrameMsg_SelectPopupMenuItem, OnSelectPopupMenuItem)
    803     IPC_MESSAGE_HANDLER(InputMsg_CopyToFindPboard, OnCopyToFindPboard)
    804 #endif
    805   IPC_END_MESSAGE_MAP()
    806 
    807   return handled;
    808 }
    809 
    810 void RenderFrameImpl::OnNavigate(const FrameMsg_Navigate_Params& params) {
    811   TRACE_EVENT2("navigation", "RenderFrameImpl::OnNavigate",
    812                "id", routing_id_, "url", params.url.possibly_invalid_spec());
    813   MaybeHandleDebugURL(params.url);
    814   if (!render_view_->webview())
    815     return;
    816 
    817   FOR_EACH_OBSERVER(
    818       RenderViewObserver, render_view_->observers_, Navigate(params.url));
    819 
    820   bool is_reload = RenderViewImpl::IsReload(params);
    821   WebURLRequest::CachePolicy cache_policy =
    822       WebURLRequest::UseProtocolCachePolicy;
    823 
    824   // If this is a stale back/forward (due to a recent navigation the browser
    825   // didn't know about), ignore it.
    826   if (render_view_->IsBackForwardToStaleEntry(params, is_reload))
    827     return;
    828 
    829   // Swap this renderer back in if necessary.
    830   if (render_view_->is_swapped_out_ &&
    831       GetWebFrame() == render_view_->webview()->mainFrame()) {
    832     // We marked the view as hidden when swapping the view out, so be sure to
    833     // reset the visibility state before navigating to the new URL.
    834     render_view_->webview()->setVisibilityState(
    835         render_view_->visibilityState(), false);
    836 
    837     // If this is an attempt to reload while we are swapped out, we should not
    838     // reload swappedout://, but the previous page, which is stored in
    839     // params.state.  Setting is_reload to false will treat this like a back
    840     // navigation to accomplish that.
    841     is_reload = false;
    842     cache_policy = WebURLRequest::ReloadIgnoringCacheData;
    843 
    844     // We refresh timezone when a view is swapped in since timezone
    845     // can get out of sync when the system timezone is updated while
    846     // the view is swapped out.
    847     RenderThreadImpl::NotifyTimezoneChange();
    848 
    849     render_view_->SetSwappedOut(false);
    850     is_swapped_out_ = false;
    851   }
    852 
    853   if (params.should_clear_history_list) {
    854     CHECK_EQ(params.pending_history_list_offset, -1);
    855     CHECK_EQ(params.current_history_list_offset, -1);
    856     CHECK_EQ(params.current_history_list_length, 0);
    857   }
    858   render_view_->history_list_offset_ = params.current_history_list_offset;
    859   render_view_->history_list_length_ = params.current_history_list_length;
    860   if (render_view_->history_list_length_ >= 0) {
    861     render_view_->history_page_ids_.resize(
    862         render_view_->history_list_length_, -1);
    863   }
    864   if (params.pending_history_list_offset >= 0 &&
    865       params.pending_history_list_offset < render_view_->history_list_length_) {
    866     render_view_->history_page_ids_[params.pending_history_list_offset] =
    867         params.page_id;
    868   }
    869 
    870   GetContentClient()->SetActiveURL(params.url);
    871 
    872   WebFrame* frame = frame_;
    873   if (!params.frame_to_navigate.empty()) {
    874     // TODO(nasko): Move this lookup to the browser process.
    875     frame = render_view_->webview()->findFrameByName(
    876         WebString::fromUTF8(params.frame_to_navigate));
    877     CHECK(frame) << "Invalid frame name passed: " << params.frame_to_navigate;
    878   }
    879 
    880   if (is_reload && !render_view_->history_controller()->GetCurrentEntry()) {
    881     // We cannot reload if we do not have any history state.  This happens, for
    882     // example, when recovering from a crash.
    883     is_reload = false;
    884     cache_policy = WebURLRequest::ReloadIgnoringCacheData;
    885   }
    886 
    887   render_view_->pending_navigation_params_.reset(
    888       new FrameMsg_Navigate_Params(params));
    889 
    890   // If we are reloading, then WebKit will use the history state of the current
    891   // page, so we should just ignore any given history state.  Otherwise, if we
    892   // have history state, then we need to navigate to it, which corresponds to a
    893   // back/forward navigation event.
    894   if (is_reload) {
    895     bool reload_original_url =
    896         (params.navigation_type ==
    897             FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL);
    898     bool ignore_cache = (params.navigation_type ==
    899                              FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE);
    900 
    901     if (reload_original_url)
    902       frame->reloadWithOverrideURL(params.url, true);
    903     else
    904       frame->reload(ignore_cache);
    905   } else if (params.page_state.IsValid()) {
    906     // We must know the page ID of the page we are navigating back to.
    907     DCHECK_NE(params.page_id, -1);
    908     scoped_ptr<HistoryEntry> entry =
    909         PageStateToHistoryEntry(params.page_state);
    910     if (entry) {
    911       // Ensure we didn't save the swapped out URL in UpdateState, since the
    912       // browser should never be telling us to navigate to swappedout://.
    913       CHECK(entry->root().urlString() != WebString::fromUTF8(kSwappedOutURL));
    914       render_view_->history_controller()->GoToEntry(entry.Pass(), cache_policy);
    915     }
    916   } else if (!params.base_url_for_data_url.is_empty()) {
    917     // A loadData request with a specified base URL.
    918     std::string mime_type, charset, data;
    919     if (net::DataURL::Parse(params.url, &mime_type, &charset, &data)) {
    920       frame->loadData(
    921           WebData(data.c_str(), data.length()),
    922           WebString::fromUTF8(mime_type),
    923           WebString::fromUTF8(charset),
    924           params.base_url_for_data_url,
    925           params.history_url_for_data_url,
    926           false);
    927     } else {
    928       CHECK(false) <<
    929           "Invalid URL passed: " << params.url.possibly_invalid_spec();
    930     }
    931   } else {
    932     // Navigate to the given URL.
    933     WebURLRequest request(params.url);
    934 
    935     // A session history navigation should have been accompanied by state.
    936     CHECK_EQ(params.page_id, -1);
    937 
    938     if (frame->isViewSourceModeEnabled())
    939       request.setCachePolicy(WebURLRequest::ReturnCacheDataElseLoad);
    940 
    941     if (params.referrer.url.is_valid()) {
    942       WebString referrer = WebSecurityPolicy::generateReferrerHeader(
    943           params.referrer.policy,
    944           params.url,
    945           WebString::fromUTF8(params.referrer.url.spec()));
    946       if (!referrer.isEmpty())
    947         request.setHTTPReferrer(referrer, params.referrer.policy);
    948     }
    949 
    950     if (!params.extra_headers.empty()) {
    951       for (net::HttpUtil::HeadersIterator i(params.extra_headers.begin(),
    952                                             params.extra_headers.end(), "\n");
    953            i.GetNext(); ) {
    954         request.addHTTPHeaderField(WebString::fromUTF8(i.name()),
    955                                    WebString::fromUTF8(i.values()));
    956       }
    957     }
    958 
    959     if (params.is_post) {
    960       request.setHTTPMethod(WebString::fromUTF8("POST"));
    961 
    962       // Set post data.
    963       WebHTTPBody http_body;
    964       http_body.initialize();
    965       const char* data = NULL;
    966       if (params.browser_initiated_post_data.size()) {
    967         data = reinterpret_cast<const char*>(
    968             &params.browser_initiated_post_data.front());
    969       }
    970       http_body.appendData(
    971           WebData(data, params.browser_initiated_post_data.size()));
    972       request.setHTTPBody(http_body);
    973     }
    974 
    975     // Record this before starting the load, we need a lower bound of this time
    976     // to sanitize the navigationStart override set below.
    977     base::TimeTicks renderer_navigation_start = base::TimeTicks::Now();
    978     frame->loadRequest(request);
    979 
    980     // The browser provides the navigation_start time to bootstrap the
    981     // Navigation Timing information for the browser-initiated navigations. In
    982     // case of cross-process navigations, this carries over the time of
    983     // finishing the onbeforeunload handler of the previous page.
    984     DCHECK(!params.browser_navigation_start.is_null());
    985     if (frame->provisionalDataSource()) {
    986       // |browser_navigation_start| is likely before this process existed, so we
    987       // can't use InterProcessTimeTicksConverter. We need at least to ensure
    988       // that the browser-side navigation start we set is not later than the one
    989       // on the renderer side.
    990       base::TimeTicks navigation_start = std::min(
    991           params.browser_navigation_start, renderer_navigation_start);
    992       double navigation_start_seconds =
    993           (navigation_start - base::TimeTicks()).InSecondsF();
    994       frame->provisionalDataSource()->setNavigationStartTime(
    995           navigation_start_seconds);
    996     }
    997   }
    998 
    999   // In case LoadRequest failed before DidCreateDataSource was called.
   1000   render_view_->pending_navigation_params_.reset();
   1001 }
   1002 
   1003 void RenderFrameImpl::BindServiceRegistry(
   1004     mojo::ScopedMessagePipeHandle service_provider_handle) {
   1005   service_registry_.BindRemoteServiceProvider(service_provider_handle.Pass());
   1006 }
   1007 
   1008 void RenderFrameImpl::OnBeforeUnload() {
   1009   TRACE_EVENT1("navigation", "RenderFrameImpl::OnBeforeUnload",
   1010                "id", routing_id_);
   1011   // TODO(creis): Right now, this is only called on the main frame.  Make the
   1012   // browser process send dispatchBeforeUnloadEvent to every frame that needs
   1013   // it.
   1014   CHECK(!frame_->parent());
   1015 
   1016   base::TimeTicks before_unload_start_time = base::TimeTicks::Now();
   1017   bool proceed = frame_->dispatchBeforeUnloadEvent();
   1018   base::TimeTicks before_unload_end_time = base::TimeTicks::Now();
   1019   Send(new FrameHostMsg_BeforeUnload_ACK(routing_id_, proceed,
   1020                                          before_unload_start_time,
   1021                                          before_unload_end_time));
   1022 }
   1023 
   1024 void RenderFrameImpl::OnSwapOut(int proxy_routing_id) {
   1025   TRACE_EVENT1("navigation", "RenderFrameImpl::OnSwapOut", "id", routing_id_);
   1026   RenderFrameProxy* proxy = NULL;
   1027   bool is_site_per_process =
   1028       CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess);
   1029   bool is_main_frame = !frame_->parent();
   1030 
   1031   // Only run unload if we're not swapped out yet, but send the ack either way.
   1032   if (!is_swapped_out_ || !render_view_->is_swapped_out_) {
   1033     // Swap this RenderFrame out so the frame can navigate to a page rendered by
   1034     // a different process.  This involves running the unload handler and
   1035     // clearing the page.  We also allow this process to exit if there are no
   1036     // other active RenderFrames in it.
   1037 
   1038     // Send an UpdateState message before we get swapped out. Create the
   1039     // RenderFrameProxy as well so its routing id is registered for receiving
   1040     // IPC messages.
   1041     render_view_->SyncNavigationState();
   1042     proxy = RenderFrameProxy::CreateProxyToReplaceFrame(this,
   1043                                                         proxy_routing_id);
   1044 
   1045     // Synchronously run the unload handler before sending the ACK.
   1046     // TODO(creis): Call dispatchUnloadEvent unconditionally here to support
   1047     // unload on subframes as well.
   1048     if (is_main_frame)
   1049       frame_->dispatchUnloadEvent();
   1050 
   1051     // Swap out and stop sending any IPC messages that are not ACKs.
   1052     // TODO(nasko): Do we need RenderFrameImpl::is_swapped_out_ anymore?
   1053     if (is_main_frame)
   1054       render_view_->SetSwappedOut(true);
   1055     is_swapped_out_ = true;
   1056 
   1057     // Now that we're swapped out and filtering IPC messages, stop loading to
   1058     // ensure that no other in-progress navigation continues.  We do this here
   1059     // to avoid sending a DidStopLoading message to the browser process.
   1060     // TODO(creis): Should we be stopping all frames here and using
   1061     // StopAltErrorPageFetcher with RenderView::OnStop, or just stopping this
   1062     // frame?
   1063     OnStop();
   1064 
   1065     // Transfer settings such as initial drawing parameters to the remote frame
   1066     // that will replace this frame.
   1067     if (!is_main_frame)
   1068       proxy->web_frame()->initializeFromFrame(frame_);
   1069 
   1070     // Replace the page with a blank dummy URL. The unload handler will not be
   1071     // run a second time, thanks to a check in FrameLoader::stopLoading.
   1072     // TODO(creis): Need to add a better way to do this that avoids running the
   1073     // beforeunload handler. For now, we just run it a second time silently.
   1074     if (!is_site_per_process || is_main_frame)
   1075       render_view_->NavigateToSwappedOutURL(frame_);
   1076 
   1077     // Let WebKit know that this view is hidden so it can drop resources and
   1078     // stop compositing.
   1079     // TODO(creis): Support this for subframes as well.
   1080     if (is_main_frame) {
   1081       render_view_->webview()->setVisibilityState(
   1082           blink::WebPageVisibilityStateHidden, false);
   1083     }
   1084   }
   1085 
   1086   // It is now safe to show modal dialogs again.
   1087   // TODO(creis): Deal with modal dialogs from subframes.
   1088   if (is_main_frame)
   1089     render_view_->suppress_dialogs_until_swap_out_ = false;
   1090 
   1091   Send(new FrameHostMsg_SwapOut_ACK(routing_id_));
   1092 
   1093   // Now that all of the cleanup is complete and the browser side is notified,
   1094   // start using the RenderFrameProxy, if one is created.
   1095   if (proxy) {
   1096     if (!is_main_frame) {
   1097       frame_->swap(proxy->web_frame());
   1098       if (is_site_per_process) {
   1099         // TODO(nasko): delete the frame here, since we've replaced it with a
   1100         // proxy.
   1101       }
   1102     } else {
   1103       set_render_frame_proxy(proxy);
   1104     }
   1105   }
   1106 
   1107   // Safe to exit if no one else is using the process.
   1108   if (is_main_frame)
   1109     render_view_->WasSwappedOut();
   1110 }
   1111 
   1112 void RenderFrameImpl::OnContextMenuClosed(
   1113     const CustomContextMenuContext& custom_context) {
   1114   if (custom_context.request_id) {
   1115     // External request, should be in our map.
   1116     ContextMenuClient* client =
   1117         pending_context_menus_.Lookup(custom_context.request_id);
   1118     if (client) {
   1119       client->OnMenuClosed(custom_context.request_id);
   1120       pending_context_menus_.Remove(custom_context.request_id);
   1121     }
   1122   } else {
   1123     if (custom_context.link_followed.is_valid()) {
   1124         frame_->sendPings(
   1125             DomUtils::ExtractParentAnchorNode(context_menu_node_),
   1126             custom_context.link_followed);
   1127     }
   1128     // Internal request, forward to WebKit.
   1129     context_menu_node_.reset();
   1130   }
   1131 }
   1132 
   1133 void RenderFrameImpl::OnCustomContextMenuAction(
   1134     const CustomContextMenuContext& custom_context,
   1135     unsigned action) {
   1136   if (custom_context.request_id) {
   1137     // External context menu request, look in our map.
   1138     ContextMenuClient* client =
   1139         pending_context_menus_.Lookup(custom_context.request_id);
   1140     if (client)
   1141       client->OnMenuAction(custom_context.request_id, action);
   1142   } else {
   1143     // Internal request, forward to WebKit.
   1144     render_view_->webview()->performCustomContextMenuAction(action);
   1145   }
   1146 }
   1147 
   1148 void RenderFrameImpl::OnUndo() {
   1149   frame_->executeCommand(WebString::fromUTF8("Undo"), GetFocusedElement());
   1150 }
   1151 
   1152 void RenderFrameImpl::OnRedo() {
   1153   frame_->executeCommand(WebString::fromUTF8("Redo"), GetFocusedElement());
   1154 }
   1155 
   1156 void RenderFrameImpl::OnCut() {
   1157   base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
   1158   frame_->executeCommand(WebString::fromUTF8("Cut"), GetFocusedElement());
   1159 }
   1160 
   1161 void RenderFrameImpl::OnCopy() {
   1162   base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
   1163   WebNode current_node = context_menu_node_.isNull() ?
   1164       GetFocusedElement() : context_menu_node_;
   1165   frame_->executeCommand(WebString::fromUTF8("Copy"), current_node);
   1166 }
   1167 
   1168 void RenderFrameImpl::OnPaste() {
   1169   base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
   1170   frame_->executeCommand(WebString::fromUTF8("Paste"), GetFocusedElement());
   1171 }
   1172 
   1173 void RenderFrameImpl::OnPasteAndMatchStyle() {
   1174   base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
   1175   frame_->executeCommand(
   1176       WebString::fromUTF8("PasteAndMatchStyle"), GetFocusedElement());
   1177 }
   1178 
   1179 #if defined(OS_MACOSX)
   1180 void RenderFrameImpl::OnCopyToFindPboard() {
   1181   // Since the find pasteboard supports only plain text, this can be simpler
   1182   // than the |OnCopy()| case.
   1183   if (frame_->hasSelection()) {
   1184     base::string16 selection = frame_->selectionAsText();
   1185     RenderThread::Get()->Send(
   1186         new ClipboardHostMsg_FindPboardWriteStringAsync(selection));
   1187   }
   1188 }
   1189 #endif
   1190 
   1191 void RenderFrameImpl::OnDelete() {
   1192   frame_->executeCommand(WebString::fromUTF8("Delete"), GetFocusedElement());
   1193 }
   1194 
   1195 void RenderFrameImpl::OnSelectAll() {
   1196   base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
   1197   frame_->executeCommand(WebString::fromUTF8("SelectAll"), GetFocusedElement());
   1198 }
   1199 
   1200 void RenderFrameImpl::OnSelectRange(const gfx::Point& start,
   1201                                     const gfx::Point& end) {
   1202   // This IPC is dispatched by RenderWidgetHost, so use its routing id.
   1203   Send(new ViewHostMsg_SelectRange_ACK(GetRenderWidget()->routing_id()));
   1204 
   1205   base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
   1206   frame_->selectRange(start, end);
   1207 }
   1208 
   1209 void RenderFrameImpl::OnUnselect() {
   1210   base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
   1211   frame_->executeCommand(WebString::fromUTF8("Unselect"), GetFocusedElement());
   1212 }
   1213 
   1214 void RenderFrameImpl::OnReplace(const base::string16& text) {
   1215   if (!frame_->hasSelection())
   1216     frame_->selectWordAroundCaret();
   1217 
   1218   frame_->replaceSelection(text);
   1219 }
   1220 
   1221 void RenderFrameImpl::OnReplaceMisspelling(const base::string16& text) {
   1222   if (!frame_->hasSelection())
   1223     return;
   1224 
   1225   frame_->replaceMisspelledRange(text);
   1226 }
   1227 
   1228 void RenderFrameImpl::OnCSSInsertRequest(const std::string& css) {
   1229   frame_->document().insertStyleSheet(WebString::fromUTF8(css));
   1230 }
   1231 
   1232 void RenderFrameImpl::OnJavaScriptExecuteRequest(
   1233     const base::string16& jscript,
   1234     int id,
   1235     bool notify_result) {
   1236   TRACE_EVENT_INSTANT0("test_tracing", "OnJavaScriptExecuteRequest",
   1237                        TRACE_EVENT_SCOPE_THREAD);
   1238 
   1239   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
   1240   v8::Handle<v8::Value> result =
   1241       frame_->executeScriptAndReturnValue(WebScriptSource(jscript));
   1242 
   1243   HandleJavascriptExecutionResult(jscript, id, notify_result, result);
   1244 }
   1245 
   1246 void RenderFrameImpl::OnJavaScriptExecuteRequestForTests(
   1247     const base::string16& jscript,
   1248     int id,
   1249     bool notify_result) {
   1250   TRACE_EVENT_INSTANT0("test_tracing", "OnJavaScriptExecuteRequestForTests",
   1251                        TRACE_EVENT_SCOPE_THREAD);
   1252 
   1253   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
   1254   v8::Handle<v8::Value> result =
   1255       frame_->executeScriptAndReturnValueForTests(WebScriptSource(jscript));
   1256 
   1257   HandleJavascriptExecutionResult(jscript, id, notify_result, result);
   1258 }
   1259 
   1260 void RenderFrameImpl::HandleJavascriptExecutionResult(
   1261     const base::string16& jscript,
   1262     int id,
   1263     bool notify_result,
   1264     v8::Handle<v8::Value> result) {
   1265   if (notify_result) {
   1266     base::ListValue list;
   1267     if (!result.IsEmpty()) {
   1268       v8::Local<v8::Context> context = frame_->mainWorldScriptContext();
   1269       v8::Context::Scope context_scope(context);
   1270       V8ValueConverterImpl converter;
   1271       converter.SetDateAllowed(true);
   1272       converter.SetRegExpAllowed(true);
   1273       base::Value* result_value = converter.FromV8Value(result, context);
   1274       list.Set(0, result_value ? result_value : base::Value::CreateNullValue());
   1275     } else {
   1276       list.Set(0, base::Value::CreateNullValue());
   1277     }
   1278     Send(new FrameHostMsg_JavaScriptExecuteResponse(routing_id_, id, list));
   1279   }
   1280 }
   1281 
   1282 void RenderFrameImpl::OnSetEditableSelectionOffsets(int start, int end) {
   1283   base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
   1284   if (!GetRenderWidget()->ShouldHandleImeEvent())
   1285     return;
   1286   ImeEventGuard guard(GetRenderWidget());
   1287   frame_->setEditableSelectionOffsets(start, end);
   1288 }
   1289 
   1290 void RenderFrameImpl::OnSetCompositionFromExistingText(
   1291     int start, int end,
   1292     const std::vector<blink::WebCompositionUnderline>& underlines) {
   1293   if (!GetRenderWidget()->ShouldHandleImeEvent())
   1294     return;
   1295   ImeEventGuard guard(GetRenderWidget());
   1296   frame_->setCompositionFromExistingText(start, end, underlines);
   1297 }
   1298 
   1299 void RenderFrameImpl::OnExtendSelectionAndDelete(int before, int after) {
   1300   if (!GetRenderWidget()->ShouldHandleImeEvent())
   1301     return;
   1302   ImeEventGuard guard(GetRenderWidget());
   1303   frame_->extendSelectionAndDelete(before, after);
   1304 }
   1305 
   1306 void RenderFrameImpl::OnSetAccessibilityMode(AccessibilityMode new_mode) {
   1307   if (accessibility_mode_ == new_mode)
   1308     return;
   1309   accessibility_mode_ = new_mode;
   1310   if (renderer_accessibility_) {
   1311     delete renderer_accessibility_;
   1312     renderer_accessibility_ = NULL;
   1313   }
   1314   if (accessibility_mode_ == AccessibilityModeOff)
   1315     return;
   1316 
   1317   if (accessibility_mode_ & AccessibilityModeFlagFullTree)
   1318     renderer_accessibility_ = new RendererAccessibilityComplete(this);
   1319 #if !defined(OS_ANDROID)
   1320   else
   1321     renderer_accessibility_ = new RendererAccessibilityFocusOnly(this);
   1322 #endif
   1323 }
   1324 
   1325 void RenderFrameImpl::OnDisownOpener() {
   1326   // TODO(creis): We should only see this for main frames for now.  To support
   1327   // disowning the opener on subframes, we will need to move WebContentsImpl's
   1328   // opener_ to FrameTreeNode.
   1329   CHECK(!frame_->parent());
   1330 
   1331   if (frame_->opener())
   1332     frame_->setOpener(NULL);
   1333 }
   1334 
   1335 #if defined(OS_ANDROID)
   1336 void RenderFrameImpl::OnSelectPopupMenuItems(
   1337     bool canceled,
   1338     const std::vector<int>& selected_indices) {
   1339   // It is possible to receive more than one of these calls if the user presses
   1340   // a select faster than it takes for the show-select-popup IPC message to make
   1341   // it to the browser UI thread. Ignore the extra-messages.
   1342   // TODO(jcivelli): http:/b/5793321 Implement a better fix, as detailed in bug.
   1343   if (!external_popup_menu_)
   1344     return;
   1345 
   1346   external_popup_menu_->DidSelectItems(canceled, selected_indices);
   1347   external_popup_menu_.reset();
   1348 }
   1349 #endif
   1350 
   1351 #if defined(OS_MACOSX)
   1352 void RenderFrameImpl::OnSelectPopupMenuItem(int selected_index) {
   1353   if (external_popup_menu_ == NULL)
   1354     return;
   1355   external_popup_menu_->DidSelectItem(selected_index);
   1356   external_popup_menu_.reset();
   1357 }
   1358 #endif
   1359 
   1360 void RenderFrameImpl::OnReload(bool ignore_cache) {
   1361   frame_->reload(ignore_cache);
   1362 }
   1363 
   1364 void RenderFrameImpl::OnTextSurroundingSelectionRequest(size_t max_length) {
   1365   blink::WebSurroundingText surroundingText;
   1366   surroundingText.initialize(frame_->selectionRange(), max_length);
   1367 
   1368   if (surroundingText.isNull()) {
   1369     // |surroundingText| might not be correctly initialized, for example if
   1370     // |frame_->selectionRange().isNull()|, in other words, if there was no
   1371     // selection.
   1372     Send(new FrameHostMsg_TextSurroundingSelectionResponse(
   1373         routing_id_, base::string16(), 0, 0));
   1374     return;
   1375   }
   1376 
   1377   Send(new FrameHostMsg_TextSurroundingSelectionResponse(
   1378       routing_id_,
   1379       surroundingText.textContent(),
   1380       surroundingText.startOffsetInTextContent(),
   1381       surroundingText.endOffsetInTextContent()));
   1382 }
   1383 
   1384 void RenderFrameImpl::OnAddStyleSheetByURL(const std::string& url) {
   1385   frame_->addStyleSheetByURL(WebString::fromUTF8(url));
   1386 }
   1387 
   1388 void RenderFrameImpl::OnSetupTransitionView(const std::string& markup) {
   1389   frame_->document().setIsTransitionDocument();
   1390   frame_->navigateToSandboxedMarkup(WebData(markup.data(), markup.length()));
   1391 }
   1392 
   1393 void RenderFrameImpl::OnBeginExitTransition(const std::string& css_selector) {
   1394   frame_->document().setIsTransitionDocument();
   1395   frame_->document().beginExitTransition(WebString::fromUTF8(css_selector));
   1396 }
   1397 
   1398 bool RenderFrameImpl::ShouldUpdateSelectionTextFromContextMenuParams(
   1399     const base::string16& selection_text,
   1400     size_t selection_text_offset,
   1401     const gfx::Range& selection_range,
   1402     const ContextMenuParams& params) {
   1403   base::string16 trimmed_selection_text;
   1404   if (!selection_text.empty() && !selection_range.is_empty()) {
   1405     const int start = selection_range.GetMin() - selection_text_offset;
   1406     const size_t length = selection_range.length();
   1407     if (start >= 0 && start + length <= selection_text.length()) {
   1408       base::TrimWhitespace(selection_text.substr(start, length), base::TRIM_ALL,
   1409                            &trimmed_selection_text);
   1410     }
   1411   }
   1412   base::string16 trimmed_params_text;
   1413   base::TrimWhitespace(params.selection_text, base::TRIM_ALL,
   1414                        &trimmed_params_text);
   1415   return trimmed_params_text != trimmed_selection_text;
   1416 }
   1417 
   1418 bool RenderFrameImpl::RunJavaScriptMessage(JavaScriptMessageType type,
   1419                                            const base::string16& message,
   1420                                            const base::string16& default_value,
   1421                                            const GURL& frame_url,
   1422                                            base::string16* result) {
   1423   // Don't allow further dialogs if we are waiting to swap out, since the
   1424   // PageGroupLoadDeferrer in our stack prevents it.
   1425   if (render_view()->suppress_dialogs_until_swap_out_)
   1426     return false;
   1427 
   1428   bool success = false;
   1429   base::string16 result_temp;
   1430   if (!result)
   1431     result = &result_temp;
   1432 
   1433   render_view()->SendAndRunNestedMessageLoop(
   1434       new FrameHostMsg_RunJavaScriptMessage(
   1435         routing_id_, message, default_value, frame_url, type, &success,
   1436         result));
   1437   return success;
   1438 }
   1439 
   1440 void RenderFrameImpl::LoadNavigationErrorPage(
   1441     const WebURLRequest& failed_request,
   1442     const WebURLError& error,
   1443     bool replace) {
   1444   std::string error_html;
   1445   GetContentClient()->renderer()->GetNavigationErrorStrings(
   1446       render_view(), frame_, failed_request, error, &error_html, NULL);
   1447 
   1448   frame_->loadHTMLString(error_html,
   1449                          GURL(kUnreachableWebDataURL),
   1450                          error.unreachableURL,
   1451                          replace);
   1452 }
   1453 
   1454 void RenderFrameImpl::DidCommitCompositorFrame() {
   1455   FOR_EACH_OBSERVER(
   1456       RenderFrameObserver, observers_, DidCommitCompositorFrame());
   1457 }
   1458 
   1459 RenderView* RenderFrameImpl::GetRenderView() {
   1460   return render_view_.get();
   1461 }
   1462 
   1463 int RenderFrameImpl::GetRoutingID() {
   1464   return routing_id_;
   1465 }
   1466 
   1467 blink::WebLocalFrame* RenderFrameImpl::GetWebFrame() {
   1468   DCHECK(frame_);
   1469   return frame_;
   1470 }
   1471 
   1472 WebPreferences& RenderFrameImpl::GetWebkitPreferences() {
   1473   return render_view_->GetWebkitPreferences();
   1474 }
   1475 
   1476 int RenderFrameImpl::ShowContextMenu(ContextMenuClient* client,
   1477                                      const ContextMenuParams& params) {
   1478   DCHECK(client);  // A null client means "internal" when we issue callbacks.
   1479   ContextMenuParams our_params(params);
   1480   our_params.custom_context.request_id = pending_context_menus_.Add(client);
   1481   Send(new FrameHostMsg_ContextMenu(routing_id_, our_params));
   1482   return our_params.custom_context.request_id;
   1483 }
   1484 
   1485 void RenderFrameImpl::CancelContextMenu(int request_id) {
   1486   DCHECK(pending_context_menus_.Lookup(request_id));
   1487   pending_context_menus_.Remove(request_id);
   1488 }
   1489 
   1490 blink::WebNode RenderFrameImpl::GetContextMenuNode() const {
   1491   return context_menu_node_;
   1492 }
   1493 
   1494 blink::WebPlugin* RenderFrameImpl::CreatePlugin(
   1495     blink::WebFrame* frame,
   1496     const WebPluginInfo& info,
   1497     const blink::WebPluginParams& params) {
   1498   DCHECK_EQ(frame_, frame);
   1499 #if defined(ENABLE_PLUGINS)
   1500   bool pepper_plugin_was_registered = false;
   1501   scoped_refptr<PluginModule> pepper_module(PluginModule::Create(
   1502       this, info, &pepper_plugin_was_registered));
   1503   if (pepper_plugin_was_registered) {
   1504     if (pepper_module.get()) {
   1505       return new PepperWebPluginImpl(pepper_module.get(), params, this);
   1506     }
   1507   }
   1508 #if defined(OS_CHROMEOS)
   1509   LOG(WARNING) << "Pepper module/plugin creation failed.";
   1510   return NULL;
   1511 #else
   1512   // TODO(jam): change to take RenderFrame.
   1513   return new WebPluginImpl(frame, params, info.path, render_view_, this);
   1514 #endif
   1515 #else
   1516   return NULL;
   1517 #endif
   1518 }
   1519 
   1520 void RenderFrameImpl::LoadURLExternally(blink::WebLocalFrame* frame,
   1521                                         const blink::WebURLRequest& request,
   1522                                         blink::WebNavigationPolicy policy) {
   1523   DCHECK(!frame_ || frame_ == frame);
   1524   loadURLExternally(frame, request, policy, WebString());
   1525 }
   1526 
   1527 void RenderFrameImpl::ExecuteJavaScript(const base::string16& javascript) {
   1528   OnJavaScriptExecuteRequest(javascript, 0, false);
   1529 }
   1530 
   1531 ServiceRegistry* RenderFrameImpl::GetServiceRegistry() {
   1532   return &service_registry_;
   1533 }
   1534 
   1535 bool RenderFrameImpl::IsFTPDirectoryListing() {
   1536   WebURLResponseExtraDataImpl* extra_data =
   1537       GetExtraDataFromResponse(frame_->dataSource()->response());
   1538   return extra_data ? extra_data->is_ftp_directory_listing() : false;
   1539 }
   1540 
   1541 void RenderFrameImpl::AttachGuest(int element_instance_id) {
   1542   render_view_->GetBrowserPluginManager()->Attach(element_instance_id);
   1543 }
   1544 
   1545 // blink::WebFrameClient implementation ----------------------------------------
   1546 
   1547 blink::WebPlugin* RenderFrameImpl::createPlugin(
   1548     blink::WebLocalFrame* frame,
   1549     const blink::WebPluginParams& params) {
   1550   DCHECK_EQ(frame_, frame);
   1551   blink::WebPlugin* plugin = NULL;
   1552   if (GetContentClient()->renderer()->OverrideCreatePlugin(
   1553           this, frame, params, &plugin)) {
   1554     return plugin;
   1555   }
   1556 
   1557   if (base::UTF16ToUTF8(params.mimeType) == kBrowserPluginMimeType) {
   1558     scoped_ptr<BrowserPluginDelegate> browser_plugin_delegate(
   1559         GetContentClient()->renderer()->CreateBrowserPluginDelegate(
   1560             this, std::string()));
   1561     return render_view_->GetBrowserPluginManager()->CreateBrowserPlugin(
   1562         render_view_.get(), frame, browser_plugin_delegate.Pass());
   1563   }
   1564 
   1565 #if defined(ENABLE_PLUGINS)
   1566   WebPluginInfo info;
   1567   std::string mime_type;
   1568   bool found = false;
   1569   Send(new FrameHostMsg_GetPluginInfo(
   1570       routing_id_, params.url, frame->top()->document().url(),
   1571       params.mimeType.utf8(), &found, &info, &mime_type));
   1572   if (!found)
   1573     return NULL;
   1574 
   1575   if (info.type == content::WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN) {
   1576     scoped_ptr<BrowserPluginDelegate> browser_plugin_delegate(
   1577         GetContentClient()->renderer()->CreateBrowserPluginDelegate(
   1578             this, base::UTF16ToUTF8(params.mimeType)));
   1579     return render_view_->GetBrowserPluginManager()->CreateBrowserPlugin(
   1580         render_view_.get(), frame, browser_plugin_delegate.Pass());
   1581   }
   1582 
   1583 
   1584   WebPluginParams params_to_use = params;
   1585   params_to_use.mimeType = WebString::fromUTF8(mime_type);
   1586   return CreatePlugin(frame, info, params_to_use);
   1587 #else
   1588   return NULL;
   1589 #endif  // defined(ENABLE_PLUGINS)
   1590 }
   1591 
   1592 blink::WebMediaPlayer* RenderFrameImpl::createMediaPlayer(
   1593     blink::WebLocalFrame* frame,
   1594     const blink::WebURL& url,
   1595     blink::WebMediaPlayerClient* client) {
   1596   return createMediaPlayer(frame, url, client, NULL);
   1597 }
   1598 
   1599 blink::WebMediaPlayer* RenderFrameImpl::createMediaPlayer(
   1600     blink::WebLocalFrame* frame,
   1601     const blink::WebURL& url,
   1602     blink::WebMediaPlayerClient* client,
   1603     blink::WebContentDecryptionModule* initial_cdm) {
   1604 #if defined(VIDEO_HOLE)
   1605   if (!contains_media_player_) {
   1606     render_view_->RegisterVideoHoleFrame(this);
   1607     contains_media_player_ = true;
   1608   }
   1609 #endif  // defined(VIDEO_HOLE)
   1610 
   1611   blink::WebMediaStream web_stream(
   1612       blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor(url));
   1613   if (!web_stream.isNull())
   1614     return CreateWebMediaPlayerForMediaStream(url, client);
   1615 
   1616 #if defined(OS_ANDROID)
   1617   return CreateAndroidWebMediaPlayer(url, client, initial_cdm);
   1618 #else
   1619   RenderThreadImpl* render_thread = RenderThreadImpl::current();
   1620   media::WebMediaPlayerParams params(
   1621       base::Bind(&ContentRendererClient::DeferMediaLoad,
   1622                  base::Unretained(GetContentClient()->renderer()),
   1623                  static_cast<RenderFrame*>(this)),
   1624       render_thread->GetAudioRendererMixerManager()->CreateInput(
   1625           render_view_->routing_id_, routing_id_),
   1626       *render_thread->GetAudioHardwareConfig(),
   1627       new RenderMediaLog(),
   1628       render_thread->GetGpuFactories(),
   1629       render_thread->GetMediaThreadTaskRunner(),
   1630       render_thread->compositor_message_loop_proxy(),
   1631       base::Bind(&EncryptedMediaPlayerSupportImpl::Create),
   1632       initial_cdm);
   1633   return new media::WebMediaPlayerImpl(frame,
   1634                                        client,
   1635                                        weak_factory_.GetWeakPtr(),
   1636                                        params);
   1637 #endif  // defined(OS_ANDROID)
   1638 }
   1639 
   1640 blink::WebContentDecryptionModule*
   1641 RenderFrameImpl::createContentDecryptionModule(
   1642     blink::WebLocalFrame* frame,
   1643     const blink::WebSecurityOrigin& security_origin,
   1644     const blink::WebString& key_system) {
   1645   DCHECK(!frame_ || frame_ == frame);
   1646   return WebContentDecryptionModuleImpl::Create(
   1647 #if defined(ENABLE_PEPPER_CDMS)
   1648       frame,
   1649 #elif defined(ENABLE_BROWSER_CDMS)
   1650       GetCdmManager(),
   1651 #endif
   1652       security_origin,
   1653       key_system);
   1654 }
   1655 
   1656 blink::WebApplicationCacheHost* RenderFrameImpl::createApplicationCacheHost(
   1657     blink::WebLocalFrame* frame,
   1658     blink::WebApplicationCacheHostClient* client) {
   1659   if (!frame || !frame->view())
   1660     return NULL;
   1661   DCHECK(!frame_ || frame_ == frame);
   1662   return new RendererWebApplicationCacheHostImpl(
   1663       RenderViewImpl::FromWebView(frame->view()), client,
   1664       RenderThreadImpl::current()->appcache_dispatcher()->backend_proxy());
   1665 }
   1666 
   1667 blink::WebWorkerPermissionClientProxy*
   1668 RenderFrameImpl::createWorkerPermissionClientProxy(
   1669     blink::WebLocalFrame* frame) {
   1670   if (!frame || !frame->view())
   1671     return NULL;
   1672   DCHECK(!frame_ || frame_ == frame);
   1673   return GetContentClient()->renderer()->CreateWorkerPermissionClientProxy(
   1674       this, frame);
   1675 }
   1676 
   1677 WebExternalPopupMenu* RenderFrameImpl::createExternalPopupMenu(
   1678     const WebPopupMenuInfo& popup_menu_info,
   1679     WebExternalPopupMenuClient* popup_menu_client) {
   1680 #if defined(OS_MACOSX) || defined(OS_ANDROID)
   1681   // An IPC message is sent to the browser to build and display the actual
   1682   // popup. The user could have time to click a different select by the time
   1683   // the popup is shown. In that case external_popup_menu_ is non NULL.
   1684   // By returning NULL in that case, we instruct Blink to cancel that new
   1685   // popup. So from the user perspective, only the first one will show, and
   1686   // will have to close the first one before another one can be shown.
   1687   if (external_popup_menu_)
   1688     return NULL;
   1689   external_popup_menu_.reset(
   1690       new ExternalPopupMenu(this, popup_menu_info, popup_menu_client));
   1691   if (render_view_->screen_metrics_emulator_) {
   1692     render_view_->SetExternalPopupOriginAdjustmentsForEmulation(
   1693         external_popup_menu_.get(),
   1694         render_view_->screen_metrics_emulator_.get());
   1695   }
   1696   return external_popup_menu_.get();
   1697 #else
   1698   return NULL;
   1699 #endif
   1700 }
   1701 
   1702 blink::WebCookieJar* RenderFrameImpl::cookieJar(blink::WebLocalFrame* frame) {
   1703   DCHECK(!frame_ || frame_ == frame);
   1704   return &cookie_jar_;
   1705 }
   1706 
   1707 blink::WebServiceWorkerProvider* RenderFrameImpl::createServiceWorkerProvider(
   1708     blink::WebLocalFrame* frame) {
   1709   DCHECK(!frame_ || frame_ == frame);
   1710   // At this point we should have non-null data source.
   1711   DCHECK(frame->dataSource());
   1712   if (!ChildThread::current())
   1713     return NULL;  // May be null in some tests.
   1714   ServiceWorkerNetworkProvider* provider =
   1715       ServiceWorkerNetworkProvider::FromDocumentState(
   1716           DocumentState::FromDataSource(frame->dataSource()));
   1717   return new WebServiceWorkerProviderImpl(
   1718       ChildThread::current()->thread_safe_sender(),
   1719       provider ? provider->context() : NULL);
   1720 }
   1721 
   1722 void RenderFrameImpl::didAccessInitialDocument(blink::WebLocalFrame* frame) {
   1723   DCHECK(!frame_ || frame_ == frame);
   1724   // Notify the browser process that it is no longer safe to show the pending
   1725   // URL of the main frame, since a URL spoof is now possible.
   1726   if (!frame->parent() && render_view_->page_id_ == -1)
   1727     Send(new FrameHostMsg_DidAccessInitialDocument(routing_id_));
   1728 }
   1729 
   1730 blink::WebFrame* RenderFrameImpl::createChildFrame(
   1731     blink::WebLocalFrame* parent,
   1732     const blink::WebString& name) {
   1733   // Synchronously notify the browser of a child frame creation to get the
   1734   // routing_id for the RenderFrame.
   1735   int child_routing_id = MSG_ROUTING_NONE;
   1736   Send(new FrameHostMsg_CreateChildFrame(routing_id_,
   1737                                          base::UTF16ToUTF8(name),
   1738                                          &child_routing_id));
   1739   // Allocation of routing id failed, so we can't create a child frame. This can
   1740   // happen if this RenderFrameImpl's IPCs are being filtered when in swapped
   1741   // out state.
   1742   if (child_routing_id == MSG_ROUTING_NONE) {
   1743 #if !defined(OS_LINUX)
   1744     // DumpWithoutCrashing() crashes on Linux in renderer processes when
   1745     // breakpad and sandboxing are enabled: crbug.com/349600
   1746     base::debug::Alias(parent);
   1747     base::debug::Alias(&routing_id_);
   1748     bool render_view_is_swapped_out = GetRenderWidget()->is_swapped_out();
   1749     base::debug::Alias(&render_view_is_swapped_out);
   1750     bool render_view_is_closing = GetRenderWidget()->closing();
   1751     base::debug::Alias(&render_view_is_closing);
   1752     base::debug::Alias(&is_swapped_out_);
   1753     base::debug::DumpWithoutCrashing();
   1754 #endif
   1755     return NULL;
   1756   }
   1757 
   1758   // Create the RenderFrame and WebLocalFrame, linking the two.
   1759   RenderFrameImpl* child_render_frame = RenderFrameImpl::Create(
   1760       render_view_.get(), child_routing_id);
   1761   blink::WebLocalFrame* web_frame = WebLocalFrame::create(child_render_frame);
   1762   child_render_frame->SetWebFrame(web_frame);
   1763 
   1764   // Add the frame to the frame tree and initialize it.
   1765   parent->appendChild(web_frame);
   1766   child_render_frame->Initialize();
   1767 
   1768   return web_frame;
   1769 }
   1770 
   1771 void RenderFrameImpl::didDisownOpener(blink::WebLocalFrame* frame) {
   1772   DCHECK(!frame_ || frame_ == frame);
   1773   // We only need to notify the browser if the active, top-level frame clears
   1774   // its opener.  We can ignore cases where a swapped out frame clears its
   1775   // opener after hearing about it from the browser, and the browser does not
   1776   // (yet) care about subframe openers.
   1777   if (render_view_->is_swapped_out_ || frame->parent())
   1778     return;
   1779 
   1780   // Notify WebContents and all its swapped out RenderViews.
   1781   Send(new FrameHostMsg_DidDisownOpener(routing_id_));
   1782 }
   1783 
   1784 void RenderFrameImpl::frameDetached(blink::WebFrame* frame) {
   1785   // NOTE: This function is called on the frame that is being detached and not
   1786   // the parent frame.  This is different from createChildFrame() which is
   1787   // called on the parent frame.
   1788   CHECK(!is_detaching_);
   1789   DCHECK(!frame_ || frame_ == frame);
   1790 
   1791   bool is_subframe = !!frame->parent();
   1792 
   1793   Send(new FrameHostMsg_Detach(routing_id_));
   1794 
   1795   // The |is_detaching_| flag disables Send(). FrameHostMsg_Detach must be
   1796   // sent before setting |is_detaching_| to true. In contrast, Observers
   1797   // should only be notified afterwards so they cannot call back into here and
   1798   // have IPCs fired off.
   1799   is_detaching_ = true;
   1800 
   1801   FOR_EACH_OBSERVER(RenderViewObserver, render_view_->observers(),
   1802                     FrameDetached(frame));
   1803 
   1804   // We need to clean up subframes by removing them from the map and deleting
   1805   // the RenderFrameImpl.  In contrast, the main frame is owned by its
   1806   // containing RenderViewHost (so that they have the same lifetime), so only
   1807   // removal from the map is needed and no deletion.
   1808   FrameMap::iterator it = g_frame_map.Get().find(frame);
   1809   CHECK(it != g_frame_map.Get().end());
   1810   CHECK_EQ(it->second, this);
   1811   g_frame_map.Get().erase(it);
   1812 
   1813   if (is_subframe)
   1814     frame->parent()->removeChild(frame);
   1815 
   1816   // |frame| is invalid after here.
   1817   frame->close();
   1818 
   1819   if (is_subframe) {
   1820     delete this;
   1821     // Object is invalid after this point.
   1822   }
   1823 }
   1824 
   1825 void RenderFrameImpl::frameFocused() {
   1826   Send(new FrameHostMsg_FrameFocused(routing_id_));
   1827 }
   1828 
   1829 void RenderFrameImpl::willClose(blink::WebFrame* frame) {
   1830   DCHECK(!frame_ || frame_ == frame);
   1831 
   1832   FOR_EACH_OBSERVER(RenderFrameObserver, observers_, FrameWillClose());
   1833   FOR_EACH_OBSERVER(RenderViewObserver, render_view_->observers(),
   1834                     FrameWillClose(frame));
   1835 }
   1836 
   1837 void RenderFrameImpl::didChangeName(blink::WebLocalFrame* frame,
   1838                                     const blink::WebString& name) {
   1839   DCHECK(!frame_ || frame_ == frame);
   1840   if (!render_view_->renderer_preferences_.report_frame_name_changes)
   1841     return;
   1842 
   1843   FOR_EACH_OBSERVER(RenderFrameObserver, observers_, DidChangeName(name));
   1844 }
   1845 
   1846 void RenderFrameImpl::didMatchCSS(
   1847     blink::WebLocalFrame* frame,
   1848     const blink::WebVector<blink::WebString>& newly_matching_selectors,
   1849     const blink::WebVector<blink::WebString>& stopped_matching_selectors) {
   1850   DCHECK(!frame_ || frame_ == frame);
   1851 
   1852   FOR_EACH_OBSERVER(RenderViewObserver, render_view_->observers(),
   1853                     DidMatchCSS(frame,
   1854                                 newly_matching_selectors,
   1855                                 stopped_matching_selectors));
   1856 }
   1857 
   1858 bool RenderFrameImpl::shouldReportDetailedMessageForSource(
   1859     const blink::WebString& source) {
   1860   return GetContentClient()->renderer()->ShouldReportDetailedMessageForSource(
   1861       source);
   1862 }
   1863 
   1864 void RenderFrameImpl::didAddMessageToConsole(
   1865     const blink::WebConsoleMessage& message,
   1866     const blink::WebString& source_name,
   1867     unsigned source_line,
   1868     const blink::WebString& stack_trace) {
   1869   logging::LogSeverity log_severity = logging::LOG_VERBOSE;
   1870   switch (message.level) {
   1871     case blink::WebConsoleMessage::LevelDebug:
   1872       log_severity = logging::LOG_VERBOSE;
   1873       break;
   1874     case blink::WebConsoleMessage::LevelLog:
   1875     case blink::WebConsoleMessage::LevelInfo:
   1876       log_severity = logging::LOG_INFO;
   1877       break;
   1878     case blink::WebConsoleMessage::LevelWarning:
   1879       log_severity = logging::LOG_WARNING;
   1880       break;
   1881     case blink::WebConsoleMessage::LevelError:
   1882       log_severity = logging::LOG_ERROR;
   1883       break;
   1884     default:
   1885       NOTREACHED();
   1886   }
   1887 
   1888   if (shouldReportDetailedMessageForSource(source_name)) {
   1889     FOR_EACH_OBSERVER(
   1890         RenderFrameObserver, observers_,
   1891         DetailedConsoleMessageAdded(message.text,
   1892                                     source_name,
   1893                                     stack_trace,
   1894                                     source_line,
   1895                                     static_cast<int32>(log_severity)));
   1896   }
   1897 
   1898   Send(new FrameHostMsg_AddMessageToConsole(routing_id_,
   1899                                             static_cast<int32>(log_severity),
   1900                                             message.text,
   1901                                             static_cast<int32>(source_line),
   1902                                             source_name));
   1903 }
   1904 
   1905 void RenderFrameImpl::loadURLExternally(
   1906     blink::WebLocalFrame* frame,
   1907     const blink::WebURLRequest& request,
   1908     blink::WebNavigationPolicy policy,
   1909     const blink::WebString& suggested_name) {
   1910   DCHECK(!frame_ || frame_ == frame);
   1911   Referrer referrer(RenderViewImpl::GetReferrerFromRequest(frame, request));
   1912   if (policy == blink::WebNavigationPolicyDownload) {
   1913     render_view_->Send(new ViewHostMsg_DownloadUrl(render_view_->GetRoutingID(),
   1914                                                    request.url(), referrer,
   1915                                                    suggested_name));
   1916   } else {
   1917     OpenURL(frame, request.url(), referrer, policy);
   1918   }
   1919 }
   1920 
   1921 blink::WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation(
   1922     const NavigationPolicyInfo& info) {
   1923   DCHECK(!frame_ || frame_ == info.frame);
   1924   return DecidePolicyForNavigation(this, info);
   1925 }
   1926 
   1927 blink::WebHistoryItem RenderFrameImpl::historyItemForNewChildFrame(
   1928     blink::WebFrame* frame) {
   1929   DCHECK(!frame_ || frame_ == frame);
   1930   return render_view_->history_controller()->GetItemForNewChildFrame(this);
   1931 }
   1932 
   1933 void RenderFrameImpl::willSendSubmitEvent(blink::WebLocalFrame* frame,
   1934                                           const blink::WebFormElement& form) {
   1935   DCHECK(!frame_ || frame_ == frame);
   1936 
   1937   FOR_EACH_OBSERVER(RenderViewObserver, render_view_->observers(),
   1938                     WillSendSubmitEvent(frame, form));
   1939 }
   1940 
   1941 void RenderFrameImpl::willSubmitForm(blink::WebLocalFrame* frame,
   1942                                      const blink::WebFormElement& form) {
   1943   DCHECK(!frame_ || frame_ == frame);
   1944   DocumentState* document_state =
   1945       DocumentState::FromDataSource(frame->provisionalDataSource());
   1946   NavigationState* navigation_state = document_state->navigation_state();
   1947   InternalDocumentStateData* internal_data =
   1948       InternalDocumentStateData::FromDocumentState(document_state);
   1949 
   1950   if (ui::PageTransitionCoreTypeIs(navigation_state->transition_type(),
   1951                                    ui::PAGE_TRANSITION_LINK)) {
   1952     navigation_state->set_transition_type(ui::PAGE_TRANSITION_FORM_SUBMIT);
   1953   }
   1954 
   1955   // Save these to be processed when the ensuing navigation is committed.
   1956   WebSearchableFormData web_searchable_form_data(form);
   1957   internal_data->set_searchable_form_url(web_searchable_form_data.url());
   1958   internal_data->set_searchable_form_encoding(
   1959       web_searchable_form_data.encoding().utf8());
   1960 
   1961   FOR_EACH_OBSERVER(RenderViewObserver, render_view_->observers(),
   1962                     WillSubmitForm(frame, form));
   1963 }
   1964 
   1965 void RenderFrameImpl::didCreateDataSource(blink::WebLocalFrame* frame,
   1966                                           blink::WebDataSource* datasource) {
   1967   DCHECK(!frame_ || frame_ == frame);
   1968 
   1969   // TODO(nasko): Move implementation here. Needed state:
   1970   // * pending_navigation_params_
   1971   // * webview
   1972   // Needed methods:
   1973   // * PopulateDocumentStateFromPending
   1974   // * CreateNavigationStateFromPending
   1975   render_view_->didCreateDataSource(frame, datasource);
   1976 
   1977   // Create the serviceworker's per-document network observing object.
   1978   scoped_ptr<ServiceWorkerNetworkProvider>
   1979       network_provider(new ServiceWorkerNetworkProvider());
   1980   ServiceWorkerNetworkProvider::AttachToDocumentState(
   1981       DocumentState::FromDataSource(datasource),
   1982       network_provider.Pass());
   1983 }
   1984 
   1985 void RenderFrameImpl::didStartProvisionalLoad(blink::WebLocalFrame* frame,
   1986                                               bool is_transition_navigation) {
   1987   DCHECK(!frame_ || frame_ == frame);
   1988   WebDataSource* ds = frame->provisionalDataSource();
   1989 
   1990   // In fast/loader/stop-provisional-loads.html, we abort the load before this
   1991   // callback is invoked.
   1992   if (!ds)
   1993     return;
   1994 
   1995   TRACE_EVENT2("navigation", "RenderFrameImpl::didStartProvisionalLoad",
   1996                "id", routing_id_, "url", ds->request().url().string().utf8());
   1997   DocumentState* document_state = DocumentState::FromDataSource(ds);
   1998 
   1999   // We should only navigate to swappedout:// when is_swapped_out_ is true.
   2000   CHECK((ds->request().url() != GURL(kSwappedOutURL)) ||
   2001         is_swapped_out_ ||
   2002         render_view_->is_swapped_out()) <<
   2003         "Heard swappedout:// when not swapped out.";
   2004 
   2005   // Update the request time if WebKit has better knowledge of it.
   2006   if (document_state->request_time().is_null()) {
   2007     double event_time = ds->triggeringEventTime();
   2008     if (event_time != 0.0)
   2009       document_state->set_request_time(Time::FromDoubleT(event_time));
   2010   }
   2011 
   2012   // Start time is only set after request time.
   2013   document_state->set_start_load_time(Time::Now());
   2014 
   2015   bool is_top_most = !frame->parent();
   2016   if (is_top_most) {
   2017     render_view_->set_navigation_gesture(
   2018         WebUserGestureIndicator::isProcessingUserGesture() ?
   2019             NavigationGestureUser : NavigationGestureAuto);
   2020   } else if (ds->replacesCurrentHistoryItem()) {
   2021     // Subframe navigations that don't add session history items must be
   2022     // marked with AUTO_SUBFRAME. See also didFailProvisionalLoad for how we
   2023     // handle loading of error pages.
   2024     document_state->navigation_state()->set_transition_type(
   2025         ui::PAGE_TRANSITION_AUTO_SUBFRAME);
   2026   }
   2027 
   2028   FOR_EACH_OBSERVER(RenderViewObserver, render_view_->observers(),
   2029                     DidStartProvisionalLoad(frame));
   2030   FOR_EACH_OBSERVER(RenderFrameObserver, observers_, DidStartProvisionalLoad());
   2031 
   2032   Send(new FrameHostMsg_DidStartProvisionalLoadForFrame(
   2033        routing_id_, ds->request().url(), is_transition_navigation));
   2034 }
   2035 
   2036 void RenderFrameImpl::didReceiveServerRedirectForProvisionalLoad(
   2037     blink::WebLocalFrame* frame) {
   2038   DCHECK(!frame_ || frame_ == frame);
   2039   render_view_->history_controller()->RemoveChildrenForRedirect(this);
   2040 }
   2041 
   2042 void RenderFrameImpl::didFailProvisionalLoad(blink::WebLocalFrame* frame,
   2043                                              const blink::WebURLError& error) {
   2044   TRACE_EVENT1("navigation", "RenderFrameImpl::didFailProvisionalLoad",
   2045                "id", routing_id_);
   2046   DCHECK(!frame_ || frame_ == frame);
   2047   WebDataSource* ds = frame->provisionalDataSource();
   2048   DCHECK(ds);
   2049 
   2050   const WebURLRequest& failed_request = ds->request();
   2051 
   2052   // Notify the browser that we failed a provisional load with an error.
   2053   //
   2054   // Note: It is important this notification occur before DidStopLoading so the
   2055   //       SSL manager can react to the provisional load failure before being
   2056   //       notified the load stopped.
   2057   //
   2058   FOR_EACH_OBSERVER(RenderViewObserver, render_view_->observers(),
   2059                     DidFailProvisionalLoad(frame, error));
   2060   FOR_EACH_OBSERVER(RenderFrameObserver, observers_,
   2061                     DidFailProvisionalLoad(error));
   2062 
   2063   bool show_repost_interstitial =
   2064       (error.reason == net::ERR_CACHE_MISS &&
   2065        EqualsASCII(failed_request.httpMethod(), "POST"));
   2066 
   2067   FrameHostMsg_DidFailProvisionalLoadWithError_Params params;
   2068   params.error_code = error.reason;
   2069   GetContentClient()->renderer()->GetNavigationErrorStrings(
   2070       render_view_.get(),
   2071       frame,
   2072       failed_request,
   2073       error,
   2074       NULL,
   2075       &params.error_description);
   2076   params.url = error.unreachableURL;
   2077   params.showing_repost_interstitial = show_repost_interstitial;
   2078   Send(new FrameHostMsg_DidFailProvisionalLoadWithError(
   2079       routing_id_, params));
   2080 
   2081   // Don't display an error page if this is simply a cancelled load.  Aside
   2082   // from being dumb, WebCore doesn't expect it and it will cause a crash.
   2083   if (error.reason == net::ERR_ABORTED)
   2084     return;
   2085 
   2086   // Don't display "client blocked" error page if browser has asked us not to.
   2087   if (error.reason == net::ERR_BLOCKED_BY_CLIENT &&
   2088       render_view_->renderer_preferences_.disable_client_blocked_error_page) {
   2089     return;
   2090   }
   2091 
   2092   // Allow the embedder to suppress an error page.
   2093   if (GetContentClient()->renderer()->ShouldSuppressErrorPage(this,
   2094           error.unreachableURL)) {
   2095     return;
   2096   }
   2097 
   2098   if (RenderThreadImpl::current() &&
   2099       RenderThreadImpl::current()->layout_test_mode()) {
   2100     return;
   2101   }
   2102 
   2103   // Make sure we never show errors in view source mode.
   2104   frame->enableViewSourceMode(false);
   2105 
   2106   DocumentState* document_state = DocumentState::FromDataSource(ds);
   2107   NavigationState* navigation_state = document_state->navigation_state();
   2108 
   2109   // If this is a failed back/forward/reload navigation, then we need to do a
   2110   // 'replace' load.  This is necessary to avoid messing up session history.
   2111   // Otherwise, we do a normal load, which simulates a 'go' navigation as far
   2112   // as session history is concerned.
   2113   //
   2114   // AUTO_SUBFRAME loads should always be treated as loads that do not advance
   2115   // the page id.
   2116   //
   2117   // TODO(davidben): This should also take the failed navigation's replacement
   2118   // state into account, if a location.replace() failed.
   2119   bool replace =
   2120       navigation_state->pending_page_id() != -1 ||
   2121       ui::PageTransitionCoreTypeIs(navigation_state->transition_type(),
   2122                                ui::PAGE_TRANSITION_AUTO_SUBFRAME);
   2123 
   2124   // If we failed on a browser initiated request, then make sure that our error
   2125   // page load is regarded as the same browser initiated request.
   2126   if (!navigation_state->is_content_initiated()) {
   2127     render_view_->pending_navigation_params_.reset(
   2128         new FrameMsg_Navigate_Params);
   2129     render_view_->pending_navigation_params_->page_id =
   2130         navigation_state->pending_page_id();
   2131     render_view_->pending_navigation_params_->pending_history_list_offset =
   2132         navigation_state->pending_history_list_offset();
   2133     render_view_->pending_navigation_params_->should_clear_history_list =
   2134         navigation_state->history_list_was_cleared();
   2135     render_view_->pending_navigation_params_->transition =
   2136         navigation_state->transition_type();
   2137     render_view_->pending_navigation_params_->request_time =
   2138         document_state->request_time();
   2139     render_view_->pending_navigation_params_->should_replace_current_entry =
   2140         replace;
   2141   }
   2142 
   2143   // Load an error page.
   2144   LoadNavigationErrorPage(failed_request, error, replace);
   2145 }
   2146 
   2147 void RenderFrameImpl::didCommitProvisionalLoad(
   2148     blink::WebLocalFrame* frame,
   2149     const blink::WebHistoryItem& item,
   2150     blink::WebHistoryCommitType commit_type) {
   2151   TRACE_EVENT2("navigation", "RenderFrameImpl::didCommitProvisionalLoad",
   2152                "id", routing_id_,
   2153                "url", GetLoadingUrl().possibly_invalid_spec());
   2154   DCHECK(!frame_ || frame_ == frame);
   2155   DocumentState* document_state =
   2156       DocumentState::FromDataSource(frame->dataSource());
   2157   NavigationState* navigation_state = document_state->navigation_state();
   2158 
   2159   // When we perform a new navigation, we need to update the last committed
   2160   // session history entry with state for the page we are leaving. Do this
   2161   // before updating the HistoryController state.
   2162   render_view_->UpdateSessionHistory(frame);
   2163 
   2164   render_view_->history_controller()->UpdateForCommit(this, item, commit_type,
   2165       navigation_state->was_within_same_page());
   2166 
   2167   InternalDocumentStateData* internal_data =
   2168       InternalDocumentStateData::FromDocumentState(document_state);
   2169 
   2170   if (document_state->commit_load_time().is_null())
   2171     document_state->set_commit_load_time(Time::Now());
   2172 
   2173   if (internal_data->must_reset_scroll_and_scale_state()) {
   2174     render_view_->webview()->resetScrollAndScaleState();
   2175     internal_data->set_must_reset_scroll_and_scale_state(false);
   2176   }
   2177   internal_data->set_use_error_page(false);
   2178 
   2179   bool is_new_navigation = commit_type == blink::WebStandardCommit;
   2180   if (is_new_navigation) {
   2181     // We bump our Page ID to correspond with the new session history entry.
   2182     render_view_->page_id_ = render_view_->next_page_id_++;
   2183 
   2184     // Don't update history_page_ids_ (etc) for kSwappedOutURL, since
   2185     // we don't want to forget the entry that was there, and since we will
   2186     // never come back to kSwappedOutURL.  Note that we have to call
   2187     // UpdateSessionHistory and update page_id_ even in this case, so that
   2188     // the current entry gets a state update and so that we don't send a
   2189     // state update to the wrong entry when we swap back in.
   2190     if (GetLoadingUrl() != GURL(kSwappedOutURL)) {
   2191       // Advance our offset in session history, applying the length limit.
   2192       // There is now no forward history.
   2193       render_view_->history_list_offset_++;
   2194       if (render_view_->history_list_offset_ >= kMaxSessionHistoryEntries)
   2195         render_view_->history_list_offset_ = kMaxSessionHistoryEntries - 1;
   2196       render_view_->history_list_length_ =
   2197           render_view_->history_list_offset_ + 1;
   2198       render_view_->history_page_ids_.resize(
   2199           render_view_->history_list_length_, -1);
   2200       render_view_->history_page_ids_[render_view_->history_list_offset_] =
   2201           render_view_->page_id_;
   2202     }
   2203   } else {
   2204     // Inspect the navigation_state on this frame to see if the navigation
   2205     // corresponds to a session history navigation...  Note: |frame| may or
   2206     // may not be the toplevel frame, but for the case of capturing session
   2207     // history, the first committed frame suffices.  We keep track of whether
   2208     // we've seen this commit before so that only capture session history once
   2209     // per navigation.
   2210     //
   2211     // Note that we need to check if the page ID changed. In the case of a
   2212     // reload, the page ID doesn't change, and UpdateSessionHistory gets the
   2213     // previous URL and the current page ID, which would be wrong.
   2214     if (navigation_state->pending_page_id() != -1 &&
   2215         navigation_state->pending_page_id() != render_view_->page_id_ &&
   2216         !navigation_state->request_committed()) {
   2217       // This is a successful session history navigation!
   2218       render_view_->page_id_ = navigation_state->pending_page_id();
   2219 
   2220       render_view_->history_list_offset_ =
   2221           navigation_state->pending_history_list_offset();
   2222 
   2223       // If the history list is valid, our list of page IDs should be correct.
   2224       DCHECK(render_view_->history_list_length_ <= 0 ||
   2225              render_view_->history_list_offset_ < 0 ||
   2226              render_view_->history_list_offset_ >=
   2227                  render_view_->history_list_length_ ||
   2228              render_view_->history_page_ids_[render_view_->history_list_offset_]
   2229                   == render_view_->page_id_);
   2230     }
   2231   }
   2232 
   2233   Send(new FrameHostMsg_DidAssignPageId(routing_id_, render_view_->page_id_));
   2234 
   2235   FOR_EACH_OBSERVER(RenderViewObserver, render_view_->observers_,
   2236                     DidCommitProvisionalLoad(frame, is_new_navigation));
   2237   FOR_EACH_OBSERVER(RenderFrameObserver, observers_,
   2238                     DidCommitProvisionalLoad(is_new_navigation));
   2239 
   2240   if (!frame->parent()) {  // Only for top frames.
   2241     RenderThreadImpl* render_thread_impl = RenderThreadImpl::current();
   2242     if (render_thread_impl) {  // Can be NULL in tests.
   2243       render_thread_impl->histogram_customizer()->
   2244           RenderViewNavigatedToHost(GURL(GetLoadingUrl()).host(),
   2245                                     RenderViewImpl::GetRenderViewCount());
   2246     }
   2247   }
   2248 
   2249   // Remember that we've already processed this request, so we don't update
   2250   // the session history again.  We do this regardless of whether this is
   2251   // a session history navigation, because if we attempted a session history
   2252   // navigation without valid HistoryItem state, WebCore will think it is a
   2253   // new navigation.
   2254   navigation_state->set_request_committed(true);
   2255 
   2256   SendDidCommitProvisionalLoad(frame);
   2257 
   2258   // Check whether we have new encoding name.
   2259   UpdateEncoding(frame, frame->view()->pageEncoding().utf8());
   2260 }
   2261 
   2262 void RenderFrameImpl::didClearWindowObject(blink::WebLocalFrame* frame) {
   2263   DCHECK(!frame_ || frame_ == frame);
   2264   // TODO(nasko): Move implementation here. Needed state:
   2265   // * enabled_bindings_
   2266   // * dom_automation_controller_
   2267   // * stats_collection_controller_
   2268 
   2269   render_view_->didClearWindowObject(frame);
   2270 
   2271   if (render_view_->GetEnabledBindings() & BINDINGS_POLICY_DOM_AUTOMATION)
   2272     DomAutomationController::Install(this, frame);
   2273 
   2274   FOR_EACH_OBSERVER(RenderFrameObserver, observers_, DidClearWindowObject());
   2275 }
   2276 
   2277 void RenderFrameImpl::didCreateDocumentElement(blink::WebLocalFrame* frame) {
   2278   DCHECK(!frame_ || frame_ == frame);
   2279 
   2280   // Notify the browser about non-blank documents loading in the top frame.
   2281   GURL url = frame->document().url();
   2282   if (url.is_valid() && url.spec() != url::kAboutBlankURL) {
   2283     // TODO(nasko): Check if webview()->mainFrame() is the same as the
   2284     // frame->tree()->top().
   2285     blink::WebFrame* main_frame = render_view_->webview()->mainFrame();
   2286     if (frame == main_frame) {
   2287       // For now, don't remember plugin zoom values.  We don't want to mix them
   2288       // with normal web content (i.e. a fixed layout plugin would usually want
   2289       // them different).
   2290       render_view_->Send(new ViewHostMsg_DocumentAvailableInMainFrame(
   2291           render_view_->GetRoutingID(),
   2292           main_frame->document().isPluginDocument()));
   2293     }
   2294   }
   2295 
   2296   FOR_EACH_OBSERVER(RenderViewObserver, render_view_->observers(),
   2297                     DidCreateDocumentElement(frame));
   2298 }
   2299 
   2300 void RenderFrameImpl::didReceiveTitle(blink::WebLocalFrame* frame,
   2301                                       const blink::WebString& title,
   2302                                       blink::WebTextDirection direction) {
   2303   DCHECK(!frame_ || frame_ == frame);
   2304   // Ignore all but top level navigations.
   2305   if (!frame->parent()) {
   2306     base::string16 title16 = title;
   2307     base::debug::TraceLog::GetInstance()->UpdateProcessLabel(
   2308         routing_id_, base::UTF16ToUTF8(title16));
   2309 
   2310     base::string16 shortened_title = title16.substr(0, kMaxTitleChars);
   2311     Send(new FrameHostMsg_UpdateTitle(routing_id_,
   2312                                       render_view_->page_id_,
   2313                                       shortened_title, direction));
   2314   }
   2315 
   2316   // Also check whether we have new encoding name.
   2317   UpdateEncoding(frame, frame->view()->pageEncoding().utf8());
   2318 }
   2319 
   2320 void RenderFrameImpl::didChangeIcon(blink::WebLocalFrame* frame,
   2321                                     blink::WebIconURL::Type icon_type) {
   2322   DCHECK(!frame_ || frame_ == frame);
   2323   // TODO(nasko): Investigate wheather implementation should move here.
   2324   render_view_->didChangeIcon(frame, icon_type);
   2325 }
   2326 
   2327 void RenderFrameImpl::didFinishDocumentLoad(blink::WebLocalFrame* frame) {
   2328   TRACE_EVENT1("navigation", "RenderFrameImpl::didFinishDocumentLoad",
   2329                "id", routing_id_);
   2330   DCHECK(!frame_ || frame_ == frame);
   2331   WebDataSource* ds = frame->dataSource();
   2332   DocumentState* document_state = DocumentState::FromDataSource(ds);
   2333   document_state->set_finish_document_load_time(Time::Now());
   2334 
   2335   Send(new FrameHostMsg_DidFinishDocumentLoad(routing_id_));
   2336 
   2337   FOR_EACH_OBSERVER(RenderViewObserver, render_view_->observers(),
   2338                     DidFinishDocumentLoad(frame));
   2339   FOR_EACH_OBSERVER(RenderFrameObserver, observers_, DidFinishDocumentLoad());
   2340 
   2341   // Check whether we have new encoding name.
   2342   UpdateEncoding(frame, frame->view()->pageEncoding().utf8());
   2343 }
   2344 
   2345 void RenderFrameImpl::didHandleOnloadEvents(blink::WebLocalFrame* frame) {
   2346   DCHECK(!frame_ || frame_ == frame);
   2347   if (!frame->parent())
   2348     Send(new FrameHostMsg_DocumentOnLoadCompleted(routing_id_));
   2349 }
   2350 
   2351 void RenderFrameImpl::didFailLoad(blink::WebLocalFrame* frame,
   2352                                   const blink::WebURLError& error) {
   2353   TRACE_EVENT1("navigation", "RenderFrameImpl::didFailLoad",
   2354                "id", routing_id_);
   2355   DCHECK(!frame_ || frame_ == frame);
   2356   // TODO(nasko): Move implementation here. No state needed.
   2357   WebDataSource* ds = frame->dataSource();
   2358   DCHECK(ds);
   2359 
   2360   FOR_EACH_OBSERVER(RenderViewObserver, render_view_->observers(),
   2361                     DidFailLoad(frame, error));
   2362 
   2363   const WebURLRequest& failed_request = ds->request();
   2364   base::string16 error_description;
   2365   GetContentClient()->renderer()->GetNavigationErrorStrings(
   2366       render_view_.get(),
   2367       frame,
   2368       failed_request,
   2369       error,
   2370       NULL,
   2371       &error_description);
   2372   Send(new FrameHostMsg_DidFailLoadWithError(routing_id_,
   2373                                              failed_request.url(),
   2374                                              error.reason,
   2375                                              error_description));
   2376 }
   2377 
   2378 void RenderFrameImpl::didFinishLoad(blink::WebLocalFrame* frame) {
   2379   TRACE_EVENT1("navigation", "RenderFrameImpl::didFinishLoad",
   2380                "id", routing_id_);
   2381   DCHECK(!frame_ || frame_ == frame);
   2382   WebDataSource* ds = frame->dataSource();
   2383   DocumentState* document_state = DocumentState::FromDataSource(ds);
   2384   if (document_state->finish_load_time().is_null()) {
   2385     if (!frame->parent()) {
   2386       TRACE_EVENT_INSTANT0("WebCore", "LoadFinished",
   2387                            TRACE_EVENT_SCOPE_PROCESS);
   2388     }
   2389     document_state->set_finish_load_time(Time::Now());
   2390   }
   2391 
   2392   FOR_EACH_OBSERVER(RenderViewObserver, render_view_->observers(),
   2393                     DidFinishLoad(frame));
   2394   FOR_EACH_OBSERVER(RenderFrameObserver, observers_, DidFinishLoad());
   2395 
   2396   // Don't send this message while the frame is swapped out.
   2397   if (is_swapped_out())
   2398     return;
   2399 
   2400   Send(new FrameHostMsg_DidFinishLoad(routing_id_,
   2401                                       ds->request().url()));
   2402 }
   2403 
   2404 void RenderFrameImpl::didNavigateWithinPage(blink::WebLocalFrame* frame,
   2405     const blink::WebHistoryItem& item,
   2406     blink::WebHistoryCommitType commit_type) {
   2407   TRACE_EVENT1("navigation", "RenderFrameImpl::didNavigateWithinPage",
   2408                "id", routing_id_);
   2409   DCHECK(!frame_ || frame_ == frame);
   2410   // If this was a reference fragment navigation that we initiated, then we
   2411   // could end up having a non-null pending navigation params.  We just need to
   2412   // update the ExtraData on the datasource so that others who read the
   2413   // ExtraData will get the new NavigationState.  Similarly, if we did not
   2414   // initiate this navigation, then we need to take care to reset any pre-
   2415   // existing navigation state to a content-initiated navigation state.
   2416   // DidCreateDataSource conveniently takes care of this for us.
   2417   didCreateDataSource(frame, frame->dataSource());
   2418 
   2419   DocumentState* document_state =
   2420       DocumentState::FromDataSource(frame->dataSource());
   2421   NavigationState* new_state = document_state->navigation_state();
   2422   new_state->set_was_within_same_page(true);
   2423 
   2424   didCommitProvisionalLoad(frame, item, commit_type);
   2425 }
   2426 
   2427 void RenderFrameImpl::didUpdateCurrentHistoryItem(blink::WebLocalFrame* frame) {
   2428   DCHECK(!frame_ || frame_ == frame);
   2429   // TODO(nasko): Move implementation here. Needed methods:
   2430   // * StartNavStateSyncTimerIfNecessary
   2431   render_view_->didUpdateCurrentHistoryItem(frame);
   2432 }
   2433 
   2434 void RenderFrameImpl::addNavigationTransitionData(
   2435     const blink::WebString& allowed_destination_host_pattern,
   2436     const blink::WebString& selector,
   2437     const blink::WebString& markup) {
   2438   Send(new FrameHostMsg_AddNavigationTransitionData(
   2439       routing_id_, allowed_destination_host_pattern.utf8(), selector.utf8(),
   2440       markup.utf8()));
   2441 }
   2442 
   2443 void RenderFrameImpl::didChangeThemeColor() {
   2444   if (frame_->parent())
   2445     return;
   2446 
   2447   Send(new FrameHostMsg_DidChangeThemeColor(
   2448       routing_id_, frame_->document().themeColor()));
   2449 }
   2450 
   2451 void RenderFrameImpl::requestNotificationPermission(
   2452     const blink::WebSecurityOrigin& origin,
   2453     blink::WebNotificationPermissionCallback* callback) {
   2454   if (!notification_permission_dispatcher_) {
   2455     notification_permission_dispatcher_ =
   2456         new NotificationPermissionDispatcher(this);
   2457   }
   2458 
   2459   notification_permission_dispatcher_->RequestPermission(origin, callback);
   2460 }
   2461 
   2462 blink::WebNotificationPresenter* RenderFrameImpl::notificationPresenter() {
   2463   return notification_provider_;
   2464 }
   2465 
   2466 void RenderFrameImpl::didChangeSelection(bool is_empty_selection) {
   2467   if (!GetRenderWidget()->handling_input_event() && !handling_select_range_)
   2468     return;
   2469 
   2470   if (is_empty_selection)
   2471     selection_text_.clear();
   2472 
   2473   // UpdateTextInputType should be called before SyncSelectionIfRequired.
   2474   // UpdateTextInputType may send TextInputTypeChanged to notify the focus
   2475   // was changed, and SyncSelectionIfRequired may send SelectionChanged
   2476   // to notify the selection was changed.  Focus change should be notified
   2477   // before selection change.
   2478   GetRenderWidget()->UpdateTextInputType();
   2479   SyncSelectionIfRequired();
   2480 #if defined(OS_ANDROID)
   2481   GetRenderWidget()->UpdateTextInputState(RenderWidget::NO_SHOW_IME,
   2482                                           RenderWidget::FROM_NON_IME);
   2483 #endif
   2484 }
   2485 
   2486 blink::WebColorChooser* RenderFrameImpl::createColorChooser(
   2487     blink::WebColorChooserClient* client,
   2488     const blink::WebColor& initial_color,
   2489     const blink::WebVector<blink::WebColorSuggestion>& suggestions) {
   2490   RendererWebColorChooserImpl* color_chooser =
   2491       new RendererWebColorChooserImpl(this, client);
   2492   std::vector<content::ColorSuggestion> color_suggestions;
   2493   for (size_t i = 0; i < suggestions.size(); i++) {
   2494     color_suggestions.push_back(content::ColorSuggestion(suggestions[i]));
   2495   }
   2496   color_chooser->Open(static_cast<SkColor>(initial_color), color_suggestions);
   2497   return color_chooser;
   2498 }
   2499 
   2500 void RenderFrameImpl::runModalAlertDialog(const blink::WebString& message) {
   2501   RunJavaScriptMessage(JAVASCRIPT_MESSAGE_TYPE_ALERT,
   2502                        message,
   2503                        base::string16(),
   2504                        frame_->document().url(),
   2505                        NULL);
   2506 }
   2507 
   2508 bool RenderFrameImpl::runModalConfirmDialog(const blink::WebString& message) {
   2509   return RunJavaScriptMessage(JAVASCRIPT_MESSAGE_TYPE_CONFIRM,
   2510                               message,
   2511                               base::string16(),
   2512                               frame_->document().url(),
   2513                               NULL);
   2514 }
   2515 
   2516 bool RenderFrameImpl::runModalPromptDialog(
   2517     const blink::WebString& message,
   2518     const blink::WebString& default_value,
   2519     blink::WebString* actual_value) {
   2520   base::string16 result;
   2521   bool ok = RunJavaScriptMessage(JAVASCRIPT_MESSAGE_TYPE_PROMPT,
   2522                                  message,
   2523                                  default_value,
   2524                                  frame_->document().url(),
   2525                                  &result);
   2526   if (ok)
   2527     actual_value->assign(result);
   2528   return ok;
   2529 }
   2530 
   2531 bool RenderFrameImpl::runModalBeforeUnloadDialog(
   2532     bool is_reload,
   2533     const blink::WebString& message) {
   2534   // If we are swapping out, we have already run the beforeunload handler.
   2535   // TODO(creis): Fix OnSwapOut to clear the frame without running beforeunload
   2536   // at all, to avoid running it twice.
   2537   if (render_view()->is_swapped_out_)
   2538     return true;
   2539 
   2540   // Don't allow further dialogs if we are waiting to swap out, since the
   2541   // PageGroupLoadDeferrer in our stack prevents it.
   2542   if (render_view()->suppress_dialogs_until_swap_out_)
   2543     return false;
   2544 
   2545   bool success = false;
   2546   // This is an ignored return value, but is included so we can accept the same
   2547   // response as RunJavaScriptMessage.
   2548   base::string16 ignored_result;
   2549   render_view()->SendAndRunNestedMessageLoop(
   2550       new FrameHostMsg_RunBeforeUnloadConfirm(
   2551           routing_id_, frame_->document().url(), message, is_reload,
   2552           &success, &ignored_result));
   2553   return success;
   2554 }
   2555 
   2556 void RenderFrameImpl::showContextMenu(const blink::WebContextMenuData& data) {
   2557   ContextMenuParams params = ContextMenuParamsBuilder::Build(data);
   2558   params.source_type = GetRenderWidget()->context_menu_source_type();
   2559   GetRenderWidget()->OnShowHostContextMenu(&params);
   2560   if (GetRenderWidget()->has_host_context_menu_location()) {
   2561     params.x = GetRenderWidget()->host_context_menu_location().x();
   2562     params.y = GetRenderWidget()->host_context_menu_location().y();
   2563   }
   2564 
   2565   // Plugins, e.g. PDF, don't currently update the render view when their
   2566   // selected text changes, but the context menu params do contain the updated
   2567   // selection. If that's the case, update the render view's state just prior
   2568   // to showing the context menu.
   2569   // TODO(asvitkine): http://crbug.com/152432
   2570   if (ShouldUpdateSelectionTextFromContextMenuParams(
   2571           selection_text_, selection_text_offset_, selection_range_, params)) {
   2572     selection_text_ = params.selection_text;
   2573     // TODO(asvitkine): Text offset and range is not available in this case.
   2574     selection_text_offset_ = 0;
   2575     selection_range_ = gfx::Range(0, selection_text_.length());
   2576     // This IPC is dispatched by RenderWidetHost, so use its routing ID.
   2577     Send(new ViewHostMsg_SelectionChanged(
   2578         GetRenderWidget()->routing_id(), selection_text_,
   2579         selection_text_offset_, selection_range_));
   2580   }
   2581 
   2582   // Serializing a GURL longer than kMaxURLChars will fail, so don't do
   2583   // it.  We replace it with an empty GURL so the appropriate items are disabled
   2584   // in the context menu.
   2585   // TODO(jcivelli): http://crbug.com/45160 This prevents us from saving large
   2586   //                 data encoded images.  We should have a way to save them.
   2587   if (params.src_url.spec().size() > GetMaxURLChars())
   2588     params.src_url = GURL();
   2589   context_menu_node_ = data.node;
   2590 
   2591 #if defined(OS_ANDROID)
   2592   gfx::Rect start_rect;
   2593   gfx::Rect end_rect;
   2594   GetRenderWidget()->GetSelectionBounds(&start_rect, &end_rect);
   2595   params.selection_start = gfx::Point(start_rect.x(), start_rect.bottom());
   2596   params.selection_end = gfx::Point(end_rect.right(), end_rect.bottom());
   2597 #endif
   2598 
   2599   Send(new FrameHostMsg_ContextMenu(routing_id_, params));
   2600 }
   2601 
   2602 void RenderFrameImpl::clearContextMenu() {
   2603   context_menu_node_.reset();
   2604 }
   2605 
   2606 void RenderFrameImpl::willSendRequest(
   2607     blink::WebLocalFrame* frame,
   2608     unsigned identifier,
   2609     blink::WebURLRequest& request,
   2610     const blink::WebURLResponse& redirect_response) {
   2611   DCHECK(!frame_ || frame_ == frame);
   2612   // The request my be empty during tests.
   2613   if (request.url().isEmpty())
   2614     return;
   2615 
   2616   // Set the first party for cookies url if it has not been set yet (new
   2617   // requests). For redirects, it is updated by WebURLLoaderImpl.
   2618   if (request.firstPartyForCookies().isEmpty()) {
   2619     if (request.frameType() == blink::WebURLRequest::FrameTypeTopLevel) {
   2620       request.setFirstPartyForCookies(request.url());
   2621     } else {
   2622       // TODO(nasko): When the top-level frame is remote, there is no document.
   2623       // This is broken and should be fixed to propagate the first party.
   2624       WebFrame* top = frame->top();
   2625       if (top->isWebLocalFrame()) {
   2626         request.setFirstPartyForCookies(
   2627             frame->top()->document().firstPartyForCookies());
   2628       }
   2629     }
   2630   }
   2631 
   2632   WebFrame* top_frame = frame->top();
   2633   // TODO(nasko): Hack around asking about top-frame data source. This means
   2634   // for out-of-process iframes we are treating the current frame as the
   2635   // top-level frame, which is wrong.
   2636   if (!top_frame || top_frame->isWebRemoteFrame())
   2637     top_frame = frame;
   2638   WebDataSource* provisional_data_source = top_frame->provisionalDataSource();
   2639   WebDataSource* top_data_source = top_frame->dataSource();
   2640   WebDataSource* data_source =
   2641       provisional_data_source ? provisional_data_source : top_data_source;
   2642 
   2643   ui::PageTransition transition_type = ui::PAGE_TRANSITION_LINK;
   2644   DocumentState* document_state = DocumentState::FromDataSource(data_source);
   2645   DCHECK(document_state);
   2646   InternalDocumentStateData* internal_data =
   2647       InternalDocumentStateData::FromDocumentState(document_state);
   2648   NavigationState* navigation_state = document_state->navigation_state();
   2649   transition_type = navigation_state->transition_type();
   2650 
   2651   GURL request_url(request.url());
   2652   GURL new_url;
   2653   if (GetContentClient()->renderer()->WillSendRequest(
   2654           frame,
   2655           transition_type,
   2656           request_url,
   2657           request.firstPartyForCookies(),
   2658           &new_url)) {
   2659     request.setURL(WebURL(new_url));
   2660   }
   2661 
   2662   if (internal_data->is_cache_policy_override_set())
   2663     request.setCachePolicy(internal_data->cache_policy_override());
   2664 
   2665   // The request's extra data may indicate that we should set a custom user
   2666   // agent. This needs to be done here, after WebKit is through with setting the
   2667   // user agent on its own. Similarly, it may indicate that we should set an
   2668   // X-Requested-With header. This must be done here to avoid breaking CORS
   2669   // checks.
   2670   WebString custom_user_agent;
   2671   WebString requested_with;
   2672   if (request.extraData()) {
   2673     RequestExtraData* old_extra_data =
   2674         static_cast<RequestExtraData*>(request.extraData());
   2675 
   2676     custom_user_agent = old_extra_data->custom_user_agent();
   2677     if (!custom_user_agent.isNull()) {
   2678       if (custom_user_agent.isEmpty())
   2679         request.clearHTTPHeaderField("User-Agent");
   2680       else
   2681         request.setHTTPHeaderField("User-Agent", custom_user_agent);
   2682     }
   2683 
   2684     requested_with = old_extra_data->requested_with();
   2685     if (!requested_with.isNull()) {
   2686       if (requested_with.isEmpty())
   2687         request.clearHTTPHeaderField("X-Requested-With");
   2688       else
   2689         request.setHTTPHeaderField("X-Requested-With", requested_with);
   2690     }
   2691   }
   2692 
   2693   // Add the default accept header for frame request if it has not been set
   2694   // already.
   2695   if ((request.frameType() == blink::WebURLRequest::FrameTypeTopLevel ||
   2696        request.frameType() == blink::WebURLRequest::FrameTypeNested) &&
   2697       request.httpHeaderField(WebString::fromUTF8(kAcceptHeader)).isEmpty()) {
   2698     request.setHTTPHeaderField(WebString::fromUTF8(kAcceptHeader),
   2699                                WebString::fromUTF8(kDefaultAcceptHeader));
   2700   }
   2701 
   2702   // Add an empty HTTP origin header for non GET methods if none is currently
   2703   // present.
   2704   request.addHTTPOriginIfNeeded(WebString());
   2705 
   2706   // Attach |should_replace_current_entry| state to requests so that, should
   2707   // this navigation later require a request transfer, all state is preserved
   2708   // when it is re-created in the new process.
   2709   bool should_replace_current_entry = false;
   2710   if (navigation_state->is_content_initiated()) {
   2711     should_replace_current_entry = data_source->replacesCurrentHistoryItem();
   2712   } else {
   2713     // If the navigation is browser-initiated, the NavigationState contains the
   2714     // correct value instead of the WebDataSource.
   2715     //
   2716     // TODO(davidben): Avoid this awkward duplication of state. See comment on
   2717     // NavigationState::should_replace_current_entry().
   2718     should_replace_current_entry =
   2719         navigation_state->should_replace_current_entry();
   2720   }
   2721 
   2722   int provider_id = kInvalidServiceWorkerProviderId;
   2723   if (request.frameType() == blink::WebURLRequest::FrameTypeTopLevel ||
   2724       request.frameType() == blink::WebURLRequest::FrameTypeNested) {
   2725     // |provisionalDataSource| may be null in some content::ResourceFetcher
   2726     // use cases, we don't hook those requests.
   2727     if (frame->provisionalDataSource()) {
   2728       ServiceWorkerNetworkProvider* provider =
   2729           ServiceWorkerNetworkProvider::FromDocumentState(
   2730               DocumentState::FromDataSource(frame->provisionalDataSource()));
   2731       provider_id = provider->provider_id();
   2732     }
   2733   } else if (frame->dataSource()) {
   2734     ServiceWorkerNetworkProvider* provider =
   2735         ServiceWorkerNetworkProvider::FromDocumentState(
   2736             DocumentState::FromDataSource(frame->dataSource()));
   2737     provider_id = provider->provider_id();
   2738   }
   2739 
   2740   WebFrame* parent = frame->parent();
   2741   int parent_routing_id = MSG_ROUTING_NONE;
   2742   if (!parent) {
   2743     parent_routing_id = -1;
   2744   } else if (parent->isWebLocalFrame()) {
   2745     parent_routing_id = FromWebFrame(parent)->GetRoutingID();
   2746   } else {
   2747     parent_routing_id = RenderFrameProxy::FromWebFrame(parent)->routing_id();
   2748   }
   2749 
   2750   RequestExtraData* extra_data = new RequestExtraData();
   2751   extra_data->set_visibility_state(render_view_->visibilityState());
   2752   extra_data->set_custom_user_agent(custom_user_agent);
   2753   extra_data->set_requested_with(requested_with);
   2754   extra_data->set_render_frame_id(routing_id_);
   2755   extra_data->set_is_main_frame(frame == top_frame);
   2756   extra_data->set_frame_origin(
   2757       GURL(frame->document().securityOrigin().toString()));
   2758   extra_data->set_parent_is_main_frame(frame->parent() == top_frame);
   2759   extra_data->set_parent_render_frame_id(parent_routing_id);
   2760   extra_data->set_allow_download(navigation_state->allow_download());
   2761   extra_data->set_transition_type(transition_type);
   2762   extra_data->set_should_replace_current_entry(should_replace_current_entry);
   2763   extra_data->set_transferred_request_child_id(
   2764       navigation_state->transferred_request_child_id());
   2765   extra_data->set_transferred_request_request_id(
   2766       navigation_state->transferred_request_request_id());
   2767   extra_data->set_service_worker_provider_id(provider_id);
   2768   request.setExtraData(extra_data);
   2769 
   2770   DocumentState* top_document_state =
   2771       DocumentState::FromDataSource(top_data_source);
   2772   if (top_document_state) {
   2773     // TODO(gavinp): separate out prefetching and prerender field trials
   2774     // if the rel=prerender rel type is sticking around.
   2775     if (request.requestContext() == WebURLRequest::RequestContextPrefetch)
   2776       top_document_state->set_was_prefetcher(true);
   2777   }
   2778 
   2779   // This is an instance where we embed a copy of the routing id
   2780   // into the data portion of the message. This can cause problems if we
   2781   // don't register this id on the browser side, since the download manager
   2782   // expects to find a RenderViewHost based off the id.
   2783   request.setRequestorID(render_view_->GetRoutingID());
   2784   request.setHasUserGesture(WebUserGestureIndicator::isProcessingUserGesture());
   2785 
   2786   if (!navigation_state->extra_headers().empty()) {
   2787     for (net::HttpUtil::HeadersIterator i(
   2788         navigation_state->extra_headers().begin(),
   2789         navigation_state->extra_headers().end(), "\n");
   2790         i.GetNext(); ) {
   2791       if (LowerCaseEqualsASCII(i.name(), "referer")) {
   2792         WebString referrer = WebSecurityPolicy::generateReferrerHeader(
   2793             blink::WebReferrerPolicyDefault,
   2794             request.url(),
   2795             WebString::fromUTF8(i.values()));
   2796         request.setHTTPReferrer(referrer, blink::WebReferrerPolicyDefault);
   2797       } else {
   2798         request.setHTTPHeaderField(WebString::fromUTF8(i.name()),
   2799                                    WebString::fromUTF8(i.values()));
   2800       }
   2801     }
   2802   }
   2803 
   2804   if (!render_view_->renderer_preferences_.enable_referrers)
   2805     request.setHTTPReferrer(WebString(), blink::WebReferrerPolicyDefault);
   2806 }
   2807 
   2808 void RenderFrameImpl::didReceiveResponse(
   2809     blink::WebLocalFrame* frame,
   2810     unsigned identifier,
   2811     const blink::WebURLResponse& response) {
   2812   DCHECK(!frame_ || frame_ == frame);
   2813   // Only do this for responses that correspond to a provisional data source
   2814   // of the top-most frame.  If we have a provisional data source, then we
   2815   // can't have any sub-resources yet, so we know that this response must
   2816   // correspond to a frame load.
   2817   if (!frame->provisionalDataSource() || frame->parent())
   2818     return;
   2819 
   2820   // If we are in view source mode, then just let the user see the source of
   2821   // the server's error page.
   2822   if (frame->isViewSourceModeEnabled())
   2823     return;
   2824 
   2825   DocumentState* document_state =
   2826       DocumentState::FromDataSource(frame->provisionalDataSource());
   2827   int http_status_code = response.httpStatusCode();
   2828 
   2829   // Record page load flags.
   2830   WebURLResponseExtraDataImpl* extra_data = GetExtraDataFromResponse(response);
   2831   if (extra_data) {
   2832     document_state->set_was_fetched_via_spdy(
   2833         extra_data->was_fetched_via_spdy());
   2834     document_state->set_was_npn_negotiated(
   2835         extra_data->was_npn_negotiated());
   2836     document_state->set_npn_negotiated_protocol(
   2837         extra_data->npn_negotiated_protocol());
   2838     document_state->set_was_alternate_protocol_available(
   2839         extra_data->was_alternate_protocol_available());
   2840     document_state->set_connection_info(
   2841         extra_data->connection_info());
   2842     document_state->set_was_fetched_via_proxy(
   2843         extra_data->was_fetched_via_proxy());
   2844   }
   2845   InternalDocumentStateData* internal_data =
   2846       InternalDocumentStateData::FromDocumentState(document_state);
   2847   internal_data->set_http_status_code(http_status_code);
   2848   // Whether or not the http status code actually corresponds to an error is
   2849   // only checked when the page is done loading, if |use_error_page| is
   2850   // still true.
   2851   internal_data->set_use_error_page(true);
   2852 }
   2853 
   2854 void RenderFrameImpl::didFinishResourceLoad(blink::WebLocalFrame* frame,
   2855                                             unsigned identifier) {
   2856   DCHECK(!frame_ || frame_ == frame);
   2857   InternalDocumentStateData* internal_data =
   2858       InternalDocumentStateData::FromDataSource(frame->dataSource());
   2859   if (!internal_data->use_error_page())
   2860     return;
   2861 
   2862   // Do not show error page when DevTools is attached.
   2863   if (render_view_->devtools_agent_->IsAttached())
   2864     return;
   2865 
   2866   // Display error page, if appropriate.
   2867   std::string error_domain = "http";
   2868   int http_status_code = internal_data->http_status_code();
   2869   if (GetContentClient()->renderer()->HasErrorPage(
   2870           http_status_code, &error_domain)) {
   2871     WebURLError error;
   2872     error.unreachableURL = frame->document().url();
   2873     error.domain = WebString::fromUTF8(error_domain);
   2874     error.reason = http_status_code;
   2875     LoadNavigationErrorPage(frame->dataSource()->request(), error, true);
   2876   }
   2877 }
   2878 
   2879 void RenderFrameImpl::didLoadResourceFromMemoryCache(
   2880     blink::WebLocalFrame* frame,
   2881     const blink::WebURLRequest& request,
   2882     const blink::WebURLResponse& response) {
   2883   DCHECK(!frame_ || frame_ == frame);
   2884   // The recipients of this message have no use for data: URLs: they don't
   2885   // affect the page's insecure content list and are not in the disk cache. To
   2886   // prevent large (1M+) data: URLs from crashing in the IPC system, we simply
   2887   // filter them out here.
   2888   GURL url(request.url());
   2889   if (url.SchemeIs(url::kDataScheme))
   2890     return;
   2891 
   2892   // Let the browser know we loaded a resource from the memory cache.  This
   2893   // message is needed to display the correct SSL indicators.
   2894   render_view_->Send(new ViewHostMsg_DidLoadResourceFromMemoryCache(
   2895       render_view_->GetRoutingID(),
   2896       url,
   2897       response.securityInfo(),
   2898       request.httpMethod().utf8(),
   2899       response.mimeType().utf8(),
   2900       WebURLRequestToResourceType(request)));
   2901 }
   2902 
   2903 void RenderFrameImpl::didDisplayInsecureContent(blink::WebLocalFrame* frame) {
   2904   DCHECK(!frame_ || frame_ == frame);
   2905   render_view_->Send(new ViewHostMsg_DidDisplayInsecureContent(
   2906       render_view_->GetRoutingID()));
   2907 }
   2908 
   2909 void RenderFrameImpl::didRunInsecureContent(
   2910     blink::WebLocalFrame* frame,
   2911     const blink::WebSecurityOrigin& origin,
   2912     const blink::WebURL& target) {
   2913   DCHECK(!frame_ || frame_ == frame);
   2914   render_view_->Send(new ViewHostMsg_DidRunInsecureContent(
   2915       render_view_->GetRoutingID(),
   2916       origin.toString().utf8(),
   2917       target));
   2918 }
   2919 
   2920 void RenderFrameImpl::didAbortLoading(blink::WebLocalFrame* frame) {
   2921   DCHECK(!frame_ || frame_ == frame);
   2922 #if defined(ENABLE_PLUGINS)
   2923   if (frame != render_view_->webview()->mainFrame())
   2924     return;
   2925   PluginChannelHost::Broadcast(
   2926       new PluginHostMsg_DidAbortLoading(render_view_->GetRoutingID()));
   2927 #endif
   2928 }
   2929 
   2930 void RenderFrameImpl::didCreateScriptContext(blink::WebLocalFrame* frame,
   2931                                              v8::Handle<v8::Context> context,
   2932                                              int extension_group,
   2933                                              int world_id) {
   2934   DCHECK(!frame_ || frame_ == frame);
   2935   GetContentClient()->renderer()->DidCreateScriptContext(
   2936       frame, context, extension_group, world_id);
   2937 }
   2938 
   2939 void RenderFrameImpl::willReleaseScriptContext(blink::WebLocalFrame* frame,
   2940                                                v8::Handle<v8::Context> context,
   2941                                                int world_id) {
   2942   DCHECK(!frame_ || frame_ == frame);
   2943 
   2944   FOR_EACH_OBSERVER(RenderFrameObserver,
   2945                     observers_,
   2946                     WillReleaseScriptContext(context, world_id));
   2947 }
   2948 
   2949 void RenderFrameImpl::didFirstVisuallyNonEmptyLayout(
   2950     blink::WebLocalFrame* frame) {
   2951   DCHECK(!frame_ || frame_ == frame);
   2952   if (frame->parent())
   2953     return;
   2954 
   2955   InternalDocumentStateData* data =
   2956       InternalDocumentStateData::FromDataSource(frame->dataSource());
   2957   data->set_did_first_visually_non_empty_layout(true);
   2958 
   2959 #if defined(OS_ANDROID)
   2960   GetRenderWidget()->DidChangeBodyBackgroundColor(
   2961       render_view_->webwidget_->backgroundColor());
   2962 #endif
   2963 
   2964   GetRenderWidget()->QueueMessage(
   2965       new FrameHostMsg_DidFirstVisuallyNonEmptyPaint(routing_id_),
   2966       MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE);
   2967 }
   2968 
   2969 void RenderFrameImpl::didChangeScrollOffset(blink::WebLocalFrame* frame) {
   2970   DCHECK(!frame_ || frame_ == frame);
   2971   // TODO(nasko): Move implementation here. Needed methods:
   2972   // * StartNavStateSyncTimerIfNecessary
   2973   render_view_->didChangeScrollOffset(frame);
   2974 }
   2975 
   2976 void RenderFrameImpl::willInsertBody(blink::WebLocalFrame* frame) {
   2977   DCHECK(!frame_ || frame_ == frame);
   2978   if (!frame->parent()) {
   2979     render_view_->Send(new ViewHostMsg_WillInsertBody(
   2980         render_view_->GetRoutingID()));
   2981   }
   2982 }
   2983 
   2984 void RenderFrameImpl::reportFindInPageMatchCount(int request_id,
   2985                                                  int count,
   2986                                                  bool final_update) {
   2987   int active_match_ordinal = -1;  // -1 = don't update active match ordinal
   2988   if (!count)
   2989     active_match_ordinal = 0;
   2990 
   2991   render_view_->Send(new ViewHostMsg_Find_Reply(
   2992       render_view_->GetRoutingID(), request_id, count,
   2993       gfx::Rect(), active_match_ordinal, final_update));
   2994 }
   2995 
   2996 void RenderFrameImpl::reportFindInPageSelection(
   2997     int request_id,
   2998     int active_match_ordinal,
   2999     const blink::WebRect& selection_rect) {
   3000   render_view_->Send(new ViewHostMsg_Find_Reply(
   3001       render_view_->GetRoutingID(), request_id, -1, selection_rect,
   3002       active_match_ordinal, false));
   3003 }
   3004 
   3005 void RenderFrameImpl::requestStorageQuota(
   3006     blink::WebLocalFrame* frame,
   3007     blink::WebStorageQuotaType type,
   3008     unsigned long long requested_size,
   3009     blink::WebStorageQuotaCallbacks callbacks) {
   3010   DCHECK(!frame_ || frame_ == frame);
   3011   WebSecurityOrigin origin = frame->document().securityOrigin();
   3012   if (origin.isUnique()) {
   3013     // Unique origins cannot store persistent state.
   3014     callbacks.didFail(blink::WebStorageQuotaErrorAbort);
   3015     return;
   3016   }
   3017   ChildThread::current()->quota_dispatcher()->RequestStorageQuota(
   3018       render_view_->GetRoutingID(),
   3019       GURL(origin.toString()),
   3020       static_cast<storage::StorageType>(type),
   3021       requested_size,
   3022       QuotaDispatcher::CreateWebStorageQuotaCallbacksWrapper(callbacks));
   3023 }
   3024 
   3025 void RenderFrameImpl::willOpenSocketStream(
   3026     blink::WebSocketStreamHandle* handle) {
   3027   WebSocketStreamHandleImpl* impl =
   3028       static_cast<WebSocketStreamHandleImpl*>(handle);
   3029   impl->SetUserData(handle, new SocketStreamHandleData(routing_id_));
   3030 }
   3031 
   3032 void RenderFrameImpl::willOpenWebSocket(blink::WebSocketHandle* handle) {
   3033   WebSocketBridge* impl = static_cast<WebSocketBridge*>(handle);
   3034   impl->set_render_frame_id(routing_id_);
   3035 }
   3036 
   3037 blink::WebGeolocationClient* RenderFrameImpl::geolocationClient() {
   3038   if (!geolocation_dispatcher_)
   3039     geolocation_dispatcher_ = new GeolocationDispatcher(this);
   3040   return geolocation_dispatcher_;
   3041 }
   3042 
   3043 blink::WebPushClient* RenderFrameImpl::pushClient() {
   3044   if (!push_messaging_dispatcher_)
   3045     push_messaging_dispatcher_ = new PushMessagingDispatcher(this);
   3046   return push_messaging_dispatcher_;
   3047 }
   3048 
   3049 void RenderFrameImpl::willStartUsingPeerConnectionHandler(
   3050     blink::WebLocalFrame* frame,
   3051     blink::WebRTCPeerConnectionHandler* handler) {
   3052   DCHECK(!frame_ || frame_ == frame);
   3053 #if defined(ENABLE_WEBRTC)
   3054   static_cast<RTCPeerConnectionHandler*>(handler)->associateWithFrame(frame);
   3055 #endif
   3056 }
   3057 
   3058 blink::WebUserMediaClient* RenderFrameImpl::userMediaClient() {
   3059   if (!web_user_media_client_)
   3060     InitializeUserMediaClient();
   3061   return web_user_media_client_;
   3062 }
   3063 
   3064 blink::WebMIDIClient* RenderFrameImpl::webMIDIClient() {
   3065   if (!midi_dispatcher_)
   3066     midi_dispatcher_ = new MidiDispatcher(this);
   3067   return midi_dispatcher_;
   3068 }
   3069 
   3070 bool RenderFrameImpl::willCheckAndDispatchMessageEvent(
   3071     blink::WebLocalFrame* source_frame,
   3072     blink::WebFrame* target_frame,
   3073     blink::WebSecurityOrigin target_origin,
   3074     blink::WebDOMMessageEvent event) {
   3075   DCHECK(!frame_ || frame_ == target_frame);
   3076 
   3077   if (!render_view_->is_swapped_out_)
   3078     return false;
   3079 
   3080   ViewMsg_PostMessage_Params params;
   3081   params.is_data_raw_string = false;
   3082   params.data = event.data().toString();
   3083   params.source_origin = event.origin();
   3084   if (!target_origin.isNull())
   3085     params.target_origin = target_origin.toString();
   3086 
   3087   blink::WebMessagePortChannelArray channels = event.releaseChannels();
   3088   if (!channels.isEmpty()) {
   3089     std::vector<int> message_port_ids(channels.size());
   3090      // Extract the port IDs from the channel array.
   3091      for (size_t i = 0; i < channels.size(); ++i) {
   3092        WebMessagePortChannelImpl* webchannel =
   3093            static_cast<WebMessagePortChannelImpl*>(channels[i]);
   3094        message_port_ids[i] = webchannel->message_port_id();
   3095        webchannel->QueueMessages();
   3096        DCHECK_NE(message_port_ids[i], MSG_ROUTING_NONE);
   3097      }
   3098      params.message_port_ids = message_port_ids;
   3099   }
   3100 
   3101   // Include the routing ID for the source frame (if one exists), which the
   3102   // browser process will translate into the routing ID for the equivalent
   3103   // frame in the target process.
   3104   params.source_routing_id = MSG_ROUTING_NONE;
   3105   if (source_frame) {
   3106     RenderViewImpl* source_view =
   3107         RenderViewImpl::FromWebView(source_frame->view());
   3108     if (source_view)
   3109       params.source_routing_id = source_view->routing_id();
   3110   }
   3111 
   3112   Send(new ViewHostMsg_RouteMessageEvent(render_view_->routing_id_, params));
   3113   return true;
   3114 }
   3115 
   3116 blink::WebString RenderFrameImpl::userAgentOverride(blink::WebLocalFrame* frame,
   3117                                                     const blink::WebURL& url) {
   3118   DCHECK(!frame_ || frame_ == frame);
   3119   if (!render_view_->webview() || !render_view_->webview()->mainFrame() ||
   3120       render_view_->renderer_preferences_.user_agent_override.empty()) {
   3121     return blink::WebString();
   3122   }
   3123 
   3124   // If we're in the middle of committing a load, the data source we need
   3125   // will still be provisional.
   3126   WebFrame* main_frame = render_view_->webview()->mainFrame();
   3127   WebDataSource* data_source = NULL;
   3128   if (main_frame->provisionalDataSource())
   3129     data_source = main_frame->provisionalDataSource();
   3130   else
   3131     data_source = main_frame->dataSource();
   3132 
   3133   InternalDocumentStateData* internal_data = data_source ?
   3134       InternalDocumentStateData::FromDataSource(data_source) : NULL;
   3135   if (internal_data && internal_data->is_overriding_user_agent())
   3136     return WebString::fromUTF8(
   3137         render_view_->renderer_preferences_.user_agent_override);
   3138   return blink::WebString();
   3139 }
   3140 
   3141 blink::WebString RenderFrameImpl::doNotTrackValue(blink::WebLocalFrame* frame) {
   3142   DCHECK(!frame_ || frame_ == frame);
   3143   if (render_view_->renderer_preferences_.enable_do_not_track)
   3144     return WebString::fromUTF8("1");
   3145   return WebString();
   3146 }
   3147 
   3148 bool RenderFrameImpl::allowWebGL(blink::WebLocalFrame* frame,
   3149                                  bool default_value) {
   3150   DCHECK(!frame_ || frame_ == frame);
   3151   if (!default_value)
   3152     return false;
   3153 
   3154   bool blocked = true;
   3155   render_view_->Send(new ViewHostMsg_Are3DAPIsBlocked(
   3156       render_view_->GetRoutingID(),
   3157       GURL(frame->top()->document().securityOrigin().toString()),
   3158       THREE_D_API_TYPE_WEBGL,
   3159       &blocked));
   3160   return !blocked;
   3161 }
   3162 
   3163 void RenderFrameImpl::didLoseWebGLContext(blink::WebLocalFrame* frame,
   3164                                           int arb_robustness_status_code) {
   3165   DCHECK(!frame_ || frame_ == frame);
   3166   render_view_->Send(new ViewHostMsg_DidLose3DContext(
   3167       GURL(frame->top()->document().securityOrigin().toString()),
   3168       THREE_D_API_TYPE_WEBGL,
   3169       arb_robustness_status_code));
   3170 }
   3171 
   3172 void RenderFrameImpl::forwardInputEvent(const blink::WebInputEvent* event) {
   3173   Send(new FrameHostMsg_ForwardInputEvent(routing_id_, event));
   3174 }
   3175 
   3176 blink::WebScreenOrientationClient*
   3177     RenderFrameImpl::webScreenOrientationClient() {
   3178   if (!screen_orientation_dispatcher_)
   3179     screen_orientation_dispatcher_ = new ScreenOrientationDispatcher(this);
   3180   return screen_orientation_dispatcher_;
   3181 }
   3182 
   3183 bool RenderFrameImpl::isControlledByServiceWorker() {
   3184   // If we're in the middle of committing a load, the data source we need
   3185   // will still be provisional.
   3186   WebFrame* main_frame = render_view_->webview()->mainFrame();
   3187   WebDataSource* data_source = NULL;
   3188   if (main_frame->provisionalDataSource())
   3189     data_source = main_frame->provisionalDataSource();
   3190   else
   3191     data_source = main_frame->dataSource();
   3192   ServiceWorkerNetworkProvider* provider =
   3193       ServiceWorkerNetworkProvider::FromDocumentState(
   3194           DocumentState::FromDataSource(data_source));
   3195   return provider->context()->controller_handle_id() !=
   3196       kInvalidServiceWorkerHandleId;
   3197 }
   3198 
   3199 void RenderFrameImpl::postAccessibilityEvent(const blink::WebAXObject& obj,
   3200                                              blink::WebAXEvent event) {
   3201   HandleWebAccessibilityEvent(obj, event);
   3202 }
   3203 
   3204 void RenderFrameImpl::didChangeManifest(blink::WebLocalFrame* frame)
   3205 {
   3206   DCHECK(!frame_ || frame_ == frame);
   3207 
   3208   FOR_EACH_OBSERVER(RenderFrameObserver, observers_, DidChangeManifest());
   3209 }
   3210 
   3211 void RenderFrameImpl::DidPlay(blink::WebMediaPlayer* player) {
   3212   Send(new FrameHostMsg_MediaPlayingNotification(
   3213       routing_id_, reinterpret_cast<int64>(player), player->hasVideo(),
   3214       player->hasAudio(), player->isRemote()));
   3215 }
   3216 
   3217 void RenderFrameImpl::DidPause(blink::WebMediaPlayer* player) {
   3218   Send(new FrameHostMsg_MediaPausedNotification(
   3219       routing_id_, reinterpret_cast<int64>(player)));
   3220 }
   3221 
   3222 void RenderFrameImpl::PlayerGone(blink::WebMediaPlayer* player) {
   3223   DidPause(player);
   3224 }
   3225 
   3226 void RenderFrameImpl::AddObserver(RenderFrameObserver* observer) {
   3227   observers_.AddObserver(observer);
   3228 }
   3229 
   3230 void RenderFrameImpl::RemoveObserver(RenderFrameObserver* observer) {
   3231   observer->RenderFrameGone();
   3232   observers_.RemoveObserver(observer);
   3233 }
   3234 
   3235 void RenderFrameImpl::OnStop() {
   3236   DCHECK(frame_);
   3237   frame_->stopLoading();
   3238   if (!frame_->parent())
   3239     FOR_EACH_OBSERVER(RenderViewObserver, render_view_->observers_, OnStop());
   3240 
   3241   FOR_EACH_OBSERVER(RenderFrameObserver, observers_, OnStop());
   3242 }
   3243 
   3244 void RenderFrameImpl::WasHidden() {
   3245   FOR_EACH_OBSERVER(RenderFrameObserver, observers_, WasHidden());
   3246 }
   3247 
   3248 void RenderFrameImpl::WasShown() {
   3249   FOR_EACH_OBSERVER(RenderFrameObserver, observers_, WasShown());
   3250 }
   3251 
   3252 bool RenderFrameImpl::IsHidden() {
   3253   return GetRenderWidget()->is_hidden();
   3254 }
   3255 
   3256 // Tell the embedding application that the URL of the active page has changed.
   3257 void RenderFrameImpl::SendDidCommitProvisionalLoad(blink::WebFrame* frame) {
   3258   DCHECK(!frame_ || frame_ == frame);
   3259   WebDataSource* ds = frame->dataSource();
   3260   DCHECK(ds);
   3261 
   3262   const WebURLRequest& request = ds->request();
   3263   const WebURLResponse& response = ds->response();
   3264 
   3265   DocumentState* document_state = DocumentState::FromDataSource(ds);
   3266   NavigationState* navigation_state = document_state->navigation_state();
   3267   InternalDocumentStateData* internal_data =
   3268       InternalDocumentStateData::FromDocumentState(document_state);
   3269 
   3270   FrameHostMsg_DidCommitProvisionalLoad_Params params;
   3271   params.http_status_code = response.httpStatusCode();
   3272   params.url_is_unreachable = ds->hasUnreachableURL();
   3273   params.is_post = false;
   3274   params.post_id = -1;
   3275   params.page_id = render_view_->page_id_;
   3276   // We need to track the RenderViewHost routing_id because of downstream
   3277   // dependencies (crbug.com/392171 DownloadRequestHandle, SaveFileManager,
   3278   // ResourceDispatcherHostImpl, MediaStreamUIProxy,
   3279   // SpeechRecognitionDispatcherHost and possibly others). They look up the view
   3280   // based on the ID stored in the resource requests. Once those dependencies
   3281   // are unwound or moved to RenderFrameHost (crbug.com/304341) we can move the
   3282   // client to be based on the routing_id of the RenderFrameHost.
   3283   params.render_view_routing_id = render_view_->routing_id();
   3284   params.socket_address.set_host(response.remoteIPAddress().utf8());
   3285   params.socket_address.set_port(response.remotePort());
   3286   WebURLResponseExtraDataImpl* extra_data = GetExtraDataFromResponse(response);
   3287   if (extra_data)
   3288     params.was_fetched_via_proxy = extra_data->was_fetched_via_proxy();
   3289   params.was_within_same_page = navigation_state->was_within_same_page();
   3290   params.security_info = response.securityInfo();
   3291 
   3292   // Set the URL to be displayed in the browser UI to the user.
   3293   params.url = GetLoadingUrl();
   3294   DCHECK(!is_swapped_out_ || params.url == GURL(kSwappedOutURL));
   3295 
   3296   if (frame->document().baseURL() != params.url)
   3297     params.base_url = frame->document().baseURL();
   3298 
   3299   GetRedirectChain(ds, &params.redirects);
   3300   params.should_update_history = !ds->hasUnreachableURL() &&
   3301       !response.isMultipartPayload() && (response.httpStatusCode() != 404);
   3302 
   3303   params.searchable_form_url = internal_data->searchable_form_url();
   3304   params.searchable_form_encoding = internal_data->searchable_form_encoding();
   3305 
   3306   params.gesture = render_view_->navigation_gesture_;
   3307   render_view_->navigation_gesture_ = NavigationGestureUnknown;
   3308 
   3309   // Make navigation state a part of the DidCommitProvisionalLoad message so
   3310   // that commited entry has it at all times.
   3311   HistoryEntry* entry = render_view_->history_controller()->GetCurrentEntry();
   3312   if (entry)
   3313     params.page_state = HistoryEntryToPageState(entry);
   3314   else
   3315     params.page_state = PageState::CreateFromURL(request.url());
   3316 
   3317   if (!frame->parent()) {
   3318     // Top-level navigation.
   3319 
   3320     // Reset the zoom limits in case a plugin had changed them previously. This
   3321     // will also call us back which will cause us to send a message to
   3322     // update WebContentsImpl.
   3323     render_view_->webview()->zoomLimitsChanged(
   3324         ZoomFactorToZoomLevel(kMinimumZoomFactor),
   3325         ZoomFactorToZoomLevel(kMaximumZoomFactor));
   3326 
   3327     // Set zoom level, but don't do it for full-page plugin since they don't use
   3328     // the same zoom settings.
   3329     HostZoomLevels::iterator host_zoom =
   3330         render_view_->host_zoom_levels_.find(GURL(request.url()));
   3331     if (render_view_->webview()->mainFrame()->document().isPluginDocument()) {
   3332       // Reset the zoom levels for plugins.
   3333       render_view_->webview()->setZoomLevel(0);
   3334     } else {
   3335       if (host_zoom != render_view_->host_zoom_levels_.end())
   3336         render_view_->webview()->setZoomLevel(host_zoom->second);
   3337     }
   3338 
   3339     if (host_zoom != render_view_->host_zoom_levels_.end()) {
   3340       // This zoom level was merely recorded transiently for this load.  We can
   3341       // erase it now.  If at some point we reload this page, the browser will
   3342       // send us a new, up-to-date zoom level.
   3343       render_view_->host_zoom_levels_.erase(host_zoom);
   3344     }
   3345 
   3346     // Update contents MIME type for main frame.
   3347     params.contents_mime_type = ds->response().mimeType().utf8();
   3348 
   3349     params.transition = navigation_state->transition_type();
   3350     if (!ui::PageTransitionIsMainFrame(params.transition)) {
   3351       // If the main frame does a load, it should not be reported as a subframe
   3352       // navigation.  This can occur in the following case:
   3353       // 1. You're on a site with frames.
   3354       // 2. You do a subframe navigation.  This is stored with transition type
   3355       //    MANUAL_SUBFRAME.
   3356       // 3. You navigate to some non-frame site, say, google.com.
   3357       // 4. You navigate back to the page from step 2.  Since it was initially
   3358       //    MANUAL_SUBFRAME, it will be that same transition type here.
   3359       // We don't want that, because any navigation that changes the toplevel
   3360       // frame should be tracked as a toplevel navigation (this allows us to
   3361       // update the URL bar, etc).
   3362       params.transition = ui::PAGE_TRANSITION_LINK;
   3363     }
   3364 
   3365     // If the page contained a client redirect (meta refresh, document.loc...),
   3366     // set the referrer and transition appropriately.
   3367     if (ds->isClientRedirect()) {
   3368       params.referrer =
   3369           Referrer(params.redirects[0], ds->request().referrerPolicy());
   3370       params.transition = ui::PageTransitionFromInt(
   3371           params.transition | ui::PAGE_TRANSITION_CLIENT_REDIRECT);
   3372     } else {
   3373       params.referrer = RenderViewImpl::GetReferrerFromRequest(
   3374           frame, ds->request());
   3375     }
   3376 
   3377     base::string16 method = request.httpMethod();
   3378     if (EqualsASCII(method, "POST")) {
   3379       params.is_post = true;
   3380       params.post_id = ExtractPostId(entry->root());
   3381     }
   3382 
   3383     // Send the user agent override back.
   3384     params.is_overriding_user_agent = internal_data->is_overriding_user_agent();
   3385 
   3386     // Track the URL of the original request.  We use the first entry of the
   3387     // redirect chain if it exists because the chain may have started in another
   3388     // process.
   3389     params.original_request_url = GetOriginalRequestURL(ds);
   3390 
   3391     params.history_list_was_cleared =
   3392         navigation_state->history_list_was_cleared();
   3393 
   3394     // Save some histogram data so we can compute the average memory used per
   3395     // page load of the glyphs.
   3396     UMA_HISTOGRAM_COUNTS_10000("Memory.GlyphPagesPerLoad",
   3397                                blink::WebGlyphCache::pageCount());
   3398 
   3399     // This message needs to be sent before any of allowScripts(),
   3400     // allowImages(), allowPlugins() is called for the new page, so that when
   3401     // these functions send a ViewHostMsg_ContentBlocked message, it arrives
   3402     // after the FrameHostMsg_DidCommitProvisionalLoad message.
   3403     Send(new FrameHostMsg_DidCommitProvisionalLoad(routing_id_, params));
   3404   } else {
   3405     // Subframe navigation: the type depends on whether this navigation
   3406     // generated a new session history entry. When they do generate a session
   3407     // history entry, it means the user initiated the navigation and we should
   3408     // mark it as such. This test checks if this is the first time
   3409     // SendDidCommitProvisionalLoad has been called since WillNavigateToURL was
   3410     // called to initiate the load.
   3411     if (render_view_->page_id_ > render_view_->last_page_id_sent_to_browser_)
   3412       params.transition = ui::PAGE_TRANSITION_MANUAL_SUBFRAME;
   3413     else
   3414       params.transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME;
   3415 
   3416     DCHECK(!navigation_state->history_list_was_cleared());
   3417     params.history_list_was_cleared = false;
   3418 
   3419     // Don't send this message while the subframe is swapped out.
   3420     if (!is_swapped_out())
   3421       Send(new FrameHostMsg_DidCommitProvisionalLoad(routing_id_, params));
   3422   }
   3423 
   3424   render_view_->last_page_id_sent_to_browser_ =
   3425       std::max(render_view_->last_page_id_sent_to_browser_,
   3426                render_view_->page_id_);
   3427 
   3428   // If we end up reusing this WebRequest (for example, due to a #ref click),
   3429   // we don't want the transition type to persist.  Just clear it.
   3430   navigation_state->set_transition_type(ui::PAGE_TRANSITION_LINK);
   3431 }
   3432 
   3433 WebElement RenderFrameImpl::GetFocusedElement() {
   3434   WebDocument doc = frame_->document();
   3435   if (!doc.isNull())
   3436     return doc.focusedElement();
   3437 
   3438   return WebElement();
   3439 }
   3440 
   3441 void RenderFrameImpl::didStartLoading(bool to_different_document) {
   3442   TRACE_EVENT1("navigation", "RenderFrameImpl::didStartLoading",
   3443                "id", routing_id_);
   3444   render_view_->FrameDidStartLoading(frame_);
   3445   Send(new FrameHostMsg_DidStartLoading(routing_id_, to_different_document));
   3446 }
   3447 
   3448 void RenderFrameImpl::didStopLoading() {
   3449   TRACE_EVENT1("navigation", "RenderFrameImpl::didStopLoading",
   3450                "id", routing_id_);
   3451   render_view_->FrameDidStopLoading(frame_);
   3452   Send(new FrameHostMsg_DidStopLoading(routing_id_));
   3453 }
   3454 
   3455 void RenderFrameImpl::didChangeLoadProgress(double load_progress) {
   3456   Send(new FrameHostMsg_DidChangeLoadProgress(routing_id_, load_progress));
   3457 }
   3458 
   3459 void RenderFrameImpl::HandleWebAccessibilityEvent(
   3460     const blink::WebAXObject& obj, blink::WebAXEvent event) {
   3461   if (renderer_accessibility_)
   3462     renderer_accessibility_->HandleWebAccessibilityEvent(obj, event);
   3463 }
   3464 
   3465 void RenderFrameImpl::FocusedNodeChanged(const WebNode& node) {
   3466   if (renderer_accessibility_)
   3467     renderer_accessibility_->FocusedNodeChanged(node);
   3468 }
   3469 
   3470 WebNavigationPolicy RenderFrameImpl::DecidePolicyForNavigation(
   3471     RenderFrame* render_frame,
   3472     const NavigationPolicyInfo& info) {
   3473 #ifdef OS_ANDROID
   3474   // The handlenavigation API is deprecated and will be removed once
   3475   // crbug.com/325351 is resolved.
   3476   if (info.urlRequest.url() != GURL(kSwappedOutURL) &&
   3477       GetContentClient()->renderer()->HandleNavigation(
   3478           render_frame,
   3479           static_cast<DocumentState*>(info.extraData),
   3480           render_view_->opener_id_,
   3481           info.frame,
   3482           info.urlRequest,
   3483           info.navigationType,
   3484           info.defaultPolicy,
   3485           info.isRedirect)) {
   3486     return blink::WebNavigationPolicyIgnore;
   3487   }
   3488 #endif
   3489 
   3490   Referrer referrer(RenderViewImpl::GetReferrerFromRequest(info.frame,
   3491                                                            info.urlRequest));
   3492   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
   3493 
   3494   bool is_subframe = !!info.frame->parent();
   3495 
   3496   if (command_line.HasSwitch(switches::kSitePerProcess) && is_subframe) {
   3497     // There's no reason to ignore navigations on subframes, since the swap out
   3498     // logic no longer applies.
   3499   } else {
   3500     if (is_swapped_out_ || render_view_->is_swapped_out()) {
   3501       if (info.urlRequest.url() != GURL(kSwappedOutURL)) {
   3502         // Targeted links may try to navigate a swapped out frame.  Allow the
   3503         // browser process to navigate the tab instead.  Note that it is also
   3504         // possible for non-targeted navigations (from this view) to arrive
   3505         // here just after we are swapped out.  It's ok to send them to the
   3506         // browser, as long as they're for the top level frame.
   3507         // TODO(creis): Ensure this supports targeted form submissions when
   3508         // fixing http://crbug.com/101395.
   3509         if (info.frame->parent() == NULL) {
   3510           OpenURL(info.frame, info.urlRequest.url(), referrer,
   3511                   info.defaultPolicy);
   3512           return blink::WebNavigationPolicyIgnore;  // Suppress the load here.
   3513         }
   3514 
   3515         // We should otherwise ignore in-process iframe navigations, if they
   3516         // arrive just after we are swapped out.
   3517         return blink::WebNavigationPolicyIgnore;
   3518       }
   3519 
   3520       // Allow kSwappedOutURL to complete.
   3521       return info.defaultPolicy;
   3522     }
   3523   }
   3524 
   3525   // Webkit is asking whether to navigate to a new URL.
   3526   // This is fine normally, except if we're showing UI from one security
   3527   // context and they're trying to navigate to a different context.
   3528   const GURL& url = info.urlRequest.url();
   3529 
   3530   // A content initiated navigation may have originated from a link-click,
   3531   // script, drag-n-drop operation, etc.
   3532   bool is_content_initiated = static_cast<DocumentState*>(info.extraData)->
   3533           navigation_state()->is_content_initiated();
   3534 
   3535   // Experimental:
   3536   // If --enable-strict-site-isolation or --site-per-process is enabled, send
   3537   // all top-level navigations to the browser to let it swap processes when
   3538   // crossing site boundaries.  This is currently expected to break some script
   3539   // calls and navigations, such as form submissions.
   3540   bool force_swap_due_to_flag =
   3541       command_line.HasSwitch(switches::kEnableStrictSiteIsolation) ||
   3542       command_line.HasSwitch(switches::kSitePerProcess);
   3543   if (force_swap_due_to_flag &&
   3544       !info.frame->parent() && (is_content_initiated || info.isRedirect)) {
   3545     WebString origin_str = info.frame->document().securityOrigin().toString();
   3546     GURL frame_url(origin_str.utf8().data());
   3547     // TODO(cevans): revisit whether this site check is still necessary once
   3548     // crbug.com/101395 is fixed.
   3549     bool same_domain_or_host =
   3550         net::registry_controlled_domains::SameDomainOrHost(
   3551             frame_url,
   3552             url,
   3553             net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
   3554     if (!same_domain_or_host || frame_url.scheme() != url.scheme()) {
   3555       OpenURL(info.frame, url, referrer, info.defaultPolicy);
   3556       return blink::WebNavigationPolicyIgnore;
   3557     }
   3558   }
   3559 
   3560   // If the browser is interested, then give it a chance to look at the request.
   3561   if (is_content_initiated) {
   3562     bool is_form_post =
   3563         ((info.navigationType == blink::WebNavigationTypeFormSubmitted) ||
   3564             (info.navigationType == blink::WebNavigationTypeFormResubmitted)) &&
   3565         EqualsASCII(info.urlRequest.httpMethod(), "POST");
   3566     bool browser_handles_request =
   3567         render_view_->renderer_preferences_
   3568             .browser_handles_non_local_top_level_requests
   3569         && IsNonLocalTopLevelNavigation(url, info.frame, info.navigationType,
   3570                                         is_form_post);
   3571     if (!browser_handles_request) {
   3572       browser_handles_request = IsTopLevelNavigation(info.frame) &&
   3573           render_view_->renderer_preferences_
   3574               .browser_handles_all_top_level_requests;
   3575     }
   3576 
   3577     if (browser_handles_request) {
   3578       OpenURL(info.frame, url, referrer, info.defaultPolicy);
   3579       return blink::WebNavigationPolicyIgnore;  // Suppress the load here.
   3580     }
   3581   }
   3582 
   3583   // Use the frame's original request's URL rather than the document's URL for
   3584   // subsequent checks.  For a popup, the document's URL may become the opener
   3585   // window's URL if the opener has called document.write().
   3586   // See http://crbug.com/93517.
   3587   GURL old_url(info.frame->dataSource()->request().url());
   3588 
   3589   // Detect when we're crossing a permission-based boundary (e.g. into or out of
   3590   // an extension or app origin, leaving a WebUI page, etc). We only care about
   3591   // top-level navigations (not iframes). But we sometimes navigate to
   3592   // about:blank to clear a tab, and we want to still allow that.
   3593   //
   3594   // Note: this is known to break POST submissions when crossing process
   3595   // boundaries until http://crbug.com/101395 is fixed.  This is better for
   3596   // security than loading a WebUI, extension or app page in the wrong process.
   3597   // POST requests don't work because this mechanism does not preserve form
   3598   // POST data. We will need to send the request's httpBody data up to the
   3599   // browser process, and issue a special POST navigation in WebKit (via
   3600   // FrameLoader::loadFrameRequest). See ResourceDispatcher and WebURLLoaderImpl
   3601   // for examples of how to send the httpBody data.
   3602   if (!info.frame->parent() && is_content_initiated &&
   3603       !url.SchemeIs(url::kAboutScheme)) {
   3604     bool send_referrer = false;
   3605 
   3606     // All navigations to or from WebUI URLs or within WebUI-enabled
   3607     // RenderProcesses must be handled by the browser process so that the
   3608     // correct bindings and data sources can be registered.
   3609     // Similarly, navigations to view-source URLs or within ViewSource mode
   3610     // must be handled by the browser process (except for reloads - those are
   3611     // safe to leave within the renderer).
   3612     // Lastly, access to file:// URLs from non-file:// URL pages must be
   3613     // handled by the browser so that ordinary renderer processes don't get
   3614     // blessed with file permissions.
   3615     int cumulative_bindings = RenderProcess::current()->GetEnabledBindings();
   3616     bool is_initial_navigation = render_view_->page_id_ == -1;
   3617     bool should_fork = HasWebUIScheme(url) || HasWebUIScheme(old_url) ||
   3618         (cumulative_bindings & BINDINGS_POLICY_WEB_UI) ||
   3619         url.SchemeIs(kViewSourceScheme) ||
   3620         (info.frame->isViewSourceModeEnabled() &&
   3621             info.navigationType != blink::WebNavigationTypeReload);
   3622 
   3623     if (!should_fork && url.SchemeIs(url::kFileScheme)) {
   3624       // Fork non-file to file opens.  Check the opener URL if this is the
   3625       // initial navigation in a newly opened window.
   3626       GURL source_url(old_url);
   3627       if (is_initial_navigation && source_url.is_empty() &&
   3628           info.frame->opener())
   3629         source_url = info.frame->opener()->top()->document().url();
   3630       DCHECK(!source_url.is_empty());
   3631       should_fork = !source_url.SchemeIs(url::kFileScheme);
   3632     }
   3633 
   3634     if (!should_fork) {
   3635       // Give the embedder a chance.
   3636       should_fork = GetContentClient()->renderer()->ShouldFork(
   3637           info.frame, url, info.urlRequest.httpMethod().utf8(),
   3638           is_initial_navigation, info.isRedirect, &send_referrer);
   3639     }
   3640 
   3641     if (should_fork) {
   3642       OpenURL(info.frame, url, send_referrer ? referrer : Referrer(),
   3643               info.defaultPolicy);
   3644       return blink::WebNavigationPolicyIgnore;  // Suppress the load here.
   3645     }
   3646   }
   3647 
   3648   // Detect when a page is "forking" a new tab that can be safely rendered in
   3649   // its own process.  This is done by sites like Gmail that try to open links
   3650   // in new windows without script connections back to the original page.  We
   3651   // treat such cases as browser navigations (in which we will create a new
   3652   // renderer for a cross-site navigation), rather than WebKit navigations.
   3653   //
   3654   // We use the following heuristic to decide whether to fork a new page in its
   3655   // own process:
   3656   // The parent page must open a new tab to about:blank, set the new tab's
   3657   // window.opener to null, and then redirect the tab to a cross-site URL using
   3658   // JavaScript.
   3659   //
   3660   // TODO(creis): Deprecate this logic once we can rely on rel=noreferrer
   3661   // (see below).
   3662   bool is_fork =
   3663       // Must start from a tab showing about:blank, which is later redirected.
   3664       old_url == GURL(url::kAboutBlankURL) &&
   3665       // Must be the first real navigation of the tab.
   3666       render_view_->historyBackListCount() < 1 &&
   3667       render_view_->historyForwardListCount() < 1 &&
   3668       // The parent page must have set the child's window.opener to null before
   3669       // redirecting to the desired URL.
   3670       info.frame->opener() == NULL &&
   3671       // Must be a top-level frame.
   3672       info.frame->parent() == NULL &&
   3673       // Must not have issued the request from this page.
   3674       is_content_initiated &&
   3675       // Must be targeted at the current tab.
   3676       info.defaultPolicy == blink::WebNavigationPolicyCurrentTab &&
   3677       // Must be a JavaScript navigation, which appears as "other".
   3678       info.navigationType == blink::WebNavigationTypeOther;
   3679 
   3680   if (is_fork) {
   3681     // Open the URL via the browser, not via WebKit.
   3682     OpenURL(info.frame, url, Referrer(), info.defaultPolicy);
   3683     return blink::WebNavigationPolicyIgnore;
   3684   }
   3685 
   3686   return info.defaultPolicy;
   3687 }
   3688 
   3689 void RenderFrameImpl::OpenURL(WebFrame* frame,
   3690                               const GURL& url,
   3691                               const Referrer& referrer,
   3692                               WebNavigationPolicy policy) {
   3693   DCHECK_EQ(frame_, frame);
   3694 
   3695   FrameHostMsg_OpenURL_Params params;
   3696   params.url = url;
   3697   params.referrer = referrer;
   3698   params.disposition = RenderViewImpl::NavigationPolicyToDisposition(policy);
   3699   WebDataSource* ds = frame->provisionalDataSource();
   3700   if (ds) {
   3701     DocumentState* document_state = DocumentState::FromDataSource(ds);
   3702     NavigationState* navigation_state = document_state->navigation_state();
   3703     if (navigation_state->is_content_initiated()) {
   3704       params.should_replace_current_entry = ds->replacesCurrentHistoryItem();
   3705     } else {
   3706       // This is necessary to preserve the should_replace_current_entry value on
   3707       // cross-process redirects, in the event it was set by a previous process.
   3708       //
   3709       // TODO(davidben): Avoid this awkward duplication of state. See comment on
   3710       // NavigationState::should_replace_current_entry().
   3711       params.should_replace_current_entry =
   3712           navigation_state->should_replace_current_entry();
   3713     }
   3714   } else {
   3715     params.should_replace_current_entry = false;
   3716   }
   3717   params.user_gesture = WebUserGestureIndicator::isProcessingUserGesture();
   3718   if (GetContentClient()->renderer()->AllowPopup())
   3719     params.user_gesture = true;
   3720 
   3721   if (policy == blink::WebNavigationPolicyNewBackgroundTab ||
   3722       policy == blink::WebNavigationPolicyNewForegroundTab ||
   3723       policy == blink::WebNavigationPolicyNewWindow ||
   3724       policy == blink::WebNavigationPolicyNewPopup) {
   3725     WebUserGestureIndicator::consumeUserGesture();
   3726   }
   3727 
   3728   Send(new FrameHostMsg_OpenURL(routing_id_, params));
   3729 }
   3730 
   3731 void RenderFrameImpl::UpdateEncoding(WebFrame* frame,
   3732                                      const std::string& encoding_name) {
   3733   // Only update main frame's encoding_name.
   3734   if (!frame->parent())
   3735     Send(new FrameHostMsg_UpdateEncoding(routing_id_, encoding_name));
   3736 }
   3737 
   3738 void RenderFrameImpl::SyncSelectionIfRequired() {
   3739   base::string16 text;
   3740   size_t offset;
   3741   gfx::Range range;
   3742 #if defined(ENABLE_PLUGINS)
   3743   if (render_view_->focused_pepper_plugin_) {
   3744     render_view_->focused_pepper_plugin_->GetSurroundingText(&text, &range);
   3745     offset = 0;  // Pepper API does not support offset reporting.
   3746     // TODO(kinaba): cut as needed.
   3747   } else
   3748 #endif
   3749   {
   3750     size_t location, length;
   3751     if (!GetRenderWidget()->webwidget()->caretOrSelectionRange(
   3752             &location, &length)) {
   3753       return;
   3754     }
   3755 
   3756     range = gfx::Range(location, location + length);
   3757 
   3758     if (GetRenderWidget()->webwidget()->textInputInfo().type !=
   3759             blink::WebTextInputTypeNone) {
   3760       // If current focused element is editable, we will send 100 more chars
   3761       // before and after selection. It is for input method surrounding text
   3762       // feature.
   3763       if (location > kExtraCharsBeforeAndAfterSelection)
   3764         offset = location - kExtraCharsBeforeAndAfterSelection;
   3765       else
   3766         offset = 0;
   3767       length = location + length - offset + kExtraCharsBeforeAndAfterSelection;
   3768       WebRange webrange = WebRange::fromDocumentRange(frame_, offset, length);
   3769       if (!webrange.isNull())
   3770         text = WebRange::fromDocumentRange(
   3771             frame_, offset, length).toPlainText();
   3772     } else {
   3773       offset = location;
   3774       text = frame_->selectionAsText();
   3775       // http://crbug.com/101435
   3776       // In some case, frame->selectionAsText() returned text's length is not
   3777       // equal to the length returned from webwidget()->caretOrSelectionRange().
   3778       // So we have to set the range according to text.length().
   3779       range.set_end(range.start() + text.length());
   3780     }
   3781   }
   3782 
   3783   // Sometimes we get repeated didChangeSelection calls from webkit when
   3784   // the selection hasn't actually changed. We don't want to report these
   3785   // because it will cause us to continually claim the X clipboard.
   3786   if (selection_text_offset_ != offset ||
   3787       selection_range_ != range ||
   3788       selection_text_ != text) {
   3789     selection_text_ = text;
   3790     selection_text_offset_ = offset;
   3791     selection_range_ = range;
   3792     // This IPC is dispatched by RenderWidetHost, so use its routing ID.
   3793     Send(new ViewHostMsg_SelectionChanged(
   3794         GetRenderWidget()->routing_id(), text, offset, range));
   3795   }
   3796   GetRenderWidget()->UpdateSelectionBounds();
   3797 }
   3798 
   3799 void RenderFrameImpl::InitializeUserMediaClient() {
   3800   if (!RenderThreadImpl::current())  // Will be NULL during unit tests.
   3801     return;
   3802 
   3803 #if defined(OS_ANDROID)
   3804   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableWebRTC))
   3805     return;
   3806 #endif
   3807 
   3808 #if defined(ENABLE_WEBRTC)
   3809   DCHECK(!web_user_media_client_);
   3810   web_user_media_client_ = new UserMediaClientImpl(
   3811       this,
   3812       RenderThreadImpl::current()->GetPeerConnectionDependencyFactory(),
   3813       make_scoped_ptr(new MediaStreamDispatcher(this)).Pass());
   3814 #endif
   3815 }
   3816 
   3817 WebMediaPlayer* RenderFrameImpl::CreateWebMediaPlayerForMediaStream(
   3818     const blink::WebURL& url,
   3819     WebMediaPlayerClient* client) {
   3820 #if defined(ENABLE_WEBRTC)
   3821 #if defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL)
   3822   bool found_neon =
   3823       (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0;
   3824   UMA_HISTOGRAM_BOOLEAN("Platform.WebRtcNEONFound", found_neon);
   3825 #endif  // defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL)
   3826   return new WebMediaPlayerMS(frame_, client, weak_factory_.GetWeakPtr(),
   3827                               new RenderMediaLog(),
   3828                               CreateRendererFactory());
   3829 #else
   3830   return NULL;
   3831 #endif  // defined(ENABLE_WEBRTC)
   3832 }
   3833 
   3834 scoped_ptr<MediaStreamRendererFactory>
   3835 RenderFrameImpl::CreateRendererFactory() {
   3836 #if defined(ENABLE_WEBRTC)
   3837   return scoped_ptr<MediaStreamRendererFactory>(
   3838       new MediaStreamRendererFactory());
   3839 #else
   3840   return scoped_ptr<MediaStreamRendererFactory>(
   3841       static_cast<MediaStreamRendererFactory*>(NULL));
   3842 #endif
   3843 }
   3844 
   3845 GURL RenderFrameImpl::GetLoadingUrl() const {
   3846   WebDataSource* ds = frame_->dataSource();
   3847   if (ds->hasUnreachableURL())
   3848     return ds->unreachableURL();
   3849 
   3850   const WebURLRequest& request = ds->request();
   3851   return request.url();
   3852 }
   3853 
   3854 #if defined(OS_ANDROID)
   3855 
   3856 WebMediaPlayer* RenderFrameImpl::CreateAndroidWebMediaPlayer(
   3857     const blink::WebURL& url,
   3858     WebMediaPlayerClient* client,
   3859     blink::WebContentDecryptionModule* initial_cdm) {
   3860   GpuChannelHost* gpu_channel_host =
   3861       RenderThreadImpl::current()->EstablishGpuChannelSync(
   3862           CAUSE_FOR_GPU_LAUNCH_VIDEODECODEACCELERATOR_INITIALIZE);
   3863   if (!gpu_channel_host) {
   3864     LOG(ERROR) << "Failed to establish GPU channel for media player";
   3865     return NULL;
   3866   }
   3867 
   3868   scoped_refptr<StreamTextureFactory> stream_texture_factory;
   3869   if (SynchronousCompositorFactory* factory =
   3870           SynchronousCompositorFactory::GetInstance()) {
   3871     stream_texture_factory = factory->CreateStreamTextureFactory(routing_id_);
   3872   } else {
   3873     scoped_refptr<webkit::gpu::ContextProviderWebContext> context_provider =
   3874         RenderThreadImpl::current()->SharedMainThreadContextProvider();
   3875 
   3876     if (!context_provider.get()) {
   3877       LOG(ERROR) << "Failed to get context3d for media player";
   3878       return NULL;
   3879     }
   3880 
   3881     stream_texture_factory = StreamTextureFactoryImpl::Create(
   3882         context_provider, gpu_channel_host, routing_id_);
   3883   }
   3884 
   3885   return new WebMediaPlayerAndroid(
   3886       frame_,
   3887       client,
   3888       weak_factory_.GetWeakPtr(),
   3889       GetMediaPlayerManager(),
   3890       GetCdmManager(),
   3891       initial_cdm,
   3892       stream_texture_factory,
   3893       RenderThreadImpl::current()->GetMediaThreadTaskRunner(),
   3894       new RenderMediaLog());
   3895 }
   3896 
   3897 RendererMediaPlayerManager* RenderFrameImpl::GetMediaPlayerManager() {
   3898   if (!media_player_manager_)
   3899     media_player_manager_ = new RendererMediaPlayerManager(this);
   3900   return media_player_manager_;
   3901 }
   3902 
   3903 #endif  // defined(OS_ANDROID)
   3904 
   3905 #if defined(ENABLE_BROWSER_CDMS)
   3906 RendererCdmManager* RenderFrameImpl::GetCdmManager() {
   3907   if (!cdm_manager_)
   3908     cdm_manager_ = new RendererCdmManager(this);
   3909   return cdm_manager_;
   3910 }
   3911 #endif  // defined(ENABLE_BROWSER_CDMS)
   3912 
   3913 }  // namespace content
   3914