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/bookmarks/bookmark_tab_helper.h" 14 #include "chrome/browser/ui/search/search_tab_helper.h" 15 #include "chrome/browser/ui/tab_contents/core_tab_helper.h" 16 #include "content/public/browser/navigation_entry.h" 17 #include "content/public/browser/notification_source.h" 18 #include "content/public/browser/notification_types.h" 19 #include "content/public/browser/site_instance.h" 20 #include "content/public/browser/web_contents_view.h" 21 #include "grit/generated_resources.h" 22 #include "ui/base/l10n/l10n_util.h" 23 24 #if !defined(OS_ANDROID) 25 #include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h" 26 #endif 27 28 namespace { 29 30 // This HTTP header and value are set on loads that originate from Instant. 31 const char kInstantHeader[] = "X-Purpose: Instant"; 32 33 } // namespace 34 35 InstantLoader::Delegate::~Delegate() { 36 } 37 38 InstantLoader::InstantLoader(Delegate* delegate) 39 : delegate_(delegate), stale_page_timer_(false, false) {} 40 41 InstantLoader::~InstantLoader() { 42 } 43 44 void InstantLoader::Init(const GURL& instant_url, 45 Profile* profile, 46 const base::Closure& on_stale_callback) { 47 content::WebContents::CreateParams create_params(profile); 48 create_params.site_instance = content::SiteInstance::CreateForURL( 49 profile, instant_url); 50 SetContents(scoped_ptr<content::WebContents>( 51 content::WebContents::Create(create_params))); 52 instant_url_ = instant_url; 53 on_stale_callback_ = on_stale_callback; 54 } 55 56 void InstantLoader::Load() { 57 DVLOG(1) << "LoadURL: " << instant_url_; 58 contents_->GetController().LoadURL( 59 instant_url_, content::Referrer(), 60 content::PAGE_TRANSITION_GENERATED, kInstantHeader); 61 62 // Explicitly set the new tab title and virtual URL. 63 // 64 // This ensures that the title is set even before we get a title from the 65 // page, preventing a potential flicker of the URL, and also ensures that 66 // (unless overridden by the page) the new tab title matches the browser UI 67 // locale. 68 content::NavigationEntry* entry = 69 contents_->GetController().GetVisibleEntry(); 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 // Bookmarks (Users can bookmark the Instant NTP. This ensures the bookmarked 93 // state is correctly set when the contents are swapped into a tab.) 94 BookmarkTabHelper::CreateForWebContents(contents()); 95 96 // A tab helper to catch prerender content swapping shenanigans. 97 CoreTabHelper::CreateForWebContents(contents()); 98 CoreTabHelper::FromWebContents(contents())->set_delegate(this); 99 100 SearchTabHelper::CreateForWebContents(contents()); 101 102 #if !defined(OS_ANDROID) 103 // Observers. 104 extensions::WebNavigationTabObserver::CreateForWebContents(contents()); 105 #endif // OS_ANDROID 106 107 // Favicons, required by the Task Manager. 108 FaviconTabHelper::CreateForWebContents(contents()); 109 110 // And some flat-out paranoia. 111 safe_browsing::SafeBrowsingTabObserver::CreateForWebContents(contents()); 112 113 // When the WebContents finishes loading it should be checked to ensure that 114 // it is in the instant process. 115 registrar_.Add(this, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, 116 content::Source<content::WebContents>(contents_.get())); 117 } 118 119 scoped_ptr<content::WebContents> InstantLoader::ReleaseContents() { 120 stale_page_timer_.Stop(); 121 contents_->SetDelegate(NULL); 122 123 // Undo tab helper work done in SetContents(). 124 CoreTabHelper::FromWebContents(contents())->set_delegate(NULL); 125 126 registrar_.Remove(this, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, 127 content::Source<content::WebContents>(contents_.get())); 128 return contents_.Pass(); 129 } 130 131 void InstantLoader::Observe(int type, 132 const content::NotificationSource& source, 133 const content::NotificationDetails& details) { 134 DCHECK_EQ(type, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME); 135 const content::WebContents* web_contents = 136 content::Source<content::WebContents>(source).ptr(); 137 DCHECK_EQ(contents_.get(), web_contents); 138 delegate_->LoadCompletedMainFrame(); 139 } 140 141 void InstantLoader::SwapTabContents(content::WebContents* old_contents, 142 content::WebContents* new_contents) { 143 DCHECK_EQ(old_contents, contents()); 144 // We release here without deleting since the caller has the responsibility 145 // for deleting the old WebContents. 146 ignore_result(ReleaseContents().release()); 147 SetContents(scoped_ptr<content::WebContents>(new_contents)); 148 delegate_->OnSwappedContents(); 149 } 150 151 bool InstantLoader::ShouldSuppressDialogs() { 152 // Messages shown during Instant cancel Instant, so we suppress them. 153 return true; 154 } 155 156 bool InstantLoader::ShouldFocusPageAfterCrash() { 157 return false; 158 } 159 160 void InstantLoader::CanDownload(content::RenderViewHost* /* render_view_host */, 161 int /* request_id */, 162 const std::string& /* request_method */, 163 const base::Callback<void(bool)>& callback) { 164 // Downloads are disabled. 165 callback.Run(false); 166 } 167 168 bool InstantLoader::OnGoToEntryOffset(int /* offset */) { 169 return false; 170 } 171 172 content::WebContents* InstantLoader::OpenURLFromTab( 173 content::WebContents* source, 174 const content::OpenURLParams& params) { 175 return delegate_->OpenURLFromTab(source, params); 176 } 177