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