Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / autofill / generated_credit_card_bubble_controller.cc
1 // Copyright 2013 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 #include "chrome/browser/ui/autofill/generated_credit_card_bubble_controller.h"
6
7 #include <climits>
8
9 #include "base/logging.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/strings/string_split.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/ui/autofill/chrome_autofill_client.h"
15 #include "chrome/browser/ui/autofill/generated_credit_card_bubble_view.h"
16 #include "chrome/browser/ui/browser_finder.h"
17 #include "chrome/browser/ui/browser_navigator.h"
18 #include "chrome/browser/ui/browser_window.h"
19 #include "chrome/browser/ui/location_bar/location_bar.h"
20 #include "chrome/browser/ui/tabs/tab_strip_model.h"
21 #include "chrome/common/pref_names.h"
22 #include "chrome/grit/generated_resources.h"
23 #include "components/pref_registry/pref_registry_syncable.h"
24 #include "content/public/browser/navigation_details.h"
25 #include "content/public/browser/navigation_entry.h"
26 #include "content/public/browser/web_contents.h"
27 #include "grit/components_strings.h"
28 #include "grit/theme_resources.h"
29 #include "ui/base/l10n/l10n_util.h"
30 #include "ui/base/resource/resource_bundle.h"
31
32 DEFINE_WEB_CONTENTS_USER_DATA_KEY(
33     autofill::GeneratedCreditCardBubbleController);
34
35 namespace autofill {
36
37 namespace {
38
39 static const int kMaxGeneratedCardTimesToShow = INT_MAX;
40 static const base::char16 kRangeSeparator = '|';
41 static const char kWalletGeneratedCardLearnMoreLink[] =
42     "http://support.google.com/wallet/bin/answer.py?hl=en&answer=2740044";
43
44 GeneratedCreditCardBubbleController* GetOrCreate(content::WebContents* wc) {
45   GeneratedCreditCardBubbleController::CreateForWebContents(wc);
46   return GeneratedCreditCardBubbleController::FromWebContents(wc);
47 }
48
49 }  // namespace
50
51 bool TextRange::operator==(const TextRange& other) const {
52   return other.range == range && other.is_link == is_link;
53 }
54
55 GeneratedCreditCardBubbleController::GeneratedCreditCardBubbleController(
56     content::WebContents* web_contents)
57     : WebContentsObserver(web_contents),
58       web_contents_(web_contents),
59       title_text_(l10n_util::GetStringUTF16(
60           IDS_AUTOFILL_GENERATED_CREDIT_CARD_BUBBLE_TITLE)),
61       should_show_anchor_(true),
62       weak_ptr_factory_(this) {}
63
64 GeneratedCreditCardBubbleController::~GeneratedCreditCardBubbleController() {
65   // In the case that the tab is closed, the controller can be deleted while
66   // bubble is showing. Always calling |Hide()| ensures that the bubble closes.
67   Hide();
68 }
69
70 // static
71 void GeneratedCreditCardBubbleController::RegisterUserPrefs(
72     user_prefs::PrefRegistrySyncable* registry) {
73   registry->RegisterIntegerPref(
74       ::prefs::kAutofillGeneratedCardBubbleTimesShown,
75       0,
76       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
77 }
78
79 // static
80 void GeneratedCreditCardBubbleController::Show(
81     content::WebContents* contents,
82     const base::string16& fronting_card_name,
83     const base::string16& backing_card_name) {
84   GetOrCreate(contents)->SetupAndShow(fronting_card_name, backing_card_name);
85 }
86
87 void GeneratedCreditCardBubbleController::DidNavigateMainFrame(
88     const content::LoadCommittedDetails& details,
89     const content::FrameNavigateParams& params) {
90   if (!details.entry)
91     return;
92
93   // Don't destory the bubble due to reloads, form submits, or redirects right
94   // after the dialog succeeds. Merchants often navigate to a confirmation page.
95   ui::PageTransition transition = details.entry->GetTransitionType();
96   if (transition == ui::PAGE_TRANSITION_FORM_SUBMIT ||
97       transition == ui::PAGE_TRANSITION_RELOAD ||
98       ui::PageTransitionIsRedirect(transition)) {
99     return;
100   }
101
102   should_show_anchor_ = false;
103   UpdateAnchor();
104   web_contents()->RemoveUserData(UserDataKey());
105   // |this| is now deleted.
106 }
107
108 bool GeneratedCreditCardBubbleController::IsHiding() const {
109   return bubble_ && bubble_->IsHiding();
110 }
111
112 gfx::Image GeneratedCreditCardBubbleController::AnchorIcon() const {
113   if (!should_show_anchor_)
114     return gfx::Image();
115   return ui::ResourceBundle::GetSharedInstance().GetImageNamed(IDR_WALLET_ICON);
116 }
117
118 const base::string16& GeneratedCreditCardBubbleController::TitleText() const {
119   return title_text_;
120 }
121
122 const base::string16& GeneratedCreditCardBubbleController::ContentsText()
123     const {
124   return contents_text_;
125 }
126
127 const std::vector<TextRange>& GeneratedCreditCardBubbleController::
128     ContentsTextRanges() const {
129   return contents_text_ranges_;
130 }
131
132 void GeneratedCreditCardBubbleController::OnAnchorClicked() {
133   Show(true);
134 }
135
136 void GeneratedCreditCardBubbleController::OnLinkClicked() {
137   // Open a new tab to the Online Wallet help link.
138   chrome::NavigateParams params(
139       chrome::FindBrowserWithWebContents(web_contents()),
140       GURL(kWalletGeneratedCardLearnMoreLink),
141       ui::PAGE_TRANSITION_AUTO_BOOKMARK);
142   params.disposition = NEW_FOREGROUND_TAB;
143   chrome::Navigate(&params);
144
145   Hide();
146 }
147
148 base::WeakPtr<GeneratedCreditCardBubbleController>
149     GeneratedCreditCardBubbleController::GetWeakPtr() {
150   return weak_ptr_factory_.GetWeakPtr();
151 }
152
153 base::WeakPtr<GeneratedCreditCardBubbleView>
154     GeneratedCreditCardBubbleController::CreateBubble() {
155   return GeneratedCreditCardBubbleView::Create(GetWeakPtr());
156 }
157
158 base::WeakPtr<GeneratedCreditCardBubbleView>
159     GeneratedCreditCardBubbleController::bubble() {
160   return bubble_;
161 }
162
163 bool GeneratedCreditCardBubbleController::CanShow() const {
164   Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
165   return web_contents() == browser->tab_strip_model()->GetActiveWebContents();
166 }
167
168 bool GeneratedCreditCardBubbleController::ShouldDisplayBubbleInitially() const {
169   Profile* profile = Profile::FromBrowserContext(
170       web_contents_->GetBrowserContext());
171   int times_shown = profile->GetPrefs()->GetInteger(
172       ::prefs::kAutofillGeneratedCardBubbleTimesShown);
173   return times_shown < kMaxGeneratedCardTimesToShow;
174 }
175
176 void GeneratedCreditCardBubbleController::SetupAndShow(
177     const base::string16& fronting_card_name,
178     const base::string16& backing_card_name) {
179   DCHECK(!fronting_card_name.empty());
180   DCHECK(!backing_card_name.empty());
181
182   fronting_card_name_ = fronting_card_name;
183   backing_card_name_ = backing_card_name;
184
185   // Clear any generated state or from the last |SetupAndShow()| call.
186   contents_text_.clear();
187   contents_text_ranges_.clear();
188
189   base::string16 to_split = l10n_util::GetStringFUTF16(
190       IDS_AUTOFILL_GENERATED_CREDIT_CARD_BUBBLE_CONTENTS,
191       fronting_card_name_,
192       backing_card_name_);
193
194   // Split the full text on '|' to highlight certain parts. For example, "sly"
195   // and "jumped" would be bolded in "The |sly| fox |jumped| over the lazy dog".
196   std::vector<base::string16> pieces;
197   base::SplitStringDontTrim(to_split, kRangeSeparator, &pieces);
198
199   while (!pieces.empty()) {
200     base::string16 piece = pieces.front();
201
202     // Every second piece should be bolded. Because |base::SplitString*()|
203     // leaves an empty "" even if '|' is the first character, this is guaranteed
204     // to work for "|highlighting| starts here". Ignore empty pieces because
205     // there's nothing to highlight.
206     if (!piece.empty() && pieces.size() % 2 == 0) {
207       const size_t start = contents_text_.size();
208       TextRange bold_text;
209       bold_text.range = gfx::Range(start, start + piece.size());
210       bold_text.is_link = false;
211       contents_text_ranges_.push_back(bold_text);
212     }
213
214     // Append the piece whether it's bolded or not and move on to the next one.
215     contents_text_.append(piece);
216     pieces.erase(pieces.begin(), pieces.begin() + 1);
217   }
218
219   // Add a "Learn more" link at the end of the header text if it's a generated
220   // card bubble.
221   base::string16 learn_more = l10n_util::GetStringUTF16(IDS_LEARN_MORE);
222   contents_text_.append(base::ASCIIToUTF16(" ") + learn_more);
223   const size_t header_size = contents_text_.size();
224   TextRange end_link;
225   end_link.range = gfx::Range(header_size - learn_more.size(), header_size);
226   end_link.is_link = true;
227   contents_text_ranges_.push_back(end_link);
228
229   UpdateAnchor();
230
231   if (ShouldDisplayBubbleInitially())
232     Show(false);
233 }
234
235 void GeneratedCreditCardBubbleController::Show(bool was_anchor_click) {
236   Hide();
237
238   if (!CanShow())
239     return;
240
241   bubble_ = CreateBubble();
242   if (!bubble_) {
243     // TODO(dbeam): Make a bubble on all applicable platforms.
244     return;
245   }
246
247   bubble_->Show();
248
249   if (!was_anchor_click) {
250     // If the bubble was an automatically created "you generated a card" bubble,
251     // count it as a show. If the user clicked the omnibox icon, don't count it.
252     PrefService* prefs = Profile::FromBrowserContext(
253         web_contents()->GetBrowserContext())->GetPrefs();
254     prefs->SetInteger(::prefs::kAutofillGeneratedCardBubbleTimesShown,
255         prefs->GetInteger(::prefs::kAutofillGeneratedCardBubbleTimesShown) + 1);
256   }
257 }
258
259 void GeneratedCreditCardBubbleController::UpdateAnchor() {
260   Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
261   if (browser && browser->window() && browser->window()->GetLocationBar())
262     browser->window()->GetLocationBar()->UpdateGeneratedCreditCardView();
263 }
264
265 void GeneratedCreditCardBubbleController::Hide() {
266   if (bubble_ && !bubble_->IsHiding())
267     bubble_->Hide();
268 }
269
270 }  // namespace autofill