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