OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/search/instant_controller.h" | 5 #include "chrome/browser/ui/search/instant_controller.h" |
6 | 6 |
7 #include "base/metrics/histogram.h" | 7 #include "base/metrics/histogram.h" |
8 #include "base/string_util.h" | 8 #include "base/string_util.h" |
9 #include "base/stringprintf.h" | 9 #include "base/stringprintf.h" |
10 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
261 UTF16ToUTF8(user_text).c_str(), UTF16ToUTF8(full_text).c_str(), | 261 UTF16ToUTF8(user_text).c_str(), UTF16ToUTF8(full_text).c_str(), |
262 static_cast<int>(selection_start), static_cast<int>(selection_end), | 262 static_cast<int>(selection_start), static_cast<int>(selection_end), |
263 verbatim, user_input_in_progress, omnibox_popup_is_open, escape_pressed, | 263 verbatim, user_input_in_progress, omnibox_popup_is_open, escape_pressed, |
264 is_keyword_search)); | 264 is_keyword_search)); |
265 | 265 |
266 // TODO(dhollowa): Complete keyword match UI. For now just hide suggestions. | 266 // TODO(dhollowa): Complete keyword match UI. For now just hide suggestions. |
267 // http://crbug.com/153932. Note, this early escape is happens prior to the | 267 // http://crbug.com/153932. Note, this early escape is happens prior to the |
268 // DCHECKs below because |user_text| and |full_text| have different semantics | 268 // DCHECKs below because |user_text| and |full_text| have different semantics |
269 // when keyword search is in effect. | 269 // when keyword search is in effect. |
270 if (is_keyword_search) { | 270 if (is_keyword_search) { |
271 if (UseInstantTabToShowSuggestions()) | 271 if (instant_tab_) |
272 instant_tab_->Update(string16(), 0, 0, true); | 272 instant_tab_->Update(string16(), 0, 0, true); |
273 else | 273 else |
274 HideOverlay(); | 274 HideOverlay(); |
275 last_match_was_search_ = false; | 275 last_match_was_search_ = false; |
276 return false; | 276 return false; |
277 } | 277 } |
278 | 278 |
279 // Ignore spurious updates when the omnibox is blurred; otherwise click | 279 // Ignore spurious updates when the omnibox is blurred; otherwise click |
280 // targets on the page may vanish before a click event arrives. | 280 // targets on the page may vanish before a click event arrives. |
281 if (omnibox_focus_state_ == OMNIBOX_FOCUS_NONE) | 281 if (omnibox_focus_state_ == OMNIBOX_FOCUS_NONE) |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
314 // In non extended mode, Instant is disabled for URLs and keyword mode. | 314 // In non extended mode, Instant is disabled for URLs and keyword mode. |
315 if (!extended_enabled_ && | 315 if (!extended_enabled_ && |
316 (!last_match_was_search_ || | 316 (!last_match_was_search_ || |
317 match.type == AutocompleteMatch::SEARCH_OTHER_ENGINE)) { | 317 match.type == AutocompleteMatch::SEARCH_OTHER_ENGINE)) { |
318 HideOverlay(); | 318 HideOverlay(); |
319 return false; | 319 return false; |
320 } | 320 } |
321 | 321 |
322 // If we have an |instant_tab_| use it, else ensure we have an overlay that is | 322 // If we have an |instant_tab_| use it, else ensure we have an overlay that is |
323 // current or is using the local overlay. | 323 // current or is using the local overlay. |
324 if (!UseInstantTabToShowSuggestions() && | 324 if (!instant_tab_ && !(overlay_ && overlay_->IsLocal()) && |
325 !(overlay_ && overlay_->IsLocalOverlay()) && | |
326 !EnsureOverlayIsCurrent(false)) { | 325 !EnsureOverlayIsCurrent(false)) { |
327 HideOverlay(); | 326 HideOverlay(); |
328 return false; | 327 return false; |
329 } | 328 } |
330 | 329 |
331 if (extended_enabled_) { | 330 if (extended_enabled_) { |
332 if (!omnibox_popup_is_open) { | 331 if (!omnibox_popup_is_open) { |
333 if (!user_input_in_progress) { | 332 if (!user_input_in_progress) { |
334 // If the user isn't typing and the omnibox popup is closed, it means a | 333 // If the user isn't typing and the omnibox popup is closed, it means a |
335 // regular navigation, tab-switch or the user hitting Escape. | 334 // regular navigation, tab-switch or the user hitting Escape. |
336 if (UseInstantTabToShowSuggestions()) { | 335 if (instant_tab_) { |
337 // The user is on a search results page. It may be showing results for | 336 // The user is on a search results page. It may be showing results for |
338 // a partial query the user typed before they hit Escape. Send the | 337 // a partial query the user typed before they hit Escape. Send the |
339 // omnibox text to the page to restore the original results. | 338 // omnibox text to the page to restore the original results. |
340 // | 339 // |
341 // In a tab switch, |instant_tab_| won't have updated yet, so it may | 340 // In a tab switch, |instant_tab_| won't have updated yet, so it may |
342 // be pointing to the previous tab (which was a search results page). | 341 // be pointing to the previous tab (which was a search results page). |
343 // Ensure we don't send the omnibox text to a random webpage (the new | 342 // Ensure we don't send the omnibox text to a random webpage (the new |
344 // tab), by comparing the old and new WebContents. | 343 // tab), by comparing the old and new WebContents. |
345 if (escape_pressed && | 344 if (escape_pressed && |
346 instant_tab_->contents() == browser_->GetActiveWebContents()) { | 345 instant_tab_->contents() == browser_->GetActiveWebContents()) { |
(...skipping 12 matching lines...) Expand all Loading... |
359 // If |full_text| is empty, the user is on the NTP. The overlay may | 358 // If |full_text| is empty, the user is on the NTP. The overlay may |
360 // be showing custom NTP content; hide only if that's not the case. | 359 // be showing custom NTP content; hide only if that's not the case. |
361 HideOverlay(); | 360 HideOverlay(); |
362 } | 361 } |
363 } else if (full_text.empty()) { | 362 } else if (full_text.empty()) { |
364 // The user is typing, and backspaced away all omnibox text. Clear | 363 // The user is typing, and backspaced away all omnibox text. Clear |
365 // |last_omnibox_text_| so that we don't attempt to set suggestions. | 364 // |last_omnibox_text_| so that we don't attempt to set suggestions. |
366 last_omnibox_text_.clear(); | 365 last_omnibox_text_.clear(); |
367 last_user_text_.clear(); | 366 last_user_text_.clear(); |
368 last_suggestion_ = InstantSuggestion(); | 367 last_suggestion_ = InstantSuggestion(); |
369 if (UseInstantTabToShowSuggestions()) { | 368 if (instant_tab_) { |
370 // On a search results page, tell it to clear old results. | 369 // On a search results page, tell it to clear old results. |
371 instant_tab_->Update(string16(), 0, 0, true); | 370 instant_tab_->Update(string16(), 0, 0, true); |
372 } else if (search_mode_.is_origin_ntp()) { | 371 } else if (search_mode_.is_origin_ntp()) { |
373 // On the NTP, tell the overlay to clear old results. Don't hide the | 372 // On the NTP, tell the overlay to clear old results. Don't hide the |
374 // overlay so it can show a blank page or logo if it wants. | 373 // overlay so it can show a blank page or logo if it wants. |
375 overlay_->Update(string16(), 0, 0, true); | 374 overlay_->Update(string16(), 0, 0, true); |
376 } else { | 375 } else { |
377 HideOverlay(); | 376 HideOverlay(); |
378 } | 377 } |
379 } else { | 378 } else { |
380 // The user switched to a tab with partial text already in the omnibox. | 379 // The user switched to a tab with partial text already in the omnibox. |
381 HideOverlay(); | 380 HideOverlay(); |
382 | 381 |
383 // The new tab may or may not be a search results page; we don't know | 382 // The new tab may or may not be a search results page; we don't know |
384 // since SearchModeChanged() hasn't been called yet. If it later turns | 383 // since SearchModeChanged() hasn't been called yet. If it later turns |
385 // out to be, we should store |full_text| now, so that if the user hits | 384 // out to be, we should store |full_text| now, so that if the user hits |
386 // Enter, we'll send the correct query to instant_tab_->Submit(). If the | 385 // Enter, we'll send the correct query to instant_tab_->Submit(). If the |
387 // partial text is not a query (|last_match_was_search_| is false), we | 386 // partial text is not a query (|last_match_was_search_| is false), we |
388 // won't Submit(), so no need to worry about that. | 387 // won't Submit(), so no need to worry about that. |
389 last_omnibox_text_ = full_text; | 388 last_omnibox_text_ = full_text; |
390 last_user_text_ = user_text; | 389 last_user_text_ = user_text; |
391 last_suggestion_ = InstantSuggestion(); | 390 last_suggestion_ = InstantSuggestion(); |
392 } | 391 } |
393 return false; | 392 return false; |
394 } else if (full_text.empty()) { | 393 } else if (full_text.empty()) { |
395 // The user typed a solitary "?". Same as the backspace case above. | 394 // The user typed a solitary "?". Same as the backspace case above. |
396 last_omnibox_text_.clear(); | 395 last_omnibox_text_.clear(); |
397 last_user_text_.clear(); | 396 last_user_text_.clear(); |
398 last_suggestion_ = InstantSuggestion(); | 397 last_suggestion_ = InstantSuggestion(); |
399 if (UseInstantTabToShowSuggestions()) | 398 if (instant_tab_) |
400 instant_tab_->Update(string16(), 0, 0, true); | 399 instant_tab_->Update(string16(), 0, 0, true); |
401 else if (search_mode_.is_origin_ntp()) | 400 else if (search_mode_.is_origin_ntp()) |
402 overlay_->Update(string16(), 0, 0, true); | 401 overlay_->Update(string16(), 0, 0, true); |
403 else | 402 else |
404 HideOverlay(); | 403 HideOverlay(); |
405 return false; | 404 return false; |
406 } | 405 } |
407 } else if (!omnibox_popup_is_open || full_text.empty()) { | 406 } else if (!omnibox_popup_is_open || full_text.empty()) { |
408 // In the non-extended case, hide the overlay as long as the user isn't | 407 // In the non-extended case, hide the overlay as long as the user isn't |
409 // actively typing a non-empty query. | 408 // actively typing a non-empty query. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
444 last_verbatim_ = verbatim; | 443 last_verbatim_ = verbatim; |
445 | 444 |
446 last_transition_type_ = match.transition; | 445 last_transition_type_ = match.transition; |
447 url_for_history_ = match.destination_url; | 446 url_for_history_ = match.destination_url; |
448 | 447 |
449 // Allow search suggestions. In extended mode, SearchModeChanged() will set | 448 // Allow search suggestions. In extended mode, SearchModeChanged() will set |
450 // this, but it's not called in non-extended mode, so fake it. | 449 // this, but it's not called in non-extended mode, so fake it. |
451 if (!extended_enabled_) | 450 if (!extended_enabled_) |
452 search_mode_.mode = SearchMode::MODE_SEARCH_SUGGESTIONS; | 451 search_mode_.mode = SearchMode::MODE_SEARCH_SUGGESTIONS; |
453 | 452 |
454 if (UseInstantTabToShowSuggestions()) { | 453 if (instant_tab_) { |
455 // If we have an |instant_tab_| but it doesn't support Instant yet, sever | 454 // If we have an |instant_tab_| but it doesn't support Instant yet, sever |
456 // the connection to it so we use the overlay instead. This ensures that the | 455 // the connection to it so we use the overlay instead. This ensures that the |
457 // user interaction will be responsive and handles cases where | 456 // user interaction will be responsive and handles cases where |
458 // |instant_tab_| never responds about whether it supports Instant. | 457 // |instant_tab_| never responds about whether it supports Instant. |
459 if (instant_tab_->supports_instant()) | 458 if (instant_tab_->supports_instant()) |
460 instant_tab_->Update(user_text, selection_start, selection_end, verbatim); | 459 instant_tab_->Update(user_text, selection_start, selection_end, verbatim); |
461 else | 460 else |
462 instant_tab_.reset(); | 461 instant_tab_.reset(); |
463 } | 462 } |
464 | 463 |
465 if (!UseInstantTabToShowSuggestions()) { | 464 if (!instant_tab_) { |
466 if (first_interaction_time_.is_null()) | 465 if (first_interaction_time_.is_null()) |
467 first_interaction_time_ = base::Time::Now(); | 466 first_interaction_time_ = base::Time::Now(); |
468 allow_overlay_to_show_search_suggestions_ = true; | 467 allow_overlay_to_show_search_suggestions_ = true; |
469 | 468 |
470 // For extended mode, if the loader is not ready at this point, switch over | 469 // For extended mode, if the loader is not ready at this point, switch over |
471 // to a backup loader. | 470 // to a backup loader. |
472 if (extended_enabled_ && !overlay_->supports_instant() && | 471 if (extended_enabled_ && !overlay_->supports_instant() && |
473 !overlay_->IsLocalOverlay() && browser_->GetActiveWebContents()) { | 472 !overlay_->IsLocal() && browser_->GetActiveWebContents()) { |
474 CreateOverlay(chrome::kChromeSearchLocalOmniboxPopupURL, | 473 CreateOverlay(chrome::GetLocalInstantURL(browser_->profile()).spec(), |
475 browser_->GetActiveWebContents()); | 474 browser_->GetActiveWebContents()); |
476 } | 475 } |
477 | 476 |
478 overlay_->Update(extended_enabled_ ? user_text : full_text, | 477 overlay_->Update(extended_enabled_ ? user_text : full_text, |
479 selection_start, selection_end, verbatim); | 478 selection_start, selection_end, verbatim); |
480 } | 479 } |
481 | 480 |
482 content::NotificationService::current()->Notify( | 481 content::NotificationService::current()->Notify( |
483 chrome::NOTIFICATION_INSTANT_CONTROLLER_UPDATED, | 482 chrome::NOTIFICATION_INSTANT_CONTROLLER_UPDATED, |
484 content::Source<InstantController>(this), | 483 content::Source<InstantController>(this), |
485 content::NotificationService::NoDetails()); | 484 content::NotificationService::NoDetails()); |
486 | 485 |
487 // We don't have new suggestions yet, but we can either reuse the existing | 486 // We don't have new suggestions yet, but we can either reuse the existing |
488 // suggestion or reset the existing "gray text". | 487 // suggestion or reset the existing "gray text". |
489 browser_->SetInstantSuggestion(last_suggestion_); | 488 browser_->SetInstantSuggestion(last_suggestion_); |
490 | 489 |
491 return true; | 490 return true; |
492 } | 491 } |
493 | 492 |
494 scoped_ptr<content::WebContents> InstantController::ReleaseNTPContents() { | 493 scoped_ptr<content::WebContents> InstantController::ReleaseNTPContents() { |
495 if (!extended_enabled_ || !browser_->profile() || | 494 if (!extended_enabled_ || !browser_->profile() || |
496 browser_->profile()->IsOffTheRecord()) | 495 browser_->profile()->IsOffTheRecord()) |
497 return scoped_ptr<content::WebContents>(NULL); | 496 return scoped_ptr<content::WebContents>(NULL); |
498 | 497 |
499 LOG_INSTANT_DEBUG_EVENT(this, "ReleaseNTPContents"); | 498 LOG_INSTANT_DEBUG_EVENT(this, "ReleaseNTPContents"); |
500 | 499 |
501 // Switch to the local NTP unless we're already using one. | 500 // TODO(jeremycho): Add tests for this logic. |
502 if (!ntp_ || (ShouldSwitchToLocalNTP() && !ntp_->IsLocalNTP())) | 501 if (ShouldSwitchToLocalNTP()) |
503 ResetNTP(false, true); | 502 ResetNTP(false, true); |
504 | 503 |
505 scoped_ptr<content::WebContents> ntp_contents = ntp_->ReleaseContents(); | 504 scoped_ptr<content::WebContents> ntp_contents = ntp_->ReleaseContents(); |
506 | 505 |
507 // Override the blacklist on an explicit user action. | 506 // Override the blacklist on an explicit user action. |
508 ResetNTP(true, false); | 507 ResetNTP(true, false); |
509 return ntp_contents.Pass(); | 508 return ntp_contents.Pass(); |
510 } | 509 } |
511 | 510 |
512 // TODO(tonyg): This method only fires when the omnibox bounds change. It also | 511 // TODO(tonyg): This method only fires when the omnibox bounds change. It also |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
554 // as it stops autocomplete. Ignore these. | 553 // as it stops autocomplete. Ignore these. |
555 if (omnibox_focus_state_ == OMNIBOX_FOCUS_NONE) | 554 if (omnibox_focus_state_ == OMNIBOX_FOCUS_NONE) |
556 return; | 555 return; |
557 | 556 |
558 DVLOG(1) << "AutocompleteResults:"; | 557 DVLOG(1) << "AutocompleteResults:"; |
559 std::vector<InstantAutocompleteResult> results; | 558 std::vector<InstantAutocompleteResult> results; |
560 for (ACProviders::const_iterator provider = providers.begin(); | 559 for (ACProviders::const_iterator provider = providers.begin(); |
561 provider != providers.end(); ++provider) { | 560 provider != providers.end(); ++provider) { |
562 const bool from_search_provider = | 561 const bool from_search_provider = |
563 (*provider)->type() == AutocompleteProvider::TYPE_SEARCH; | 562 (*provider)->type() == AutocompleteProvider::TYPE_SEARCH; |
564 // Unless we are talking to the local overlay, skip SearchProvider, since | 563 const bool using_local_page = |
565 // it only echoes suggestions. | 564 (instant_tab_ && instant_tab_->IsLocal()) || overlay_->IsLocal(); |
566 if (from_search_provider && | 565 // Unless we are talking to a local page, skip SearchProvider, since it only |
567 (UseInstantTabToShowSuggestions() || !overlay_->IsLocalOverlay())) | 566 // echoes suggestions. |
| 567 if (from_search_provider && !using_local_page) |
568 continue; | 568 continue; |
569 // Only send autocomplete results when all the providers are done. Skip | 569 // Only send autocomplete results when all the providers are done. Skip |
570 // this check for the SearchProvider, since it isn't done until the page | 570 // this check for the SearchProvider, since it isn't done until the page |
571 // calls SetSuggestions (causing SearchProvider::FinalizeInstantQuery() to | 571 // calls SetSuggestions (causing SearchProvider::FinalizeInstantQuery() to |
572 // be called), which makes it a chicken-and-egg thing. | 572 // be called), which makes it a chicken-and-egg thing. |
573 if (!from_search_provider && !(*provider)->done()) { | 573 if (!from_search_provider && !(*provider)->done()) { |
574 DVLOG(1) << "Waiting for " << (*provider)->GetName(); | 574 DVLOG(1) << "Waiting for " << (*provider)->GetName(); |
575 return; | 575 return; |
576 } | 576 } |
577 for (ACMatches::const_iterator match = (*provider)->matches().begin(); | 577 for (ACMatches::const_iterator match = (*provider)->matches().begin(); |
(...skipping 11 matching lines...) Expand all Loading... |
589 << result.provider << " " << result.destination_url << " '" | 589 << result.provider << " " << result.destination_url << " '" |
590 << result.description << "' '" << result.search_query << "' " | 590 << result.description << "' '" << result.search_query << "' " |
591 << result.transition; | 591 << result.transition; |
592 results.push_back(result); | 592 results.push_back(result); |
593 } | 593 } |
594 } | 594 } |
595 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( | 595 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( |
596 "HandleAutocompleteResults: total_results=%d", | 596 "HandleAutocompleteResults: total_results=%d", |
597 static_cast<int>(results.size()))); | 597 static_cast<int>(results.size()))); |
598 | 598 |
599 if (UseInstantTabToShowSuggestions()) | 599 if (instant_tab_) |
600 instant_tab_->SendAutocompleteResults(results); | 600 instant_tab_->SendAutocompleteResults(results); |
601 else | 601 else |
602 overlay_->SendAutocompleteResults(results); | 602 overlay_->SendAutocompleteResults(results); |
603 } | 603 } |
604 | 604 |
605 bool InstantController::OnUpOrDownKeyPressed(int count) { | 605 bool InstantController::OnUpOrDownKeyPressed(int count) { |
606 if (!extended_enabled_) | 606 if (!extended_enabled_) |
607 return false; | 607 return false; |
608 | 608 |
609 if (!instant_tab_ && !overlay_) | 609 if (!instant_tab_ && !overlay_) |
610 return false; | 610 return false; |
611 | 611 |
612 if (UseInstantTabToShowSuggestions()) | 612 if (instant_tab_) |
613 instant_tab_->UpOrDownKeyPressed(count); | 613 instant_tab_->UpOrDownKeyPressed(count); |
614 else | 614 else |
615 overlay_->UpOrDownKeyPressed(count); | 615 overlay_->UpOrDownKeyPressed(count); |
616 | 616 |
617 return true; | 617 return true; |
618 } | 618 } |
619 | 619 |
620 void InstantController::OnCancel(const AutocompleteMatch& match, | 620 void InstantController::OnCancel(const AutocompleteMatch& match, |
621 const string16& user_text, | 621 const string16& user_text, |
622 const string16& full_text) { | 622 const string16& full_text) { |
623 if (!extended_enabled_) | 623 if (!extended_enabled_) |
624 return; | 624 return; |
625 | 625 |
626 if (!instant_tab_ && !overlay_) | 626 if (!instant_tab_ && !overlay_) |
627 return; | 627 return; |
628 | 628 |
629 // We manually reset the state here since the JS is not expected to do it. | 629 // We manually reset the state here since the JS is not expected to do it. |
630 // TODO(sreeram): Handle the case where user_text is now a URL | 630 // TODO(sreeram): Handle the case where user_text is now a URL |
631 last_match_was_search_ = AutocompleteMatch::IsSearchType(match.type) && | 631 last_match_was_search_ = AutocompleteMatch::IsSearchType(match.type) && |
632 !full_text.empty(); | 632 !full_text.empty(); |
633 last_omnibox_text_ = full_text; | 633 last_omnibox_text_ = full_text; |
634 last_user_text_ = user_text; | 634 last_user_text_ = user_text; |
635 last_suggestion_ = InstantSuggestion(); | 635 last_suggestion_ = InstantSuggestion(); |
636 | 636 |
637 // Say |full_text| is "amazon.com" and |user_text| is "ama". This means the | 637 // Say |full_text| is "amazon.com" and |user_text| is "ama". This means the |
638 // inline autocompletion is "zon.com"; so the selection should span from | 638 // inline autocompletion is "zon.com"; so the selection should span from |
639 // user_text.size() to full_text.size(). The selection bounds are inverted | 639 // user_text.size() to full_text.size(). The selection bounds are inverted |
640 // because the caret is at the end of |user_text|, not |full_text|. | 640 // because the caret is at the end of |user_text|, not |full_text|. |
641 if (UseInstantTabToShowSuggestions()) { | 641 if (instant_tab_) { |
642 instant_tab_->CancelSelection(user_text, full_text.size(), user_text.size(), | 642 instant_tab_->CancelSelection(user_text, full_text.size(), user_text.size(), |
643 last_verbatim_); | 643 last_verbatim_); |
644 } else { | 644 } else { |
645 overlay_->CancelSelection(user_text, full_text.size(), user_text.size(), | 645 overlay_->CancelSelection(user_text, full_text.size(), user_text.size(), |
646 last_verbatim_); | 646 last_verbatim_); |
647 } | 647 } |
648 } | 648 } |
649 | 649 |
650 void InstantController::OmniboxNavigateToURL() { | 650 void InstantController::OmniboxNavigateToURL() { |
651 if (!extended_enabled_) | 651 if (!extended_enabled_) |
(...skipping 18 matching lines...) Expand all Loading... |
670 return false; | 670 return false; |
671 | 671 |
672 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( | 672 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( |
673 "CommitIfPossible: type=%d last_omnibox_text_='%s' " | 673 "CommitIfPossible: type=%d last_omnibox_text_='%s' " |
674 "last_match_was_search_=%d instant_tab_=%d", type, | 674 "last_match_was_search_=%d instant_tab_=%d", type, |
675 UTF16ToUTF8(last_omnibox_text_).c_str(), last_match_was_search_, | 675 UTF16ToUTF8(last_omnibox_text_).c_str(), last_match_was_search_, |
676 instant_tab_ != NULL)); | 676 instant_tab_ != NULL)); |
677 | 677 |
678 // If we are on an already committed search results page, send a submit event | 678 // If we are on an already committed search results page, send a submit event |
679 // to the page, but otherwise, nothing else to do. | 679 // to the page, but otherwise, nothing else to do. |
680 if (UseInstantTabToShowSuggestions()) { | 680 if (instant_tab_) { |
681 if (type == INSTANT_COMMIT_PRESSED_ENTER && | 681 if (type == INSTANT_COMMIT_PRESSED_ENTER && |
| 682 !instant_tab_->IsLocal() && |
682 (last_match_was_search_ || | 683 (last_match_was_search_ || |
683 last_suggestion_.behavior == INSTANT_COMPLETE_NEVER)) { | 684 last_suggestion_.behavior == INSTANT_COMPLETE_NEVER)) { |
684 last_suggestion_.text.clear(); | 685 last_suggestion_.text.clear(); |
685 instant_tab_->Submit(last_omnibox_text_); | 686 instant_tab_->Submit(last_omnibox_text_); |
686 instant_tab_->contents()->GetView()->Focus(); | 687 instant_tab_->contents()->GetView()->Focus(); |
687 EnsureSearchTermsAreSet(instant_tab_->contents(), last_omnibox_text_); | 688 EnsureSearchTermsAreSet(instant_tab_->contents(), last_omnibox_text_); |
688 return true; | 689 return true; |
689 } | 690 } |
690 return false; | 691 return false; |
691 } | 692 } |
692 | 693 |
693 // If the overlay is not showing at all, don't commit it. | 694 // If the overlay is not showing at all, don't commit it. |
694 if (!model_.mode().is_search_suggestions()) | 695 if (!model_.mode().is_search_suggestions()) |
695 return false; | 696 return false; |
696 | 697 |
697 // If the overlay is showing at full height (with results), commit it. | 698 // If the overlay is showing at full height (with results), commit it. |
698 // If it's showing at parial height, commit if it's navigating. | 699 // If it's showing at parial height, commit if it's navigating. |
699 if (!IsOverlayingSearchResults() && type != INSTANT_COMMIT_NAVIGATED) | 700 if (!IsOverlayingSearchResults() && type != INSTANT_COMMIT_NAVIGATED) |
700 return false; | 701 return false; |
701 | 702 |
702 // There may re-entrance here, from the call to browser_->CommitInstant below, | 703 // There may re-entrance here, from the call to browser_->CommitInstant below, |
703 // which can cause a TabDeactivated notification which gets back here. | 704 // which can cause a TabDeactivated notification which gets back here. |
704 // In this case, overlay_->ReleaseContents() was called already. | 705 // In this case, overlay_->ReleaseContents() was called already. |
705 if (!GetOverlayContents()) | 706 if (!GetOverlayContents()) |
706 return false; | 707 return false; |
707 | 708 |
708 // Never commit the local overlay. | 709 // Never commit the local overlay. |
709 if (overlay_->IsLocalOverlay()) | 710 if (overlay_->IsLocal()) |
710 return false; | 711 return false; |
711 | 712 |
712 if (type == INSTANT_COMMIT_FOCUS_LOST) { | 713 if (type == INSTANT_COMMIT_FOCUS_LOST) { |
713 // Extended mode doesn't need or use the Cancel message. | 714 // Extended mode doesn't need or use the Cancel message. |
714 if (!extended_enabled_) | 715 if (!extended_enabled_) |
715 overlay_->Cancel(last_omnibox_text_); | 716 overlay_->Cancel(last_omnibox_text_); |
716 } else if (type != INSTANT_COMMIT_NAVIGATED) { | 717 } else if (type != INSTANT_COMMIT_NAVIGATED) { |
717 overlay_->Submit(last_omnibox_text_); | 718 overlay_->Submit(last_omnibox_text_); |
718 } | 719 } |
719 | 720 |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
931 #if defined(USE_AURA) | 932 #if defined(USE_AURA) |
932 // On aura the omnibox only receives a focus lost if we initiate the focus | 933 // On aura the omnibox only receives a focus lost if we initiate the focus |
933 // change. This does that. | 934 // change. This does that. |
934 if (!model_.mode().is_default()) | 935 if (!model_.mode().is_default()) |
935 browser_->InstantOverlayFocused(); | 936 browser_->InstantOverlayFocused(); |
936 #endif | 937 #endif |
937 } | 938 } |
938 | 939 |
939 void InstantController::ReloadOverlayIfStale() { | 940 void InstantController::ReloadOverlayIfStale() { |
940 // The local overlay is never stale. | 941 // The local overlay is never stale. |
941 if (overlay_ && overlay_->IsLocalOverlay()) | 942 if (overlay_ && overlay_->IsLocal()) |
942 return; | 943 return; |
943 | 944 |
944 // If the overlay is showing or the omnibox has focus, don't delete the | 945 // If the overlay is showing or the omnibox has focus, don't delete the |
945 // overlay. It will get refreshed the next time the overlay is hidden or the | 946 // overlay. It will get refreshed the next time the overlay is hidden or the |
946 // omnibox loses focus. | 947 // omnibox loses focus. |
947 if ((!overlay_ || overlay_->is_stale()) && | 948 if ((!overlay_ || overlay_->is_stale()) && |
948 omnibox_focus_state_ == OMNIBOX_FOCUS_NONE && | 949 omnibox_focus_state_ == OMNIBOX_FOCUS_NONE && |
949 model_.mode().is_default()) { | 950 model_.mode().is_default()) { |
950 overlay_.reset(); | 951 overlay_.reset(); |
951 EnsureOverlayIsCurrent(false); | 952 EnsureOverlayIsCurrent(false); |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1121 } | 1122 } |
1122 | 1123 |
1123 void InstantController::SetSuggestions( | 1124 void InstantController::SetSuggestions( |
1124 const content::WebContents* contents, | 1125 const content::WebContents* contents, |
1125 const std::vector<InstantSuggestion>& suggestions) { | 1126 const std::vector<InstantSuggestion>& suggestions) { |
1126 LOG_INSTANT_DEBUG_EVENT(this, "SetSuggestions"); | 1127 LOG_INSTANT_DEBUG_EVENT(this, "SetSuggestions"); |
1127 | 1128 |
1128 // Ignore if the message is from an unexpected source. | 1129 // Ignore if the message is from an unexpected source. |
1129 if (IsContentsFrom(ntp(), contents)) | 1130 if (IsContentsFrom(ntp(), contents)) |
1130 return; | 1131 return; |
1131 if (UseInstantTabToShowSuggestions() && | 1132 if (instant_tab_ && !IsContentsFrom(instant_tab(), contents)) |
1132 !IsContentsFrom(instant_tab(), contents)) | |
1133 return; | 1133 return; |
1134 if (IsContentsFrom(overlay(), contents) && | 1134 if (IsContentsFrom(overlay(), contents) && |
1135 !allow_overlay_to_show_search_suggestions_) | 1135 !allow_overlay_to_show_search_suggestions_) |
1136 return; | 1136 return; |
1137 | 1137 |
1138 InstantSuggestion suggestion; | 1138 InstantSuggestion suggestion; |
1139 if (!suggestions.empty()) | 1139 if (!suggestions.empty()) |
1140 suggestion = suggestions[0]; | 1140 suggestion = suggestions[0]; |
1141 | 1141 |
1142 // TODO(samarth): allow InstantTabs to call SetSuggestions() from the NTP once | 1142 // TODO(samarth): allow InstantTabs to call SetSuggestions() from the NTP once |
1143 // that is better supported. | 1143 // that is better supported. |
1144 bool can_use_instant_tab = UseInstantTabToShowSuggestions() && | 1144 bool can_use_instant_tab = instant_tab_ && search_mode_.is_search(); |
1145 search_mode_.is_search(); | |
1146 bool can_use_overlay = search_mode_.is_search_suggestions() && | 1145 bool can_use_overlay = search_mode_.is_search_suggestions() && |
1147 !last_omnibox_text_.empty(); | 1146 !last_omnibox_text_.empty(); |
1148 if (!can_use_instant_tab && !can_use_overlay) | 1147 if (!can_use_instant_tab && !can_use_overlay) |
1149 return; | 1148 return; |
1150 | 1149 |
1151 if (suggestion.behavior == INSTANT_COMPLETE_REPLACE) { | 1150 if (suggestion.behavior == INSTANT_COMPLETE_REPLACE) { |
1152 // We don't get an Update() when changing the omnibox due to a REPLACE | 1151 // We don't get an Update() when changing the omnibox due to a REPLACE |
1153 // suggestion (so that we don't inadvertently cause the overlay to change | 1152 // suggestion (so that we don't inadvertently cause the overlay to change |
1154 // what it's showing, as the user arrows up/down through the page-provided | 1153 // what it's showing, as the user arrows up/down through the page-provided |
1155 // suggestions). So, update these state variables here. | 1154 // suggestions). So, update these state variables here. |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1270 else if (!IsViewInContents(GetViewGainingFocus(view_gaining_focus), | 1269 else if (!IsViewInContents(GetViewGainingFocus(view_gaining_focus), |
1271 overlay_->contents())) | 1270 overlay_->contents())) |
1272 HideOverlay(); | 1271 HideOverlay(); |
1273 #endif | 1272 #endif |
1274 } | 1273 } |
1275 | 1274 |
1276 void InstantController::ResetNTP(bool ignore_blacklist, bool use_local_ntp) { | 1275 void InstantController::ResetNTP(bool ignore_blacklist, bool use_local_ntp) { |
1277 std::string instant_url; | 1276 std::string instant_url; |
1278 if (use_local_ntp || | 1277 if (use_local_ntp || |
1279 !GetInstantURL(browser_->profile(), ignore_blacklist, &instant_url)) | 1278 !GetInstantURL(browser_->profile(), ignore_blacklist, &instant_url)) |
1280 instant_url = chrome::kChromeSearchLocalNtpUrl; | 1279 instant_url = chrome::GetLocalInstantURL(browser_->profile()).spec(); |
1281 ntp_.reset(new InstantNTP(this, instant_url)); | 1280 ntp_.reset(new InstantNTP(this, instant_url)); |
1282 ntp_->InitContents(browser_->profile(), browser_->GetActiveWebContents(), | 1281 ntp_->InitContents(browser_->profile(), browser_->GetActiveWebContents(), |
1283 base::Bind(&InstantController::ResetNTP, | 1282 base::Bind(&InstantController::ResetNTP, |
1284 base::Unretained(this), false, false)); | 1283 base::Unretained(this), false, false)); |
1285 } | 1284 } |
1286 | 1285 |
1287 bool InstantController::EnsureOverlayIsCurrent(bool ignore_blacklist) { | 1286 bool InstantController::EnsureOverlayIsCurrent(bool ignore_blacklist) { |
1288 // If there's no active tab, the browser is closing. | 1287 // If there's no active tab, the browser is closing. |
1289 const content::WebContents* active_tab = browser_->GetActiveWebContents(); | 1288 const content::WebContents* active_tab = browser_->GetActiveWebContents(); |
1290 if (!active_tab) | 1289 if (!active_tab) |
1291 return false; | 1290 return false; |
1292 | 1291 |
1293 Profile* profile = Profile::FromBrowserContext( | 1292 Profile* profile = Profile::FromBrowserContext( |
1294 active_tab->GetBrowserContext()); | 1293 active_tab->GetBrowserContext()); |
1295 std::string instant_url; | 1294 std::string instant_url; |
1296 if (!GetInstantURL(profile, ignore_blacklist, &instant_url)) { | 1295 if (!GetInstantURL(profile, ignore_blacklist, &instant_url)) { |
1297 // If we are in extended mode, fallback to the local overlay. | 1296 // If we are in extended mode, fallback to the local overlay. |
1298 if (extended_enabled_) | 1297 if (extended_enabled_) |
1299 instant_url = chrome::kChromeSearchLocalOmniboxPopupURL; | 1298 instant_url = chrome::GetLocalInstantURL(browser_->profile()).spec(); |
1300 else | 1299 else |
1301 return false; | 1300 return false; |
1302 } | 1301 } |
1303 | 1302 |
1304 if (!overlay_ || overlay_->instant_url() != instant_url) | 1303 if (!overlay_ || overlay_->instant_url() != instant_url) |
1305 CreateOverlay(instant_url, active_tab); | 1304 CreateOverlay(instant_url, active_tab); |
1306 | 1305 |
1307 return true; | 1306 return true; |
1308 } | 1307 } |
1309 | 1308 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1371 // Send a message asking the overlay to clear out old results. | 1370 // Send a message asking the overlay to clear out old results. |
1372 overlay_->Update(string16(), 0, 0, true); | 1371 overlay_->Update(string16(), 0, 0, true); |
1373 } | 1372 } |
1374 | 1373 |
1375 // Clear the first interaction timestamp for later use. | 1374 // Clear the first interaction timestamp for later use. |
1376 first_interaction_time_ = base::Time(); | 1375 first_interaction_time_ = base::Time(); |
1377 } | 1376 } |
1378 | 1377 |
1379 void InstantController::ShowOverlay(int height, InstantSizeUnits units) { | 1378 void InstantController::ShowOverlay(int height, InstantSizeUnits units) { |
1380 // If we are on a committed search results page, the |overlay_| is not in use. | 1379 // If we are on a committed search results page, the |overlay_| is not in use. |
1381 if (UseInstantTabToShowSuggestions()) | 1380 if (instant_tab_) |
1382 return; | 1381 return; |
1383 | 1382 |
1384 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( | 1383 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( |
1385 "Show: height=%d units=%d", height, units)); | 1384 "Show: height=%d units=%d", height, units)); |
1386 | 1385 |
1387 // Must have updated omnibox after the last HideOverlay() to show suggestions. | 1386 // Must have updated omnibox after the last HideOverlay() to show suggestions. |
1388 if (!allow_overlay_to_show_search_suggestions_) | 1387 if (!allow_overlay_to_show_search_suggestions_) |
1389 return; | 1388 return; |
1390 | 1389 |
1391 // The page is trying to hide itself. Hide explicitly (i.e., don't use | 1390 // The page is trying to hide itself. Hide explicitly (i.e., don't use |
1392 // HideOverlay()) so that it can change its mind. | 1391 // HideOverlay()) so that it can change its mind. |
1393 if (height == 0) { | 1392 if (height == 0) { |
1394 model_.SetOverlayState(SearchMode(), 0, INSTANT_SIZE_PERCENT); | 1393 model_.SetOverlayState(SearchMode(), 0, INSTANT_SIZE_PERCENT); |
1395 return; | 1394 return; |
1396 } | 1395 } |
1397 | 1396 |
1398 // If the overlay is being shown for the first time since the user started | 1397 // If the overlay is being shown for the first time since the user started |
1399 // typing, record a histogram value. | 1398 // typing, record a histogram value. |
1400 if (!first_interaction_time_.is_null() && model_.mode().is_default()) { | 1399 if (!first_interaction_time_.is_null() && model_.mode().is_default()) { |
1401 base::TimeDelta delta = base::Time::Now() - first_interaction_time_; | 1400 base::TimeDelta delta = base::Time::Now() - first_interaction_time_; |
1402 UMA_HISTOGRAM_TIMES("Instant.TimeToFirstShow", delta); | 1401 UMA_HISTOGRAM_TIMES("Instant.TimeToFirstShow", delta); |
1403 } | 1402 } |
1404 | 1403 |
1405 // Show at 100% height except in the following cases: | 1404 // Show at 100% height except in the following cases: |
1406 // - The local overlay (omnibox popup) is being loaded. | 1405 // - The local overlay (omnibox popup) is being loaded. |
1407 // - Instant is disabled. The page needs to be able to show only a dropdown. | 1406 // - Instant is disabled. The page needs to be able to show only a dropdown. |
1408 // - The page is over a website other than search or an NTP, and is not | 1407 // - The page is over a website other than search or an NTP, and is not |
1409 // already showing at 100% height. | 1408 // already showing at 100% height. |
1410 if (overlay_->IsLocalOverlay() || !instant_enabled_ || | 1409 if (overlay_->IsLocal() || !instant_enabled_ || |
1411 (search_mode_.is_origin_default() && !IsFullHeight(model_))) | 1410 (search_mode_.is_origin_default() && !IsFullHeight(model_))) |
1412 model_.SetOverlayState(search_mode_, height, units); | 1411 model_.SetOverlayState(search_mode_, height, units); |
1413 else | 1412 else |
1414 model_.SetOverlayState(search_mode_, 100, INSTANT_SIZE_PERCENT); | 1413 model_.SetOverlayState(search_mode_, 100, INSTANT_SIZE_PERCENT); |
1415 | 1414 |
1416 // If the overlay is being shown at full height and the omnibox is not | 1415 // If the overlay is being shown at full height and the omnibox is not |
1417 // focused, commit right away. | 1416 // focused, commit right away. |
1418 if (IsFullHeight(model_) && omnibox_focus_state_ == OMNIBOX_FOCUS_NONE) | 1417 if (IsFullHeight(model_) && omnibox_focus_state_ == OMNIBOX_FOCUS_NONE) |
1419 CommitIfPossible(INSTANT_COMMIT_FOCUS_LOST); | 1418 CommitIfPossible(INSTANT_COMMIT_FOCUS_LOST); |
1420 } | 1419 } |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1616 // suggest 'nstant'. Otherwise, the user text really isn't a prefix, so | 1615 // suggest 'nstant'. Otherwise, the user text really isn't a prefix, so |
1617 // suggest nothing. | 1616 // suggest nothing. |
1618 // TODO(samarth|jered): revisit this logic. http://crbug.com/196572. | 1617 // TODO(samarth|jered): revisit this logic. http://crbug.com/196572. |
1619 return true; | 1618 return true; |
1620 } | 1619 } |
1621 } | 1620 } |
1622 | 1621 |
1623 return false; | 1622 return false; |
1624 } | 1623 } |
1625 | 1624 |
1626 bool InstantController::UseInstantTabToShowSuggestions() const { | 1625 bool InstantController::ShouldSwitchToLocalNTP() const { |
1627 return instant_tab_ && !instant_tab_->IsLocalNTP(); | 1626 if (!ntp_) |
1628 } | 1627 return true; |
1629 | 1628 |
1630 bool InstantController::ShouldSwitchToLocalNTP() const { | 1629 // Don't switch if already using the correct local NTP. |
| 1630 if (ntp_->instant_url() == chrome::GetLocalInstantURL( |
| 1631 browser_->profile()).spec()) { |
| 1632 return false; |
| 1633 } |
| 1634 |
1631 // If there is no Instant URL or the NTP is stale, switch. | 1635 // If there is no Instant URL or the NTP is stale, switch. |
1632 std::string instant_url; | 1636 std::string instant_url; |
1633 if (!GetInstantURL(browser_->profile(), false, &instant_url) || | 1637 if (!GetInstantURL(browser_->profile(), false, &instant_url) || |
1634 !chrome::MatchesOriginAndPath(GURL(ntp_->instant_url()), | 1638 !chrome::MatchesOriginAndPath(GURL(ntp_->instant_url()), |
1635 GURL(instant_url))) { | 1639 GURL(instant_url))) { |
1636 return true; | 1640 return true; |
1637 } | 1641 } |
1638 | 1642 |
1639 if (ntp_->supports_instant()) | 1643 if (ntp_->supports_instant()) |
1640 return false; | 1644 return false; |
1641 | 1645 |
1642 // If this is not window startup, switch. | 1646 // If this is not window startup, switch. |
1643 // TODO(shishir): This is not completely reliable. Find a better way to detect | 1647 // TODO(shishir): This is not completely reliable. Find a better way to detect |
1644 // startup time. | 1648 // startup time. |
1645 if (browser_->GetActiveWebContents()) | 1649 if (browser_->GetActiveWebContents()) |
1646 return true; | 1650 return true; |
1647 | 1651 |
1648 return chrome::IsAggressiveLocalNTPFallbackEnabled(); | 1652 return chrome::IsAggressiveLocalNTPFallbackEnabled(); |
1649 } | 1653 } |
OLD | NEW |