Home | History | Annotate | Download | only in history
      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 
     35 HistoryTabHelper::HistoryTabHelper(WebContents* web_contents)
     36     : content::WebContentsObserver(web_contents),
     37       received_page_title_(false) {
     38 }
     39 
     40 HistoryTabHelper::~HistoryTabHelper() {
     41 }
     42 
     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 
     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
     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 
     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 
     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 
    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 
    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 
    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