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

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

Powered by Google App Engine
This is Rietveld 408576698