1// Copyright (c) 2011 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/extensions/apps_promo.h"
6
7#include "base/command_line.h"
8#include "base/metrics/histogram.h"
9#include "chrome/browser/browser_process.h"
10#include "chrome/browser/prefs/pref_service.h"
11#include "chrome/browser/ui/webui/shown_sections_handler.h"
12#include "chrome/common/chrome_switches.h"
13#include "chrome/common/extensions/extension.h"
14#include "chrome/common/pref_names.h"
15
16const int AppsPromo::kDefaultAppsCounterMax = 10;
17
18// static
19void AppsPromo::RegisterPrefs(PrefService* local_state) {
20  std::string empty;
21  local_state->RegisterStringPref(prefs::kNTPWebStorePromoId, empty);
22  local_state->RegisterStringPref(prefs::kNTPWebStorePromoHeader, empty);
23  local_state->RegisterStringPref(prefs::kNTPWebStorePromoButton, empty);
24  local_state->RegisterStringPref(prefs::kNTPWebStorePromoLink, empty);
25  local_state->RegisterStringPref(prefs::kNTPWebStorePromoExpire, empty);
26}
27
28// static
29void AppsPromo::RegisterUserPrefs(PrefService* prefs) {
30  // Set the default value for the counter to max+1 since we don't install
31  // default apps for new users.
32  prefs->RegisterIntegerPref(
33      prefs::kAppsPromoCounter, kDefaultAppsCounterMax + 1);
34  prefs->RegisterBooleanPref(prefs::kDefaultAppsInstalled, false);
35  prefs->RegisterStringPref(prefs::kNTPWebStorePromoLastId, std::string());
36}
37
38// static
39void AppsPromo::ClearPromo() {
40  PrefService* local_state = g_browser_process->local_state();
41  local_state->ClearPref(prefs::kNTPWebStorePromoId);
42  local_state->ClearPref(prefs::kNTPWebStorePromoHeader);
43  local_state->ClearPref(prefs::kNTPWebStorePromoButton);
44  local_state->ClearPref(prefs::kNTPWebStorePromoLink);
45  local_state->ClearPref(prefs::kNTPWebStorePromoExpire);
46}
47
48// static
49std::string AppsPromo::GetPromoButtonText() {
50  PrefService* local_state = g_browser_process->local_state();
51  return local_state->GetString(prefs::kNTPWebStorePromoButton);
52}
53
54// static
55std::string AppsPromo::GetPromoId() {
56  PrefService* local_state = g_browser_process->local_state();
57  return local_state->GetString(prefs::kNTPWebStorePromoId);
58}
59
60// static
61std::string AppsPromo::GetPromoHeaderText() {
62  PrefService* local_state = g_browser_process->local_state();
63  return local_state->GetString(prefs::kNTPWebStorePromoHeader);
64}
65
66// static
67GURL AppsPromo::GetPromoLink() {
68  PrefService* local_state = g_browser_process->local_state();
69  return GURL(local_state->GetString(prefs::kNTPWebStorePromoLink));
70}
71
72// static
73std::string AppsPromo::GetPromoExpireText() {
74  PrefService* local_state = g_browser_process->local_state();
75  return local_state->GetString(prefs::kNTPWebStorePromoExpire);
76}
77
78// static
79void AppsPromo::SetPromo(const std::string& id,
80                         const std::string& header_text,
81                         const std::string& button_text,
82                         const GURL& link,
83                         const std::string& expire_text) {
84  PrefService* local_state = g_browser_process->local_state();
85  local_state->SetString(prefs::kNTPWebStorePromoId, id);
86  local_state->SetString(prefs::kNTPWebStorePromoButton, button_text);
87  local_state->SetString(prefs::kNTPWebStorePromoHeader, header_text);
88  local_state->SetString(prefs::kNTPWebStorePromoLink, link.spec());
89  local_state->SetString(prefs::kNTPWebStorePromoExpire, expire_text);
90}
91
92// static
93bool AppsPromo::IsPromoSupportedForLocale() {
94  PrefService* local_state = g_browser_process->local_state();
95  // PromoResourceService will clear the promo data if the current locale is
96  // not supported.
97  return local_state->HasPrefPath(prefs::kNTPWebStorePromoId) &&
98      local_state->HasPrefPath(prefs::kNTPWebStorePromoHeader) &&
99      local_state->HasPrefPath(prefs::kNTPWebStorePromoButton) &&
100      local_state->HasPrefPath(prefs::kNTPWebStorePromoLink) &&
101      local_state->HasPrefPath(prefs::kNTPWebStorePromoExpire);
102}
103
104AppsPromo::AppsPromo(PrefService* prefs)
105    : prefs_(prefs) {
106  // Poppit, Entanglement
107  old_default_app_ids_.insert("mcbkbpnkkkipelfledbfocopglifcfmi");
108  old_default_app_ids_.insert("aciahcmjmecflokailenpkdchphgkefd");
109}
110
111AppsPromo::~AppsPromo() {}
112
113bool AppsPromo::ShouldShowPromo(const ExtensionIdSet& installed_ids,
114                                bool* just_expired) {
115  *just_expired = false;
116
117  if (CommandLine::ForCurrentProcess()->HasSwitch(
118          switches::kForceAppsPromoVisible)) {
119    return true;
120  }
121
122  // Don't show the promo if one wasn't served to this locale.
123  if (!IsPromoSupportedForLocale())
124    return false;
125
126  int promo_counter = GetPromoCounter();
127  if (GetDefaultAppsInstalled() && promo_counter <= kDefaultAppsCounterMax) {
128    // If the default apps were installed from a previous Chrome version, we
129    // should still show the promo. If we don't have the exact set of default
130    // apps, this means that the user manually installed or uninstalled one.
131    // We no longer keep track of the default apps once others have been
132    // installed, so expire them immediately.
133    if (old_default_app_ids_ != installed_ids) {
134      ExpireDefaultApps();
135      return false;
136    }
137
138    if (promo_counter == kDefaultAppsCounterMax) {
139      *just_expired = true;
140
141      // The default apps have expired due to inaction, so ping PROMO_EXPIRE.
142      UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppsPromoHistogram,
143                                extension_misc::PROMO_EXPIRE,
144                                extension_misc::PROMO_BUCKET_BOUNDARY);
145
146      ExpireDefaultApps();
147      return true;
148    } else {
149      SetPromoCounter(++promo_counter);
150      return true;
151    }
152  } else if (installed_ids.empty()) {
153    return true;
154  }
155
156  return false;
157}
158
159bool AppsPromo::ShouldShowAppLauncher(const ExtensionIdSet& installed_ids) {
160  // On Chrome OS the default apps are installed via a separate mechanism that
161  // is always enabled. Therefore we always show the launcher.
162#if defined(OS_CHROME)
163  return true;
164#else
165
166  // Always show the app launcher if an app is installed.
167  if (!installed_ids.empty())
168    return true;
169
170  // Otherwise, only show the app launcher if there's a promo for this locale.
171  return IsPromoSupportedForLocale();
172#endif
173}
174
175void AppsPromo::ExpireDefaultApps() {
176  SetPromoCounter(kDefaultAppsCounterMax + 1);
177}
178
179void AppsPromo::MaximizeAppsIfFirstView() {
180  std::string promo_id = GetPromoId();
181
182  // Maximize the apps section of the NTP if this is the first time viewing the
183  // specific promo.
184  if (GetLastPromoId() != promo_id) {
185    prefs_->SetString(prefs::kNTPWebStorePromoLastId, promo_id);
186    ShownSectionsHandler::SetShownSection(prefs_, APPS);
187  }
188}
189
190void AppsPromo::HidePromo() {
191  UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppsPromoHistogram,
192                            extension_misc::PROMO_CLOSE,
193                            extension_misc::PROMO_BUCKET_BOUNDARY);
194
195  // Put the apps section into menu mode, and maximize the recent section.
196  ShownSectionsHandler::SetShownSection(prefs_, MENU_APPS);
197  ShownSectionsHandler::SetShownSection(prefs_, THUMB);
198
199  ExpireDefaultApps();
200}
201
202std::string AppsPromo::GetLastPromoId() {
203  return prefs_->GetString(prefs::kNTPWebStorePromoLastId);
204}
205
206void AppsPromo::SetLastPromoId(const std::string& id) {
207  prefs_->SetString(prefs::kNTPWebStorePromoLastId, id);
208}
209
210int AppsPromo::GetPromoCounter() const {
211  return prefs_->GetInteger(prefs::kAppsPromoCounter);
212}
213
214void AppsPromo::SetPromoCounter(int val) {
215  prefs_->SetInteger(prefs::kAppsPromoCounter, val);
216  prefs_->ScheduleSavePersistentPrefs();
217}
218
219bool AppsPromo::GetDefaultAppsInstalled() const {
220  return prefs_->GetBoolean(prefs::kDefaultAppsInstalled);
221}
222