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