This source file includes following definitions.
- GetNavigationType
- MakeNavigateParams
- GetRenderManager
- delegate_
- DidStartProvisionalLoad
- DidFailProvisionalLoadWithError
- DidFailLoadWithError
- DidRedirectProvisionalLoad
- NavigateToEntry
- NavigateToPendingEntry
- GetCurrentLoadStart
- DidNavigate
- ShouldAssignSiteForURL
- RequestOpenURL
- RequestTransferURL
#include "content/browser/frame_host/navigator_impl.h"
#include "base/command_line.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/navigation_controller_impl.h"
#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/frame_host/navigator_delegate.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/site_instance_impl.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/browser/webui/web_ui_impl.h"
#include "content/common/frame_messages.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/invalidate_type.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/page_navigator.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
namespace content {
namespace {
FrameMsg_Navigate_Type::Value GetNavigationType(
BrowserContext* browser_context, const NavigationEntryImpl& entry,
NavigationController::ReloadType reload_type) {
switch (reload_type) {
case NavigationControllerImpl::RELOAD:
return FrameMsg_Navigate_Type::RELOAD;
case NavigationControllerImpl::RELOAD_IGNORING_CACHE:
return FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE;
case NavigationControllerImpl::RELOAD_ORIGINAL_REQUEST_URL:
return FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL;
case NavigationControllerImpl::NO_RELOAD:
break;
}
if (entry.restore_type() ==
NavigationEntryImpl::RESTORE_LAST_SESSION_EXITED_CLEANLY) {
if (entry.GetHasPostData())
return FrameMsg_Navigate_Type::RESTORE_WITH_POST;
return FrameMsg_Navigate_Type::RESTORE;
}
return FrameMsg_Navigate_Type::NORMAL;
}
void MakeNavigateParams(const NavigationEntryImpl& entry,
const NavigationControllerImpl& controller,
NavigationController::ReloadType reload_type,
FrameMsg_Navigate_Params* params) {
params->page_id = entry.GetPageID();
params->should_clear_history_list = entry.should_clear_history_list();
params->should_replace_current_entry = entry.should_replace_entry();
if (entry.should_clear_history_list()) {
params->pending_history_list_offset = -1;
params->current_history_list_offset = -1;
params->current_history_list_length = 0;
} else {
params->pending_history_list_offset = controller.GetIndexOfEntry(&entry);
params->current_history_list_offset =
controller.GetLastCommittedEntryIndex();
params->current_history_list_length = controller.GetEntryCount();
}
params->url = entry.GetURL();
if (!entry.GetBaseURLForDataURL().is_empty()) {
params->base_url_for_data_url = entry.GetBaseURLForDataURL();
params->history_url_for_data_url = entry.GetVirtualURL();
}
params->referrer = entry.GetReferrer();
params->transition = entry.GetTransitionType();
params->page_state = entry.GetPageState();
params->navigation_type =
GetNavigationType(controller.GetBrowserContext(), entry, reload_type);
params->request_time = base::Time::Now();
params->extra_headers = entry.extra_headers();
params->transferred_request_child_id =
entry.transferred_global_request_id().child_id;
params->transferred_request_request_id =
entry.transferred_global_request_id().request_id;
params->is_overriding_user_agent = entry.GetIsOverridingUserAgent();
params->allow_download = !entry.IsViewSourceMode();
params->is_post = entry.GetHasPostData();
if (entry.GetBrowserInitiatedPostData()) {
params->browser_initiated_post_data.assign(
entry.GetBrowserInitiatedPostData()->front(),
entry.GetBrowserInitiatedPostData()->front() +
entry.GetBrowserInitiatedPostData()->size());
}
params->redirects = entry.redirect_chain();
params->can_load_local_resources = entry.GetCanLoadLocalResources();
params->frame_to_navigate = entry.GetFrameToNavigate();
}
RenderFrameHostManager* GetRenderManager(RenderFrameHostImpl* rfh) {
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess))
return rfh->frame_tree_node()->render_manager();
return rfh->frame_tree_node()->frame_tree()->root()->render_manager();
}
}
NavigatorImpl::NavigatorImpl(
NavigationControllerImpl* navigation_controller,
NavigatorDelegate* delegate)
: controller_(navigation_controller),
delegate_(delegate) {
}
void NavigatorImpl::DidStartProvisionalLoad(
RenderFrameHostImpl* render_frame_host,
int parent_routing_id,
const GURL& url) {
bool is_error_page = (url.spec() == kUnreachableWebDataURL);
bool is_iframe_srcdoc = (url.spec() == kAboutSrcDocURL);
GURL validated_url(url);
RenderProcessHost* render_process_host = render_frame_host->GetProcess();
render_process_host->FilterURL(false, &validated_url);
bool is_main_frame = render_frame_host->frame_tree_node()->IsMainFrame();
NavigationEntryImpl* pending_entry =
NavigationEntryImpl::FromNavigationEntry(controller_->GetPendingEntry());
if (is_main_frame) {
bool has_browser_initiated_pending_entry = pending_entry &&
!pending_entry->is_renderer_initiated();
if (!has_browser_initiated_pending_entry && !is_error_page) {
NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
controller_->CreateNavigationEntry(validated_url,
content::Referrer(),
content::PAGE_TRANSITION_LINK,
true ,
std::string(),
controller_->GetBrowserContext()));
entry->set_site_instance(
static_cast<SiteInstanceImpl*>(
render_frame_host->render_view_host()->GetSiteInstance()));
if (pending_entry) {
entry->set_transferred_global_request_id(
pending_entry->transferred_global_request_id());
entry->set_should_replace_entry(pending_entry->should_replace_entry());
entry->set_redirect_chain(pending_entry->redirect_chain());
}
controller_->SetPendingEntry(entry);
if (delegate_)
delegate_->NotifyChangedNavigationState(content::INVALIDATE_TYPE_URL);
}
}
if (delegate_) {
delegate_->DidStartProvisionalLoad(
render_frame_host, parent_routing_id,
validated_url, is_error_page, is_iframe_srcdoc);
}
}
void NavigatorImpl::DidFailProvisionalLoadWithError(
RenderFrameHostImpl* render_frame_host,
const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params) {
VLOG(1) << "Failed Provisional Load: " << params.url.possibly_invalid_spec()
<< ", error_code: " << params.error_code
<< ", error_description: " << params.error_description
<< ", showing_repost_interstitial: " <<
params.showing_repost_interstitial
<< ", frame_id: " << render_frame_host->GetRoutingID();
GURL validated_url(params.url);
RenderProcessHost* render_process_host = render_frame_host->GetProcess();
render_process_host->FilterURL(false, &validated_url);
if (net::ERR_ABORTED == params.error_code) {
FrameTreeNode* root =
render_frame_host->frame_tree_node()->frame_tree()->root();
if (root->render_manager()->interstitial_page() != NULL) {
LOG(WARNING) << "Discarding message during interstitial.";
return;
}
}
if (controller_->GetPendingEntry() != controller_->GetVisibleEntry())
controller_->DiscardPendingEntry();
if (delegate_)
delegate_->DidFailProvisionalLoadWithError(render_frame_host, params);
}
void NavigatorImpl::DidFailLoadWithError(
RenderFrameHostImpl* render_frame_host,
const GURL& url,
int error_code,
const base::string16& error_description) {
if (delegate_) {
delegate_->DidFailLoadWithError(
render_frame_host, url, error_code,
error_description);
}
}
void NavigatorImpl::DidRedirectProvisionalLoad(
RenderFrameHostImpl* render_frame_host,
int32 page_id,
const GURL& source_url,
const GURL& target_url) {
GURL validated_source_url(source_url);
GURL validated_target_url(target_url);
RenderProcessHost* render_process_host = render_frame_host->GetProcess();
render_process_host->FilterURL(false, &validated_source_url);
render_process_host->FilterURL(false, &validated_target_url);
NavigationEntry* entry;
if (page_id == -1) {
entry = controller_->GetPendingEntry();
} else {
entry = controller_->GetEntryWithPageID(
render_frame_host->GetSiteInstance(), page_id);
}
if (!entry || entry->GetURL() != validated_source_url)
return;
if (delegate_) {
delegate_->DidRedirectProvisionalLoad(
render_frame_host, validated_target_url);
}
}
bool NavigatorImpl::NavigateToEntry(
RenderFrameHostImpl* render_frame_host,
const NavigationEntryImpl& entry,
NavigationController::ReloadType reload_type) {
TRACE_EVENT0("browser", "NavigatorImpl::NavigateToEntry");
if (entry.GetURL().spec().size() > GetMaxURLChars()) {
LOG(WARNING) << "Refusing to load URL as it exceeds " << GetMaxURLChars()
<< " characters.";
return false;
}
RenderFrameHostManager* manager =
render_frame_host->frame_tree_node()->render_manager();
RenderFrameHostImpl* dest_render_frame_host = manager->Navigate(entry);
if (!dest_render_frame_host)
return false;
CHECK_EQ(controller_->GetPendingEntry(), &entry);
int enabled_bindings =
dest_render_frame_host->render_view_host()->GetEnabledBindings();
bool is_allowed_in_web_ui_renderer =
WebUIControllerFactoryRegistry::GetInstance()->IsURLAcceptableForWebUI(
controller_->GetBrowserContext(), entry.GetURL());
if ((enabled_bindings & BINDINGS_POLICY_WEB_UI) &&
!is_allowed_in_web_ui_renderer) {
GetContentClient()->SetActiveURL(entry.GetURL());
CHECK(0);
}
if (delegate_)
delegate_->AboutToNavigateRenderFrame(dest_render_frame_host);
current_load_start_ = base::TimeTicks::Now();
FrameMsg_Navigate_Params navigate_params;
MakeNavigateParams(entry, *controller_, reload_type, &navigate_params);
dest_render_frame_host->Navigate(navigate_params);
CHECK_EQ(controller_->GetPendingEntry(), &entry);
if (entry.GetPageID() == -1) {
if (entry.GetURL().SchemeIs(kJavaScriptScheme))
return false;
}
if (delegate_) {
delegate_->DidStartNavigationToPendingEntry(render_frame_host,
entry.GetURL(),
reload_type);
}
return true;
}
bool NavigatorImpl::NavigateToPendingEntry(
RenderFrameHostImpl* render_frame_host,
NavigationController::ReloadType reload_type) {
return NavigateToEntry(
render_frame_host,
*NavigationEntryImpl::FromNavigationEntry(controller_->GetPendingEntry()),
reload_type);
}
base::TimeTicks NavigatorImpl::GetCurrentLoadStart() {
return current_load_start_;
}
void NavigatorImpl::DidNavigate(
RenderFrameHostImpl* render_frame_host,
const FrameHostMsg_DidCommitProvisionalLoad_Params& input_params) {
FrameHostMsg_DidCommitProvisionalLoad_Params params(input_params);
FrameTree* frame_tree = render_frame_host->frame_tree_node()->frame_tree();
bool use_site_per_process =
CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess);
if (use_site_per_process) {
NavigationEntryImpl* pending_entry =
NavigationEntryImpl::FromNavigationEntry(
controller_->GetPendingEntry());
if (!render_frame_host->frame_tree_node()->IsMainFrame() &&
pending_entry &&
pending_entry->frame_tree_node_id() ==
render_frame_host->frame_tree_node()->frame_tree_node_id()) {
params.transition = PAGE_TRANSITION_AUTO_SUBFRAME;
}
}
if (PageTransitionIsMainFrame(params.transition)) {
if (delegate_) {
if (delegate_->CanOverscrollContent())
controller_->TakeScreenshot();
delegate_->DidNavigateMainFramePreCommit(params);
}
if (!use_site_per_process)
frame_tree->root()->render_manager()->DidNavigateFrame(render_frame_host);
}
if (use_site_per_process) {
FrameTreeNode* frame = render_frame_host->frame_tree_node();
frame->render_manager()->DidNavigateFrame(render_frame_host);
}
SiteInstanceImpl* site_instance =
static_cast<SiteInstanceImpl*>(render_frame_host->GetSiteInstance());
if (!site_instance->HasSite() &&
ShouldAssignSiteForURL(params.url)) {
site_instance->SetSite(params.url);
}
if (PageTransitionIsMainFrame(params.transition) && delegate_)
delegate_->SetMainFrameMimeType(params.contents_mime_type);
LoadCommittedDetails details;
bool did_navigate = controller_->RendererDidNavigate(render_frame_host,
params, &details);
render_frame_host->frame_tree_node()->set_current_url(params.url);
if (details.type != NAVIGATION_TYPE_NAV_IGNORE && delegate_) {
bool is_main_frame = did_navigate ? details.is_main_frame : false;
PageTransition transition_type = params.transition;
if (did_navigate &&
(controller_->GetLastCommittedEntry()->GetTransitionType() &
PAGE_TRANSITION_FORWARD_BACK)) {
transition_type = PageTransitionFromInt(
params.transition | PAGE_TRANSITION_FORWARD_BACK);
}
delegate_->DidCommitProvisionalLoad(render_frame_host,
params.frame_unique_name,
is_main_frame,
params.url,
transition_type);
}
if (!did_navigate)
return;
if (delegate_) {
if (details.is_main_frame)
delegate_->DidNavigateMainFramePostCommit(details, params);
delegate_->DidNavigateAnyFramePostCommit(
render_frame_host, details, params);
}
}
bool NavigatorImpl::ShouldAssignSiteForURL(const GURL& url) {
if (url == GURL(kAboutBlankURL))
return false;
return GetContentClient()->browser()->ShouldAssignSiteForURL(url);
}
void NavigatorImpl::RequestOpenURL(
RenderFrameHostImpl* render_frame_host,
const GURL& url,
const Referrer& referrer,
WindowOpenDisposition disposition,
bool should_replace_current_entry,
bool user_gesture) {
SiteInstance* current_site_instance =
GetRenderManager(render_frame_host)->current_frame_host()->
GetSiteInstance();
if (render_frame_host->render_view_host()->IsSwappedOut() &&
!render_frame_host->GetSiteInstance()->IsRelatedSiteInstance(
current_site_instance)) {
return;
}
std::vector<GURL> redirect_chain;
RequestTransferURL(
render_frame_host, url, redirect_chain, referrer, PAGE_TRANSITION_LINK,
disposition, GlobalRequestID(),
should_replace_current_entry, user_gesture);
}
void NavigatorImpl::RequestTransferURL(
RenderFrameHostImpl* render_frame_host,
const GURL& url,
const std::vector<GURL>& redirect_chain,
const Referrer& referrer,
PageTransition page_transition,
WindowOpenDisposition disposition,
const GlobalRequestID& transferred_global_request_id,
bool should_replace_current_entry,
bool user_gesture) {
GURL dest_url(url);
SiteInstance* current_site_instance =
GetRenderManager(render_frame_host)->current_frame_host()->
GetSiteInstance();
if (!GetContentClient()->browser()->ShouldAllowOpenURL(
current_site_instance, url)) {
dest_url = GURL(kAboutBlankURL);
}
int64 frame_tree_node_id = -1;
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) {
frame_tree_node_id =
render_frame_host->frame_tree_node()->frame_tree_node_id();
}
OpenURLParams params(
dest_url, referrer, frame_tree_node_id, disposition, page_transition,
true );
if (redirect_chain.size() > 0)
params.redirect_chain = redirect_chain;
params.transferred_global_request_id = transferred_global_request_id;
params.should_replace_current_entry = should_replace_current_entry;
params.user_gesture = user_gesture;
if (GetRenderManager(render_frame_host)->web_ui()) {
if (PageTransitionCoreTypeIs(params.transition, PAGE_TRANSITION_LINK))
params.transition =
GetRenderManager(render_frame_host)->web_ui()->
GetLinkTransitionType();
params.referrer = Referrer();
params.is_renderer_initiated = false;
}
if (delegate_)
delegate_->RequestOpenURL(render_frame_host, params);
}
}