OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/autofill/save_card_bubble_controller_impl.h" | 5 #include "chrome/browser/ui/autofill/save_card_bubble_controller_impl.h" |
6 | 6 |
7 #include "base/i18n/message_formatter.h" | |
8 #include "base/strings/string_util.h" | |
9 #include "base/strings/utf_string_conversions.h" | |
7 #include "chrome/browser/ui/autofill/save_card_bubble_view.h" | 10 #include "chrome/browser/ui/autofill/save_card_bubble_view.h" |
8 #include "chrome/browser/ui/browser.h" | 11 #include "chrome/browser/ui/browser.h" |
9 #include "chrome/browser/ui/browser_finder.h" | 12 #include "chrome/browser/ui/browser_finder.h" |
10 #include "chrome/browser/ui/browser_window.h" | 13 #include "chrome/browser/ui/browser_window.h" |
11 #include "chrome/browser/ui/location_bar/location_bar.h" | 14 #include "chrome/browser/ui/location_bar/location_bar.h" |
12 #include "components/autofill/core/common/autofill_constants.h" | 15 #include "components/autofill/core/common/autofill_constants.h" |
13 #include "content/public/browser/navigation_details.h" | 16 #include "content/public/browser/navigation_details.h" |
14 | 17 |
15 DEFINE_WEB_CONTENTS_USER_DATA_KEY(autofill::SaveCardBubbleControllerImpl); | 18 DEFINE_WEB_CONTENTS_USER_DATA_KEY(autofill::SaveCardBubbleControllerImpl); |
16 | 19 |
(...skipping 18 matching lines...) Expand all Loading... | |
35 SaveCardBubbleControllerImpl::~SaveCardBubbleControllerImpl() { | 38 SaveCardBubbleControllerImpl::~SaveCardBubbleControllerImpl() { |
36 if (save_card_bubble_view_) | 39 if (save_card_bubble_view_) |
37 save_card_bubble_view_->ControllerGone(); | 40 save_card_bubble_view_->ControllerGone(); |
38 } | 41 } |
39 | 42 |
40 void SaveCardBubbleControllerImpl::SetCallback( | 43 void SaveCardBubbleControllerImpl::SetCallback( |
41 const base::Closure& save_card_callback) { | 44 const base::Closure& save_card_callback) { |
42 save_card_callback_ = save_card_callback; | 45 save_card_callback_ = save_card_callback; |
43 } | 46 } |
44 | 47 |
48 bool SaveCardBubbleControllerImpl::SetLegalMessage( | |
bondd
2015/11/07 02:29:38
I'll add some unit tests for SetLegalMessage() unl
Evan Stade
2015/11/07 03:03:19
this function needs unit tests
| |
49 const base::ListValue& lines) { | |
50 ClearLegalMessage(); | |
51 base::string16 message; | |
52 size_t next_range_index = 0; | |
Evan Stade
2015/11/07 03:03:19
|next_range_index| is not intuitive at all and req
bondd
2015/11/11 01:53:36
Done.
| |
53 | |
54 // Process all lines of the message. See comment in header file for example | |
55 // of valid |lines| data. | |
56 for (size_t line_index = 0; line_index < lines.GetSize(); ++line_index) { | |
57 const base::DictionaryValue* single_line; | |
58 if (!lines.GetDictionary(line_index, &single_line)) | |
59 return false; | |
60 | |
61 // |display_texts| elements are the strings that will be substituted for | |
62 // "{0}", "{1}", etc. in the template string. | |
63 std::vector<base::string16> display_texts; | |
64 | |
65 // Process all the template parameters for the current message line. | |
66 const base::ListValue* template_parameters = nullptr; | |
67 if (single_line->GetList("template_parameter", &template_parameters)) { | |
68 for (size_t parameter_index = 0; | |
69 parameter_index < template_parameters->GetSize(); | |
70 ++parameter_index) { | |
71 // Get a single element of the "template_parameter" list. | |
72 const base::DictionaryValue* single_parameter; | |
73 if (!template_parameters->GetDictionary(parameter_index, | |
74 &single_parameter)) | |
75 return false; | |
76 | |
77 // Read and store the "display_text" string. | |
78 base::string16 text; | |
Evan Stade
2015/11/07 03:03:19
display_texts.push_back(base::string16());
if (!si
bondd
2015/11/11 01:53:36
Done.
| |
79 if (!single_parameter->GetString("display_text", &text)) | |
80 return false; | |
81 display_texts.push_back(text); | |
82 | |
83 // Read and store the "url" string. | |
84 LegalMessageLink link; | |
Evan Stade
2015/11/07 03:03:19
ditto
bondd
2015/11/11 01:53:36
Done.
| |
85 if (!single_parameter->GetString("url", &link.url)) | |
86 return false; | |
87 legal_message_links_.push_back(link); | |
88 } | |
89 } | |
90 | |
91 // Read the template string. It's a small subset of the ICU message format | |
92 // syntax. | |
93 base::string16 template_icu; | |
94 if (!single_line->GetString("template", &template_icu)) | |
Evan Stade
2015/11/07 03:03:19
this function is pretty long and hard to read, can
bondd
2015/11/11 01:53:36
Done. I think the new level of splitting makes sen
| |
95 return false; | |
96 | |
97 // Escape "$" -> "$$" for ReplaceStringPlaceholders(). | |
98 // | |
99 // Edge cases: | |
100 // 1. Two or more consecutive $ characters will be incorrectly expanded | |
101 // ("$$" -> "$$$$", which ReplaceStringPlaceholders() then turns into | |
102 // "$$$"). | |
103 // | |
104 // 2. "${" will cause false to be returned. "${0}" will expand to "$${0}". | |
105 // FormatWithNumberedArgs() turns it into "$$$1", which | |
106 // ReplaceStringPlaceholders() then turns into "$$1" without doing the | |
107 // parameter replacement. This causes false to be returned because each | |
108 // parameter is not used exactly once. | |
109 // | |
110 // Both of these cases are noted in the header file, and are unlikely to | |
111 // occur in any actual legal message. | |
112 base::ReplaceChars(template_icu, base::ASCIIToUTF16("$"), | |
113 base::ASCIIToUTF16("$$"), &template_icu); | |
114 | |
115 // Replace "{0}" -> "$1", "{1}" -> "$2", ... to prepare |template_dollars| | |
116 // for ReplaceStringPlaceholders(). | |
117 base::string16 template_dollars = | |
118 base::i18n::MessageFormatter::FormatWithNumberedArgs( | |
119 template_icu, "$1", "$2", "$3", "$4", "$5", "$6", "$7"); | |
120 | |
121 // FormatWithNumberedArgs() returns an empty string on failure. | |
122 if (template_dollars.empty() && !template_icu.empty()) | |
123 return false; | |
124 | |
125 // Replace "$1", "$2", ... with the display text of each parameter. | |
126 std::vector<size_t> offsets; | |
127 base::string16 message_line = | |
128 ReplaceStringPlaceholders(template_dollars, display_texts, &offsets); | |
129 | |
130 // Each parameter must be used exactly once. If a parameter is unused or | |
131 // used more than once then it can't be determined which |offsets| entry | |
132 // corresponds to which parameter. | |
133 if (offsets.size() != display_texts.size()) | |
134 return false; | |
135 | |
136 // Fill in |range| values for all links in this line. | |
137 for (size_t offset_index = 0; offset_index < offsets.size(); | |
138 ++offset_index) { | |
139 size_t range_start = message.size() + offsets[offset_index]; | |
140 legal_message_links_[next_range_index++].range = gfx::Range( | |
141 range_start, range_start + display_texts[offset_index].size()); | |
142 } | |
143 | |
144 // |message_line| is now the final line that will be displayed. Append it to | |
145 // |message|, along with a newline if there will be another line after this | |
146 // one. | |
147 message.append(message_line); | |
148 if (line_index + 1 < lines.GetSize()) | |
149 message.push_back('\n'); | |
150 } | |
151 | |
152 legal_message_ = message; | |
Evan Stade
2015/11/07 03:03:19
so legal_message_ will be empty on failure but leg
bondd
2015/11/11 01:53:36
Done. Everything is now empty on failure.
| |
153 return true; | |
154 } | |
155 | |
156 void SaveCardBubbleControllerImpl::ClearLegalMessage() { | |
157 legal_message_.clear(); | |
158 legal_message_links_.clear(); | |
159 } | |
160 | |
45 void SaveCardBubbleControllerImpl::ShowBubble() { | 161 void SaveCardBubbleControllerImpl::ShowBubble() { |
46 DCHECK(!save_card_callback_.is_null()); | 162 DCHECK(!save_card_callback_.is_null()); |
47 | 163 |
48 // Need to create location bar icon before bubble, otherwise bubble will be | 164 // Need to create location bar icon before bubble, otherwise bubble will be |
49 // unanchored. | 165 // unanchored. |
50 UpdateIcon(); | 166 UpdateIcon(); |
51 | 167 |
52 Browser* browser = chrome::FindBrowserWithWebContents(web_contents()); | 168 Browser* browser = chrome::FindBrowserWithWebContents(web_contents()); |
53 save_card_bubble_view_ = | 169 save_card_bubble_view_ = |
54 browser->window()->ShowSaveCreditCardBubble(web_contents(), this); | 170 browser->window()->ShowSaveCreditCardBubble(web_contents(), this); |
(...skipping 22 matching lines...) Expand all Loading... | |
77 void SaveCardBubbleControllerImpl::OnSaveButton() { | 193 void SaveCardBubbleControllerImpl::OnSaveButton() { |
78 save_card_callback_.Run(); | 194 save_card_callback_.Run(); |
79 save_card_callback_.Reset(); | 195 save_card_callback_.Reset(); |
80 } | 196 } |
81 | 197 |
82 void SaveCardBubbleControllerImpl::OnCancelButton() { | 198 void SaveCardBubbleControllerImpl::OnCancelButton() { |
83 save_card_callback_.Reset(); | 199 save_card_callback_.Reset(); |
84 } | 200 } |
85 | 201 |
86 void SaveCardBubbleControllerImpl::OnLearnMoreClicked() { | 202 void SaveCardBubbleControllerImpl::OnLearnMoreClicked() { |
87 web_contents()->OpenURL(content::OpenURLParams( | 203 OpenUrl(kHelpURL); |
88 GURL(kHelpURL), content::Referrer(), NEW_FOREGROUND_TAB, | 204 } |
89 ui::PAGE_TRANSITION_LINK, false)); | 205 |
206 void SaveCardBubbleControllerImpl::OnLegalMessageLinkClicked( | |
207 const gfx::Range& link_range) { | |
208 for (size_t i = 0; i < legal_message_links_.size(); ++i) { | |
209 if (legal_message_links_[i].range == link_range) { | |
210 OpenUrl(legal_message_links_[i].url); | |
211 return; | |
212 } | |
213 } | |
214 // link_range was not found. | |
215 NOTREACHED(); | |
90 } | 216 } |
91 | 217 |
92 void SaveCardBubbleControllerImpl::OnBubbleClosed() { | 218 void SaveCardBubbleControllerImpl::OnBubbleClosed() { |
93 save_card_bubble_view_ = nullptr; | 219 save_card_bubble_view_ = nullptr; |
94 UpdateIcon(); | 220 UpdateIcon(); |
95 } | 221 } |
96 | 222 |
223 const base::string16& SaveCardBubbleControllerImpl::GetLegalMessage() const { | |
224 return legal_message_; | |
225 } | |
226 | |
227 size_t SaveCardBubbleControllerImpl::GetLegalMessageNumLinks() const { | |
228 return legal_message_links_.size(); | |
229 } | |
230 | |
231 const gfx::Range& SaveCardBubbleControllerImpl::GetLegalMessageLinkRange( | |
232 size_t index) const { | |
233 return legal_message_links_[index].range; | |
234 } | |
235 | |
97 void SaveCardBubbleControllerImpl::UpdateIcon() { | 236 void SaveCardBubbleControllerImpl::UpdateIcon() { |
98 Browser* browser = chrome::FindBrowserWithWebContents(web_contents()); | 237 Browser* browser = chrome::FindBrowserWithWebContents(web_contents()); |
99 LocationBar* location_bar = browser->window()->GetLocationBar(); | 238 LocationBar* location_bar = browser->window()->GetLocationBar(); |
100 location_bar->UpdateSaveCreditCardIcon(); | 239 location_bar->UpdateSaveCreditCardIcon(); |
101 } | 240 } |
102 | 241 |
242 void SaveCardBubbleControllerImpl::OpenUrl(const std::string& url) { | |
243 web_contents()->OpenURL( | |
244 content::OpenURLParams(GURL(url), content::Referrer(), NEW_FOREGROUND_TAB, | |
245 ui::PAGE_TRANSITION_LINK, false)); | |
246 } | |
247 | |
103 void SaveCardBubbleControllerImpl::DidNavigateMainFrame( | 248 void SaveCardBubbleControllerImpl::DidNavigateMainFrame( |
104 const content::LoadCommittedDetails& details, | 249 const content::LoadCommittedDetails& details, |
105 const content::FrameNavigateParams& params) { | 250 const content::FrameNavigateParams& params) { |
106 // Nothing to do if there's no bubble available. | 251 // Nothing to do if there's no bubble available. |
107 if (save_card_callback_.is_null()) | 252 if (save_card_callback_.is_null()) |
108 return; | 253 return; |
109 | 254 |
110 // Don't react to in-page (fragment) navigations. | 255 // Don't react to in-page (fragment) navigations. |
111 if (details.is_in_page) | 256 if (details.is_in_page) |
112 return; | 257 return; |
113 | 258 |
114 // Don't do anything if a navigation occurs before a user could reasonably | 259 // Don't do anything if a navigation occurs before a user could reasonably |
115 // interact with the bubble. | 260 // interact with the bubble. |
116 if (timer_->Elapsed() < | 261 if (timer_->Elapsed() < |
117 base::TimeDelta::FromSeconds(kSurviveNavigationSeconds)) | 262 base::TimeDelta::FromSeconds(kSurviveNavigationSeconds)) |
118 return; | 263 return; |
119 | 264 |
120 // Otherwise, get rid of the bubble and icon. | 265 // Otherwise, get rid of the bubble and icon. |
121 save_card_callback_.Reset(); | 266 save_card_callback_.Reset(); |
122 if (save_card_bubble_view_) | 267 if (save_card_bubble_view_) |
123 save_card_bubble_view_->Close(); | 268 save_card_bubble_view_->Close(); |
124 else | 269 else |
125 UpdateIcon(); | 270 UpdateIcon(); |
126 } | 271 } |
127 | 272 |
128 } // namespace autofill | 273 } // namespace autofill |
OLD | NEW |