• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/history/history_tab_helper.h"
6 
7 #include <utility>
8 
9 #include "chrome/browser/history/history_service.h"
10 #include "chrome/browser/history/history_service_factory.h"
11 #if !defined(OS_ANDROID)
12 #include "chrome/browser/network_time/navigation_time_helper.h"
13 #endif
14 #include "chrome/browser/prerender/prerender_contents.h"
15 #include "chrome/browser/prerender/prerender_manager.h"
16 #include "chrome/browser/prerender/prerender_manager_factory.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/common/render_messages.h"
19 #include "content/public/browser/navigation_details.h"
20 #include "content/public/browser/navigation_entry.h"
21 #include "content/public/browser/web_contents.h"
22 #include "content/public/browser/web_contents_delegate.h"
23 #include "content/public/common/frame_navigate_params.h"
24 
25 #if !defined(OS_ANDROID)
26 #include "chrome/browser/ui/browser.h"
27 #include "chrome/browser/ui/browser_finder.h"
28 #endif
29 
30 using content::NavigationEntry;
31 using content::WebContents;
32 
33 DEFINE_WEB_CONTENTS_USER_DATA_KEY(HistoryTabHelper);
34 
HistoryTabHelper(WebContents * web_contents)35 HistoryTabHelper::HistoryTabHelper(WebContents* web_contents)
36     : content::WebContentsObserver(web_contents),
37       received_page_title_(false) {
38 }
39 
~HistoryTabHelper()40 HistoryTabHelper::~HistoryTabHelper() {
41 }
42 
UpdateHistoryForNavigation(const history::HistoryAddPageArgs & add_page_args)43 void HistoryTabHelper::UpdateHistoryForNavigation(
44     const history::HistoryAddPageArgs& add_page_args) {
45   HistoryService* hs = GetHistoryService();
46   if (hs)
47     GetHistoryService()->AddPage(add_page_args);
48 }
49 
UpdateHistoryPageTitle(const NavigationEntry & entry)50 void HistoryTabHelper::UpdateHistoryPageTitle(const NavigationEntry& entry) {
51   HistoryService* hs = GetHistoryService();
52   if (hs)
53     hs->SetPageTitle(entry.GetVirtualURL(),
54                      entry.GetTitleForDisplay(std::string()));
55 }
56 
57 history::HistoryAddPageArgs
CreateHistoryAddPageArgs(const GURL & virtual_url,base::Time timestamp,bool did_replace_entry,const content::FrameNavigateParams & params)58 HistoryTabHelper::CreateHistoryAddPageArgs(
59     const GURL& virtual_url,
60     base::Time timestamp,
61     bool did_replace_entry,
62     const content::FrameNavigateParams& params) {
63   history::HistoryAddPageArgs add_page_args(
64       params.url, timestamp, web_contents(), params.page_id,
65       params.referrer.url, params.redirects, params.transition,
66       history::SOURCE_BROWSED, did_replace_entry);
67   if (content::PageTransitionIsMainFrame(params.transition) &&
68       virtual_url != params.url) {
69     // Hack on the "virtual" URL so that it will appear in history. For some
70     // types of URLs, we will display a magic URL that is different from where
71     // the page is actually navigated. We want the user to see in history what
72     // they saw in the URL bar, so we add the virtual URL as a redirect.  This
73     // only applies to the main frame, as the virtual URL doesn't apply to
74     // sub-frames.
75     add_page_args.url = virtual_url;
76     if (!add_page_args.redirects.empty())
77       add_page_args.redirects.back() = virtual_url;
78   }
79   return add_page_args;
80 }
81 
DidNavigateMainFrame(const content::LoadCommittedDetails & details,const content::FrameNavigateParams & params)82 void HistoryTabHelper::DidNavigateMainFrame(
83     const content::LoadCommittedDetails& details,
84     const content::FrameNavigateParams& params) {
85   // Allow the new page to set the title again.
86   received_page_title_ = false;
87 }
88 
DidNavigateAnyFrame(const content::LoadCommittedDetails & details,const content::FrameNavigateParams & params)89 void HistoryTabHelper::DidNavigateAnyFrame(
90     const content::LoadCommittedDetails& details,
91     const content::FrameNavigateParams& params) {
92   // Update history. Note that this needs to happen after the entry is complete,
93   // which WillNavigate[Main,Sub]Frame will do before this function is called.
94   if (!params.should_update_history)
95     return;
96 
97 #if !defined(OS_ANDROID)
98   base::Time navigation_time =
99       NavigationTimeHelper::FromWebContents(web_contents())->GetNavigationTime(
100           details.entry);
101 #else
102   base::Time navigation_time = details.entry->GetTimestamp();
103 #endif
104 
105   // Most of the time, the displayURL matches the loaded URL, but for about:
106   // URLs, we use a data: URL as the real value.  We actually want to save the
107   // about: URL to the history db and keep the data: URL hidden. This is what
108   // the WebContents' URL getter does.
109   const history::HistoryAddPageArgs& add_page_args =
110       CreateHistoryAddPageArgs(
111           web_contents()->GetURL(), navigation_time,
112           details.did_replace_entry, params);
113 
114   prerender::PrerenderManager* prerender_manager =
115       prerender::PrerenderManagerFactory::GetForProfile(
116           Profile::FromBrowserContext(web_contents()->GetBrowserContext()));
117   if (prerender_manager) {
118     prerender::PrerenderContents* prerender_contents =
119         prerender_manager->GetPrerenderContents(web_contents());
120     if (prerender_contents) {
121       prerender_contents->DidNavigate(add_page_args);
122       return;
123     }
124   }
125 
126 #if !defined(OS_ANDROID)
127   // Don't update history if this web contents isn't associatd with a tab.
128   Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
129   if (!browser || browser->is_app())
130     return;
131 #endif
132 
133   UpdateHistoryForNavigation(add_page_args);
134 }
135 
TitleWasSet(NavigationEntry * entry,bool explicit_set)136 void HistoryTabHelper::TitleWasSet(NavigationEntry* entry, bool explicit_set) {
137   if (received_page_title_)
138     return;
139 
140   if (entry) {
141     UpdateHistoryPageTitle(*entry);
142     received_page_title_ = explicit_set;
143   }
144 }
145 
GetHistoryService()146 HistoryService* HistoryTabHelper::GetHistoryService() {
147   Profile* profile =
148       Profile::FromBrowserContext(web_contents()->GetBrowserContext());
149   if (profile->IsOffTheRecord())
150     return NULL;
151 
152   return HistoryServiceFactory::GetForProfile(profile,
153                                               Profile::IMPLICIT_ACCESS);
154 }
155 
WebContentsDestroyed(WebContents * tab)156 void HistoryTabHelper::WebContentsDestroyed(WebContents* tab) {
157   // TODO(sky): nuke this since no one is using visit_duration (and this is all
158   // wrong).
159 
160   // We update the history for this URL.
161   // The content returned from web_contents() has been destroyed by now.
162   // We need to use tab value directly.
163   Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
164   if (profile->IsOffTheRecord())
165     return;
166 
167   HistoryService* hs =
168       HistoryServiceFactory::GetForProfile(profile, Profile::IMPLICIT_ACCESS);
169   if (hs) {
170     NavigationEntry* entry = tab->GetController().GetLastCommittedEntry();
171     if (entry) {
172       hs->UpdateWithPageEndTime(tab, entry->GetPageID(), tab->GetURL(),
173                                 base::Time::Now());
174     }
175   }
176 }
177