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/command_line.h"
     11 #include "base/i18n/char_iterator.h"
     12 #include "base/strings/utf_string_conversions.h"
     13 #include "base/time/time.h"
     14 #include "content/child/appcache/appcache_dispatcher.h"
     15 #include "content/child/plugin_messages.h"
     16 #include "content/child/quota_dispatcher.h"
     17 #include "content/child/request_extra_data.h"
     18 #include "content/child/service_worker/web_service_worker_provider_impl.h"
     19 #include "content/common/frame_messages.h"
     20 #include "content/common/socket_stream_handle_data.h"
     21 #include "content/common/swapped_out_messages.h"
     22 #include "content/common/view_messages.h"
     23 #include "content/public/common/content_constants.h"
     24 #include "content/public/common/content_switches.h"
     25 #include "content/public/common/url_constants.h"
     26 #include "content/public/renderer/content_renderer_client.h"
     27 #include "content/public/renderer/document_state.h"
     28 #include "content/public/renderer/navigation_state.h"
     29 #include "content/public/renderer/render_frame_observer.h"
     30 #include "content/renderer/accessibility/renderer_accessibility.h"
     31 #include "content/renderer/browser_plugin/browser_plugin.h"
     32 #include "content/renderer/browser_plugin/browser_plugin_manager.h"
     33 #include "content/renderer/internal_document_state_data.h"
     34 #include "content/renderer/npapi/plugin_channel_host.h"
     35 #include "content/renderer/render_thread_impl.h"
     36 #include "content/renderer/render_view_impl.h"
     37 #include "content/renderer/render_widget_fullscreen_pepper.h"
     38 #include "content/renderer/renderer_webapplicationcachehost_impl.h"
     39 #include "content/renderer/websharedworker_proxy.h"
     40 #include "net/base/net_errors.h"
     41 #include "net/http/http_util.h"
     42 #include "third_party/WebKit/public/platform/WebStorageQuotaCallbacks.h"
     43 #include "third_party/WebKit/public/platform/WebString.h"
     44 #include "third_party/WebKit/public/platform/WebURL.h"
     45 #include "third_party/WebKit/public/platform/WebURLError.h"
     46 #include "third_party/WebKit/public/platform/WebURLResponse.h"
     47 #include "third_party/WebKit/public/platform/WebVector.h"
     48 #include "third_party/WebKit/public/web/WebDocument.h"
     49 #include "third_party/WebKit/public/web/WebFrame.h"
     50 #include "third_party/WebKit/public/web/WebNavigationPolicy.h"
     51 #include "third_party/WebKit/public/web/WebPlugin.h"
     52 #include "third_party/WebKit/public/web/WebPluginParams.h"
     53 #include "third_party/WebKit/public/web/WebSearchableFormData.h"
     54 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
     55 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
     56 #include "third_party/WebKit/public/web/WebView.h"
     57 #include "webkit/child/weburlresponse_extradata_impl.h"
     58 
     59 #if defined(ENABLE_PLUGINS)
     60 #include "content/renderer/npapi/webplugin_impl.h"
     61 #include "content/renderer/pepper/pepper_browser_connection.h"
     62 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
     63 #include "content/renderer/pepper/pepper_webplugin_impl.h"
     64 #include "content/renderer/pepper/plugin_module.h"
     65 #endif
     66 
     67 #if defined(ENABLE_WEBRTC)
     68 #include "content/renderer/media/rtc_peer_connection_handler.h"
     69 #endif
     70 
     71 using blink::WebDataSource;
     72 using blink::WebDocument;
     73 using blink::WebFrame;
     74 using blink::WebNavigationPolicy;
     75 using blink::WebPluginParams;
     76 using blink::WebReferrerPolicy;
     77 using blink::WebSearchableFormData;
     78 using blink::WebSecurityOrigin;
     79 using blink::WebServiceWorkerProvider;
     80 using blink::WebStorageQuotaCallbacks;
     81 using blink::WebString;
     82 using blink::WebURL;
     83 using blink::WebURLError;
     84 using blink::WebURLRequest;
     85 using blink::WebURLResponse;
     86 using blink::WebUserGestureIndicator;
     87 using blink::WebVector;
     88 using blink::WebView;
     89 using base::Time;
     90 using base::TimeDelta;
     91 using webkit_glue::WebURLResponseExtraDataImpl;
     92 
     93 namespace content {
     94 
     95 namespace {
     96 
     97 typedef std::map<blink::WebFrame*, RenderFrameImpl*> FrameMap;
     98 base::LazyInstance<FrameMap> g_child_frame_map = LAZY_INSTANCE_INITIALIZER;
     99 
    100 }  // namespace
    101 
    102 static RenderFrameImpl* (*g_create_render_frame_impl)(RenderViewImpl*, int32) =
    103     NULL;
    104 
    105 // static
    106 RenderFrameImpl* RenderFrameImpl::Create(RenderViewImpl* render_view,
    107                                          int32 routing_id) {
    108   DCHECK(routing_id != MSG_ROUTING_NONE);
    109 
    110   if (g_create_render_frame_impl)
    111     return g_create_render_frame_impl(render_view, routing_id);
    112   else
    113     return new RenderFrameImpl(render_view, routing_id);
    114 }
    115 
    116 // static
    117 void RenderFrameImpl::InstallCreateHook(
    118     RenderFrameImpl* (*create_render_frame_impl)(RenderViewImpl*, int32)) {
    119   CHECK(!g_create_render_frame_impl);
    120   g_create_render_frame_impl = create_render_frame_impl;
    121 }
    122 
    123 // RenderFrameImpl ----------------------------------------------------------
    124 RenderFrameImpl::RenderFrameImpl(RenderViewImpl* render_view, int routing_id)
    125     : render_view_(render_view),
    126       routing_id_(routing_id),
    127       is_swapped_out_(false),
    128       is_detaching_(false) {
    129   RenderThread::Get()->AddRoute(routing_id_, this);
    130 #if defined(ENABLE_PLUGINS)
    131   new PepperBrowserConnection(this);
    132 #endif
    133 
    134   GetContentClient()->renderer()->RenderFrameCreated(this);
    135 }
    136 
    137 RenderFrameImpl::~RenderFrameImpl() {
    138   FOR_EACH_OBSERVER(RenderFrameObserver, observers_, RenderFrameGone());
    139   FOR_EACH_OBSERVER(RenderFrameObserver, observers_, OnDestruct());
    140   RenderThread::Get()->RemoveRoute(routing_id_);
    141 }
    142 
    143 RenderWidget* RenderFrameImpl::GetRenderWidget() {
    144   return render_view_;
    145 }
    146 
    147 #if defined(ENABLE_PLUGINS)
    148 void RenderFrameImpl::PepperPluginCreated(RendererPpapiHost* host) {
    149   FOR_EACH_OBSERVER(RenderFrameObserver, observers_,
    150                     DidCreatePepperPlugin(host));
    151 }
    152 
    153 void RenderFrameImpl::PepperInstanceCreated(
    154     PepperPluginInstanceImpl* instance) {
    155   active_pepper_instances_.insert(instance);
    156 }
    157 
    158 void RenderFrameImpl::PepperInstanceDeleted(
    159     PepperPluginInstanceImpl* instance) {
    160   active_pepper_instances_.erase(instance);
    161 
    162   if (render_view_->pepper_last_mouse_event_target() == instance)
    163     render_view_->set_pepper_last_mouse_event_target(NULL);
    164   if (render_view_->focused_pepper_plugin() == instance)
    165     PepperFocusChanged(instance, false);
    166 }
    167 
    168 void RenderFrameImpl::PepperDidChangeCursor(
    169     PepperPluginInstanceImpl* instance,
    170     const blink::WebCursorInfo& cursor) {
    171   // Update the cursor appearance immediately if the requesting plugin is the
    172   // one which receives the last mouse event. Otherwise, the new cursor won't be
    173   // picked up until the plugin gets the next input event. That is bad if, e.g.,
    174   // the plugin would like to set an invisible cursor when there isn't any user
    175   // input for a while.
    176   if (instance == render_view_->pepper_last_mouse_event_target())
    177     GetRenderWidget()->didChangeCursor(cursor);
    178 }
    179 
    180 void RenderFrameImpl::PepperDidReceiveMouseEvent(
    181     PepperPluginInstanceImpl* instance) {
    182   render_view_->set_pepper_last_mouse_event_target(instance);
    183 }
    184 
    185 void RenderFrameImpl::PepperFocusChanged(PepperPluginInstanceImpl* instance,
    186                                          bool focused) {
    187   if (focused)
    188     render_view_->set_focused_pepper_plugin(instance);
    189   else if (render_view_->focused_pepper_plugin() == instance)
    190     render_view_->set_focused_pepper_plugin(NULL);
    191 
    192   GetRenderWidget()->UpdateTextInputType();
    193   GetRenderWidget()->UpdateSelectionBounds();
    194 }
    195 
    196 void RenderFrameImpl::PepperTextInputTypeChanged(
    197     PepperPluginInstanceImpl* instance) {
    198   if (instance != render_view_->focused_pepper_plugin())
    199     return;
    200 
    201   GetRenderWidget()->UpdateTextInputType();
    202   if (render_view_->renderer_accessibility()) {
    203     render_view_->renderer_accessibility()->FocusedNodeChanged(
    204         blink::WebNode());
    205   }
    206 }
    207 
    208 void RenderFrameImpl::PepperCaretPositionChanged(
    209     PepperPluginInstanceImpl* instance) {
    210   if (instance != render_view_->focused_pepper_plugin())
    211     return;
    212   GetRenderWidget()->UpdateSelectionBounds();
    213 }
    214 
    215 void RenderFrameImpl::PepperCancelComposition(
    216     PepperPluginInstanceImpl* instance) {
    217   if (instance != render_view_->focused_pepper_plugin())
    218     return;
    219   Send(new ViewHostMsg_ImeCancelComposition(render_view_->GetRoutingID()));;
    220 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
    221   GetRenderWidget()->UpdateCompositionInfo(true);
    222 #endif
    223 }
    224 
    225 void RenderFrameImpl::PepperSelectionChanged(
    226     PepperPluginInstanceImpl* instance) {
    227   if (instance != render_view_->focused_pepper_plugin())
    228     return;
    229   render_view_->SyncSelectionIfRequired();
    230 }
    231 
    232 RenderWidgetFullscreenPepper* RenderFrameImpl::CreatePepperFullscreenContainer(
    233     PepperPluginInstanceImpl* plugin) {
    234   GURL active_url;
    235   if (render_view_->webview() && render_view_->webview()->mainFrame())
    236     active_url = GURL(render_view_->webview()->mainFrame()->document().url());
    237   RenderWidgetFullscreenPepper* widget = RenderWidgetFullscreenPepper::Create(
    238       GetRenderWidget()->routing_id(), plugin, active_url,
    239       GetRenderWidget()->screenInfo());
    240   widget->show(blink::WebNavigationPolicyIgnore);
    241   return widget;
    242 }
    243 
    244 bool RenderFrameImpl::IsPepperAcceptingCompositionEvents() const {
    245   if (!render_view_->focused_pepper_plugin())
    246     return false;
    247   return render_view_->focused_pepper_plugin()->
    248       IsPluginAcceptingCompositionEvents();
    249 }
    250 
    251 void RenderFrameImpl::PluginCrashed(const base::FilePath& plugin_path,
    252                                    base::ProcessId plugin_pid) {
    253   // TODO(jam): dispatch this IPC in RenderFrameHost and switch to use
    254   // routing_id_ as a result.
    255   Send(new FrameHostMsg_PluginCrashed(routing_id_, plugin_path, plugin_pid));
    256 }
    257 
    258 void RenderFrameImpl::DidInitiatePaint() {
    259   // Notify all instances that we painted.  The same caveats apply as for
    260   // ViewFlushedPaint regarding instances closing themselves, so we take
    261   // similar precautions.
    262   PepperPluginSet plugins = active_pepper_instances_;
    263   for (PepperPluginSet::iterator i = plugins.begin(); i != plugins.end(); ++i) {
    264     if (active_pepper_instances_.find(*i) != active_pepper_instances_.end())
    265       (*i)->ViewInitiatedPaint();
    266   }
    267 }
    268 
    269 void RenderFrameImpl::DidFlushPaint() {
    270   // Notify all instances that we flushed. This will call into the plugin, and
    271   // we it may ask to close itself as a result. This will, in turn, modify our
    272   // set, possibly invalidating the iterator. So we iterate on a copy that
    273   // won't change out from under us.
    274   PepperPluginSet plugins = active_pepper_instances_;
    275   for (PepperPluginSet::iterator i = plugins.begin(); i != plugins.end(); ++i) {
    276     // The copy above makes sure our iterator is never invalid if some plugins
    277     // are destroyed. But some plugin may decide to close all of its views in
    278     // response to a paint in one of them, so we need to make sure each one is
    279     // still "current" before using it.
    280     //
    281     // It's possible that a plugin was destroyed, but another one was created
    282     // with the same address. In this case, we'll call ViewFlushedPaint on that
    283     // new plugin. But that's OK for this particular case since we're just
    284     // notifying all of our instances that the view flushed, and the new one is
    285     // one of our instances.
    286     //
    287     // What about the case where a new one is created in a callback at a new
    288     // address and we don't issue the callback? We're still OK since this
    289     // callback is used for flush callbacks and we could not have possibly
    290     // started a new paint for the new plugin while processing a previous paint
    291     // for an existing one.
    292     if (active_pepper_instances_.find(*i) != active_pepper_instances_.end())
    293       (*i)->ViewFlushedPaint();
    294   }
    295 }
    296 
    297 PepperPluginInstanceImpl* RenderFrameImpl::GetBitmapForOptimizedPluginPaint(
    298       const gfx::Rect& paint_bounds,
    299       TransportDIB** dib,
    300       gfx::Rect* location,
    301       gfx::Rect* clip,
    302       float* scale_factor) {
    303   for (PepperPluginSet::iterator i = active_pepper_instances_.begin();
    304        i != active_pepper_instances_.end(); ++i) {
    305     PepperPluginInstanceImpl* instance = *i;
    306     // In Flash fullscreen , the plugin contents should be painted onto the
    307     // fullscreen widget instead of the web page.
    308     if (!instance->FlashIsFullscreenOrPending() &&
    309         instance->GetBitmapForOptimizedPluginPaint(paint_bounds, dib, location,
    310                                                    clip, scale_factor))
    311       return *i;
    312   }
    313   return NULL;
    314 }
    315 
    316 void RenderFrameImpl::PageVisibilityChanged(bool shown) {
    317   // Inform PPAPI plugins that their page is no longer visible.
    318   for (PepperPluginSet::iterator i = active_pepper_instances_.begin();
    319        i != active_pepper_instances_.end(); ++i)
    320     (*i)->PageVisibilityChanged(shown);
    321 }
    322 
    323 void RenderFrameImpl::OnSetFocus(bool enable) {
    324   // Notify all Pepper plugins.
    325   for (PepperPluginSet::iterator i = active_pepper_instances_.begin();
    326        i != active_pepper_instances_.end(); ++i)
    327     (*i)->SetContentAreaFocus(enable);
    328 }
    329 
    330 void RenderFrameImpl::WillHandleMouseEvent(const blink::WebMouseEvent& event) {
    331   // This method is called for every mouse event that the render view receives.
    332   // And then the mouse event is forwarded to WebKit, which dispatches it to the
    333   // event target. Potentially a Pepper plugin will receive the event.
    334   // In order to tell whether a plugin gets the last mouse event and which it
    335   // is, we set |pepper_last_mouse_event_target_| to NULL here. If a plugin gets
    336   // the event, it will notify us via DidReceiveMouseEvent() and set itself as
    337   // |pepper_last_mouse_event_target_|.
    338   render_view_->set_pepper_last_mouse_event_target(NULL);
    339 }
    340 
    341 void RenderFrameImpl::SimulateImeSetComposition(
    342     const base::string16& text,
    343     const std::vector<blink::WebCompositionUnderline>& underlines,
    344     int selection_start,
    345     int selection_end) {
    346   render_view_->OnImeSetComposition(
    347       text, underlines, selection_start, selection_end);
    348 }
    349 
    350 void RenderFrameImpl::SimulateImeConfirmComposition(
    351     const base::string16& text,
    352     const gfx::Range& replacement_range) {
    353   render_view_->OnImeConfirmComposition(text, replacement_range, false);
    354 }
    355 
    356 
    357 void RenderFrameImpl::OnImeSetComposition(
    358     const base::string16& text,
    359     const std::vector<blink::WebCompositionUnderline>& underlines,
    360     int selection_start,
    361     int selection_end) {
    362   // When a PPAPI plugin has focus, we bypass WebKit.
    363   if (!IsPepperAcceptingCompositionEvents()) {
    364     pepper_composition_text_ = text;
    365   } else {
    366     // TODO(kinaba) currently all composition events are sent directly to
    367     // plugins. Use DOM event mechanism after WebKit is made aware about
    368     // plugins that support composition.
    369     // The code below mimics the behavior of WebCore::Editor::setComposition.
    370 
    371     // Empty -> nonempty: composition started.
    372     if (pepper_composition_text_.empty() && !text.empty()) {
    373       render_view_->focused_pepper_plugin()->HandleCompositionStart(
    374           base::string16());
    375     }
    376     // Nonempty -> empty: composition canceled.
    377     if (!pepper_composition_text_.empty() && text.empty()) {
    378       render_view_->focused_pepper_plugin()->HandleCompositionEnd(
    379           base::string16());
    380     }
    381     pepper_composition_text_ = text;
    382     // Nonempty: composition is ongoing.
    383     if (!pepper_composition_text_.empty()) {
    384       render_view_->focused_pepper_plugin()->HandleCompositionUpdate(
    385           pepper_composition_text_, underlines, selection_start,
    386           selection_end);
    387     }
    388   }
    389 }
    390 
    391 void RenderFrameImpl::OnImeConfirmComposition(
    392     const base::string16& text,
    393     const gfx::Range& replacement_range,
    394     bool keep_selection) {
    395   // When a PPAPI plugin has focus, we bypass WebKit.
    396   // Here, text.empty() has a special meaning. It means to commit the last
    397   // update of composition text (see
    398   // RenderWidgetHost::ImeConfirmComposition()).
    399   const base::string16& last_text = text.empty() ? pepper_composition_text_
    400                                                  : text;
    401 
    402   // last_text is empty only when both text and pepper_composition_text_ is.
    403   // Ignore it.
    404   if (last_text.empty())
    405     return;
    406 
    407   if (!IsPepperAcceptingCompositionEvents()) {
    408     base::i18n::UTF16CharIterator iterator(&last_text);
    409     int32 i = 0;
    410     while (iterator.Advance()) {
    411       blink::WebKeyboardEvent char_event;
    412       char_event.type = blink::WebInputEvent::Char;
    413       char_event.timeStampSeconds = base::Time::Now().ToDoubleT();
    414       char_event.modifiers = 0;
    415       char_event.windowsKeyCode = last_text[i];
    416       char_event.nativeKeyCode = last_text[i];
    417 
    418       const int32 char_start = i;
    419       for (; i < iterator.array_pos(); ++i) {
    420         char_event.text[i - char_start] = last_text[i];
    421         char_event.unmodifiedText[i - char_start] = last_text[i];
    422       }
    423 
    424       if (GetRenderWidget()->webwidget())
    425         GetRenderWidget()->webwidget()->handleInputEvent(char_event);
    426     }
    427   } else {
    428     // Mimics the order of events sent by WebKit.
    429     // See WebCore::Editor::setComposition() for the corresponding code.
    430     render_view_->focused_pepper_plugin()->HandleCompositionEnd(last_text);
    431     render_view_->focused_pepper_plugin()->HandleTextInput(last_text);
    432   }
    433   pepper_composition_text_.clear();
    434 }
    435 
    436 #endif  // ENABLE_PLUGINS
    437 
    438 bool RenderFrameImpl::Send(IPC::Message* message) {
    439   if (is_detaching_ ||
    440       ((is_swapped_out_ || render_view_->is_swapped_out()) &&
    441        !SwappedOutMessages::CanSendWhileSwappedOut(message))) {
    442     delete message;
    443     return false;
    444   }
    445 
    446   return RenderThread::Get()->Send(message);
    447 }
    448 
    449 bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) {
    450   ObserverListBase<RenderFrameObserver>::Iterator it(observers_);
    451   RenderFrameObserver* observer;
    452   while ((observer = it.GetNext()) != NULL) {
    453     if (observer->OnMessageReceived(msg))
    454       return true;
    455   }
    456 
    457   // TODO(ajwong): Fill in with message handlers as various components
    458   // are migrated over to understand frames.
    459   return false;
    460 }
    461 
    462 RenderView* RenderFrameImpl::GetRenderView() {
    463   return render_view_;
    464 }
    465 
    466 int RenderFrameImpl::GetRoutingID() {
    467   return routing_id_;
    468 }
    469 
    470 WebPreferences& RenderFrameImpl::GetWebkitPreferences() {
    471   return render_view_->GetWebkitPreferences();
    472 }
    473 
    474 int RenderFrameImpl::ShowContextMenu(ContextMenuClient* client,
    475                                      const ContextMenuParams& params) {
    476   return render_view_->ShowContextMenu(client, params);
    477 }
    478 
    479 void RenderFrameImpl::CancelContextMenu(int request_id) {
    480   return render_view_->CancelContextMenu(request_id);
    481 }
    482 
    483 blink::WebPlugin* RenderFrameImpl::CreatePlugin(
    484     blink::WebFrame* frame,
    485     const WebPluginInfo& info,
    486     const blink::WebPluginParams& params) {
    487 #if defined(ENABLE_PLUGINS)
    488   bool pepper_plugin_was_registered = false;
    489   scoped_refptr<PluginModule> pepper_module(PluginModule::Create(
    490       this, info, &pepper_plugin_was_registered));
    491   if (pepper_plugin_was_registered) {
    492     if (pepper_module.get()) {
    493       // TODO(jam): change to take RenderFrame.
    494       return new PepperWebPluginImpl(
    495           pepper_module.get(), params, render_view_->AsWeakPtr(), this);
    496     }
    497   }
    498 #if defined(OS_CHROMEOS)
    499   LOG(WARNING) << "Pepper module/plugin creation failed.";
    500   return NULL;
    501 #else
    502   // TODO(jam): change to take RenderFrame.
    503   return new WebPluginImpl(frame, params, info.path, render_view_->AsWeakPtr(),
    504                            this);
    505 #endif
    506 #else
    507   return NULL;
    508 #endif
    509 }
    510 
    511 void RenderFrameImpl::LoadURLExternally(
    512     blink::WebFrame* frame,
    513     const blink::WebURLRequest& request,
    514     blink::WebNavigationPolicy policy) {
    515   loadURLExternally(frame, request, policy);
    516 }
    517 
    518 // blink::WebFrameClient implementation ----------------------------------------
    519 
    520 blink::WebPlugin* RenderFrameImpl::createPlugin(
    521     blink::WebFrame* frame,
    522     const blink::WebPluginParams& params) {
    523   blink::WebPlugin* plugin = NULL;
    524   if (GetContentClient()->renderer()->OverrideCreatePlugin(
    525           this, frame, params, &plugin)) {
    526     return plugin;
    527   }
    528 
    529   if (UTF16ToASCII(params.mimeType) == kBrowserPluginMimeType) {
    530     return render_view_->GetBrowserPluginManager()->CreateBrowserPlugin(
    531         render_view_, frame);
    532   }
    533 
    534 #if defined(ENABLE_PLUGINS)
    535   WebPluginInfo info;
    536   std::string mime_type;
    537   bool found = false;
    538   Send(new FrameHostMsg_GetPluginInfo(
    539       routing_id_, params.url, frame->top()->document().url(),
    540       params.mimeType.utf8(), &found, &info, &mime_type));
    541   if (!found)
    542     return NULL;
    543 
    544   WebPluginParams params_to_use = params;
    545   params_to_use.mimeType = WebString::fromUTF8(mime_type);
    546   return CreatePlugin(frame, info, params_to_use);
    547 #else
    548   return NULL;
    549 #endif  // defined(ENABLE_PLUGINS)
    550 }
    551 
    552 blink::WebMediaPlayer* RenderFrameImpl::createMediaPlayer(
    553     blink::WebFrame* frame,
    554     const blink::WebURL& url,
    555     blink::WebMediaPlayerClient* client) {
    556   // TODO(nasko): Moving the implementation here involves moving a few media
    557   // related client objects here or referencing them in the RenderView. Needs
    558   // more work to understand where the proper place for those objects is.
    559   return render_view_->CreateMediaPlayer(this, frame, url, client);
    560 }
    561 
    562 blink::WebApplicationCacheHost* RenderFrameImpl::createApplicationCacheHost(
    563     blink::WebFrame* frame,
    564     blink::WebApplicationCacheHostClient* client) {
    565   if (!frame || !frame->view())
    566     return NULL;
    567   return new RendererWebApplicationCacheHostImpl(
    568       RenderViewImpl::FromWebView(frame->view()), client,
    569       RenderThreadImpl::current()->appcache_dispatcher()->backend_proxy());
    570 }
    571 
    572 blink::WebWorkerPermissionClientProxy*
    573 RenderFrameImpl::createWorkerPermissionClientProxy(WebFrame* frame) {
    574   if (!frame || !frame->view())
    575     return NULL;
    576   return GetContentClient()->renderer()->CreateWorkerPermissionClientProxy(
    577       RenderViewImpl::FromWebView(frame->view()), frame);
    578 }
    579 
    580 blink::WebCookieJar* RenderFrameImpl::cookieJar(blink::WebFrame* frame) {
    581   return render_view_->cookieJar(frame);
    582 }
    583 
    584 blink::WebServiceWorkerProvider* RenderFrameImpl::createServiceWorkerProvider(
    585     blink::WebFrame* frame,
    586     blink::WebServiceWorkerProviderClient* client) {
    587   return new WebServiceWorkerProviderImpl(
    588       ChildThread::current()->thread_safe_sender(),
    589       make_scoped_ptr(client));
    590 }
    591 
    592 void RenderFrameImpl::didAccessInitialDocument(blink::WebFrame* frame) {
    593   render_view_->didAccessInitialDocument(frame);
    594 }
    595 
    596 blink::WebFrame* RenderFrameImpl::createChildFrame(
    597     blink::WebFrame* parent,
    598     const blink::WebString& name) {
    599   RenderFrameImpl* child_render_frame = this;
    600   long long child_frame_identifier = WebFrame::generateEmbedderIdentifier();
    601   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) {
    602     // Synchronously notify the browser of a child frame creation to get the
    603     // routing_id for the RenderFrame.
    604     int routing_id;
    605     Send(new FrameHostMsg_CreateChildFrame(routing_id_,
    606                                            parent->identifier(),
    607                                            child_frame_identifier,
    608                                            UTF16ToUTF8(name),
    609                                            &routing_id));
    610     child_render_frame = RenderFrameImpl::Create(render_view_, routing_id);
    611   }
    612 
    613   blink::WebFrame* web_frame = WebFrame::create(child_render_frame,
    614                                                 child_frame_identifier);
    615 
    616   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) {
    617     g_child_frame_map.Get().insert(
    618         std::make_pair(web_frame, child_render_frame));
    619   }
    620 
    621   return web_frame;
    622 }
    623 
    624 void RenderFrameImpl::didDisownOpener(blink::WebFrame* frame) {
    625   render_view_->didDisownOpener(frame);
    626 }
    627 
    628 void RenderFrameImpl::frameDetached(blink::WebFrame* frame) {
    629   // NOTE: This function is called on the frame that is being detached and not
    630   // the parent frame.  This is different from createChildFrame() which is
    631   // called on the parent frame.
    632   CHECK(!is_detaching_);
    633 
    634   int64 parent_frame_id = -1;
    635   if (frame->parent())
    636     parent_frame_id = frame->parent()->identifier();
    637 
    638   Send(new FrameHostMsg_Detach(routing_id_, parent_frame_id,
    639                                frame->identifier()));
    640 
    641   // Currently multiple WebCore::Frames can send frameDetached to a single
    642   // RenderFrameImpl. This is legacy behavior from when RenderViewImpl served
    643   // as a shared WebFrameClient for multiple Webcore::Frame objects. It also
    644   // prevents this class from entering the |is_detaching_| state because
    645   // even though one WebCore::Frame may have detached itself, others will
    646   // still need to use this object.
    647   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) {
    648     // The |is_detaching_| flag disables Send(). FrameHostMsg_Detach must be
    649     // sent before setting |is_detaching_| to true. In contrast, Observers
    650     // should only be notified afterwards so they cannot call back into and
    651     // have IPCs fired off.
    652     is_detaching_ = true;
    653   }
    654 
    655   // Call back to RenderViewImpl for observers to be notified.
    656   // TODO(nasko): Remove once we have RenderFrameObserver.
    657   render_view_->frameDetached(frame);
    658 
    659   frame->close();
    660 
    661   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) {
    662     // If the frame does not have a parent, it is the main frame. The main
    663     // frame is owned by the containing RenderViewHost so it does not require
    664     // any cleanup here.
    665     if (frame->parent()) {
    666       FrameMap::iterator it = g_child_frame_map.Get().find(frame);
    667       DCHECK(it != g_child_frame_map.Get().end());
    668       DCHECK_EQ(it->second, this);
    669       g_child_frame_map.Get().erase(it);
    670       delete this;
    671       // Object is invalid after this point.
    672     }
    673   }
    674 }
    675 
    676 void RenderFrameImpl::willClose(blink::WebFrame* frame) {
    677   // Call back to RenderViewImpl for observers to be notified.
    678   // TODO(nasko): Remove once we have RenderFrameObserver.
    679   render_view_->willClose(frame);
    680 }
    681 
    682 void RenderFrameImpl::didChangeName(blink::WebFrame* frame,
    683                                     const blink::WebString& name) {
    684   if (!render_view_->renderer_preferences_.report_frame_name_changes)
    685     return;
    686 
    687   render_view_->Send(
    688       new ViewHostMsg_UpdateFrameName(render_view_->GetRoutingID(),
    689                                       frame->identifier(),
    690                                       !frame->parent(),
    691                                       UTF16ToUTF8(name)));
    692 }
    693 
    694 void RenderFrameImpl::didMatchCSS(
    695     blink::WebFrame* frame,
    696     const blink::WebVector<blink::WebString>& newly_matching_selectors,
    697     const blink::WebVector<blink::WebString>& stopped_matching_selectors) {
    698   render_view_->didMatchCSS(
    699       frame, newly_matching_selectors, stopped_matching_selectors);
    700 }
    701 
    702 void RenderFrameImpl::loadURLExternally(blink::WebFrame* frame,
    703                                         const blink::WebURLRequest& request,
    704                                         blink::WebNavigationPolicy policy) {
    705   loadURLExternally(frame, request, policy, WebString());
    706 }
    707 
    708 void RenderFrameImpl::loadURLExternally(
    709     blink::WebFrame* frame,
    710     const blink::WebURLRequest& request,
    711     blink::WebNavigationPolicy policy,
    712     const blink::WebString& suggested_name) {
    713   Referrer referrer(RenderViewImpl::GetReferrerFromRequest(frame, request));
    714   if (policy == blink::WebNavigationPolicyDownload) {
    715     render_view_->Send(new ViewHostMsg_DownloadUrl(render_view_->GetRoutingID(),
    716                                                    request.url(), referrer,
    717                                                    suggested_name));
    718   } else {
    719     render_view_->OpenURL(frame, request.url(), referrer, policy);
    720   }
    721 }
    722 
    723 blink::WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation(
    724     blink::WebFrame* frame,
    725     blink::WebDataSource::ExtraData* extra_data,
    726     const blink::WebURLRequest& request,
    727     blink::WebNavigationType type,
    728     blink::WebNavigationPolicy default_policy,
    729     bool is_redirect) {
    730   return render_view_->decidePolicyForNavigation(
    731       frame, extra_data, request, type, default_policy, is_redirect);
    732 }
    733 
    734 blink::WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation(
    735     blink::WebFrame* frame,
    736     const blink::WebURLRequest& request,
    737     blink::WebNavigationType type,
    738     blink::WebNavigationPolicy default_policy,
    739     bool is_redirect) {
    740   return render_view_->decidePolicyForNavigation(
    741       frame, request, type, default_policy, is_redirect);
    742 }
    743 
    744 void RenderFrameImpl::willSendSubmitEvent(blink::WebFrame* frame,
    745                                           const blink::WebFormElement& form) {
    746   // Call back to RenderViewImpl for observers to be notified.
    747   // TODO(nasko): Remove once we have RenderFrameObserver.
    748   render_view_->willSendSubmitEvent(frame, form);
    749 }
    750 
    751 void RenderFrameImpl::willSubmitForm(blink::WebFrame* frame,
    752                                      const blink::WebFormElement& form) {
    753   DocumentState* document_state =
    754       DocumentState::FromDataSource(frame->provisionalDataSource());
    755   NavigationState* navigation_state = document_state->navigation_state();
    756   InternalDocumentStateData* internal_data =
    757       InternalDocumentStateData::FromDocumentState(document_state);
    758 
    759   if (PageTransitionCoreTypeIs(navigation_state->transition_type(),
    760                                PAGE_TRANSITION_LINK)) {
    761     navigation_state->set_transition_type(PAGE_TRANSITION_FORM_SUBMIT);
    762   }
    763 
    764   // Save these to be processed when the ensuing navigation is committed.
    765   WebSearchableFormData web_searchable_form_data(form);
    766   internal_data->set_searchable_form_url(web_searchable_form_data.url());
    767   internal_data->set_searchable_form_encoding(
    768       web_searchable_form_data.encoding().utf8());
    769 
    770   // Call back to RenderViewImpl for observers to be notified.
    771   // TODO(nasko): Remove once we have RenderFrameObserver.
    772   render_view_->willSubmitForm(frame, form);
    773 }
    774 
    775 void RenderFrameImpl::didCreateDataSource(blink::WebFrame* frame,
    776                                           blink::WebDataSource* datasource) {
    777   // TODO(nasko): Move implementation here. Needed state:
    778   // * pending_navigation_params_
    779   // * webview
    780   // Needed methods:
    781   // * PopulateDocumentStateFromPending
    782   // * CreateNavigationStateFromPending
    783   render_view_->didCreateDataSource(frame, datasource);
    784 }
    785 
    786 void RenderFrameImpl::didStartProvisionalLoad(blink::WebFrame* frame) {
    787   WebDataSource* ds = frame->provisionalDataSource();
    788 
    789   // In fast/loader/stop-provisional-loads.html, we abort the load before this
    790   // callback is invoked.
    791   if (!ds)
    792     return;
    793 
    794   DocumentState* document_state = DocumentState::FromDataSource(ds);
    795 
    796   // We should only navigate to swappedout:// when is_swapped_out_ is true.
    797   CHECK((ds->request().url() != GURL(kSwappedOutURL)) ||
    798         render_view_->is_swapped_out()) <<
    799         "Heard swappedout:// when not swapped out.";
    800 
    801   // Update the request time if WebKit has better knowledge of it.
    802   if (document_state->request_time().is_null()) {
    803     double event_time = ds->triggeringEventTime();
    804     if (event_time != 0.0)
    805       document_state->set_request_time(Time::FromDoubleT(event_time));
    806   }
    807 
    808   // Start time is only set after request time.
    809   document_state->set_start_load_time(Time::Now());
    810 
    811   bool is_top_most = !frame->parent();
    812   if (is_top_most) {
    813     render_view_->set_navigation_gesture(
    814         WebUserGestureIndicator::isProcessingUserGesture() ?
    815             NavigationGestureUser : NavigationGestureAuto);
    816   } else if (ds->replacesCurrentHistoryItem()) {
    817     // Subframe navigations that don't add session history items must be
    818     // marked with AUTO_SUBFRAME. See also didFailProvisionalLoad for how we
    819     // handle loading of error pages.
    820     document_state->navigation_state()->set_transition_type(
    821         PAGE_TRANSITION_AUTO_SUBFRAME);
    822   }
    823 
    824   FOR_EACH_OBSERVER(
    825       RenderViewObserver, render_view_->observers(),
    826       DidStartProvisionalLoad(frame));
    827 
    828   Send(new FrameHostMsg_DidStartProvisionalLoadForFrame(
    829        routing_id_, frame->identifier(),
    830        frame->parent() ? frame->parent()->identifier() : -1,
    831        is_top_most, ds->request().url()));
    832 }
    833 
    834 void RenderFrameImpl::didReceiveServerRedirectForProvisionalLoad(
    835     blink::WebFrame* frame) {
    836   // TODO(nasko): Move implementation here. Needed state:
    837   // * page_id_
    838   render_view_->didReceiveServerRedirectForProvisionalLoad(frame);
    839 }
    840 
    841 void RenderFrameImpl::didFailProvisionalLoad(
    842     blink::WebFrame* frame,
    843     const blink::WebURLError& error) {
    844   // TODO(nasko): Move implementation here. Needed state:
    845   // * page_id_
    846   // * pending_navigation_params_
    847   // Needed methods
    848   // * MaybeLoadAlternateErrorPage
    849   // * LoadNavigationErrorPage
    850   render_view_->didFailProvisionalLoad(frame, error);
    851 }
    852 
    853 void RenderFrameImpl::didCommitProvisionalLoad(blink::WebFrame* frame,
    854                                                bool is_new_navigation) {
    855   // TODO(nasko): Move implementation here. Needed state:
    856   // * page_id_
    857   // * next_page_id_
    858   // * history_list_offset_
    859   // * history_list_length_
    860   // * history_page_ids_
    861   // Needed methods
    862   // * webview
    863   // * UpdateSessionHistory
    864   // * GetLoadingUrl
    865   render_view_->didCommitProvisionalLoad(frame, is_new_navigation);
    866 }
    867 
    868 void RenderFrameImpl::didClearWindowObject(blink::WebFrame* frame) {
    869   // TODO(nasko): Move implementation here. Needed state:
    870   // * enabled_bindings_
    871   // * dom_automation_controller_
    872   // * stats_collection_controller_
    873   render_view_->didClearWindowObject(frame);
    874 }
    875 
    876 void RenderFrameImpl::didCreateDocumentElement(blink::WebFrame* frame) {
    877   // Notify the browser about non-blank documents loading in the top frame.
    878   GURL url = frame->document().url();
    879   if (url.is_valid() && url.spec() != kAboutBlankURL) {
    880     // TODO(nasko): Check if webview()->mainFrame() is the same as the
    881     // frame->tree()->top().
    882     if (frame == render_view_->webview()->mainFrame()) {
    883       render_view_->Send(new ViewHostMsg_DocumentAvailableInMainFrame(
    884           render_view_->GetRoutingID()));
    885     }
    886   }
    887 
    888   // Call back to RenderViewImpl for observers to be notified.
    889   // TODO(nasko): Remove once we have RenderFrameObserver.
    890   render_view_->didCreateDocumentElement(frame);
    891 }
    892 
    893 void RenderFrameImpl::didReceiveTitle(blink::WebFrame* frame,
    894                                       const blink::WebString& title,
    895                                       blink::WebTextDirection direction) {
    896   // TODO(nasko): Investigate wheather implementation should move here.
    897   render_view_->didReceiveTitle(frame, title, direction);
    898 }
    899 
    900 void RenderFrameImpl::didChangeIcon(blink::WebFrame* frame,
    901                                     blink::WebIconURL::Type icon_type) {
    902   // TODO(nasko): Investigate wheather implementation should move here.
    903   render_view_->didChangeIcon(frame, icon_type);
    904 }
    905 
    906 void RenderFrameImpl::didFinishDocumentLoad(blink::WebFrame* frame) {
    907   // TODO(nasko): Move implementation here. No state needed, just observers
    908   // notification in before updating encoding.
    909   render_view_->didFinishDocumentLoad(frame);
    910 }
    911 
    912 void RenderFrameImpl::didHandleOnloadEvents(blink::WebFrame* frame) {
    913   // TODO(nasko): Move implementation here. Needed state:
    914   // * page_id_
    915   render_view_->didHandleOnloadEvents(frame);
    916 }
    917 
    918 void RenderFrameImpl::didFailLoad(blink::WebFrame* frame,
    919                                   const blink::WebURLError& error) {
    920   // TODO(nasko): Move implementation here. No state needed.
    921   render_view_->didFailLoad(frame, error);
    922 }
    923 
    924 void RenderFrameImpl::didFinishLoad(blink::WebFrame* frame) {
    925   // TODO(nasko): Move implementation here. No state needed, just observers
    926   // notification before sending message to the browser process.
    927   render_view_->didFinishLoad(frame);
    928 }
    929 
    930 void RenderFrameImpl::didNavigateWithinPage(blink::WebFrame* frame,
    931                                             bool is_new_navigation) {
    932   // TODO(nasko): Move implementation here. No state needed, just observers
    933   // notification before sending message to the browser process.
    934   render_view_->didNavigateWithinPage(frame, is_new_navigation);
    935 }
    936 
    937 void RenderFrameImpl::didUpdateCurrentHistoryItem(blink::WebFrame* frame) {
    938   // TODO(nasko): Move implementation here. Needed methods:
    939   // * StartNavStateSyncTimerIfNecessary
    940   render_view_->didUpdateCurrentHistoryItem(frame);
    941 }
    942 
    943 void RenderFrameImpl::willRequestAfterPreconnect(
    944     blink::WebFrame* frame,
    945     blink::WebURLRequest& request) {
    946   blink::WebReferrerPolicy referrer_policy = blink::WebReferrerPolicyDefault;
    947   WebString custom_user_agent;
    948 
    949   if (request.extraData()) {
    950     // This will only be called before willSendRequest, so only ExtraData
    951     // members we have to copy here is on WebURLRequestExtraDataImpl.
    952     webkit_glue::WebURLRequestExtraDataImpl* old_extra_data =
    953         static_cast<webkit_glue::WebURLRequestExtraDataImpl*>(
    954             request.extraData());
    955 
    956     referrer_policy = old_extra_data->referrer_policy();
    957     custom_user_agent = old_extra_data->custom_user_agent();
    958   }
    959 
    960   bool was_after_preconnect_request = true;
    961   // The args after |was_after_preconnect_request| are not used, and set to
    962   // correct values at |willSendRequest|.
    963   request.setExtraData(new webkit_glue::WebURLRequestExtraDataImpl(
    964       referrer_policy, custom_user_agent, was_after_preconnect_request));
    965 }
    966 
    967 void RenderFrameImpl::willSendRequest(
    968     blink::WebFrame* frame,
    969     unsigned identifier,
    970     blink::WebURLRequest& request,
    971     const blink::WebURLResponse& redirect_response) {
    972   // The request my be empty during tests.
    973   if (request.url().isEmpty())
    974     return;
    975 
    976   WebFrame* top_frame = frame->top();
    977   if (!top_frame)
    978     top_frame = frame;
    979   WebDataSource* provisional_data_source = top_frame->provisionalDataSource();
    980   WebDataSource* top_data_source = top_frame->dataSource();
    981   WebDataSource* data_source =
    982       provisional_data_source ? provisional_data_source : top_data_source;
    983 
    984   PageTransition transition_type = PAGE_TRANSITION_LINK;
    985   DocumentState* document_state = DocumentState::FromDataSource(data_source);
    986   DCHECK(document_state);
    987   InternalDocumentStateData* internal_data =
    988       InternalDocumentStateData::FromDocumentState(document_state);
    989   NavigationState* navigation_state = document_state->navigation_state();
    990   transition_type = navigation_state->transition_type();
    991 
    992   GURL request_url(request.url());
    993   GURL new_url;
    994   if (GetContentClient()->renderer()->WillSendRequest(
    995           frame,
    996           transition_type,
    997           request_url,
    998           request.firstPartyForCookies(),
    999           &new_url)) {
   1000     request.setURL(WebURL(new_url));
   1001   }
   1002 
   1003   if (internal_data->is_cache_policy_override_set())
   1004     request.setCachePolicy(internal_data->cache_policy_override());
   1005 
   1006   blink::WebReferrerPolicy referrer_policy;
   1007   if (internal_data->is_referrer_policy_set()) {
   1008     referrer_policy = internal_data->referrer_policy();
   1009     internal_data->clear_referrer_policy();
   1010   } else {
   1011     referrer_policy = frame->document().referrerPolicy();
   1012   }
   1013 
   1014   // The request's extra data may indicate that we should set a custom user
   1015   // agent. This needs to be done here, after WebKit is through with setting the
   1016   // user agent on its own.
   1017   WebString custom_user_agent;
   1018   bool was_after_preconnect_request = false;
   1019   if (request.extraData()) {
   1020     webkit_glue::WebURLRequestExtraDataImpl* old_extra_data =
   1021         static_cast<webkit_glue::WebURLRequestExtraDataImpl*>(
   1022             request.extraData());
   1023     custom_user_agent = old_extra_data->custom_user_agent();
   1024     was_after_preconnect_request =
   1025         old_extra_data->was_after_preconnect_request();
   1026 
   1027     if (!custom_user_agent.isNull()) {
   1028       if (custom_user_agent.isEmpty())
   1029         request.clearHTTPHeaderField("User-Agent");
   1030       else
   1031         request.setHTTPHeaderField("User-Agent", custom_user_agent);
   1032     }
   1033   }
   1034 
   1035   // Attach |should_replace_current_entry| state to requests so that, should
   1036   // this navigation later require a request transfer, all state is preserved
   1037   // when it is re-created in the new process.
   1038   bool should_replace_current_entry = false;
   1039   if (navigation_state->is_content_initiated()) {
   1040     should_replace_current_entry = data_source->replacesCurrentHistoryItem();
   1041   } else {
   1042     // If the navigation is browser-initiated, the NavigationState contains the
   1043     // correct value instead of the WebDataSource.
   1044     //
   1045     // TODO(davidben): Avoid this awkward duplication of state. See comment on
   1046     // NavigationState::should_replace_current_entry().
   1047     should_replace_current_entry =
   1048         navigation_state->should_replace_current_entry();
   1049   }
   1050   request.setExtraData(
   1051       new RequestExtraData(referrer_policy,
   1052                            custom_user_agent,
   1053                            was_after_preconnect_request,
   1054                            routing_id_,
   1055                            (frame == top_frame),
   1056                            frame->identifier(),
   1057                            GURL(frame->document().securityOrigin().toString()),
   1058                            frame->parent() == top_frame,
   1059                            frame->parent() ? frame->parent()->identifier() : -1,
   1060                            navigation_state->allow_download(),
   1061                            transition_type,
   1062                            should_replace_current_entry,
   1063                            navigation_state->transferred_request_child_id(),
   1064                            navigation_state->transferred_request_request_id()));
   1065 
   1066   DocumentState* top_document_state =
   1067       DocumentState::FromDataSource(top_data_source);
   1068   if (top_document_state) {
   1069     // TODO(gavinp): separate out prefetching and prerender field trials
   1070     // if the rel=prerender rel type is sticking around.
   1071     if (request.targetType() == WebURLRequest::TargetIsPrefetch)
   1072       top_document_state->set_was_prefetcher(true);
   1073 
   1074     if (was_after_preconnect_request)
   1075       top_document_state->set_was_after_preconnect_request(true);
   1076   }
   1077 
   1078   // This is an instance where we embed a copy of the routing id
   1079   // into the data portion of the message. This can cause problems if we
   1080   // don't register this id on the browser side, since the download manager
   1081   // expects to find a RenderViewHost based off the id.
   1082   request.setRequestorID(render_view_->GetRoutingID());
   1083   request.setHasUserGesture(WebUserGestureIndicator::isProcessingUserGesture());
   1084 
   1085   if (!navigation_state->extra_headers().empty()) {
   1086     for (net::HttpUtil::HeadersIterator i(
   1087         navigation_state->extra_headers().begin(),
   1088         navigation_state->extra_headers().end(), "\n");
   1089         i.GetNext(); ) {
   1090       request.setHTTPHeaderField(WebString::fromUTF8(i.name()),
   1091                                  WebString::fromUTF8(i.values()));
   1092     }
   1093   }
   1094 
   1095   if (!render_view_->renderer_preferences_.enable_referrers)
   1096     request.clearHTTPHeaderField("Referer");
   1097 }
   1098 
   1099 void RenderFrameImpl::didReceiveResponse(
   1100     blink::WebFrame* frame,
   1101     unsigned identifier,
   1102     const blink::WebURLResponse& response) {
   1103   // Only do this for responses that correspond to a provisional data source
   1104   // of the top-most frame.  If we have a provisional data source, then we
   1105   // can't have any sub-resources yet, so we know that this response must
   1106   // correspond to a frame load.
   1107   if (!frame->provisionalDataSource() || frame->parent())
   1108     return;
   1109 
   1110   // If we are in view source mode, then just let the user see the source of
   1111   // the server's error page.
   1112   if (frame->isViewSourceModeEnabled())
   1113     return;
   1114 
   1115   DocumentState* document_state =
   1116       DocumentState::FromDataSource(frame->provisionalDataSource());
   1117   int http_status_code = response.httpStatusCode();
   1118 
   1119   // Record page load flags.
   1120   WebURLResponseExtraDataImpl* extra_data =
   1121       RenderViewImpl::GetExtraDataFromResponse(response);
   1122   if (extra_data) {
   1123     document_state->set_was_fetched_via_spdy(
   1124         extra_data->was_fetched_via_spdy());
   1125     document_state->set_was_npn_negotiated(
   1126         extra_data->was_npn_negotiated());
   1127     document_state->set_npn_negotiated_protocol(
   1128         extra_data->npn_negotiated_protocol());
   1129     document_state->set_was_alternate_protocol_available(
   1130         extra_data->was_alternate_protocol_available());
   1131     document_state->set_connection_info(
   1132         extra_data->connection_info());
   1133     document_state->set_was_fetched_via_proxy(
   1134         extra_data->was_fetched_via_proxy());
   1135   }
   1136   InternalDocumentStateData* internal_data =
   1137       InternalDocumentStateData::FromDocumentState(document_state);
   1138   internal_data->set_http_status_code(http_status_code);
   1139   // Whether or not the http status code actually corresponds to an error is
   1140   // only checked when the page is done loading, if |use_error_page| is
   1141   // still true.
   1142   internal_data->set_use_error_page(true);
   1143 }
   1144 
   1145 void RenderFrameImpl::didFinishResourceLoad(blink::WebFrame* frame,
   1146                                             unsigned identifier) {
   1147   // TODO(nasko): Move implementation here. Needed state:
   1148   // * devtools_agent_
   1149   // Needed methods:
   1150   // * LoadNavigationErrorPage
   1151   render_view_->didFinishResourceLoad(frame, identifier);
   1152 }
   1153 
   1154 void RenderFrameImpl::didLoadResourceFromMemoryCache(
   1155     blink::WebFrame* frame,
   1156     const blink::WebURLRequest& request,
   1157     const blink::WebURLResponse& response) {
   1158   // The recipients of this message have no use for data: URLs: they don't
   1159   // affect the page's insecure content list and are not in the disk cache. To
   1160   // prevent large (1M+) data: URLs from crashing in the IPC system, we simply
   1161   // filter them out here.
   1162   GURL url(request.url());
   1163   if (url.SchemeIs("data"))
   1164     return;
   1165 
   1166   // Let the browser know we loaded a resource from the memory cache.  This
   1167   // message is needed to display the correct SSL indicators.
   1168   render_view_->Send(new ViewHostMsg_DidLoadResourceFromMemoryCache(
   1169       render_view_->GetRoutingID(),
   1170       url,
   1171       response.securityInfo(),
   1172       request.httpMethod().utf8(),
   1173       response.mimeType().utf8(),
   1174       ResourceType::FromTargetType(request.targetType())));
   1175 }
   1176 
   1177 void RenderFrameImpl::didDisplayInsecureContent(blink::WebFrame* frame) {
   1178   render_view_->Send(new ViewHostMsg_DidDisplayInsecureContent(
   1179       render_view_->GetRoutingID()));
   1180 }
   1181 
   1182 void RenderFrameImpl::didRunInsecureContent(
   1183     blink::WebFrame* frame,
   1184     const blink::WebSecurityOrigin& origin,
   1185     const blink::WebURL& target) {
   1186   render_view_->Send(new ViewHostMsg_DidRunInsecureContent(
   1187       render_view_->GetRoutingID(),
   1188       origin.toString().utf8(),
   1189       target));
   1190 }
   1191 
   1192 void RenderFrameImpl::didAbortLoading(blink::WebFrame* frame) {
   1193 #if defined(ENABLE_PLUGINS)
   1194   if (frame != render_view_->webview()->mainFrame())
   1195     return;
   1196   PluginChannelHost::Broadcast(
   1197       new PluginHostMsg_DidAbortLoading(render_view_->GetRoutingID()));
   1198 #endif
   1199 }
   1200 
   1201 void RenderFrameImpl::didExhaustMemoryAvailableForScript(
   1202     blink::WebFrame* frame) {
   1203   render_view_->Send(new ViewHostMsg_JSOutOfMemory(
   1204       render_view_->GetRoutingID()));
   1205 }
   1206 
   1207 void RenderFrameImpl::didCreateScriptContext(blink::WebFrame* frame,
   1208                                              v8::Handle<v8::Context> context,
   1209                                              int extension_group,
   1210                                              int world_id) {
   1211   GetContentClient()->renderer()->DidCreateScriptContext(
   1212       frame, context, extension_group, world_id);
   1213 }
   1214 
   1215 void RenderFrameImpl::willReleaseScriptContext(blink::WebFrame* frame,
   1216                                                v8::Handle<v8::Context> context,
   1217                                                int world_id) {
   1218   GetContentClient()->renderer()->WillReleaseScriptContext(
   1219       frame, context, world_id);
   1220 }
   1221 
   1222 void RenderFrameImpl::didFirstVisuallyNonEmptyLayout(blink::WebFrame* frame) {
   1223   render_view_->didFirstVisuallyNonEmptyLayout(frame);
   1224 }
   1225 
   1226 void RenderFrameImpl::didChangeContentsSize(blink::WebFrame* frame,
   1227                                             const blink::WebSize& size) {
   1228   // TODO(nasko): Move implementation here. Needed state:
   1229   // * cached_has_main_frame_horizontal_scrollbar_
   1230   // * cached_has_main_frame_vertical_scrollbar_
   1231   render_view_->didChangeContentsSize(frame, size);
   1232 }
   1233 
   1234 void RenderFrameImpl::didChangeScrollOffset(blink::WebFrame* frame) {
   1235   // TODO(nasko): Move implementation here. Needed methods:
   1236   // * StartNavStateSyncTimerIfNecessary
   1237   render_view_->didChangeScrollOffset(frame);
   1238 }
   1239 
   1240 void RenderFrameImpl::willInsertBody(blink::WebFrame* frame) {
   1241   if (!frame->parent()) {
   1242     render_view_->Send(new ViewHostMsg_WillInsertBody(
   1243         render_view_->GetRoutingID()));
   1244   }
   1245 }
   1246 
   1247 void RenderFrameImpl::reportFindInPageMatchCount(int request_id,
   1248                                                  int count,
   1249                                                  bool final_update) {
   1250   int active_match_ordinal = -1;  // -1 = don't update active match ordinal
   1251   if (!count)
   1252     active_match_ordinal = 0;
   1253 
   1254   render_view_->Send(new ViewHostMsg_Find_Reply(
   1255       render_view_->GetRoutingID(), request_id, count,
   1256       gfx::Rect(), active_match_ordinal, final_update));
   1257 }
   1258 
   1259 void RenderFrameImpl::reportFindInPageSelection(
   1260     int request_id,
   1261     int active_match_ordinal,
   1262     const blink::WebRect& selection_rect) {
   1263   render_view_->Send(new ViewHostMsg_Find_Reply(
   1264       render_view_->GetRoutingID(), request_id, -1, selection_rect,
   1265       active_match_ordinal, false));
   1266 }
   1267 
   1268 void RenderFrameImpl::requestStorageQuota(
   1269     blink::WebFrame* frame,
   1270     blink::WebStorageQuotaType type,
   1271     unsigned long long requested_size,
   1272     blink::WebStorageQuotaCallbacks* callbacks) {
   1273   DCHECK(frame);
   1274   WebSecurityOrigin origin = frame->document().securityOrigin();
   1275   if (origin.isUnique()) {
   1276     // Unique origins cannot store persistent state.
   1277     callbacks->didFail(blink::WebStorageQuotaErrorAbort);
   1278     return;
   1279   }
   1280   ChildThread::current()->quota_dispatcher()->RequestStorageQuota(
   1281       render_view_->GetRoutingID(), GURL(origin.toString()),
   1282       static_cast<quota::StorageType>(type), requested_size,
   1283       QuotaDispatcher::CreateWebStorageQuotaCallbacksWrapper(callbacks));
   1284 }
   1285 
   1286 void RenderFrameImpl::willOpenSocketStream(
   1287     blink::WebSocketStreamHandle* handle) {
   1288   SocketStreamHandleData::AddToHandle(handle, render_view_->GetRoutingID());
   1289 }
   1290 
   1291 void RenderFrameImpl::willStartUsingPeerConnectionHandler(
   1292     blink::WebFrame* frame,
   1293     blink::WebRTCPeerConnectionHandler* handler) {
   1294 #if defined(ENABLE_WEBRTC)
   1295   static_cast<RTCPeerConnectionHandler*>(handler)->associateWithFrame(frame);
   1296 #endif
   1297 }
   1298 
   1299 bool RenderFrameImpl::willCheckAndDispatchMessageEvent(
   1300     blink::WebFrame* sourceFrame,
   1301     blink::WebFrame* targetFrame,
   1302     blink::WebSecurityOrigin targetOrigin,
   1303     blink::WebDOMMessageEvent event) {
   1304   // TODO(nasko): Move implementation here. Needed state:
   1305   // * is_swapped_out_
   1306   return render_view_->willCheckAndDispatchMessageEvent(
   1307       sourceFrame, targetFrame, targetOrigin, event);
   1308 }
   1309 
   1310 blink::WebString RenderFrameImpl::userAgentOverride(
   1311     blink::WebFrame* frame,
   1312     const blink::WebURL& url) {
   1313   if (!render_view_->webview() || !render_view_->webview()->mainFrame() ||
   1314       render_view_->renderer_preferences_.user_agent_override.empty()) {
   1315     return blink::WebString();
   1316   }
   1317 
   1318   // If we're in the middle of committing a load, the data source we need
   1319   // will still be provisional.
   1320   WebFrame* main_frame = render_view_->webview()->mainFrame();
   1321   WebDataSource* data_source = NULL;
   1322   if (main_frame->provisionalDataSource())
   1323     data_source = main_frame->provisionalDataSource();
   1324   else
   1325     data_source = main_frame->dataSource();
   1326 
   1327   InternalDocumentStateData* internal_data = data_source ?
   1328       InternalDocumentStateData::FromDataSource(data_source) : NULL;
   1329   if (internal_data && internal_data->is_overriding_user_agent())
   1330     return WebString::fromUTF8(
   1331         render_view_->renderer_preferences_.user_agent_override);
   1332   return blink::WebString();
   1333 }
   1334 
   1335 blink::WebString RenderFrameImpl::doNotTrackValue(blink::WebFrame* frame) {
   1336   if (render_view_->renderer_preferences_.enable_do_not_track)
   1337     return WebString::fromUTF8("1");
   1338   return WebString();
   1339 }
   1340 
   1341 bool RenderFrameImpl::allowWebGL(blink::WebFrame* frame, bool default_value) {
   1342   if (!default_value)
   1343     return false;
   1344 
   1345   bool blocked = true;
   1346   render_view_->Send(new ViewHostMsg_Are3DAPIsBlocked(
   1347       render_view_->GetRoutingID(),
   1348       GURL(frame->top()->document().securityOrigin().toString()),
   1349       THREE_D_API_TYPE_WEBGL,
   1350       &blocked));
   1351   return !blocked;
   1352 }
   1353 
   1354 void RenderFrameImpl::didLoseWebGLContext(blink::WebFrame* frame,
   1355                                           int arb_robustness_status_code) {
   1356   render_view_->Send(new ViewHostMsg_DidLose3DContext(
   1357       GURL(frame->top()->document().securityOrigin().toString()),
   1358       THREE_D_API_TYPE_WEBGL,
   1359       arb_robustness_status_code));
   1360 }
   1361 
   1362 void RenderFrameImpl::AddObserver(RenderFrameObserver* observer) {
   1363   observers_.AddObserver(observer);
   1364 }
   1365 
   1366 void RenderFrameImpl::RemoveObserver(RenderFrameObserver* observer) {
   1367   observer->RenderFrameGone();
   1368   observers_.RemoveObserver(observer);
   1369 }
   1370 
   1371 }  // namespace content
   1372