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/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/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 InstantController::InstantController(chrome::BrowserInstantController* browser, | 145 InstantController::InstantController(chrome::BrowserInstantController* browser, |
146 bool extended_enabled) | 146 bool extended_enabled) |
147 : browser_(browser), | 147 : browser_(browser), |
148 extended_enabled_(extended_enabled), | 148 extended_enabled_(extended_enabled), |
149 instant_enabled_(false), | 149 instant_enabled_(false), |
150 model_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), | 150 model_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), |
151 last_omnibox_text_has_inline_autocompletion_(false), | 151 last_omnibox_text_has_inline_autocompletion_(false), |
152 last_verbatim_(false), | 152 last_verbatim_(false), |
153 last_transition_type_(content::PAGE_TRANSITION_LINK), | 153 last_transition_type_(content::PAGE_TRANSITION_LINK), |
154 last_match_was_search_(false), | 154 last_match_was_search_(false), |
155 is_omnibox_focused_(false), | 155 omnibox_focus_state_(FOCUS_NONE), |
156 allow_preview_to_show_search_suggestions_(false) { | 156 allow_preview_to_show_search_suggestions_(false) { |
157 } | 157 } |
158 | 158 |
159 InstantController::~InstantController() { | 159 InstantController::~InstantController() { |
160 } | 160 } |
161 | 161 |
162 bool InstantController::Update(const AutocompleteMatch& match, | 162 bool InstantController::Update(const AutocompleteMatch& match, |
163 const string16& user_text, | 163 const string16& user_text, |
164 const string16& full_text, | 164 const string16& full_text, |
165 size_t selection_start, | 165 size_t selection_start, |
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
527 // Delay deletion as we could've gotten here from an InstantLoader method. | 527 // Delay deletion as we could've gotten here from an InstantLoader method. |
528 MessageLoop::current()->DeleteSoon(FROM_HERE, loader_.release()); | 528 MessageLoop::current()->DeleteSoon(FROM_HERE, loader_.release()); |
529 | 529 |
530 // Try to create another loader immediately so that it is ready for the next | 530 // Try to create another loader immediately so that it is ready for the next |
531 // user interaction. | 531 // user interaction. |
532 CreateDefaultLoader(); | 532 CreateDefaultLoader(); |
533 | 533 |
534 return true; | 534 return true; |
535 } | 535 } |
536 | 536 |
537 void InstantController::OmniboxLostFocus(gfx::NativeView view_gaining_focus) { | 537 void InstantController::OmniboxFocusChanged( |
538 DVLOG(1) << "OmniboxLostFocus"; | 538 OmniboxFocusState state, |
539 is_omnibox_focused_ = false; | 539 OmniboxFocusChangeReason reason, |
| 540 gfx::NativeView view_gaining_focus) { |
| 541 DVLOG(1) << "OmniboxFocusChanged: " << omnibox_focus_state_ << " to " |
| 542 << state << " for reason " << reason; |
540 | 543 |
| 544 OmniboxFocusState old_focus_state = omnibox_focus_state_; |
| 545 omnibox_focus_state_ = state; |
541 if (!extended_enabled_ && !instant_enabled_) | 546 if (!extended_enabled_ && !instant_enabled_) |
542 return; | 547 return; |
543 | 548 |
544 // If the preview is showing custom NTP content, don't hide it, commit it | 549 // Tell the page if the key capture mode changed unless the focus state |
545 // (no matter where the user clicked) or try to recreate it. | 550 // changed because of TYPING. This is because in that case, the browser hasn't |
546 if (model_.mode().is_ntp()) | 551 // really stopped capturing key strokes. |
547 return; | 552 // |
| 553 // (More practically, if we don't do this check, the page would receive |
| 554 // onkeycapturechange before the corresponding onchange, and the page would |
| 555 // have no way of telling whether the keycapturechange happened because of |
| 556 // some actual user action or just because they started typing.) |
| 557 if (extended_enabled_ && GetPreviewContents() && |
| 558 reason != FOCUS_CHANGE_TYPING) |
| 559 loader_->KeyCaptureChanged(omnibox_focus_state_ == FOCUS_INVISIBLE); |
548 | 560 |
549 // If the preview is not showing at all, recreate it if it's stale. | 561 // If focus went from outside the omnibox to the omnibox, preload the default |
550 if (model_.mode().is_default()) { | 562 // search engine, in anticipation of the user typing a query. If the reverse |
551 OnStaleLoader(); | 563 // happened, commit or discard the preview. |
552 return; | 564 if (state != FOCUS_NONE && old_focus_state == FOCUS_NONE) |
553 } | 565 CreateDefaultLoader(); |
554 | 566 else if (state == FOCUS_NONE && old_focus_state != FOCUS_NONE) |
555 // The preview is showing search suggestions. If GetPreviewContents() is NULL, | 567 OmniboxLostFocus(view_gaining_focus); |
556 // we are in the commit path. Don't do anything. | |
557 if (!GetPreviewContents()) | |
558 return; | |
559 | |
560 #if defined(OS_MACOSX) | |
561 // TODO(sreeram): See if Mac really needs this special treatment. | |
562 if (!loader_->is_pointer_down_from_activate()) | |
563 HideLoader(); | |
564 #else | |
565 // If the preview was clicked, commit if it was for a search; ignore the click | |
566 // if it was for a URL. If the preview was not clicked, hide it. | |
567 if (IsViewInContents(GetViewGainingFocus(view_gaining_focus), | |
568 loader_->contents())) { | |
569 if (last_match_was_search_) | |
570 CommitIfCurrent(INSTANT_COMMIT_FOCUS_LOST); | |
571 } else { | |
572 HideLoader(); | |
573 } | |
574 #endif | |
575 } | |
576 | |
577 void InstantController::OmniboxGotFocus() { | |
578 DVLOG(1) << "OmniboxGotFocus"; | |
579 is_omnibox_focused_ = true; | |
580 | |
581 if (!extended_enabled_ && !instant_enabled_) | |
582 return; | |
583 | |
584 CreateDefaultLoader(); | |
585 } | 568 } |
586 | 569 |
587 void InstantController::SearchModeChanged( | 570 void InstantController::SearchModeChanged( |
588 const chrome::search::Mode& old_mode, | 571 const chrome::search::Mode& old_mode, |
589 const chrome::search::Mode& new_mode) { | 572 const chrome::search::Mode& new_mode) { |
590 if (!extended_enabled_) | 573 if (!extended_enabled_) |
591 return; | 574 return; |
592 | 575 |
593 DVLOG(1) << "SearchModeChanged: [origin:mode] " << old_mode.origin << ":" | 576 DVLOG(1) << "SearchModeChanged: [origin:mode] " << old_mode.origin << ":" |
594 << old_mode.mode << " to " << new_mode.origin << ":" | 577 << old_mode.mode << " to " << new_mode.origin << ":" |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
784 | 767 |
785 void InstantController::InstantLoaderRenderViewGone() { | 768 void InstantController::InstantLoaderRenderViewGone() { |
786 ++blacklisted_urls_[loader_->instant_url()]; | 769 ++blacklisted_urls_[loader_->instant_url()]; |
787 HideInternal(); | 770 HideInternal(); |
788 delete loader_->ReleaseContents(); | 771 delete loader_->ReleaseContents(); |
789 // Delay deletion as we have gotten here from an InstantLoader method. | 772 // Delay deletion as we have gotten here from an InstantLoader method. |
790 MessageLoop::current()->DeleteSoon(FROM_HERE, loader_.release()); | 773 MessageLoop::current()->DeleteSoon(FROM_HERE, loader_.release()); |
791 CreateDefaultLoader(); | 774 CreateDefaultLoader(); |
792 } | 775 } |
793 | 776 |
| 777 void InstantController::OmniboxLostFocus(gfx::NativeView view_gaining_focus) { |
| 778 // If the preview is showing custom NTP content, don't hide it, commit it |
| 779 // (no matter where the user clicked) or try to recreate it. |
| 780 if (model_.mode().is_ntp()) |
| 781 return; |
| 782 |
| 783 // If the preview is not showing at all, recreate it if it's stale. |
| 784 if (model_.mode().is_default()) { |
| 785 OnStaleLoader(); |
| 786 return; |
| 787 } |
| 788 |
| 789 // The preview is showing search suggestions. If GetPreviewContents() is NULL, |
| 790 // we are in the commit path. Don't do anything. |
| 791 if (!GetPreviewContents()) |
| 792 return; |
| 793 |
| 794 #if defined(OS_MACOSX) |
| 795 // TODO(sreeram): See if Mac really needs this special treatment. |
| 796 if (!loader_->is_pointer_down_from_activate()) |
| 797 HideLoader(); |
| 798 #else |
| 799 // If the preview was clicked, commit if it was for a search; ignore the click |
| 800 // if it was for a URL. If the preview was not clicked, hide it. |
| 801 if (IsViewInContents(GetViewGainingFocus(view_gaining_focus), |
| 802 loader_->contents())) { |
| 803 if (last_match_was_search_) |
| 804 CommitIfCurrent(INSTANT_COMMIT_FOCUS_LOST); |
| 805 } else { |
| 806 HideLoader(); |
| 807 } |
| 808 #endif |
| 809 } |
| 810 |
794 bool InstantController::ResetLoader(const TemplateURL* template_url, | 811 bool InstantController::ResetLoader(const TemplateURL* template_url, |
795 const content::WebContents* active_tab) { | 812 const content::WebContents* active_tab) { |
796 std::string instant_url; | 813 std::string instant_url; |
797 if (!GetInstantURL(template_url, &instant_url)) | 814 if (!GetInstantURL(template_url, &instant_url)) |
798 return false; | 815 return false; |
799 | 816 |
800 if (loader_ && loader_->instant_url() == instant_url) | 817 if (loader_ && loader_->instant_url() == instant_url) |
801 return true; | 818 return true; |
802 | 819 |
803 HideInternal(); | 820 HideInternal(); |
804 loader_.reset(new InstantLoader(this, instant_url)); | 821 loader_.reset(new InstantLoader(this, instant_url)); |
805 loader_->InitContents(active_tab); | 822 loader_->InitContents(active_tab); |
806 | 823 |
807 // Ensure the searchbox API has the correct initial state. | 824 // Ensure the searchbox API has the correct initial state. |
808 if (extended_enabled_) { | 825 if (extended_enabled_) { |
809 browser_->UpdateThemeInfoForPreview(); | 826 browser_->UpdateThemeInfoForPreview(); |
810 loader_->SetDisplayInstantResults(instant_enabled_); | 827 loader_->SetDisplayInstantResults(instant_enabled_); |
811 loader_->SearchModeChanged(search_mode_); | 828 loader_->SearchModeChanged(search_mode_); |
| 829 loader_->KeyCaptureChanged(omnibox_focus_state_ == FOCUS_INVISIBLE); |
812 } | 830 } |
813 | 831 |
814 // Restart the stale loader timer. | 832 // Restart the stale loader timer. |
815 stale_loader_timer_.Start(FROM_HERE, | 833 stale_loader_timer_.Start(FROM_HERE, |
816 base::TimeDelta::FromMilliseconds(kStaleLoaderTimeoutMS), this, | 834 base::TimeDelta::FromMilliseconds(kStaleLoaderTimeoutMS), this, |
817 &InstantController::OnStaleLoader); | 835 &InstantController::OnStaleLoader); |
818 | 836 |
819 return true; | 837 return true; |
820 } | 838 } |
821 | 839 |
822 bool InstantController::CreateDefaultLoader() { | 840 bool InstantController::CreateDefaultLoader() { |
823 // If there's no active tab, the browser is closing. | 841 // If there's no active tab, the browser is closing. |
824 const content::WebContents* active_tab = browser_->GetActiveWebContents(); | 842 const content::WebContents* active_tab = browser_->GetActiveWebContents(); |
825 if (!active_tab) | 843 if (!active_tab) |
826 return false; | 844 return false; |
827 | 845 |
828 const TemplateURL* template_url = TemplateURLServiceFactory::GetForProfile( | 846 const TemplateURL* template_url = TemplateURLServiceFactory::GetForProfile( |
829 Profile::FromBrowserContext(active_tab->GetBrowserContext()))-> | 847 Profile::FromBrowserContext(active_tab->GetBrowserContext()))-> |
830 GetDefaultSearchProvider(); | 848 GetDefaultSearchProvider(); |
831 | 849 |
832 return ResetLoader(template_url, active_tab); | 850 return ResetLoader(template_url, active_tab); |
833 } | 851 } |
834 | 852 |
835 void InstantController::OnStaleLoader() { | 853 void InstantController::OnStaleLoader() { |
836 // If the preview is showing or the omnibox has focus, don't delete the | 854 // If the preview is showing or the omnibox has focus, don't delete the |
837 // loader. It will get refreshed the next time the preview is hidden or the | 855 // loader. It will get refreshed the next time the preview is hidden or the |
838 // omnibox loses focus. | 856 // omnibox loses focus. |
839 if (!stale_loader_timer_.IsRunning() && !is_omnibox_focused_ && | 857 if (!stale_loader_timer_.IsRunning() && omnibox_focus_state_ == FOCUS_NONE && |
840 model_.mode().is_default()) { | 858 model_.mode().is_default()) { |
841 loader_.reset(); | 859 loader_.reset(); |
842 CreateDefaultLoader(); | 860 CreateDefaultLoader(); |
843 } | 861 } |
844 } | 862 } |
845 | 863 |
846 void InstantController::ResetInstantTab() { | 864 void InstantController::ResetInstantTab() { |
847 if (search_mode_.is_origin_search()) { | 865 if (search_mode_.is_origin_search()) { |
848 content::WebContents* active_tab = browser_->GetActiveWebContents(); | 866 content::WebContents* active_tab = browser_->GetActiveWebContents(); |
849 if (!instant_tab_ || active_tab != instant_tab_->contents()) { | 867 if (!instant_tab_ || active_tab != instant_tab_->contents()) { |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1031 } | 1049 } |
1032 | 1050 |
1033 std::map<std::string, int>::const_iterator iter = | 1051 std::map<std::string, int>::const_iterator iter = |
1034 blacklisted_urls_.find(*instant_url); | 1052 blacklisted_urls_.find(*instant_url); |
1035 if (iter != blacklisted_urls_.end() && | 1053 if (iter != blacklisted_urls_.end() && |
1036 iter->second > kMaxInstantSupportFailures) | 1054 iter->second > kMaxInstantSupportFailures) |
1037 return false; | 1055 return false; |
1038 | 1056 |
1039 return true; | 1057 return true; |
1040 } | 1058 } |
OLD | NEW |