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 |