1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // This file defines helper functions shared by the various implementations
8 #include "components/omnibox/browser/omnibox_view.h"
10 #include "base/strings/string16.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "components/omnibox/browser/autocomplete_match.h"
14 #include "components/omnibox/browser/omnibox_client.h"
15 #include "components/omnibox/browser/omnibox_edit_controller.h"
16 #include "components/toolbar/toolbar_model.h"
17 #include "grit/components_scaled_resources.h"
18 #include "ui/base/clipboard/clipboard.h"
19 #include "ui/base/l10n/l10n_util.h"
22 base::string16
OmniboxView::StripJavascriptSchemas(const base::string16
& text
) {
23 const base::string16
kJsPrefix(
24 base::ASCIIToUTF16(url::kJavaScriptScheme
) + base::ASCIIToUTF16(":"));
25 base::string16
out(text
);
26 while (base::StartsWith(out
, kJsPrefix
,
27 base::CompareCase::INSENSITIVE_ASCII
)) {
28 base::TrimWhitespace(out
.substr(kJsPrefix
.length()), base::TRIM_LEADING
,
35 base::string16
OmniboxView::SanitizeTextForPaste(const base::string16
& text
) {
36 // Check for non-newline whitespace; if found, collapse whitespace runs down
38 // TODO(shess): It may also make sense to ignore leading or
39 // trailing whitespace when making this determination.
40 for (size_t i
= 0; i
< text
.size(); ++i
) {
41 if (base::IsUnicodeWhitespace(text
[i
]) &&
42 text
[i
] != '\n' && text
[i
] != '\r') {
43 const base::string16 collapsed
= base::CollapseWhitespace(text
, false);
44 // If the user is pasting all-whitespace, paste a single space
45 // rather than nothing, since pasting nothing feels broken.
46 return collapsed
.empty() ?
47 base::ASCIIToUTF16(" ") : StripJavascriptSchemas(collapsed
);
51 // Otherwise, all whitespace is newlines; remove it entirely.
52 return StripJavascriptSchemas(base::CollapseWhitespace(text
, true));
56 base::string16
OmniboxView::GetClipboardText() {
58 ui::Clipboard
* clipboard
= ui::Clipboard::GetForCurrentThread();
59 if (clipboard
->IsFormatAvailable(ui::Clipboard::GetPlainTextWFormatType(),
60 ui::CLIPBOARD_TYPE_COPY_PASTE
)) {
62 clipboard
->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE
, &text
);
63 return SanitizeTextForPaste(text
);
66 // Try bookmark format.
68 // It is tempting to try bookmark format first, but the URL we get out of a
69 // bookmark has been cannonicalized via GURL. This means if a user copies
70 // and pastes from the URL bar to itself, the text will get fixed up and
71 // cannonicalized, which is not what the user expects. By pasting in this
72 // order, we are sure to paste what the user copied.
73 if (clipboard
->IsFormatAvailable(ui::Clipboard::GetUrlWFormatType(),
74 ui::CLIPBOARD_TYPE_COPY_PASTE
)) {
76 clipboard
->ReadBookmark(NULL
, &url_str
);
77 // pass resulting url string through GURL to normalize
80 return StripJavascriptSchemas(base::UTF8ToUTF16(url
.spec()));
83 return base::string16();
86 OmniboxView::~OmniboxView() {
89 void OmniboxView::OpenMatch(const AutocompleteMatch
& match
,
90 WindowOpenDisposition disposition
,
91 const GURL
& alternate_nav_url
,
92 const base::string16
& pasted_text
,
93 size_t selected_line
) {
94 // Invalid URLs such as chrome://history can end up here.
95 if (!match
.destination_url
.is_valid() || !model_
)
98 match
, disposition
, alternate_nav_url
, pasted_text
, selected_line
);
102 bool OmniboxView::IsEditingOrEmpty() const {
103 return (model_
.get() && model_
->user_input_in_progress()) ||
104 (GetOmniboxTextLength() == 0);
107 int OmniboxView::GetIcon() const {
108 if (!IsEditingOrEmpty())
109 return controller_
->GetToolbarModel()->GetIcon();
110 int id
= AutocompleteMatch::TypeToIcon(model_
.get() ?
111 model_
->CurrentTextType() : AutocompleteMatchType::URL_WHAT_YOU_TYPED
);
112 return (id
== IDR_OMNIBOX_HTTP
) ? IDR_LOCATION_BAR_HTTP
: id
;
115 void OmniboxView::SetUserText(const base::string16
& text
) {
116 SetUserText(text
, text
, true);
119 void OmniboxView::SetUserText(const base::string16
& text
,
120 const base::string16
& display_text
,
123 model_
->SetUserText(text
);
124 SetWindowTextAndCaretPos(display_text
, display_text
.length(), update_popup
,
128 void OmniboxView::ShowURL() {
130 controller_
->GetToolbarModel()->set_url_replacement_enabled(false);
131 model_
->UpdatePermanentText();
132 RevertWithoutResettingSearchTermReplacement();
136 void OmniboxView::HideURL() {
137 controller_
->GetToolbarModel()->set_url_replacement_enabled(true);
138 model_
->UpdatePermanentText();
139 RevertWithoutResettingSearchTermReplacement();
142 void OmniboxView::RevertAll() {
143 controller_
->GetToolbarModel()->set_url_replacement_enabled(true);
144 RevertWithoutResettingSearchTermReplacement();
147 void OmniboxView::RevertWithoutResettingSearchTermReplacement() {
154 void OmniboxView::CloseOmniboxPopup() {
156 model_
->StopAutocomplete();
159 bool OmniboxView::IsImeShowingPopup() const {
160 // Default to claiming that the IME is not showing a popup, since hiding the
161 // omnibox dropdown is a bad user experience when we don't know for sure that
166 void OmniboxView::ShowImeIfNeeded() {
169 bool OmniboxView::IsIndicatingQueryRefinement() const {
170 // The default implementation always returns false. Mobile ports can override
171 // this method and implement as needed.
175 void OmniboxView::OnMatchOpened(const AutocompleteMatch
& match
) {
178 OmniboxView::OmniboxView(OmniboxEditController
* controller
,
179 scoped_ptr
<OmniboxClient
> client
)
180 : controller_(controller
) {
181 // |client| can be null in tests.
184 new OmniboxEditModel(this, controller
, client
.Pass()));
188 void OmniboxView::TextChanged() {
189 EmphasizeURLComponents();