15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/web_resource/notification_promo.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cmath>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_registry_simple.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/rand_util.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sys_info.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/thread_restrictions.h"
18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/browser_process.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/web_resource/promo_resource_service.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_version_info.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/pref_registry/pref_registry_syncable.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/user_metrics.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/url_util.h"
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/base/device_form_factor.h"
28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::UserMetricsAction;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kDefaultGroupSize = 100;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char promo_server_url[] = "https://clients3.google.com/crsignal/client";
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The name of the preference that stores the promotion object.
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPrefPromoObject[] = "promo";
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Keys in the kPrefPromoObject dictionary; used only here.
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPrefPromoText[] = "text";
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPrefPromoPayload[] = "payload";
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPrefPromoStart[] = "start";
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPrefPromoEnd[] = "end";
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPrefPromoNumGroups[] = "num_groups";
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPrefPromoSegment[] = "segment";
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPrefPromoIncrement[] = "increment";
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPrefPromoIncrementFrequency[] = "increment_frequency";
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPrefPromoIncrementMax[] = "increment_max";
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPrefPromoMaxViews[] = "max_views";
525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kPrefPromoMaxSeconds[] = "max_seconds";
535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kPrefPromoFirstViewTime[] = "first_view_time";
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPrefPromoGroup[] = "group";
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPrefPromoViews[] = "views";
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPrefPromoClosed[] = "closed";
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns a string suitable for the Promo Server URL 'osname' value.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string PlatformString() {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "win";
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#elif defined(OS_ANDROID)
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ui::DeviceFormFactor form_factor = ui::GetDeviceFormFactor();
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return std::string("android-") +
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      (form_factor == ui::DEVICE_FORM_FACTOR_TABLET ? "tablet" : "phone");
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_IOS)
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ui::DeviceFormFactor form_factor = ui::GetDeviceFormFactor();
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return std::string("ios-") +
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      (form_factor == ui::DEVICE_FORM_FACTOR_TABLET ? "tablet" : "phone");
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_MACOSX)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "mac";
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_CHROMEOS)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "chromeos";
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_LINUX)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "linux";
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "none";
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns a string suitable for the Promo Server URL 'dist' value.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* ChannelString() {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined (OS_WIN)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GetChannel hits the registry on Windows. See http://crbug.com/70898.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(achuith): Move NotificationPromo::PromoServerURL to the blocking pool.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ThreadRestrictions::ScopedAllowIO allow_io;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const chrome::VersionInfo::Channel channel =
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome::VersionInfo::GetChannel();
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (channel) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case chrome::VersionInfo::CHANNEL_CANARY:
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "canary";
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case chrome::VersionInfo::CHANNEL_DEV:
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "dev";
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case chrome::VersionInfo::CHANNEL_BETA:
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "beta";
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case chrome::VersionInfo::CHANNEL_STABLE:
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "stable";
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "none";
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct PromoMapEntry {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NotificationPromo::PromoType promo_type;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* promo_type_str;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const PromoMapEntry kPromoMap[] = {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { NotificationPromo::NO_PROMO, "" },
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { NotificationPromo::NTP_NOTIFICATION_PROMO, "ntp_notification_promo" },
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { NotificationPromo::NTP_BUBBLE_PROMO, "ntp_bubble_promo" },
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { NotificationPromo::MOBILE_NTP_SYNC_PROMO, "mobile_ntp_sync_promo" },
114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    { NotificationPromo::MOBILE_NTP_WHATS_NEW_PROMO,
115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        "mobile_ntp_whats_new_promo" },
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Convert PromoType to appropriate string.
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* PromoTypeToString(NotificationPromo::PromoType promo_type) {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < arraysize(kPromoMap); ++i) {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (kPromoMap[i].promo_type == promo_type)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return kPromoMap[i].promo_type_str;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "";
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Deep-copies a node, replacing any "value" that is a key
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// into "strings" dictionary with its value from "strings".
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// E.g. for
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   {promo_action_args:['MSG_SHORT']} + strings:{MSG_SHORT:'yes'}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it will return
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   {promo_action_args:['yes']}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |node| - a value to be deep copied and resolved.
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |strings| - a dictionary of strings to be used for resolution.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns a _new_ object that is a deep copy with replacements.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(aruslan): http://crbug.com/144320 Consider moving it to values.cc/h.
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::Value* DeepCopyAndResolveStrings(
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Value* node,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::DictionaryValue* strings) {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (node->GetType()) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case base::Value::TYPE_LIST: {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const base::ListValue* list = static_cast<const base::ListValue*>(node);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::ListValue* copy = new base::ListValue;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (base::ListValue::const_iterator it = list->begin();
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           it != list->end();
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           ++it) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Value* child_copy = DeepCopyAndResolveStrings(*it, strings);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        copy->Append(child_copy);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return copy;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case base::Value::TYPE_DICTIONARY: {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const base::DictionaryValue* dict =
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          static_cast<const base::DictionaryValue*>(node);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::DictionaryValue* copy = new base::DictionaryValue;
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for (base::DictionaryValue::Iterator it(*dict);
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           !it.IsAtEnd();
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           it.Advance()) {
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Value* child_copy = DeepCopyAndResolveStrings(&it.value(),
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                            strings);
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        copy->SetWithoutPathExpansion(it.key(), child_copy);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return copy;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case base::Value::TYPE_STRING: {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string value;
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool rv = node->GetAsString(&value);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(rv);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string actual_value;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!strings || !strings->GetString(value, &actual_value))
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        actual_value = value;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return new base::StringValue(actual_value);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // For everything else, just make a copy.
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return node->DeepCopy();
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppendQueryParameter(GURL* url,
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const std::string& param,
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const std::string& value) {
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *url = net::AppendQueryParameter(*url, param, value);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)NotificationPromo::NotificationPromo()
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : prefs_(g_browser_process->local_state()),
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      promo_type_(NO_PROMO),
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      promo_payload_(new base::DictionaryValue()),
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      start_(0.0),
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      end_(0.0),
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      num_groups_(kDefaultGroupSize),
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      initial_segment_(0),
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      increment_(1),
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      time_slice_(0),
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_group_(0),
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_views_(0),
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      max_seconds_(0),
2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      first_view_time_(0),
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      group_(0),
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      views_(0),
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      closed_(false),
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new_notification_(false) {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(prefs_);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NotificationPromo::~NotificationPromo() {}
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NotificationPromo::InitFromJson(const base::DictionaryValue& json,
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     PromoType promo_type) {
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  promo_type_ = promo_type;
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::ListValue* promo_list = NULL;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "InitFromJson " << PromoTypeToString(promo_type_);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!json.GetList(PromoTypeToString(promo_type_), &promo_list))
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No support for multiple promos yet. Only consider the first one.
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::DictionaryValue* promo = NULL;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!promo_list->GetDictionary(0, &promo))
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Date.
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::ListValue* date_list = NULL;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (promo->GetList("date", &date_list)) {
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::DictionaryValue* date;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (date_list->GetDictionary(0, &date)) {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string time_str;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Time time;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (date->GetString("start", &time_str) &&
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Time::FromString(time_str.c_str(), &time)) {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        start_ = time.ToDoubleT();
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DVLOG(1) << "start str=" << time_str
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << ", start_="<< base::DoubleToString(start_);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (date->GetString("end", &time_str) &&
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Time::FromString(time_str.c_str(), &time)) {
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        end_ = time.ToDoubleT();
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DVLOG(1) << "end str =" << time_str
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << ", end_=" << base::DoubleToString(end_);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Grouping.
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::DictionaryValue* grouping = NULL;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (promo->GetDictionary("grouping", &grouping)) {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    grouping->GetInteger("buckets", &num_groups_);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    grouping->GetInteger("segment", &initial_segment_);
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    grouping->GetInteger("increment", &increment_);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    grouping->GetInteger("increment_frequency", &time_slice_);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    grouping->GetInteger("increment_max", &max_group_);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "num_groups_ = " << num_groups_
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << ", initial_segment_ = " << initial_segment_
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << ", increment_ = " << increment_
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << ", time_slice_ = " << time_slice_
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << ", max_group_ = " << max_group_;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Strings.
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::DictionaryValue* strings = NULL;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  promo->GetDictionary("strings", &strings);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Payload.
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::DictionaryValue* payload = NULL;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (promo->GetDictionary("payload", &payload)) {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Value* ppcopy = DeepCopyAndResolveStrings(payload, strings);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(ppcopy && ppcopy->IsType(base::Value::TYPE_DICTIONARY));
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    promo_payload_.reset(static_cast<base::DictionaryValue*>(ppcopy));
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!promo_payload_->GetString("promo_message_short", &promo_text_) &&
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      strings) {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // For compatibility with the legacy desktop version,
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // if no |payload.promo_message_short| is specified,
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the first string in |strings| is used.
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::DictionaryValue::Iterator iter(*strings);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    iter.value().GetAsString(&promo_text_);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "promo_text_=" << promo_text_;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  promo->GetInteger("max_views", &max_views_);
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "max_views_ " << max_views_;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  promo->GetInteger("max_seconds", &max_seconds_);
2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DVLOG(1) << "max_seconds_ " << max_seconds_;
2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckForNewNotification();
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NotificationPromo::CheckForNewNotification() {
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NotificationPromo old_promo;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  old_promo.InitFromPrefs(promo_type_);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const double old_start = old_promo.start_;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const double old_end = old_promo.end_;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string old_promo_text = old_promo.promo_text_;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  new_notification_ =
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      old_start != start_ || old_end != end_ || old_promo_text != promo_text_;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (new_notification_)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnNewNotification();
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NotificationPromo::OnNewNotification() {
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "OnNewNotification";
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a new promo group.
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  group_ = base::RandInt(0, num_groups_ - 1);
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WritePrefs();
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotificationPromo::RegisterPrefs(PrefRegistrySimple* registry) {
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  registry->RegisterDictionaryPref(kPrefPromoObject);
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
3237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid NotificationPromo::RegisterProfilePrefs(
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    user_prefs::PrefRegistrySyncable* registry) {
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(dbeam): Registered only for migration. Remove in M28 when
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // we're reasonably sure all prefs are gone.
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // http://crbug.com/168887
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  registry->RegisterDictionaryPref(
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kPrefPromoObject, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotificationPromo::MigrateUserPrefs(PrefService* user_prefs) {
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  user_prefs->ClearPref(kPrefPromoObject);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NotificationPromo::WritePrefs() {
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::DictionaryValue* ntp_promo = new base::DictionaryValue;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ntp_promo->SetString(kPrefPromoText, promo_text_);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ntp_promo->Set(kPrefPromoPayload, promo_payload_->DeepCopy());
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ntp_promo->SetDouble(kPrefPromoStart, start_);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ntp_promo->SetDouble(kPrefPromoEnd, end_);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ntp_promo->SetInteger(kPrefPromoNumGroups, num_groups_);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ntp_promo->SetInteger(kPrefPromoSegment, initial_segment_);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ntp_promo->SetInteger(kPrefPromoIncrement, increment_);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ntp_promo->SetInteger(kPrefPromoIncrementFrequency, time_slice_);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ntp_promo->SetInteger(kPrefPromoIncrementMax, max_group_);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ntp_promo->SetInteger(kPrefPromoMaxViews, max_views_);
3515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ntp_promo->SetInteger(kPrefPromoMaxSeconds, max_seconds_);
3525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ntp_promo->SetDouble(kPrefPromoFirstViewTime, first_view_time_);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ntp_promo->SetInteger(kPrefPromoGroup, group_);
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ntp_promo->SetInteger(kPrefPromoViews, views_);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ntp_promo->SetBoolean(kPrefPromoClosed, closed_);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ListValue* promo_list = new base::ListValue;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  promo_list->Set(0, ntp_promo);  // Only support 1 promo for now.
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::DictionaryValue promo_dict;
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  promo_dict.MergeDictionary(prefs_->GetDictionary(kPrefPromoObject));
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  promo_dict.Set(PromoTypeToString(promo_type_), promo_list);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prefs_->Set(kPrefPromoObject, promo_dict);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "WritePrefs " << promo_dict;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NotificationPromo::InitFromPrefs(PromoType promo_type) {
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  promo_type_ = promo_type;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::DictionaryValue* promo_dict =
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prefs_->GetDictionary(kPrefPromoObject);
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!promo_dict)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::ListValue* promo_list = NULL;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  promo_dict->GetList(PromoTypeToString(promo_type_), &promo_list);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!promo_list)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::DictionaryValue* ntp_promo = NULL;
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  promo_list->GetDictionary(0, &ntp_promo);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ntp_promo)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ntp_promo->GetString(kPrefPromoText, &promo_text_);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::DictionaryValue* promo_payload = NULL;
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ntp_promo->GetDictionary(kPrefPromoPayload, &promo_payload))
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    promo_payload_.reset(promo_payload->DeepCopy());
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ntp_promo->GetDouble(kPrefPromoStart, &start_);
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ntp_promo->GetDouble(kPrefPromoEnd, &end_);
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ntp_promo->GetInteger(kPrefPromoNumGroups, &num_groups_);
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ntp_promo->GetInteger(kPrefPromoSegment, &initial_segment_);
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ntp_promo->GetInteger(kPrefPromoIncrement, &increment_);
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ntp_promo->GetInteger(kPrefPromoIncrementFrequency, &time_slice_);
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ntp_promo->GetInteger(kPrefPromoIncrementMax, &max_group_);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ntp_promo->GetInteger(kPrefPromoMaxViews, &max_views_);
4005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ntp_promo->GetInteger(kPrefPromoMaxSeconds, &max_seconds_);
4015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ntp_promo->GetDouble(kPrefPromoFirstViewTime, &first_view_time_);
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ntp_promo->GetInteger(kPrefPromoGroup, &group_);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ntp_promo->GetInteger(kPrefPromoViews, &views_);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ntp_promo->GetBoolean(kPrefPromoClosed, &closed_);
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool NotificationPromo::CheckAppLauncher() const {
4094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#if !defined(ENABLE_APP_LIST)
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#else
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool is_app_launcher_promo = false;
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!promo_payload_->GetBoolean("is_app_launcher_promo",
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  &is_app_launcher_promo))
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return !is_app_launcher_promo ||
4174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)         !prefs_->GetBoolean(prefs::kAppLauncherIsEnabled);
4184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif  // !defined(ENABLE_APP_LIST)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NotificationPromo::CanShow() const {
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !closed_ &&
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         !promo_text_.empty() &&
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         !ExceedsMaxGroup() &&
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         !ExceedsMaxViews() &&
4265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)         !ExceedsMaxSeconds() &&
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         CheckAppLauncher() &&
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         base::Time::FromDoubleT(StartTimeForGroup()) < base::Time::Now() &&
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         base::Time::FromDoubleT(EndTime()) > base::Time::Now();
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotificationPromo::HandleClosed(PromoType promo_type) {
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::RecordAction(UserMetricsAction("NTPPromoClosed"));
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NotificationPromo promo;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  promo.InitFromPrefs(promo_type);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!promo.closed_) {
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    promo.closed_ = true;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    promo.WritePrefs();
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool NotificationPromo::HandleViewed(PromoType promo_type) {
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::RecordAction(UserMetricsAction("NTPPromoShown"));
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NotificationPromo promo;
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  promo.InitFromPrefs(promo_type);
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++promo.views_;
4495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (promo.first_view_time_ == 0) {
4505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    promo.first_view_time_ = base::Time::Now().ToDoubleT();
4515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  promo.WritePrefs();
4535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return promo.ExceedsMaxViews() || promo.ExceedsMaxSeconds();
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NotificationPromo::ExceedsMaxGroup() const {
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (max_group_ == 0) ? false : group_ >= max_group_;
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NotificationPromo::ExceedsMaxViews() const {
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (max_views_ == 0) ? false : views_ >= max_views_;
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool NotificationPromo::ExceedsMaxSeconds() const {
4655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (max_seconds_ == 0 || first_view_time_ == 0)
4665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
4675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const base::Time last_view_time = base::Time::FromDoubleT(first_view_time_) +
4695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    base::TimeDelta::FromSeconds(max_seconds_);
4705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return last_view_time < base::Time::Now();
4715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
4725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GURL NotificationPromo::PromoServerURL() {
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url(promo_server_url);
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendQueryParameter(&url, "dist", ChannelString());
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendQueryParameter(&url, "osname", PlatformString());
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendQueryParameter(&url, "branding", chrome::VersionInfo().Version());
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendQueryParameter(&url, "osver", base::SysInfo::OperatingSystemVersion());
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "PromoServerURL=" << url.spec();
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that locale param is added by WebResourceService.
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return url;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double NotificationPromo::StartTimeForGroup() const {
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (group_ < initial_segment_)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return start_;
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return start_ +
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::ceil(static_cast<float>(group_ - initial_segment_ + 1) / increment_)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      * time_slice_;
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double NotificationPromo::EndTime() const {
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return end_;
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
496