Home | History | Annotate | Download | only in search
      1 // Copyright 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/ui/search/instant_loader.h"
      6 
      7 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
      8 #include "chrome/browser/extensions/api/web_navigation/web_navigation_api.h"
      9 #include "chrome/browser/favicon/favicon_tab_helper.h"
     10 #include "chrome/browser/safe_browsing/safe_browsing_tab_observer.h"
     11 #include "chrome/browser/search/search.h"
     12 #include "chrome/browser/tab_contents/tab_util.h"
     13 #include "chrome/browser/ui/blocked_content/blocked_content_tab_helper.h"
     14 #include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h"
     15 #include "chrome/browser/ui/search/search_tab_helper.h"
     16 #include "chrome/browser/ui/tab_contents/core_tab_helper.h"
     17 #include "content/public/browser/navigation_entry.h"
     18 #include "content/public/browser/notification_source.h"
     19 #include "content/public/browser/notification_types.h"
     20 #include "content/public/browser/site_instance.h"
     21 #include "content/public/browser/web_contents_view.h"
     22 #include "grit/generated_resources.h"
     23 #include "ui/base/l10n/l10n_util.h"
     24 
     25 #if !defined(OS_ANDROID)
     26 #include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h"
     27 #endif
     28 
     29 namespace {
     30 
     31 // This HTTP header and value are set on loads that originate from Instant.
     32 const char kInstantHeader[] = "X-Purpose: Instant";
     33 
     34 }  // namespace
     35 
     36 InstantLoader::Delegate::~Delegate() {
     37 }
     38 
     39 InstantLoader::InstantLoader(Delegate* delegate)
     40     : delegate_(delegate), stale_page_timer_(false, false) {}
     41 
     42 InstantLoader::~InstantLoader() {
     43 }
     44 
     45 void InstantLoader::Init(const GURL& instant_url,
     46                          Profile* profile,
     47                          const base::Closure& on_stale_callback) {
     48   content::WebContents::CreateParams create_params(profile);
     49   create_params.site_instance = content::SiteInstance::CreateForURL(
     50       profile, instant_url);
     51   SetContents(scoped_ptr<content::WebContents>(
     52       content::WebContents::Create(create_params)));
     53   instant_url_ = instant_url;
     54   on_stale_callback_ = on_stale_callback;
     55 }
     56 
     57 void InstantLoader::Load() {
     58   DVLOG(1) << "LoadURL: " << instant_url_;
     59   contents_->GetController().LoadURL(
     60       instant_url_, content::Referrer(),
     61       content::PAGE_TRANSITION_GENERATED, kInstantHeader);
     62 
     63   // Explicitly set the new tab title and virtual URL.
     64   //
     65   // This ensures that the title is set even before we get a title from the
     66   // page, preventing a potential flicker of the URL, and also ensures that
     67   // (unless overridden by the page) the new tab title matches the browser UI
     68   // locale.
     69   content::NavigationEntry* entry = contents_->GetController().GetActiveEntry();
     70   if (entry)
     71     entry->SetTitle(l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE));
     72 
     73   contents_->WasHidden();
     74 
     75   int staleness_timeout_ms = chrome::GetInstantLoaderStalenessTimeoutSec() *
     76       1000;
     77   if (staleness_timeout_ms > 0) {
     78     stale_page_timer_.Start(
     79         FROM_HERE,
     80         base::TimeDelta::FromMilliseconds(staleness_timeout_ms),
     81         on_stale_callback_);
     82   }
     83 }
     84 
     85 void InstantLoader::SetContents(scoped_ptr<content::WebContents> new_contents) {
     86   contents_.reset(new_contents.release());
     87   contents_->SetDelegate(this);
     88 
     89   // Set up various tab helpers. The rest will get attached when (if) the
     90   // contents is added to the tab strip.
     91 
     92   // Tab helpers to control popups.
     93   BlockedContentTabHelper::CreateForWebContents(contents());
     94   BlockedContentTabHelper::FromWebContents(contents())->
     95       SetAllContentsBlocked(true);
     96   TabSpecificContentSettings::CreateForWebContents(contents());
     97   TabSpecificContentSettings::FromWebContents(contents())->
     98       SetPopupsBlocked(true);
     99 
    100   // Bookmarks (Users can bookmark the Instant NTP. This ensures the bookmarked
    101   // state is correctly set when the contents are swapped into a tab.)
    102   BookmarkTabHelper::CreateForWebContents(contents());
    103 
    104   // A tab helper to catch prerender content swapping shenanigans.
    105   CoreTabHelper::CreateForWebContents(contents());
    106   CoreTabHelper::FromWebContents(contents())->set_delegate(this);
    107 
    108   SearchTabHelper::CreateForWebContents(contents());
    109 
    110 #if !defined(OS_ANDROID)
    111   // Observers.
    112   extensions::WebNavigationTabObserver::CreateForWebContents(contents());
    113 #endif  // OS_ANDROID
    114 
    115   // Favicons, required by the Task Manager.
    116   FaviconTabHelper::CreateForWebContents(contents());
    117 
    118   // And some flat-out paranoia.
    119   safe_browsing::SafeBrowsingTabObserver::CreateForWebContents(contents());
    120 
    121   // When the WebContents finishes loading it should be checked to ensure that
    122   // it is in the instant process.
    123   registrar_.Add(this, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
    124                  content::Source<content::WebContents>(contents_.get()));
    125 }
    126 
    127 scoped_ptr<content::WebContents> InstantLoader::ReleaseContents() {
    128   stale_page_timer_.Stop();
    129   contents_->SetDelegate(NULL);
    130 
    131   // Undo tab helper work done in SetContents().
    132 
    133   BlockedContentTabHelper::FromWebContents(contents())->
    134       SetAllContentsBlocked(false);
    135   TabSpecificContentSettings::FromWebContents(contents())->
    136       SetPopupsBlocked(false);
    137 #if !defined(OS_ANDROID)
    138   PopupBlockerTabHelper* popup_helper =
    139       PopupBlockerTabHelper::FromWebContents(contents());
    140   if (popup_helper) {
    141     TabSpecificContentSettings::FromWebContents(contents())
    142         ->SetPopupsBlocked(!!popup_helper->GetBlockedPopupsCount());
    143   }
    144 #endif
    145 
    146   CoreTabHelper::FromWebContents(contents())->set_delegate(NULL);
    147 
    148   registrar_.Remove(this, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
    149                     content::Source<content::WebContents>(contents_.get()));
    150   return contents_.Pass();
    151 }
    152 
    153 void InstantLoader::Observe(int type,
    154                             const content::NotificationSource& source,
    155                             const content::NotificationDetails& details) {
    156   DCHECK_EQ(type, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME);
    157   const content::WebContents* web_contents =
    158       content::Source<content::WebContents>(source).ptr();
    159   DCHECK_EQ(contents_.get(), web_contents);
    160   delegate_->LoadCompletedMainFrame();
    161 }
    162 
    163 void InstantLoader::SwapTabContents(content::WebContents* old_contents,
    164                                     content::WebContents* new_contents) {
    165   DCHECK_EQ(old_contents, contents());
    166   // We release here without deleting since the caller has the responsibility
    167   // for deleting the old WebContents.
    168   ignore_result(ReleaseContents().release());
    169   SetContents(scoped_ptr<content::WebContents>(new_contents));
    170   delegate_->OnSwappedContents();
    171 }
    172 
    173 bool InstantLoader::ShouldSuppressDialogs() {
    174   // Messages shown during Instant cancel Instant, so we suppress them.
    175   return true;
    176 }
    177 
    178 bool InstantLoader::ShouldFocusPageAfterCrash() {
    179   return false;
    180 }
    181 
    182 void InstantLoader::CanDownload(content::RenderViewHost* /* render_view_host */,
    183                                 int /* request_id */,
    184                                 const std::string& /* request_method */,
    185                                 const base::Callback<void(bool)>& callback) {
    186   // Downloads are disabled.
    187   callback.Run(false);
    188 }
    189 
    190 bool InstantLoader::OnGoToEntryOffset(int /* offset */) {
    191   return false;
    192 }
    193 
    194 content::WebContents* InstantLoader::OpenURLFromTab(
    195     content::WebContents* source,
    196     const content::OpenURLParams& params) {
    197   return delegate_->OpenURLFromTab(source, params);
    198 }
    199