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