Index: chrome/browser/ui/omnibox/omnibox_edit_model.cc |
diff --git a/chrome/browser/ui/omnibox/omnibox_edit_model.cc b/chrome/browser/ui/omnibox/omnibox_edit_model.cc |
index b5bb65d2ac1709ca96816ba0484b95acb017ab02..ecaf6948e142cb9ab15e0e2a50f5ffd61a41a9c6 100644 |
--- a/chrome/browser/ui/omnibox/omnibox_edit_model.cc |
+++ b/chrome/browser/ui/omnibox/omnibox_edit_model.cc |
@@ -463,10 +463,28 @@ void OmniboxEditModel::AdjustTextForCopy(int sel_min, |
if ((sel_min != 0) || controller_->GetToolbarModel()->WouldReplaceURL()) |
return; |
- if (!user_input_in_progress_ && is_all_selected) { |
- // The user selected all the text and has not edited it. Use the url as the |
- // text so that if the scheme was stripped it's added back, and the url |
- // is unescaped (we escape parts of the url for display). |
+ // Check whether the user is trying to copy the current page's URL by |
+ // selecting the whole thing without editing it. |
+ // |
+ // This is complicated by ZeroSuggest. When ZeroSuggest is active, the user |
+ // may be selecting different items and thus changing the address bar text, |
+ // even though !user_input_in_progress_; and the permanent URL may change |
+ // without updating the visible text, just like when user input is in |
+ // progress. In these cases, we don't want to copy the underlying URL, we |
+ // want to copy what the user actually sees. However, if we simply never do |
+ // this block when !popup_model()->IsOpen(), then just clicking into the |
+ // address bar and trying to copy will always bypass this block on pages that |
+ // trigger ZeroSuggest, which is too conservative. Instead, in the |
+ // ZeroSuggest case, we check that (a) the user hasn't selected one of the |
+ // other suggestions, and (b) the selected text is still the same as the |
+ // permanent text. ((b) probably implies (a), but it doesn't hurt to be |
+ // sure.) If these hold, then it's safe to copy the underlying URL. |
+ if (!user_input_in_progress_ && is_all_selected && |
+ (!popup_model() || !popup_model()->IsOpen() || |
+ ((popup_model()->selected_line() == 0) && (*text == permanent_text_)))) { |
+ // It's safe to copy the underlying URL. These lines ensure that if the |
+ // scheme was stripped it's added back, and the URL is unescaped (we escape |
+ // parts of it for display). |
*url = PermanentURL(); |
*text = base::UTF8ToUTF16(url->spec()); |
*write_url = true; |
@@ -985,42 +1003,48 @@ void OmniboxEditModel::OnKillFocus() { |
paste_state_ = NONE; |
} |
+bool OmniboxEditModel::WillHandleEscapeKey() const { |
+ return user_input_in_progress_ || |
+ (has_temporary_text_ && |
+ (CurrentMatch(NULL).destination_url != original_url_)); |
+} |
+ |
bool OmniboxEditModel::OnEscapeKeyPressed() { |
- const AutocompleteMatch& match = CurrentMatch(NULL); |
- if (has_temporary_text_) { |
- if (match.destination_url != original_url_) { |
- RevertTemporaryText(true); |
- return true; |
- } |
+ if (has_temporary_text_ && |
+ (CurrentMatch(NULL).destination_url != original_url_)) { |
+ RevertTemporaryText(true); |
+ return true; |
} |
// We do not clear the pending entry from the omnibox when a load is first |
- // stopped. If the user presses Escape while stopped, we clear it. |
+ // stopped. If the user presses Escape while stopped, whether editing or not, |
+ // we clear it. |
if (delegate_->CurrentPageExists() && !delegate_->IsLoading()) { |
delegate_->GetNavigationController().DiscardNonCommittedEntries(); |
view_->Update(); |
} |
- // If the user wasn't editing, but merely had focus in the edit, allow <esc> |
- // to be processed as an accelerator, so it can still be used to stop a load. |
- // When the permanent text isn't all selected we still fall through to the |
- // SelectAll() call below so users can arrow around in the text and then hit |
- // <esc> to quickly replace all the text; this matches IE. |
- const bool has_zero_suggest_match = match.provider && |
- (match.provider->type() == AutocompleteProvider::TYPE_ZERO_SUGGEST); |
- if (!has_zero_suggest_match && !user_input_in_progress_ && |
- view_->IsSelectAll()) |
- return false; |
- |
if (!user_text_.empty()) { |
UMA_HISTOGRAM_ENUMERATION(kOmniboxUserTextClearedHistogram, |
OMNIBOX_USER_TEXT_CLEARED_WITH_ESCAPE, |
OMNIBOX_USER_TEXT_CLEARED_NUM_OF_ITEMS); |
} |
+ // Unconditionally revert/select all. This ensures any popup, whether due to |
+ // normal editing or ZeroSuggest, is closed, and the full text is selected. |
+ // This in turn allows the user to use escape to quickly select all the text |
+ // for ease of replacement, and matches other browsers. |
+ bool user_input_was_in_progress = user_input_in_progress_; |
view_->RevertAll(); |
view_->SelectAll(true); |
- return true; |
+ |
+ // If the user was in the midst of editing, don't cancel any underlying page |
+ // load. This doesn't match IE or Firefox, but seems more correct. Note that |
+ // we do allow the page load to be stopped in the case where ZeroSuggest was |
+ // visible; this is so that it's still possible to focus the address bar and |
+ // hit escape once to stop a load even if the address being loaded triggers |
+ // the ZeroSuggest popup. |
+ return user_input_was_in_progress; |
} |
void OmniboxEditModel::OnControlKeyChanged(bool pressed) { |