• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 // This file defines helper functions shared by the various implementations
6 // of OmniboxView.
7 
8 #include "chrome/browser/ui/omnibox/omnibox_view.h"
9 
10 #include "base/strings/string16.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/autocomplete/autocomplete_match.h"
14 #include "chrome/browser/ui/omnibox/omnibox_edit_controller.h"
15 #include "chrome/browser/ui/toolbar/toolbar_model.h"
16 #include "ui/base/clipboard/clipboard.h"
17 
18 // static
StripJavascriptSchemas(const base::string16 & text)19 base::string16 OmniboxView::StripJavascriptSchemas(const base::string16& text) {
20   const base::string16 kJsPrefix(ASCIIToUTF16(content::kJavaScriptScheme) +
21                            ASCIIToUTF16(":"));
22   base::string16 out(text);
23   while (StartsWith(out, kJsPrefix, false))
24     TrimWhitespace(out.substr(kJsPrefix.length()), TRIM_LEADING, &out);
25   return out;
26 }
27 
28 // static
SanitizeTextForPaste(const base::string16 & text)29 base::string16 OmniboxView::SanitizeTextForPaste(const base::string16& text) {
30   // Check for non-newline whitespace; if found, collapse whitespace runs down
31   // to single spaces.
32   // TODO(shess): It may also make sense to ignore leading or
33   // trailing whitespace when making this determination.
34   for (size_t i = 0; i < text.size(); ++i) {
35     if (IsWhitespace(text[i]) && text[i] != '\n' && text[i] != '\r') {
36       const base::string16 collapsed = CollapseWhitespace(text, false);
37       // If the user is pasting all-whitespace, paste a single space
38       // rather than nothing, since pasting nothing feels broken.
39       return collapsed.empty() ?
40           ASCIIToUTF16(" ") : StripJavascriptSchemas(collapsed);
41     }
42   }
43 
44   // Otherwise, all whitespace is newlines; remove it entirely.
45   return StripJavascriptSchemas(CollapseWhitespace(text, true));
46 }
47 
48 // static
GetClipboardText()49 base::string16 OmniboxView::GetClipboardText() {
50   // Try text format.
51   ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
52   if (clipboard->IsFormatAvailable(ui::Clipboard::GetPlainTextWFormatType(),
53                                    ui::CLIPBOARD_TYPE_COPY_PASTE)) {
54     base::string16 text;
55     clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &text);
56     return SanitizeTextForPaste(text);
57   }
58 
59   // Try bookmark format.
60   //
61   // It is tempting to try bookmark format first, but the URL we get out of a
62   // bookmark has been cannonicalized via GURL.  This means if a user copies
63   // and pastes from the URL bar to itself, the text will get fixed up and
64   // cannonicalized, which is not what the user expects.  By pasting in this
65   // order, we are sure to paste what the user copied.
66   if (clipboard->IsFormatAvailable(ui::Clipboard::GetUrlWFormatType(),
67                                    ui::CLIPBOARD_TYPE_COPY_PASTE)) {
68     std::string url_str;
69     clipboard->ReadBookmark(NULL, &url_str);
70     // pass resulting url string through GURL to normalize
71     GURL url(url_str);
72     if (url.is_valid())
73       return StripJavascriptSchemas(UTF8ToUTF16(url.spec()));
74   }
75 
76   return base::string16();
77 }
78 
~OmniboxView()79 OmniboxView::~OmniboxView() {
80 }
81 
OpenMatch(const AutocompleteMatch & match,WindowOpenDisposition disposition,const GURL & alternate_nav_url,size_t selected_line)82 void OmniboxView::OpenMatch(const AutocompleteMatch& match,
83                             WindowOpenDisposition disposition,
84                             const GURL& alternate_nav_url,
85                             size_t selected_line) {
86   // Invalid URLs such as chrome://history can end up here.
87   if (!match.destination_url.is_valid())
88     return;
89   if (model_.get())
90     model_->OpenMatch(match, disposition, alternate_nav_url, selected_line);
91 }
92 
IsEditingOrEmpty() const93 bool OmniboxView::IsEditingOrEmpty() const {
94   return (model_.get() && model_->user_input_in_progress()) ||
95       (GetOmniboxTextLength() == 0);
96 }
97 
GetIcon() const98 int OmniboxView::GetIcon() const {
99   if (!IsEditingOrEmpty())
100     return controller_->GetToolbarModel()->GetIcon();
101   return AutocompleteMatch::TypeToLocationBarIcon(model_.get() ?
102       model_->CurrentTextType() : AutocompleteMatchType::URL_WHAT_YOU_TYPED);
103 }
104 
SetUserText(const base::string16 & text)105 void OmniboxView::SetUserText(const base::string16& text) {
106   SetUserText(text, text, true);
107 }
108 
SetUserText(const base::string16 & text,const base::string16 & display_text,bool update_popup)109 void OmniboxView::SetUserText(const base::string16& text,
110                               const base::string16& display_text,
111                               bool update_popup) {
112   if (model_.get())
113     model_->SetUserText(text);
114   SetWindowTextAndCaretPos(display_text, display_text.length(), update_popup,
115                            true);
116 }
117 
ShowURL()118 void OmniboxView::ShowURL() {
119   SetFocus();
120   controller_->GetToolbarModel()->set_url_replacement_enabled(false);
121   model_->UpdatePermanentText();
122   RevertWithoutResettingSearchTermReplacement();
123   SelectAll(true);
124 }
125 
RevertAll()126 void OmniboxView::RevertAll() {
127   controller_->GetToolbarModel()->set_url_replacement_enabled(true);
128   RevertWithoutResettingSearchTermReplacement();
129 }
130 
RevertWithoutResettingSearchTermReplacement()131 void OmniboxView::RevertWithoutResettingSearchTermReplacement() {
132   CloseOmniboxPopup();
133   if (model_.get())
134     model_->Revert();
135   TextChanged();
136 }
137 
CloseOmniboxPopup()138 void OmniboxView::CloseOmniboxPopup() {
139   if (model_.get())
140     model_->StopAutocomplete();
141 }
142 
IsImeShowingPopup() const143 bool OmniboxView::IsImeShowingPopup() const {
144   // Default to claiming that the IME is not showing a popup, since hiding the
145   // omnibox dropdown is a bad user experience when we don't know for sure that
146   // we have to.
147   return false;
148 }
149 
IsIndicatingQueryRefinement() const150 bool OmniboxView::IsIndicatingQueryRefinement() const {
151   // The default implementation always returns false.  Mobile ports can override
152   // this method and implement as needed.
153   return false;
154 }
155 
OmniboxView(Profile * profile,OmniboxEditController * controller,CommandUpdater * command_updater)156 OmniboxView::OmniboxView(Profile* profile,
157                          OmniboxEditController* controller,
158                          CommandUpdater* command_updater)
159     : controller_(controller),
160       command_updater_(command_updater) {
161   // |profile| can be NULL in tests.
162   if (profile)
163     model_.reset(new OmniboxEditModel(this, controller, profile));
164 }
165 
TextChanged()166 void OmniboxView::TextChanged() {
167   EmphasizeURLComponents();
168   if (model_.get())
169     model_->OnChanged();
170 }
171