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/omnibox/omnibox_edit_model.h" | 5 #include "chrome/browser/ui/omnibox/omnibox_edit_model.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
| 10 #include "base/format_macros.h" | 10 #include "base/format_macros.h" |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 220 void OmniboxEditModel::SetUserText(const string16& text) { | 220 void OmniboxEditModel::SetUserText(const string16& text) { |
| 221 SetInputInProgress(true); | 221 SetInputInProgress(true); |
| 222 InternalSetUserText(text); | 222 InternalSetUserText(text); |
| 223 paste_state_ = NONE; | 223 paste_state_ = NONE; |
| 224 has_temporary_text_ = false; | 224 has_temporary_text_ = false; |
| 225 is_temporary_text_set_by_instant_ = false; | 225 is_temporary_text_set_by_instant_ = false; |
| 226 selected_instant_autocomplete_match_index_ = OmniboxPopupModel::kNoMatch; | 226 selected_instant_autocomplete_match_index_ = OmniboxPopupModel::kNoMatch; |
| 227 is_instant_temporary_text_a_search_query_ = false; | 227 is_instant_temporary_text_a_search_query_ = false; |
| 228 } | 228 } |
| 229 | 229 |
| 230 void OmniboxEditModel::FinalizeInstantQuery(const string16& input_text, | 230 void OmniboxEditModel::FinalizeInstantQuery( |
| 231 const InstantSuggestion& suggestion, | 231 const string16& input_text, |
| 232 bool skip_inline_autocomplete) { | 232 const InstantSuggestion& suggestion) { |
| 233 if (skip_inline_autocomplete) { | 233 if (popup_model()->IsOpen()) { |
| 234 const string16 final_text = input_text + suggestion.text; | |
| 235 view_->OnBeforePossibleChange(); | |
| 236 view_->SetWindowTextAndCaretPos(final_text, final_text.length(), false, | |
| 237 false); | |
| 238 view_->OnAfterPossibleChange(); | |
| 239 } else if (popup_model()->IsOpen()) { | |
| 240 SearchProvider* search_provider = | 234 SearchProvider* search_provider = |
| 241 autocomplete_controller()->search_provider(); | 235 autocomplete_controller()->search_provider(); |
| 242 // There may be no providers during testing; guard against that. | 236 // There may be no providers during testing; guard against that. |
| 243 if (search_provider) | 237 if (search_provider) |
| 244 search_provider->FinalizeInstantQuery(input_text, suggestion); | 238 search_provider->FinalizeInstantQuery(input_text, suggestion); |
| 245 } | 239 } |
| 246 } | 240 } |
| 247 | 241 |
| 248 void OmniboxEditModel::SetInstantSuggestion( | 242 void OmniboxEditModel::SetInstantSuggestion( |
| 249 const InstantSuggestion& suggestion) { | 243 const InstantSuggestion& suggestion) { |
| 250 switch (suggestion.behavior) { | 244 switch (suggestion.behavior) { |
| 251 case INSTANT_COMPLETE_NOW: | 245 case INSTANT_COMPLETE_NOW: |
| 252 view_->SetInstantSuggestion(string16()); | 246 view_->SetInstantSuggestion(string16()); |
| 253 if (!suggestion.text.empty()) | 247 if (!suggestion.text.empty()) |
| 254 FinalizeInstantQuery(view_->GetText(), suggestion, false); | 248 FinalizeInstantQuery(view_->GetText(), suggestion); |
| 255 break; | 249 break; |
| 256 | 250 |
| 257 case INSTANT_COMPLETE_NEVER: { | 251 case INSTANT_COMPLETE_NEVER: { |
| 258 DCHECK_EQ(INSTANT_SUGGESTION_SEARCH, suggestion.type); | 252 DCHECK_EQ(INSTANT_SUGGESTION_SEARCH, suggestion.type); |
| 259 view_->SetInstantSuggestion(suggestion.text); | 253 view_->SetInstantSuggestion(suggestion.text); |
| 260 autocomplete_controller()->search_provider()->ClearInstantSuggestion(); | 254 autocomplete_controller()->search_provider()->ClearInstantSuggestion(); |
| 261 break; | 255 break; |
| 262 } | 256 } |
| 263 | 257 |
| 264 case INSTANT_COMPLETE_REPLACE: { | 258 case INSTANT_COMPLETE_REPLACE: { |
| 265 const bool save_original_selection = !has_temporary_text_; | 259 const bool save_original_selection = !has_temporary_text_; |
| 266 view_->SetInstantSuggestion(string16()); | 260 view_->SetInstantSuggestion(string16()); |
| 267 has_temporary_text_ = true; | 261 has_temporary_text_ = true; |
| 268 is_temporary_text_set_by_instant_ = true; | 262 is_temporary_text_set_by_instant_ = true; |
| 269 selected_instant_autocomplete_match_index_ = | 263 selected_instant_autocomplete_match_index_ = |
| 270 suggestion.autocomplete_match_index; | 264 suggestion.autocomplete_match_index; |
| 271 is_instant_temporary_text_a_search_query_ = | 265 is_instant_temporary_text_a_search_query_ = |
| 272 suggestion.type == INSTANT_SUGGESTION_SEARCH; | 266 suggestion.type == INSTANT_SUGGESTION_SEARCH; |
| 273 // Instant suggestions are never a keyword. | 267 // Instant suggestions are never a keyword. |
| 274 keyword_ = string16(); | 268 keyword_ = string16(); |
| 275 is_keyword_hint_ = false; | 269 is_keyword_hint_ = false; |
| 276 view_->OnTemporaryTextMaybeChanged(suggestion.text, | 270 view_->OnTemporaryTextMaybeChanged(suggestion.text, |
| 277 save_original_selection, true); | 271 save_original_selection, true); |
| 278 break; | 272 break; |
| 279 } | 273 } |
| 280 } | 274 } |
| 281 } | 275 } |
| 282 | 276 |
| 283 bool OmniboxEditModel::CommitSuggestedText(bool skip_inline_autocomplete) { | 277 bool OmniboxEditModel::CommitSuggestedText() { |
| 284 if (!controller_->GetInstant()) | |
| 285 return false; | |
| 286 | |
| 287 const string16 suggestion = view_->GetInstantSuggestion(); | 278 const string16 suggestion = view_->GetInstantSuggestion(); |
| 288 if (suggestion.empty()) | 279 if (suggestion.empty()) |
| 289 return false; | 280 return false; |
| 290 | 281 |
| 291 // Assume that the gray text we are committing is a search suggestion. | 282 // Assume that the gray text we are committing is a search suggestion. |
| 292 FinalizeInstantQuery(view_->GetText(), | 283 const string16 final_text = view_->GetText() + suggestion; |
| 293 InstantSuggestion(suggestion, | 284 view_->OnBeforePossibleChange(); |
| 294 INSTANT_COMPLETE_NOW, | 285 view_->SetWindowTextAndCaretPos(final_text, final_text.length(), false, |
| 295 INSTANT_SUGGESTION_SEARCH, | 286 false); |
| 296 string16(), | 287 view_->OnAfterPossibleChange(); |
| 297 OmniboxPopupModel::kNoMatch), | |
| 298 skip_inline_autocomplete); | |
| 299 return true; | 288 return true; |
| 300 } | 289 } |
| 301 | 290 |
| 302 void OmniboxEditModel::OnChanged() { | 291 void OmniboxEditModel::OnChanged() { |
| 303 // Don't call CurrentMatch() when there's no editing, as in this case we'll | 292 // Don't call CurrentMatch() when there's no editing, as in this case we'll |
| 304 // never actually use it. This avoids running the autocomplete providers (and | 293 // never actually use it. This avoids running the autocomplete providers (and |
| 305 // any systems they then spin up) during startup. | 294 // any systems they then spin up) during startup. |
| 306 const AutocompleteMatch& current_match = user_input_in_progress_ ? | 295 const AutocompleteMatch& current_match = user_input_in_progress_ ? |
| 307 CurrentMatch() : AutocompleteMatch(); | 296 CurrentMatch() : AutocompleteMatch(); |
| 308 | 297 |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 320 // before it's needed. Note: This event is triggered as part of startup when | 309 // before it's needed. Note: This event is triggered as part of startup when |
| 321 // the initial tab transitions to the start page. | 310 // the initial tab transitions to the start page. |
| 322 recommended_action = | 311 recommended_action = |
| 323 action_predictor->RecommendAction(user_text_, current_match); | 312 action_predictor->RecommendAction(user_text_, current_match); |
| 324 } | 313 } |
| 325 | 314 |
| 326 UMA_HISTOGRAM_ENUMERATION("AutocompleteActionPredictor.Action", | 315 UMA_HISTOGRAM_ENUMERATION("AutocompleteActionPredictor.Action", |
| 327 recommended_action, | 316 recommended_action, |
| 328 AutocompleteActionPredictor::LAST_PREDICT_ACTION); | 317 AutocompleteActionPredictor::LAST_PREDICT_ACTION); |
| 329 | 318 |
| 330 if (!DoInstant(current_match)) { | 319 // Do not perform instant if we're currently reverting or the change is the |
| 320 // result of an INSTANT_COMPLETE_REPLACE instant suggestion. | |
| 321 bool performed_instant = false; | |
| 322 if (!in_revert_ && !is_temporary_text_set_by_instant_) { | |
| 323 size_t start, end; | |
| 324 view_->GetSelectionBounds(&start, &end); | |
| 325 string16 user_text = has_temporary_text_ ? current_match.fill_into_edit : | |
|
sreeram
2013/05/29 16:34:01
Now that old Instant is dead, I think we can never
beaudoin
2013/05/29 17:02:27
Done.
| |
| 326 DisplayTextFromUserText(user_text_); | |
| 327 performed_instant = omnibox_controller_->DoInstant( | |
| 328 current_match, user_text, view_->GetText(), start, end, | |
| 329 user_input_in_progress_, in_escape_handler_, | |
| 330 view_->DeleteAtEndPressed() || just_deleted_text_, | |
| 331 KeywordIsSelected()); | |
| 332 } | |
| 333 | |
| 334 if (!performed_instant) { | |
| 331 // Hide any suggestions we might be showing. | 335 // Hide any suggestions we might be showing. |
| 332 view_->SetInstantSuggestion(string16()); | 336 view_->SetInstantSuggestion(string16()); |
| 333 | 337 |
| 334 // No need to wait any longer for Instant. | 338 // No need to wait any longer for Instant. |
| 335 FinalizeInstantQuery(string16(), InstantSuggestion(), false); | 339 FinalizeInstantQuery(string16(), InstantSuggestion()); |
| 336 } | 340 } |
| 337 | 341 |
| 338 switch (recommended_action) { | 342 switch (recommended_action) { |
| 339 case AutocompleteActionPredictor::ACTION_PRERENDER: | 343 case AutocompleteActionPredictor::ACTION_PRERENDER: |
| 340 // It's possible that there is no current page, for instance if the tab | 344 // It's possible that there is no current page, for instance if the tab |
| 341 // has been closed or on return from a sleep state. | 345 // has been closed or on return from a sleep state. |
| 342 // (http://crbug.com/105689) | 346 // (http://crbug.com/105689) |
| 343 if (!delegate_->CurrentPageExists()) | 347 if (!delegate_->CurrentPageExists()) |
| 344 break; | 348 break; |
| 345 // Ask for prerendering if the destination URL is different than the | 349 // Ask for prerendering if the destination URL is different than the |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 363 AutocompleteMatch match; | 367 AutocompleteMatch match; |
| 364 GetInfoForCurrentText(&match, NULL); | 368 GetInfoForCurrentText(&match, NULL); |
| 365 *url = match.destination_url; | 369 *url = match.destination_url; |
| 366 if (*url == URLFixerUpper::FixupURL(UTF16ToUTF8(permanent_text_), | 370 if (*url == URLFixerUpper::FixupURL(UTF16ToUTF8(permanent_text_), |
| 367 std::string())) { | 371 std::string())) { |
| 368 *title = controller_->GetTitle(); | 372 *title = controller_->GetTitle(); |
| 369 *favicon = controller_->GetFavicon(); | 373 *favicon = controller_->GetFavicon(); |
| 370 } | 374 } |
| 371 } | 375 } |
| 372 | 376 |
| 373 bool OmniboxEditModel::UseVerbatimInstant() { | |
| 374 #if defined(OS_MACOSX) | |
| 375 // TODO(suzhe): Fix Mac port to display Instant suggest in a separated NSView, | |
| 376 // so that we can display Instant suggest along with composition text. | |
| 377 const AutocompleteInput& input = autocomplete_controller()->input(); | |
| 378 if (input.prevent_inline_autocomplete()) | |
| 379 return true; | |
| 380 #endif | |
| 381 | |
| 382 // The value of input.prevent_inline_autocomplete() is determined by the | |
| 383 // following conditions: | |
| 384 // 1. If the caret is at the end of the text. | |
| 385 // 2. If it's in IME composition mode. | |
| 386 // We send the caret position to Instant (so it can determine #1 itself), and | |
| 387 // we use a separated widget for displaying the Instant suggest (so it doesn't | |
| 388 // interfere with #2). So, we don't need to care about the value of | |
| 389 // input.prevent_inline_autocomplete() here. | |
| 390 return view_->DeleteAtEndPressed() || popup_model()->selected_line() != 0 || | |
| 391 just_deleted_text_; | |
| 392 } | |
| 393 | |
| 394 bool OmniboxEditModel::CurrentTextIsURL() const { | 377 bool OmniboxEditModel::CurrentTextIsURL() const { |
| 395 if (view_->toolbar_model()->GetSearchTermsType() != | 378 if (view_->toolbar_model()->GetSearchTermsType() != |
| 396 ToolbarModel::NO_SEARCH_TERMS) | 379 ToolbarModel::NO_SEARCH_TERMS) |
| 397 return false; | 380 return false; |
| 398 | 381 |
| 399 // If current text is not composed of replaced search terms and | 382 // If current text is not composed of replaced search terms and |
| 400 // !user_input_in_progress_, then permanent text is showing and should be a | 383 // !user_input_in_progress_, then permanent text is showing and should be a |
| 401 // URL, so no further checking is needed. By avoiding checking in this case, | 384 // URL, so no further checking is needed. By avoiding checking in this case, |
| 402 // we avoid calling into the autocomplete providers, and thus initializing the | 385 // we avoid calling into the autocomplete providers, and thus initializing the |
| 403 // history system, as long as possible, which speeds startup. | 386 // history system, as long as possible, which speeds startup. |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 495 false, true); | 478 false, true); |
| 496 AutocompleteActionPredictor* action_predictor = | 479 AutocompleteActionPredictor* action_predictor = |
| 497 AutocompleteActionPredictorFactory::GetForProfile(profile_); | 480 AutocompleteActionPredictorFactory::GetForProfile(profile_); |
| 498 if (action_predictor) | 481 if (action_predictor) |
| 499 action_predictor->ClearTransitionalMatches(); | 482 action_predictor->ClearTransitionalMatches(); |
| 500 } | 483 } |
| 501 | 484 |
| 502 void OmniboxEditModel::StartAutocomplete( | 485 void OmniboxEditModel::StartAutocomplete( |
| 503 bool has_selected_text, | 486 bool has_selected_text, |
| 504 bool prevent_inline_autocomplete) const { | 487 bool prevent_inline_autocomplete) const { |
| 505 omnibox_controller_->ClearPopupKeywordMode(); | |
| 506 | |
| 507 bool keyword_is_selected = KeywordIsSelected(); | |
| 508 popup_model()->SetHoveredLine(OmniboxPopupModel::kNoMatch); | |
| 509 | |
| 510 size_t cursor_position; | 488 size_t cursor_position; |
| 511 if (inline_autocomplete_text_.empty()) { | 489 if (inline_autocomplete_text_.empty()) { |
| 512 // Cursor position is equivalent to the current selection's end. | 490 // Cursor position is equivalent to the current selection's end. |
| 513 size_t start; | 491 size_t start; |
| 514 view_->GetSelectionBounds(&start, &cursor_position); | 492 view_->GetSelectionBounds(&start, &cursor_position); |
| 515 // Adjust cursor position taking into account possible keyword in the user | 493 // Adjust cursor position taking into account possible keyword in the user |
| 516 // text. We rely on DisplayTextFromUserText() method which is consistent | 494 // text. We rely on DisplayTextFromUserText() method which is consistent |
| 517 // with keyword extraction done in KeywordProvider/SearchProvider. | 495 // with keyword extraction done in KeywordProvider/SearchProvider. |
| 518 const size_t cursor_offset = | 496 const size_t cursor_offset = |
| 519 user_text_.length() - DisplayTextFromUserText(user_text_).length(); | 497 user_text_.length() - DisplayTextFromUserText(user_text_).length(); |
| 520 cursor_position += cursor_offset; | 498 cursor_position += cursor_offset; |
| 521 } else { | 499 } else { |
| 522 // There are some cases where StartAutocomplete() may be called | 500 // There are some cases where StartAutocomplete() may be called |
| 523 // with non-empty |inline_autocomplete_text_|. In such cases, we cannot | 501 // with non-empty |inline_autocomplete_text_|. In such cases, we cannot |
| 524 // use the current selection, because it could result with the cursor | 502 // use the current selection, because it could result with the cursor |
| 525 // position past the last character from the user text. Instead, | 503 // position past the last character from the user text. Instead, |
| 526 // we assume that the cursor is simply at the end of input. | 504 // we assume that the cursor is simply at the end of input. |
| 527 // One example is when user presses Ctrl key while having a highlighted | 505 // One example is when user presses Ctrl key while having a highlighted |
| 528 // inline autocomplete text. | 506 // inline autocomplete text. |
| 529 // TODO: Rethink how we are going to handle this case to avoid | 507 // TODO: Rethink how we are going to handle this case to avoid |
| 530 // inconsistent behavior when user presses Ctrl key. | 508 // inconsistent behavior when user presses Ctrl key. |
| 531 // See http://crbug.com/165961 and http://crbug.com/165968 for more details. | 509 // See http://crbug.com/165961 and http://crbug.com/165968 for more details. |
| 532 cursor_position = user_text_.length(); | 510 cursor_position = user_text_.length(); |
| 533 } | 511 } |
| 534 | 512 |
| 535 InstantController* instant = controller_->GetInstant(); | 513 bool keyword_is_selected = KeywordIsSelected(); |
| 536 if (instant) { | 514 omnibox_controller_->StartAutocomplete( |
| 537 instant->OnAutocompleteStart(); | 515 user_text_, |
| 538 // If the embedded page for InstantExtended is fetching its own suggestions, | 516 cursor_position, |
| 539 // suppress search suggestions from SearchProvider. We still need | |
| 540 // SearchProvider to run for FinalizeInstantQuery. | |
| 541 // TODO(dcblack): Once we are done refactoring the omnibox so we don't need | |
| 542 // to use FinalizeInstantQuery anymore, we can take out this check and | |
| 543 // remove this provider from kInstantExtendedOmniboxProviders. | |
| 544 if (instant->WillFetchCompletions()) | |
| 545 autocomplete_controller()->search_provider()->SuppressSearchSuggestions(); | |
| 546 } | |
| 547 | |
| 548 // We don't explicitly clear OmniboxPopupModel::manually_selected_match, as | |
| 549 // Start ends up invoking OmniboxPopupModel::OnResultChanged which clears it. | |
| 550 autocomplete_controller()->Start(AutocompleteInput( | |
| 551 user_text_, cursor_position, string16(), GURL(), | |
| 552 prevent_inline_autocomplete || just_deleted_text_ || | 517 prevent_inline_autocomplete || just_deleted_text_ || |
| 553 (has_selected_text && inline_autocomplete_text_.empty()) || | 518 (has_selected_text && inline_autocomplete_text_.empty()) || |
| 554 (paste_state_ != NONE), keyword_is_selected, | 519 (paste_state_ != NONE), |
| 555 keyword_is_selected || allow_exact_keyword_match_, | 520 keyword_is_selected, |
| 556 AutocompleteInput::ALL_MATCHES)); | 521 keyword_is_selected || allow_exact_keyword_match_); |
| 557 } | 522 } |
| 558 | 523 |
| 559 void OmniboxEditModel::StopAutocomplete() { | 524 void OmniboxEditModel::StopAutocomplete() { |
| 560 autocomplete_controller()->Stop(true); | 525 autocomplete_controller()->Stop(true); |
| 561 } | 526 } |
| 562 | 527 |
| 563 bool OmniboxEditModel::CanPasteAndGo(const string16& text) const { | 528 bool OmniboxEditModel::CanPasteAndGo(const string16& text) const { |
| 564 if (!view_->command_updater()->IsCommandEnabled(IDC_OPEN_CURRENT_URL)) | 529 if (!view_->command_updater()->IsCommandEnabled(IDC_OPEN_CURRENT_URL)) |
| 565 return false; | 530 return false; |
| 566 | 531 |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 758 const GURL destination_url = autocomplete_controller()-> | 723 const GURL destination_url = autocomplete_controller()-> |
| 759 GetDestinationURL(match, query_formulation_time); | 724 GetDestinationURL(match, query_formulation_time); |
| 760 | 725 |
| 761 // If running with instant, notify the instant controller that a navigation | 726 // If running with instant, notify the instant controller that a navigation |
| 762 // is about to take place if we are navigating to a URL. This can be | 727 // is about to take place if we are navigating to a URL. This can be |
| 763 // determined by inspecting the transition type. To ensure that this is only | 728 // determined by inspecting the transition type. To ensure that this is only |
| 764 // done on Enter key press, check that the disposition is CURRENT_TAB. This | 729 // done on Enter key press, check that the disposition is CURRENT_TAB. This |
| 765 // is the same heuristic used by BrowserInstantController::OpenInstant | 730 // is the same heuristic used by BrowserInstantController::OpenInstant |
| 766 if (match.transition == content::PAGE_TRANSITION_TYPED && | 731 if (match.transition == content::PAGE_TRANSITION_TYPED && |
| 767 disposition == CURRENT_TAB) { | 732 disposition == CURRENT_TAB) { |
| 768 InstantController* instant = controller_->GetInstant(); | 733 InstantController* instant = GetInstantController(); |
| 769 if (instant) | 734 if (instant) |
| 770 instant->OmniboxNavigateToURL(); | 735 instant->OmniboxNavigateToURL(); |
| 771 } | 736 } |
| 772 | 737 |
| 773 // This calls RevertAll again. | 738 // This calls RevertAll again. |
| 774 base::AutoReset<bool> tmp(&in_revert_, true); | 739 base::AutoReset<bool> tmp(&in_revert_, true); |
| 775 controller_->OnAutocompleteAccept(destination_url, disposition, | 740 controller_->OnAutocompleteAccept(destination_url, disposition, |
| 776 match.transition, alternate_nav_url); | 741 match.transition, alternate_nav_url); |
| 777 } | 742 } |
| 778 | 743 |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 870 | 835 |
| 871 void OmniboxEditModel::SetCaretVisibility(bool visible) { | 836 void OmniboxEditModel::SetCaretVisibility(bool visible) { |
| 872 // Caret visibility only matters if the omnibox has focus. | 837 // Caret visibility only matters if the omnibox has focus. |
| 873 if (focus_state_ != OMNIBOX_FOCUS_NONE) { | 838 if (focus_state_ != OMNIBOX_FOCUS_NONE) { |
| 874 SetFocusState(visible ? OMNIBOX_FOCUS_VISIBLE : OMNIBOX_FOCUS_INVISIBLE, | 839 SetFocusState(visible ? OMNIBOX_FOCUS_VISIBLE : OMNIBOX_FOCUS_INVISIBLE, |
| 875 OMNIBOX_FOCUS_CHANGE_EXPLICIT); | 840 OMNIBOX_FOCUS_CHANGE_EXPLICIT); |
| 876 } | 841 } |
| 877 } | 842 } |
| 878 | 843 |
| 879 void OmniboxEditModel::OnWillKillFocus(gfx::NativeView view_gaining_focus) { | 844 void OmniboxEditModel::OnWillKillFocus(gfx::NativeView view_gaining_focus) { |
| 880 InstantController* instant = controller_->GetInstant(); | 845 InstantController* instant = GetInstantController(); |
| 881 if (instant) { | 846 if (instant) { |
| 882 instant->OmniboxFocusChanged(OMNIBOX_FOCUS_NONE, | 847 instant->OmniboxFocusChanged(OMNIBOX_FOCUS_NONE, |
| 883 OMNIBOX_FOCUS_CHANGE_EXPLICIT, | 848 OMNIBOX_FOCUS_CHANGE_EXPLICIT, |
| 884 view_gaining_focus); | 849 view_gaining_focus); |
| 885 } | 850 } |
| 886 | 851 |
| 887 // TODO(jered): Rip this out along with StartZeroSuggest. | 852 // TODO(jered): Rip this out along with StartZeroSuggest. |
| 888 autocomplete_controller()->StopZeroSuggest(); | 853 autocomplete_controller()->StopZeroSuggest(); |
| 889 delegate_->NotifySearchTabHelper(user_input_in_progress_, !in_revert_, | 854 delegate_->NotifySearchTabHelper(user_input_in_progress_, !in_revert_, |
| 890 popup_model()->IsOpen(), user_text_.empty()); | 855 popup_model()->IsOpen(), user_text_.empty()); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 972 // TODO(pkasting): We should, in fact, force this particular query to open | 937 // TODO(pkasting): We should, in fact, force this particular query to open |
| 973 // the popup immediately. | 938 // the popup immediately. |
| 974 if (!user_input_in_progress_) | 939 if (!user_input_in_progress_) |
| 975 InternalSetUserText(permanent_text_); | 940 InternalSetUserText(permanent_text_); |
| 976 view_->UpdatePopup(); | 941 view_->UpdatePopup(); |
| 977 } else { | 942 } else { |
| 978 // TODO(pkasting): The popup is working on a query but is not open. We | 943 // TODO(pkasting): The popup is working on a query but is not open. We |
| 979 // should force it to open immediately. | 944 // should force it to open immediately. |
| 980 } | 945 } |
| 981 } else { | 946 } else { |
| 982 InstantController* instant = controller_->GetInstant(); | 947 InstantController* instant = GetInstantController(); |
| 983 if (instant && instant->OnUpOrDownKeyPressed(count)) { | 948 if (instant && instant->OnUpOrDownKeyPressed(count)) { |
| 984 // If Instant handles the key press, it's showing a list of suggestions | 949 // If Instant handles the key press, it's showing a list of suggestions |
| 985 // that it's stepping through. In that case, our popup model is | 950 // that it's stepping through. In that case, our popup model is |
| 986 // irrelevant, so don't process the key press ourselves. However, do stop | 951 // irrelevant, so don't process the key press ourselves. However, do stop |
| 987 // the autocomplete system from changing the results. | 952 // the autocomplete system from changing the results. |
| 988 autocomplete_controller()->Stop(false); | 953 autocomplete_controller()->Stop(false); |
| 989 } else { | 954 } else { |
| 990 // The popup is open, so the user should be able to interact with it | 955 // The popup is open, so the user should be able to interact with it |
| 991 // normally. | 956 // normally. |
| 992 popup_model()->Move(count); | 957 popup_model()->Move(count); |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1173 // will have updated our state already, so in that case we don't also return | 1138 // will have updated our state already, so in that case we don't also return |
| 1174 // true from this function. | 1139 // true from this function. |
| 1175 return !(text_differs && allow_keyword_ui_change && !just_deleted_text && | 1140 return !(text_differs && allow_keyword_ui_change && !just_deleted_text && |
| 1176 no_selection && (selection_start == user_text_.length()) && | 1141 no_selection && (selection_start == user_text_.length()) && |
| 1177 MaybeAcceptKeywordBySpace(user_text_)); | 1142 MaybeAcceptKeywordBySpace(user_text_)); |
| 1178 } | 1143 } |
| 1179 | 1144 |
| 1180 void OmniboxEditModel::OnResultChanged(bool default_match_changed) { | 1145 void OmniboxEditModel::OnResultChanged(bool default_match_changed) { |
| 1181 } | 1146 } |
| 1182 | 1147 |
| 1148 InstantController* OmniboxEditModel::GetInstantController() const { | |
| 1149 return controller_->GetInstant(); | |
| 1150 } | |
| 1151 | |
| 1183 bool OmniboxEditModel::query_in_progress() const { | 1152 bool OmniboxEditModel::query_in_progress() const { |
| 1184 return !autocomplete_controller()->done(); | 1153 return !autocomplete_controller()->done(); |
| 1185 } | 1154 } |
| 1186 | 1155 |
| 1187 void OmniboxEditModel::InternalSetUserText(const string16& text) { | 1156 void OmniboxEditModel::InternalSetUserText(const string16& text) { |
| 1188 user_text_ = text; | 1157 user_text_ = text; |
| 1189 just_deleted_text_ = false; | 1158 just_deleted_text_ = false; |
| 1190 inline_autocomplete_text_.clear(); | 1159 inline_autocomplete_text_.clear(); |
| 1191 } | 1160 } |
| 1192 | 1161 |
| 1193 bool OmniboxEditModel::KeywordIsSelected() const { | 1162 bool OmniboxEditModel::KeywordIsSelected() const { |
| 1194 return !is_keyword_hint_ && !keyword_.empty(); | 1163 return !is_keyword_hint_ && !keyword_.empty(); |
| 1195 } | 1164 } |
| 1196 | 1165 |
| 1166 void OmniboxEditModel::ClearPopupKeywordMode() const { | |
| 1167 omnibox_controller_->ClearPopupKeywordMode(); | |
| 1168 } | |
| 1169 | |
| 1197 string16 OmniboxEditModel::DisplayTextFromUserText(const string16& text) const { | 1170 string16 OmniboxEditModel::DisplayTextFromUserText(const string16& text) const { |
| 1198 return KeywordIsSelected() ? | 1171 return KeywordIsSelected() ? |
| 1199 KeywordProvider::SplitReplacementStringFromInput(text, false) : text; | 1172 KeywordProvider::SplitReplacementStringFromInput(text, false) : text; |
| 1200 } | 1173 } |
| 1201 | 1174 |
| 1202 string16 OmniboxEditModel::UserTextFromDisplayText(const string16& text) const { | 1175 string16 OmniboxEditModel::UserTextFromDisplayText(const string16& text) const { |
| 1203 return KeywordIsSelected() ? (keyword_ + char16(' ') + text) : text; | 1176 return KeywordIsSelected() ? (keyword_ + char16(' ') + text) : text; |
| 1204 } | 1177 } |
| 1205 | 1178 |
| 1206 void OmniboxEditModel::GetInfoForCurrentText(AutocompleteMatch* match, | 1179 void OmniboxEditModel::GetInfoForCurrentText(AutocompleteMatch* match, |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1301 // The user typed something, then selected a different item. Restore the | 1274 // The user typed something, then selected a different item. Restore the |
| 1302 // text they typed and change back to the default item. | 1275 // text they typed and change back to the default item. |
| 1303 // NOTE: This purposefully does not reset paste_state_. | 1276 // NOTE: This purposefully does not reset paste_state_. |
| 1304 bool notify_instant = is_temporary_text_set_by_instant_; | 1277 bool notify_instant = is_temporary_text_set_by_instant_; |
| 1305 just_deleted_text_ = false; | 1278 just_deleted_text_ = false; |
| 1306 has_temporary_text_ = false; | 1279 has_temporary_text_ = false; |
| 1307 is_temporary_text_set_by_instant_ = false; | 1280 is_temporary_text_set_by_instant_ = false; |
| 1308 selected_instant_autocomplete_match_index_ = OmniboxPopupModel::kNoMatch; | 1281 selected_instant_autocomplete_match_index_ = OmniboxPopupModel::kNoMatch; |
| 1309 is_instant_temporary_text_a_search_query_ = false; | 1282 is_instant_temporary_text_a_search_query_ = false; |
| 1310 | 1283 |
| 1311 InstantController* instant = controller_->GetInstant(); | 1284 InstantController* instant = GetInstantController(); |
| 1312 if (instant && notify_instant) { | 1285 if (instant && notify_instant) { |
| 1313 // Normally, popup_->ResetToDefaultMatch() will cause the view text to be | 1286 // Normally, popup_->ResetToDefaultMatch() will cause the view text to be |
| 1314 // updated. In Instant Extended mode however, the popup_ is not used, so it | 1287 // updated. In Instant Extended mode however, the popup_ is not used, so it |
| 1315 // won't do anything. So, update the view ourselves. Even if Instant is not | 1288 // won't do anything. So, update the view ourselves. Even if Instant is not |
| 1316 // in extended mode (i.e., it's enabled in non-extended mode, or disabled | 1289 // in extended mode (i.e., it's enabled in non-extended mode, or disabled |
| 1317 // altogether), this is okay to do, since the call to | 1290 // altogether), this is okay to do, since the call to |
| 1318 // popup_->ResetToDefaultMatch() will just override whatever we do here. | 1291 // popup_->ResetToDefaultMatch() will just override whatever we do here. |
| 1319 // | 1292 // |
| 1320 // The two "false" arguments make sure that our shenanigans don't cause any | 1293 // The two "false" arguments make sure that our shenanigans don't cause any |
| 1321 // previously saved selection to be erased nor OnChanged() to be called. | 1294 // previously saved selection to be erased nor OnChanged() to be called. |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1365 // Then check if the text before the inserted space matches a keyword. | 1338 // Then check if the text before the inserted space matches a keyword. |
| 1366 string16 keyword; | 1339 string16 keyword; |
| 1367 TrimWhitespace(new_text.substr(0, space_position), TRIM_LEADING, &keyword); | 1340 TrimWhitespace(new_text.substr(0, space_position), TRIM_LEADING, &keyword); |
| 1368 // TODO(sreeram): Once the Instant extended API supports keywords properly, | 1341 // TODO(sreeram): Once the Instant extended API supports keywords properly, |
| 1369 // keyword_provider() should never be NULL. Remove that clause. | 1342 // keyword_provider() should never be NULL. Remove that clause. |
| 1370 return !keyword.empty() && autocomplete_controller()->keyword_provider() && | 1343 return !keyword.empty() && autocomplete_controller()->keyword_provider() && |
| 1371 !autocomplete_controller()->keyword_provider()-> | 1344 !autocomplete_controller()->keyword_provider()-> |
| 1372 GetKeywordForText(keyword).empty(); | 1345 GetKeywordForText(keyword).empty(); |
| 1373 } | 1346 } |
| 1374 | 1347 |
| 1375 bool OmniboxEditModel::DoInstant(const AutocompleteMatch& match) { | |
| 1376 InstantController* instant = controller_->GetInstant(); | |
| 1377 if (!instant || in_revert_) | |
| 1378 return false; | |
| 1379 | |
| 1380 // Don't call Update() if the change is the result of an | |
| 1381 // INSTANT_COMPLETE_REPLACE instant suggestion. | |
| 1382 if (is_temporary_text_set_by_instant_) | |
| 1383 return false; | |
| 1384 | |
| 1385 // The two pieces of text we want to send Instant, viz., what the user has | |
| 1386 // typed, and the full omnibox text including any inline autocompletion. | |
| 1387 string16 user_text = has_temporary_text_ ? | |
| 1388 match.fill_into_edit : DisplayTextFromUserText(user_text_); | |
| 1389 string16 full_text = view_->GetText(); | |
| 1390 | |
| 1391 // Remove "?" if we're in forced query mode. | |
| 1392 AutocompleteInput::RemoveForcedQueryStringIfNecessary( | |
| 1393 autocomplete_controller()->input().type(), &user_text); | |
| 1394 AutocompleteInput::RemoveForcedQueryStringIfNecessary( | |
| 1395 autocomplete_controller()->input().type(), &full_text); | |
| 1396 | |
| 1397 size_t start, end; | |
| 1398 view_->GetSelectionBounds(&start, &end); | |
| 1399 | |
| 1400 return instant->Update(match, user_text, full_text, start, end, | |
| 1401 UseVerbatimInstant(), user_input_in_progress_, popup_model()->IsOpen(), | |
| 1402 in_escape_handler_, KeywordIsSelected()); | |
| 1403 } | |
| 1404 | |
| 1405 // static | 1348 // static |
| 1406 bool OmniboxEditModel::IsSpaceCharForAcceptingKeyword(wchar_t c) { | 1349 bool OmniboxEditModel::IsSpaceCharForAcceptingKeyword(wchar_t c) { |
| 1407 switch (c) { | 1350 switch (c) { |
| 1408 case 0x0020: // Space | 1351 case 0x0020: // Space |
| 1409 case 0x3000: // Ideographic Space | 1352 case 0x3000: // Ideographic Space |
| 1410 return true; | 1353 return true; |
| 1411 default: | 1354 default: |
| 1412 return false; | 1355 return false; |
| 1413 } | 1356 } |
| 1414 } | 1357 } |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 1434 DCHECK(match); | 1377 DCHECK(match); |
| 1435 AutocompleteClassifierFactory::GetForProfile(profile_)->Classify(text, | 1378 AutocompleteClassifierFactory::GetForProfile(profile_)->Classify(text, |
| 1436 false, false, match, alternate_nav_url); | 1379 false, false, match, alternate_nav_url); |
| 1437 } | 1380 } |
| 1438 | 1381 |
| 1439 void OmniboxEditModel::SetFocusState(OmniboxFocusState state, | 1382 void OmniboxEditModel::SetFocusState(OmniboxFocusState state, |
| 1440 OmniboxFocusChangeReason reason) { | 1383 OmniboxFocusChangeReason reason) { |
| 1441 if (state == focus_state_) | 1384 if (state == focus_state_) |
| 1442 return; | 1385 return; |
| 1443 | 1386 |
| 1444 InstantController* instant = controller_->GetInstant(); | 1387 InstantController* instant = GetInstantController(); |
| 1445 if (instant) | 1388 if (instant) |
| 1446 instant->OmniboxFocusChanged(state, reason, NULL); | 1389 instant->OmniboxFocusChanged(state, reason, NULL); |
| 1447 | 1390 |
| 1448 // Update state and notify view if the omnibox has focus and the caret | 1391 // Update state and notify view if the omnibox has focus and the caret |
| 1449 // visibility changed. | 1392 // visibility changed. |
| 1450 const bool was_caret_visible = is_caret_visible(); | 1393 const bool was_caret_visible = is_caret_visible(); |
| 1451 focus_state_ = state; | 1394 focus_state_ = state; |
| 1452 if (focus_state_ != OMNIBOX_FOCUS_NONE && | 1395 if (focus_state_ != OMNIBOX_FOCUS_NONE && |
| 1453 is_caret_visible() != was_caret_visible) | 1396 is_caret_visible() != was_caret_visible) |
| 1454 view_->ApplyCaretVisibility(); | 1397 view_->ApplyCaretVisibility(); |
| 1455 } | 1398 } |
| OLD | NEW |