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 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 just_deleted_text_(false), | 127 just_deleted_text_(false), |
128 has_temporary_text_(false), | 128 has_temporary_text_(false), |
129 is_temporary_text_set_by_instant_(false), | 129 is_temporary_text_set_by_instant_(false), |
130 paste_state_(NONE), | 130 paste_state_(NONE), |
131 control_key_state_(UP), | 131 control_key_state_(UP), |
132 is_keyword_hint_(false), | 132 is_keyword_hint_(false), |
133 profile_(profile), | 133 profile_(profile), |
134 in_revert_(false), | 134 in_revert_(false), |
135 in_escape_handler_(false), | 135 in_escape_handler_(false), |
136 allow_exact_keyword_match_(false) { | 136 allow_exact_keyword_match_(false) { |
137 // Use a restricted subset of the autocomplete providers if we're using the | 137 omnibox_controller_.reset(new OmniboxController(this, profile)); |
138 // Instant Extended API, as it doesn't support them all. | |
139 autocomplete_controller_.reset(new AutocompleteController(profile, this, | |
140 chrome::IsInstantExtendedAPIEnabled() ? | |
141 AutocompleteClassifier::kInstantExtendedOmniboxProviders : | |
142 AutocompleteClassifier::kDefaultOmniboxProviders)); | |
143 delegate_.reset(new OmniboxCurrentPageDelegateImpl(controller, profile)); | 138 delegate_.reset(new OmniboxCurrentPageDelegateImpl(controller, profile)); |
144 } | 139 } |
145 | 140 |
146 OmniboxEditModel::~OmniboxEditModel() { | 141 OmniboxEditModel::~OmniboxEditModel() { |
147 } | 142 } |
148 | 143 |
149 const OmniboxEditModel::State OmniboxEditModel::GetStateForTabSwitch() { | 144 const OmniboxEditModel::State OmniboxEditModel::GetStateForTabSwitch() { |
150 // Like typing, switching tabs "accepts" the temporary text as the user | 145 // Like typing, switching tabs "accepts" the temporary text as the user |
151 // text, because it makes little sense to have temporary text when the | 146 // text, because it makes little sense to have temporary text when the |
152 // popup is closed. | 147 // popup is closed. |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
231 const InstantSuggestion& suggestion, | 226 const InstantSuggestion& suggestion, |
232 bool skip_inline_autocomplete) { | 227 bool skip_inline_autocomplete) { |
233 if (skip_inline_autocomplete) { | 228 if (skip_inline_autocomplete) { |
234 const string16 final_text = input_text + suggestion.text; | 229 const string16 final_text = input_text + suggestion.text; |
235 view_->OnBeforePossibleChange(); | 230 view_->OnBeforePossibleChange(); |
236 view_->SetWindowTextAndCaretPos(final_text, final_text.length(), false, | 231 view_->SetWindowTextAndCaretPos(final_text, final_text.length(), false, |
237 false); | 232 false); |
238 view_->OnAfterPossibleChange(); | 233 view_->OnAfterPossibleChange(); |
239 } else if (popup_->IsOpen()) { | 234 } else if (popup_->IsOpen()) { |
240 SearchProvider* search_provider = | 235 SearchProvider* search_provider = |
241 autocomplete_controller_->search_provider(); | 236 autocomplete_controller()->search_provider(); |
242 // There may be no providers during testing; guard against that. | 237 // There may be no providers during testing; guard against that. |
243 if (search_provider) | 238 if (search_provider) |
244 search_provider->FinalizeInstantQuery(input_text, suggestion); | 239 search_provider->FinalizeInstantQuery(input_text, suggestion); |
245 } | 240 } |
246 } | 241 } |
247 | 242 |
248 void OmniboxEditModel::SetInstantSuggestion( | 243 void OmniboxEditModel::SetInstantSuggestion( |
249 const InstantSuggestion& suggestion) { | 244 const InstantSuggestion& suggestion) { |
250 switch (suggestion.behavior) { | 245 switch (suggestion.behavior) { |
251 case INSTANT_COMPLETE_NOW: | 246 case INSTANT_COMPLETE_NOW: |
252 view_->SetInstantSuggestion(string16()); | 247 view_->SetInstantSuggestion(string16()); |
253 if (!suggestion.text.empty()) | 248 if (!suggestion.text.empty()) |
254 FinalizeInstantQuery(view_->GetText(), suggestion, false); | 249 FinalizeInstantQuery(view_->GetText(), suggestion, false); |
255 break; | 250 break; |
256 | 251 |
257 case INSTANT_COMPLETE_NEVER: { | 252 case INSTANT_COMPLETE_NEVER: { |
258 DCHECK_EQ(INSTANT_SUGGESTION_SEARCH, suggestion.type); | 253 DCHECK_EQ(INSTANT_SUGGESTION_SEARCH, suggestion.type); |
259 view_->SetInstantSuggestion(suggestion.text); | 254 view_->SetInstantSuggestion(suggestion.text); |
260 SearchProvider* search_provider = | 255 SearchProvider* search_provider = |
261 autocomplete_controller_->search_provider(); | 256 autocomplete_controller()->search_provider(); |
262 if (search_provider) | 257 if (search_provider) |
263 search_provider->ClearInstantSuggestion(); | 258 search_provider->ClearInstantSuggestion(); |
264 break; | 259 break; |
265 } | 260 } |
266 | 261 |
267 case INSTANT_COMPLETE_REPLACE: { | 262 case INSTANT_COMPLETE_REPLACE: { |
268 const bool save_original_selection = !has_temporary_text_; | 263 const bool save_original_selection = !has_temporary_text_; |
269 view_->SetInstantSuggestion(string16()); | 264 view_->SetInstantSuggestion(string16()); |
270 has_temporary_text_ = true; | 265 has_temporary_text_ = true; |
271 is_temporary_text_set_by_instant_ = true; | 266 is_temporary_text_set_by_instant_ = true; |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
365 std::string())) { | 360 std::string())) { |
366 *title = controller_->GetTitle(); | 361 *title = controller_->GetTitle(); |
367 *favicon = controller_->GetFavicon(); | 362 *favicon = controller_->GetFavicon(); |
368 } | 363 } |
369 } | 364 } |
370 | 365 |
371 bool OmniboxEditModel::UseVerbatimInstant() { | 366 bool OmniboxEditModel::UseVerbatimInstant() { |
372 #if defined(OS_MACOSX) | 367 #if defined(OS_MACOSX) |
373 // TODO(suzhe): Fix Mac port to display Instant suggest in a separated NSView, | 368 // TODO(suzhe): Fix Mac port to display Instant suggest in a separated NSView, |
374 // so that we can display Instant suggest along with composition text. | 369 // so that we can display Instant suggest along with composition text. |
375 const AutocompleteInput& input = autocomplete_controller_->input(); | 370 const AutocompleteInput& input = autocomplete_controller()->input(); |
376 if (input.prevent_inline_autocomplete()) | 371 if (input.prevent_inline_autocomplete()) |
377 return true; | 372 return true; |
378 #endif | 373 #endif |
379 | 374 |
380 // The value of input.prevent_inline_autocomplete() is determined by the | 375 // The value of input.prevent_inline_autocomplete() is determined by the |
381 // following conditions: | 376 // following conditions: |
382 // 1. If the caret is at the end of the text. | 377 // 1. If the caret is at the end of the text. |
383 // 2. If it's in IME composition mode. | 378 // 2. If it's in IME composition mode. |
384 // We send the caret position to Instant (so it can determine #1 itself), and | 379 // We send the caret position to Instant (so it can determine #1 itself), and |
385 // we use a separated widget for displaying the Instant suggest (so it doesn't | 380 // we use a separated widget for displaying the Instant suggest (so it doesn't |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
461 } | 456 } |
462 | 457 |
463 void OmniboxEditModel::SetInputInProgress(bool in_progress) { | 458 void OmniboxEditModel::SetInputInProgress(bool in_progress) { |
464 if (user_input_in_progress_ == in_progress) | 459 if (user_input_in_progress_ == in_progress) |
465 return; | 460 return; |
466 | 461 |
467 user_input_in_progress_ = in_progress; | 462 user_input_in_progress_ = in_progress; |
468 if (user_input_in_progress_) { | 463 if (user_input_in_progress_) { |
469 time_user_first_modified_omnibox_ = base::TimeTicks::Now(); | 464 time_user_first_modified_omnibox_ = base::TimeTicks::Now(); |
470 content::RecordAction(content::UserMetricsAction("OmniboxInputInProgress")); | 465 content::RecordAction(content::UserMetricsAction("OmniboxInputInProgress")); |
471 autocomplete_controller_->ResetSession(); | 466 autocomplete_controller()->ResetSession(); |
472 } | 467 } |
473 controller_->OnInputInProgress(in_progress); | 468 controller_->OnInputInProgress(in_progress); |
474 | 469 |
475 delegate_->NotifySearchTabHelper(user_input_in_progress_, !in_revert_); | 470 delegate_->NotifySearchTabHelper(user_input_in_progress_, !in_revert_); |
476 } | 471 } |
477 | 472 |
478 void OmniboxEditModel::Revert() { | 473 void OmniboxEditModel::Revert() { |
479 SetInputInProgress(false); | 474 SetInputInProgress(false); |
480 paste_state_ = NONE; | 475 paste_state_ = NONE; |
481 InternalSetUserText(string16()); | 476 InternalSetUserText(string16()); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 // One example is when user presses Ctrl key while having a highlighted | 515 // One example is when user presses Ctrl key while having a highlighted |
521 // inline autocomplete text. | 516 // inline autocomplete text. |
522 // TODO: Rethink how we are going to handle this case to avoid | 517 // TODO: Rethink how we are going to handle this case to avoid |
523 // inconsistent behavior when user presses Ctrl key. | 518 // inconsistent behavior when user presses Ctrl key. |
524 // See http://crbug.com/165961 and http://crbug.com/165968 for more details. | 519 // See http://crbug.com/165961 and http://crbug.com/165968 for more details. |
525 cursor_position = user_text_.length(); | 520 cursor_position = user_text_.length(); |
526 } | 521 } |
527 | 522 |
528 // We don't explicitly clear OmniboxPopupModel::manually_selected_match, as | 523 // We don't explicitly clear OmniboxPopupModel::manually_selected_match, as |
529 // Start ends up invoking OmniboxPopupModel::OnResultChanged which clears it. | 524 // Start ends up invoking OmniboxPopupModel::OnResultChanged which clears it. |
530 autocomplete_controller_->Start(AutocompleteInput( | 525 autocomplete_controller()->Start(AutocompleteInput( |
531 user_text_, cursor_position, string16(), GURL(), | 526 user_text_, cursor_position, string16(), GURL(), |
532 prevent_inline_autocomplete || just_deleted_text_ || | 527 prevent_inline_autocomplete || just_deleted_text_ || |
533 (has_selected_text && inline_autocomplete_text_.empty()) || | 528 (has_selected_text && inline_autocomplete_text_.empty()) || |
534 (paste_state_ != NONE), keyword_is_selected, | 529 (paste_state_ != NONE), keyword_is_selected, |
535 keyword_is_selected || allow_exact_keyword_match_, | 530 keyword_is_selected || allow_exact_keyword_match_, |
536 AutocompleteInput::ALL_MATCHES)); | 531 AutocompleteInput::ALL_MATCHES)); |
537 } | 532 } |
538 | 533 |
539 void OmniboxEditModel::StopAutocomplete() { | 534 void OmniboxEditModel::StopAutocomplete() { |
540 autocomplete_controller_->Stop(true); | 535 autocomplete_controller()->Stop(true); |
541 } | 536 } |
542 | 537 |
543 bool OmniboxEditModel::CanPasteAndGo(const string16& text) const { | 538 bool OmniboxEditModel::CanPasteAndGo(const string16& text) const { |
544 if (!view_->command_updater()->IsCommandEnabled(IDC_OPEN_CURRENT_URL)) | 539 if (!view_->command_updater()->IsCommandEnabled(IDC_OPEN_CURRENT_URL)) |
545 return false; | 540 return false; |
546 | 541 |
547 AutocompleteMatch match; | 542 AutocompleteMatch match; |
548 ClassifyStringForPasteAndGo(text, &match, NULL); | 543 ClassifyStringForPasteAndGo(text, &match, NULL); |
549 return match.destination_url.is_valid(); | 544 return match.destination_url.is_valid(); |
550 } | 545 } |
(...skipping 19 matching lines...) Expand all Loading... |
570 // Get the URL and transition type for the selected entry. | 565 // Get the URL and transition type for the selected entry. |
571 AutocompleteMatch match; | 566 AutocompleteMatch match; |
572 GURL alternate_nav_url; | 567 GURL alternate_nav_url; |
573 GetInfoForCurrentText(&match, &alternate_nav_url); | 568 GetInfoForCurrentText(&match, &alternate_nav_url); |
574 | 569 |
575 // If CTRL is down it means the user wants to append ".com" to the text he | 570 // If CTRL is down it means the user wants to append ".com" to the text he |
576 // typed. If we can successfully generate a URL_WHAT_YOU_TYPED match doing | 571 // typed. If we can successfully generate a URL_WHAT_YOU_TYPED match doing |
577 // that, then we use this. These matches are marked as generated by the | 572 // that, then we use this. These matches are marked as generated by the |
578 // HistoryURLProvider so we only generate them if this provider is present. | 573 // HistoryURLProvider so we only generate them if this provider is present. |
579 if (control_key_state_ == DOWN_WITHOUT_CHANGE && !KeywordIsSelected() && | 574 if (control_key_state_ == DOWN_WITHOUT_CHANGE && !KeywordIsSelected() && |
580 autocomplete_controller_->history_url_provider()) { | 575 autocomplete_controller()->history_url_provider()) { |
581 // Generate a new AutocompleteInput, copying the latest one but using "com" | 576 // Generate a new AutocompleteInput, copying the latest one but using "com" |
582 // as the desired TLD. Then use this autocomplete input to generate a | 577 // as the desired TLD. Then use this autocomplete input to generate a |
583 // URL_WHAT_YOU_TYPED AutocompleteMatch. Note that using the most recent | 578 // URL_WHAT_YOU_TYPED AutocompleteMatch. Note that using the most recent |
584 // input instead of the currently visible text means we'll ignore any | 579 // input instead of the currently visible text means we'll ignore any |
585 // visible inline autocompletion: if a user types "foo" and is autocompleted | 580 // visible inline autocompletion: if a user types "foo" and is autocompleted |
586 // to "foodnetwork.com", ctrl-enter will navigate to "foo.com", not | 581 // to "foodnetwork.com", ctrl-enter will navigate to "foo.com", not |
587 // "foodnetwork.com". At the time of writing, this behavior matches | 582 // "foodnetwork.com". At the time of writing, this behavior matches |
588 // Internet Explorer, but not Firefox. | 583 // Internet Explorer, but not Firefox. |
589 const AutocompleteInput& old_input = autocomplete_controller_->input(); | 584 const AutocompleteInput& old_input = autocomplete_controller()->input(); |
590 AutocompleteInput input( | 585 AutocompleteInput input( |
591 old_input.text(), old_input.cursor_position(), ASCIIToUTF16("com"), | 586 old_input.text(), old_input.cursor_position(), ASCIIToUTF16("com"), |
592 GURL(), old_input.prevent_inline_autocomplete(), | 587 GURL(), old_input.prevent_inline_autocomplete(), |
593 old_input.prefer_keyword(), old_input.allow_exact_keyword_match(), | 588 old_input.prefer_keyword(), old_input.allow_exact_keyword_match(), |
594 old_input.matches_requested()); | 589 old_input.matches_requested()); |
595 AutocompleteMatch url_match = HistoryURLProvider::SuggestExactInput( | 590 AutocompleteMatch url_match = HistoryURLProvider::SuggestExactInput( |
596 autocomplete_controller_->history_url_provider(), input, true); | 591 autocomplete_controller()->history_url_provider(), input, true); |
597 | 592 |
598 if (url_match.destination_url.is_valid()) { | 593 if (url_match.destination_url.is_valid()) { |
599 // We have a valid URL, we use this newly generated AutocompleteMatch. | 594 // We have a valid URL, we use this newly generated AutocompleteMatch. |
600 match = url_match; | 595 match = url_match; |
601 alternate_nav_url = GURL(); | 596 alternate_nav_url = GURL(); |
602 } | 597 } |
603 } | 598 } |
604 | 599 |
605 if (!match.destination_url.is_valid()) | 600 if (!match.destination_url.is_valid()) |
606 return; | 601 return; |
(...skipping 30 matching lines...) Expand all Loading... |
637 void OmniboxEditModel::OpenMatch(const AutocompleteMatch& match, | 632 void OmniboxEditModel::OpenMatch(const AutocompleteMatch& match, |
638 WindowOpenDisposition disposition, | 633 WindowOpenDisposition disposition, |
639 const GURL& alternate_nav_url, | 634 const GURL& alternate_nav_url, |
640 size_t index) { | 635 size_t index) { |
641 // We only care about cases where there is a selection (i.e. the popup is | 636 // We only care about cases where there is a selection (i.e. the popup is |
642 // open). | 637 // open). |
643 if (popup_->IsOpen()) { | 638 if (popup_->IsOpen()) { |
644 const base::TimeTicks& now(base::TimeTicks::Now()); | 639 const base::TimeTicks& now(base::TimeTicks::Now()); |
645 // TODO(sreeram): Handle is_temporary_text_set_by_instant_ correctly. | 640 // TODO(sreeram): Handle is_temporary_text_set_by_instant_ correctly. |
646 AutocompleteLog log( | 641 AutocompleteLog log( |
647 autocomplete_controller_->input().text(), | 642 autocomplete_controller()->input().text(), |
648 just_deleted_text_, | 643 just_deleted_text_, |
649 autocomplete_controller_->input().type(), | 644 autocomplete_controller()->input().type(), |
650 popup_->selected_line(), | 645 popup_->selected_line(), |
651 -1, // don't yet know tab ID; set later if appropriate | 646 -1, // don't yet know tab ID; set later if appropriate |
652 delegate_->CurrentPageExists() ? ClassifyPage(delegate_->GetURL()) : | 647 delegate_->CurrentPageExists() ? ClassifyPage(delegate_->GetURL()) : |
653 metrics::OmniboxEventProto_PageClassification_OTHER, | 648 metrics::OmniboxEventProto_PageClassification_OTHER, |
654 now - time_user_first_modified_omnibox_, | 649 now - time_user_first_modified_omnibox_, |
655 string16::npos, // completed_length; possibly set later | 650 string16::npos, // completed_length; possibly set later |
656 now - autocomplete_controller_->last_time_default_match_changed(), | 651 now - autocomplete_controller()->last_time_default_match_changed(), |
657 result()); | 652 result()); |
658 DCHECK(user_input_in_progress_ || | 653 DCHECK(user_input_in_progress_ || |
659 match.provider->type() == AutocompleteProvider::TYPE_ZERO_SUGGEST) | 654 match.provider->type() == AutocompleteProvider::TYPE_ZERO_SUGGEST) |
660 << "We didn't get here through the expected series of calls. " | 655 << "We didn't get here through the expected series of calls. " |
661 << "time_user_first_modified_omnibox_ is not set correctly and other " | 656 << "time_user_first_modified_omnibox_ is not set correctly and other " |
662 << "things may be wrong. Match provider: " << match.provider->GetName(); | 657 << "things may be wrong. Match provider: " << match.provider->GetName(); |
663 DCHECK(log.elapsed_time_since_user_first_modified_omnibox >= | 658 DCHECK(log.elapsed_time_since_user_first_modified_omnibox >= |
664 log.elapsed_time_since_last_change_to_default_match) | 659 log.elapsed_time_since_last_change_to_default_match) |
665 << "We should've got the notification that the user modified the " | 660 << "We should've got the notification that the user modified the " |
666 << "omnibox text at same time or before the most recent time the " | 661 << "omnibox text at same time or before the most recent time the " |
667 << "default match changed."; | 662 << "default match changed."; |
668 if (index != OmniboxPopupModel::kNoMatch) | 663 if (index != OmniboxPopupModel::kNoMatch) |
669 log.selected_index = index; | 664 log.selected_index = index; |
670 if (match.inline_autocomplete_offset != string16::npos) { | 665 if (match.inline_autocomplete_offset != string16::npos) { |
671 DCHECK_GE(match.fill_into_edit.length(), | 666 DCHECK_GE(match.fill_into_edit.length(), |
672 match.inline_autocomplete_offset); | 667 match.inline_autocomplete_offset); |
673 log.completed_length = | 668 log.completed_length = |
674 match.fill_into_edit.length() - match.inline_autocomplete_offset; | 669 match.fill_into_edit.length() - match.inline_autocomplete_offset; |
675 } | 670 } |
676 | 671 |
677 if ((disposition == CURRENT_TAB) && delegate_->CurrentPageExists()) { | 672 if ((disposition == CURRENT_TAB) && delegate_->CurrentPageExists()) { |
678 // If we know the destination is being opened in the current tab, | 673 // If we know the destination is being opened in the current tab, |
679 // we can easily get the tab ID. (If it's being opened in a new | 674 // we can easily get the tab ID. (If it's being opened in a new |
680 // tab, we don't know the tab ID yet.) | 675 // tab, we don't know the tab ID yet.) |
681 log.tab_id = delegate_->GetSessionID().id(); | 676 log.tab_id = delegate_->GetSessionID().id(); |
682 } | 677 } |
683 autocomplete_controller_->AddProvidersInfo(&log.providers_info); | 678 autocomplete_controller()->AddProvidersInfo(&log.providers_info); |
684 content::NotificationService::current()->Notify( | 679 content::NotificationService::current()->Notify( |
685 chrome::NOTIFICATION_OMNIBOX_OPENED_URL, | 680 chrome::NOTIFICATION_OMNIBOX_OPENED_URL, |
686 content::Source<Profile>(profile_), | 681 content::Source<Profile>(profile_), |
687 content::Details<AutocompleteLog>(&log)); | 682 content::Details<AutocompleteLog>(&log)); |
688 HISTOGRAM_ENUMERATION("Omnibox.EventCount", 1, 2); | 683 HISTOGRAM_ENUMERATION("Omnibox.EventCount", 1, 2); |
689 } | 684 } |
690 | 685 |
691 TemplateURL* template_url = match.GetTemplateURL(profile_, false); | 686 TemplateURL* template_url = match.GetTemplateURL(profile_, false); |
692 if (template_url) { | 687 if (template_url) { |
693 if (match.transition == content::PAGE_TRANSITION_KEYWORD) { | 688 if (match.transition == content::PAGE_TRANSITION_KEYWORD) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
727 if (disposition != NEW_BACKGROUND_TAB) { | 722 if (disposition != NEW_BACKGROUND_TAB) { |
728 base::AutoReset<bool> tmp(&in_revert_, true); | 723 base::AutoReset<bool> tmp(&in_revert_, true); |
729 view_->RevertAll(); // Revert the box to its unedited state | 724 view_->RevertAll(); // Revert the box to its unedited state |
730 } | 725 } |
731 | 726 |
732 if (match.type == AutocompleteMatch::EXTENSION_APP) { | 727 if (match.type == AutocompleteMatch::EXTENSION_APP) { |
733 ExtensionAppProvider::LaunchAppFromOmnibox(match, profile_, disposition); | 728 ExtensionAppProvider::LaunchAppFromOmnibox(match, profile_, disposition); |
734 } else { | 729 } else { |
735 base::TimeDelta query_formulation_time = | 730 base::TimeDelta query_formulation_time = |
736 base::TimeTicks::Now() - time_user_first_modified_omnibox_; | 731 base::TimeTicks::Now() - time_user_first_modified_omnibox_; |
737 const GURL destination_url = autocomplete_controller_-> | 732 const GURL destination_url = autocomplete_controller()-> |
738 GetDestinationURL(match, query_formulation_time); | 733 GetDestinationURL(match, query_formulation_time); |
739 | 734 |
740 // If running with instant, notify the instant controller that a navigation | 735 // If running with instant, notify the instant controller that a navigation |
741 // is about to take place if we are navigating to a URL. This can be | 736 // is about to take place if we are navigating to a URL. This can be |
742 // determined by inspecting the transition type. To ensure that this is only | 737 // determined by inspecting the transition type. To ensure that this is only |
743 // done on Enter key press, check that the disposition is CURRENT_TAB. This | 738 // done on Enter key press, check that the disposition is CURRENT_TAB. This |
744 // is the same heuristic used by BrowserInstantController::OpenInstant | 739 // is the same heuristic used by BrowserInstantController::OpenInstant |
745 if (match.transition == content::PAGE_TRANSITION_TYPED && | 740 if (match.transition == content::PAGE_TRANSITION_TYPED && |
746 disposition == CURRENT_TAB) { | 741 disposition == CURRENT_TAB) { |
747 InstantController* instant = controller_->GetInstant(); | 742 InstantController* instant = controller_->GetInstant(); |
748 if (instant) | 743 if (instant) |
749 instant->OmniboxNavigateToURL(); | 744 instant->OmniboxNavigateToURL(); |
750 } | 745 } |
751 | 746 |
752 // This calls RevertAll again. | 747 // This calls RevertAll again. |
753 base::AutoReset<bool> tmp(&in_revert_, true); | 748 base::AutoReset<bool> tmp(&in_revert_, true); |
754 controller_->OnAutocompleteAccept(destination_url, disposition, | 749 controller_->OnAutocompleteAccept(destination_url, disposition, |
755 match.transition, alternate_nav_url); | 750 match.transition, alternate_nav_url); |
756 } | 751 } |
757 | 752 |
758 if (match.starred) | 753 if (match.starred) |
759 bookmark_utils::RecordBookmarkLaunch(bookmark_utils::LAUNCH_OMNIBOX); | 754 bookmark_utils::RecordBookmarkLaunch(bookmark_utils::LAUNCH_OMNIBOX); |
760 } | 755 } |
761 | 756 |
762 bool OmniboxEditModel::AcceptKeyword(EnteredKeywordModeMethod entered_method) { | 757 bool OmniboxEditModel::AcceptKeyword(EnteredKeywordModeMethod entered_method) { |
763 DCHECK(is_keyword_hint_ && !keyword_.empty()); | 758 DCHECK(is_keyword_hint_ && !keyword_.empty()); |
764 | 759 |
765 autocomplete_controller_->Stop(false); | 760 autocomplete_controller()->Stop(false); |
766 is_keyword_hint_ = false; | 761 is_keyword_hint_ = false; |
767 | 762 |
768 if (popup_->IsOpen()) | 763 if (popup_->IsOpen()) |
769 popup_->SetSelectedLineState(OmniboxPopupModel::KEYWORD); | 764 popup_->SetSelectedLineState(OmniboxPopupModel::KEYWORD); |
770 else | 765 else |
771 StartAutocomplete(false, true); | 766 StartAutocomplete(false, true); |
772 | 767 |
773 // Ensure the current selection is saved before showing keyword mode | 768 // Ensure the current selection is saved before showing keyword mode |
774 // so that moving to another line and then reverting the text will restore | 769 // so that moving to another line and then reverting the text will restore |
775 // the current state properly. | 770 // the current state properly. |
776 bool save_original_selection = !has_temporary_text_; | 771 bool save_original_selection = !has_temporary_text_; |
777 has_temporary_text_ = true; | 772 has_temporary_text_ = true; |
778 is_temporary_text_set_by_instant_ = false; | 773 is_temporary_text_set_by_instant_ = false; |
779 view_->OnTemporaryTextMaybeChanged( | 774 view_->OnTemporaryTextMaybeChanged( |
780 DisplayTextFromUserText(CurrentMatch().fill_into_edit), | 775 DisplayTextFromUserText(CurrentMatch().fill_into_edit), |
781 save_original_selection, true); | 776 save_original_selection, true); |
782 | 777 |
783 content::RecordAction(UserMetricsAction("AcceptedKeywordHint")); | 778 content::RecordAction(UserMetricsAction("AcceptedKeywordHint")); |
784 UMA_HISTOGRAM_ENUMERATION(kEnteredKeywordModeHistogram, entered_method, | 779 UMA_HISTOGRAM_ENUMERATION(kEnteredKeywordModeHistogram, entered_method, |
785 ENTERED_KEYWORD_MODE_NUM_ITEMS); | 780 ENTERED_KEYWORD_MODE_NUM_ITEMS); |
786 | 781 |
787 return true; | 782 return true; |
788 } | 783 } |
789 | 784 |
790 void OmniboxEditModel::ClearKeyword(const string16& visible_text) { | 785 void OmniboxEditModel::ClearKeyword(const string16& visible_text) { |
791 autocomplete_controller_->Stop(false); | 786 autocomplete_controller()->Stop(false); |
792 ClearPopupKeywordMode(); | 787 ClearPopupKeywordMode(); |
793 | 788 |
794 const string16 window_text(keyword_ + visible_text); | 789 const string16 window_text(keyword_ + visible_text); |
795 | 790 |
796 // Only reset the result if the edit text has changed since the | 791 // Only reset the result if the edit text has changed since the |
797 // keyword was accepted, or if the popup is closed. | 792 // keyword was accepted, or if the popup is closed. |
798 if (just_deleted_text_ || !visible_text.empty() || !popup_->IsOpen()) { | 793 if (just_deleted_text_ || !visible_text.empty() || !popup_->IsOpen()) { |
799 view_->OnBeforePossibleChange(); | 794 view_->OnBeforePossibleChange(); |
800 view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length(), | 795 view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length(), |
801 false, false); | 796 false, false); |
802 keyword_.clear(); | 797 keyword_.clear(); |
803 is_keyword_hint_ = false; | 798 is_keyword_hint_ = false; |
804 view_->OnAfterPossibleChange(); | 799 view_->OnAfterPossibleChange(); |
805 just_deleted_text_ = true; // OnAfterPossibleChange() fails to clear this | 800 just_deleted_text_ = true; // OnAfterPossibleChange() fails to clear this |
806 // since the edit contents have actually grown | 801 // since the edit contents have actually grown |
807 // longer. | 802 // longer. |
808 } else { | 803 } else { |
809 is_keyword_hint_ = true; | 804 is_keyword_hint_ = true; |
810 view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length(), | 805 view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length(), |
811 false, true); | 806 false, true); |
812 } | 807 } |
813 } | 808 } |
814 | 809 |
815 const AutocompleteResult& OmniboxEditModel::result() const { | 810 const AutocompleteResult& OmniboxEditModel::result() const { |
816 return autocomplete_controller_->result(); | 811 return autocomplete_controller()->result(); |
817 } | 812 } |
818 | 813 |
819 void OmniboxEditModel::OnSetFocus(bool control_down) { | 814 void OmniboxEditModel::OnSetFocus(bool control_down) { |
820 // If the omnibox lost focus while the caret was hidden and then regained | 815 // If the omnibox lost focus while the caret was hidden and then regained |
821 // focus, OnSetFocus() is called and should restore visibility. Note that | 816 // focus, OnSetFocus() is called and should restore visibility. Note that |
822 // focus can be regained without an accompanying call to | 817 // focus can be regained without an accompanying call to |
823 // OmniboxView::SetFocus(), e.g. by tabbing in. | 818 // OmniboxView::SetFocus(), e.g. by tabbing in. |
824 SetFocusState(OMNIBOX_FOCUS_VISIBLE, OMNIBOX_FOCUS_CHANGE_EXPLICIT); | 819 SetFocusState(OMNIBOX_FOCUS_VISIBLE, OMNIBOX_FOCUS_CHANGE_EXPLICIT); |
825 control_key_state_ = control_down ? DOWN_WITHOUT_CHANGE : UP; | 820 control_key_state_ = control_down ? DOWN_WITHOUT_CHANGE : UP; |
826 | 821 |
827 if (delegate_->CurrentPageExists()) { | 822 if (delegate_->CurrentPageExists()) { |
828 // TODO(jered): We may want to merge this into Start() and just call that | 823 // TODO(jered): We may want to merge this into Start() and just call that |
829 // here rather than having a special entry point for zero-suggest. Note | 824 // here rather than having a special entry point for zero-suggest. Note |
830 // that we avoid PermanentURL() here because it's not guaranteed to give us | 825 // that we avoid PermanentURL() here because it's not guaranteed to give us |
831 // the actual underlying current URL, e.g. if we're on the NTP and the | 826 // the actual underlying current URL, e.g. if we're on the NTP and the |
832 // |permanent_text_| is empty. | 827 // |permanent_text_| is empty. |
833 autocomplete_controller_->StartZeroSuggest(delegate_->GetURL(), | 828 autocomplete_controller()->StartZeroSuggest(delegate_->GetURL(), |
834 user_text_); | 829 user_text_); |
835 } | 830 } |
836 | 831 |
837 delegate_->NotifySearchTabHelper(user_input_in_progress_, !in_revert_); | 832 delegate_->NotifySearchTabHelper(user_input_in_progress_, !in_revert_); |
838 } | 833 } |
839 | 834 |
840 void OmniboxEditModel::SetCaretVisibility(bool visible) { | 835 void OmniboxEditModel::SetCaretVisibility(bool visible) { |
841 // Caret visibility only matters if the omnibox has focus. | 836 // Caret visibility only matters if the omnibox has focus. |
842 if (focus_state_ != OMNIBOX_FOCUS_NONE) { | 837 if (focus_state_ != OMNIBOX_FOCUS_NONE) { |
843 SetFocusState(visible ? OMNIBOX_FOCUS_VISIBLE : OMNIBOX_FOCUS_INVISIBLE, | 838 SetFocusState(visible ? OMNIBOX_FOCUS_VISIBLE : OMNIBOX_FOCUS_INVISIBLE, |
844 OMNIBOX_FOCUS_CHANGE_EXPLICIT); | 839 OMNIBOX_FOCUS_CHANGE_EXPLICIT); |
845 } | 840 } |
846 } | 841 } |
847 | 842 |
848 void OmniboxEditModel::OnWillKillFocus(gfx::NativeView view_gaining_focus) { | 843 void OmniboxEditModel::OnWillKillFocus(gfx::NativeView view_gaining_focus) { |
849 InstantController* instant = controller_->GetInstant(); | 844 InstantController* instant = controller_->GetInstant(); |
850 if (instant) { | 845 if (instant) { |
851 instant->OmniboxFocusChanged(OMNIBOX_FOCUS_NONE, | 846 instant->OmniboxFocusChanged(OMNIBOX_FOCUS_NONE, |
852 OMNIBOX_FOCUS_CHANGE_EXPLICIT, | 847 OMNIBOX_FOCUS_CHANGE_EXPLICIT, |
853 view_gaining_focus); | 848 view_gaining_focus); |
854 } | 849 } |
855 | 850 |
856 // TODO(jered): Rip this out along with StartZeroSuggest. | 851 // TODO(jered): Rip this out along with StartZeroSuggest. |
857 autocomplete_controller_->StopZeroSuggest(); | 852 autocomplete_controller()->StopZeroSuggest(); |
858 delegate_->NotifySearchTabHelper(user_input_in_progress_, !in_revert_); | 853 delegate_->NotifySearchTabHelper(user_input_in_progress_, !in_revert_); |
859 } | 854 } |
860 | 855 |
861 void OmniboxEditModel::OnKillFocus() { | 856 void OmniboxEditModel::OnKillFocus() { |
862 // TODO(samarth): determine if it is safe to move the call to | 857 // TODO(samarth): determine if it is safe to move the call to |
863 // OmniboxFocusChanged() from OnWillKillFocus() to here, which would let us | 858 // OmniboxFocusChanged() from OnWillKillFocus() to here, which would let us |
864 // just call SetFocusState() to handle the state change. | 859 // just call SetFocusState() to handle the state change. |
865 focus_state_ = OMNIBOX_FOCUS_NONE; | 860 focus_state_ = OMNIBOX_FOCUS_NONE; |
866 control_key_state_ = UP; | 861 control_key_state_ = UP; |
867 paste_state_ = NONE; | 862 paste_state_ = NONE; |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
944 // TODO(pkasting): The popup is working on a query but is not open. We | 939 // TODO(pkasting): The popup is working on a query but is not open. We |
945 // should force it to open immediately. | 940 // should force it to open immediately. |
946 } | 941 } |
947 } else { | 942 } else { |
948 InstantController* instant = controller_->GetInstant(); | 943 InstantController* instant = controller_->GetInstant(); |
949 if (instant && instant->OnUpOrDownKeyPressed(count)) { | 944 if (instant && instant->OnUpOrDownKeyPressed(count)) { |
950 // If Instant handles the key press, it's showing a list of suggestions | 945 // If Instant handles the key press, it's showing a list of suggestions |
951 // that it's stepping through. In that case, our popup model is | 946 // that it's stepping through. In that case, our popup model is |
952 // irrelevant, so don't process the key press ourselves. However, do stop | 947 // irrelevant, so don't process the key press ourselves. However, do stop |
953 // the autocomplete system from changing the results. | 948 // the autocomplete system from changing the results. |
954 autocomplete_controller_->Stop(false); | 949 autocomplete_controller()->Stop(false); |
955 } else { | 950 } else { |
956 // The popup is open, so the user should be able to interact with it | 951 // The popup is open, so the user should be able to interact with it |
957 // normally. | 952 // normally. |
958 popup_->Move(count); | 953 popup_->Move(count); |
959 } | 954 } |
960 } | 955 } |
961 } | 956 } |
962 | 957 |
963 void OmniboxEditModel::OnPopupDataChanged( | 958 void OmniboxEditModel::OnPopupDataChanged( |
964 const string16& text, | 959 const string16& text, |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1177 } else { | 1172 } else { |
1178 popup_->OnResultChanged(); | 1173 popup_->OnResultChanged(); |
1179 } | 1174 } |
1180 | 1175 |
1181 if (popup_->IsOpen()) { | 1176 if (popup_->IsOpen()) { |
1182 OnPopupBoundsChanged(popup_->view()->GetTargetBounds()); | 1177 OnPopupBoundsChanged(popup_->view()->GetTargetBounds()); |
1183 | 1178 |
1184 InstantController* instant = controller_->GetInstant(); | 1179 InstantController* instant = controller_->GetInstant(); |
1185 if (instant && !in_revert_) { | 1180 if (instant && !in_revert_) { |
1186 instant->HandleAutocompleteResults( | 1181 instant->HandleAutocompleteResults( |
1187 *autocomplete_controller_->providers()); | 1182 *autocomplete_controller()->providers()); |
1188 } | 1183 } |
1189 } else if (was_open) { | 1184 } else if (was_open) { |
1190 // Accepts the temporary text as the user text, because it makes little | 1185 // Accepts the temporary text as the user text, because it makes little |
1191 // sense to have temporary text when the popup is closed. | 1186 // sense to have temporary text when the popup is closed. |
1192 InternalSetUserText(UserTextFromDisplayText(view_->GetText())); | 1187 InternalSetUserText(UserTextFromDisplayText(view_->GetText())); |
1193 has_temporary_text_ = false; | 1188 has_temporary_text_ = false; |
1194 is_temporary_text_set_by_instant_ = false; | 1189 is_temporary_text_set_by_instant_ = false; |
1195 OnPopupBoundsChanged(gfx::Rect()); | 1190 OnPopupBoundsChanged(gfx::Rect()); |
1196 delegate_->NotifySearchTabHelper(user_input_in_progress_, !in_revert_); | 1191 delegate_->NotifySearchTabHelper(user_input_in_progress_, !in_revert_); |
1197 } | 1192 } |
1198 } | 1193 } |
1199 | 1194 |
1200 bool OmniboxEditModel::query_in_progress() const { | 1195 bool OmniboxEditModel::query_in_progress() const { |
1201 return !autocomplete_controller_->done(); | 1196 return !autocomplete_controller()->done(); |
1202 } | 1197 } |
1203 | 1198 |
1204 void OmniboxEditModel::InternalSetUserText(const string16& text) { | 1199 void OmniboxEditModel::InternalSetUserText(const string16& text) { |
1205 user_text_ = text; | 1200 user_text_ = text; |
1206 just_deleted_text_ = false; | 1201 just_deleted_text_ = false; |
1207 inline_autocomplete_text_.clear(); | 1202 inline_autocomplete_text_.clear(); |
1208 } | 1203 } |
1209 | 1204 |
1210 bool OmniboxEditModel::KeywordIsSelected() const { | 1205 bool OmniboxEditModel::KeywordIsSelected() const { |
1211 return !is_keyword_hint_ && !keyword_.empty(); | 1206 return !is_keyword_hint_ && !keyword_.empty(); |
(...skipping 11 matching lines...) Expand all Loading... |
1223 } | 1218 } |
1224 | 1219 |
1225 string16 OmniboxEditModel::UserTextFromDisplayText(const string16& text) const { | 1220 string16 OmniboxEditModel::UserTextFromDisplayText(const string16& text) const { |
1226 return KeywordIsSelected() ? (keyword_ + char16(' ') + text) : text; | 1221 return KeywordIsSelected() ? (keyword_ + char16(' ') + text) : text; |
1227 } | 1222 } |
1228 | 1223 |
1229 void OmniboxEditModel::InfoForCurrentSelection(AutocompleteMatch* match, | 1224 void OmniboxEditModel::InfoForCurrentSelection(AutocompleteMatch* match, |
1230 GURL* alternate_nav_url) const { | 1225 GURL* alternate_nav_url) const { |
1231 DCHECK(match != NULL); | 1226 DCHECK(match != NULL); |
1232 const AutocompleteResult& result = this->result(); | 1227 const AutocompleteResult& result = this->result(); |
1233 if (!autocomplete_controller_->done()) { | 1228 if (!autocomplete_controller()->done()) { |
1234 // It's technically possible for |result| to be empty if no provider returns | 1229 // It's technically possible for |result| to be empty if no provider returns |
1235 // a synchronous result but the query has not completed synchronously; | 1230 // a synchronous result but the query has not completed synchronously; |
1236 // pratically, however, that should never actually happen. | 1231 // pratically, however, that should never actually happen. |
1237 if (result.empty()) | 1232 if (result.empty()) |
1238 return; | 1233 return; |
1239 // The user cannot have manually selected a match, or the query would have | 1234 // The user cannot have manually selected a match, or the query would have |
1240 // stopped. So the default match must be the desired selection. | 1235 // stopped. So the default match must be the desired selection. |
1241 *match = *result.default_match(); | 1236 *match = *result.default_match(); |
1242 } else { | 1237 } else { |
1243 CHECK(popup_->IsOpen()); | 1238 CHECK(popup_->IsOpen()); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1327 old_text, space_position, | 1322 old_text, space_position, |
1328 old_text.length() - space_position)) { | 1323 old_text.length() - space_position)) { |
1329 return false; | 1324 return false; |
1330 } | 1325 } |
1331 | 1326 |
1332 // Then check if the text before the inserted space matches a keyword. | 1327 // Then check if the text before the inserted space matches a keyword. |
1333 string16 keyword; | 1328 string16 keyword; |
1334 TrimWhitespace(new_text.substr(0, space_position), TRIM_LEADING, &keyword); | 1329 TrimWhitespace(new_text.substr(0, space_position), TRIM_LEADING, &keyword); |
1335 // TODO(sreeram): Once the Instant extended API supports keywords properly, | 1330 // TODO(sreeram): Once the Instant extended API supports keywords properly, |
1336 // keyword_provider() should never be NULL. Remove that clause. | 1331 // keyword_provider() should never be NULL. Remove that clause. |
1337 return !keyword.empty() && autocomplete_controller_->keyword_provider() && | 1332 return !keyword.empty() && autocomplete_controller()->keyword_provider() && |
1338 !autocomplete_controller_->keyword_provider()-> | 1333 !autocomplete_controller()->keyword_provider()-> |
1339 GetKeywordForText(keyword).empty(); | 1334 GetKeywordForText(keyword).empty(); |
1340 } | 1335 } |
1341 | 1336 |
1342 bool OmniboxEditModel::DoInstant(const AutocompleteMatch& match) { | 1337 bool OmniboxEditModel::DoInstant(const AutocompleteMatch& match) { |
1343 InstantController* instant = controller_->GetInstant(); | 1338 InstantController* instant = controller_->GetInstant(); |
1344 if (!instant || in_revert_) | 1339 if (!instant || in_revert_) |
1345 return false; | 1340 return false; |
1346 | 1341 |
1347 // Don't call Update() if the change is a result of a | 1342 // Don't call Update() if the change is a result of a |
1348 // INSTANT_COMPLETE_REPLACE instant suggestion. | 1343 // INSTANT_COMPLETE_REPLACE instant suggestion. |
1349 if (has_temporary_text_ && is_temporary_text_set_by_instant_) | 1344 if (has_temporary_text_ && is_temporary_text_set_by_instant_) |
1350 return false; | 1345 return false; |
1351 | 1346 |
1352 // The two pieces of text we want to send Instant, viz., what the user has | 1347 // The two pieces of text we want to send Instant, viz., what the user has |
1353 // typed, and the full omnibox text including any inline autocompletion. | 1348 // typed, and the full omnibox text including any inline autocompletion. |
1354 string16 user_text = has_temporary_text_ ? | 1349 string16 user_text = has_temporary_text_ ? |
1355 match.fill_into_edit : DisplayTextFromUserText(user_text_); | 1350 match.fill_into_edit : DisplayTextFromUserText(user_text_); |
1356 string16 full_text = view_->GetText(); | 1351 string16 full_text = view_->GetText(); |
1357 | 1352 |
1358 // Remove "?" if we're in forced query mode. | 1353 // Remove "?" if we're in forced query mode. |
1359 AutocompleteInput::RemoveForcedQueryStringIfNecessary( | 1354 AutocompleteInput::RemoveForcedQueryStringIfNecessary( |
1360 autocomplete_controller_->input().type(), &user_text); | 1355 autocomplete_controller()->input().type(), &user_text); |
1361 AutocompleteInput::RemoveForcedQueryStringIfNecessary( | 1356 AutocompleteInput::RemoveForcedQueryStringIfNecessary( |
1362 autocomplete_controller_->input().type(), &full_text); | 1357 autocomplete_controller()->input().type(), &full_text); |
1363 | 1358 |
1364 size_t start, end; | 1359 size_t start, end; |
1365 view_->GetSelectionBounds(&start, &end); | 1360 view_->GetSelectionBounds(&start, &end); |
1366 | 1361 |
1367 return instant->Update(match, user_text, full_text, start, end, | 1362 return instant->Update(match, user_text, full_text, start, end, |
1368 UseVerbatimInstant(), user_input_in_progress_, popup_->IsOpen(), | 1363 UseVerbatimInstant(), user_input_in_progress_, popup_->IsOpen(), |
1369 in_escape_handler_, KeywordIsSelected()); | 1364 in_escape_handler_, KeywordIsSelected()); |
1370 } | 1365 } |
1371 | 1366 |
1372 void OmniboxEditModel::DoPreconnect(const AutocompleteMatch& match) { | 1367 void OmniboxEditModel::DoPreconnect(const AutocompleteMatch& match) { |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1429 instant->OmniboxFocusChanged(state, reason, NULL); | 1424 instant->OmniboxFocusChanged(state, reason, NULL); |
1430 | 1425 |
1431 // Update state and notify view if the omnibox has focus and the caret | 1426 // Update state and notify view if the omnibox has focus and the caret |
1432 // visibility changed. | 1427 // visibility changed. |
1433 const bool was_caret_visible = is_caret_visible(); | 1428 const bool was_caret_visible = is_caret_visible(); |
1434 focus_state_ = state; | 1429 focus_state_ = state; |
1435 if (focus_state_ != OMNIBOX_FOCUS_NONE && | 1430 if (focus_state_ != OMNIBOX_FOCUS_NONE && |
1436 is_caret_visible() != was_caret_visible) | 1431 is_caret_visible() != was_caret_visible) |
1437 view_->ApplyCaretVisibility(); | 1432 view_->ApplyCaretVisibility(); |
1438 } | 1433 } |
OLD | NEW |