| 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 |