Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(758)

Side by Side Diff: chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc

Issue 1407093007: Autofill: Add legal message footer to save credit card bubble. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 #include "grit/components_strings.h" 17 #include "grit/components_strings.h"
15 #include "ui/base/l10n/l10n_util.h" 18 #include "ui/base/l10n/l10n_util.h"
16 19
17 DEFINE_WEB_CONTENTS_USER_DATA_KEY(autofill::SaveCardBubbleControllerImpl); 20 DEFINE_WEB_CONTENTS_USER_DATA_KEY(autofill::SaveCardBubbleControllerImpl);
18 21
22 namespace autofill {
23
19 namespace { 24 namespace {
20 25
21 // Number of seconds the bubble and icon will survive navigations, starting 26 // Number of seconds the bubble and icon will survive navigations, starting
22 // from when the bubble is shown. 27 // from when the bubble is shown.
23 // TODO(bondd): Share with ManagePasswordsUIController. 28 // TODO(bondd): Share with ManagePasswordsUIController.
24 const int kSurviveNavigationSeconds = 5; 29 const int kSurviveNavigationSeconds = 5;
25 30
31 // Replace "{0}", "{1}", ... in |template_icu| with corresponding strings
32 // from |display_texts|. Sets |out_message| to the resulting string, with
33 // start position of each replacement in |out_offsets|.
34 // Return false on failure. If false is returned then contents of |out_message|
35 // and |out_offsets| are undefined.
36 bool ReplaceTemplatePlaceholders(
37 const base::string16& template_icu,
38 const std::vector<base::string16>& display_texts,
39 base::string16* out_message,
40 std::vector<size_t>* out_offsets) {
41 // Escape "$" -> "$$" for ReplaceStringPlaceholders().
42 //
43 // Edge cases:
44 // 1. Two or more consecutive $ characters will be incorrectly expanded
45 // ("$$" -> "$$$$", which ReplaceStringPlaceholders() then turns into
46 // "$$$").
47 //
48 // 2. "${" will cause false to be returned. "${0}" will expand to "$${0}".
49 // FormatWithNumberedArgs() turns it into "$$$1", which
50 // ReplaceStringPlaceholders() then turns into "$$1" without doing the
51 // parameter replacement. This causes false to be returned because each
52 // parameter is not used exactly once.
53 //
54 // Both of these cases are noted in the header file, and are unlikely to
55 // occur in any actual legal message.
56 base::string16 template_icu_escaped;
57 base::ReplaceChars(template_icu, base::ASCIIToUTF16("$"),
58 base::ASCIIToUTF16("$$"), &template_icu_escaped);
59
60 // Replace "{0}" -> "$1", "{1}" -> "$2", ... to prepare |template_dollars|
61 // for ReplaceStringPlaceholders().
62 base::string16 template_dollars =
63 base::i18n::MessageFormatter::FormatWithNumberedArgs(
64 template_icu_escaped, "$1", "$2", "$3", "$4", "$5", "$6", "$7");
65
66 // FormatWithNumberedArgs() returns an empty string on failure.
67 if (template_dollars.empty() && !template_icu.empty())
68 return false;
69
70 // Replace "$1", "$2", ... with the display text of each parameter.
71 *out_message = base::ReplaceStringPlaceholders(template_dollars,
72 display_texts, out_offsets);
73
74 // Each parameter must be used exactly once. If a parameter is unused or
75 // used more than once then it can't be determined which |offsets| entry
76 // corresponds to which parameter.
77 return out_offsets->size() == display_texts.size();
78 }
79
80 // Parses |line| and sets |out|.
81 // Returns false on failure. |out| is not modified if false is returned.
82 bool ParseLegalMessageLine(const base::DictionaryValue& line,
83 SaveCardBubbleController::LegalMessageLine* out) {
84 SaveCardBubbleController::LegalMessageLine result;
85
86 // |display_texts| elements are the strings that will be substituted for
87 // "{0}", "{1}", etc. in the template string.
88 std::vector<base::string16> display_texts;
89
90 // Process all the template parameters.
91 const base::ListValue* template_parameters = nullptr;
92 if (line.GetList("template_parameter", &template_parameters)) {
93 display_texts.resize(template_parameters->GetSize());
94 result.links.resize(template_parameters->GetSize());
95
96 for (size_t parameter_index = 0;
97 parameter_index < template_parameters->GetSize(); ++parameter_index) {
98 const base::DictionaryValue* single_parameter;
99 std::string url;
100 if (!template_parameters->GetDictionary(parameter_index,
101 &single_parameter) ||
102 !single_parameter->GetString("display_text",
103 &display_texts[parameter_index]) ||
104 !single_parameter->GetString("url", &url)) {
105 return false;
106 }
107 result.links[parameter_index].url = GURL(url);
108 }
109 }
110
111 // Read the template string. It's a small subset of the ICU message format
112 // syntax.
113 base::string16 template_icu;
114 if (!line.GetString("template", &template_icu))
115 return false;
116
117 // Replace the placeholders in |template_icu| with strings from
118 // |display_texts|, and store the start position of each replacement in
119 // |offsets|.
120 std::vector<size_t> offsets;
121 if (!ReplaceTemplatePlaceholders(template_icu, display_texts, &result.text,
122 &offsets)) {
123 return false;
124 }
125
126 // Fill in range values for all links.
127 for (size_t offset_index = 0; offset_index < offsets.size(); ++offset_index) {
128 size_t range_start = offsets[offset_index];
129 result.links[offset_index].range = gfx::Range(
130 range_start, range_start + display_texts[offset_index].size());
131 }
132
133 *out = result;
134 return true;
135 }
136
26 } // namespace 137 } // namespace
27 138
28 namespace autofill {
29
30 SaveCardBubbleControllerImpl::SaveCardBubbleControllerImpl( 139 SaveCardBubbleControllerImpl::SaveCardBubbleControllerImpl(
31 content::WebContents* web_contents) 140 content::WebContents* web_contents)
32 : content::WebContentsObserver(web_contents), 141 : content::WebContentsObserver(web_contents),
33 save_card_bubble_view_(nullptr), 142 save_card_bubble_view_(nullptr),
34 is_uploading_(false) { 143 is_uploading_(false) {
35 DCHECK(web_contents); 144 DCHECK(web_contents);
36 } 145 }
37 146
38 SaveCardBubbleControllerImpl::~SaveCardBubbleControllerImpl() { 147 SaveCardBubbleControllerImpl::~SaveCardBubbleControllerImpl() {
39 if (save_card_bubble_view_) 148 if (save_card_bubble_view_)
40 save_card_bubble_view_->Hide(); 149 save_card_bubble_view_->Hide();
41 } 150 }
42 151
43 void SaveCardBubbleControllerImpl::InitializeForLocalSave( 152 void SaveCardBubbleControllerImpl::InitializeForLocalSave(
44 const base::Closure& save_card_callback) { 153 const base::Closure& save_card_callback) {
45 is_uploading_ = false; 154 is_uploading_ = false;
46 save_card_callback_ = save_card_callback; 155 save_card_callback_ = save_card_callback;
47 } 156 }
48 157
49 void SaveCardBubbleControllerImpl::InitializeForUpload( 158 void SaveCardBubbleControllerImpl::InitializeForUpload(
50 const base::Closure& save_card_callback, 159 const base::Closure& save_card_callback,
51 scoped_ptr<base::DictionaryValue> legal_message) { 160 scoped_ptr<base::DictionaryValue> legal_message) {
52 is_uploading_ = true; 161 is_uploading_ = true;
53 save_card_callback_ = save_card_callback; 162 save_card_callback_ = save_card_callback;
54 // TODO(bondd): Store legal_message here. 163 // TODO(bondd): Store legal_message here.
55 } 164 }
56 165
166 bool SaveCardBubbleControllerImpl::SetLegalMessage(
167 const base::ListValue& lines) {
168 // Process all lines of the message. See comment in header file for example
169 // of valid |lines| data.
170 legal_message_lines_.resize(lines.GetSize());
171 for (size_t i = 0; i < lines.GetSize(); ++i) {
172 const base::DictionaryValue* single_line;
173 if (!lines.GetDictionary(i, &single_line) ||
174 !ParseLegalMessageLine(*single_line, &legal_message_lines_[i])) {
175 legal_message_lines_.clear();
176 return false;
177 }
178 }
179
180 return true;
181 }
182
57 void SaveCardBubbleControllerImpl::ShowBubble(bool user_action) { 183 void SaveCardBubbleControllerImpl::ShowBubble(bool user_action) {
58 DCHECK(!save_card_callback_.is_null()); 184 DCHECK(!save_card_callback_.is_null());
59 185
60 // Need to create location bar icon before bubble, otherwise bubble will be 186 // Need to create location bar icon before bubble, otherwise bubble will be
61 // unanchored. 187 // unanchored.
62 UpdateIcon(); 188 UpdateIcon();
63 189
64 Browser* browser = chrome::FindBrowserWithWebContents(web_contents()); 190 Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
65 save_card_bubble_view_ = browser->window()->ShowSaveCreditCardBubble( 191 save_card_bubble_view_ = browser->window()->ShowSaveCreditCardBubble(
66 web_contents(), this, user_action); 192 web_contents(), this, user_action);
(...skipping 30 matching lines...) Expand all
97 void SaveCardBubbleControllerImpl::OnSaveButton() { 223 void SaveCardBubbleControllerImpl::OnSaveButton() {
98 save_card_callback_.Run(); 224 save_card_callback_.Run();
99 save_card_callback_.Reset(); 225 save_card_callback_.Reset();
100 } 226 }
101 227
102 void SaveCardBubbleControllerImpl::OnCancelButton() { 228 void SaveCardBubbleControllerImpl::OnCancelButton() {
103 save_card_callback_.Reset(); 229 save_card_callback_.Reset();
104 } 230 }
105 231
106 void SaveCardBubbleControllerImpl::OnLearnMoreClicked() { 232 void SaveCardBubbleControllerImpl::OnLearnMoreClicked() {
107 web_contents()->OpenURL(content::OpenURLParams( 233 OpenUrl(GURL(kHelpURL));
108 GURL(kHelpURL), content::Referrer(), NEW_FOREGROUND_TAB, 234 }
109 ui::PAGE_TRANSITION_LINK, false)); 235
236 void SaveCardBubbleControllerImpl::OnLegalMessageLinkClicked(const GURL& url) {
237 OpenUrl(url);
110 } 238 }
111 239
112 void SaveCardBubbleControllerImpl::OnBubbleClosed() { 240 void SaveCardBubbleControllerImpl::OnBubbleClosed() {
113 save_card_bubble_view_ = nullptr; 241 save_card_bubble_view_ = nullptr;
114 UpdateIcon(); 242 UpdateIcon();
115 } 243 }
116 244
245 const SaveCardBubbleController::LegalMessageLines&
246 SaveCardBubbleControllerImpl::GetLegalMessageLines() const {
247 return legal_message_lines_;
248 }
249
117 void SaveCardBubbleControllerImpl::UpdateIcon() { 250 void SaveCardBubbleControllerImpl::UpdateIcon() {
118 Browser* browser = chrome::FindBrowserWithWebContents(web_contents()); 251 Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
119 LocationBar* location_bar = browser->window()->GetLocationBar(); 252 LocationBar* location_bar = browser->window()->GetLocationBar();
120 location_bar->UpdateSaveCreditCardIcon(); 253 location_bar->UpdateSaveCreditCardIcon();
121 } 254 }
122 255
256 void SaveCardBubbleControllerImpl::OpenUrl(const GURL& url) {
257 web_contents()->OpenURL(
258 content::OpenURLParams(url, content::Referrer(), NEW_FOREGROUND_TAB,
259 ui::PAGE_TRANSITION_LINK, false));
260 }
261
123 void SaveCardBubbleControllerImpl::DidNavigateMainFrame( 262 void SaveCardBubbleControllerImpl::DidNavigateMainFrame(
124 const content::LoadCommittedDetails& details, 263 const content::LoadCommittedDetails& details,
125 const content::FrameNavigateParams& params) { 264 const content::FrameNavigateParams& params) {
126 // Nothing to do if there's no bubble available. 265 // Nothing to do if there's no bubble available.
127 if (save_card_callback_.is_null()) 266 if (save_card_callback_.is_null())
128 return; 267 return;
129 268
130 // Don't react to in-page (fragment) navigations. 269 // Don't react to in-page (fragment) navigations.
131 if (details.is_in_page) 270 if (details.is_in_page)
132 return; 271 return;
133 272
134 // Don't do anything if a navigation occurs before a user could reasonably 273 // Don't do anything if a navigation occurs before a user could reasonably
135 // interact with the bubble. 274 // interact with the bubble.
136 if (timer_->Elapsed() < 275 if (timer_->Elapsed() <
137 base::TimeDelta::FromSeconds(kSurviveNavigationSeconds)) 276 base::TimeDelta::FromSeconds(kSurviveNavigationSeconds))
138 return; 277 return;
139 278
140 // Otherwise, get rid of the bubble and icon. 279 // Otherwise, get rid of the bubble and icon.
141 save_card_callback_.Reset(); 280 save_card_callback_.Reset();
142 if (save_card_bubble_view_) { 281 if (save_card_bubble_view_) {
143 save_card_bubble_view_->Hide(); 282 save_card_bubble_view_->Hide();
144 OnBubbleClosed(); 283 OnBubbleClosed();
145 } else { 284 } else {
146 UpdateIcon(); 285 UpdateIcon();
147 } 286 }
148 } 287 }
149 288
150 } // namespace autofill 289 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698