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 29namespace { 30 31// This HTTP header and value are set on loads that originate from Instant. 32const char kInstantHeader[] = "X-Purpose: Instant"; 33 34} // namespace 35 36InstantLoader::Delegate::~Delegate() { 37} 38 39InstantLoader::InstantLoader(Delegate* delegate) 40 : delegate_(delegate), stale_page_timer_(false, false) {} 41 42InstantLoader::~InstantLoader() { 43} 44 45void 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 57void 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 85void 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 127scoped_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 153void 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 163void 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 173bool InstantLoader::ShouldSuppressDialogs() { 174 // Messages shown during Instant cancel Instant, so we suppress them. 175 return true; 176} 177 178bool InstantLoader::ShouldFocusPageAfterCrash() { 179 return false; 180} 181 182void 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 190bool InstantLoader::OnGoToEntryOffset(int /* offset */) { 191 return false; 192} 193 194content::WebContents* InstantLoader::OpenURLFromTab( 195 content::WebContents* source, 196 const content::OpenURLParams& params) { 197 return delegate_->OpenURLFromTab(source, params); 198} 199