| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/instant/instant_loader.h" | 5 #include "chrome/browser/instant/instant_loader.h" |
| 6 | 6 |
| 7 #include "chrome/browser/content_settings/tab_specific_content_settings.h" | 7 #include "base/stringprintf.h" |
| 8 #include "chrome/browser/extensions/api/web_navigation/web_navigation_api.h" | 8 #include "chrome/browser/instant/instant_service.h" |
| 9 #include "chrome/browser/favicon/favicon_tab_helper.h" | 9 #include "chrome/browser/profiles/profile.h" |
| 10 #include "chrome/browser/history/history_tab_helper.h" | 10 #include "chrome/browser/ui/search/search.h" |
| 11 #include "chrome/browser/safe_browsing/safe_browsing_tab_observer.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/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/render_widget_host_view.h" | |
| 20 #include "content/public/browser/site_instance.h" | 11 #include "content/public/browser/site_instance.h" |
| 21 #include "content/public/browser/web_contents_view.h" | 12 #include "content/public/browser/web_contents.h" |
| 22 | 13 |
| 23 namespace { | 14 namespace { |
| 24 | 15 |
| 25 const int kStalePageTimeoutMS = 3 * 3600 * 1000; // 3 hours | 16 const int kStalePageTimeoutMS = 3 * 3600 * 1000; // 3 hours |
| 26 | 17 |
| 27 // This HTTP header and value are set on loads that originate from Instant. | 18 // This HTTP header and value are set on loads that originate from Instant. |
| 28 const char kInstantHeader[] = "X-Purpose: Instant"; | 19 const char kInstantHeader[] = "X-Purpose: Instant"; |
| 29 | 20 |
| 30 } // namespace | 21 } // namespace |
| 31 | 22 |
| 32 InstantLoader::Delegate::~Delegate() { | 23 InstantLoader::InstantLoader(InstantService* service) |
| 33 } | 24 : InstantWebContentsContainer( |
| 34 | 25 ALLOW_THIS_IN_INITIALIZER_LIST(this), service), |
| 35 InstantLoader::InstantLoader(Delegate* delegate) | 26 service_(service) { |
| 36 : delegate_(delegate), | 27 service_->AddObserver(this); |
| 37 contents_(NULL), | |
| 38 stale_page_timer_(false, false) { | |
| 39 } | 28 } |
| 40 | 29 |
| 41 InstantLoader::~InstantLoader() { | 30 InstantLoader::~InstantLoader() { |
| 31 service_->RemoveObserver(this); |
| 42 } | 32 } |
| 43 | 33 |
| 44 void InstantLoader::Init(const GURL& instant_url, | 34 void InstantLoader::InitContents() { |
| 45 Profile* profile, | 35 if (contents_ && (supports_instant() || contents_->IsLoading())) |
| 46 const content::WebContents* active_tab, | 36 return; |
| 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 | 37 |
| 57 void InstantLoader::Load() { | 38 GURL instant_url = chrome::search::GetInstantURL(service_->profile()); |
| 58 DVLOG(1) << "LoadURL: " << instant_url_; | 39 if (!instant_url.is_valid()) |
| 59 contents_->GetController().LoadURL( | 40 return; |
| 60 instant_url_, content::Referrer(), | 41 |
| 42 content::WebContents::CreateParams create_params(service_->profile(), |
| 43 content::SiteInstance::CreateForURL(service_->profile(), instant_url)); |
| 44 contents_.reset(content::WebContents::Create(create_params)); |
| 45 |
| 46 SetUpContents(); |
| 47 |
| 48 service_->LogDebugEvent(base::StringPrintf("%p LoadURL '%s'", |
| 49 this, |
| 50 instant_url.spec().c_str())); |
| 51 |
| 52 contents_->GetController().LoadURL(instant_url, content::Referrer(), |
| 61 content::PAGE_TRANSITION_GENERATED, kInstantHeader); | 53 content::PAGE_TRANSITION_GENERATED, kInstantHeader); |
| 62 contents_->WasHidden(); | 54 contents_->WasHidden(); |
| 63 stale_page_timer_.Start( | 55 |
| 64 FROM_HERE, | 56 stale_page_timer_.Start(FROM_HERE, |
| 65 base::TimeDelta::FromMilliseconds(kStalePageTimeoutMS), | 57 base::TimeDelta::FromMilliseconds(kStalePageTimeoutMS), |
| 66 on_stale_callback_); | 58 this, &InstantLoader::ReloadContents); |
| 67 } | |
| 68 | |
| 69 void InstantLoader::SetContents(scoped_ptr<content::WebContents> new_contents) { | |
| 70 contents_.reset(new_contents.release()); | |
| 71 contents_->SetDelegate(this); | |
| 72 | |
| 73 // Set up various tab helpers. The rest will get attached when (if) the | |
| 74 // contents is added to the tab strip. | |
| 75 | |
| 76 // Tab helpers to control popups. | |
| 77 BlockedContentTabHelper::CreateForWebContents(contents()); | |
| 78 BlockedContentTabHelper::FromWebContents(contents())-> | |
| 79 SetAllContentsBlocked(true); | |
| 80 TabSpecificContentSettings::CreateForWebContents(contents()); | |
| 81 TabSpecificContentSettings::FromWebContents(contents())-> | |
| 82 SetPopupsBlocked(true); | |
| 83 | |
| 84 // A tab helper to catch prerender content swapping shenanigans. | |
| 85 CoreTabHelper::CreateForWebContents(contents()); | |
| 86 CoreTabHelper::FromWebContents(contents())->set_delegate(this); | |
| 87 | |
| 88 // Tab helpers used when committing a preview. | |
| 89 chrome::search::SearchTabHelper::CreateForWebContents(contents()); | |
| 90 HistoryTabHelper::CreateForWebContents(contents()); | |
| 91 | |
| 92 // Observers. | |
| 93 extensions::WebNavigationTabObserver::CreateForWebContents(contents()); | |
| 94 | |
| 95 // Favicons, required by the Task Manager. | |
| 96 FaviconTabHelper::CreateForWebContents(contents()); | |
| 97 | |
| 98 // And some flat-out paranoia. | |
| 99 safe_browsing::SafeBrowsingTabObserver::CreateForWebContents(contents()); | |
| 100 | |
| 101 #if defined(OS_MACOSX) | |
| 102 // If |contents_| doesn't yet have a RWHV, SetTakesFocusOnlyOnMouseDown() will | |
| 103 // be called later, when NOTIFICATION_RENDER_VIEW_HOST_CHANGED is received. | |
| 104 if (content::RenderWidgetHostView* rwhv = | |
| 105 contents_->GetRenderWidgetHostView()) | |
| 106 rwhv->SetTakesFocusOnlyOnMouseDown(true); | |
| 107 registrar_.Add(this, content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED, | |
| 108 content::Source<content::NavigationController>( | |
| 109 &contents_->GetController())); | |
| 110 #endif | |
| 111 } | 59 } |
| 112 | 60 |
| 113 scoped_ptr<content::WebContents> InstantLoader::ReleaseContents() { | 61 scoped_ptr<content::WebContents> InstantLoader::ReleaseContents() { |
| 114 contents_->SetDelegate(NULL); | 62 TearDownContents(); |
| 115 | 63 scoped_ptr<content::WebContents> old_contents(contents_.Pass()); |
| 116 // Undo tab helper work done in SetContents(). | 64 InitContents(); |
| 117 | 65 return old_contents.Pass(); |
| 118 BlockedContentTabHelper::FromWebContents(contents())-> | |
| 119 SetAllContentsBlocked(false); | |
| 120 TabSpecificContentSettings::FromWebContents(contents())-> | |
| 121 SetPopupsBlocked(false); | |
| 122 | |
| 123 CoreTabHelper::FromWebContents(contents())->set_delegate(NULL); | |
| 124 | |
| 125 #if defined(OS_MACOSX) | |
| 126 if (content::RenderWidgetHostView* rwhv = | |
| 127 contents_->GetRenderWidgetHostView()) | |
| 128 rwhv->SetTakesFocusOnlyOnMouseDown(false); | |
| 129 registrar_.Remove(this, content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED, | |
| 130 content::Source<content::NavigationController>( | |
| 131 &contents_->GetController())); | |
| 132 #endif | |
| 133 | |
| 134 return contents_.Pass(); | |
| 135 } | 66 } |
| 136 | 67 |
| 137 void InstantLoader::Observe(int type, | 68 void InstantLoader::RenderViewGone(const content::WebContents* /* contents */) { |
| 138 const content::NotificationSource& /* source */, | 69 DeleteContents(); |
| 139 const content::NotificationDetails& /* details */) { | |
| 140 #if defined(OS_MACOSX) | |
| 141 if (type == content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED) { | |
| 142 if (content::RenderWidgetHostView* rwhv = | |
| 143 contents_->GetRenderWidgetHostView()) | |
| 144 rwhv->SetTakesFocusOnlyOnMouseDown(true); | |
| 145 return; | |
| 146 } | |
| 147 NOTREACHED(); | |
| 148 #endif | |
| 149 } | 70 } |
| 150 | 71 |
| 151 void InstantLoader::SwapTabContents(content::WebContents* old_contents, | 72 void InstantLoader::InitSearchBox(const content::WebContents* /* contents */) { |
| 152 content::WebContents* new_contents) { | 73 page_.DisplayInstantResults( |
| 153 DCHECK_EQ(old_contents, contents()); | 74 chrome::search::IsInstantPrefEnabled(service_->profile())); |
| 154 // We release here without deleting since the caller has the responsibility | 75 page_.ThemeChanged(service_->theme_info()); |
| 155 // for deleting the old WebContents. | 76 page_.FontChanged(service_->omnibox_font_name(), |
| 156 ignore_result(ReleaseContents().release()); | 77 service_->omnibox_font_size()); |
| 157 SetContents(scoped_ptr<content::WebContents>(new_contents)); | |
| 158 delegate_->OnSwappedContents(); | |
| 159 } | 78 } |
| 160 | 79 |
| 161 bool InstantLoader::ShouldSuppressDialogs() { | 80 void InstantLoader::InstantSupportDetermined( |
| 162 // Messages shown during Instant cancel Instant, so we suppress them. | 81 const content::WebContents* /* contents */) { |
| 163 return true; | 82 if (!supports_instant()) |
| 83 DeleteContents(); |
| 84 service_->InstantSupportDecided(); |
| 164 } | 85 } |
| 165 | 86 |
| 166 bool InstantLoader::ShouldFocusPageAfterCrash() { | 87 void InstantLoader::SetSuggestion(const content::WebContents* /* contents */, |
| 167 return false; | 88 const InstantSuggestion& /* suggestion */) { |
| 168 } | 89 } |
| 169 | 90 |
| 170 void InstantLoader::LostCapture() { | 91 void InstantLoader::NavigateToURL(const content::WebContents* /* contents */, |
| 171 delegate_->OnMouseUp(); | 92 const GURL& /* url */, |
| 93 content::PageTransition /* transition */, |
| 94 WindowOpenDisposition /* disposition */) { |
| 172 } | 95 } |
| 173 | 96 |
| 174 void InstantLoader::WebContentsFocused(content::WebContents* /* contents */) { | 97 void InstantLoader::ShowOverlay(const content::WebContents* /* contents */, |
| 175 delegate_->OnFocus(); | 98 int /* height */, |
| 99 bool /* is_height_in_pixels */) { |
| 176 } | 100 } |
| 177 | 101 |
| 178 bool InstantLoader::CanDownload(content::RenderViewHost* /* render_view_host */, | 102 void InstantLoader::StartKeyCapture( |
| 179 int /* request_id */, | 103 const content::WebContents* /* contents */) { |
| 180 const std::string& /* request_method */) { | |
| 181 // Downloads are disabled. | |
| 182 return false; | |
| 183 } | 104 } |
| 184 | 105 |
| 185 void InstantLoader::HandleMouseDown() { | 106 void InstantLoader::StopKeyCapture(const content::WebContents* /* contents */) { |
| 186 delegate_->OnMouseDown(); | |
| 187 } | 107 } |
| 188 | 108 |
| 189 void InstantLoader::HandleMouseUp() { | 109 void InstantLoader::DeleteMostVisitedItem( |
| 190 delegate_->OnMouseUp(); | 110 const content::WebContents* /* contents */, |
| 111 const GURL& /* url */) { |
| 191 } | 112 } |
| 192 | 113 |
| 193 void InstantLoader::HandlePointerActivate() { | 114 void InstantLoader::UndoMostVisitedItemDeletion( |
| 194 delegate_->OnMouseDown(); | 115 const content::WebContents* /* contents */, |
| 116 const GURL& /* url */) { |
| 195 } | 117 } |
| 196 | 118 |
| 197 void InstantLoader::HandleGestureEnd() { | 119 void InstantLoader::UndoAllMostVisitedItemDeletions( |
| 198 delegate_->OnMouseUp(); | 120 const content::WebContents* /* contents */) { |
| 199 } | 121 } |
| 200 | 122 |
| 201 void InstantLoader::DragEnded() { | 123 void InstantLoader::InstantStatusChanged() { |
| 202 // If the user drags, we won't get a mouse up (at least on Linux). Commit | 124 if (contents_) |
| 203 // the Instant result when the drag ends, so that during the drag the page | 125 ReloadContents(); |
| 204 // won't move around. | |
| 205 delegate_->OnMouseUp(); | |
| 206 } | 126 } |
| 207 | 127 |
| 208 bool InstantLoader::OnGoToEntryOffset(int /* offset */) { | 128 void InstantLoader::ThemeInfoChanged() { |
| 209 return false; | 129 page_.ThemeChanged(service_->theme_info()); |
| 210 } | 130 } |
| 211 | 131 |
| 212 content::WebContents* InstantLoader::OpenURLFromTab( | 132 void InstantLoader::MostVisitedItemsChanged() { |
| 213 content::WebContents* source, | 133 page_.MostVisitedItems(service_->most_visited_items()); |
| 214 const content::OpenURLParams& params) { | |
| 215 return delegate_->OpenURLFromTab(source, params); | |
| 216 } | 134 } |
| 135 |
| 136 void InstantLoader::InstantSupportDecided() { |
| 137 } |
| 138 |
| 139 void InstantLoader::CloseContents(content::WebContents* /* source */) { |
| 140 DeleteContents(); |
| 141 } |
| 142 |
| 143 void InstantLoader::TearDownContents() { |
| 144 InstantWebContentsContainer::TearDownContents(); |
| 145 stale_page_timer_.Stop(); |
| 146 } |
| 147 |
| 148 void InstantLoader::DeleteContents() { |
| 149 TearDownContents(); |
| 150 contents_.reset(); |
| 151 } |
| 152 |
| 153 void InstantLoader::ReloadContents() { |
| 154 DeleteContents(); |
| 155 InitContents(); |
| 156 } |
| OLD | NEW |