172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Use of this source code is governed by a BSD-style license that can be
3731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// found in the LICENSE file.
4731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
5731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/instant/instant_controller.h"
6731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
7731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/command_line.h"
8201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "base/message_loop.h"
94a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "base/metrics/histogram.h"
10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "build/build_config.h"
11513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/autocomplete/autocomplete_match.h"
12731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/instant/instant_delegate.h"
13731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/instant/instant_loader.h"
14731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/instant/instant_loader_manager.h"
154a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/instant/promo_counter.h"
16513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/platform_util.h"
17731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/prefs/pref_service.h"
1821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
19731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/search_engines/template_url.h"
20731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/search_engines/template_url_model.h"
2121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
22731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/common/chrome_switches.h"
23731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/common/pref_names.h"
24731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/common/url_constants.h"
25dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_widget_host_view.h"
26dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h"
27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_service.h"
28731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
29731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Number of ms to delay between loading urls.
30731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickstatic const int kUpdateDelayMS = 200;
31731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Amount of time we delay before showing pages that have a non-200 status.
33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic const int kShowDelayMS = 800;
34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
35201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// static
36201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochInstantController::HostBlacklist* InstantController::host_blacklist_ = NULL;
374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben MurdochInstantController::InstantController(Profile* profile,
394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                                     InstantDelegate* delegate)
404a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    : delegate_(delegate),
414a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      tab_contents_(NULL),
424a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      is_active_(false),
43dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      displayable_loader_(NULL),
444a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      commit_on_mouse_up_(false),
454a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      last_transition_type_(PageTransition::LINK),
4672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      ALLOW_THIS_IN_INITIALIZER_LIST(destroy_factory_(this)) {
474a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  PrefService* service = profile->GetPrefs();
484a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (service) {
494a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    // kInstantWasEnabledOnce was added after instant, set it now to make sure
504a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    // it is correctly set.
514a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    service->SetBoolean(prefs::kInstantEnabledOnce, true);
524a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
534a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
544a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
554a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben MurdochInstantController::~InstantController() {
564a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
574a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
58731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// static
59731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid InstantController::RegisterUserPrefs(PrefService* prefs) {
60731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  prefs->RegisterBooleanPref(prefs::kInstantConfirmDialogShown, false);
61731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  prefs->RegisterBooleanPref(prefs::kInstantEnabled, false);
624a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  prefs->RegisterBooleanPref(prefs::kInstantEnabledOnce, false);
634a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  prefs->RegisterInt64Pref(prefs::kInstantEnabledTime, false);
644a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  PromoCounter::RegisterUserPrefs(prefs, prefs::kInstantPromo);
654a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
664a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
674a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// static
684a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid InstantController::RecordMetrics(Profile* profile) {
694a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (!IsEnabled(profile))
704a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    return;
714a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
724a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  PrefService* service = profile->GetPrefs();
734a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (service) {
744a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    int64 enable_time = service->GetInt64(prefs::kInstantEnabledTime);
754a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    if (!enable_time) {
764a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      service->SetInt64(prefs::kInstantEnabledTime,
774a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                        base::Time::Now().ToInternalValue());
784a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    } else {
794a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      base::TimeDelta delta =
804a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch          base::Time::Now() - base::Time::FromInternalValue(enable_time);
814a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      // Histogram from 1 hour to 30 days.
8272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      UMA_HISTOGRAM_CUSTOM_COUNTS("Instant.EnabledTime.Predictive",
8372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                  delta.InHours(), 1, 30 * 24, 50);
844a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    }
854a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
86731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
87731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
88731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// static
89731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool InstantController::IsEnabled(Profile* profile) {
9072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  PrefService* prefs = profile->GetPrefs();
9172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return prefs->GetBoolean(prefs::kInstantEnabled);
92513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
93513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
944a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// static
954a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid InstantController::Enable(Profile* profile) {
964a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  PromoCounter* promo_counter = profile->GetInstantPromoCounter();
974a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (promo_counter)
984a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    promo_counter->Hide();
994a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1004a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  PrefService* service = profile->GetPrefs();
1014a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (!service)
1024a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    return;
1034a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1044a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  service->SetBoolean(prefs::kInstantEnabled, true);
1054a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  service->SetBoolean(prefs::kInstantConfirmDialogShown, true);
1064a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  service->SetInt64(prefs::kInstantEnabledTime,
1074a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                    base::Time::Now().ToInternalValue());
1084a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  service->SetBoolean(prefs::kInstantEnabledOnce, true);
109731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
110731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
1114a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// static
1124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid InstantController::Disable(Profile* profile) {
1134a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  PrefService* service = profile->GetPrefs();
114201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (!service || !IsEnabled(profile))
1154a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    return;
1164a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1174a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  int64 enable_time = service->GetInt64(prefs::kInstantEnabledTime);
118201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (enable_time) {
119201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    base::TimeDelta delta =
120201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        base::Time::Now() - base::Time::FromInternalValue(enable_time);
121201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // Histogram from 1 minute to 10 days.
12272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    UMA_HISTOGRAM_CUSTOM_COUNTS("Instant.TimeToDisable.Predictive",
12372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                delta.InMinutes(), 1, 60 * 24 * 10, 50);
124201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
1254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
126201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  service->SetBoolean(prefs::kInstantEnabled, false);
127731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
128731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
12921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// static
13021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool InstantController::CommitIfCurrent(InstantController* controller) {
13121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (controller && controller->IsCurrent()) {
13221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    controller->CommitCurrentPreview(INSTANT_COMMIT_PRESSED_ENTER);
13321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return true;
13421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
13521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return false;
13621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
13721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
138201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid InstantController::Update(TabContentsWrapper* tab_contents,
139731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                               const AutocompleteMatch& match,
140731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                               const string16& user_text,
141201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                               bool verbatim,
142731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                               string16* suggested_text) {
143201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  suggested_text->clear();
144201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
145731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (tab_contents != tab_contents_)
146731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    DestroyPreviewContents();
147731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
148731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  const GURL& url = match.destination_url;
149731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  tab_contents_ = tab_contents;
150731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  commit_on_mouse_up_ = false;
151731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  last_transition_type_ = match.transition;
152201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  const TemplateURL* template_url = NULL;
153731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
154201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (url.is_empty() || !url.is_valid()) {
155201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // Assume we were invoked with GURL() and should destroy all.
156731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    DestroyPreviewContents();
157731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return;
158731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
159731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
160201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (!ShouldShowPreviewFor(match, &template_url)) {
161dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DestroyPreviewContentsAndLeaveActive();
162201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return;
163201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
164731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
165731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (!loader_manager_.get())
166731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    loader_manager_.reset(new InstantLoaderManager(this));
167731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
168201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (!is_active_) {
169201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    is_active_ = true;
1704a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    delegate_->PrepareForInstant();
171201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
172201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
173201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  TemplateURLID template_url_id = template_url ? template_url->id() : 0;
174201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Verbatim only makes sense if the search engines supports instant.
175201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  bool real_verbatim = template_url_id ? verbatim : false;
1764a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
177731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (ShouldUpdateNow(template_url_id, match.destination_url)) {
178731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    UpdateLoader(template_url, match.destination_url, match.transition,
179201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                 user_text, real_verbatim, suggested_text);
180731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  } else {
181731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    ScheduleUpdate(match.destination_url);
182731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
183731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
184731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  NotificationService::current()->Notify(
185731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      NotificationType::INSTANT_CONTROLLER_UPDATED,
186731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      Source<InstantController>(this),
187731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      NotificationService::NoDetails());
188731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
189731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
190731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid InstantController::SetOmniboxBounds(const gfx::Rect& bounds) {
191731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (omnibox_bounds_ == bounds)
192731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return;
193731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
194201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Always track the omnibox bounds. That way if Update is later invoked the
195201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // bounds are in sync.
196201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  omnibox_bounds_ = bounds;
197731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (loader_manager_.get()) {
198731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (loader_manager_->current_loader())
199731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      loader_manager_->current_loader()->SetOmniboxBounds(bounds);
200731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (loader_manager_->pending_loader())
201731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      loader_manager_->pending_loader()->SetOmniboxBounds(bounds);
202731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
203731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
204731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
205731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid InstantController::DestroyPreviewContents() {
206731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (!loader_manager_.get()) {
207731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // We're not showing anything, nothing to do.
208731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return;
209731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
210731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
211201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // ReleasePreviewContents sets is_active_ to false, but we need to set it
2123f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  // before notifying the delegate, otherwise if the delegate asks for the state
2133f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  // we'll still be active.
214201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  is_active_ = false;
215731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  delegate_->HideInstant();
216731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  delete ReleasePreviewContents(INSTANT_COMMIT_DESTROY);
217731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
218731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
219dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid InstantController::DestroyPreviewContentsAndLeaveActive() {
220dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  commit_on_mouse_up_ = false;
221dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (displayable_loader_) {
222dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    displayable_loader_ = NULL;
223dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    delegate_->HideInstant();
224dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
225dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
226dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // TODO(sky): this shouldn't nuke the loader. It should just nuke non-instant
227dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // loaders and hide instant loaders.
228dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  loader_manager_.reset(new InstantLoaderManager(this));
229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  show_timer_.Stop();
230dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  update_timer_.Stop();
231dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
232dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
233731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool InstantController::IsCurrent() {
234201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return loader_manager_.get() && loader_manager_->active_loader() &&
235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      loader_manager_->active_loader()->ready() &&
236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      !loader_manager_->active_loader()->needs_reload() &&
237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      !update_timer_.IsRunning();
238731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
239731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
240731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid InstantController::CommitCurrentPreview(InstantCommitType type) {
241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (type == INSTANT_COMMIT_PRESSED_ENTER && show_timer_.IsRunning()) {
242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // The user pressed enter and the show timer is running. This means the
243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // pending_loader returned an error code and we're not showing it. Force it
244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // to be shown.
245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    show_timer_.Stop();
246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ShowTimerFired();
247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
248731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(loader_manager_.get());
249731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(loader_manager_->current_loader());
250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool showing_instant =
251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      loader_manager_->current_loader()->is_showing_instant();
252201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  TabContentsWrapper* tab = ReleasePreviewContents(type);
253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // If the loader was showing an instant page then it's navigation stack is
254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // something like: search-engine-home-page (eg google.com) search-term1
255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // search-term2 .... Each search-term navigation corresponds to the page
256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // deciding enough time has passed to commit a navigation. We don't want the
257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // searche-engine-home-page navigation in this case so we pass true to
258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // CopyStateFromAndPrune to have the search-engine-home-page navigation
259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // removed.
260ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  tab->controller().CopyStateFromAndPrune(
261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      &tab_contents_->controller(), showing_instant);
262731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  delegate_->CommitInstant(tab);
263201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  CompleteRelease(tab->tab_contents());
264731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
265731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
266731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid InstantController::SetCommitOnMouseUp() {
267731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  commit_on_mouse_up_ = true;
268731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
269731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
270731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool InstantController::IsMouseDownFromActivate() {
271731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(loader_manager_.get());
272731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(loader_manager_->current_loader());
273731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return loader_manager_->current_loader()->IsMouseDownFromActivate();
274731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
275731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
276dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(OS_MACOSX)
277dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid InstantController::OnAutocompleteLostFocus(
278dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    gfx::NativeView view_gaining_focus) {
279dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // If |IsMouseDownFromActivate()| returns false, the RenderWidgetHostView did
280dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // not receive a mouseDown event.  Therefore, we should destroy the preview.
281dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Otherwise, the RWHV was clicked, so we commit the preview.
282dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!is_displayable() || !GetPreviewContents() ||
283dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      !IsMouseDownFromActivate()) {
284dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DestroyPreviewContents();
285dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  } else if (IsShowingInstant()) {
286dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    SetCommitOnMouseUp();
287dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  } else {
288dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CommitCurrentPreview(INSTANT_COMMIT_FOCUS_LOST);
289dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
290dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
291dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#else
292513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid InstantController::OnAutocompleteLostFocus(
293513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    gfx::NativeView view_gaining_focus) {
294201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (!is_active() || !GetPreviewContents()) {
295201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    DestroyPreviewContents();
296513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return;
297201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
298513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
299513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  RenderWidgetHostView* rwhv =
300201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      GetPreviewContents()->tab_contents()->GetRenderWidgetHostView();
3014a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (!view_gaining_focus || !rwhv) {
3024a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    DestroyPreviewContents();
3034a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    return;
3044a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
305513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
306201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  gfx::NativeView tab_view =
307201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      GetPreviewContents()->tab_contents()->GetNativeView();
308513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Focus is going to the renderer.
309513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (rwhv->GetNativeView() == view_gaining_focus ||
310513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      tab_view == view_gaining_focus) {
311513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (!IsMouseDownFromActivate()) {
312513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      // If the mouse is not down, focus is not going to the renderer. Someone
313513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      // else moved focus and we shouldn't commit.
3144a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      DestroyPreviewContents();
3154a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      return;
316513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
317513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
318513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (IsShowingInstant()) {
319513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      // We're showing instant results. As instant results may shift when
320513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      // committing we commit on the mouse up. This way a slow click still
321513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      // works fine.
3224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      SetCommitOnMouseUp();
3234a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      return;
324513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
325513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
3264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    CommitCurrentPreview(INSTANT_COMMIT_FOCUS_LOST);
3274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    return;
328513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
329513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
330513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Walk up the view hierarchy. If the view gaining focus is a subview of the
331513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // TabContents view (such as a windowed plugin or http auth dialog), we want
332513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // to keep the preview contents. Otherwise, focus has gone somewhere else,
333513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // such as the JS inspector, and we want to cancel the preview.
334513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  gfx::NativeView view_gaining_focus_ancestor = view_gaining_focus;
335513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  while (view_gaining_focus_ancestor &&
336513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch         view_gaining_focus_ancestor != tab_view) {
337513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    view_gaining_focus_ancestor =
338513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        platform_util::GetParent(view_gaining_focus_ancestor);
339513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
340513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
3414a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (view_gaining_focus_ancestor) {
3424a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    CommitCurrentPreview(INSTANT_COMMIT_FOCUS_LOST);
3434a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    return;
3444a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
345513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
3464a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  DestroyPreviewContents();
347513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
348dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif
349513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
350201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochTabContentsWrapper* InstantController::ReleasePreviewContents(
351201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    InstantCommitType type) {
352731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (!loader_manager_.get())
353731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return NULL;
354731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
355ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Make sure the pending loader is active. Ideally we would call
356ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // ShowTimerFired, but if Release is invoked from the browser we don't want to
357ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // attempt to show the tab contents (since its being added to a new tab).
358ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (type == INSTANT_COMMIT_PRESSED_ENTER && show_timer_.IsRunning()) {
359ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    InstantLoader* loader = loader_manager_->active_loader();
360ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (loader && loader->ready() &&
361ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        loader == loader_manager_->pending_loader()) {
362ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      scoped_ptr<InstantLoader> old_loader;
363ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      loader_manager_->MakePendingCurrent(&old_loader);
364ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
365ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
366ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
367201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Loader may be null if the url blacklisted instant.
368201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<InstantLoader> loader;
369201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (loader_manager_->current_loader())
370201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    loader.reset(loader_manager_->ReleaseCurrentLoader());
371201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  TabContentsWrapper* tab = loader.get() ?
372201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      loader->ReleasePreviewContents(type) : NULL;
373731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
374731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ClearBlacklist();
375731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  is_active_ = false;
376dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  displayable_loader_ = NULL;
377731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  commit_on_mouse_up_ = false;
378201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  omnibox_bounds_ = gfx::Rect();
379201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  loader_manager_.reset();
380731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  update_timer_.Stop();
381ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  show_timer_.Stop();
382731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return tab;
383731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
384731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
385731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid InstantController::CompleteRelease(TabContents* tab) {
386731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  tab->SetAllContentsBlocked(false);
387731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
388731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
389201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochTabContentsWrapper* InstantController::GetPreviewContents() {
390201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return loader_manager_.get() && loader_manager_->current_loader() ?
391731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      loader_manager_->current_loader()->preview_contents() : NULL;
392731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
393731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
394731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool InstantController::IsShowingInstant() {
395201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return loader_manager_.get() && loader_manager_->current_loader() &&
396731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      loader_manager_->current_loader()->is_showing_instant();
397731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
398731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
399201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochbool InstantController::MightSupportInstant() {
400201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return loader_manager_.get() && loader_manager_->active_loader() &&
401201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      loader_manager_->active_loader()->is_showing_instant();
402201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
403201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
40472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenGURL InstantController::GetCurrentURL() {
40572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return loader_manager_.get() && loader_manager_->active_loader() ?
40672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      loader_manager_->active_loader()->url() : GURL();
40772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
40872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
409ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid InstantController::InstantStatusChanged(InstantLoader* loader) {
410ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!loader->http_status_ok()) {
411ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Status isn't ok, start a timer that when fires shows the result. This
412ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // delays showing 403 pages and the like.
413ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    show_timer_.Stop();
414ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    show_timer_.Start(
415ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        base::TimeDelta::FromMilliseconds(kShowDelayMS),
416ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        this, &InstantController::ShowTimerFired);
417ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    UpdateDisplayableLoader();
418dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return;
419731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
420513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
421ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ProcessInstantStatusChanged(loader);
422731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
423731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
424ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid InstantController::SetSuggestedTextFor(
425ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    InstantLoader* loader,
426ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const string16& text,
427ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    InstantCompleteBehavior behavior) {
428731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (loader_manager_->current_loader() == loader)
429ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    delegate_->SetSuggestedText(text, behavior);
430731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
431731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
432731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickgfx::Rect InstantController::GetInstantBounds() {
433731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return delegate_->GetInstantBounds();
434731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
435731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
436731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool InstantController::ShouldCommitInstantOnMouseUp() {
437731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return commit_on_mouse_up_;
438731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
439731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
440731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid InstantController::CommitInstantLoader(InstantLoader* loader) {
441731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (loader_manager_.get() && loader_manager_->current_loader() == loader) {
442731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    CommitCurrentPreview(INSTANT_COMMIT_FOCUS_LOST);
443731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  } else {
444731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // This can happen if the mouse was down, we swapped out the preview and
445731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // the mouse was released. Generally this shouldn't happen, but if it does
446731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // revert.
447731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    DestroyPreviewContents();
448731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
449731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
450731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
451731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid InstantController::InstantLoaderDoesntSupportInstant(
452201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    InstantLoader* loader) {
453731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(!loader->ready());  // We better not be showing this loader.
454731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(loader->template_url_id());
455731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
456201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  VLOG(1) << "provider does not support instant";
457201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
458201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Don't attempt to use instant for this search engine again.
459731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  BlacklistFromInstant(loader->template_url_id());
460731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
461ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Because of the state of the stack we can't destroy the loader now.
462ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool was_pending = loader_manager_->pending_loader() == loader;
463ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ScheduleDestroy(loader_manager_->ReleaseLoader(loader));
464ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (was_pending) {
465ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // |loader| was the pending loader. We may be showing another TabContents to
466ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // the user (what was current). Destroy it.
467dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DestroyPreviewContentsAndLeaveActive();
468731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  } else {
469ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // |loader| wasn't pending, yet it may still be the displayed loader.
470dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    UpdateDisplayableLoader();
471731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
472731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
473731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
474201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid InstantController::AddToBlacklist(InstantLoader* loader, const GURL& url) {
475201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::string host = url.host();
476201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (host.empty())
477201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return;
478201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
479201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (!host_blacklist_)
480201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    host_blacklist_ = new HostBlacklist;
481201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  host_blacklist_->insert(host);
482201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
483201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (!loader_manager_.get())
484201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return;
485201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
486201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Because of the state of the stack we can't destroy the loader now.
487201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  ScheduleDestroy(loader);
488201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
489201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  loader_manager_->ReleaseLoader(loader);
490dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
491dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  UpdateDisplayableLoader();
492201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
493201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
494dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid InstantController::UpdateDisplayableLoader() {
495dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  InstantLoader* loader = NULL;
496dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // As soon as the pending loader is displayable it becomes the current loader,
497dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // so we need only concern ourselves with the current loader here.
498dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (loader_manager_.get() && loader_manager_->current_loader() &&
499ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      loader_manager_->current_loader()->ready() &&
500ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      (!show_timer_.IsRunning() ||
501ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       loader_manager_->current_loader()->http_status_ok())) {
502dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    loader = loader_manager_->current_loader();
503dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
504dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (loader == displayable_loader_)
505dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return;
506201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
507dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  displayable_loader_ = loader;
508dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
509dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!displayable_loader_) {
510dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    delegate_->HideInstant();
511dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  } else {
512dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    delegate_->ShowInstant(displayable_loader_->preview_contents());
513dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    NotificationService::current()->Notify(
514dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        NotificationType::INSTANT_CONTROLLER_SHOWN,
515dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        Source<InstantController>(this),
516dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        NotificationService::NoDetails());
517dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
518201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
519201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
520201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochTabContentsWrapper* InstantController::GetPendingPreviewContents() {
521201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return loader_manager_.get() && loader_manager_->pending_loader() ?
522201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      loader_manager_->pending_loader()->preview_contents() : NULL;
523201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
524201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
525731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool InstantController::ShouldUpdateNow(TemplateURLID instant_id,
526731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                        const GURL& url) {
527731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(loader_manager_.get());
528731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
529731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (instant_id) {
530731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // Update sites that support instant immediately, they can do their own
531731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // throttling.
532731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return true;
533731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
534731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
535731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (url.SchemeIsFile())
536731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return true;  // File urls should load quickly, so don't delay loading them.
537731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
538731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (loader_manager_->WillUpateChangeActiveLoader(instant_id)) {
539731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // If Update would change loaders, update now. This indicates transitioning
540731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // from an instant to non-instant loader.
541731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return true;
542731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
543731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
544731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  InstantLoader* active_loader = loader_manager_->active_loader();
545731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // WillUpateChangeActiveLoader should return true if no active loader, so
546731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // we know there will be an active loader if we get here.
547731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(active_loader);
548201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Immediately update if the url is the same (which should result in nothing
549201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // happening) or the hosts differ, otherwise we'll delay the update.
550201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return (active_loader->url() == url) ||
551201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      (active_loader->url().host() != url.host());
552731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
553731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
554731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid InstantController::ScheduleUpdate(const GURL& url) {
555731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  scheduled_url_ = url;
556731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
557dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  update_timer_.Stop();
558731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  update_timer_.Start(base::TimeDelta::FromMilliseconds(kUpdateDelayMS),
559731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                      this, &InstantController::ProcessScheduledUpdate);
560731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
561731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
562731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid InstantController::ProcessScheduledUpdate() {
563731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(loader_manager_.get());
564731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
565731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // We only delay loading of sites that don't support instant, so we can ignore
566731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // suggested_text here.
567731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  string16 suggested_text;
568201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  UpdateLoader(NULL, scheduled_url_, last_transition_type_, string16(), false,
569731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick               &suggested_text);
570731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
571731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
572ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid InstantController::ProcessInstantStatusChanged(InstantLoader* loader) {
573ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(loader_manager_.get());
574ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_ptr<InstantLoader> old_loader;
575ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (loader == loader_manager_->pending_loader()) {
576ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    loader_manager_->MakePendingCurrent(&old_loader);
577ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else if (loader != loader_manager_->current_loader()) {
578ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Notification from a loader that is no longer the current (either we have
579ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // a pending, or its an instant loader). Ignore it.
580ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
581ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
582ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
583ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  UpdateDisplayableLoader();
584ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
585ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
586ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid InstantController::ShowTimerFired() {
587ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!loader_manager_.get())
588ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
589ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
590ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  InstantLoader* loader = loader_manager_->active_loader();
591ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (loader && loader->ready())
592ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ProcessInstantStatusChanged(loader);
593ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
594ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
595731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid InstantController::UpdateLoader(const TemplateURL* template_url,
596731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                     const GURL& url,
597731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                     PageTransition::Type transition_type,
598731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                     const string16& user_text,
599201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                     bool verbatim,
600731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                     string16* suggested_text) {
601731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  update_timer_.Stop();
602731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
603731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  scoped_ptr<InstantLoader> owned_loader;
604731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  TemplateURLID template_url_id = template_url ? template_url->id() : 0;
605731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  InstantLoader* new_loader =
606731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      loader_manager_->UpdateLoader(template_url_id, &owned_loader);
607731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
608731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  new_loader->SetOmniboxBounds(omnibox_bounds_);
609ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (new_loader->Update(tab_contents_, template_url, url, transition_type,
610ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                         user_text, verbatim, suggested_text)) {
611ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    show_timer_.Stop();
612ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!new_loader->http_status_ok()) {
613ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      show_timer_.Start(
614ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          base::TimeDelta::FromMilliseconds(kShowDelayMS),
615ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          this, &InstantController::ShowTimerFired);
616ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
617ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
618dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  UpdateDisplayableLoader();
619731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
620731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
621201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochbool InstantController::ShouldShowPreviewFor(const AutocompleteMatch& match,
622201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                             const TemplateURL** template_url) {
623201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  const TemplateURL* t_url = GetTemplateURL(match);
624201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (t_url) {
625201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (!t_url->id() ||
626201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        !t_url->instant_url() ||
627201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        IsBlacklistedFromInstant(t_url->id()) ||
628201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        !t_url->instant_url()->SupportsReplacement()) {
629201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      // To avoid extra load on other search engines we only enable previews if
630201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      // they support the instant API.
631201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      return false;
632201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    }
633201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
634201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  *template_url = t_url;
635201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
6364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (match.destination_url.SchemeIs(chrome::kJavaScriptScheme))
6374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    return false;
6384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
6394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // Extension keywords don't have a real destionation URL.
6404a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (match.template_url && match.template_url->IsExtensionKeyword())
6414a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    return false;
6424a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
643201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Was the host blacklisted?
644201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (host_blacklist_ && host_blacklist_->count(match.destination_url.host()))
645201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return false;
646201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
6474a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  return true;
648731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
649731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
650731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid InstantController::BlacklistFromInstant(TemplateURLID id) {
651731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  blacklisted_ids_.insert(id);
652731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
653731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
654731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool InstantController::IsBlacklistedFromInstant(TemplateURLID id) {
655731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return blacklisted_ids_.count(id) > 0;
656731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
657731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
658731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid InstantController::ClearBlacklist() {
659731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  blacklisted_ids_.clear();
660731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
661731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
662201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid InstantController::ScheduleDestroy(InstantLoader* loader) {
663201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  loaders_to_destroy_.push_back(loader);
664201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (destroy_factory_.empty()) {
665201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    MessageLoop::current()->PostTask(
666201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        FROM_HERE, destroy_factory_.NewRunnableMethod(
667201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch            &InstantController::DestroyLoaders));
668201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
669201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
670201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
671201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid InstantController::DestroyLoaders() {
672201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  loaders_to_destroy_.reset();
673201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
674201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
675731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickconst TemplateURL* InstantController::GetTemplateURL(
676731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const AutocompleteMatch& match) {
677731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  const TemplateURL* template_url = match.template_url;
678731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (match.type == AutocompleteMatch::SEARCH_WHAT_YOU_TYPED ||
679731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      match.type == AutocompleteMatch::SEARCH_HISTORY ||
680731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      match.type == AutocompleteMatch::SEARCH_SUGGEST) {
681731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    TemplateURLModel* model = tab_contents_->profile()->GetTemplateURLModel();
682731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    template_url = model ? model->GetDefaultSearchProvider() : NULL;
683731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
684201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return template_url;
685201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
686