blob: 6d8abfa1527e21cd0b11c51f07c91cbd5669f7d1 [file] [log] [blame]
[email protected]f0dc75232012-01-05 01:07:001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]fd2b9ce2010-08-11 04:03:572// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]6b723f82010-10-05 20:14:275#include "chrome/browser/instant/instant_controller.h"
[email protected]fd2b9ce2010-08-11 04:03:576
[email protected]c90388e32011-11-29 02:18:477#include "base/bind.h"
[email protected]fd2b9ce2010-08-11 04:03:578#include "base/command_line.h"
[email protected]f38adeeb2010-12-08 01:08:119#include "base/message_loop.h"
[email protected]7e03e812010-11-15 23:01:0110#include "base/metrics/histogram.h"
[email protected]2380b9a2011-07-28 20:10:3611#include "base/rand_util.h"
[email protected]b3841c502011-03-09 01:21:3112#include "build/build_config.h"
[email protected]9ac40092010-10-27 23:05:2613#include "chrome/browser/autocomplete/autocomplete_match.h"
[email protected]6b723f82010-10-05 20:14:2714#include "chrome/browser/instant/instant_delegate.h"
[email protected]2380b9a2011-07-28 20:10:3615#include "chrome/browser/instant/instant_field_trial.h"
[email protected]6b723f82010-10-05 20:14:2716#include "chrome/browser/instant/instant_loader.h"
[email protected]ba6680f2010-11-01 20:35:0817#include "chrome/browser/platform_util.h"
[email protected]018cbb22010-10-11 22:32:0918#include "chrome/browser/prefs/pref_service.h"
[email protected]8ecad5e2010-12-02 21:18:3319#include "chrome/browser/profiles/profile.h"
[email protected]03bb953d2010-09-14 21:38:3020#include "chrome/browser/search_engines/template_url.h"
[email protected]8e5c89a2011-06-07 18:13:3321#include "chrome/browser/search_engines/template_url_service.h"
22#include "chrome/browser/search_engines/template_url_service_factory.h"
[email protected]e7cfdbd2011-04-22 14:41:3723#include "chrome/browser/ui/blocked_content/blocked_content_tab_helper.h"
[email protected]6a3ec2312010-12-02 19:30:1924#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
[email protected]432115822011-07-10 15:52:2725#include "chrome/common/chrome_notification_types.h"
[email protected]fd2b9ce2010-08-11 04:03:5726#include "chrome/common/chrome_switches.h"
[email protected]018cbb22010-10-11 22:32:0927#include "chrome/common/pref_names.h"
[email protected]ad50def52011-10-19 23:17:0728#include "content/public/browser/notification_service.h"
[email protected]5626b0892012-02-20 14:46:5829#include "content/public/browser/render_widget_host_view.h"
[email protected]ef9572e2012-01-04 22:14:1230#include "content/public/browser/web_contents.h"
[email protected]fd2b9ce2010-08-11 04:03:5731
[email protected]6eb8ea92011-08-22 21:01:4132#if defined(TOOLKIT_VIEWS)
[email protected]477ae052011-11-18 23:53:5733#include "ui/views/focus/focus_manager.h"
[email protected]5025f862011-11-30 23:35:2034#include "ui/views/view.h"
[email protected]c13be0d2011-11-22 02:09:5835#include "ui/views/widget/widget.h"
[email protected]6eb8ea92011-08-22 21:01:4136#endif
37
[email protected]fdf773c52010-11-01 20:58:1938InstantController::InstantController(Profile* profile,
39 InstantDelegate* delegate)
[email protected]03bb953d2010-09-14 21:38:3040 : delegate_(delegate),
[email protected]d8e73bd2012-03-14 16:30:5241 template_url_service_(TemplateURLServiceFactory::GetForProfile(profile)),
[email protected]03bb953d2010-09-14 21:38:3042 tab_contents_(NULL),
[email protected]2b15fc8c2011-10-07 20:52:3643 is_displayable_(false),
[email protected]3e481282011-10-15 15:39:5044 is_out_of_date_(true),
[email protected]484ae5912010-09-29 19:16:1445 commit_on_mouse_up_(false),
[email protected]2905f742011-10-13 03:51:5846 last_transition_type_(content::PAGE_TRANSITION_LINK),
[email protected]c90388e32011-11-29 02:18:4747 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
[email protected]d8e73bd2012-03-14 16:30:5248 DCHECK(template_url_service_);
[email protected]7e03e812010-11-15 23:01:0149 PrefService* service = profile->GetPrefs();
[email protected]99630202011-10-28 21:49:0650 if (service && !InstantFieldTrial::IsInstantExperiment(profile)) {
[email protected]2380b9a2011-07-28 20:10:3651 // kInstantEnabledOnce was added after instant, set it now to make sure it
52 // is correctly set.
[email protected]7e03e812010-11-15 23:01:0153 service->SetBoolean(prefs::kInstantEnabledOnce, true);
54 }
[email protected]03bb953d2010-09-14 21:38:3055}
56
[email protected]6b723f82010-10-05 20:14:2757InstantController::~InstantController() {
[email protected]03bb953d2010-09-14 21:38:3058}
59
[email protected]7e03e812010-11-15 23:01:0160// static
61void InstantController::RegisterUserPrefs(PrefService* prefs) {
[email protected]d36f941b2011-05-09 06:19:1662 prefs->RegisterBooleanPref(prefs::kInstantConfirmDialogShown,
63 false,
[email protected]18c2ffac2011-09-16 21:07:2964 PrefService::SYNCABLE_PREF);
[email protected]d36f941b2011-05-09 06:19:1665 prefs->RegisterBooleanPref(prefs::kInstantEnabled,
66 false,
[email protected]18c2ffac2011-09-16 21:07:2967 PrefService::SYNCABLE_PREF);
[email protected]d36f941b2011-05-09 06:19:1668 prefs->RegisterBooleanPref(prefs::kInstantEnabledOnce,
69 false,
[email protected]18c2ffac2011-09-16 21:07:2970 PrefService::SYNCABLE_PREF);
[email protected]7e03e812010-11-15 23:01:0171}
72
73// static
74void InstantController::RecordMetrics(Profile* profile) {
[email protected]0c9d6bb12012-04-02 22:11:3775 UMA_HISTOGRAM_ENUMERATION("Instant.Status", IsEnabled(profile), 2);
[email protected]7e03e812010-11-15 23:01:0176}
77
78// static
79bool InstantController::IsEnabled(Profile* profile) {
[email protected]6eff9392011-01-26 21:46:5080 PrefService* prefs = profile->GetPrefs();
[email protected]2380b9a2011-07-28 20:10:3681 return prefs->GetBoolean(prefs::kInstantEnabled) ||
[email protected]99630202011-10-28 21:49:0682 InstantFieldTrial::IsInstantExperiment(profile);
[email protected]7e03e812010-11-15 23:01:0183}
84
85// static
86void InstantController::Enable(Profile* profile) {
[email protected]7e03e812010-11-15 23:01:0187 PrefService* service = profile->GetPrefs();
88 if (!service)
89 return;
90
[email protected]ddb3be72012-03-31 00:50:1391 base::Histogram* histogram = base::LinearHistogram::FactoryGet(
92 "Instant.Preference" + InstantFieldTrial::GetGroupName(profile), 1, 2, 3,
93 base::Histogram::kUmaTargetedHistogramFlag);
94 histogram->Add(1);
95
[email protected]2380b9a2011-07-28 20:10:3696 service->SetBoolean(prefs::kInstantEnabledOnce, true);
[email protected]7e03e812010-11-15 23:01:0197 service->SetBoolean(prefs::kInstantEnabled, true);
98 service->SetBoolean(prefs::kInstantConfirmDialogShown, true);
[email protected]7e03e812010-11-15 23:01:0199}
100
101// static
102void InstantController::Disable(Profile* profile) {
103 PrefService* service = profile->GetPrefs();
[email protected]bfc031f2010-11-29 21:39:57104 if (!service || !IsEnabled(profile))
[email protected]7e03e812010-11-15 23:01:01105 return;
106
[email protected]ddb3be72012-03-31 00:50:13107 base::Histogram* histogram = base::LinearHistogram::FactoryGet(
108 "Instant.Preference" + InstantFieldTrial::GetGroupName(profile), 1, 2, 3,
109 base::Histogram::kUmaTargetedHistogramFlag);
110 histogram->Add(0);
[email protected]2380b9a2011-07-28 20:10:36111
[email protected]849c96312011-07-26 01:06:57112 service->SetBoolean(prefs::kInstantEnabledOnce, true);
[email protected]bfc031f2010-11-29 21:39:57113 service->SetBoolean(prefs::kInstantEnabled, false);
[email protected]7e03e812010-11-15 23:01:01114}
115
[email protected]939e54a2010-12-18 02:42:07116// static
117bool InstantController::CommitIfCurrent(InstantController* controller) {
118 if (controller && controller->IsCurrent()) {
119 controller->CommitCurrentPreview(INSTANT_COMMIT_PRESSED_ENTER);
120 return true;
121 }
122 return false;
123}
124
[email protected]65d68da2011-09-08 03:19:33125bool InstantController::Update(TabContentsWrapper* tab_contents,
[email protected]6b723f82010-10-05 20:14:27126 const AutocompleteMatch& match,
127 const string16& user_text,
[email protected]57ad7b8c2010-11-18 19:13:49128 bool verbatim,
[email protected]6b723f82010-10-05 20:14:27129 string16* suggested_text) {
[email protected]bdf1d862010-11-24 02:46:11130 suggested_text->clear();
131
[email protected]03bb953d2010-09-14 21:38:30132 tab_contents_ = tab_contents;
[email protected]484ae5912010-09-29 19:16:14133 commit_on_mouse_up_ = false;
[email protected]97b6c4f2010-09-27 19:31:26134 last_transition_type_ = match.transition;
[email protected]64f09b82011-10-13 16:17:20135 last_url_ = match.destination_url;
136 last_user_text_ = user_text;
137
[email protected]d8e73bd2012-03-14 16:30:52138 const TemplateURL* template_url = match.GetTemplateURL();
139 const TemplateURL* default_t_url =
140 template_url_service_->GetDefaultSearchProvider();
141 if (!IsValidInstantTemplateURL(template_url) || !default_t_url ||
142 (template_url->id() != default_t_url->id())) {
[email protected]3e481282011-10-15 15:39:50143 Hide();
[email protected]65d68da2011-09-08 03:19:33144 return false;
[email protected]fd2b9ce2010-08-11 04:03:57145 }
146
[email protected]f0dc75232012-01-05 01:07:00147 if (!loader_.get()) {
148 loader_.reset(new InstantLoader(this, template_url->id(),
149 InstantFieldTrial::GetGroupName(tab_contents->profile())));
150 }
[email protected]03bb953d2010-09-14 21:38:30151
[email protected]64f09b82011-10-13 16:17:20152 // In some rare cases (involving group policy), Instant can go from the field
[email protected]45051c32011-10-18 05:28:45153 // trial to normal mode, with no intervening call to DestroyPreviewContents().
[email protected]64f09b82011-10-13 16:17:20154 // This would leave the loader in a weird state, which would manifest if the
155 // user pressed <Enter> without calling Update(). TODO(sreeram): Handle it.
[email protected]f6797162011-10-25 03:11:31156 if (InstantFieldTrial::IsSilentExperiment(tab_contents->profile())) {
157 // For the SILENT field trial we process |user_text| at commit time, which
[email protected]3e481282011-10-15 15:39:50158 // means we're never really out of date.
159 is_out_of_date_ = false;
[email protected]64f09b82011-10-13 16:17:20160 loader_->MaybeLoadInstantURL(tab_contents, template_url);
161 return true;
162 }
[email protected]36d5e5592010-11-15 20:45:59163
[email protected]2b15fc8c2011-10-07 20:52:36164 UpdateLoader(template_url, match.destination_url, match.transition, user_text,
165 verbatim, suggested_text);
[email protected]eac60f72010-10-21 19:11:39166
[email protected]ad50def52011-10-19 23:17:07167 content::NotificationService::current()->Notify(
[email protected]432115822011-07-10 15:52:27168 chrome::NOTIFICATION_INSTANT_CONTROLLER_UPDATED,
[email protected]6c2381d2011-10-19 02:52:53169 content::Source<InstantController>(this),
[email protected]ad50def52011-10-19 23:17:07170 content::NotificationService::NoDetails());
[email protected]65d68da2011-09-08 03:19:33171 return true;
[email protected]fd2b9ce2010-08-11 04:03:57172}
173
[email protected]6b723f82010-10-05 20:14:27174void InstantController::SetOmniboxBounds(const gfx::Rect& bounds) {
[email protected]46fe8e92010-09-22 03:32:47175 if (omnibox_bounds_ == bounds)
176 return;
177
[email protected]6e6b59f42010-12-13 20:20:23178 // Always track the omnibox bounds. That way if Update is later invoked the
179 // bounds are in sync.
180 omnibox_bounds_ = bounds;
[email protected]99630202011-10-28 21:49:06181
182 if (loader_.get() && !is_out_of_date_ &&
183 !InstantFieldTrial::IsHiddenExperiment(tab_contents_->profile())) {
[email protected]2b15fc8c2011-10-07 20:52:36184 loader_->SetOmniboxBounds(bounds);
[email protected]99630202011-10-28 21:49:06185 }
[email protected]46fe8e92010-09-22 03:32:47186}
187
[email protected]6b723f82010-10-05 20:14:27188void InstantController::DestroyPreviewContents() {
[email protected]2b15fc8c2011-10-07 20:52:36189 if (!loader_.get()) {
[email protected]17336512010-09-22 17:28:27190 // We're not showing anything, nothing to do.
191 return;
192 }
193
[email protected]6b723f82010-10-05 20:14:27194 delegate_->HideInstant();
[email protected]5419ff92012-01-06 21:17:15195 delete ReleasePreviewContents(INSTANT_COMMIT_DESTROY, NULL);
[email protected]fd2b9ce2010-08-11 04:03:57196}
197
[email protected]3e481282011-10-15 15:39:50198void InstantController::Hide() {
199 is_out_of_date_ = true;
[email protected]7cce9f22011-02-28 22:02:47200 commit_on_mouse_up_ = false;
[email protected]2b15fc8c2011-10-07 20:52:36201 if (is_displayable_) {
202 is_displayable_ = false;
[email protected]2573b8d2011-03-01 16:20:36203 delegate_->HideInstant();
204 }
[email protected]7cce9f22011-02-28 22:02:47205}
206
[email protected]eadbf9532011-11-03 23:52:16207bool InstantController::IsCurrent() const {
[email protected]5376c262011-09-01 04:53:19208 // TODO(mmenke): See if we can do something more intelligent in the
209 // navigation pending case.
[email protected]2b15fc8c2011-10-07 20:52:36210 return is_displayable_ && !loader_->IsNavigationPending() &&
211 !loader_->needs_reload();
[email protected]0a387472010-10-07 00:18:20212}
213
[email protected]64f09b82011-10-13 16:17:20214bool InstantController::PrepareForCommit() {
[email protected]07c4ce72011-10-18 17:08:20215 // Basic checks to prevent accessing a dangling |tab_contents_| pointer.
216 // http://crbug.com/100521.
217 if (is_out_of_date_ || !loader_.get())
218 return false;
219
[email protected]f6797162011-10-25 03:11:31220 // If we are not in the HIDDEN or SILENT field trials, return the status of
221 // the preview.
[email protected]99630202011-10-28 21:49:06222 if (!InstantFieldTrial::IsHiddenExperiment(tab_contents_->profile()))
[email protected]64f09b82011-10-13 16:17:20223 return IsCurrent();
224
[email protected]d8e73bd2012-03-14 16:30:52225 const TemplateURL* template_url =
226 template_url_service_->GetDefaultSearchProvider();
[email protected]07c4ce72011-10-18 17:08:20227 if (!IsValidInstantTemplateURL(template_url) ||
[email protected]64f09b82011-10-13 16:17:20228 loader_->template_url_id() != template_url->id() ||
229 loader_->IsNavigationPending() ||
230 loader_->is_determining_if_page_supports_instant()) {
231 return false;
232 }
233
[email protected]d6909df2012-01-25 01:46:35234 // In the HIDDEN and SUGGEST experiments (but not SILENT), we must have sent
235 // an Update() by now, so check if the loader failed to process it.
236 if (!InstantFieldTrial::IsSilentExperiment(tab_contents_->profile()) &&
237 (!loader_->ready() || !loader_->http_status_ok())) {
238 return false;
239 }
240
[email protected]64f09b82011-10-13 16:17:20241 // Ignore the suggested text, as we are about to commit the verbatim query.
242 string16 suggested_text;
243 UpdateLoader(template_url, last_url_, last_transition_type_, last_user_text_,
244 true, &suggested_text);
245 return true;
246}
247
[email protected]094b0522011-10-06 00:55:27248TabContentsWrapper* InstantController::CommitCurrentPreview(
249 InstantCommitType type) {
[email protected]2b15fc8c2011-10-07 20:52:36250 DCHECK(loader_.get());
[email protected]5419ff92012-01-06 21:17:15251 TabContentsWrapper* tab = ReleasePreviewContents(type, tab_contents_);
[email protected]ef9572e2012-01-04 22:14:12252 tab->web_contents()->GetController().CopyStateFromAndPrune(
253 &tab_contents_->web_contents()->GetController());
[email protected]c65e2f152010-10-14 15:30:40254 delegate_->CommitInstant(tab);
[email protected]e7cfdbd2011-04-22 14:41:37255 CompleteRelease(tab);
[email protected]094b0522011-10-06 00:55:27256 return tab;
[email protected]fd2b9ce2010-08-11 04:03:57257}
258
[email protected]6b723f82010-10-05 20:14:27259void InstantController::SetCommitOnMouseUp() {
[email protected]484ae5912010-09-29 19:16:14260 commit_on_mouse_up_ = true;
261}
262
[email protected]6b723f82010-10-05 20:14:27263bool InstantController::IsMouseDownFromActivate() {
[email protected]2b15fc8c2011-10-07 20:52:36264 DCHECK(loader_.get());
265 return loader_->IsMouseDownFromActivate();
[email protected]484ae5912010-09-29 19:16:14266}
267
[email protected]20ac3c32011-03-06 17:59:19268#if defined(OS_MACOSX)
269void InstantController::OnAutocompleteLostFocus(
270 gfx::NativeView view_gaining_focus) {
271 // If |IsMouseDownFromActivate()| returns false, the RenderWidgetHostView did
272 // not receive a mouseDown event. Therefore, we should destroy the preview.
273 // Otherwise, the RWHV was clicked, so we commit the preview.
[email protected]2b15fc8c2011-10-07 20:52:36274 if (!IsCurrent() || !IsMouseDownFromActivate())
[email protected]20ac3c32011-03-06 17:59:19275 DestroyPreviewContents();
[email protected]2b15fc8c2011-10-07 20:52:36276 else
[email protected]20ac3c32011-03-06 17:59:19277 SetCommitOnMouseUp();
[email protected]20ac3c32011-03-06 17:59:19278}
279#else
[email protected]ba6680f2010-11-01 20:35:08280void InstantController::OnAutocompleteLostFocus(
281 gfx::NativeView view_gaining_focus) {
[email protected]2b15fc8c2011-10-07 20:52:36282 if (!IsCurrent()) {
[email protected]1946c932010-12-15 00:07:38283 DestroyPreviewContents();
[email protected]ba6680f2010-11-01 20:35:08284 return;
[email protected]1946c932010-12-15 00:07:38285 }
[email protected]ba6680f2010-11-01 20:35:08286
[email protected]5626b0892012-02-20 14:46:58287 content::RenderWidgetHostView* rwhv =
[email protected]ef9572e2012-01-04 22:14:12288 GetPreviewContents()->web_contents()->GetRenderWidgetHostView();
[email protected]5a85751b2010-11-17 01:33:27289 if (!view_gaining_focus || !rwhv) {
290 DestroyPreviewContents();
291 return;
292 }
[email protected]ba6680f2010-11-01 20:35:08293
[email protected]6eb8ea92011-08-22 21:01:41294#if defined(TOOLKIT_VIEWS)
295 // For views the top level widget is always focused. If the focus change
296 // originated in views determine the child Widget from the view that is being
297 // focused.
[email protected]09c69432012-03-16 16:23:28298 views::Widget* widget =
299 views::Widget::GetWidgetForNativeView(view_gaining_focus);
300 if (widget) {
301 views::FocusManager* focus_manager = widget->GetFocusManager();
302 if (focus_manager && focus_manager->is_changing_focus() &&
303 focus_manager->GetFocusedView() &&
304 focus_manager->GetFocusedView()->GetWidget()) {
305 view_gaining_focus =
306 focus_manager->GetFocusedView()->GetWidget()->GetNativeView();
[email protected]6eb8ea92011-08-22 21:01:41307 }
308 }
309#endif
310
[email protected]3c9e1872010-11-18 16:17:49311 gfx::NativeView tab_view =
[email protected]ef9572e2012-01-04 22:14:12312 GetPreviewContents()->web_contents()->GetNativeView();
[email protected]ba6680f2010-11-01 20:35:08313 // Focus is going to the renderer.
314 if (rwhv->GetNativeView() == view_gaining_focus ||
315 tab_view == view_gaining_focus) {
316 if (!IsMouseDownFromActivate()) {
317 // If the mouse is not down, focus is not going to the renderer. Someone
318 // else moved focus and we shouldn't commit.
[email protected]5a85751b2010-11-17 01:33:27319 DestroyPreviewContents();
320 return;
[email protected]ba6680f2010-11-01 20:35:08321 }
322
[email protected]2b15fc8c2011-10-07 20:52:36323 // We're showing instant results. As instant results may shift when
324 // committing we commit on the mouse up. This way a slow click still works
325 // fine.
326 SetCommitOnMouseUp();
[email protected]5a85751b2010-11-17 01:33:27327 return;
[email protected]ba6680f2010-11-01 20:35:08328 }
329
330 // Walk up the view hierarchy. If the view gaining focus is a subview of the
[email protected]0932b30c2012-04-17 13:25:10331 // WebContents view (such as a windowed plugin or http auth dialog), we want
[email protected]ba6680f2010-11-01 20:35:08332 // to keep the preview contents. Otherwise, focus has gone somewhere else,
333 // such as the JS inspector, and we want to cancel the preview.
334 gfx::NativeView view_gaining_focus_ancestor = view_gaining_focus;
335 while (view_gaining_focus_ancestor &&
336 view_gaining_focus_ancestor != tab_view) {
337 view_gaining_focus_ancestor =
338 platform_util::GetParent(view_gaining_focus_ancestor);
339 }
340
[email protected]5a85751b2010-11-17 01:33:27341 if (view_gaining_focus_ancestor) {
342 CommitCurrentPreview(INSTANT_COMMIT_FOCUS_LOST);
343 return;
344 }
[email protected]ba6680f2010-11-01 20:35:08345
[email protected]5a85751b2010-11-17 01:33:27346 DestroyPreviewContents();
[email protected]ba6680f2010-11-01 20:35:08347}
[email protected]20ac3c32011-03-06 17:59:19348#endif
[email protected]ba6680f2010-11-01 20:35:08349
[email protected]f2557bd2011-06-01 02:33:07350void InstantController::OnAutocompleteGotFocus(
351 TabContentsWrapper* tab_contents) {
352 CommandLine* cl = CommandLine::ForCurrentProcess();
[email protected]2380b9a2011-07-28 20:10:36353 if (!cl->HasSwitch(switches::kPreloadInstantSearch) &&
[email protected]99630202011-10-28 21:49:06354 !InstantFieldTrial::IsInstantExperiment(tab_contents->profile())) {
[email protected]f2557bd2011-06-01 02:33:07355 return;
[email protected]2380b9a2011-07-28 20:10:36356 }
[email protected]f2557bd2011-06-01 02:33:07357
[email protected]d8e73bd2012-03-14 16:30:52358 const TemplateURL* template_url =
359 template_url_service_->GetDefaultSearchProvider();
[email protected]2b15fc8c2011-10-07 20:52:36360 if (!IsValidInstantTemplateURL(template_url))
[email protected]f2557bd2011-06-01 02:33:07361 return;
362
[email protected]f2557bd2011-06-01 02:33:07363 tab_contents_ = tab_contents;
364
[email protected]f0dc75232012-01-05 01:07:00365 if (!loader_.get()) {
366 loader_.reset(new InstantLoader(this, template_url->id(),
367 InstantFieldTrial::GetGroupName(tab_contents->profile())));
368 }
[email protected]2b15fc8c2011-10-07 20:52:36369 loader_->MaybeLoadInstantURL(tab_contents, template_url);
[email protected]f2557bd2011-06-01 02:33:07370}
371
[email protected]3c9e1872010-11-18 16:17:49372TabContentsWrapper* InstantController::ReleasePreviewContents(
[email protected]5419ff92012-01-06 21:17:15373 InstantCommitType type,
374 TabContentsWrapper* current_tab) {
[email protected]2b15fc8c2011-10-07 20:52:36375 if (!loader_.get())
[email protected]3aac77a2010-09-24 17:00:13376 return NULL;
377
[email protected]5419ff92012-01-06 21:17:15378 TabContentsWrapper* tab = loader_->ReleasePreviewContents(type, current_tab);
[email protected]0a387472010-10-07 00:18:20379 ClearBlacklist();
[email protected]07c4ce72011-10-18 17:08:20380 is_out_of_date_ = true;
[email protected]2b15fc8c2011-10-07 20:52:36381 is_displayable_ = false;
[email protected]a0b84662010-10-04 23:22:04382 commit_on_mouse_up_ = false;
[email protected]1946c932010-12-15 00:07:38383 omnibox_bounds_ = gfx::Rect();
[email protected]2b15fc8c2011-10-07 20:52:36384 loader_.reset();
[email protected]a0b84662010-10-04 23:22:04385 return tab;
386}
387
[email protected]e7cfdbd2011-04-22 14:41:37388void InstantController::CompleteRelease(TabContentsWrapper* tab) {
389 tab->blocked_content_tab_helper()->SetAllContentsBlocked(false);
[email protected]c65e2f152010-10-14 15:30:40390}
391
[email protected]eadbf9532011-11-03 23:52:16392TabContentsWrapper* InstantController::GetPreviewContents() const {
[email protected]2b15fc8c2011-10-07 20:52:36393 return loader_.get() ? loader_->preview_contents() : NULL;
[email protected]a5ec3ea2011-02-09 17:01:28394}
395
[email protected]3d3afbf2011-03-29 19:59:21396void InstantController::InstantStatusChanged(InstantLoader* loader) {
[email protected]2b15fc8c2011-10-07 20:52:36397 DCHECK(loader_.get());
398 UpdateIsDisplayable();
[email protected]fd2b9ce2010-08-11 04:03:57399}
[email protected]03bb953d2010-09-14 21:38:30400
[email protected]33b8b8e2011-03-15 14:51:55401void InstantController::SetSuggestedTextFor(
402 InstantLoader* loader,
403 const string16& text,
404 InstantCompleteBehavior behavior) {
[email protected]f6797162011-10-25 03:11:31405 if (!is_out_of_date_ &&
[email protected]e084b1b2011-11-17 06:52:44406 InstantFieldTrial::ShouldSetSuggestedText(tab_contents_->profile())) {
[email protected]f6797162011-10-25 03:11:31407 delegate_->SetSuggestedText(text, behavior);
408 }
[email protected]a0b84662010-10-04 23:22:04409}
[email protected]03bb953d2010-09-14 21:38:30410
[email protected]6b723f82010-10-05 20:14:27411gfx::Rect InstantController::GetInstantBounds() {
412 return delegate_->GetInstantBounds();
[email protected]a0b84662010-10-04 23:22:04413}
414
[email protected]6b723f82010-10-05 20:14:27415bool InstantController::ShouldCommitInstantOnMouseUp() {
[email protected]a0b84662010-10-04 23:22:04416 return commit_on_mouse_up_;
417}
418
[email protected]6b723f82010-10-05 20:14:27419void InstantController::CommitInstantLoader(InstantLoader* loader) {
[email protected]2b15fc8c2011-10-07 20:52:36420 if (loader_.get() && loader_.get() == loader) {
[email protected]6b723f82010-10-05 20:14:27421 CommitCurrentPreview(INSTANT_COMMIT_FOCUS_LOST);
[email protected]a0b84662010-10-04 23:22:04422 } else {
423 // This can happen if the mouse was down, we swapped out the preview and
424 // the mouse was released. Generally this shouldn't happen, but if it does
425 // revert.
426 DestroyPreviewContents();
[email protected]03bb953d2010-09-14 21:38:30427 }
[email protected]03bb953d2010-09-14 21:38:30428}
429
[email protected]0a387472010-10-07 00:18:20430void InstantController::InstantLoaderDoesntSupportInstant(
[email protected]4c1b035d2010-12-10 02:32:23431 InstantLoader* loader) {
[email protected]1946c932010-12-15 00:07:38432 VLOG(1) << "provider does not support instant";
[email protected]4c1b035d2010-12-10 02:32:23433
434 // Don't attempt to use instant for this search engine again.
[email protected]2b15fc8c2011-10-07 20:52:36435 BlacklistFromInstant();
[email protected]0a387472010-10-07 00:18:20436}
437
[email protected]f38adeeb2010-12-08 01:08:11438void InstantController::AddToBlacklist(InstantLoader* loader, const GURL& url) {
[email protected]2b15fc8c2011-10-07 20:52:36439 // Don't attempt to use instant for this search engine again.
440 BlacklistFromInstant();
[email protected]2573b8d2011-03-01 16:20:36441}
442
[email protected]00d64212011-05-25 18:18:28443void InstantController::SwappedTabContents(InstantLoader* loader) {
[email protected]2b15fc8c2011-10-07 20:52:36444 if (is_displayable_)
445 delegate_->ShowInstant(loader->preview_contents());
[email protected]00d64212011-05-25 18:18:28446}
447
[email protected]09c69432012-03-16 16:23:28448void InstantController::InstantLoaderContentsFocused() {
449#if defined(USE_AURA)
450 // On aura the omnibox only receives a focus lost if we initiate the focus
451 // change. This does that.
452 if (!InstantFieldTrial::IsSilentExperiment(tab_contents_->profile()))
453 delegate_->InstantPreviewFocused();
454#endif
455}
456
[email protected]2b15fc8c2011-10-07 20:52:36457void InstantController::UpdateIsDisplayable() {
[email protected]f6797162011-10-25 03:11:31458 if (!is_out_of_date_ &&
459 InstantFieldTrial::IsHiddenExperiment(tab_contents_->profile())) {
460 return;
461 }
462
[email protected]2b15fc8c2011-10-07 20:52:36463 bool displayable =
[email protected]3e481282011-10-15 15:39:50464 (!is_out_of_date_ && loader_.get() && loader_->ready() &&
465 loader_->http_status_ok());
[email protected]2b15fc8c2011-10-07 20:52:36466 if (displayable == is_displayable_)
[email protected]2573b8d2011-03-01 16:20:36467 return;
468
[email protected]2b15fc8c2011-10-07 20:52:36469 is_displayable_ = displayable;
470 if (!is_displayable_) {
[email protected]f38adeeb2010-12-08 01:08:11471 delegate_->HideInstant();
[email protected]2573b8d2011-03-01 16:20:36472 } else {
[email protected]2b15fc8c2011-10-07 20:52:36473 delegate_->ShowInstant(loader_->preview_contents());
[email protected]ad50def52011-10-19 23:17:07474 content::NotificationService::current()->Notify(
[email protected]432115822011-07-10 15:52:27475 chrome::NOTIFICATION_INSTANT_CONTROLLER_SHOWN,
[email protected]6c2381d2011-10-19 02:52:53476 content::Source<InstantController>(this),
[email protected]ad50def52011-10-19 23:17:07477 content::NotificationService::NoDetails());
[email protected]f38adeeb2010-12-08 01:08:11478 }
479}
480
[email protected]7c71e942010-10-14 18:18:59481void InstantController::UpdateLoader(const TemplateURL* template_url,
[email protected]0a387472010-10-07 00:18:20482 const GURL& url,
[email protected]2905f742011-10-13 03:51:58483 content::PageTransition transition_type,
[email protected]0a387472010-10-07 00:18:20484 const string16& user_text,
[email protected]57ad7b8c2010-11-18 19:13:49485 bool verbatim,
[email protected]0a387472010-10-07 00:18:20486 string16* suggested_text) {
[email protected]3e481282011-10-15 15:39:50487 is_out_of_date_ = false;
[email protected]e084b1b2011-11-17 06:52:44488 if (!InstantFieldTrial::IsHiddenExperiment(tab_contents_->profile()))
[email protected]99630202011-10-28 21:49:06489 loader_->SetOmniboxBounds(omnibox_bounds_);
[email protected]2b15fc8c2011-10-07 20:52:36490 loader_->Update(tab_contents_, template_url, url, transition_type, user_text,
491 verbatim, suggested_text);
492 UpdateIsDisplayable();
[email protected]99630202011-10-28 21:49:06493 // For the HIDDEN and SILENT field trials, don't send back suggestions.
[email protected]e084b1b2011-11-17 06:52:44494 if (!InstantFieldTrial::ShouldSetSuggestedText(tab_contents_->profile()))
[email protected]f6797162011-10-25 03:11:31495 suggested_text->clear();
[email protected]0a387472010-10-07 00:18:20496}
497
[email protected]2b15fc8c2011-10-07 20:52:36498// Returns true if |template_url| is a valid TemplateURL for use by instant.
499bool InstantController::IsValidInstantTemplateURL(
500 const TemplateURL* template_url) {
[email protected]360ba052012-04-04 17:26:13501 return template_url && template_url->id() &&
502 template_url->instant_url_ref().SupportsReplacement() &&
[email protected]2b15fc8c2011-10-07 20:52:36503 !IsBlacklistedFromInstant(template_url->id());
504}
505
506void InstantController::BlacklistFromInstant() {
507 if (!loader_.get())
508 return;
509
510 DCHECK(loader_->template_url_id());
511 blacklisted_ids_.insert(loader_->template_url_id());
512
513 // Because of the state of the stack we can't destroy the loader now.
514 ScheduleDestroy(loader_.release());
515 UpdateIsDisplayable();
[email protected]0a387472010-10-07 00:18:20516}
517
518bool InstantController::IsBlacklistedFromInstant(TemplateURLID id) {
519 return blacklisted_ids_.count(id) > 0;
520}
521
522void InstantController::ClearBlacklist() {
523 blacklisted_ids_.clear();
524}
[email protected]804d6c8f2010-10-08 02:49:50525
[email protected]f38adeeb2010-12-08 01:08:11526void InstantController::ScheduleDestroy(InstantLoader* loader) {
527 loaders_to_destroy_.push_back(loader);
[email protected]c90388e32011-11-29 02:18:47528 if (!weak_factory_.HasWeakPtrs()) {
[email protected]f38adeeb2010-12-08 01:08:11529 MessageLoop::current()->PostTask(
[email protected]c90388e32011-11-29 02:18:47530 FROM_HERE, base::Bind(&InstantController::DestroyLoaders,
531 weak_factory_.GetWeakPtr()));
[email protected]f38adeeb2010-12-08 01:08:11532 }
533}
534
535void InstantController::DestroyLoaders() {
536 loaders_to_destroy_.reset();
537}