OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/web_contents/web_contents_impl.h" | 5 #include "content/browser/web_contents/web_contents_impl.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
(...skipping 2045 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2056 RenderFrameHostImpl* render_frame_host, | 2056 RenderFrameHostImpl* render_frame_host, |
2057 const GURL& validated_target_url) { | 2057 const GURL& validated_target_url) { |
2058 // Notify observers about the provisional change in the main frame URL. | 2058 // Notify observers about the provisional change in the main frame URL. |
2059 FOR_EACH_OBSERVER( | 2059 FOR_EACH_OBSERVER( |
2060 WebContentsObserver, | 2060 WebContentsObserver, |
2061 observers_, | 2061 observers_, |
2062 ProvisionalChangeToMainFrameUrl(validated_target_url, | 2062 ProvisionalChangeToMainFrameUrl(validated_target_url, |
2063 render_frame_host)); | 2063 render_frame_host)); |
2064 } | 2064 } |
2065 | 2065 |
| 2066 void WebContentsImpl::DidCommitProvisionalLoad( |
| 2067 int64 frame_id, |
| 2068 const base::string16& frame_unique_name, |
| 2069 bool is_main_frame, |
| 2070 const GURL& url, |
| 2071 PageTransition transition_type, |
| 2072 RenderFrameHostImpl* render_frame_host) { |
| 2073 // Notify observers about the commit of the provisional load. |
| 2074 FOR_EACH_OBSERVER( |
| 2075 WebContentsObserver, |
| 2076 observers_, |
| 2077 DidCommitProvisionalLoadForFrame(frame_id, |
| 2078 frame_unique_name, |
| 2079 is_main_frame, |
| 2080 url, |
| 2081 transition_type, |
| 2082 render_frame_host->render_view_host())); |
| 2083 } |
| 2084 |
| 2085 void WebContentsImpl::DidNavigateMainFramePostCommit( |
| 2086 const LoadCommittedDetails& details, |
| 2087 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) { |
| 2088 if (details.is_navigation_to_different_page()) { |
| 2089 // Clear the status bubble. This is a workaround for a bug where WebKit |
| 2090 // doesn't let us know that the cursor left an element during a |
| 2091 // transition (this is also why the mouse cursor remains as a hand after |
| 2092 // clicking on a link); see bugs 1184641 and 980803. We don't want to |
| 2093 // clear the bubble when a user navigates to a named anchor in the same |
| 2094 // page. |
| 2095 UpdateTargetURL(details.entry->GetPageID(), GURL()); |
| 2096 } |
| 2097 |
| 2098 if (!details.is_in_page) { |
| 2099 // Once the main frame is navigated, we're no longer considered to have |
| 2100 // displayed insecure content. |
| 2101 displayed_insecure_content_ = false; |
| 2102 SSLManager::NotifySSLInternalStateChanged( |
| 2103 GetController().GetBrowserContext()); |
| 2104 } |
| 2105 |
| 2106 // Notify observers about navigation. |
| 2107 FOR_EACH_OBSERVER(WebContentsObserver, observers_, |
| 2108 DidNavigateMainFrame(details, params)); |
| 2109 |
| 2110 if (delegate_) { |
| 2111 delegate_->DidNavigateMainFramePostCommit(this); |
| 2112 view_->SetOverscrollControllerEnabled(delegate_->CanOverscrollContent()); |
| 2113 } |
| 2114 } |
| 2115 |
| 2116 void WebContentsImpl::DidNavigateAnyFramePostCommit( |
| 2117 RenderFrameHostImpl* render_frame_host, |
| 2118 const LoadCommittedDetails& details, |
| 2119 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) { |
| 2120 // If we navigate off the page, close all JavaScript dialogs. |
| 2121 if (dialog_manager_ && !details.is_in_page) |
| 2122 dialog_manager_->CancelActiveAndPendingDialogs(this); |
| 2123 |
| 2124 // Notify observers about navigation. |
| 2125 FOR_EACH_OBSERVER(WebContentsObserver, observers_, |
| 2126 DidNavigateAnyFrame(details, params)); |
| 2127 } |
| 2128 |
| 2129 void WebContentsImpl::SetMainFrameMimeType(const std::string& mime_type) { |
| 2130 contents_mime_type_ = mime_type; |
| 2131 } |
| 2132 |
| 2133 bool WebContentsImpl::CanOverscrollContent() { |
| 2134 if (delegate_) |
| 2135 return delegate_->CanOverscrollContent(); |
| 2136 |
| 2137 return false; |
| 2138 } |
| 2139 |
2066 void WebContentsImpl::OnDidLoadResourceFromMemoryCache( | 2140 void WebContentsImpl::OnDidLoadResourceFromMemoryCache( |
2067 const GURL& url, | 2141 const GURL& url, |
2068 const std::string& security_info, | 2142 const std::string& security_info, |
2069 const std::string& http_method, | 2143 const std::string& http_method, |
2070 const std::string& mime_type, | 2144 const std::string& mime_type, |
2071 ResourceType::Type resource_type) { | 2145 ResourceType::Type resource_type) { |
2072 base::StatsCounter cache("WebKit.CacheHit"); | 2146 base::StatsCounter cache("WebKit.CacheHit"); |
2073 cache.Increment(); | 2147 cache.Increment(); |
2074 | 2148 |
2075 // Send out a notification that we loaded a resource from our memory cache. | 2149 // Send out a notification that we loaded a resource from our memory cache. |
(...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2500 | 2574 |
2501 // TODO(avi): Remove. http://crbug.com/170921 | 2575 // TODO(avi): Remove. http://crbug.com/170921 |
2502 int type = is_loading ? NOTIFICATION_LOAD_START : NOTIFICATION_LOAD_STOP; | 2576 int type = is_loading ? NOTIFICATION_LOAD_START : NOTIFICATION_LOAD_STOP; |
2503 NotificationDetails det = NotificationService::NoDetails(); | 2577 NotificationDetails det = NotificationService::NoDetails(); |
2504 if (details) | 2578 if (details) |
2505 det = Details<LoadNotificationDetails>(details); | 2579 det = Details<LoadNotificationDetails>(details); |
2506 NotificationService::current()->Notify( | 2580 NotificationService::current()->Notify( |
2507 type, Source<NavigationController>(&controller_), det); | 2581 type, Source<NavigationController>(&controller_), det); |
2508 } | 2582 } |
2509 | 2583 |
2510 void WebContentsImpl::DidNavigateMainFramePostCommit( | |
2511 const LoadCommittedDetails& details, | |
2512 const ViewHostMsg_FrameNavigate_Params& params) { | |
2513 if (details.is_navigation_to_different_page()) { | |
2514 // Clear the status bubble. This is a workaround for a bug where WebKit | |
2515 // doesn't let us know that the cursor left an element during a | |
2516 // transition (this is also why the mouse cursor remains as a hand after | |
2517 // clicking on a link); see bugs 1184641 and 980803. We don't want to | |
2518 // clear the bubble when a user navigates to a named anchor in the same | |
2519 // page. | |
2520 UpdateTargetURL(details.entry->GetPageID(), GURL()); | |
2521 } | |
2522 | |
2523 if (!details.is_in_page) { | |
2524 // Once the main frame is navigated, we're no longer considered to have | |
2525 // displayed insecure content. | |
2526 displayed_insecure_content_ = false; | |
2527 SSLManager::NotifySSLInternalStateChanged( | |
2528 GetController().GetBrowserContext()); | |
2529 } | |
2530 | |
2531 // Notify observers about navigation. | |
2532 FOR_EACH_OBSERVER(WebContentsObserver, observers_, | |
2533 DidNavigateMainFrame(details, params)); | |
2534 } | |
2535 | |
2536 void WebContentsImpl::DidNavigateAnyFramePostCommit( | |
2537 RenderViewHost* render_view_host, | |
2538 const LoadCommittedDetails& details, | |
2539 const ViewHostMsg_FrameNavigate_Params& params) { | |
2540 // If we navigate off the page, close all JavaScript dialogs. | |
2541 if (dialog_manager_ && !details.is_in_page) | |
2542 dialog_manager_->CancelActiveAndPendingDialogs(this); | |
2543 | |
2544 // Notify observers about navigation. | |
2545 FOR_EACH_OBSERVER(WebContentsObserver, observers_, | |
2546 DidNavigateAnyFrame(details, params)); | |
2547 } | |
2548 | |
2549 bool WebContentsImpl::ShouldAssignSiteForURL(const GURL& url) { | |
2550 // about:blank should not "use up" a new SiteInstance. The SiteInstance can | |
2551 // still be used for a normal web site. | |
2552 if (url == GURL(kAboutBlankURL)) | |
2553 return false; | |
2554 | |
2555 // The embedder will then have the opportunity to determine if the URL | |
2556 // should "use up" the SiteInstance. | |
2557 return GetContentClient()->browser()->ShouldAssignSiteForURL(url); | |
2558 } | |
2559 | |
2560 void WebContentsImpl::UpdateMaxPageIDIfNecessary(RenderViewHost* rvh) { | 2584 void WebContentsImpl::UpdateMaxPageIDIfNecessary(RenderViewHost* rvh) { |
2561 // If we are creating a RVH for a restored controller, then we need to make | 2585 // If we are creating a RVH for a restored controller, then we need to make |
2562 // sure the RenderView starts with a next_page_id_ larger than the number | 2586 // sure the RenderView starts with a next_page_id_ larger than the number |
2563 // of restored entries. This must be called before the RenderView starts | 2587 // of restored entries. This must be called before the RenderView starts |
2564 // navigating (to avoid a race between the browser updating max_page_id and | 2588 // navigating (to avoid a race between the browser updating max_page_id and |
2565 // the renderer updating next_page_id_). Because of this, we only call this | 2589 // the renderer updating next_page_id_). Because of this, we only call this |
2566 // from CreateRenderView and allow that to notify the RenderView for us. | 2590 // from CreateRenderView and allow that to notify the RenderView for us. |
2567 int max_restored_page_id = controller_.GetMaxRestoredPageID(); | 2591 int max_restored_page_id = controller_.GetMaxRestoredPageID(); |
2568 if (max_restored_page_id > | 2592 if (max_restored_page_id > |
2569 GetMaxPageIDForSiteInstance(rvh->GetSiteInstance())) | 2593 GetMaxPageIDForSiteInstance(rvh->GetSiteInstance())) |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2807 observers_, | 2831 observers_, |
2808 RenderProcessGone(GetCrashedStatus())); | 2832 RenderProcessGone(GetCrashedStatus())); |
2809 } | 2833 } |
2810 | 2834 |
2811 void WebContentsImpl::RenderViewDeleted(RenderViewHost* rvh) { | 2835 void WebContentsImpl::RenderViewDeleted(RenderViewHost* rvh) { |
2812 ClearPowerSaveBlockers(rvh); | 2836 ClearPowerSaveBlockers(rvh); |
2813 GetRenderManager()->RenderViewDeleted(rvh); | 2837 GetRenderManager()->RenderViewDeleted(rvh); |
2814 FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewDeleted(rvh)); | 2838 FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewDeleted(rvh)); |
2815 } | 2839 } |
2816 | 2840 |
2817 void WebContentsImpl::DidNavigate( | |
2818 RenderViewHost* rvh, | |
2819 const ViewHostMsg_FrameNavigate_Params& orig_params) { | |
2820 ViewHostMsg_FrameNavigate_Params params(orig_params); | |
2821 bool use_site_per_process = | |
2822 CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess); | |
2823 if (frame_tree_.IsFirstNavigationAfterSwap()) { | |
2824 // First navigation should be a main frame navigation. | |
2825 // TODO(creis): This DCHECK is currently disabled for --site-per-process | |
2826 // because cross-process subframe navigations still have a main frame | |
2827 // PageTransition. | |
2828 if (!use_site_per_process) | |
2829 DCHECK(PageTransitionIsMainFrame(params.transition)); | |
2830 frame_tree_.OnFirstNavigationAfterSwap(params.frame_id); | |
2831 } | |
2832 | |
2833 // When using --site-per-process, look up the FrameTreeNode ID that the | |
2834 // renderer-specific frame ID corresponds to. | |
2835 int64 frame_tree_node_id = frame_tree_.root()->frame_tree_node_id(); | |
2836 if (use_site_per_process) { | |
2837 FrameTreeNode* source_node = frame_tree_.FindByFrameID(params.frame_id); | |
2838 if (source_node) | |
2839 frame_tree_node_id = source_node->frame_tree_node_id(); | |
2840 | |
2841 // TODO(creis): In the short term, cross-process subframe navigations are | |
2842 // happening in the pending RenderViewHost's top-level frame. (We need to | |
2843 // both mirror the frame tree and get the navigation to occur in the correct | |
2844 // subframe to fix this.) Until then, we should check whether we have a | |
2845 // pending NavigationEntry with a frame ID and if so, treat the | |
2846 // cross-process "main frame" navigation as a subframe navigation. This | |
2847 // limits us to a single cross-process subframe per RVH, and it affects | |
2848 // NavigateToEntry, NavigatorImpl::DidStartProvisionalLoad, and | |
2849 // OnDidFinishLoad. | |
2850 NavigationEntryImpl* pending_entry = | |
2851 NavigationEntryImpl::FromNavigationEntry(controller_.GetPendingEntry()); | |
2852 int root_ftn_id = frame_tree_.root()->frame_tree_node_id(); | |
2853 if (pending_entry && | |
2854 pending_entry->frame_tree_node_id() != -1 && | |
2855 pending_entry->frame_tree_node_id() != root_ftn_id) { | |
2856 params.transition = PAGE_TRANSITION_AUTO_SUBFRAME; | |
2857 frame_tree_node_id = pending_entry->frame_tree_node_id(); | |
2858 } | |
2859 } | |
2860 | |
2861 if (PageTransitionIsMainFrame(params.transition)) { | |
2862 // When overscroll navigation gesture is enabled, a screenshot of the page | |
2863 // in its current state is taken so that it can be used during the | |
2864 // nav-gesture. It is necessary to take the screenshot here, before calling | |
2865 // RenderFrameHostManager::DidNavigateMainFrame, because that can change | |
2866 // WebContents::GetRenderViewHost to return the new host, instead of the one | |
2867 // that may have just been swapped out. | |
2868 if (delegate_ && delegate_->CanOverscrollContent()) | |
2869 controller_.TakeScreenshot(); | |
2870 | |
2871 if (!use_site_per_process) | |
2872 GetRenderManager()->DidNavigateMainFrame(rvh); | |
2873 } | |
2874 | |
2875 // When using --site-per-process, we notify the RFHM for all navigations, | |
2876 // not just main frame navigations. | |
2877 if (use_site_per_process) { | |
2878 FrameTreeNode* frame = frame_tree_.FindByID(frame_tree_node_id); | |
2879 // TODO(creis): Rename to DidNavigateFrame. | |
2880 frame->render_manager()->DidNavigateMainFrame(rvh); | |
2881 } | |
2882 | |
2883 // Update the site of the SiteInstance if it doesn't have one yet, unless | |
2884 // assigning a site is not necessary for this URL. In that case, the | |
2885 // SiteInstance can still be considered unused until a navigation to a real | |
2886 // page. | |
2887 if (!static_cast<SiteInstanceImpl*>(GetSiteInstance())->HasSite() && | |
2888 ShouldAssignSiteForURL(params.url)) { | |
2889 static_cast<SiteInstanceImpl*>(GetSiteInstance())->SetSite(params.url); | |
2890 } | |
2891 | |
2892 // Need to update MIME type here because it's referred to in | |
2893 // UpdateNavigationCommands() called by RendererDidNavigate() to | |
2894 // determine whether or not to enable the encoding menu. | |
2895 // It's updated only for the main frame. For a subframe, | |
2896 // RenderView::UpdateURL does not set params.contents_mime_type. | |
2897 // (see http://code.google.com/p/chromium/issues/detail?id=2929 ) | |
2898 // TODO(jungshik): Add a test for the encoding menu to avoid | |
2899 // regressing it again. | |
2900 if (PageTransitionIsMainFrame(params.transition)) | |
2901 contents_mime_type_ = params.contents_mime_type; | |
2902 | |
2903 LoadCommittedDetails details; | |
2904 bool did_navigate = controller_.RendererDidNavigate(rvh, params, &details); | |
2905 | |
2906 // For now, keep track of each frame's URL in its FrameTreeNode. This lets | |
2907 // us estimate our process count for implementing OOP iframes. | |
2908 // TODO(creis): Remove this when we track which pages commit in each frame. | |
2909 frame_tree_.SetFrameUrl(params.frame_id, params.url); | |
2910 | |
2911 // Send notification about committed provisional loads. This notification is | |
2912 // different from the NAV_ENTRY_COMMITTED notification which doesn't include | |
2913 // the actual URL navigated to and isn't sent for AUTO_SUBFRAME navigations. | |
2914 if (details.type != NAVIGATION_TYPE_NAV_IGNORE) { | |
2915 // For AUTO_SUBFRAME navigations, an event for the main frame is generated | |
2916 // that is not recorded in the navigation history. For the purpose of | |
2917 // tracking navigation events, we treat this event as a sub frame navigation | |
2918 // event. | |
2919 bool is_main_frame = did_navigate ? details.is_main_frame : false; | |
2920 PageTransition transition_type = params.transition; | |
2921 // Whether or not a page transition was triggered by going backward or | |
2922 // forward in the history is only stored in the navigation controller's | |
2923 // entry list. | |
2924 if (did_navigate && | |
2925 (controller_.GetLastCommittedEntry()->GetTransitionType() & | |
2926 PAGE_TRANSITION_FORWARD_BACK)) { | |
2927 transition_type = PageTransitionFromInt( | |
2928 params.transition | PAGE_TRANSITION_FORWARD_BACK); | |
2929 } | |
2930 // Notify observers about the commit of the provisional load. | |
2931 FOR_EACH_OBSERVER(WebContentsObserver, observers_, | |
2932 DidCommitProvisionalLoadForFrame( | |
2933 params.frame_id, | |
2934 params.frame_unique_name, | |
2935 is_main_frame, | |
2936 params.url, | |
2937 transition_type, | |
2938 rvh)); | |
2939 } | |
2940 | |
2941 if (!did_navigate) | |
2942 return; // No navigation happened. | |
2943 | |
2944 // DO NOT ADD MORE STUFF TO THIS FUNCTION! Your component should either listen | |
2945 // for the appropriate notification (best) or you can add it to | |
2946 // DidNavigateMainFramePostCommit / DidNavigateAnyFramePostCommit (only if | |
2947 // necessary, please). | |
2948 | |
2949 // Run post-commit tasks. | |
2950 if (details.is_main_frame) { | |
2951 DidNavigateMainFramePostCommit(details, params); | |
2952 if (delegate_) { | |
2953 delegate_->DidNavigateMainFramePostCommit(this); | |
2954 view_->SetOverscrollControllerEnabled(delegate_->CanOverscrollContent()); | |
2955 } | |
2956 } | |
2957 DidNavigateAnyFramePostCommit(rvh, details, params); | |
2958 } | |
2959 | |
2960 void WebContentsImpl::UpdateState(RenderViewHost* rvh, | 2841 void WebContentsImpl::UpdateState(RenderViewHost* rvh, |
2961 int32 page_id, | 2842 int32 page_id, |
2962 const PageState& page_state) { | 2843 const PageState& page_state) { |
2963 // Ensure that this state update comes from either the active RVH or one of | 2844 // Ensure that this state update comes from either the active RVH or one of |
2964 // the swapped out RVHs. We don't expect to hear from any other RVHs. | 2845 // the swapped out RVHs. We don't expect to hear from any other RVHs. |
2965 // TODO(nasko): This should go through RenderFrameHost. | 2846 // TODO(nasko): This should go through RenderFrameHost. |
2966 // TODO(creis): We can't update state for cross-process subframes until we | 2847 // TODO(creis): We can't update state for cross-process subframes until we |
2967 // have FrameNavigationEntries. Once we do, this should be a DCHECK. | 2848 // have FrameNavigationEntries. Once we do, this should be a DCHECK. |
2968 if (rvh != GetRenderViewHost() && | 2849 if (rvh != GetRenderViewHost() && |
2969 !GetRenderManager()->IsRVHOnSwappedOutList( | 2850 !GetRenderManager()->IsRVHOnSwappedOutList( |
(...skipping 769 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3739 } | 3620 } |
3740 | 3621 |
3741 void WebContentsImpl::OnFrameRemoved( | 3622 void WebContentsImpl::OnFrameRemoved( |
3742 RenderViewHostImpl* render_view_host, | 3623 RenderViewHostImpl* render_view_host, |
3743 int64 frame_id) { | 3624 int64 frame_id) { |
3744 FOR_EACH_OBSERVER(WebContentsObserver, observers_, | 3625 FOR_EACH_OBSERVER(WebContentsObserver, observers_, |
3745 FrameDetached(render_view_host, frame_id)); | 3626 FrameDetached(render_view_host, frame_id)); |
3746 } | 3627 } |
3747 | 3628 |
3748 } // namespace content | 3629 } // namespace content |
OLD | NEW |