Chromium Code Reviews| Index: content/renderer/render_frame_impl.cc |
| diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc |
| index d411147589e6a4a92c1f6315ee13c27ff4c00e2d..e9f8f2787236a5de4c84c279b00700df294fdf0f 100644 |
| --- a/content/renderer/render_frame_impl.cc |
| +++ b/content/renderer/render_frame_impl.cc |
| @@ -38,6 +38,7 @@ |
| #include "content/common/frame_messages.h" |
| #include "content/common/frame_replication_state.h" |
| #include "content/common/input_messages.h" |
| +#include "content/common/navigation_params.h" |
| #include "content/common/service_worker/service_worker_types.h" |
| #include "content/common/swapped_out_messages.h" |
| #include "content/common/view_messages.h" |
| @@ -488,6 +489,12 @@ media::Context3D GetSharedMainThreadContext3D() { |
| } |
| #endif |
| +bool IsReload(FrameMsg_Navigate_Type::Value navigation_type) { |
| + return navigation_type == FrameMsg_Navigate_Type::RELOAD || |
| + navigation_type == FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE || |
| + navigation_type == FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL; |
| +} |
| + |
| RenderFrameImpl::CreateRenderFrameImplFunction g_create_render_frame_impl = |
| nullptr; |
| @@ -1047,7 +1054,7 @@ void RenderFrameImpl::OnNavigate( |
| TRACE_EVENT2("navigation", "RenderFrameImpl::OnNavigate", "id", routing_id_, |
| "url", common_params.url.possibly_invalid_spec()); |
| - bool is_reload = RenderViewImpl::IsReload(common_params.navigation_type); |
| + bool is_reload = IsReload(common_params.navigation_type); |
| bool is_history_navigation = history_params.page_state.IsValid(); |
| WebURLRequest::CachePolicy cache_policy = |
| WebURLRequest::UseProtocolCachePolicy; |
| @@ -1076,7 +1083,7 @@ void RenderFrameImpl::OnNavigate( |
| cache_policy = WebURLRequest::ReloadIgnoringCacheData; |
| } |
| - render_view_->pending_navigation_params_.reset(new NavigationParams( |
| + provisional_navigation_params_.reset(new NavigationParams( |
| common_params, start_params, commit_params, history_params)); |
| // If we are reloading, then WebKit will use the history state of the current |
| @@ -1103,7 +1110,10 @@ void RenderFrameImpl::OnNavigate( |
| // Ensure we didn't save the swapped out URL in UpdateState, since the |
| // browser should never be telling us to navigate to swappedout://. |
| CHECK(entry->root().urlString() != WebString::fromUTF8(kSwappedOutURL)); |
| - render_view_->history_controller()->GoToEntry(entry.Pass(), cache_policy); |
| + scoped_ptr<NavigationParams> navigation_params( |
| + new NavigationParams(*provisional_navigation_params_.get())); |
| + render_view_->history_controller()->GoToEntry( |
| + entry.Pass(), navigation_params.Pass(), cache_policy); |
| } |
| } else if (!common_params.base_url_for_data_url.is_empty()) { |
| LoadDataURL(common_params, frame); |
| @@ -1151,8 +1161,8 @@ void RenderFrameImpl::OnNavigate( |
| renderer_navigation_start); |
| } |
| - // In case LoadRequest failed before DidCreateDataSource was called. |
| - render_view_->pending_navigation_params_.reset(); |
| + // In case LoadRequest failed before didCreateDataSource was called. |
| + provisional_navigation_params_.reset(); |
| } |
| void RenderFrameImpl::NavigateToSwappedOutURL() { |
| @@ -1179,6 +1189,11 @@ ManifestManager* RenderFrameImpl::manifest_manager() { |
| return manifest_manager_; |
| } |
| +void RenderFrameImpl::SetProvisionalNavigationParams( |
| + scoped_ptr<NavigationParams> navigation_params) { |
| + provisional_navigation_params_ = navigation_params.Pass(); |
| +} |
| + |
| void RenderFrameImpl::OnBeforeUnload() { |
| TRACE_EVENT1("navigation", "RenderFrameImpl::OnBeforeUnload", |
| "id", routing_id_); |
| @@ -2290,13 +2305,98 @@ void RenderFrameImpl::didCreateDataSource(blink::WebLocalFrame* frame, |
| blink::WebDataSource* datasource) { |
| DCHECK(!frame_ || frame_ == frame); |
| - // TODO(nasko): Move implementation here. Needed state: |
| - // * pending_navigation_params_ |
| - // * webview |
| - // Needed methods: |
| - // * PopulateDocumentStateFromPending |
| - // * CreateNavigationStateFromPending |
| - render_view_->didCreateDataSource(frame, datasource); |
| + bool content_initiated = !provisional_navigation_params_.get(); |
| + |
| + // Make sure any previous redirect URLs end up in our new data source. |
| + if (provisional_navigation_params_.get()) { |
| + for (const auto& i : |
| + provisional_navigation_params_->commit_params.redirects) { |
| + datasource->appendRedirect(i); |
| + } |
| + } |
| + |
| + DocumentState* document_state = DocumentState::FromDataSource(datasource); |
| + if (!document_state) { |
| + document_state = new DocumentState; |
| + datasource->setExtraData(document_state); |
| + if (!content_initiated) |
| + PopulateDocumentStateFromPending(document_state); |
| + } |
| + |
| + // Carry over the user agent override flag, if it exists. |
| + blink::WebView* webview = render_view_->webview(); |
| + if (content_initiated && webview && webview->mainFrame() && |
| + webview->mainFrame()->isWebLocalFrame() && |
| + webview->mainFrame()->dataSource()) { |
| + DocumentState* old_document_state = |
| + DocumentState::FromDataSource(webview->mainFrame()->dataSource()); |
| + if (old_document_state) { |
| + InternalDocumentStateData* internal_data = |
| + InternalDocumentStateData::FromDocumentState(document_state); |
| + InternalDocumentStateData* old_internal_data = |
| + InternalDocumentStateData::FromDocumentState(old_document_state); |
| + internal_data->set_is_overriding_user_agent( |
| + old_internal_data->is_overriding_user_agent()); |
| + } |
| + } |
| + |
| + // The rest of RenderView assumes that a WebDataSource will always have a |
| + // non-null NavigationState. |
| + if (content_initiated) { |
| + document_state->set_navigation_state( |
| + NavigationStateImpl::CreateContentInitiated()); |
| + } else { |
| + document_state->set_navigation_state(CreateNavigationStateFromPending()); |
| + provisional_navigation_params_.reset(); |
| + } |
| + |
| + // DocumentState::referred_by_prefetcher_ is true if we are |
| + // navigating from a page that used prefetching using a link on that |
| + // page. We are early enough in the request process here that we |
| + // can still see the DocumentState of the previous page and set |
| + // this value appropriately. |
| + // TODO(gavinp): catch the important case of navigation in a new |
| + // renderer process. |
| + if (webview) { |
| + if (WebFrame* old_frame = webview->mainFrame()) { |
| + const WebURLRequest& original_request = datasource->originalRequest(); |
| + const GURL referrer( |
| + original_request.httpHeaderField(WebString::fromUTF8("Referer"))); |
| + if (!referrer.is_empty() && old_frame->isWebLocalFrame() && |
| + DocumentState::FromDataSource(old_frame->dataSource()) |
| + ->was_prefetcher()) { |
| + for (; old_frame; old_frame = old_frame->traverseNext(false)) { |
| + WebDataSource* old_frame_datasource = old_frame->dataSource(); |
| + if (old_frame_datasource && |
| + referrer == GURL(old_frame_datasource->request().url())) { |
| + document_state->set_was_referred_by_prefetcher(true); |
| + break; |
| + } |
| + } |
| + } |
| + } |
| + } |
| + |
| + if (content_initiated) { |
| + const WebURLRequest& request = datasource->request(); |
| + switch (request.cachePolicy()) { |
| + case WebURLRequest::UseProtocolCachePolicy: // normal load. |
| + document_state->set_load_type(DocumentState::LINK_LOAD_NORMAL); |
| + break; |
| + case WebURLRequest::ReloadIgnoringCacheData: // reload. |
| + case WebURLRequest::ReloadBypassingCache: // end-to-end reload. |
| + document_state->set_load_type(DocumentState::LINK_LOAD_RELOAD); |
| + break; |
| + case WebURLRequest::ReturnCacheDataElseLoad: // allow stale data. |
| + document_state->set_load_type(DocumentState::LINK_LOAD_CACHE_STALE_OK); |
| + break; |
| + case WebURLRequest::ReturnCacheDataDontLoad: // Don't re-post. |
| + document_state->set_load_type(DocumentState::LINK_LOAD_CACHE_ONLY); |
| + break; |
| + default: |
| + NOTREACHED(); |
| + } |
| + } |
| // Create the serviceworker's per-document network observing object if it |
| // does not exist (When navigation happens within a page, the provider already |
| @@ -2454,7 +2554,7 @@ void RenderFrameImpl::didFailProvisionalLoad(blink::WebLocalFrame* frame, |
| // If we failed on a browser initiated request, then make sure that our error |
| // page load is regarded as the same browser initiated request. |
| if (!navigation_state->IsContentInitiated()) { |
| - render_view_->pending_navigation_params_.reset(new NavigationParams( |
| + provisional_navigation_params_.reset(new NavigationParams( |
| navigation_state->common_params(), navigation_state->start_params(), |
| CommitNavigationParams(false, base::TimeTicks(), std::vector<GURL>(), |
| false, std::string(), |
| @@ -2507,8 +2607,7 @@ void RenderFrameImpl::didCommitProvisionalLoad( |
| } |
| internal_data->set_use_error_page(false); |
| - bool is_new_navigation = commit_type == blink::WebStandardCommit; |
|
Charlie Reis
2015/03/23 22:23:02
Why remove this if we need it below?
Avi (use Gerrit)
2015/03/24 20:33:46
To keep the if() branches parallel:
if (commit_ty
|
| - if (is_new_navigation) { |
| + if (commit_type == blink::WebStandardCommit) { |
| // We bump our Page ID to correspond with the new session history entry. |
| render_view_->page_id_ = render_view_->next_page_id_++; |
| @@ -2531,32 +2630,17 @@ void RenderFrameImpl::didCommitProvisionalLoad( |
| render_view_->history_list_length_ = |
| render_view_->history_list_offset_ + 1; |
| } |
| - } else { |
| - // Inspect the navigation_state on this frame to see if the navigation |
| - // corresponds to a session history navigation... Note: |frame| may or |
| - // may not be the toplevel frame, but for the case of capturing session |
| - // history, the first committed frame suffices. We keep track of whether |
| - // we've seen this commit before so that only capture session history once |
| - // per navigation. |
| - // |
| - // Note that we need to check if the page ID changed. In the case of a |
| - // reload, the page ID doesn't change, and UpdateSessionHistory gets the |
| - // previous URL and the current page ID, which would be wrong. |
| - if (navigation_state->history_params().page_id != -1 && |
| - navigation_state->history_params().page_id != render_view_->page_id_ && |
| - !navigation_state->request_committed()) { |
| - // This is a successful session history navigation! |
| - render_view_->page_id_ = navigation_state->history_params().page_id; |
| - |
| - render_view_->history_list_offset_ = |
| - navigation_state->history_params().pending_history_list_offset; |
| - } |
| + } else if (commit_type == blink::WebBackForwardCommit) { |
|
Charlie Reis
2015/03/23 22:23:02
What would you think about doing this part of the
Avi (use Gerrit)
2015/03/24 20:33:46
Hmm... In the original change, the !navigation_sta
Charlie Reis
2015/03/24 22:04:08
Acknowledged.
|
| + render_view_->page_id_ = navigation_state->history_params().page_id; |
| + render_view_->history_list_offset_ = |
| + navigation_state->history_params().pending_history_list_offset; |
| } |
| bool sent = Send( |
| new FrameHostMsg_DidAssignPageId(routing_id_, render_view_->page_id_)); |
| CHECK(sent); // http://crbug.com/407376 |
| + bool is_new_navigation = commit_type == blink::WebStandardCommit; |
| FOR_EACH_OBSERVER(RenderViewObserver, render_view_->observers_, |
| DidCommitProvisionalLoad(frame, is_new_navigation)); |
| FOR_EACH_OBSERVER( |
| @@ -2771,7 +2855,7 @@ void RenderFrameImpl::didNavigateWithinPage(blink::WebLocalFrame* frame, |
| // ExtraData will get the new NavigationState. Similarly, if we did not |
| // initiate this navigation, then we need to take care to reset any pre- |
| // existing navigation state to a content-initiated navigation state. |
| - // DidCreateDataSource conveniently takes care of this for us. |
| + // didCreateDataSource conveniently takes care of this for us. |
| didCreateDataSource(frame, frame->dataSource()); |
| DocumentState* document_state = |
| @@ -3942,7 +4026,7 @@ void RenderFrameImpl::OnCommitNavigation( |
| GetContentClient()->SetActiveURL(common_params.url); |
| - render_view_->pending_navigation_params_.reset(new NavigationParams( |
| + provisional_navigation_params_.reset(new NavigationParams( |
| common_params, StartNavigationParams(), commit_params, history_params)); |
| if (!common_params.base_url_for_data_url.is_empty() || |
| @@ -4484,6 +4568,61 @@ GURL RenderFrameImpl::GetLoadingUrl() const { |
| return request.url(); |
| } |
| +void RenderFrameImpl::PopulateDocumentStateFromPending( |
| + DocumentState* document_state) { |
| + document_state->set_request_time( |
| + provisional_navigation_params_->commit_params.request_time); |
| + |
| + InternalDocumentStateData* internal_data = |
| + InternalDocumentStateData::FromDocumentState(document_state); |
| + |
| + if (!provisional_navigation_params_->common_params.url.SchemeIs( |
| + url::kJavaScriptScheme) && |
| + provisional_navigation_params_->common_params.navigation_type == |
| + FrameMsg_Navigate_Type::RESTORE) { |
| + // We're doing a load of a page that was restored from the last session. By |
| + // default this prefers the cache over loading (LOAD_PREFERRING_CACHE) which |
| + // can result in stale data for pages that are set to expire. We explicitly |
| + // override that by setting the policy here so that as necessary we load |
| + // from the network. |
| + // |
| + // TODO(davidben): Remove this in favor of passing a cache policy to the |
| + // loadHistoryItem call in OnNavigate. That requires not overloading |
| + // UseProtocolCachePolicy to mean both "normal load" and "determine cache |
| + // policy based on load type, etc". |
| + internal_data->set_cache_policy_override( |
| + WebURLRequest::UseProtocolCachePolicy); |
| + } |
| + |
| + if (IsReload(provisional_navigation_params_->common_params.navigation_type)) |
| + document_state->set_load_type(DocumentState::RELOAD); |
| + else if (provisional_navigation_params_->history_params.page_state.IsValid()) |
| + document_state->set_load_type(DocumentState::HISTORY_LOAD); |
| + else |
| + document_state->set_load_type(DocumentState::NORMAL_LOAD); |
| + |
| + internal_data->set_is_overriding_user_agent( |
| + provisional_navigation_params_->commit_params.is_overriding_user_agent); |
| + internal_data->set_must_reset_scroll_and_scale_state( |
| + provisional_navigation_params_->common_params.navigation_type == |
| + FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL); |
| + document_state->set_can_load_local_resources( |
| + provisional_navigation_params_->commit_params.can_load_local_resources); |
| +} |
| + |
| +NavigationState* RenderFrameImpl::CreateNavigationStateFromPending() { |
| + // A navigation resulting from loading a javascript URL should not be treated |
| + // as a browser initiated event. Instead, we want it to look as if the page |
| + // initiated any load resulting from JS execution. |
| + if (!provisional_navigation_params_->common_params.url.SchemeIs( |
| + url::kJavaScriptScheme)) { |
| + return NavigationStateImpl::CreateBrowserInitiated( |
| + provisional_navigation_params_->common_params, |
| + provisional_navigation_params_->start_params, |
| + provisional_navigation_params_->history_params); |
| + } |
| + return NavigationStateImpl::CreateContentInitiated(); |
| +} |
| #if defined(OS_ANDROID) |
| WebMediaPlayer* RenderFrameImpl::CreateAndroidWebMediaPlayer( |