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