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

Side by Side Diff: ios/chrome/browser/ui/ntp/notification_promo_whats_new.mm

Issue 2589803002: Upstream Chrome on iOS source code [6/11]. (Closed)
Patch Set: Created 4 years 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
(Empty)
1 // Copyright (c) 2014 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 #import "ios/chrome/browser/ui/ntp/notification_promo_whats_new.h"
6
7 #include <stdint.h>
8 #include <algorithm>
9 #include <memory>
10 #include <vector>
11
12 #include "base/json/json_reader.h"
13 #include "base/metrics/field_trial.h"
14 #include "base/metrics/user_metrics.h"
15 #include "base/metrics/user_metrics_action.h"
16 #include "base/strings/string_util.h"
17 #include "base/time/time.h"
18 #include "base/values.h"
19 #include "components/metrics/metrics_pref_names.h"
20 #include "components/prefs/pref_service.h"
21 #include "ios/chrome/browser/experimental_flags.h"
22 #include "ios/chrome/browser/notification_promo.h"
23 #include "ios/chrome/browser/pref_names.h"
24 #include "ios/chrome/browser/ui/commands/ios_command_ids.h"
25 #include "ios/chrome/grit/ios_chromium_strings.h"
26 #include "ios/chrome/grit/ios_strings.h"
27 #include "ui/base/l10n/l10n_util.h"
28
29 namespace {
30
31 struct PromoStringToIdsMapEntry {
32 const char* promo_text_str;
33 int message_id;
34 };
35
36 // A mapping from a string to a l10n message id.
37 const PromoStringToIdsMapEntry kPromoStringToIdsMap[] = {
38 {"IDS_IOS_APP_RATING_PROMO_STRING", IDS_IOS_APP_RATING_PROMO_STRING},
39 {"IDS_IOS_MOVE_TO_DOCK_FASTER_ACCESS", IDS_IOS_MOVE_TO_DOCK_FASTER_ACCESS},
40 {"IDS_IOS_MOVE_TO_DOCK_LOVE_CHROME", IDS_IOS_MOVE_TO_DOCK_LOVE_CHROME},
41 {"IDS_IOS_MOVE_TO_DOCK_TIP", IDS_IOS_MOVE_TO_DOCK_TIP},
42 };
43
44 // Returns a localized version of |promo_text| if it has an entry in the
45 // |kPromoStringToIdsMap|. If there is no entry, |promo_text| is returned.
46 std::string GetLocalizedPromoText(const std::string& promo_text) {
47 for (size_t i = 0; i < arraysize(kPromoStringToIdsMap); ++i) {
48 if (kPromoStringToIdsMap[i].promo_text_str == promo_text)
49 return l10n_util::GetStringUTF8(kPromoStringToIdsMap[i].message_id);
50 }
51 return promo_text;
52 }
53
54 } // namespace
55
56 NotificationPromoWhatsNew::NotificationPromoWhatsNew(PrefService* local_state)
57 : local_state_(local_state),
58 valid_(false),
59 notification_promo_(local_state_) {}
60
61 NotificationPromoWhatsNew::~NotificationPromoWhatsNew() {}
62
63 bool NotificationPromoWhatsNew::Init() {
64 notification_promo_.InitFromVariations();
65
66 // Force enable a particular promo if experimental flag is set.
67 experimental_flags::WhatsNewPromoStatus forceEnabled =
68 experimental_flags::GetWhatsNewPromoStatus();
69 if (forceEnabled != experimental_flags::WHATS_NEW_DEFAULT) {
70 switch (forceEnabled) {
71 case experimental_flags::WHATS_NEW_APP_RATING:
72 InjectFakePromo("1", "IDS_IOS_APP_RATING_PROMO_STRING",
73 "chrome_command", "ratethisapp", "", "RateThisAppPromo",
74 "logo");
75 break;
76 case experimental_flags::WHATS_NEW_MOVE_TO_DOCK_FASTER:
77 InjectFakePromo("2", "IDS_IOS_MOVE_TO_DOCK_FASTER_ACCESS", "url", "",
78 "https://support.google.com/chrome/?p=iphone_dock",
79 "MoveToDockFasterAccessPromo",
80 "logoWithRoundedRectangle");
81 break;
82 case experimental_flags::WHATS_NEW_MOVE_TO_DOCK_LOVE:
83 InjectFakePromo("3", "IDS_IOS_MOVE_TO_DOCK_LOVE_CHROME", "url", "",
84 "https://support.google.com/chrome/?p=iphone_dock",
85 "MoveToDockLovePromo", "logoWithRoundedRectangle");
86 break;
87 case experimental_flags::WHATS_NEW_MOVE_TO_DOCK_TIP:
88 InjectFakePromo("4", "IDS_IOS_MOVE_TO_DOCK_TIP", "url", "",
89 "https://support.google.com/chrome/?p=iphone_dock",
90 "MoveToDockTipPromo", "logoWithRoundedRectangle");
91 break;
92 default:
93 NOTREACHED();
94 break;
95 }
96 }
97
98 notification_promo_.InitFromPrefs(
99 ios::NotificationPromo::MOBILE_NTP_WHATS_NEW_PROMO);
100 return InitFromNotificationPromo();
101 }
102
103 bool NotificationPromoWhatsNew::ClearAndInitFromJson(
104 const base::DictionaryValue& json) {
105 // This clears away old promos.
106 notification_promo_.MigrateUserPrefs(local_state_);
107
108 notification_promo_.InitFromJson(
109 json, ios::NotificationPromo::MOBILE_NTP_WHATS_NEW_PROMO);
110 return InitFromNotificationPromo();
111 }
112
113 bool NotificationPromoWhatsNew::CanShow() const {
114 if (!valid_ || !notification_promo_.CanShow()) {
115 return false;
116 }
117
118 // Check optional restrictions.
119
120 if (seconds_since_install_ > 0) {
121 // Do not show the promo if the app's installation did not occur more than
122 // |seconds_since_install_| seconds ago.
123 int64_t install_date = local_state_->GetInt64(metrics::prefs::kInstallDate);
124 const base::Time first_view_time =
125 base::Time::FromTimeT(install_date) +
126 base::TimeDelta::FromSeconds(seconds_since_install_);
127 if (first_view_time > base::Time::Now()) {
128 return false;
129 }
130 }
131
132 if (max_seconds_since_install_ > 0) {
133 // Do not show the promo if the app's installation occurred more than
134 // |max_seconds_since_install_| seconds ago.
135 int64_t install_date = local_state_->GetInt64(metrics::prefs::kInstallDate);
136 const base::Time last_view_time =
137 base::Time::FromTimeT(install_date) +
138 base::TimeDelta::FromSeconds(max_seconds_since_install_);
139 if (last_view_time < base::Time::Now()) {
140 return false;
141 }
142 }
143
144 if (promo_name_ == "WKWVGotFasterPromo") {
145 // Promo is not relevant anymore: It was shown during the migration to the
146 // WKWebview.
147 return false;
148 }
149
150 return true;
151 }
152
153 void NotificationPromoWhatsNew::HandleViewed() {
154 // TODO(justincohen): metrics actions names should be inlined. Since
155 // metric_name_ is retrieved from a server, it's not possible to know at build
156 // time the values. We should investigate to find a solution. In the meantime,
157 // metrics will be reported hashed.
158 // http://crbug.com/437500
159 std::string metric = std::string("WhatsNewPromoViewed_") + metric_name_;
160 base::RecordAction(base::UserMetricsAction(metric.c_str()));
161 base::RecordAction(base::UserMetricsAction("NTPPromoShown"));
162 notification_promo_.HandleViewed();
163 }
164
165 void NotificationPromoWhatsNew::HandleClosed() {
166 // TODO(justincohen): metrics actions names should be inlined. Since
167 // metric_name_ is retrieved from a server, it's not possible to know at build
168 // time the values. We should investigate to find a solution. In the meantime,
169 // metrics will be reported hashed.
170 // http://crbug.com/437500
171 std::string metric = std::string("WhatsNewPromoClosed_") + metric_name_;
172 base::RecordAction(base::UserMetricsAction(metric.c_str()));
173 base::RecordAction(base::UserMetricsAction("NTPPromoClosed"));
174 notification_promo_.HandleClosed();
175 }
176
177 bool NotificationPromoWhatsNew::IsURLPromo() const {
178 return promo_type_ == "url";
179 }
180
181 bool NotificationPromoWhatsNew::IsChromeCommand() const {
182 return promo_type_ == "chrome_command";
183 }
184
185 WhatsNewIcon NotificationPromoWhatsNew::ParseIconName(
186 const std::string& icon_name) {
187 if (icon_name == "logo") {
188 return WHATS_NEW_LOGO;
189 } else if (icon_name == "logoWithRoundedRectangle") {
190 return WHATS_NEW_LOGO_ROUNDED_RECTANGLE;
191 }
192 return WHATS_NEW_INFO;
193 }
194
195 bool NotificationPromoWhatsNew::InitFromNotificationPromo() {
196 valid_ = false;
197
198 notification_promo_.promo_payload()->GetString("promo_type", &promo_type_);
199 notification_promo_.promo_payload()->GetString("metric_name", &metric_name_);
200 promo_text_ = GetLocalizedPromoText(notification_promo_.promo_text());
201
202 if (IsURLPromo()) {
203 std::string url_text;
204 notification_promo_.promo_payload()->GetString("url", &url_text);
205 url_ = GURL(url_text);
206 if (url_.is_empty() || !url_.is_valid()) {
207 valid_ = false;
208 return valid_;
209 }
210 }
211
212 if (IsChromeCommand()) {
213 std::string command;
214 notification_promo_.promo_payload()->GetString("command", &command);
215 if (command == "bookmark") {
216 command_id_ = IDC_SHOW_BOOKMARK_MANAGER;
217 } else if (command == "ratethisapp") {
218 command_id_ = IDC_RATE_THIS_APP;
219 } else {
220 valid_ = false;
221 return valid_;
222 }
223 }
224
225 valid_ =
226 !metric_name_.empty() && !promo_type_.empty() && !promo_text_.empty();
227
228 notification_promo_.promo_payload()->GetString("promo_name", &promo_name_);
229 std::string icon_name;
230 notification_promo_.promo_payload()->GetString("icon", &icon_name);
231 icon_ = ParseIconName(icon_name);
232
233 // Optional values don't need validation.
234 seconds_since_install_ = 0;
235 notification_promo_.promo_payload()->GetInteger("seconds_since_install",
236 &seconds_since_install_);
237 max_seconds_since_install_ = 0;
238 notification_promo_.promo_payload()->GetInteger("max_seconds_since_install",
239 &max_seconds_since_install_);
240 return valid_;
241 }
242
243 void NotificationPromoWhatsNew::InjectFakePromo(const std::string& promo_id,
244 const std::string& promo_text,
245 const std::string& promo_type,
246 const std::string& command,
247 const std::string& url,
248 const std::string& metric_name,
249 const std::string& icon) {
250 // Build vector to fill in json string with given parameters.
251 std::vector<std::string> replacements;
252 replacements.push_back(promo_text);
253 replacements.push_back(promo_type);
254 replacements.push_back(metric_name);
255 replacements.push_back(command);
256 replacements.push_back(url);
257 replacements.push_back(icon);
258 replacements.push_back(promo_id);
259
260 std::string promo_json =
261 "{"
262 " \"start\":\"1 Jan 1999 0:26:06 GMT\","
263 " \"end\":\"1 Jan 2199 0:26:06 GMT\","
264 " \"promo_text\":\"$1\","
265 " \"max_views\":20,"
266 " \"payload\":"
267 " {"
268 " \"promo_type\":\"$2\","
269 " \"metric_name\":\"$3\","
270 " \"command\":\"$4\","
271 " \"url\":\"$5\","
272 " \"icon\":\"$6\""
273 " },"
274 " \"max_seconds\":259200,"
275 " \"promo_id\":$7"
276 "}";
277 std::string promo_json_filled_in =
278 base::ReplaceStringPlaceholders(promo_json, replacements, NULL);
279
280 std::unique_ptr<base::Value> value(
281 base::JSONReader::Read(promo_json_filled_in));
282 base::DictionaryValue* dict = NULL;
283 if (value->GetAsDictionary(&dict)) {
284 notification_promo_.InitFromJson(
285 *dict, ios::NotificationPromo::MOBILE_NTP_WHATS_NEW_PROMO);
286 }
287 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698