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#ifndef CHROME_BROWSER_WEB_RESOURCE_PROMO_RESOURCE_SERVICE_H_
6#define CHROME_BROWSER_WEB_RESOURCE_PROMO_RESOURCE_SERVICE_H_
7#pragma once
8
9#include "chrome/browser/web_resource/web_resource_service.h"
10
11namespace PromoResourceServiceUtil {
12
13// Certain promotions should only be shown to certain classes of users. This
14// function will change to reflect each kind of promotion.
15bool CanShowPromo(Profile* profile);
16
17}  // namespace PromoResourceServiceUtil
18
19class PrefService;
20
21// A PromoResourceService fetches data from a web resource server to be used to
22// dynamically change the appearance of the New Tab Page. For example, it has
23// been used to fetch "tips" to be displayed on the NTP, or to display
24// promotional messages to certain groups of Chrome users.
25//
26// TODO(mirandac): Arrange for a server to be set up specifically for promo
27// messages, which have until now been piggybacked onto the old tips server
28// structure. (see http://crbug.com/70634 for details.)
29class PromoResourceService
30    : public WebResourceService {
31 public:
32  static bool IsBuildTargeted(const std::string& channel, int builds_targeted);
33
34  static void RegisterPrefs(PrefService* local_state);
35
36  static void RegisterUserPrefs(PrefService* prefs);
37
38  explicit PromoResourceService(Profile* profile);
39
40  // Default server of dynamically loaded NTP HTML elements.
41  static const char* kDefaultPromoResourceServer;
42
43 private:
44  FRIEND_TEST_ALL_PREFIXES(PromoResourceServiceTest, UnpackLogoSignal);
45  FRIEND_TEST_ALL_PREFIXES(PromoResourceServiceTest, UnpackPromoSignal);
46  FRIEND_TEST_ALL_PREFIXES(PromoResourceServiceTest, UnpackWebStoreSignal);
47
48  // Identifies types of Chrome builds for promo targeting.
49  enum BuildType {
50    NO_BUILD = 0,
51    DEV_BUILD = 1,
52    BETA_BUILD = 1 << 1,
53    STABLE_BUILD = 1 << 2,
54    CANARY_BUILD = 1 << 3,
55  };
56
57  virtual ~PromoResourceService();
58
59  int GetPromoServiceVersion();
60
61  // Gets the locale of the last promos fetched from the server. This is saved
62  // so we can fetch new data if the locale changes.
63  std::string GetPromoLocale();
64
65  void Init();
66
67  // Returns true if |builds_targeted| includes the release channel Chrome
68  // belongs to. For testing purposes, you can override the current channel
69  // with set_channel.
70  bool IsThisBuildTargeted(int builds_targeted);
71
72  // Schedule a notification that a web resource is either going to become
73  // available or be no longer valid.
74  void ScheduleNotification(double ms_start_time, double ms_end_time);
75
76  // Schedules the initial notification for when the web resource is going
77  // to become available or no longer valid. This performs a few additional
78  // checks than ScheduleNotification, namely it schedules updates immediately
79  // if the promo service or Chrome locale has changed.
80  void ScheduleNotificationOnInit();
81
82  // Overrides the current Chrome release channel for testing purposes.
83  void set_channel(const char* channel) { channel_ = channel; }
84
85  virtual void Unpack(const DictionaryValue& parsed_json);
86
87  // Unpack the web resource as a custom promo signal. Expects a start and end
88  // signal, with the promo to be shown in the tooltip of the start signal
89  // field. Delivery will be in json in the form of:
90  // {
91  //   "topic": {
92  //     "answers": [
93  //       {
94  //         "answer_id": "1067976",
95  //         "name": "promo_start",
96  //         "question": "1:24",
97  //         "tooltip":
98  //       "Click \u003ca href=http://www.google.com\u003ehere\u003c/a\u003e!",
99  //         "inproduct": "10/8/09 12:00",
100  //         "inproduct_target": null
101  //       },
102  //       {
103  //         "answer_id": "1067976",
104  //         "name": "promo_end",
105  //         "question": "",
106  //         "tooltip": "",
107  //         "inproduct": "10/8/11 12:00",
108  //         "inproduct_target": null
109  //       },
110  //       ...
111  //     ]
112  //   }
113  // }
114  //
115  // Because the promo signal data is piggybacked onto the tip server, the
116  // values don't exactly correspond with the field names:
117  //
118  // For "promo_start" or "promo_end", the date to start or stop showing the
119  // promotional line is given by the "inproduct" line.
120  // For "promo_start", the promotional line itself is given in the "tooltip"
121  // field. The "question" field gives the type of builds that should be shown
122  // this promo (see the BuildType enum in web_resource_service.cc) and the
123  // number of hours that each promo group should see it, separated by ":".
124  // For example, "7:24" would indicate that all builds should see the promo,
125  // and each group should see it for 24 hours.
126  //
127  void UnpackPromoSignal(const DictionaryValue& parsed_json);
128
129  // Unpack the promo resource as a custom logo signal. Expects a start and end
130  // signal. Delivery will be in json in the form of:
131  // {
132  //   "topic": {
133  //     "answers": [
134  //       {
135  //         "answer_id": "107366",
136  //         "name": "custom_logo_start",
137  //         "question": "",
138  //         "tooltip": "",
139  //         "inproduct": "10/8/09 12:00",
140  //         "inproduct_target": null
141  //       },
142  //       {
143  //         "answer_id": "107366",
144  //         "name": "custom_logo_end",
145  //         "question": "",
146  //         "tooltip": "",
147  //         "inproduct": "10/8/09 12:00",
148  //         "inproduct_target": null
149  //       },
150  //       ...
151  //     ]
152  //   }
153  // }
154  //
155  void UnpackLogoSignal(const DictionaryValue& parsed_json);
156
157  // Unpack the web store promo. Expects JSON delivery in the following format:
158  // {
159  //   "topic": {
160  //     "answers": [
161  //       {
162  //         "answer_id": "1143011",
163  //         "name": "webstore_promo:15",
164  //         "question": "Browse thousands of apps and games for Chrome.",
165  //         "inproduct_target": "Visit the Chrome Web Store",
166  //         "inproduct": "https://chrome.google.com/webstore?hl=en",
167  //         "tooltip": "No thanks, hide this"
168  //       },
169  //       ...
170  //     ]
171  //   }
172  // }
173  // The properties are defined as follows:
174  //   inproduct: the release channels targeted (bitwise or of BuildTypes)
175  //   question: the promo header text
176  //   inproduct_target: the promo button text
177  //   inproduct: the promo button link
178  //   tooltip: the text for the "hide this" link on the promo
179  //   name: starts with "webstore_promo" to identify the signal. the second
180  //         part contains the release channels targeted (bitwise or of
181  //         BuildTypes)
182  //   answer_id: the promo's id
183  void UnpackWebStoreSignal(const DictionaryValue& parsed_json);
184
185  // Gets mutable dictionary attached to user's preferences, so that we
186  // can write resource data back to user's pref file.
187  DictionaryValue* web_resource_cache_;
188
189  // Overrides the current Chrome release channel for testing purposes.
190  const char* channel_;
191
192  DISALLOW_COPY_AND_ASSIGN(PromoResourceService);
193};
194
195#endif  // CHROME_BROWSER_WEB_RESOURCE_PROMO_RESOURCE_SERVICE_H_
196