| 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/search_tab_helper.h" | 5 #include "chrome/browser/ui/search/search_tab_helper.h" |
| 6 | 6 |
| 7 #include "chrome/browser/profiles/profile.h" |
| 7 #include "chrome/browser/search/search.h" | 8 #include "chrome/browser/search/search.h" |
| 8 #include "chrome/common/render_messages.h" | 9 #include "chrome/common/render_messages.h" |
| 9 #include "chrome/common/url_constants.h" | 10 #include "chrome/common/url_constants.h" |
| 11 #include "content/public/browser/navigation_controller.h" |
| 12 #include "content/public/browser/navigation_details.h" |
| 10 #include "content/public/browser/navigation_entry.h" | 13 #include "content/public/browser/navigation_entry.h" |
| 14 #include "content/public/browser/navigation_type.h" |
| 11 #include "content/public/browser/notification_service.h" | 15 #include "content/public/browser/notification_service.h" |
| 12 #include "content/public/browser/notification_types.h" | 16 #include "content/public/browser/notification_types.h" |
| 17 #include "content/public/browser/web_contents.h" |
| 13 | 18 |
| 14 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SearchTabHelper); | 19 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SearchTabHelper); |
| 15 | 20 |
| 16 namespace { | 21 namespace { |
| 17 | 22 |
| 18 bool IsNTP(const content::WebContents* contents) { | 23 bool IsNTP(const content::WebContents* contents) { |
| 19 // We can't use WebContents::GetURL() because that uses the active entry, | 24 // We can't use WebContents::GetURL() because that uses the active entry, |
| 20 // whereas we want the visible entry. | 25 // whereas we want the visible entry. |
| 21 const content::NavigationEntry* entry = | 26 const content::NavigationEntry* entry = |
| 22 contents->GetController().GetVisibleEntry(); | 27 contents->GetController().GetVisibleEntry(); |
| 23 if (entry && entry->GetVirtualURL() == GURL(chrome::kChromeUINewTabURL)) | 28 if (entry && entry->GetVirtualURL() == GURL(chrome::kChromeUINewTabURL)) |
| 24 return true; | 29 return true; |
| 25 | 30 |
| 26 return chrome::IsInstantNTP(contents); | 31 return chrome::IsInstantNTP(contents); |
| 27 } | 32 } |
| 28 | 33 |
| 29 bool IsSearchResults(const content::WebContents* contents) { | 34 bool IsSearchResults(const content::WebContents* contents) { |
| 30 return !chrome::GetSearchTerms(contents).empty(); | 35 return !chrome::GetSearchTerms(contents).empty(); |
| 31 } | 36 } |
| 32 | 37 |
| 38 // TODO(kmadhusu): Move this helper from anonymous namespace to chrome |
| 39 // namespace and remove InstantPage::IsLocal(). |
| 40 bool IsLocal(const content::WebContents* contents) { |
| 41 return contents && |
| 42 (contents->GetURL() == GURL(chrome::kChromeSearchLocalNtpUrl) || |
| 43 contents->GetURL() == GURL(chrome::kChromeSearchLocalGoogleNtpUrl)); |
| 44 } |
| 45 |
| 33 } // namespace | 46 } // namespace |
| 34 | 47 |
| 35 SearchTabHelper::SearchTabHelper(content::WebContents* web_contents) | 48 SearchTabHelper::SearchTabHelper(content::WebContents* web_contents) |
| 36 : WebContentsObserver(web_contents), | 49 : WebContentsObserver(web_contents), |
| 37 is_search_enabled_(chrome::IsInstantExtendedAPIEnabled()), | 50 is_search_enabled_(chrome::IsInstantExtendedAPIEnabled()), |
| 38 user_input_in_progress_(false), | 51 user_input_in_progress_(false), |
| 39 popup_is_open_(false), | 52 popup_is_open_(false), |
| 40 user_text_is_empty_(true), | 53 user_text_is_empty_(true), |
| 41 web_contents_(web_contents) { | 54 web_contents_(web_contents) { |
| 42 if (!is_search_enabled_) | 55 if (!is_search_enabled_) |
| 43 return; | 56 return; |
| 44 | 57 |
| 58 // Observe NOTIFICATION_NAV_ENTRY_COMMITTED events so we can reset state |
| 59 // associated with the WebContents (such as mode, last known most visited |
| 60 // items, instant support state etc). |
| 45 registrar_.Add( | 61 registrar_.Add( |
| 46 this, | 62 this, |
| 47 content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 63 content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| 48 content::Source<content::NavigationController>( | 64 content::Source<content::NavigationController>( |
| 49 &web_contents->GetController())); | 65 &web_contents->GetController())); |
| 50 } | 66 } |
| 51 | 67 |
| 52 SearchTabHelper::~SearchTabHelper() { | 68 SearchTabHelper::~SearchTabHelper() { |
| 53 } | 69 } |
| 54 | 70 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 77 | 93 |
| 78 bool SearchTabHelper::UpdateLastKnownMostVisitedItems( | 94 bool SearchTabHelper::UpdateLastKnownMostVisitedItems( |
| 79 const std::vector<InstantMostVisitedItem>& items) { | 95 const std::vector<InstantMostVisitedItem>& items) { |
| 80 if (chrome::AreMostVisitedItemsEqual(items, last_known_most_visited_items_)) | 96 if (chrome::AreMostVisitedItemsEqual(items, last_known_most_visited_items_)) |
| 81 return false; | 97 return false; |
| 82 | 98 |
| 83 last_known_most_visited_items_ = items; | 99 last_known_most_visited_items_ = items; |
| 84 return true; | 100 return true; |
| 85 } | 101 } |
| 86 | 102 |
| 103 void SearchTabHelper::InstantSupportChanged(bool instant_support) { |
| 104 if (!is_search_enabled_) |
| 105 return; |
| 106 |
| 107 model_.SetInstantSupportState(instant_support ? INSTANT_SUPPORT_YES : |
| 108 INSTANT_SUPPORT_NO); |
| 109 } |
| 110 |
| 111 bool SearchTabHelper::SupportsInstant() const { |
| 112 return model_.instant_support() == INSTANT_SUPPORT_YES; |
| 113 } |
| 114 |
| 87 void SearchTabHelper::Observe( | 115 void SearchTabHelper::Observe( |
| 88 int type, | 116 int type, |
| 89 const content::NotificationSource& source, | 117 const content::NotificationSource& source, |
| 90 const content::NotificationDetails& details) { | 118 const content::NotificationDetails& details) { |
| 91 DCHECK_EQ(content::NOTIFICATION_NAV_ENTRY_COMMITTED, type); | 119 DCHECK_EQ(content::NOTIFICATION_NAV_ENTRY_COMMITTED, type); |
| 120 content::LoadCommittedDetails* load_details = |
| 121 content::Details<content::LoadCommittedDetails>(details).ptr(); |
| 122 if (!load_details->is_main_frame) |
| 123 return; |
| 124 |
| 92 UpdateMode(); | 125 UpdateMode(); |
| 93 last_known_most_visited_items_.clear(); | 126 last_known_most_visited_items_.clear(); |
| 127 |
| 128 // Already determined the instant support state for this page, do not reset |
| 129 // the instant support state. |
| 130 // |
| 131 // When we get a navigation entry committed event, there seem to be two ways |
| 132 // to tell whether the navigation was "in-page". Ideally, when |
| 133 // LoadCommittedDetails::is_in_page is true, we should have |
| 134 // LoadCommittedDetails::type to be NAVIGATION_TYPE_IN_PAGE. Unfortunately, |
| 135 // they are different in some cases. To workaround this bug, we are checking |
| 136 // (is_in_page || type == NAVIGATION_TYPE_IN_PAGE). Please refer to |
| 137 // crbug.com/251330 for more details. |
| 138 if (load_details->is_in_page || |
| 139 load_details->type == content::NAVIGATION_TYPE_IN_PAGE) { |
| 140 return; |
| 141 } |
| 142 |
| 143 model_.SetInstantSupportState(INSTANT_SUPPORT_UNKNOWN); |
| 94 } | 144 } |
| 95 | 145 |
| 96 bool SearchTabHelper::OnMessageReceived(const IPC::Message& message) { | 146 bool SearchTabHelper::OnMessageReceived(const IPC::Message& message) { |
| 97 bool handled = true; | 147 bool handled = true; |
| 98 IPC_BEGIN_MESSAGE_MAP(SearchTabHelper, message) | 148 IPC_BEGIN_MESSAGE_MAP(SearchTabHelper, message) |
| 99 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_SearchBoxShowBars, | 149 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_SearchBoxShowBars, |
| 100 OnSearchBoxShowBars) | 150 OnSearchBoxShowBars) |
| 101 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_SearchBoxHideBars, | 151 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_SearchBoxHideBars, |
| 102 OnSearchBoxHideBars) | 152 OnSearchBoxHideBars) |
| 153 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_InstantSupportDetermined, |
| 154 OnInstantSupportDetermined) |
| 103 IPC_MESSAGE_UNHANDLED(handled = false) | 155 IPC_MESSAGE_UNHANDLED(handled = false) |
| 104 IPC_END_MESSAGE_MAP() | 156 IPC_END_MESSAGE_MAP() |
| 105 return handled; | 157 return handled; |
| 106 } | 158 } |
| 107 | 159 |
| 160 void SearchTabHelper::DidFinishLoad( |
| 161 int64 /* frame_id */, |
| 162 const GURL& /* validated_url */, |
| 163 bool is_main_frame, |
| 164 content::RenderViewHost* /* render_view_host */) { |
| 165 if (is_main_frame) |
| 166 DetermineIfPageSupportsInstant(); |
| 167 } |
| 168 |
| 108 void SearchTabHelper::UpdateMode() { | 169 void SearchTabHelper::UpdateMode() { |
| 109 SearchMode::Type type = SearchMode::MODE_DEFAULT; | 170 SearchMode::Type type = SearchMode::MODE_DEFAULT; |
| 110 SearchMode::Origin origin = SearchMode::ORIGIN_DEFAULT; | 171 SearchMode::Origin origin = SearchMode::ORIGIN_DEFAULT; |
| 111 if (IsNTP(web_contents_)) { | 172 if (IsNTP(web_contents_)) { |
| 112 type = SearchMode::MODE_NTP; | 173 type = SearchMode::MODE_NTP; |
| 113 origin = SearchMode::ORIGIN_NTP; | 174 origin = SearchMode::ORIGIN_NTP; |
| 114 } else if (IsSearchResults(web_contents_)) { | 175 } else if (IsSearchResults(web_contents_)) { |
| 115 type = SearchMode::MODE_SEARCH_RESULTS; | 176 type = SearchMode::MODE_SEARCH_RESULTS; |
| 116 origin = SearchMode::ORIGIN_SEARCH; | 177 origin = SearchMode::ORIGIN_SEARCH; |
| 117 } | 178 } |
| 118 if (user_input_in_progress_) | 179 if (user_input_in_progress_) |
| 119 type = SearchMode::MODE_SEARCH_SUGGESTIONS; | 180 type = SearchMode::MODE_SEARCH_SUGGESTIONS; |
| 120 | 181 |
| 121 if (type == SearchMode::MODE_NTP && origin == SearchMode::ORIGIN_NTP && | 182 if (type == SearchMode::MODE_NTP && origin == SearchMode::ORIGIN_NTP && |
| 122 !popup_is_open_ && !user_text_is_empty_) { | 183 !popup_is_open_ && !user_text_is_empty_) { |
| 123 // We're switching back (|popup_is_open_| is false) to an NTP (type and | 184 // We're switching back (|popup_is_open_| is false) to an NTP (type and |
| 124 // mode are |NTP|) with suggestions (|user_text_is_empty_| is false), don't | 185 // mode are |NTP|) with suggestions (|user_text_is_empty_| is false), don't |
| 125 // modify visibility of top bars. This specific omnibox state is set when | 186 // modify visibility of top bars. This specific omnibox state is set when |
| 126 // OmniboxEditModelChanged() is called from | 187 // OmniboxEditModelChanged() is called from |
| 127 // OmniboxEditModel::SetInputInProgress() which is called from | 188 // OmniboxEditModel::SetInputInProgress() which is called from |
| 128 // OmniboxEditModel::Revert(). | 189 // OmniboxEditModel::Revert(). |
| 129 model_.SetState(SearchModel::State(SearchMode(type, origin), | 190 model_.SetState(SearchModel::State(SearchMode(type, origin), |
| 130 model_.state().top_bars_visible)); | 191 model_.state().top_bars_visible, |
| 192 model_.instant_support())); |
| 131 } else { | 193 } else { |
| 132 model_.SetMode(SearchMode(type, origin)); | 194 model_.SetMode(SearchMode(type, origin)); |
| 133 } | 195 } |
| 134 } | 196 } |
| 135 | 197 |
| 198 void SearchTabHelper::DetermineIfPageSupportsInstant() { |
| 199 Profile* profile = |
| 200 Profile::FromBrowserContext(web_contents_->GetBrowserContext()); |
| 201 if (!chrome::ShouldAssignURLToInstantRenderer(web_contents_->GetURL(), |
| 202 profile)) { |
| 203 // The page is not in the Instant process. This page does not support |
| 204 // instant. If we send an IPC message to a page that is not in the Instant |
| 205 // process, it will never receive it and will never respond. Therefore, |
| 206 // return immediately. |
| 207 InstantSupportChanged(false); |
| 208 } else if (IsLocal(web_contents_)) { |
| 209 // Local pages always support Instant. |
| 210 InstantSupportChanged(true); |
| 211 } else { |
| 212 Send(new ChromeViewMsg_DetermineIfPageSupportsInstant(routing_id())); |
| 213 } |
| 214 } |
| 215 |
| 216 void SearchTabHelper::OnInstantSupportDetermined(int page_id, |
| 217 bool instant_support) { |
| 218 if (!web_contents()->IsActiveEntry(page_id)) |
| 219 return; |
| 220 |
| 221 InstantSupportChanged(instant_support); |
| 222 } |
| 223 |
| 136 void SearchTabHelper::OnSearchBoxShowBars(int page_id) { | 224 void SearchTabHelper::OnSearchBoxShowBars(int page_id) { |
| 137 if (web_contents()->IsActiveEntry(page_id)) | 225 if (web_contents()->IsActiveEntry(page_id)) |
| 138 model_.SetTopBarsVisible(true); | 226 model_.SetTopBarsVisible(true); |
| 139 } | 227 } |
| 140 | 228 |
| 141 void SearchTabHelper::OnSearchBoxHideBars(int page_id) { | 229 void SearchTabHelper::OnSearchBoxHideBars(int page_id) { |
| 142 if (web_contents()->IsActiveEntry(page_id)) { | 230 if (web_contents()->IsActiveEntry(page_id)) { |
| 143 model_.SetTopBarsVisible(false); | 231 model_.SetTopBarsVisible(false); |
| 144 Send(new ChromeViewMsg_SearchBoxBarsHidden(routing_id())); | 232 Send(new ChromeViewMsg_SearchBoxBarsHidden(routing_id())); |
| 145 } | 233 } |
| 146 } | 234 } |
| OLD | NEW |