Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(71)

Side by Side Diff: chrome/browser/instant/instant_controller.cc

Issue 11824050: InstantExtended: Committed NTP (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Undo to fix blacklisting. Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/instant/instant_controller.h" 5 #include "chrome/browser/instant/instant_controller.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/metrics/histogram.h" 8 #include "base/metrics/histogram.h"
9 #include "base/string_util.h" 9 #include "base/string_util.h"
10 #include "base/stringprintf.h" 10 #include "base/stringprintf.h"
11 #include "base/utf_string_conversions.h" 11 #include "base/utf_string_conversions.h"
12 #include "chrome/browser/autocomplete/autocomplete_provider.h" 12 #include "chrome/browser/autocomplete/autocomplete_provider.h"
13 #include "chrome/browser/google/google_util.h" 13 #include "chrome/browser/google/google_util.h"
14 #include "chrome/browser/history/history_service.h" 14 #include "chrome/browser/history/history_service.h"
15 #include "chrome/browser/history/history_service_factory.h" 15 #include "chrome/browser/history/history_service_factory.h"
16 #include "chrome/browser/history/history_tab_helper.h" 16 #include "chrome/browser/history/history_tab_helper.h"
17 #include "chrome/browser/instant/instant_loader.h" 17 #include "chrome/browser/instant/instant_ntp.h"
18 #include "chrome/browser/instant/instant_overlay.h"
18 #include "chrome/browser/instant/instant_tab.h" 19 #include "chrome/browser/instant/instant_tab.h"
19 #include "chrome/browser/platform_util.h" 20 #include "chrome/browser/platform_util.h"
20 #include "chrome/browser/search_engines/template_url_service.h" 21 #include "chrome/browser/search_engines/template_url_service.h"
21 #include "chrome/browser/search_engines/template_url_service_factory.h" 22 #include "chrome/browser/search_engines/template_url_service_factory.h"
22 #include "chrome/browser/ui/browser_instant_controller.h" 23 #include "chrome/browser/ui/browser_instant_controller.h"
23 #include "chrome/browser/ui/search/search_tab_helper.h" 24 #include "chrome/browser/ui/search/search_tab_helper.h"
24 #include "chrome/common/chrome_notification_types.h" 25 #include "chrome/common/chrome_notification_types.h"
25 #include "chrome/common/chrome_switches.h" 26 #include "chrome/common/chrome_switches.h"
27 #include "chrome/common/url_constants.h"
26 #include "content/public/browser/navigation_entry.h" 28 #include "content/public/browser/navigation_entry.h"
27 #include "content/public/browser/notification_service.h" 29 #include "content/public/browser/notification_service.h"
28 #include "content/public/browser/render_widget_host_view.h" 30 #include "content/public/browser/render_widget_host_view.h"
29 #include "content/public/browser/web_contents.h" 31 #include "content/public/browser/web_contents.h"
30 #include "net/base/escape.h" 32 #include "net/base/escape.h"
31 #include "third_party/icu/public/common/unicode/normalizer2.h" 33 #include "third_party/icu/public/common/unicode/normalizer2.h"
32 34
33 #if defined(TOOLKIT_VIEWS) 35 #if defined(TOOLKIT_VIEWS)
34 #include "ui/views/widget/widget.h" 36 #include "ui/views/widget/widget.h"
35 #endif 37 #endif
36 38
37 namespace { 39 namespace {
38 40
39 // An artificial delay (in milliseconds) we introduce before telling the Instant 41 // An artificial delay (in milliseconds) we introduce before telling the Instant
40 // page about the new omnibox bounds, in cases where the bounds shrink. This is 42 // page about the new omnibox bounds, in cases where the bounds shrink. This is
41 // to avoid the page jumping up/down very fast in response to bounds changes. 43 // to avoid the page jumping up/down very fast in response to bounds changes.
42 const int kUpdateBoundsDelayMS = 1000; 44 const int kUpdateBoundsDelayMS = 1000;
43 45
44 // The maximum number of times we'll load a non-Instant-supporting search engine 46 // The maximum number of times we'll load a non-Instant-supporting search engine
45 // before we give up and blacklist it for the rest of the browsing session. 47 // before we give up and blacklist it for the rest of the browsing session.
46 const int kMaxInstantSupportFailures = 10; 48 const int kMaxInstantSupportFailures = 10;
47 49
48 // If an Instant page has not been used in these many milliseconds, it is
49 // reloaded so that the page does not become stale.
50 const int kStaleLoaderTimeoutMS = 3 * 3600 * 1000;
51
52 // For reporting events of interest. 50 // For reporting events of interest.
53 enum InstantControllerEvent { 51 enum InstantControllerEvent {
54 INSTANT_CONTROLLER_EVENT_URL_ADDED_TO_BLACKLIST = 0, 52 INSTANT_CONTROLLER_EVENT_URL_ADDED_TO_BLACKLIST = 0,
55 INSTANT_CONTROLLER_EVENT_URL_REMOVED_FROM_BLACKLIST = 1, 53 INSTANT_CONTROLLER_EVENT_URL_REMOVED_FROM_BLACKLIST = 1,
56 INSTANT_CONTROLLER_EVENT_URL_BLOCKED_BY_BLACKLIST = 2, 54 INSTANT_CONTROLLER_EVENT_URL_BLOCKED_BY_BLACKLIST = 2,
57 INSTANT_CONTROLLER_EVENT_MAX = 3, 55 INSTANT_CONTROLLER_EVENT_MAX = 3,
58 }; 56 };
59 57
60 void RecordEventHistogram(InstantControllerEvent event) { 58 void RecordEventHistogram(InstantControllerEvent event) {
61 UMA_HISTOGRAM_ENUMERATION("Instant.InstantControllerEvent", 59 UMA_HISTOGRAM_ENUMERATION("Instant.InstantControllerEvent",
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 return true; 151 return true;
154 } 152 }
155 153
156 return false; 154 return false;
157 } 155 }
158 156
159 bool IsFullHeight(const InstantModel& model) { 157 bool IsFullHeight(const InstantModel& model) {
160 return model.height() == 100 && model.height_units() == INSTANT_SIZE_PERCENT; 158 return model.height() == 100 && model.height_units() == INSTANT_SIZE_PERCENT;
161 } 159 }
162 160
161 bool IsContentsFrom(const InstantPage* page,
162 const content::WebContents* contents) {
163 return page && (page->contents() == contents);
164 }
165
163 } // namespace 166 } // namespace
164 167
165 // static 168 // static
166 const char* InstantController::kLocalOmniboxPopupURL = 169 const char* InstantController::kLocalOmniboxPopupURL =
167 "chrome://local-omnibox-popup/local-omnibox-popup.html"; 170 "chrome://local-omnibox-popup/local-omnibox-popup.html";
168 171
169 InstantController::InstantController(chrome::BrowserInstantController* browser, 172 InstantController::InstantController(chrome::BrowserInstantController* browser,
170 bool extended_enabled) 173 bool extended_enabled)
171 : browser_(browser), 174 : browser_(browser),
172 extended_enabled_(extended_enabled), 175 extended_enabled_(extended_enabled),
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 is_keyword_search)); 213 is_keyword_search));
211 214
212 // TODO(dhollowa): Complete keyword match UI. For now just hide suggestions. 215 // TODO(dhollowa): Complete keyword match UI. For now just hide suggestions.
213 // http://crbug.com/153932. Note, this early escape is happens prior to the 216 // http://crbug.com/153932. Note, this early escape is happens prior to the
214 // DCHECKs below because |user_text| and |full_text| have different semantics 217 // DCHECKs below because |user_text| and |full_text| have different semantics
215 // when keyword search is in effect. 218 // when keyword search is in effect.
216 if (is_keyword_search) { 219 if (is_keyword_search) {
217 if (instant_tab_) 220 if (instant_tab_)
218 instant_tab_->Update(string16(), 0, 0, true); 221 instant_tab_->Update(string16(), 0, 0, true);
219 else 222 else
220 HideLoader(); 223 HideOverlay();
221 last_match_was_search_ = false; 224 last_match_was_search_ = false;
222 return false; 225 return false;
223 } 226 }
224 227
225 // If the popup is open, the user has to be typing. 228 // If the popup is open, the user has to be typing.
226 DCHECK(!omnibox_popup_is_open || user_input_in_progress); 229 DCHECK(!omnibox_popup_is_open || user_input_in_progress);
227 230
228 // If the popup is closed, there should be no inline autocompletion. 231 // If the popup is closed, there should be no inline autocompletion.
229 DCHECK(omnibox_popup_is_open || user_text.empty() || user_text == full_text) 232 DCHECK(omnibox_popup_is_open || user_text.empty() || user_text == full_text)
230 << user_text << "|" << full_text; 233 << user_text << "|" << full_text;
231 234
232 // If there's no text in the omnibox, the user can't have typed any. 235 // If there's no text in the omnibox, the user can't have typed any.
233 DCHECK(!full_text.empty() || user_text.empty()) << user_text; 236 DCHECK(!full_text.empty() || user_text.empty()) << user_text;
234 237
235 // If the user isn't typing, and the popup is closed, there can't be any 238 // If the user isn't typing, and the popup is closed, there can't be any
236 // user-typed text. 239 // user-typed text.
237 DCHECK(user_input_in_progress || omnibox_popup_is_open || user_text.empty()) 240 DCHECK(user_input_in_progress || omnibox_popup_is_open || user_text.empty())
238 << user_text; 241 << user_text;
239 242
240 // The preview is being clicked and will commit soon. Don't change anything. 243 // The preview is being clicked and will commit soon. Don't change anything.
241 // TODO(sreeram): Add a browser test for this. 244 // TODO(sreeram): Add a browser test for this.
242 if (loader_ && loader_->is_pointer_down_from_activate()) 245 if (overlay_ && overlay_->is_pointer_down_from_activate())
243 return false; 246 return false;
244 247
245 // In non-extended mode, SearchModeChanged() is never called, so fake it. The 248 // In non-extended mode, SearchModeChanged() is never called, so fake it. The
246 // mode is set to "disallow suggestions" here, so that if one of the early 249 // mode is set to "disallow suggestions" here, so that if one of the early
247 // "return false" conditions is hit, suggestions will be disallowed. If the 250 // "return false" conditions is hit, suggestions will be disallowed. If the
248 // query is sent to the loader, the mode is set to "allow" further below. 251 // query is sent to the overlay, the mode is set to "allow" further below.
249 if (!extended_enabled_) 252 if (!extended_enabled_)
250 search_mode_.mode = chrome::search::Mode::MODE_DEFAULT; 253 search_mode_.mode = chrome::search::Mode::MODE_DEFAULT;
251 254
252 last_match_was_search_ = AutocompleteMatch::IsSearchType(match.type) && 255 last_match_was_search_ = AutocompleteMatch::IsSearchType(match.type) &&
253 !user_text.empty(); 256 !user_text.empty();
254 257
255 // In non extended mode, Instant is disabled for URLs and keyword mode. 258 // In non extended mode, Instant is disabled for URLs and keyword mode.
256 if (!extended_enabled_ && 259 if (!extended_enabled_ &&
257 (!last_match_was_search_ || 260 (!last_match_was_search_ ||
258 match.type == AutocompleteMatch::SEARCH_OTHER_ENGINE)) { 261 match.type == AutocompleteMatch::SEARCH_OTHER_ENGINE)) {
259 HideLoader(); 262 HideOverlay();
260 return false; 263 return false;
261 } 264 }
262 265
263 // If we have an |instant_tab_| use it, else ensure we have a loader that is 266 // If we have an |instant_tab_| use it, else ensure we have a overlay that is
264 // current or is using local preview. 267 // current or is using local preview.
265 if (!instant_tab_ && !(loader_ && loader_->IsUsingLocalPreview()) && 268 if (!instant_tab_ && !(overlay_ && overlay_->IsUsingLocalPreview()) &&
266 !EnsureLoaderIsCurrent(false)) { 269 !EnsureOverlayIsCurrent(false)) {
267 HideLoader(); 270 HideOverlay();
268 return false; 271 return false;
269 } 272 }
270 273
271 if (extended_enabled_) { 274 if (extended_enabled_) {
272 if (!omnibox_popup_is_open) { 275 if (!omnibox_popup_is_open) {
273 if (!user_input_in_progress) { 276 if (!user_input_in_progress) {
274 // If the user isn't typing and the omnibox popup is closed, it means a 277 // If the user isn't typing and the omnibox popup is closed, it means a
275 // regular navigation, tab-switch or the user hitting Escape. 278 // regular navigation, tab-switch or the user hitting Escape.
276 if (instant_tab_) { 279 if (instant_tab_) {
277 // The user is on a search results page. It may be showing results for 280 // The user is on a search results page. It may be showing results for
278 // a partial query the user typed before they hit Escape. Send the 281 // a partial query the user typed before they hit Escape. Send the
279 // omnibox text to the page to restore the original results. 282 // omnibox text to the page to restore the original results.
280 // 283 //
281 // In a tab switch, |instant_tab_| won't have updated yet, so it may 284 // In a tab switch, |instant_tab_| won't have updated yet, so it may
282 // be pointing to the previous tab (which was a search results page). 285 // be pointing to the previous tab (which was a search results page).
283 // Ensure we don't send the omnibox text to a random webpage (the new 286 // Ensure we don't send the omnibox text to a random webpage (the new
284 // tab), by comparing the old and new WebContents. 287 // tab), by comparing the old and new WebContents.
285 if (escape_pressed && 288 if (escape_pressed &&
286 instant_tab_->contents() == browser_->GetActiveWebContents()) { 289 instant_tab_->contents() == browser_->GetActiveWebContents()) {
287 instant_tab_->Submit(full_text); 290 instant_tab_->Submit(full_text);
288 } 291 }
289 } else if (!full_text.empty()) { 292 } else if (!full_text.empty()) {
290 // If |full_text| is empty, the user is on the NTP. The preview may 293 // If |full_text| is empty, the user is on the NTP. The preview may
291 // be showing custom NTP content; hide only if that's not the case. 294 // be showing custom NTP content; hide only if that's not the case.
292 HideLoader(); 295 HideOverlay();
293 } 296 }
294 } else if (full_text.empty()) { 297 } else if (full_text.empty()) {
295 // The user is typing, and backspaced away all omnibox text. Clear 298 // The user is typing, and backspaced away all omnibox text. Clear
296 // |last_omnibox_text_| so that we don't attempt to set suggestions. 299 // |last_omnibox_text_| so that we don't attempt to set suggestions.
297 last_omnibox_text_.clear(); 300 last_omnibox_text_.clear();
298 last_suggestion_ = InstantSuggestion(); 301 last_suggestion_ = InstantSuggestion();
299 if (instant_tab_) { 302 if (instant_tab_) {
300 // On a search results page, tell it to clear old results. 303 // On a search results page, tell it to clear old results.
301 instant_tab_->Update(string16(), 0, 0, true); 304 instant_tab_->Update(string16(), 0, 0, true);
302 } else if (search_mode_.is_origin_ntp()) { 305 } else if (search_mode_.is_origin_ntp()) {
303 // On the NTP, tell the preview to clear old results. Don't hide the 306 // On the NTP, tell the preview to clear old results. Don't hide the
304 // preview so it can show a blank page or logo if it wants. 307 // preview so it can show a blank page or logo if it wants.
305 loader_->Update(string16(), 0, 0, true); 308 overlay_->Update(string16(), 0, 0, true);
306 } else { 309 } else {
307 HideLoader(); 310 HideOverlay();
308 } 311 }
309 } else { 312 } else {
310 // The user switched to a tab with partial text already in the omnibox. 313 // The user switched to a tab with partial text already in the omnibox.
311 HideLoader(); 314 HideOverlay();
312 315
313 // The new tab may or may not be a search results page; we don't know 316 // The new tab may or may not be a search results page; we don't know
314 // since SearchModeChanged() hasn't been called yet. If it later turns 317 // since SearchModeChanged() hasn't been called yet. If it later turns
315 // out to be, we should store |full_text| now, so that if the user hits 318 // out to be, we should store |full_text| now, so that if the user hits
316 // Enter, we'll send the correct query to instant_tab_->Submit(). If the 319 // Enter, we'll send the correct query to instant_tab_->Submit(). If the
317 // partial text is not a query (|last_match_was_search_| is false), we 320 // partial text is not a query (|last_match_was_search_| is false), we
318 // won't Submit(), so no need to worry about that. 321 // won't Submit(), so no need to worry about that.
319 last_omnibox_text_ = full_text; 322 last_omnibox_text_ = full_text;
320 last_suggestion_ = InstantSuggestion(); 323 last_suggestion_ = InstantSuggestion();
321 } 324 }
322 return false; 325 return false;
323 } else if (full_text.empty()) { 326 } else if (full_text.empty()) {
324 // The user typed a solitary "?". Same as the backspace case above. 327 // The user typed a solitary "?". Same as the backspace case above.
325 last_omnibox_text_.clear(); 328 last_omnibox_text_.clear();
326 last_suggestion_ = InstantSuggestion(); 329 last_suggestion_ = InstantSuggestion();
327 if (instant_tab_) 330 if (instant_tab_)
328 instant_tab_->Update(string16(), 0, 0, true); 331 instant_tab_->Update(string16(), 0, 0, true);
329 else if (search_mode_.is_origin_ntp()) 332 else if (search_mode_.is_origin_ntp())
330 loader_->Update(string16(), 0, 0, true); 333 overlay_->Update(string16(), 0, 0, true);
331 else 334 else
332 HideLoader(); 335 HideOverlay();
333 return false; 336 return false;
334 } 337 }
335 } else if (!omnibox_popup_is_open || full_text.empty()) { 338 } else if (!omnibox_popup_is_open || full_text.empty()) {
336 // In the non-extended case, hide the preview as long as the user isn't 339 // In the non-extended case, hide the preview as long as the user isn't
337 // actively typing a non-empty query. 340 // actively typing a non-empty query.
338 HideLoader(); 341 HideOverlay();
339 return false; 342 return false;
340 } 343 }
341 344
342 last_omnibox_text_has_inline_autocompletion_ = user_text != full_text; 345 last_omnibox_text_has_inline_autocompletion_ = user_text != full_text;
343 346
344 // If the user continues typing the same query as the suggested text is 347 // If the user continues typing the same query as the suggested text is
345 // showing, reuse the suggestion (but only for INSTANT_COMPLETE_NEVER). 348 // showing, reuse the suggestion (but only for INSTANT_COMPLETE_NEVER).
346 bool reused_suggestion = false; 349 bool reused_suggestion = false;
347 if (last_suggestion_.behavior == INSTANT_COMPLETE_NEVER && 350 if (last_suggestion_.behavior == INSTANT_COMPLETE_NEVER &&
348 !last_omnibox_text_has_inline_autocompletion_) { 351 !last_omnibox_text_has_inline_autocompletion_) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 383
381 if (instant_tab_) { 384 if (instant_tab_) {
382 instant_tab_->Update(user_text, selection_start, selection_end, verbatim); 385 instant_tab_->Update(user_text, selection_start, selection_end, verbatim);
383 } else { 386 } else {
384 if (first_interaction_time_.is_null()) 387 if (first_interaction_time_.is_null())
385 first_interaction_time_ = base::Time::Now(); 388 first_interaction_time_ = base::Time::Now();
386 allow_preview_to_show_search_suggestions_ = true; 389 allow_preview_to_show_search_suggestions_ = true;
387 390
388 // For extended mode, if the loader is not ready at this point, switch over 391 // For extended mode, if the loader is not ready at this point, switch over
389 // to a backup loader. 392 // to a backup loader.
390 if (extended_enabled_ && !loader_->supports_instant() && 393 if (extended_enabled_ && !overlay_->supports_instant() &&
391 !loader_->IsUsingLocalPreview() && browser_->GetActiveWebContents()) { 394 !overlay_->IsUsingLocalPreview() && browser_->GetActiveWebContents()) {
392 CreateLoader(kLocalOmniboxPopupURL, browser_->GetActiveWebContents()); 395 CreateOverlay(kLocalOmniboxPopupURL, browser_->GetActiveWebContents());
393 } 396 }
394 397
395 loader_->Update(extended_enabled_ ? user_text : full_text, 398 overlay_->Update(extended_enabled_ ? user_text : full_text,
396 selection_start, selection_end, verbatim); 399 selection_start, selection_end, verbatim);
397 } 400 }
398 401
399 content::NotificationService::current()->Notify( 402 content::NotificationService::current()->Notify(
400 chrome::NOTIFICATION_INSTANT_CONTROLLER_UPDATED, 403 chrome::NOTIFICATION_INSTANT_CONTROLLER_UPDATED,
401 content::Source<InstantController>(this), 404 content::Source<InstantController>(this),
402 content::NotificationService::NoDetails()); 405 content::NotificationService::NoDetails());
403 406
404 // We don't have new suggestions yet, but we can either reuse the existing 407 // We don't have new suggestions yet, but we can either reuse the existing
405 // suggestion or reset the existing "gray text". 408 // suggestion or reset the existing "gray text".
406 browser_->SetInstantSuggestion(last_suggestion_); 409 browser_->SetInstantSuggestion(last_suggestion_);
407 410
408 return true; 411 return true;
409 } 412 }
410 413
414 scoped_ptr<content::WebContents> InstantController::ReleaseNTPContents() {
415 if (!extended_enabled_ || !ntp_)
416 return scoped_ptr<content::WebContents>(NULL);
417
418 LOG_INSTANT_DEBUG_EVENT(this, "ReleaseNTPContents");
419
420 scoped_ptr<content::WebContents> ntp_contents = ntp_->ReleaseContents();
421 ntp_.reset();
422 ResetNTP();
423 return ntp_contents.Pass();
424 }
425
411 // TODO(tonyg): This method only fires when the omnibox bounds change. It also 426 // TODO(tonyg): This method only fires when the omnibox bounds change. It also
412 // needs to fire when the preview bounds change (e.g.: open/close info bar). 427 // needs to fire when the preview bounds change (e.g.: open/close info bar).
413 void InstantController::SetPopupBounds(const gfx::Rect& bounds) { 428 void InstantController::SetPopupBounds(const gfx::Rect& bounds) {
414 if (!extended_enabled_ && !instant_enabled_) 429 if (!extended_enabled_ && !instant_enabled_)
415 return; 430 return;
416 431
417 if (popup_bounds_ == bounds) 432 if (popup_bounds_ == bounds)
418 return; 433 return;
419 434
420 popup_bounds_ = bounds; 435 popup_bounds_ = bounds;
421 if (popup_bounds_.height() > last_popup_bounds_.height()) { 436 if (popup_bounds_.height() > last_popup_bounds_.height()) {
422 update_bounds_timer_.Stop(); 437 update_bounds_timer_.Stop();
423 SendPopupBoundsToPage(); 438 SendPopupBoundsToPage();
424 } else if (!update_bounds_timer_.IsRunning()) { 439 } else if (!update_bounds_timer_.IsRunning()) {
425 update_bounds_timer_.Start(FROM_HERE, 440 update_bounds_timer_.Start(FROM_HERE,
426 base::TimeDelta::FromMilliseconds(kUpdateBoundsDelayMS), this, 441 base::TimeDelta::FromMilliseconds(kUpdateBoundsDelayMS), this,
427 &InstantController::SendPopupBoundsToPage); 442 &InstantController::SendPopupBoundsToPage);
428 } 443 }
429 } 444 }
430 445
431 void InstantController::SetMarginSize(int start, int end) { 446 void InstantController::SetMarginSize(int start, int end) {
432 if (!extended_enabled_ || (start_margin_ == start && end_margin_ == end)) 447 if (!extended_enabled_ || (start_margin_ == start && end_margin_ == end))
433 return; 448 return;
434 449
435 start_margin_ = start; 450 start_margin_ = start;
436 end_margin_ = end; 451 end_margin_ = end;
437 if (loader_) 452 if (overlay_)
438 loader_->SetMarginSize(start_margin_, end_margin_); 453 overlay_->SetMarginSize(start_margin_, end_margin_);
454 if (ntp_)
455 ntp_->SetMarginSize(start_margin_, end_margin_);
439 if (instant_tab_) 456 if (instant_tab_)
440 instant_tab_->SetMarginSize(start_margin_, end_margin_); 457 instant_tab_->SetMarginSize(start_margin_, end_margin_);
441 } 458 }
442 459
443 void InstantController::HandleAutocompleteResults( 460 void InstantController::HandleAutocompleteResults(
444 const std::vector<AutocompleteProvider*>& providers) { 461 const std::vector<AutocompleteProvider*>& providers) {
445 if (!extended_enabled_) 462 if (!extended_enabled_)
446 return; 463 return;
447 464
448 if (!instant_tab_ && !loader_) 465 if (!instant_tab_ && !overlay_)
449 return; 466 return;
450 467
451 DVLOG(1) << "AutocompleteResults:"; 468 DVLOG(1) << "AutocompleteResults:";
452 std::vector<InstantAutocompleteResult> results; 469 std::vector<InstantAutocompleteResult> results;
453 for (ACProviders::const_iterator provider = providers.begin(); 470 for (ACProviders::const_iterator provider = providers.begin();
454 provider != providers.end(); ++provider) { 471 provider != providers.end(); ++provider) {
455 for (ACMatches::const_iterator match = (*provider)->matches().begin(); 472 for (ACMatches::const_iterator match = (*provider)->matches().begin();
456 match != (*provider)->matches().end(); ++match) { 473 match != (*provider)->matches().end(); ++match) {
457 InstantAutocompleteResult result; 474 InstantAutocompleteResult result;
458 result.provider = UTF8ToUTF16((*provider)->GetName()); 475 result.provider = UTF8ToUTF16((*provider)->GetName());
459 result.type = UTF8ToUTF16(AutocompleteMatch::TypeToString(match->type)); 476 result.type = UTF8ToUTF16(AutocompleteMatch::TypeToString(match->type));
460 result.description = match->description; 477 result.description = match->description;
461 result.destination_url = UTF8ToUTF16(match->destination_url.spec()); 478 result.destination_url = UTF8ToUTF16(match->destination_url.spec());
462 result.transition = match->transition; 479 result.transition = match->transition;
463 result.relevance = match->relevance; 480 result.relevance = match->relevance;
464 DVLOG(1) << " " << result.relevance << " " << result.type << " " 481 DVLOG(1) << " " << result.relevance << " " << result.type << " "
465 << result.provider << " " << result.destination_url << " '" 482 << result.provider << " " << result.destination_url << " '"
466 << result.description << "' " << result.transition; 483 << result.description << "' " << result.transition;
467 results.push_back(result); 484 results.push_back(result);
468 } 485 }
469 } 486 }
470 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( 487 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
471 "HandleAutocompleteResults: total_results=%d", 488 "HandleAutocompleteResults: total_results=%d",
472 static_cast<int>(results.size()))); 489 static_cast<int>(results.size())));
473 490
474 if (instant_tab_) 491 if (instant_tab_)
475 instant_tab_->SendAutocompleteResults(results); 492 instant_tab_->SendAutocompleteResults(results);
476 else 493 else
477 loader_->SendAutocompleteResults(results); 494 overlay_->SendAutocompleteResults(results);
478 } 495 }
479 496
480 bool InstantController::OnUpOrDownKeyPressed(int count) { 497 bool InstantController::OnUpOrDownKeyPressed(int count) {
481 if (!extended_enabled_) 498 if (!extended_enabled_)
482 return false; 499 return false;
483 500
484 if (!instant_tab_ && !loader_) 501 if (!instant_tab_ && !overlay_)
485 return false; 502 return false;
486 503
487 if (instant_tab_) 504 if (instant_tab_)
488 instant_tab_->UpOrDownKeyPressed(count); 505 instant_tab_->UpOrDownKeyPressed(count);
489 else 506 else
490 loader_->UpOrDownKeyPressed(count); 507 overlay_->UpOrDownKeyPressed(count);
491 508
492 return true; 509 return true;
493 } 510 }
494 511
495 content::WebContents* InstantController::GetPreviewContents() const { 512 content::WebContents* InstantController::GetPreviewContents() const {
496 return loader_ ? loader_->contents() : NULL; 513 return overlay_ ? overlay_->contents() : NULL;
497 } 514 }
498 515
499 bool InstantController::IsPreviewingSearchResults() const { 516 bool InstantController::IsPreviewingSearchResults() const {
500 return model_.mode().is_search_suggestions() && IsFullHeight(model_) && 517 return model_.mode().is_search_suggestions() && IsFullHeight(model_) &&
501 (last_match_was_search_ || 518 (last_match_was_search_ ||
502 last_suggestion_.behavior == INSTANT_COMPLETE_NEVER); 519 last_suggestion_.behavior == INSTANT_COMPLETE_NEVER);
503 } 520 }
504 521
505 bool InstantController::CommitIfPossible(InstantCommitType type) { 522 bool InstantController::CommitIfPossible(InstantCommitType type) {
506 if (!extended_enabled_ && !instant_enabled_) 523 if (!extended_enabled_ && !instant_enabled_)
(...skipping 16 matching lines...) Expand all
523 return true; 540 return true;
524 } 541 }
525 return false; 542 return false;
526 } 543 }
527 544
528 if (!IsPreviewingSearchResults() && type != INSTANT_COMMIT_NAVIGATED) 545 if (!IsPreviewingSearchResults() && type != INSTANT_COMMIT_NAVIGATED)
529 return false; 546 return false;
530 547
531 // There may re-entrance here, from the call to browser_->CommitInstant below, 548 // There may re-entrance here, from the call to browser_->CommitInstant below,
532 // which can cause a TabDeactivated notification which gets back here. 549 // which can cause a TabDeactivated notification which gets back here.
533 // In this case, loader_->ReleaseContents() was called already. 550 // In this case, overlay_->ReleaseContents() was called already.
534 if (!GetPreviewContents()) 551 if (!GetPreviewContents())
535 return false; 552 return false;
536 553
537 // Never commit the local omnibox. 554 // Never commit the local omnibox.
538 if (loader_->IsUsingLocalPreview()) 555 if (overlay_->IsUsingLocalPreview())
539 return false; 556 return false;
540 557
541 if (type == INSTANT_COMMIT_FOCUS_LOST) 558 if (type == INSTANT_COMMIT_FOCUS_LOST)
542 loader_->Cancel(last_omnibox_text_); 559 overlay_->Cancel(last_omnibox_text_);
543 else if (type != INSTANT_COMMIT_NAVIGATED && 560 else if (type != INSTANT_COMMIT_NAVIGATED &&
544 type != INSTANT_COMMIT_CLICKED_QUERY_SUGGESTION) 561 type != INSTANT_COMMIT_CLICKED_QUERY_SUGGESTION)
545 loader_->Submit(last_omnibox_text_); 562 overlay_->Submit(last_omnibox_text_);
546 563
547 content::WebContents* preview = loader_->ReleaseContents(); 564 scoped_ptr<content::WebContents> preview = overlay_->ReleaseContents();
548 565
549 if (extended_enabled_) { 566 if (extended_enabled_) {
550 // Consider what's happening: 567 // Consider what's happening:
551 // 1. The user has typed a query in the omnibox and committed it (either 568 // 1. The user has typed a query in the omnibox and committed it (either
552 // by pressing Enter or clicking on the preview). 569 // by pressing Enter or clicking on the preview).
553 // 2. We commit the preview to the tab strip, and tell the page. 570 // 2. We commit the preview to the tab strip, and tell the page.
554 // 3. The page will update the URL hash fragment with the query terms. 571 // 3. The page will update the URL hash fragment with the query terms.
555 // After steps 1 and 3, the omnibox will show the query terms. However, if 572 // After steps 1 and 3, the omnibox will show the query terms. However, if
556 // the URL we are committing at step 2 doesn't already have query terms, it 573 // the URL we are committing at step 2 doesn't already have query terms, it
557 // will flash for a brief moment as a plain URL. So, avoid that flicker by 574 // will flash for a brief moment as a plain URL. So, avoid that flicker by
(...skipping 12 matching lines...) Expand all
570 std::string query(UTF16ToUTF8(last_omnibox_text_)); 587 std::string query(UTF16ToUTF8(last_omnibox_text_));
571 if (type != INSTANT_COMMIT_PRESSED_ENTER) { 588 if (type != INSTANT_COMMIT_PRESSED_ENTER) {
572 query += UTF16ToUTF8(last_suggestion_.text); 589 query += UTF16ToUTF8(last_suggestion_.text);
573 // Update |last_omnibox_text_| so that the controller commits the proper 590 // Update |last_omnibox_text_| so that the controller commits the proper
574 // query if the user focuses the omnibox and presses Enter. 591 // query if the user focuses the omnibox and presses Enter.
575 last_omnibox_text_ += last_suggestion_.text; 592 last_omnibox_text_ += last_suggestion_.text;
576 } 593 }
577 entry->SetVirtualURL(GURL( 594 entry->SetVirtualURL(GURL(
578 url + "#q=" + 595 url + "#q=" +
579 net::EscapeQueryParamValue(query, true))); 596 net::EscapeQueryParamValue(query, true)));
580 chrome::search::SearchTabHelper::FromWebContents(preview)-> 597 chrome::search::SearchTabHelper::FromWebContents(preview.get())->
581 NavigationEntryUpdated(); 598 NavigationEntryUpdated();
582 } 599 }
583 } 600 }
584 601
585 // If the preview page has navigated since the last Update(), we need to add 602 // If the preview page has navigated since the last Update(), we need to add
586 // the navigation to history ourselves. Else, the page will navigate after 603 // the navigation to history ourselves. Else, the page will navigate after
587 // commit, and it will be added to history in the usual manner. 604 // commit, and it will be added to history in the usual manner.
588 const history::HistoryAddPageArgs& last_navigation = 605 const history::HistoryAddPageArgs& last_navigation =
589 loader_->last_navigation(); 606 overlay_->last_navigation();
590 if (!last_navigation.url.is_empty()) { 607 if (!last_navigation.url.is_empty()) {
591 content::NavigationEntry* entry = preview->GetController().GetActiveEntry(); 608 content::NavigationEntry* entry = preview->GetController().GetActiveEntry();
592 609
593 // The last navigation should be the same as the active entry if the loader 610 // The last navigation should be the same as the active entry if the overlay
594 // is in search mode. During navigation, the active entry could have 611 // is in search mode. During navigation, the active entry could have
595 // changed since DidCommitProvisionalLoadForFrame is called after the entry 612 // changed since DidCommitProvisionalLoadForFrame is called after the entry
596 // is changed. 613 // is changed.
597 // TODO(shishir): Should we commit the last navigation for 614 // TODO(shishir): Should we commit the last navigation for
598 // INSTANT_COMMIT_NAVIGATED. 615 // INSTANT_COMMIT_NAVIGATED.
599 DCHECK(type == INSTANT_COMMIT_NAVIGATED || 616 DCHECK(type == INSTANT_COMMIT_NAVIGATED ||
600 last_navigation.url == entry->GetURL()); 617 last_navigation.url == entry->GetURL());
601 618
602 // Add the page to history. 619 // Add the page to history.
603 HistoryTabHelper* history_tab_helper = 620 HistoryTabHelper* history_tab_helper =
604 HistoryTabHelper::FromWebContents(preview); 621 HistoryTabHelper::FromWebContents(preview.get());
605 history_tab_helper->UpdateHistoryForNavigation(last_navigation); 622 history_tab_helper->UpdateHistoryForNavigation(last_navigation);
606 623
607 // Update the page title. 624 // Update the page title.
608 history_tab_helper->UpdateHistoryPageTitle(*entry); 625 history_tab_helper->UpdateHistoryPageTitle(*entry);
609 } 626 }
610 627
611 // Add a fake history entry with a non-Instant search URL, so that search 628 // Add a fake history entry with a non-Instant search URL, so that search
612 // terms extraction (for autocomplete history matches) works. 629 // terms extraction (for autocomplete history matches) works.
613 HistoryService* history = HistoryServiceFactory::GetForProfile( 630 HistoryService* history = HistoryServiceFactory::GetForProfile(
614 Profile::FromBrowserContext(preview->GetBrowserContext()), 631 Profile::FromBrowserContext(preview->GetBrowserContext()),
615 Profile::EXPLICIT_ACCESS); 632 Profile::EXPLICIT_ACCESS);
616 if (history) { 633 if (history) {
617 history->AddPage(url_for_history_, base::Time::Now(), NULL, 0, GURL(), 634 history->AddPage(url_for_history_, base::Time::Now(), NULL, 0, GURL(),
618 history::RedirectList(), last_transition_type_, 635 history::RedirectList(), last_transition_type_,
619 history::SOURCE_BROWSED, false); 636 history::SOURCE_BROWSED, false);
620 } 637 }
621 638
622 preview->GetController().PruneAllButActive(); 639 preview->GetController().PruneAllButActive();
623 640
624 if (type != INSTANT_COMMIT_PRESSED_ALT_ENTER) { 641 if (type != INSTANT_COMMIT_PRESSED_ALT_ENTER) {
625 content::WebContents* active_tab = browser_->GetActiveWebContents(); 642 content::WebContents* active_tab = browser_->GetActiveWebContents();
626 AddSessionStorageHistogram(extended_enabled_, active_tab, preview); 643 AddSessionStorageHistogram(extended_enabled_, active_tab, preview.get());
627 preview->GetController().CopyStateFromAndPrune( 644 preview->GetController().CopyStateFromAndPrune(
628 &active_tab->GetController()); 645 &active_tab->GetController());
629 } 646 }
630 647
631 // Browser takes ownership of the preview. 648 // Save notification source before we release the preview.
632 browser_->CommitInstant(preview, type == INSTANT_COMMIT_PRESSED_ALT_ENTER); 649 content::Source<content::WebContents> notification_source(preview.get());
650
651 browser_->CommitInstant(preview.Pass(),
652 type == INSTANT_COMMIT_PRESSED_ALT_ENTER);
633 653
634 content::NotificationService::current()->Notify( 654 content::NotificationService::current()->Notify(
635 chrome::NOTIFICATION_INSTANT_COMMITTED, 655 chrome::NOTIFICATION_INSTANT_COMMITTED,
636 content::Source<content::WebContents>(preview), 656 notification_source,
637 content::NotificationService::NoDetails()); 657 content::NotificationService::NoDetails());
638 658
639 // Hide explicitly. See comments in HideLoader() for why. 659 // Hide explicitly. See comments in HideOverlay() for why.
640 model_.SetPreviewState(chrome::search::Mode(), 0, INSTANT_SIZE_PERCENT); 660 model_.SetPreviewState(chrome::search::Mode(), 0, INSTANT_SIZE_PERCENT);
641 661
642 // Delay deletion as we could've gotten here from an InstantLoader method. 662 // Delay deletion as we could've gotten here from an InstantOverlay method.
643 MessageLoop::current()->DeleteSoon(FROM_HERE, loader_.release()); 663 MessageLoop::current()->DeleteSoon(FROM_HERE, overlay_.release());
644 664
645 // Try to create another loader immediately so that it is ready for the next 665 // Try to create another overlay immediately so that it is ready for the next
646 // user interaction. 666 // user interaction.
647 EnsureLoaderIsCurrent(false); 667 EnsureOverlayIsCurrent(false);
648 668
649 LOG_INSTANT_DEBUG_EVENT(this, "Committed"); 669 LOG_INSTANT_DEBUG_EVENT(this, "Committed");
650 return true; 670 return true;
651 } 671 }
652 672
653 void InstantController::OmniboxFocusChanged( 673 void InstantController::OmniboxFocusChanged(
654 OmniboxFocusState state, 674 OmniboxFocusState state,
655 OmniboxFocusChangeReason reason, 675 OmniboxFocusChangeReason reason,
656 gfx::NativeView view_gaining_focus) { 676 gfx::NativeView view_gaining_focus) {
657 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( 677 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
658 "OmniboxFocusChanged: %d to %d for reason %d", omnibox_focus_state_, 678 "OmniboxFocusChanged: %d to %d for reason %d", omnibox_focus_state_,
659 state, reason)); 679 state, reason));
660 680
661 OmniboxFocusState old_focus_state = omnibox_focus_state_; 681 OmniboxFocusState old_focus_state = omnibox_focus_state_;
662 omnibox_focus_state_ = state; 682 omnibox_focus_state_ = state;
663 if (!extended_enabled_ && !instant_enabled_) 683 if (!extended_enabled_ && !instant_enabled_)
664 return; 684 return;
665 685
666 // Tell the page if the key capture mode changed unless the focus state 686 // Tell the page if the key capture mode changed unless the focus state
667 // changed because of TYPING. This is because in that case, the browser hasn't 687 // changed because of TYPING. This is because in that case, the browser hasn't
668 // really stopped capturing key strokes. 688 // really stopped capturing key strokes.
669 // 689 //
670 // (More practically, if we don't do this check, the page would receive 690 // (More practically, if we don't do this check, the page would receive
671 // onkeycapturechange before the corresponding onchange, and the page would 691 // onkeycapturechange before the corresponding onchange, and the page would
672 // have no way of telling whether the keycapturechange happened because of 692 // have no way of telling whether the keycapturechange happened because of
673 // some actual user action or just because they started typing.) 693 // some actual user action or just because they started typing.)
674 if (extended_enabled_ && GetPreviewContents() && 694 if (extended_enabled_ && GetPreviewContents() &&
675 reason != OMNIBOX_FOCUS_CHANGE_TYPING) 695 reason != OMNIBOX_FOCUS_CHANGE_TYPING) {
676 loader_->KeyCaptureChanged(omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE); 696 const bool is_key_capture_enabled =
697 omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE;
698 if (overlay_)
699 overlay_->KeyCaptureChanged(is_key_capture_enabled);
700 if (instant_tab_)
701 instant_tab_->KeyCaptureChanged(is_key_capture_enabled);
702 }
677 703
678 // If focus went from outside the omnibox to the omnibox, preload the default 704 // If focus went from outside the omnibox to the omnibox, preload the default
679 // search engine, in anticipation of the user typing a query. If the reverse 705 // search engine, in anticipation of the user typing a query. If the reverse
680 // happened, commit or discard the preview. 706 // happened, commit or discard the preview.
681 if (state != OMNIBOX_FOCUS_NONE && old_focus_state == OMNIBOX_FOCUS_NONE) { 707 if (state != OMNIBOX_FOCUS_NONE && old_focus_state == OMNIBOX_FOCUS_NONE) {
682 // On explicit user actions, ignore the Instant blacklist. 708 // On explicit user actions, ignore the Instant blacklist.
683 EnsureLoaderIsCurrent(reason == OMNIBOX_FOCUS_CHANGE_EXPLICIT); 709 EnsureOverlayIsCurrent(reason == OMNIBOX_FOCUS_CHANGE_EXPLICIT);
684 } else if (state == OMNIBOX_FOCUS_NONE && 710 } else if (state == OMNIBOX_FOCUS_NONE &&
685 old_focus_state != OMNIBOX_FOCUS_NONE) { 711 old_focus_state != OMNIBOX_FOCUS_NONE) {
686 OmniboxLostFocus(view_gaining_focus); 712 OmniboxLostFocus(view_gaining_focus);
687 } 713 }
688 } 714 }
689 715
690 void InstantController::SearchModeChanged( 716 void InstantController::SearchModeChanged(
691 const chrome::search::Mode& old_mode, 717 const chrome::search::Mode& old_mode,
692 const chrome::search::Mode& new_mode) { 718 const chrome::search::Mode& new_mode) {
693 if (!extended_enabled_) 719 if (!extended_enabled_)
694 return; 720 return;
695 721
696 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( 722 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
697 "SearchModeChanged: [origin:mode] %d:%d to %d:%d", old_mode.origin, 723 "SearchModeChanged: [origin:mode] %d:%d to %d:%d", old_mode.origin,
698 old_mode.mode, new_mode.origin, new_mode.mode)); 724 old_mode.mode, new_mode.origin, new_mode.mode));
699 725
700 search_mode_ = new_mode; 726 search_mode_ = new_mode;
701 if (!new_mode.is_search_suggestions()) 727 if (!new_mode.is_search_suggestions())
702 HideLoader(); 728 HideOverlay();
703 729
704 if (loader_) 730 if (overlay_)
705 loader_->SearchModeChanged(new_mode); 731 overlay_->SearchModeChanged(new_mode);
706 732
707 ResetInstantTab(); 733 ResetInstantTab();
708 } 734 }
709 735
710 void InstantController::ActiveTabChanged() { 736 void InstantController::ActiveTabChanged() {
711 if (!extended_enabled_ && !instant_enabled_) 737 if (!extended_enabled_ && !instant_enabled_)
712 return; 738 return;
713 739
714 LOG_INSTANT_DEBUG_EVENT(this, "ActiveTabChanged"); 740 LOG_INSTANT_DEBUG_EVENT(this, "ActiveTabChanged");
715 741
716 // When switching tabs, always hide the preview, except if it's showing NTP 742 // When switching tabs, always hide the preview.
717 // content, and the new tab is also an NTP. 743 HideOverlay();
718 if (!search_mode_.is_ntp() || !model_.mode().is_ntp())
719 HideLoader();
720 744
721 if (extended_enabled_) 745 if (extended_enabled_)
722 ResetInstantTab(); 746 ResetInstantTab();
723 } 747 }
724 748
725 void InstantController::TabDeactivated(content::WebContents* contents) { 749 void InstantController::TabDeactivated(content::WebContents* contents) {
726 LOG_INSTANT_DEBUG_EVENT(this, "TabDeactivated"); 750 LOG_INSTANT_DEBUG_EVENT(this, "TabDeactivated");
727 if (extended_enabled_ && !contents->IsBeingDestroyed()) 751 if (extended_enabled_ && !contents->IsBeingDestroyed())
728 CommitIfPossible(INSTANT_COMMIT_FOCUS_LOST); 752 CommitIfPossible(INSTANT_COMMIT_FOCUS_LOST);
729 } 753 }
730 754
731 void InstantController::SetInstantEnabled(bool instant_enabled, 755 void InstantController::SetInstantEnabled(bool instant_enabled,
732 bool use_local_preview_only) { 756 bool use_local_preview_only) {
733 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( 757 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
734 "SetInstantEnabled: instant_enabled=%d, use_local_preview_only=%d", 758 "SetInstantEnabled: instant_enabled=%d, use_local_preview_only=%d",
735 instant_enabled, use_local_preview_only)); 759 instant_enabled, use_local_preview_only));
736 760
737 // Non extended mode does not care about |use_local_preview_only|. 761 // Non extended mode does not care about |use_local_preview_only|.
738 if (instant_enabled == instant_enabled_ && 762 if (instant_enabled == instant_enabled_ &&
739 (!extended_enabled_ || 763 (!extended_enabled_ ||
740 use_local_preview_only == use_local_preview_only_)) { 764 use_local_preview_only == use_local_preview_only_)) {
741 return; 765 return;
742 } 766 }
743 767
744 instant_enabled_ = instant_enabled; 768 instant_enabled_ = instant_enabled;
745 use_local_preview_only_ = use_local_preview_only; 769 use_local_preview_only_ = use_local_preview_only;
746 HideInternal(); 770 HideInternal();
747 loader_.reset(); 771 overlay_.reset();
748 if (extended_enabled_ || instant_enabled_) 772 if (extended_enabled_ || instant_enabled_)
749 EnsureLoaderIsCurrent(false); 773 EnsureOverlayIsCurrent(false);
774 if (extended_enabled_)
775 ResetNTP();
750 if (instant_tab_) 776 if (instant_tab_)
751 instant_tab_->SetDisplayInstantResults(instant_enabled_); 777 instant_tab_->SetDisplayInstantResults(instant_enabled_);
752 } 778 }
753 779
754 void InstantController::ThemeChanged(const ThemeBackgroundInfo& theme_info) { 780 void InstantController::ThemeChanged(const ThemeBackgroundInfo& theme_info) {
755 if (!extended_enabled_) 781 if (!extended_enabled_)
756 return; 782 return;
757 783
758 if (loader_) 784 if (overlay_)
759 loader_->SendThemeBackgroundInfo(theme_info); 785 overlay_->SendThemeBackgroundInfo(theme_info);
786 if (ntp_)
787 ntp_->SendThemeBackgroundInfo(theme_info);
788 if (instant_tab_)
789 instant_tab_->SendThemeBackgroundInfo(theme_info);
760 } 790 }
761 791
762 void InstantController::ThemeAreaHeightChanged(int height) { 792 void InstantController::ThemeAreaHeightChanged(int height) {
763 if (!extended_enabled_) 793 if (!extended_enabled_)
764 return; 794 return;
765 795
766 if (loader_) 796 if (overlay_)
767 loader_->SendThemeAreaHeight(height); 797 overlay_->SendThemeAreaHeight(height);
798 if (ntp_)
799 ntp_->SendThemeAreaHeight(height);
800 if (instant_tab_)
801 instant_tab_->SendThemeAreaHeight(height);
802 }
803
804 void InstantController::SwappedOverlayContents() {
805 model_.SetPreviewContents(GetPreviewContents());
806 }
807
808 void InstantController::FocusedOverlayContents() {
809 #if defined(USE_AURA)
810 // On aura the omnibox only receives a focus lost if we initiate the focus
811 // change. This does that.
812 if (!model_.mode().is_default())
813 browser_->InstantPreviewFocused();
814 #endif
815 }
816
817 void InstantController::ReloadOverlayIfStale() {
818 // The local popup is never stale.
819 if (overlay_ && overlay_->IsUsingLocalPreview())
820 return;
821
822 // If the preview is showing or the omnibox has focus, don't delete the
823 // overlay. It will get refreshed the next time the preview is hidden or the
824 // omnibox loses focus.
825 if ((!overlay_ || overlay_->is_stale()) &&
826 omnibox_focus_state_ == OMNIBOX_FOCUS_NONE &&
827 model_.mode().is_default()) {
828 overlay_.reset();
829 EnsureOverlayIsCurrent(false);
830 }
831 }
832
833 void InstantController::LogDebugEvent(const std::string& info) const {
834 DVLOG(1) << info;
835
836 debug_events_.push_front(std::make_pair(
837 base::Time::Now().ToInternalValue(), info));
838 static const size_t kMaxDebugEventSize = 2000;
839 if (debug_events_.size() > kMaxDebugEventSize)
840 debug_events_.pop_back();
841 }
842
843 // TODO(shishir): We assume that the WebContent's current RenderViewHost is the
844 // RenderViewHost being created which is not always true. Fix this.
845 void InstantController::InstantPageRenderViewCreated(
846 const content::WebContents* contents) {
847 if (!extended_enabled_)
848 return;
849
850 // Update theme info so that the page picks it up.
851 browser_->UpdateThemeInfoForPreview();
852
853 // Ensure the searchbox API has the correct initial state.
854 if (IsContentsFrom(overlay(), contents)) {
855 overlay_->SetDisplayInstantResults(instant_enabled_);
856 overlay_->SearchModeChanged(search_mode_);
857 overlay_->KeyCaptureChanged(
858 omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE);
859 overlay_->SetMarginSize(start_margin_, end_margin_);
860 overlay_->InitializeFonts();
861 } else if (IsContentsFrom(ntp(), contents)) {
862 ntp_->SetDisplayInstantResults(instant_enabled_);
863 ntp_->SetMarginSize(start_margin_, end_margin_);
864 ntp_->InitializeFonts();
865 } else {
866 NOTREACHED();
867 }
868 }
869
870 void InstantController::InstantSupportDetermined(
871 const content::WebContents* contents,
872 bool supports_instant) {
873 if (IsContentsFrom(instant_tab(), contents)) {
874 if (!supports_instant)
875 MessageLoop::current()->DeleteSoon(FROM_HERE, instant_tab_.release());
876 } else if (IsContentsFrom(ntp(), contents)) {
877 if (supports_instant)
878 RemoveFromBlacklist(ntp_->instant_url());
879 else
880 BlacklistAndResetNTP();
881
882 content::NotificationService::current()->Notify(
883 chrome::NOTIFICATION_INSTANT_NTP_SUPPORT_DETERMINED,
884 content::Source<InstantController>(this),
885 content::NotificationService::NoDetails());
886
887 } else if (IsContentsFrom(overlay(), contents)) {
888 if (supports_instant)
889 RemoveFromBlacklist(overlay_->instant_url());
890 else
891 BlacklistAndResetOverlay();
892
893 content::NotificationService::current()->Notify(
894 chrome::NOTIFICATION_INSTANT_OVERLAY_SUPPORT_DETERMINED,
895 content::Source<InstantController>(this),
896 content::NotificationService::NoDetails());
897 }
898 }
899
900 void InstantController::InstantPageRenderViewGone(
901 const content::WebContents* contents) {
902 if (IsContentsFrom(overlay(), contents))
903 BlacklistAndResetOverlay();
904 else if (IsContentsFrom(ntp(), contents))
905 BlacklistAndResetNTP();
906 else
907 NOTREACHED();
908 }
909
910 void InstantController::InstantPageAboutToNavigateMainFrame(
911 const content::WebContents* contents,
912 const GURL& url) {
913 DCHECK(IsContentsFrom(overlay(), contents));
914
915 // If the page does not yet support instant, we allow redirects and other
916 // navigations to go through since the instant URL can redirect - e.g. to
917 // country specific pages.
918 if (!overlay_->supports_instant())
919 return;
920
921 GURL instant_url(overlay_->instant_url());
922
923 // If we are navigating to the instant URL, do nothing.
924 if (url == instant_url)
925 return;
926
927 // Commit the navigation if either:
928 // - The page is in NTP mode (so it could only navigate on a user click) or
929 // - The page is not in NTP mode and we are navigating to a URL with a
930 // different host or path than the instant URL. This enables the instant
931 // page when it is showing search results to change the query parameters
932 // and fragments of the URL without it navigating.
933 if (model_.mode().is_ntp() ||
934 (url.host() != instant_url.host() || url.path() != instant_url.path())) {
935 CommitIfPossible(INSTANT_COMMIT_NAVIGATED);
936 }
768 } 937 }
769 938
770 void InstantController::SetSuggestions( 939 void InstantController::SetSuggestions(
771 const content::WebContents* contents, 940 const content::WebContents* contents,
772 const std::vector<InstantSuggestion>& suggestions) { 941 const std::vector<InstantSuggestion>& suggestions) {
773 LOG_INSTANT_DEBUG_EVENT(this, "SetSuggestions"); 942 LOG_INSTANT_DEBUG_EVENT(this, "SetSuggestions");
774 943
775 // Ignore if the message is from an unexpected source. 944 // Ignore if the message is from an unexpected source.
776 if (instant_tab_) { 945 if (IsContentsFrom(ntp(), contents))
777 if (instant_tab_->contents() != contents)
778 return;
779 } else if (!loader_ || loader_->contents() != contents ||
780 !allow_preview_to_show_search_suggestions_) {
781 return; 946 return;
782 } 947 if (instant_tab_ && !IsContentsFrom(instant_tab(), contents))
948 return;
949 if (IsContentsFrom(overlay(), contents) &&
950 !allow_preview_to_show_search_suggestions_)
951 return;
783 952
784 InstantSuggestion suggestion; 953 InstantSuggestion suggestion;
785 if (!suggestions.empty()) 954 if (!suggestions.empty())
786 suggestion = suggestions[0]; 955 suggestion = suggestions[0];
787 956
788 if (instant_tab_ && search_mode_.is_search_results() && 957 if (instant_tab_ && search_mode_.is_search_results() &&
789 suggestion.behavior == INSTANT_COMPLETE_REPLACE) { 958 suggestion.behavior == INSTANT_COMPLETE_REPLACE) {
790 // Update |last_omnibox_text_| so that the controller commits the proper 959 // Update |last_omnibox_text_| so that the controller commits the proper
791 // query if the user focuses the omnibox and presses Enter. 960 // query if the user focuses the omnibox and presses Enter.
792 last_omnibox_text_ = suggestion.text; 961 last_omnibox_text_ = suggestion.text;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
853 last_suggestion_ = suggestion; 1022 last_suggestion_ = suggestion;
854 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( 1023 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
855 "SetInstantSuggestion: text='%s' behavior=%d", 1024 "SetInstantSuggestion: text='%s' behavior=%d",
856 UTF16ToUTF8(suggestion.text).c_str(), suggestion.behavior)); 1025 UTF16ToUTF8(suggestion.text).c_str(), suggestion.behavior));
857 browser_->SetInstantSuggestion(suggestion); 1026 browser_->SetInstantSuggestion(suggestion);
858 } else { 1027 } else {
859 last_suggestion_ = InstantSuggestion(); 1028 last_suggestion_ = InstantSuggestion();
860 } 1029 }
861 } 1030 }
862 1031
863 // Extended mode pages will call ShowLoader() when they are ready. 1032 // Extended mode pages will call ShowOverlay() when they are ready.
864 if (!extended_enabled_) 1033 if (!extended_enabled_)
865 ShowLoader(INSTANT_SHOWN_QUERY_SUGGESTIONS, 100, INSTANT_SIZE_PERCENT); 1034 ShowOverlay(INSTANT_SHOWN_QUERY_SUGGESTIONS, 100, INSTANT_SIZE_PERCENT);
866 } 1035 }
867 1036
868 void InstantController::InstantSupportDetermined( 1037 void InstantController::ShowInstantPreview(const content::WebContents* contents,
869 const content::WebContents* contents, 1038 InstantShownReason reason,
870 bool supports_instant) { 1039 int height,
871 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( 1040 InstantSizeUnits units) {
872 "InstantSupportDetermined: supports_instant=%d", supports_instant)); 1041 if (extended_enabled_ && IsContentsFrom(overlay(), contents))
873 1042 ShowOverlay(reason, height, units);
874 if (instant_tab_ && instant_tab_->contents() == contents) {
875 if (!supports_instant)
876 MessageLoop::current()->DeleteSoon(FROM_HERE, instant_tab_.release());
877 return;
878 }
879
880 if (loader_ && loader_->contents() == contents) {
881 if (supports_instant) {
882 if (blacklisted_urls_.erase(loader_->instant_url())) {
883 RecordEventHistogram(
884 INSTANT_CONTROLLER_EVENT_URL_REMOVED_FROM_BLACKLIST);
885 }
886 } else {
887 ++blacklisted_urls_[loader_->instant_url()];
888 RecordEventHistogram(INSTANT_CONTROLLER_EVENT_URL_ADDED_TO_BLACKLIST);
889 HideInternal();
890 delete loader_->ReleaseContents();
891 MessageLoop::current()->DeleteSoon(FROM_HERE, loader_.release());
892 EnsureLoaderIsCurrent(false);
893 }
894 content::NotificationService::current()->Notify(
895 chrome::NOTIFICATION_INSTANT_SUPPORT_DETERMINED,
896 content::Source<InstantController>(this),
897 content::NotificationService::NoDetails());
898 }
899 } 1043 }
900 1044
901 void InstantController::ShowInstantPreview(InstantShownReason reason, 1045 void InstantController::StartCapturingKeyStrokes(
902 int height, 1046 const content::WebContents* contents) {
903 InstantSizeUnits units) {
904 if (extended_enabled_)
905 ShowLoader(reason, height, units);
906 }
907
908 void InstantController::StartCapturingKeyStrokes() {
909 // Ignore unless the loader is active and on the NTP.
910 if (extended_enabled_ && !instant_tab_ && model_.mode().is_ntp())
911 browser_->FocusOmniboxInvisibly();
912 }
913
914 void InstantController::StopCapturingKeyStrokes() {
915 // Ignore unless the loader is active and on the NTP, and the omnibox has
916 // invisible focus.
917 if (extended_enabled_ && !instant_tab_ && model_.mode().is_ntp() &&
918 omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE)
919 loader_->contents()->Focus();
920 }
921
922 void InstantController::SwappedWebContents() {
923 model_.SetPreviewContents(GetPreviewContents());
924 }
925
926 void InstantController::InstantLoaderContentsFocused() {
927 #if defined(USE_AURA)
928 // On aura the omnibox only receives a focus lost if we initiate the focus
929 // change. This does that.
930 if (!model_.mode().is_default())
931 browser_->InstantPreviewFocused();
932 #endif
933 }
934
935 void InstantController::InstantLoaderRenderViewGone() {
936 ++blacklisted_urls_[loader_->instant_url()];
937 HideInternal();
938 delete loader_->ReleaseContents();
939 // Delay deletion as we have gotten here from an InstantLoader method.
940 MessageLoop::current()->DeleteSoon(FROM_HERE, loader_.release());
941 EnsureLoaderIsCurrent(false);
942 }
943
944 void InstantController::InstantLoaderAboutToNavigateMainFrame(const GURL& url) {
945 // If the page does not yet support instant, we allow redirects and other
946 // navigations to go through since the instant URL can redirect - e.g. to
947 // country specific pages.
948 if (!loader_->supports_instant())
949 return;
950
951 GURL instant_url(loader_->instant_url());
952
953 // If we are navigating to the instant URL, do nothing.
954 if (url == instant_url)
955 return;
956
957 // Commit the navigation if either:
958 // - The page is in NTP mode (so it could only navigate on a user click) or
959 // - The page is not in NTP mode and we are navigating to a URL with a
960 // different host or path than the instant URL. This enables the instant
961 // page when it is showing search results to change the query parameters
962 // and fragments of the URL without it navigating.
963 if (model_.mode().is_ntp() ||
964 (url.host() != instant_url.host() || url.path() != instant_url.path())) {
965 CommitIfPossible(INSTANT_COMMIT_NAVIGATED);
966 }
967 }
968
969 void InstantController::InstantLoaderRenderViewCreated() {
970 if (!extended_enabled_) 1047 if (!extended_enabled_)
971 return; 1048 return;
972 1049
973 // Ensure the searchbox API has the correct initial state. 1050 DCHECK(IsContentsFrom(instant_tab(), contents));
974 loader_->SetDisplayInstantResults(instant_enabled_); 1051 browser_->FocusOmniboxInvisibly();
975 loader_->SearchModeChanged(search_mode_); 1052 }
976 loader_->KeyCaptureChanged(omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE); 1053
977 loader_->SetMarginSize(start_margin_, end_margin_); 1054 void InstantController::StopCapturingKeyStrokes(
978 loader_->InitializeFonts(); 1055 content::WebContents* contents) {
1056 // Nothing to do if omnibox doesn't have invisible focus.
1057 if (!extended_enabled_ || omnibox_focus_state_ != OMNIBOX_FOCUS_INVISIBLE)
1058 return;
1059
1060 DCHECK(IsContentsFrom(instant_tab(), contents));
1061 contents->Focus();
1062 }
1063
1064 void InstantController::NavigateToURL(const content::WebContents* contents,
1065 const GURL& url,
1066 content::PageTransition transition) {
1067 // TODO(samarth): handle case where contents are no longer "active" (e.g. user
1068 // has switched tabs).
1069 if (!extended_enabled_)
1070 return;
1071 if (overlay_)
1072 HideOverlay();
1073 browser_->OpenURLInCurrentTab(url, transition);
979 } 1074 }
980 1075
981 void InstantController::OmniboxLostFocus(gfx::NativeView view_gaining_focus) { 1076 void InstantController::OmniboxLostFocus(gfx::NativeView view_gaining_focus) {
982 // If the preview is showing custom NTP content, don't hide it, commit it 1077 // If the preview is showing custom NTP content, don't hide it, commit it
983 // (no matter where the user clicked) or try to recreate it. 1078 // (no matter where the user clicked) or try to recreate it.
984 if (model_.mode().is_ntp()) 1079 if (model_.mode().is_ntp())
985 return; 1080 return;
986 1081
987 // If the preview is not showing at all, recreate it if it's stale. 1082 // If the preview is not showing at all, recreate it if it's stale.
988 if (model_.mode().is_default()) { 1083 if (model_.mode().is_default()) {
989 OnStaleLoader(); 1084 ReloadOverlayIfStale();
990 MaybeSwitchToRemoteLoader(); 1085 MaybeSwitchToRemoteOverlay();
991 return; 1086 return;
992 } 1087 }
993 1088
994 // The preview is showing search suggestions. If GetPreviewContents() is NULL, 1089 // The preview is showing search suggestions. If GetPreviewContents() is NULL,
995 // we are in the commit path. Don't do anything. 1090 // we are in the commit path. Don't do anything.
996 if (!GetPreviewContents()) 1091 if (!GetPreviewContents())
997 return; 1092 return;
998 1093
999 #if defined(OS_MACOSX) 1094 #if defined(OS_MACOSX)
1000 // TODO(sreeram): See if Mac really needs this special treatment. 1095 // TODO(sreeram): See if Mac really needs this special treatment.
1001 if (!loader_->is_pointer_down_from_activate()) 1096 if (!overlay_->is_pointer_down_from_activate())
1002 HideLoader(); 1097 HideOverlay();
1003 #else 1098 #else
1004 if (IsViewInContents(GetViewGainingFocus(view_gaining_focus), 1099 if (IsViewInContents(GetViewGainingFocus(view_gaining_focus),
1005 loader_->contents())) 1100 overlay_->contents()))
1006 CommitIfPossible(INSTANT_COMMIT_FOCUS_LOST); 1101 CommitIfPossible(INSTANT_COMMIT_FOCUS_LOST);
1007 else 1102 else
1008 HideLoader(); 1103 HideOverlay();
1009 #endif 1104 #endif
1010 } 1105 }
1011 1106
1012 void InstantController::NavigateToURL(const GURL& url, 1107 void InstantController::ResetNTP() {
1013 content::PageTransition transition) { 1108 ntp_.reset();
1014 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( 1109 std::string instant_url;
1015 "NavigateToURL: url='%s'", url.spec().c_str())); 1110 if (!GetInstantURL(browser_->profile(), false, &instant_url))
1111 return;
1016 1112
1017 if (!extended_enabled_) 1113 ntp_.reset(new InstantNTP(this, instant_url));
1018 return; 1114 ntp_->InitContents(browser_->profile(), browser_->GetActiveWebContents(),
1019 if (loader_) 1115 base::Bind(&InstantController::ResetNTP,
1020 HideLoader(); 1116 base::Unretained(this)));
1021 browser_->OpenURLInCurrentTab(url, transition);
1022 } 1117 }
1023 1118
1024 void InstantController::LogDebugEvent(const std::string& info) const { 1119 bool InstantController::EnsureOverlayIsCurrent(bool ignore_blacklist) {
1025 DVLOG(1) << info;
1026
1027 debug_events_.push_front(std::make_pair(
1028 base::Time::Now().ToInternalValue(), info));
1029 static const size_t kMaxDebugEventSize = 2000;
1030 if (debug_events_.size() > kMaxDebugEventSize)
1031 debug_events_.pop_back();
1032 }
1033
1034 bool InstantController::EnsureLoaderIsCurrent(bool ignore_blacklist) {
1035 // If there's no active tab, the browser is closing. 1120 // If there's no active tab, the browser is closing.
1036 const content::WebContents* active_tab = browser_->GetActiveWebContents(); 1121 const content::WebContents* active_tab = browser_->GetActiveWebContents();
1037 if (!active_tab) 1122 if (!active_tab)
1038 return false; 1123 return false;
1039 1124
1125 Profile* profile = Profile::FromBrowserContext(
1126 active_tab->GetBrowserContext());
1040 std::string instant_url; 1127 std::string instant_url;
1041 if (!GetInstantURL(active_tab, ignore_blacklist, &instant_url)) { 1128 if (!GetInstantURL(profile, ignore_blacklist, &instant_url)) {
1042 // If we are in extended mode, fallback to the local popup. 1129 // If we are in extended mode, fallback to the local popup.
1043 if (extended_enabled_) 1130 if (extended_enabled_)
1044 instant_url = kLocalOmniboxPopupURL; 1131 instant_url = kLocalOmniboxPopupURL;
1045 else 1132 else
1046 return false; 1133 return false;
1047 } 1134 }
1048 1135
1049 if (!loader_ || loader_->instant_url() != instant_url) 1136 if (!overlay_ || overlay_->instant_url() != instant_url)
1050 CreateLoader(instant_url, active_tab); 1137 CreateOverlay(instant_url, active_tab);
1051 1138
1052 return true; 1139 return true;
1053 } 1140 }
1054 1141
1055 void InstantController::CreateLoader(const std::string& instant_url, 1142 void InstantController::CreateOverlay(const std::string& instant_url,
1056 const content::WebContents* active_tab) { 1143 const content::WebContents* active_tab) {
1057 // Update theme info so that the loader picks up the correct fonts.
1058 if (extended_enabled_)
1059 browser_->UpdateThemeInfoForPreview();
1060
1061 HideInternal(); 1144 HideInternal();
1062 loader_.reset(new InstantLoader(this, instant_url)); 1145 overlay_.reset(new InstantOverlay(this, instant_url));
1063 loader_->InitContents(active_tab); 1146 overlay_->InitContents(browser_->profile(), active_tab);
1064 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( 1147 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
1065 "CreateLoader: instant_url='%s'", instant_url.c_str())); 1148 "CreateOverlay: instant_url='%s'", instant_url.c_str()));
1066
1067 // Restart the stale loader timer.
1068 stale_loader_timer_.Start(FROM_HERE,
1069 base::TimeDelta::FromMilliseconds(kStaleLoaderTimeoutMS), this,
1070 &InstantController::OnStaleLoader);
1071 } 1149 }
1072 1150
1073 void InstantController::OnStaleLoader() { 1151 void InstantController::MaybeSwitchToRemoteOverlay() {
1074 // The local popup is never stale. 1152 if (!overlay_ || omnibox_focus_state_ != OMNIBOX_FOCUS_NONE ||
1075 if (loader_ && loader_->IsUsingLocalPreview())
1076 return;
1077
1078 // If the preview is showing or the omnibox has focus, don't delete the
1079 // loader. It will get refreshed the next time the preview is hidden or the
1080 // omnibox loses focus.
1081 if (!stale_loader_timer_.IsRunning() &&
1082 omnibox_focus_state_ == OMNIBOX_FOCUS_NONE &&
1083 model_.mode().is_default()) {
1084 loader_.reset();
1085 EnsureLoaderIsCurrent(false);
1086 }
1087 }
1088
1089 void InstantController::MaybeSwitchToRemoteLoader() {
1090 if (!loader_ || omnibox_focus_state_ != OMNIBOX_FOCUS_NONE ||
1091 !model_.mode().is_default()) { 1153 !model_.mode().is_default()) {
1092 return; 1154 return;
1093 } 1155 }
1094 1156
1095 EnsureLoaderIsCurrent(false); 1157 EnsureOverlayIsCurrent(false);
1096 } 1158 }
1097 1159
1098 void InstantController::ResetInstantTab() { 1160 void InstantController::ResetInstantTab() {
1099 // Do not wire up the InstantTab if instant should only use local previews, to 1161 // Do not wire up the InstantTab if instant should only use local previews, to
1100 // prevent it from sending data to the page. 1162 // prevent it from sending data to the page.
1101 if (search_mode_.is_origin_search() && !use_local_preview_only_) { 1163 if (!search_mode_.is_origin_default() && !use_local_preview_only_) {
1102 content::WebContents* active_tab = browser_->GetActiveWebContents(); 1164 content::WebContents* active_tab = browser_->GetActiveWebContents();
1103 if (!instant_tab_ || active_tab != instant_tab_->contents()) { 1165 if (!instant_tab_ || active_tab != instant_tab_->contents()) {
1104 instant_tab_.reset(new InstantTab(this, active_tab)); 1166 instant_tab_.reset(new InstantTab(this));
1105 instant_tab_->Init(); 1167 instant_tab_->Init(active_tab);
1168 // Update theme info for this tab.
1169 browser_->UpdateThemeInfoForPreview();
1106 instant_tab_->SetDisplayInstantResults(instant_enabled_); 1170 instant_tab_->SetDisplayInstantResults(instant_enabled_);
1107 instant_tab_->SetMarginSize(start_margin_, end_margin_); 1171 instant_tab_->SetMarginSize(start_margin_, end_margin_);
1108 instant_tab_->InitializeFonts(); 1172 instant_tab_->InitializeFonts();
1173 instant_tab_->KeyCaptureChanged(
1174 omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE);
1109 } 1175 }
1110 1176
1111 // Hide the |loader_| since we are now using |instant_tab_| instead. 1177 // Hide the |overlay_| since we are now using |instant_tab_| instead.
1112 HideLoader(); 1178 HideOverlay();
1113 } else { 1179 } else {
1114 instant_tab_.reset(); 1180 instant_tab_.reset();
1115 } 1181 }
1116 } 1182 }
1117 1183
1118 void InstantController::HideLoader() { 1184 void InstantController::HideOverlay() {
1119 HideInternal(); 1185 HideInternal();
1120 OnStaleLoader(); 1186 ReloadOverlayIfStale();
1121 MaybeSwitchToRemoteLoader(); 1187 MaybeSwitchToRemoteOverlay();
1122 } 1188 }
1123 1189
1124 void InstantController::HideInternal() { 1190 void InstantController::HideInternal() {
1125 LOG_INSTANT_DEBUG_EVENT(this, "Hide"); 1191 LOG_INSTANT_DEBUG_EVENT(this, "Hide");
1126 1192
1127 // If GetPreviewContents() returns NULL, either we're already in the desired 1193 // If GetPreviewContents() returns NULL, either we're already in the desired
1128 // MODE_DEFAULT state, or we're in the commit path. For the latter, don't 1194 // MODE_DEFAULT state, or we're in the commit path. For the latter, don't
1129 // change the state just yet; else we may hide the preview unnecessarily. 1195 // change the state just yet; else we may hide the preview unnecessarily.
1130 // Instead, the state will be set correctly after the commit is done. 1196 // Instead, the state will be set correctly after the commit is done.
1131 if (GetPreviewContents()) { 1197 if (GetPreviewContents()) {
1132 model_.SetPreviewState(chrome::search::Mode(), 0, INSTANT_SIZE_PERCENT); 1198 model_.SetPreviewState(chrome::search::Mode(), 0, INSTANT_SIZE_PERCENT);
1133 allow_preview_to_show_search_suggestions_ = false; 1199 allow_preview_to_show_search_suggestions_ = false;
1134 1200
1135 // Send a message asking the preview to clear out old results. 1201 // Send a message asking the preview to clear out old results.
1136 loader_->Update(string16(), 0, 0, true); 1202 overlay_->Update(string16(), 0, 0, true);
1137 } 1203 }
1138 1204
1139 // Clear the first interaction timestamp for later use. 1205 // Clear the first interaction timestamp for later use.
1140 first_interaction_time_ = base::Time(); 1206 first_interaction_time_ = base::Time();
1141 } 1207 }
1142 1208
1143 void InstantController::ShowLoader(InstantShownReason reason, 1209 void InstantController::ShowOverlay(InstantShownReason reason,
1144 int height, 1210 int height,
1145 InstantSizeUnits units) { 1211 InstantSizeUnits units) {
1146 // If we are on a committed search results page, the |loader_| is not in use. 1212 // If we are on a committed search results page, the |overlay_| is not in use.
1147 if (instant_tab_) 1213 if (instant_tab_)
1148 return; 1214 return;
1149 1215
1150 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( 1216 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
1151 "Show: reason=%d height=%d units=%d", reason, height, units)); 1217 "Show: reason=%d height=%d units=%d", reason, height, units));
1152 1218
1153 // Must be on NTP to show NTP content. 1219 // INSTANT_SHOWN_CUSTOM_NTP_CONTENT is no longer supported.
1154 if (reason == INSTANT_SHOWN_CUSTOM_NTP_CONTENT && !search_mode_.is_ntp()) 1220 // TODO(samarth): remove once the server has been updated.
1221 if (reason == INSTANT_SHOWN_CUSTOM_NTP_CONTENT)
1155 return; 1222 return;
1156 1223
1157 // Must have updated omnibox after the last HideLoader() to show suggestions. 1224 // Must have updated omnibox after the last HideOverlay() to show suggestions.
1158 if ((reason == INSTANT_SHOWN_QUERY_SUGGESTIONS || 1225 if ((reason == INSTANT_SHOWN_QUERY_SUGGESTIONS ||
1159 reason == INSTANT_SHOWN_CLICKED_QUERY_SUGGESTION) && 1226 reason == INSTANT_SHOWN_CLICKED_QUERY_SUGGESTION) &&
1160 !allow_preview_to_show_search_suggestions_) 1227 !allow_preview_to_show_search_suggestions_)
1161 return; 1228 return;
1162 1229
1163 // The page is trying to hide itself. Hide explicitly (i.e., don't use 1230 // The page is trying to hide itself. Hide explicitly (i.e., don't use
1164 // HideLoader()) so that it can change its mind. 1231 // HideOverlay()) so that it can change its mind.
1165 if (height == 0) { 1232 if (height == 0) {
1166 model_.SetPreviewState(chrome::search::Mode(), 0, INSTANT_SIZE_PERCENT); 1233 model_.SetPreviewState(chrome::search::Mode(), 0, INSTANT_SIZE_PERCENT);
1167 return; 1234 return;
1168 } 1235 }
1169 1236
1170 // If the preview is being shown for the first time since the user started 1237 // If the preview is being shown for the first time since the user started
1171 // typing, record a histogram value. 1238 // typing, record a histogram value.
1172 if (!first_interaction_time_.is_null() && model_.mode().is_default()) { 1239 if (!first_interaction_time_.is_null() && model_.mode().is_default()) {
1173 base::TimeDelta delta = base::Time::Now() - first_interaction_time_; 1240 base::TimeDelta delta = base::Time::Now() - first_interaction_time_;
1174 UMA_HISTOGRAM_TIMES("Instant.TimeToFirstShow", delta); 1241 UMA_HISTOGRAM_TIMES("Instant.TimeToFirstShow", delta);
1175 } 1242 }
1176 1243
1177 // Show at 100% height except in the following cases: 1244 // Show at 100% height except in the following cases:
1178 // - The local omnibox popup is being loaded. 1245 // - The local omnibox popup is being loaded.
1179 // - Instant is disabled. The page needs to be able to show only a dropdown. 1246 // - Instant is disabled. The page needs to be able to show only a dropdown.
1180 // - The page wants to show custom NTP content. 1247 // - The page wants to show custom NTP content.
1181 // - The page is over a website other than search or an NTP, and is not 1248 // - The page is over a website other than search or an NTP, and is not
1182 // already showing at 100% height. 1249 // already showing at 100% height.
1183 if (loader_->IsUsingLocalPreview() || !instant_enabled_ || 1250 if (overlay_->IsUsingLocalPreview() || !instant_enabled_ ||
1184 reason == INSTANT_SHOWN_CUSTOM_NTP_CONTENT || 1251 reason == INSTANT_SHOWN_CUSTOM_NTP_CONTENT ||
1185 (search_mode_.is_origin_default() && !IsFullHeight(model_))) 1252 (search_mode_.is_origin_default() && !IsFullHeight(model_)))
1186 model_.SetPreviewState(search_mode_, height, units); 1253 model_.SetPreviewState(search_mode_, height, units);
1187 else 1254 else
1188 model_.SetPreviewState(search_mode_, 100, INSTANT_SIZE_PERCENT); 1255 model_.SetPreviewState(search_mode_, 100, INSTANT_SIZE_PERCENT);
1189 1256
1190 // If the user clicked on a query suggestion, also go ahead and commit the 1257 // If the user clicked on a query suggestion, also go ahead and commit the
1191 // overlay. This is necessary because if the overlay was partially visible 1258 // overlay. This is necessary because if the overlay was partially visible
1192 // when the suggestion was clicked, the click itself would not commit the 1259 // when the suggestion was clicked, the click itself would not commit the
1193 // overlay (because we're not full height). 1260 // overlay (because we're not full height).
1194 if (reason == INSTANT_SHOWN_CLICKED_QUERY_SUGGESTION) 1261 if (reason == INSTANT_SHOWN_CLICKED_QUERY_SUGGESTION)
1195 CommitIfPossible(INSTANT_COMMIT_CLICKED_QUERY_SUGGESTION); 1262 CommitIfPossible(INSTANT_COMMIT_CLICKED_QUERY_SUGGESTION);
1196 } 1263 }
1197 1264
1198 void InstantController::SendPopupBoundsToPage() { 1265 void InstantController::SendPopupBoundsToPage() {
1199 if (last_popup_bounds_ == popup_bounds_ || !loader_ || 1266 if (last_popup_bounds_ == popup_bounds_ || !overlay_ ||
1200 loader_->is_pointer_down_from_activate()) 1267 overlay_->is_pointer_down_from_activate())
1201 return; 1268 return;
1202 1269
1203 last_popup_bounds_ = popup_bounds_; 1270 last_popup_bounds_ = popup_bounds_;
1204 gfx::Rect preview_bounds = browser_->GetInstantBounds(); 1271 gfx::Rect preview_bounds = browser_->GetInstantBounds();
1205 gfx::Rect intersection = gfx::IntersectRects(popup_bounds_, preview_bounds); 1272 gfx::Rect intersection = gfx::IntersectRects(popup_bounds_, preview_bounds);
1206 1273
1207 // Translate into window coordinates. 1274 // Translate into window coordinates.
1208 if (!intersection.IsEmpty()) { 1275 if (!intersection.IsEmpty()) {
1209 intersection.Offset(-preview_bounds.origin().x(), 1276 intersection.Offset(-preview_bounds.origin().x(),
1210 -preview_bounds.origin().y()); 1277 -preview_bounds.origin().y());
1211 } 1278 }
1212 1279
1213 // In the current Chrome UI, these must always be true so they sanity check 1280 // In the current Chrome UI, these must always be true so they sanity check
1214 // the above operations. In a future UI, these may be removed or adjusted. 1281 // the above operations. In a future UI, these may be removed or adjusted.
1215 // There is no point in sanity-checking |intersection.y()| because the omnibox 1282 // There is no point in sanity-checking |intersection.y()| because the omnibox
1216 // can be placed anywhere vertically relative to the preview (for example, in 1283 // can be placed anywhere vertically relative to the preview (for example, in
1217 // Mac fullscreen mode, the omnibox is fully enclosed by the preview bounds). 1284 // Mac fullscreen mode, the omnibox is fully enclosed by the preview bounds).
1218 DCHECK_LE(0, intersection.x()); 1285 DCHECK_LE(0, intersection.x());
1219 DCHECK_LE(0, intersection.width()); 1286 DCHECK_LE(0, intersection.width());
1220 DCHECK_LE(0, intersection.height()); 1287 DCHECK_LE(0, intersection.height());
1221 1288
1222 loader_->SetPopupBounds(intersection); 1289 overlay_->SetPopupBounds(intersection);
1223 } 1290 }
1224 1291
1225 bool InstantController::GetInstantURL(const content::WebContents* active_tab, 1292 bool InstantController::GetInstantURL(Profile* profile,
1226 bool ignore_blacklist, 1293 bool ignore_blacklist,
1227 std::string* instant_url) const { 1294 std::string* instant_url) const {
1228 DCHECK(active_tab); 1295 DCHECK(profile);
1229 instant_url->clear(); 1296 instant_url->clear();
1230 1297
1231 if (extended_enabled_ && use_local_preview_only_) { 1298 if (extended_enabled_ && use_local_preview_only_) {
1232 *instant_url = kLocalOmniboxPopupURL; 1299 *instant_url = kLocalOmniboxPopupURL;
1233 return true; 1300 return true;
1234 } 1301 }
1235 1302
1236 const TemplateURL* template_url = TemplateURLServiceFactory::GetForProfile( 1303 const TemplateURL* template_url = TemplateURLServiceFactory::GetForProfile(
1237 Profile::FromBrowserContext(active_tab->GetBrowserContext()))-> 1304 profile)->GetDefaultSearchProvider();
1238 GetDefaultSearchProvider();
1239 1305
1240 if (!template_url) { 1306 if (!template_url) {
1241 LOG_INSTANT_DEBUG_EVENT(this, "GetInstantURL: No template URL"); 1307 LOG_INSTANT_DEBUG_EVENT(this, "GetInstantURL: No template URL");
1242 return false; 1308 return false;
1243 } 1309 }
1244 1310
1245 CommandLine* command_line = CommandLine::ForCurrentProcess(); 1311 CommandLine* command_line = CommandLine::ForCurrentProcess();
1246 if (command_line->HasSwitch(switches::kInstantURL)) 1312 if (command_line->HasSwitch(switches::kInstantURL))
1247 *instant_url = command_line->GetSwitchValueASCII(switches::kInstantURL); 1313 *instant_url = command_line->GetSwitchValueASCII(switches::kInstantURL);
1248 1314
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1309 RecordEventHistogram(INSTANT_CONTROLLER_EVENT_URL_BLOCKED_BY_BLACKLIST); 1375 RecordEventHistogram(INSTANT_CONTROLLER_EVENT_URL_BLOCKED_BY_BLACKLIST);
1310 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( 1376 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
1311 "GetInstantURL: Instant URL blacklisted: url=%s", 1377 "GetInstantURL: Instant URL blacklisted: url=%s",
1312 instant_url->c_str())); 1378 instant_url->c_str()));
1313 return false; 1379 return false;
1314 } 1380 }
1315 } 1381 }
1316 1382
1317 return true; 1383 return true;
1318 } 1384 }
1385
1386 void InstantController::BlacklistAndResetNTP() {
1387 ++blacklisted_urls_[ntp_->instant_url()];
1388 RecordEventHistogram(INSTANT_CONTROLLER_EVENT_URL_ADDED_TO_BLACKLIST);
1389 delete ntp_->ReleaseContents().release();
1390 MessageLoop::current()->DeleteSoon(FROM_HERE, ntp_.release());
1391 ResetNTP();
1392 }
1393
1394 void InstantController::BlacklistAndResetOverlay() {
1395 ++blacklisted_urls_[overlay_->instant_url()];
1396 RecordEventHistogram(INSTANT_CONTROLLER_EVENT_URL_ADDED_TO_BLACKLIST);
1397 HideInternal();
1398 delete overlay_->ReleaseContents().release();
1399 MessageLoop::current()->DeleteSoon(FROM_HERE, overlay_.release());
1400 EnsureOverlayIsCurrent(false);
1401 }
1402
1403 void InstantController::RemoveFromBlacklist(const std::string& url) {
1404 if (blacklisted_urls_.erase(url)) {
1405 RecordEventHistogram(INSTANT_CONTROLLER_EVENT_URL_REMOVED_FROM_BLACKLIST);
1406 }
1407 }
OLDNEW
« no previous file with comments | « chrome/browser/instant/instant_controller.h ('k') | chrome/browser/instant/instant_extended_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698