Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / content / browser / frame_host / navigator_impl.cc
index 0103285..f01dc53 100644 (file)
 #include "content/public/browser/content_browser_client.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/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"
@@ -30,16 +32,16 @@ namespace content {
 
 namespace {
 
-ViewMsg_Navigate_Type::Value GetNavigationType(
+FrameMsg_Navigate_Type::Value GetNavigationType(
     BrowserContext* browser_context, const NavigationEntryImpl& entry,
     NavigationController::ReloadType reload_type) {
   switch (reload_type) {
     case NavigationControllerImpl::RELOAD:
-      return ViewMsg_Navigate_Type::RELOAD;
+      return FrameMsg_Navigate_Type::RELOAD;
     case NavigationControllerImpl::RELOAD_IGNORING_CACHE:
-      return ViewMsg_Navigate_Type::RELOAD_IGNORING_CACHE;
+      return FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE;
     case NavigationControllerImpl::RELOAD_ORIGINAL_REQUEST_URL:
-      return ViewMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL;
+      return FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL;
     case NavigationControllerImpl::NO_RELOAD:
       break;  // Fall through to rest of function.
   }
@@ -49,17 +51,17 @@ ViewMsg_Navigate_Type::Value GetNavigationType(
   if (entry.restore_type() ==
       NavigationEntryImpl::RESTORE_LAST_SESSION_EXITED_CLEANLY) {
     if (entry.GetHasPostData())
-      return ViewMsg_Navigate_Type::RESTORE_WITH_POST;
-    return ViewMsg_Navigate_Type::RESTORE;
+      return FrameMsg_Navigate_Type::RESTORE_WITH_POST;
+    return FrameMsg_Navigate_Type::RESTORE;
   }
 
-  return ViewMsg_Navigate_Type::NORMAL;
+  return FrameMsg_Navigate_Type::NORMAL;
 }
 
 void MakeNavigateParams(const NavigationEntryImpl& entry,
                         const NavigationControllerImpl& controller,
                         NavigationController::ReloadType reload_type,
-                        ViewMsg_Navigate_Params* params) {
+                        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();
@@ -243,6 +245,18 @@ void NavigatorImpl::DidFailProvisionalLoadWithError(
   delegate_->DidFailProvisionalLoadWithError(render_frame_host, params);
 }
 
+void NavigatorImpl::DidFailLoadWithError(
+    RenderFrameHostImpl* render_frame_host,
+    int64 frame_id,
+    const GURL& url,
+    bool is_main_frame,
+    int error_code,
+    const base::string16& error_description) {
+  delegate_->DidFailLoadWithError(
+      render_frame_host, frame_id, url, is_main_frame, error_code,
+      error_description);
+}
+
 void NavigatorImpl::DidRedirectProvisionalLoad(
     RenderFrameHostImpl* render_frame_host,
     int32 page_id,
@@ -320,13 +334,13 @@ bool NavigatorImpl::NavigateToEntry(
   // Used for page load time metrics.
   current_load_start_ = base::TimeTicks::Now();
 
-  // Navigate in the desired RenderViewHost.
+  // Navigate in the desired RenderFrameHost.
   // TODO(creis): As a temporary hack, we currently do cross-process subframe
   // navigations in a top-level frame of the new process.  Thus, we don't yet
-  // need to store the correct frame ID in ViewMsg_Navigate_Params.
-  ViewMsg_Navigate_Params navigate_params;
+  // need to store the correct frame ID in FrameMsg_Navigate_Params.
+  FrameMsg_Navigate_Params navigate_params;
   MakeNavigateParams(entry, *controller_, reload_type, &navigate_params);
-  dest_render_frame_host->render_view_host()->Navigate(navigate_params);
+  dest_render_frame_host->Navigate(navigate_params);
 
   if (entry.GetPageID() == -1) {
     // HACK!!  This code suppresses javascript: URLs from being added to
@@ -361,4 +375,162 @@ 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();
+  RenderViewHostImpl* rvh = render_frame_host->render_view_host();
+  bool use_site_per_process =
+      CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess);
+  if (frame_tree->IsFirstNavigationAfterSwap()) {
+    // First navigation should be a main frame navigation.
+    // TODO(creis): This DCHECK is currently disabled for --site-per-process
+    // because cross-process subframe navigations still have a main frame
+    // PageTransition.
+    if (!use_site_per_process)
+      DCHECK(PageTransitionIsMainFrame(params.transition));
+    frame_tree->OnFirstNavigationAfterSwap(params.frame_id);
+  }
+
+  // When using --site-per-process, look up the FrameTreeNode ID that the
+  // renderer-specific frame ID corresponds to.
+  int64 frame_tree_node_id = frame_tree->root()->frame_tree_node_id();
+  if (use_site_per_process) {
+    frame_tree_node_id =
+        render_frame_host->frame_tree_node()->frame_tree_node_id();
+
+    // TODO(creis): In the short term, cross-process subframe navigations are
+    // happening in the pending RenderViewHost's top-level frame.  (We need to
+    // both mirror the frame tree and get the navigation to occur in the correct
+    // subframe to fix this.)  Until then, we should check whether we have a
+    // pending NavigationEntry with a frame ID and if so, treat the
+    // cross-process "main frame" navigation as a subframe navigation.  This
+    // limits us to a single cross-process subframe per RVH, and it affects
+    // NavigateToEntry, NavigatorImpl::DidStartProvisionalLoad, and
+    // OnDidFinishLoad.
+    NavigationEntryImpl* pending_entry =
+        NavigationEntryImpl::FromNavigationEntry(
+            controller_->GetPendingEntry());
+    int root_ftn_id = frame_tree->root()->frame_tree_node_id();
+    if (pending_entry &&
+        pending_entry->frame_tree_node_id() != -1 &&
+        pending_entry->frame_tree_node_id() != root_ftn_id) {
+      params.transition = PAGE_TRANSITION_AUTO_SUBFRAME;
+      frame_tree_node_id = pending_entry->frame_tree_node_id();
+    }
+  }
+
+  if (PageTransitionIsMainFrame(params.transition)) {
+    // When overscroll navigation gesture is enabled, a screenshot of the page
+    // in its current state is taken so that it can be used during the
+    // nav-gesture. It is necessary to take the screenshot here, before calling
+    // RenderFrameHostManager::DidNavigateMainFrame, because that can change
+    // WebContents::GetRenderViewHost to return the new host, instead of the one
+    // that may have just been swapped out.
+    if (delegate_ && delegate_->CanOverscrollContent())
+      controller_->TakeScreenshot();
+
+    if (!use_site_per_process)
+      frame_tree->root()->render_manager()->DidNavigateMainFrame(rvh);
+  }
+
+  // When using --site-per-process, we notify the RFHM for all navigations,
+  // not just main frame navigations.
+  if (use_site_per_process) {
+    FrameTreeNode* frame = frame_tree->FindByID(frame_tree_node_id);
+    // TODO(creis): Rename to DidNavigateFrame.
+    frame->render_manager()->DidNavigateMainFrame(rvh);
+  }
+
+  // Update the site of the SiteInstance if it doesn't have one yet, unless
+  // assigning a site is not necessary for this URL.  In that case, the
+  // SiteInstance can still be considered unused until a navigation to a real
+  // page.
+  SiteInstanceImpl* site_instance =
+      static_cast<SiteInstanceImpl*>(render_frame_host->GetSiteInstance());
+  if (!site_instance->HasSite() &&
+      ShouldAssignSiteForURL(params.url)) {
+    site_instance->SetSite(params.url);
+  }
+
+  // Need to update MIME type here because it's referred to in
+  // UpdateNavigationCommands() called by RendererDidNavigate() to
+  // determine whether or not to enable the encoding menu.
+  // It's updated only for the main frame. For a subframe,
+  // RenderView::UpdateURL does not set params.contents_mime_type.
+  // (see http://code.google.com/p/chromium/issues/detail?id=2929 )
+  // TODO(jungshik): Add a test for the encoding menu to avoid
+  // regressing it again.
+  // TODO(nasko): Verify the correctness of the above comment, since some of the
+  // code doesn't exist anymore. Also, move this code in the
+  // PageTransitionIsMainFrame code block above.
+  if (PageTransitionIsMainFrame(params.transition) && delegate_)
+    delegate_->SetMainFrameMimeType(params.contents_mime_type);
+
+  LoadCommittedDetails details;
+  bool did_navigate = controller_->RendererDidNavigate(rvh, params, &details);
+
+  // For now, keep track of each frame's URL in its FrameTreeNode.  This lets
+  // us estimate our process count for implementing OOP iframes.
+  // TODO(creis): Remove this when we track which pages commit in each frame.
+  frame_tree->SetFrameUrl(params.frame_id, params.url);
+
+  // Send notification about committed provisional loads. This notification is
+  // different from the NAV_ENTRY_COMMITTED notification which doesn't include
+  // the actual URL navigated to and isn't sent for AUTO_SUBFRAME navigations.
+  if (details.type != NAVIGATION_TYPE_NAV_IGNORE && delegate_) {
+    // For AUTO_SUBFRAME navigations, an event for the main frame is generated
+    // that is not recorded in the navigation history. For the purpose of
+    // tracking navigation events, we treat this event as a sub frame navigation
+    // event.
+    bool is_main_frame = did_navigate ? details.is_main_frame : false;
+    PageTransition transition_type = params.transition;
+    // Whether or not a page transition was triggered by going backward or
+    // forward in the history is only stored in the navigation controller's
+    // entry list.
+    if (did_navigate &&
+        (controller_->GetLastCommittedEntry()->GetTransitionType() &
+            PAGE_TRANSITION_FORWARD_BACK)) {
+      transition_type = PageTransitionFromInt(
+          params.transition | PAGE_TRANSITION_FORWARD_BACK);
+    }
+
+    delegate_->DidCommitProvisionalLoad(params.frame_id,
+                                        params.frame_unique_name,
+                                        is_main_frame,
+                                        params.url,
+                                        transition_type,
+                                        render_frame_host);
+  }
+
+  if (!did_navigate)
+    return;  // No navigation happened.
+
+  // DO NOT ADD MORE STUFF TO THIS FUNCTION! Your component should either listen
+  // for the appropriate notification (best) or you can add it to
+  // DidNavigateMainFramePostCommit / DidNavigateAnyFramePostCommit (only if
+  // necessary, please).
+
+  // Run post-commit tasks.
+  if (delegate_) {
+    if (details.is_main_frame)
+      delegate_->DidNavigateMainFramePostCommit(details, params);
+
+    delegate_->DidNavigateAnyFramePostCommit(
+        render_frame_host, details, params);
+  }
+}
+
+bool NavigatorImpl::ShouldAssignSiteForURL(const GURL& url) {
+  // about:blank should not "use up" a new SiteInstance.  The SiteInstance can
+  // still be used for a normal web site.
+  if (url == GURL(kAboutBlankURL))
+    return false;
+
+  // The embedder will then have the opportunity to determine if the URL
+  // should "use up" the SiteInstance.
+  return GetContentClient()->browser()->ShouldAssignSiteForURL(url);
+}
+
 }  // namespace content