#include "content/child/plugin_messages.h"
#include "content/child/quota_dispatcher.h"
#include "content/child/request_extra_data.h"
+#include "content/child/service_worker/service_worker_handle_reference.h"
#include "content/child/service_worker/service_worker_network_provider.h"
#include "content/child/service_worker/service_worker_provider_context.h"
#include "content/child/service_worker/web_service_worker_provider_impl.h"
-#include "content/child/web_socket_stream_handle_impl.h"
+#include "content/child/web_url_loader_impl.h"
#include "content/child/web_url_request_util.h"
#include "content/child/webmessageportchannel_impl.h"
#include "content/child/websocket_bridge.h"
#include "content/common/frame_messages.h"
#include "content/common/input_messages.h"
#include "content/common/service_worker/service_worker_types.h"
-#include "content/common/socket_stream_handle_data.h"
#include "content/common/swapped_out_messages.h"
#include "content/common/view_messages.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/context_menu_params.h"
+#include "content/public/common/page_state.h"
+#include "content/public/common/resource_response.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
#include "content/public/renderer/browser_plugin_delegate.h"
#include "content/public/renderer/document_state.h"
#include "content/public/renderer/navigation_state.h"
#include "content/public/renderer/render_frame_observer.h"
+#include "content/public/renderer/renderer_ppapi_host.h"
#include "content/renderer/accessibility/renderer_accessibility.h"
-#include "content/renderer/accessibility/renderer_accessibility_complete.h"
-#include "content/renderer/accessibility/renderer_accessibility_focus_only.h"
#include "content/renderer/browser_plugin/browser_plugin.h"
#include "content/renderer/browser_plugin/browser_plugin_manager.h"
#include "content/renderer/child_frame_compositing_helper.h"
#include "content/renderer/manifest/manifest_manager.h"
#include "content/renderer/media/audio_renderer_mixer_manager.h"
#include "content/renderer/media/crypto/encrypted_media_player_support_impl.h"
+#include "content/renderer/media/crypto/render_cdm_factory.h"
#include "content/renderer/media/media_stream_dispatcher.h"
#include "content/renderer/media/media_stream_renderer_factory.h"
#include "content/renderer/media/midi_dispatcher.h"
#include "content/renderer/media/user_media_client_impl.h"
#include "content/renderer/media/webcontentdecryptionmodule_impl.h"
#include "content/renderer/media/webmediaplayer_ms.h"
+#include "content/renderer/mojo/service_registry_js_wrapper.h"
#include "content/renderer/notification_permission_dispatcher.h"
#include "content/renderer/notification_provider.h"
#include "content/renderer/npapi/plugin_channel_host.h"
#include "content/renderer/push_messaging_dispatcher.h"
+#include "content/renderer/push_permission_dispatcher.h"
#include "content/renderer/render_frame_proxy.h"
#include "content/renderer/render_process.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/shared_worker_repository.h"
#include "content/renderer/v8_value_converter_impl.h"
#include "content/renderer/websharedworker_proxy.h"
+#include "gin/modules/module_registry.h"
#include "media/base/audio_renderer_mixer_input.h"
+#include "media/base/renderer.h"
#include "media/blink/webmediaplayer_impl.h"
#include "media/blink/webmediaplayer_params.h"
#include "media/filters/gpu_video_accelerator_factories.h"
+#include "mojo/edk/js/core.h"
+#include "mojo/edk/js/support.h"
#include "net/base/data_url.h"
#include "net/base/net_errors.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "third_party/WebKit/public/web/WebNavigationPolicy.h"
#include "third_party/WebKit/public/web/WebPlugin.h"
#include "third_party/WebKit/public/web/WebPluginParams.h"
+#include "third_party/WebKit/public/web/WebPluginPlaceholder.h"
#include "third_party/WebKit/public/web/WebRange.h"
#include "third_party/WebKit/public/web/WebScriptSource.h"
#include "third_party/WebKit/public/web/WebSearchableFormData.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/pepper/pepper_webplugin_impl.h"
#include "content/renderer/pepper/plugin_module.h"
+#include "content/renderer/pepper/plugin_power_saver_helper.h"
#endif
#if defined(ENABLE_WEBRTC)
#include "content/renderer/media/android/webmediaplayer_android.h"
#endif
-#if defined(ENABLE_BROWSER_CDMS)
+#if defined(ENABLE_PEPPER_CDMS)
+#include "content/renderer/media/crypto/pepper_cdm_wrapper_impl.h"
+#elif defined(ENABLE_BROWSER_CDMS)
#include "content/renderer/media/crypto/renderer_cdm_manager.h"
#endif
return false;
}
+WebURLRequest CreateURLRequestForNavigation(
+ const CommonNavigationParams& common_params,
+ const RequestNavigationParams& request_params,
+ scoped_ptr<StreamOverrideParameters> stream_override,
+ bool is_view_source_mode_enabled) {
+ WebURLRequest request(common_params.url);
+ if (is_view_source_mode_enabled)
+ request.setCachePolicy(WebURLRequest::ReturnCacheDataElseLoad);
+
+ if (common_params.referrer.url.is_valid()) {
+ WebString web_referrer = WebSecurityPolicy::generateReferrerHeader(
+ common_params.referrer.policy,
+ common_params.url,
+ WebString::fromUTF8(common_params.referrer.url.spec()));
+ if (!web_referrer.isEmpty())
+ request.setHTTPReferrer(web_referrer, common_params.referrer.policy);
+ }
+
+ if (!request_params.extra_headers.empty()) {
+ for (net::HttpUtil::HeadersIterator i(request_params.extra_headers.begin(),
+ request_params.extra_headers.end(),
+ "\n");
+ i.GetNext();) {
+ request.addHTTPHeaderField(WebString::fromUTF8(i.name()),
+ WebString::fromUTF8(i.values()));
+ }
+ }
+
+ if (request_params.is_post) {
+ request.setHTTPMethod(WebString::fromUTF8("POST"));
+
+ // Set post data.
+ WebHTTPBody http_body;
+ http_body.initialize();
+ const char* data = NULL;
+ if (request_params.browser_initiated_post_data.size()) {
+ data = reinterpret_cast<const char*>(
+ &request_params.browser_initiated_post_data.front());
+ }
+ http_body.appendData(
+ WebData(data, request_params.browser_initiated_post_data.size()));
+ request.setHTTPBody(http_body);
+ }
+
+ RequestExtraData* extra_data = new RequestExtraData();
+ extra_data->set_stream_override(stream_override.Pass());
+ request.setExtraData(extra_data);
+ return request;
+}
+
+void UpdateFrameNavigationTiming(WebFrame* frame,
+ base::TimeTicks browser_navigation_start,
+ base::TimeTicks renderer_navigation_start) {
+ // The browser provides the navigation_start time to bootstrap the
+ // Navigation Timing information for the browser-initiated navigations. In
+ // case of cross-process navigations, this carries over the time of
+ // finishing the onbeforeunload handler of the previous page.
+ DCHECK(!browser_navigation_start.is_null());
+ if (frame->provisionalDataSource()) {
+ // |browser_navigation_start| is likely before this process existed, so we
+ // can't use InterProcessTimeTicksConverter. We need at least to ensure
+ // that the browser-side navigation start we set is not later than the one
+ // on the renderer side.
+ base::TimeTicks navigation_start = std::min(
+ browser_navigation_start, renderer_navigation_start);
+ double navigation_start_seconds =
+ (navigation_start - base::TimeTicks()).InSecondsF();
+ frame->provisionalDataSource()->setNavigationStartTime(
+ navigation_start_seconds);
+ // TODO(clamy): We need to provide additional timing values for the
+ // Navigation Timing API to work with browser-side navigations.
+ }
+}
+
+// PlzNavigate
+FrameHostMsg_BeginNavigation_Params MakeBeginNavigationParams(
+ const blink::WebURLRequest& request) {
+ FrameHostMsg_BeginNavigation_Params params;
+ params.method = request.httpMethod().latin1();
+ params.headers = GetWebURLRequestHeaders(request);
+ params.load_flags = GetLoadFlagsForWebURLRequest(request);
+ // TODO(clamy): fill the http body.
+ params.has_user_gesture = request.hasUserGesture();
+ return params;
+}
+
+// PlzNavigate
+CommonNavigationParams MakeCommonNavigationParams(
+ const blink::WebURLRequest& request) {
+ const RequestExtraData kEmptyData;
+ const RequestExtraData* extra_data =
+ static_cast<RequestExtraData*>(request.extraData());
+ if (!extra_data)
+ extra_data = &kEmptyData;
+ CommonNavigationParams params;
+ params.url = request.url();
+ params.referrer = Referrer(
+ GURL(request.httpHeaderField(WebString::fromUTF8("Referer")).latin1()),
+ request.referrerPolicy());
+ params.transition = extra_data->transition_type();
+ return params;
+}
+
} // namespace
static RenderFrameImpl* (*g_create_render_frame_impl)(RenderViewImpl*, int32) =
}
// static
-void RenderFrameImpl::CreateFrame(int routing_id, int parent_routing_id) {
+void RenderFrameImpl::CreateFrame(int routing_id,
+ int parent_routing_id,
+ int proxy_routing_id) {
// TODO(nasko): For now, this message is only sent for subframes, as the
// top level frame is created when the RenderView is created through the
// ViewMsg_New IPC.
CHECK_NE(MSG_ROUTING_NONE, parent_routing_id);
- RenderFrameProxy* proxy = RenderFrameProxy::FromRoutingID(parent_routing_id);
-
- // If the browser is sending a valid parent routing id, it should already be
- // created and registered.
- CHECK(proxy);
- blink::WebRemoteFrame* parent_web_frame = proxy->web_frame();
-
- // Create the RenderFrame and WebLocalFrame, linking the two.
- RenderFrameImpl* render_frame =
- RenderFrameImpl::Create(proxy->render_view(), routing_id);
- blink::WebLocalFrame* web_frame =
- parent_web_frame->createLocalChild("", render_frame);
+ blink::WebLocalFrame* web_frame;
+ RenderFrameImpl* render_frame;
+ if (proxy_routing_id == MSG_ROUTING_NONE) {
+ RenderFrameProxy* parent_proxy =
+ RenderFrameProxy::FromRoutingID(parent_routing_id);
+ // If the browser is sending a valid parent routing id, it should already
+ // be created and registered.
+ CHECK(parent_proxy);
+ blink::WebRemoteFrame* parent_web_frame = parent_proxy->web_frame();
+
+ // Create the RenderFrame and WebLocalFrame, linking the two.
+ render_frame =
+ RenderFrameImpl::Create(parent_proxy->render_view(), routing_id);
+ web_frame = parent_web_frame->createLocalChild("", render_frame);
+ } else {
+ RenderFrameProxy* proxy =
+ RenderFrameProxy::FromRoutingID(proxy_routing_id);
+ CHECK(proxy);
+ render_frame = RenderFrameImpl::Create(proxy->render_view(), routing_id);
+ web_frame = blink::WebLocalFrame::create(render_frame);
+ render_frame->proxy_routing_id_ = proxy_routing_id;
+ web_frame->initializeToReplaceRemoteFrame(proxy->web_frame());
+ }
render_frame->SetWebFrame(web_frame);
render_frame->Initialize();
}
is_swapped_out_(false),
render_frame_proxy_(NULL),
is_detaching_(false),
+ proxy_routing_id_(MSG_ROUTING_NONE),
+#if defined(ENABLE_PLUGINS)
+ plugin_power_saver_helper_(NULL),
+#endif
cookie_jar_(this),
selection_text_offset_(0),
selection_range_(gfx::Range::InvalidRange()),
render_view_->RegisterRenderFrame(this);
+ // Everything below subclasses RenderFrameObserver and is automatically
+ // deleted when the RenderFrame gets deleted.
#if defined(OS_ANDROID)
new GinJavaBridgeDispatcher(this);
#endif
+#if defined(ENABLE_PLUGINS)
+ plugin_power_saver_helper_ = new PluginPowerSaverHelper(this);
+#endif
+
#if defined(ENABLE_NOTIFICATIONS)
notification_provider_ = new NotificationProvider(this);
#endif
render_view_->UnregisterVideoHoleFrame(this);
#endif
+ if (render_frame_proxy_)
+ delete render_frame_proxy_;
+
render_view_->UnregisterRenderFrame(this);
g_routing_id_frame_map.Get().erase(routing_id_);
RenderThread::Get()->RemoveRoute(routing_id_);
void RenderFrameImpl::PepperPluginCreated(RendererPpapiHost* host) {
FOR_EACH_OBSERVER(RenderFrameObserver, observers_,
DidCreatePepperPlugin(host));
+ if (host->GetPluginName() == kFlashPluginName) {
+ RenderThread::Get()->RecordAction(
+ base::UserMetricsAction("FrameLoadWithFlash"));
+ }
}
void RenderFrameImpl::PepperDidChangeCursor(
render_view_->OnImeConfirmComposition(text, replacement_range, false);
}
-
void RenderFrameImpl::OnImeSetComposition(
const base::string16& text,
const std::vector<blink::WebCompositionUnderline>& underlines,
pepper_composition_text_.clear();
}
-#endif // ENABLE_PLUGINS
+PluginPowerSaverHelper* RenderFrameImpl::plugin_power_saver_helper() {
+ DCHECK(plugin_power_saver_helper_);
+ return plugin_power_saver_helper_;
+}
+#endif // defined(ENABLE_PLUGINS)
MediaStreamDispatcher* RenderFrameImpl::GetMediaStreamDispatcher() {
if (!web_user_media_client_)
IPC_MESSAGE_HANDLER(InputMsg_SelectAll, OnSelectAll)
IPC_MESSAGE_HANDLER(InputMsg_SelectRange, OnSelectRange)
IPC_MESSAGE_HANDLER(InputMsg_Unselect, OnUnselect)
+ IPC_MESSAGE_HANDLER(InputMsg_MoveRangeSelectionExtent,
+ OnMoveRangeSelectionExtent)
IPC_MESSAGE_HANDLER(InputMsg_Replace, OnReplace)
IPC_MESSAGE_HANDLER(InputMsg_ReplaceMisspelling, OnReplaceMisspelling)
IPC_MESSAGE_HANDLER(InputMsg_ExtendSelectionAndDelete,
IPC_MESSAGE_HANDLER(FrameMsg_SetAccessibilityMode,
OnSetAccessibilityMode)
IPC_MESSAGE_HANDLER(FrameMsg_DisownOpener, OnDisownOpener)
+ IPC_MESSAGE_HANDLER(FrameMsg_RequestNavigation, OnRequestNavigation)
+ IPC_MESSAGE_HANDLER(FrameMsg_CommitNavigation, OnCommitNavigation)
#if defined(OS_ANDROID)
IPC_MESSAGE_HANDLER(FrameMsg_SelectPopupMenuItems, OnSelectPopupMenuItems)
#elif defined(OS_MACOSX)
void RenderFrameImpl::OnNavigate(const FrameMsg_Navigate_Params& params) {
TRACE_EVENT2("navigation", "RenderFrameImpl::OnNavigate",
- "id", routing_id_, "url", params.url.possibly_invalid_spec());
- MaybeHandleDebugURL(params.url);
- if (!render_view_->webview())
- return;
-
- FOR_EACH_OBSERVER(
- RenderViewObserver, render_view_->observers_, Navigate(params.url));
-
- bool is_reload = RenderViewImpl::IsReload(params);
+ "id", routing_id_,
+ "url", params.common_params.url.possibly_invalid_spec());
+ bool is_reload =
+ RenderViewImpl::IsReload(params.common_params.navigation_type);
WebURLRequest::CachePolicy cache_policy =
WebURLRequest::UseProtocolCachePolicy;
-
- // If this is a stale back/forward (due to a recent navigation the browser
- // didn't know about), ignore it.
- if (render_view_->IsBackForwardToStaleEntry(params, is_reload))
+ if (!RenderFrameImpl::PrepareRenderViewForNavigation(
+ params.common_params.url, params.common_params.navigation_type,
+ params.commit_params.page_state, true, params.pending_history_list_offset,
+ params.page_id, &is_reload, &cache_policy)) {
return;
-
- // Swap this renderer back in if necessary.
- if (render_view_->is_swapped_out_ &&
- GetWebFrame() == render_view_->webview()->mainFrame()) {
- // We marked the view as hidden when swapping the view out, so be sure to
- // reset the visibility state before navigating to the new URL.
- render_view_->webview()->setVisibilityState(
- render_view_->visibilityState(), false);
-
- // If this is an attempt to reload while we are swapped out, we should not
- // reload swappedout://, but the previous page, which is stored in
- // params.state. Setting is_reload to false will treat this like a back
- // navigation to accomplish that.
- is_reload = false;
- cache_policy = WebURLRequest::ReloadIgnoringCacheData;
-
- // We refresh timezone when a view is swapped in since timezone
- // can get out of sync when the system timezone is updated while
- // the view is swapped out.
- RenderThreadImpl::NotifyTimezoneChange();
-
- render_view_->SetSwappedOut(false);
- is_swapped_out_ = false;
}
+ int pending_history_list_offset = params.pending_history_list_offset;
+ int current_history_list_offset = params.current_history_list_offset;
+ int current_history_list_length = params.current_history_list_length;
if (params.should_clear_history_list) {
- CHECK_EQ(params.pending_history_list_offset, -1);
- CHECK_EQ(params.current_history_list_offset, -1);
- CHECK_EQ(params.current_history_list_length, 0);
+ CHECK_EQ(pending_history_list_offset, -1);
+ CHECK_EQ(current_history_list_offset, -1);
+ CHECK_EQ(current_history_list_length, 0);
}
- render_view_->history_list_offset_ = params.current_history_list_offset;
- render_view_->history_list_length_ = params.current_history_list_length;
+ render_view_->history_list_offset_ = current_history_list_offset;
+ render_view_->history_list_length_ = current_history_list_length;
if (render_view_->history_list_length_ >= 0) {
render_view_->history_page_ids_.resize(
render_view_->history_list_length_, -1);
}
- if (params.pending_history_list_offset >= 0 &&
- params.pending_history_list_offset < render_view_->history_list_length_) {
- render_view_->history_page_ids_[params.pending_history_list_offset] =
+ if (pending_history_list_offset >= 0 &&
+ pending_history_list_offset < render_view_->history_list_length_) {
+ render_view_->history_page_ids_[pending_history_list_offset] =
params.page_id;
}
- GetContentClient()->SetActiveURL(params.url);
+ GetContentClient()->SetActiveURL(params.common_params.url);
WebFrame* frame = frame_;
if (!params.frame_to_navigate.empty()) {
// back/forward navigation event.
if (is_reload) {
bool reload_original_url =
- (params.navigation_type ==
- FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL);
- bool ignore_cache = (params.navigation_type ==
- FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE);
+ (params.common_params.navigation_type ==
+ FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL);
+ bool ignore_cache = (params.common_params.navigation_type ==
+ FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE);
if (reload_original_url)
- frame->reloadWithOverrideURL(params.url, true);
+ frame->reloadWithOverrideURL(params.common_params.url, true);
else
frame->reload(ignore_cache);
- } else if (params.page_state.IsValid()) {
+ } else if (params.commit_params.page_state.IsValid()) {
// We must know the page ID of the page we are navigating back to.
DCHECK_NE(params.page_id, -1);
scoped_ptr<HistoryEntry> entry =
- PageStateToHistoryEntry(params.page_state);
+ PageStateToHistoryEntry(params.commit_params.page_state);
if (entry) {
// Ensure we didn't save the swapped out URL in UpdateState, since the
// browser should never be telling us to navigate to swappedout://.
} else if (!params.base_url_for_data_url.is_empty()) {
// A loadData request with a specified base URL.
std::string mime_type, charset, data;
- if (net::DataURL::Parse(params.url, &mime_type, &charset, &data)) {
+ if (net::DataURL::Parse(
+ params.common_params.url, &mime_type, &charset, &data)) {
frame->loadData(
WebData(data.c_str(), data.length()),
WebString::fromUTF8(mime_type),
params.history_url_for_data_url,
false);
} else {
- CHECK(false) <<
- "Invalid URL passed: " << params.url.possibly_invalid_spec();
+ CHECK(false) << "Invalid URL passed: "
+ << params.common_params.url.possibly_invalid_spec();
}
} else {
// Navigate to the given URL.
- WebURLRequest request(params.url);
+ WebURLRequest request =
+ CreateURLRequestForNavigation(params.common_params,
+ params.request_params,
+ scoped_ptr<StreamOverrideParameters>(),
+ frame->isViewSourceModeEnabled());
// A session history navigation should have been accompanied by state.
CHECK_EQ(params.page_id, -1);
- if (frame->isViewSourceModeEnabled())
- request.setCachePolicy(WebURLRequest::ReturnCacheDataElseLoad);
-
- if (params.referrer.url.is_valid()) {
- WebString referrer = WebSecurityPolicy::generateReferrerHeader(
- params.referrer.policy,
- params.url,
- WebString::fromUTF8(params.referrer.url.spec()));
- if (!referrer.isEmpty())
- request.setHTTPReferrer(referrer, params.referrer.policy);
- }
-
- if (!params.extra_headers.empty()) {
- for (net::HttpUtil::HeadersIterator i(params.extra_headers.begin(),
- params.extra_headers.end(), "\n");
- i.GetNext(); ) {
- request.addHTTPHeaderField(WebString::fromUTF8(i.name()),
- WebString::fromUTF8(i.values()));
- }
- }
-
- if (params.is_post) {
- request.setHTTPMethod(WebString::fromUTF8("POST"));
-
- // Set post data.
- WebHTTPBody http_body;
- http_body.initialize();
- const char* data = NULL;
- if (params.browser_initiated_post_data.size()) {
- data = reinterpret_cast<const char*>(
- ¶ms.browser_initiated_post_data.front());
- }
- http_body.appendData(
- WebData(data, params.browser_initiated_post_data.size()));
- request.setHTTPBody(http_body);
- }
-
// Record this before starting the load, we need a lower bound of this time
// to sanitize the navigationStart override set below.
base::TimeTicks renderer_navigation_start = base::TimeTicks::Now();
frame->loadRequest(request);
- // The browser provides the navigation_start time to bootstrap the
- // Navigation Timing information for the browser-initiated navigations. In
- // case of cross-process navigations, this carries over the time of
- // finishing the onbeforeunload handler of the previous page.
- DCHECK(!params.browser_navigation_start.is_null());
- if (frame->provisionalDataSource()) {
- // |browser_navigation_start| is likely before this process existed, so we
- // can't use InterProcessTimeTicksConverter. We need at least to ensure
- // that the browser-side navigation start we set is not later than the one
- // on the renderer side.
- base::TimeTicks navigation_start = std::min(
- params.browser_navigation_start, renderer_navigation_start);
- double navigation_start_seconds =
- (navigation_start - base::TimeTicks()).InSecondsF();
- frame->provisionalDataSource()->setNavigationStartTime(
- navigation_start_seconds);
- }
+ UpdateFrameNavigationTiming(
+ frame, params.commit_params.browser_navigation_start,
+ renderer_navigation_start);
}
// In case LoadRequest failed before DidCreateDataSource was called.
service_registry_.BindRemoteServiceProvider(service_provider_handle.Pass());
}
+ManifestManager* RenderFrameImpl::manifest_manager() {
+ return manifest_manager_;
+}
+
void RenderFrameImpl::OnBeforeUnload() {
TRACE_EVENT1("navigation", "RenderFrameImpl::OnBeforeUnload",
"id", routing_id_);
// clearing the page. We also allow this process to exit if there are no
// other active RenderFrames in it.
- // Send an UpdateState message before we get swapped out. Create the
- // RenderFrameProxy as well so its routing id is registered for receiving
- // IPC messages.
+ // Send an UpdateState message before we get swapped out.
render_view_->SyncNavigationState();
- proxy = RenderFrameProxy::CreateProxyToReplaceFrame(this,
- proxy_routing_id);
+
+ // If we need a proxy to replace this, create it now so its routing id is
+ // registered for receiving IPC messages.
+ if (proxy_routing_id != MSG_ROUTING_NONE) {
+ proxy = RenderFrameProxy::CreateProxyToReplaceFrame(this,
+ proxy_routing_id);
+ }
// Synchronously run the unload handler before sending the ACK.
// TODO(creis): Call dispatchUnloadEvent unconditionally here to support
// frame?
OnStop();
- // Transfer settings such as initial drawing parameters to the remote frame
- // that will replace this frame.
- if (!is_main_frame)
+ // Transfer settings such as initial drawing parameters to the remote frame,
+ // if one is created, that will replace this frame.
+ if (!is_main_frame && proxy)
proxy->web_frame()->initializeFromFrame(frame_);
// Replace the page with a blank dummy URL. The unload handler will not be
frame_->executeCommand(WebString::fromUTF8("SelectAll"), GetFocusedElement());
}
-void RenderFrameImpl::OnSelectRange(const gfx::Point& start,
- const gfx::Point& end) {
+void RenderFrameImpl::OnSelectRange(const gfx::Point& base,
+ const gfx::Point& extent) {
// This IPC is dispatched by RenderWidgetHost, so use its routing id.
- Send(new ViewHostMsg_SelectRange_ACK(GetRenderWidget()->routing_id()));
+ Send(new InputHostMsg_SelectRange_ACK(GetRenderWidget()->routing_id()));
base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
- frame_->selectRange(start, end);
+ frame_->selectRange(base, extent);
}
void RenderFrameImpl::OnUnselect() {
frame_->executeCommand(WebString::fromUTF8("Unselect"), GetFocusedElement());
}
+void RenderFrameImpl::OnMoveRangeSelectionExtent(const gfx::Point& point) {
+ // This IPC is dispatched by RenderWidgetHost, so use its routing id.
+ Send(new InputHostMsg_MoveRangeSelectionExtent_ACK(
+ GetRenderWidget()->routing_id()));
+
+ base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
+ frame_->moveRangeSelectionExtent(point);
+}
+
void RenderFrameImpl::OnReplace(const base::string16& text) {
if (!frame_->hasSelection())
frame_->selectWordAroundCaret();
return;
accessibility_mode_ = new_mode;
if (renderer_accessibility_) {
+ // Note: this isn't called automatically by the destructor because
+ // there'd be no point in calling it in frame teardown, only if there's
+ // an accessibility mode change but the frame is persisting.
+ renderer_accessibility_->DisableAccessibility();
+
delete renderer_accessibility_;
renderer_accessibility_ = NULL;
}
return;
if (accessibility_mode_ & AccessibilityModeFlagFullTree)
- renderer_accessibility_ = new RendererAccessibilityComplete(this);
-#if !defined(OS_ANDROID)
- else
- renderer_accessibility_ = new RendererAccessibilityFocusOnly(this);
-#endif
+ renderer_accessibility_ = new RendererAccessibility(this);
}
void RenderFrameImpl::OnDisownOpener() {
frame_->document().beginExitTransition(WebString::fromUTF8(css_selector));
}
-bool RenderFrameImpl::ShouldUpdateSelectionTextFromContextMenuParams(
- const base::string16& selection_text,
- size_t selection_text_offset,
- const gfx::Range& selection_range,
- const ContextMenuParams& params) {
- base::string16 trimmed_selection_text;
- if (!selection_text.empty() && !selection_range.is_empty()) {
- const int start = selection_range.GetMin() - selection_text_offset;
- const size_t length = selection_range.length();
- if (start >= 0 && start + length <= selection_text.length()) {
- base::TrimWhitespace(selection_text.substr(start, length), base::TRIM_ALL,
- &trimmed_selection_text);
- }
- }
- base::string16 trimmed_params_text;
- base::TrimWhitespace(params.selection_text, base::TRIM_ALL,
- &trimmed_params_text);
- return trimmed_params_text != trimmed_selection_text;
-}
-
bool RenderFrameImpl::RunJavaScriptMessage(JavaScriptMessageType type,
const base::string16& message,
const base::string16& default_value,
render_view_->GetBrowserPluginManager()->Attach(element_instance_id);
}
+void RenderFrameImpl::SetSelectedText(const base::string16& selection_text,
+ size_t offset,
+ const gfx::Range& range) {
+ // Use the routing id of Render Widget Host.
+ Send(new ViewHostMsg_SelectionChanged(GetRenderWidget()->routing_id(),
+ selection_text,
+ offset,
+ range));
+}
+
+void RenderFrameImpl::EnsureMojoBuiltinsAreAvailable(
+ v8::Isolate* isolate,
+ v8::Handle<v8::Context> context) {
+ gin::ModuleRegistry* registry = gin::ModuleRegistry::From(context);
+ if (registry->available_modules().count(mojo::js::Core::kModuleName))
+ return;
+
+ v8::HandleScope handle_scope(isolate);
+ registry->AddBuiltinModule(
+ isolate, mojo::js::Core::kModuleName, mojo::js::Core::GetModule(isolate));
+ registry->AddBuiltinModule(isolate,
+ mojo::js::Support::kModuleName,
+ mojo::js::Support::GetModule(isolate));
+ registry->AddBuiltinModule(
+ isolate,
+ ServiceRegistryJsWrapper::kModuleName,
+ ServiceRegistryJsWrapper::Create(isolate, &service_registry_).ToV8());
+}
+
// blink::WebFrameClient implementation ----------------------------------------
+blink::WebPluginPlaceholder* RenderFrameImpl::createPluginPlaceholder(
+ blink::WebLocalFrame* frame,
+ const blink::WebPluginParams& params) {
+ DCHECK_EQ(frame_, frame);
+ return GetContentClient()
+ ->renderer()
+ ->CreatePluginPlaceholder(this, frame, params)
+ .release();
+}
+
blink::WebPlugin* RenderFrameImpl::createPlugin(
blink::WebLocalFrame* frame,
const blink::WebPluginParams& params) {
if (base::UTF16ToUTF8(params.mimeType) == kBrowserPluginMimeType) {
scoped_ptr<BrowserPluginDelegate> browser_plugin_delegate(
- GetContentClient()->renderer()->CreateBrowserPluginDelegate(
- this, std::string()));
+ GetContentClient()->renderer()->CreateBrowserPluginDelegate(this,
+ kBrowserPluginMimeType, GURL(params.url)));
return render_view_->GetBrowserPluginManager()->CreateBrowserPlugin(
render_view_.get(), frame, browser_plugin_delegate.Pass());
}
if (!found)
return NULL;
- if (info.type == content::WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN) {
+ if (info.type == WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN) {
scoped_ptr<BrowserPluginDelegate> browser_plugin_delegate(
GetContentClient()->renderer()->CreateBrowserPluginDelegate(
- this, base::UTF16ToUTF8(params.mimeType)));
+ this, mime_type, GURL(params.url)));
return render_view_->GetBrowserPluginManager()->CreateBrowserPlugin(
render_view_.get(), frame, browser_plugin_delegate.Pass());
}
GetTizenMediaPlayerManager(), params);
return media_player;
#endif
- return new media::WebMediaPlayerImpl(frame,
- client,
- weak_factory_.GetWeakPtr(),
- params);
+ return new media::WebMediaPlayerImpl(
+ frame, client, weak_factory_.GetWeakPtr(), nullptr, params);
#endif // defined(OS_ANDROID)
}
const blink::WebSecurityOrigin& security_origin,
const blink::WebString& key_system) {
DCHECK(!frame_ || frame_ == frame);
- return WebContentDecryptionModuleImpl::Create(
+
#if defined(ENABLE_PEPPER_CDMS)
- frame,
+ RenderCdmFactory cdm_factory(
+ base::Bind(&PepperCdmWrapperImpl::Create, frame));
#elif defined(ENABLE_BROWSER_CDMS)
- GetCdmManager(),
+ RenderCdmFactory cdm_factory(GetCdmManager());
+#else
+ RenderCdmFactory cdm_factory;
#endif
- security_origin,
- key_system);
+
+ return WebContentDecryptionModuleImpl::Create(&cdm_factory, security_origin,
+ key_system);
}
blink::WebApplicationCacheHost* RenderFrameImpl::createApplicationCacheHost(
navigation_state->pending_history_list_offset();
render_view_->pending_navigation_params_->should_clear_history_list =
navigation_state->history_list_was_cleared();
- render_view_->pending_navigation_params_->transition =
+ render_view_->pending_navigation_params_->common_params.transition =
navigation_state->transition_type();
render_view_->pending_navigation_params_->request_time =
document_state->request_time();
DocumentState::FromDataSource(frame->dataSource());
NavigationState* navigation_state = document_state->navigation_state();
+ if (proxy_routing_id_ != MSG_ROUTING_NONE) {
+ RenderFrameProxy* proxy =
+ RenderFrameProxy::FromRoutingID(proxy_routing_id_);
+ CHECK(proxy);
+ proxy->web_frame()->swap(frame_);
+ proxy_routing_id_ = MSG_ROUTING_NONE;
+ }
+
// When we perform a new navigation, we need to update the last committed
// session history entry with state for the page we are leaving. Do this
// before updating the HistoryController state.
}
}
- Send(new FrameHostMsg_DidAssignPageId(routing_id_, render_view_->page_id_));
+ bool sent = Send(
+ new FrameHostMsg_DidAssignPageId(routing_id_, render_view_->page_id_));
+ CHECK(sent); // http://crbug.com/407376
FOR_EACH_OBSERVER(RenderViewObserver, render_view_->observers_,
DidCommitProvisionalLoad(frame, is_new_navigation));
base::string16 shortened_title = title16.substr(0, kMaxTitleChars);
Send(new FrameHostMsg_UpdateTitle(routing_id_,
- render_view_->page_id_,
shortened_title, direction));
}
render_view_->didUpdateCurrentHistoryItem(frame);
}
+// TODO(zhenw): This will be removed once the blink side implementation is done.
void RenderFrameImpl::addNavigationTransitionData(
const blink::WebString& allowed_destination_host_pattern,
const blink::WebString& selector,
const blink::WebString& markup) {
- Send(new FrameHostMsg_AddNavigationTransitionData(
- routing_id_, allowed_destination_host_pattern.utf8(), selector.utf8(),
- markup.utf8()));
+ FrameHostMsg_AddNavigationTransitionData_Params params;
+ params.render_frame_id = routing_id_;
+ params.allowed_destination_host_pattern =
+ allowed_destination_host_pattern.utf8();
+ params.selector = selector.utf8();
+ params.markup = markup.utf8();
+
+ Send(new FrameHostMsg_AddNavigationTransitionData(params));
+}
+
+void RenderFrameImpl::addNavigationTransitionData(
+ const blink::WebString& allowed_destination_host_pattern,
+ const blink::WebString& selector,
+ const blink::WebString& markup,
+ const blink::WebVector<blink::WebString>& web_names,
+ const blink::WebVector<blink::WebRect>& web_rects) {
+ FrameHostMsg_AddNavigationTransitionData_Params params;
+ params.render_frame_id = routing_id_;
+ params.allowed_destination_host_pattern =
+ allowed_destination_host_pattern.utf8();
+ params.selector = selector.utf8();
+ params.markup = markup.utf8();
+ params.elements.resize(web_names.size());
+ for (size_t i = 0; i < web_names.size(); i++) {
+ params.elements[i].name = web_names[i].utf8();
+ params.elements[i].rect = gfx::Rect(web_rects[i]);
+ }
+
+ Send(new FrameHostMsg_AddNavigationTransitionData(params));
}
void RenderFrameImpl::didChangeThemeColor() {
const blink::WebVector<blink::WebColorSuggestion>& suggestions) {
RendererWebColorChooserImpl* color_chooser =
new RendererWebColorChooserImpl(this, client);
- std::vector<content::ColorSuggestion> color_suggestions;
+ std::vector<ColorSuggestion> color_suggestions;
for (size_t i = 0; i < suggestions.size(); i++) {
- color_suggestions.push_back(content::ColorSuggestion(suggestions[i]));
+ color_suggestions.push_back(ColorSuggestion(suggestions[i]));
}
color_chooser->Open(static_cast<SkColor>(initial_color), color_suggestions);
return color_chooser;
params.y = GetRenderWidget()->host_context_menu_location().y();
}
- // Plugins, e.g. PDF, don't currently update the render view when their
- // selected text changes, but the context menu params do contain the updated
- // selection. If that's the case, update the render view's state just prior
- // to showing the context menu.
- // TODO(asvitkine): http://crbug.com/152432
- if (ShouldUpdateSelectionTextFromContextMenuParams(
- selection_text_, selection_text_offset_, selection_range_, params)) {
- selection_text_ = params.selection_text;
- // TODO(asvitkine): Text offset and range is not available in this case.
- selection_text_offset_ = 0;
- selection_range_ = gfx::Range(0, selection_text_.length());
- // This IPC is dispatched by RenderWidetHost, so use its routing ID.
- Send(new ViewHostMsg_SelectionChanged(
- GetRenderWidget()->routing_id(), selection_text_,
- selection_text_offset_, selection_range_));
- }
-
// Serializing a GURL longer than kMaxURLChars will fail, so don't do
// it. We replace it with an empty GURL so the appropriate items are disabled
// in the context menu.
// user agent on its own. Similarly, it may indicate that we should set an
// X-Requested-With header. This must be done here to avoid breaking CORS
// checks.
+ // PlzNavigate: there may also be a stream url associated with the request.
WebString custom_user_agent;
WebString requested_with;
+ scoped_ptr<StreamOverrideParameters> stream_override;
if (request.extraData()) {
RequestExtraData* old_extra_data =
static_cast<RequestExtraData*>(request.extraData());
else
request.setHTTPHeaderField("X-Requested-With", requested_with);
}
+ stream_override = old_extra_data->TakeStreamOverrideOwnership();
}
// Add the default accept header for frame request if it has not been set
extra_data->set_transferred_request_request_id(
navigation_state->transferred_request_request_id());
extra_data->set_service_worker_provider_id(provider_id);
+ extra_data->set_stream_override(stream_override.Pass());
request.setExtraData(extra_data);
DocumentState* top_document_state =
extra_data->connection_info());
document_state->set_was_fetched_via_proxy(
extra_data->was_fetched_via_proxy());
+ document_state->set_proxy_server(
+ extra_data->proxy_server());
}
InternalDocumentStateData* internal_data =
InternalDocumentStateData::FromDocumentState(document_state);
QuotaDispatcher::CreateWebStorageQuotaCallbacksWrapper(callbacks));
}
-void RenderFrameImpl::willOpenSocketStream(
- blink::WebSocketStreamHandle* handle) {
- WebSocketStreamHandleImpl* impl =
- static_cast<WebSocketStreamHandleImpl*>(handle);
- impl->SetUserData(handle, new SocketStreamHandleData(routing_id_));
-}
-
void RenderFrameImpl::willOpenWebSocket(blink::WebSocketHandle* handle) {
WebSocketBridge* impl = static_cast<WebSocketBridge*>(handle);
impl->set_render_frame_id(routing_id_);
return geolocation_dispatcher_;
}
+void RenderFrameImpl::requestPushPermission(blink::WebCallback* callback) {
+ if (!push_permission_dispatcher_)
+ push_permission_dispatcher_ = new PushPermissionDispatcher(this);
+ push_permission_dispatcher_->RequestPermission(callback);
+}
+
blink::WebPushClient* RenderFrameImpl::pushClient() {
if (!push_messaging_dispatcher_)
push_messaging_dispatcher_ = new PushMessagingDispatcher(this);
blink::WebString RenderFrameImpl::userAgentOverride(blink::WebLocalFrame* frame,
const blink::WebURL& url) {
DCHECK(!frame_ || frame_ == frame);
+ std::string user_agent_override_for_url =
+ GetContentClient()->renderer()->GetUserAgentOverrideForURL(GURL(url));
+ if (!user_agent_override_for_url.empty())
+ return WebString::fromUTF8(user_agent_override_for_url);
+
if (!render_view_->webview() || !render_view_->webview()->mainFrame() ||
render_view_->renderer_preferences_.user_agent_override.empty()) {
return blink::WebString();
}
+ // TODO(nasko): When the top-level frame is remote, there is no WebDataSource
+ // associated with it, so the checks below are not valid. Temporarily
+ // return early and fix properly as part of https://crbug.com/426555.
+ if (render_view_->webview()->mainFrame()->isWebRemoteFrame())
+ return blink::WebString();
+
// If we're in the middle of committing a load, the data source we need
// will still be provisional.
WebFrame* main_frame = render_view_->webview()->mainFrame();
arb_robustness_status_code));
}
-void RenderFrameImpl::forwardInputEvent(const blink::WebInputEvent* event) {
- Send(new FrameHostMsg_ForwardInputEvent(routing_id_, event));
-}
-
blink::WebScreenOrientationClient*
RenderFrameImpl::webScreenOrientationClient() {
if (!screen_orientation_dispatcher_)
return screen_orientation_dispatcher_;
}
-bool RenderFrameImpl::isControlledByServiceWorker() {
- // If we're in the middle of committing a load, the data source we need
- // will still be provisional.
- WebFrame* main_frame = render_view_->webview()->mainFrame();
- WebDataSource* data_source = NULL;
- if (main_frame->provisionalDataSource())
- data_source = main_frame->provisionalDataSource();
- else
- data_source = main_frame->dataSource();
+bool RenderFrameImpl::isControlledByServiceWorker(WebDataSource& data_source) {
ServiceWorkerNetworkProvider* provider =
ServiceWorkerNetworkProvider::FromDocumentState(
- DocumentState::FromDataSource(data_source));
+ DocumentState::FromDataSource(&data_source));
return provider->context()->controller_handle_id() !=
kInvalidServiceWorkerHandleId;
}
+int64_t RenderFrameImpl::serviceWorkerID(WebDataSource& data_source) {
+ ServiceWorkerNetworkProvider* provider =
+ ServiceWorkerNetworkProvider::FromDocumentState(
+ DocumentState::FromDataSource(&data_source));
+
+ if (provider->context()->controller())
+ return provider->context()->controller()->version_id();
+ return kInvalidServiceWorkerVersionId;
+}
+
void RenderFrameImpl::postAccessibilityEvent(const blink::WebAXObject& obj,
blink::WebAXEvent event) {
HandleWebAccessibilityEvent(obj, event);
}
+void RenderFrameImpl::handleAccessibilityFindInPageResult(
+ int identifier,
+ int match_index,
+ const blink::WebAXObject& start_object,
+ int start_offset,
+ const blink::WebAXObject& end_object,
+ int end_offset) {
+ if (renderer_accessibility_) {
+ renderer_accessibility_->HandleAccessibilityFindInPageResult(
+ identifier, match_index, start_object, start_offset,
+ end_object, end_offset);
+ }
+}
+
void RenderFrameImpl::didChangeManifest(blink::WebLocalFrame* frame)
{
DCHECK(!frame_ || frame_ == frame);
// Reset the zoom levels for plugins.
render_view_->webview()->setZoomLevel(0);
} else {
+ // If the zoom level is not found, then do nothing. In-page navigation
+ // relies on not changing the zoom level in this case.
if (host_zoom != render_view_->host_zoom_levels_.end())
render_view_->webview()->setZoomLevel(host_zoom->second);
}
renderer_accessibility_->FocusedNodeChanged(node);
}
+// PlzNavigate
+void RenderFrameImpl::OnRequestNavigation(
+ const CommonNavigationParams& common_params,
+ const RequestNavigationParams& request_params) {
+ CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation));
+
+ // TODO(clamy): Execute the beforeunload event.
+
+ WebURLRequest request =
+ CreateURLRequestForNavigation(common_params,
+ request_params,
+ scoped_ptr<StreamOverrideParameters>(),
+ frame_->isViewSourceModeEnabled());
+
+ // Note: At this stage, the goal is to apply all the modifications the
+ // renderer wants to make to the request, and then send it to the browser, so
+ // that the actual network request can be started. Ideally, all such
+ // modifications should take place in willSendRequest, and in the
+ // implementation of willSendRequest for the various InspectorAgents
+ // (devtools).
+ //
+ // TODO(clamy): Apply devtools override.
+ // TODO(clamy): Make sure that navigation requests are not modified somewhere
+ // else in blink.
+ willSendRequest(frame_, 0, request, blink::WebURLResponse());
+
+ // TODO(clamy): Same-document navigations should not be sent back to the
+ // browser.
+ Send(new FrameHostMsg_BeginNavigation(routing_id_,
+ MakeBeginNavigationParams(request),
+ MakeCommonNavigationParams(request)));
+}
+
+// PlzNavigate
+void RenderFrameImpl::OnCommitNavigation(
+ const ResourceResponseHead& response,
+ const GURL& stream_url,
+ const CommonNavigationParams& common_params,
+ const CommitNavigationParams& commit_params) {
+ CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation));
+ bool is_reload = false;
+ WebURLRequest::CachePolicy cache_policy =
+ WebURLRequest::UseProtocolCachePolicy;
+ if (!RenderFrameImpl::PrepareRenderViewForNavigation(
+ common_params.url, common_params.navigation_type,
+ commit_params.page_state, false, -1, -1, &is_reload, &cache_policy)) {
+ return;
+ }
+
+ GetContentClient()->SetActiveURL(common_params.url);
+
+ // Create a WebURLRequest that blink can use to get access to the body of the
+ // response through a stream in the browser. Blink will then commit the
+ // navigation.
+ // TODO(clamy): Have the navigation commit directly, without going through
+ // loading a WebURLRequest.
+ scoped_ptr<StreamOverrideParameters> stream_override(
+ new StreamOverrideParameters());
+ stream_override->stream_url = stream_url;
+ stream_override->response = response;
+ WebURLRequest request =
+ CreateURLRequestForNavigation(common_params,
+ RequestNavigationParams(),
+ stream_override.Pass(),
+ frame_->isViewSourceModeEnabled());
+
+ // Record this before starting the load. A lower bound of this time is needed
+ // to sanitize the navigationStart override set below.
+ base::TimeTicks renderer_navigation_start = base::TimeTicks::Now();
+ frame_->loadRequest(request);
+ UpdateFrameNavigationTiming(
+ frame_, commit_params.browser_navigation_start,
+ renderer_navigation_start);
+}
+
WebNavigationPolicy RenderFrameImpl::DecidePolicyForNavigation(
RenderFrame* render_frame,
const NavigationPolicyInfo& info) {
navigation_state()->is_content_initiated();
// Experimental:
- // If --enable-strict-site-isolation or --site-per-process is enabled, send
- // all top-level navigations to the browser to let it swap processes when
- // crossing site boundaries. This is currently expected to break some script
- // calls and navigations, such as form submissions.
+ // If --enable-strict-site-isolation is enabled, send all top-level
+ // navigations to the browser to let it swap processes when crossing site
+ // boundaries. This is currently expected to break some script calls and
+ // navigations, such as form submissions.
bool force_swap_due_to_flag =
- command_line.HasSwitch(switches::kEnableStrictSiteIsolation) ||
- command_line.HasSwitch(switches::kSitePerProcess);
+ command_line.HasSwitch(switches::kEnableStrictSiteIsolation);
if (force_swap_due_to_flag &&
!info.frame->parent() && (is_content_initiated || info.isRedirect)) {
WebString origin_str = info.frame->document().securityOrigin().toString();
frame_url,
url,
net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
- if (!same_domain_or_host || frame_url.scheme() != url.scheme()) {
+ // Only keep same-site (domain + scheme) and data URLs in the same process.
+ bool is_same_site =
+ (same_domain_or_host && frame_url.scheme() == url.scheme()) ||
+ url.SchemeIs(url::kDataScheme);
+ if (!is_same_site) {
OpenURL(info.frame, url, referrer, info.defaultPolicy);
return blink::WebNavigationPolicyIgnore;
}
selection_text_ = text;
selection_text_offset_ = offset;
selection_range_ = range;
- // This IPC is dispatched by RenderWidetHost, so use its routing ID.
- Send(new ViewHostMsg_SelectionChanged(
- GetRenderWidget()->routing_id(), text, offset, range));
+ SetSelectedText(text, offset, range);
}
GetRenderWidget()->UpdateSelectionBounds();
}
#endif
}
+bool RenderFrameImpl::PrepareRenderViewForNavigation(
+ const GURL& url,
+ FrameMsg_Navigate_Type::Value navigate_type,
+ const PageState& state,
+ bool check_history,
+ int pending_history_list_offset,
+ int32 page_id,
+ bool* is_reload,
+ WebURLRequest::CachePolicy* cache_policy) {
+ MaybeHandleDebugURL(url);
+ if (!render_view_->webview())
+ return false;
+
+ FOR_EACH_OBSERVER(
+ RenderViewObserver, render_view_->observers_, Navigate(url));
+
+ // If this is a stale back/forward (due to a recent navigation the browser
+ // didn't know about), ignore it.
+ if (check_history && render_view_->IsBackForwardToStaleEntry(
+ state, pending_history_list_offset, page_id, *is_reload))
+ return false;
+
+ if (!render_view_->is_swapped_out_ ||
+ GetWebFrame() != render_view_->webview()->mainFrame())
+ return true;
+
+ // This is a swapped out main frame, so swap the renderer back in.
+ // We marked the view as hidden when swapping the view out, so be sure to
+ // reset the visibility state before navigating to the new URL.
+ render_view_->webview()->setVisibilityState(
+ render_view_->visibilityState(), false);
+
+ // If this is an attempt to reload while we are swapped out, we should not
+ // reload swappedout://, but the previous page, which is stored in
+ // params.state. Setting is_reload to false will treat this like a back
+ // navigation to accomplish that.
+ *is_reload = false;
+ *cache_policy = WebURLRequest::ReloadIgnoringCacheData;
+
+ // We refresh timezone when a view is swapped in since timezone
+ // can get out of sync when the system timezone is updated while
+ // the view is swapped out.
+ RenderThreadImpl::NotifyTimezoneChange();
+
+ render_view_->SetSwappedOut(false);
+ is_swapped_out_ = false;
+ return true;
+}
+
GURL RenderFrameImpl::GetLoadingUrl() const {
WebDataSource* ds = frame_->dataSource();
if (ds->hasUnreachableURL())