15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file. 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifndef CHROME_BROWSER_NOTIFICATIONS_EXTENSION_WELCOME_NOTIFICATION_H_ 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define CHROME_BROWSER_NOTIFICATIONS_EXTENSION_WELCOME_NOTIFICATION_H_ 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <string> 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/prefs/pref_member.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/timer/timer.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/prefs/pref_service_syncable_observer.h" 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/keyed_service/core/keyed_service.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/message_center/notifier_settings.h" 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace base { 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)typedef Callback<void(void)> Closure; 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace message_center { 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class MessageCenter; 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace tracked_objects { 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class Location; 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace user_prefs { 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class PrefRegistrySyncable; 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class Notification; 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class Profile; 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// ExtensionWelcomeNotification is a keyed service which manages showing and 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// hiding a welcome notification for built-in components that show 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// notifications. The Welcome Notification presumes network connectivity since 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// it relies on synced preferences to work. This is generally fine since the 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// current consumers on the welcome notification also presume network 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// connectivity. 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This class expects to be created and called from the UI thread. 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass ExtensionWelcomeNotification : public KeyedService, 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public PrefServiceSyncableObserver { 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Allows for overriding global calls. 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) class Delegate { 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Delegate() {} 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual ~Delegate() {} 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual message_center::MessageCenter* GetMessageCenter() = 0; 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual base::Time GetCurrentTime() = 0; 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void PostTask( 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const tracked_objects::Location& from_here, 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Closure& task) = 0; 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(Delegate); 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) }; 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Requested time from showing the welcome notification to expiration. 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const int kRequestedShowTimeDays; 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The extension Id associated with the Google Now extension. 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static const char kChromeNowExtensionID[]; 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual ~ExtensionWelcomeNotification(); 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // To workaround the lack of delegating constructors prior to C++11, we use 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // static Create methods. 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Creates an ExtensionWelcomeNotification with the default delegate. 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static ExtensionWelcomeNotification* Create(Profile* const profile); 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Creates an ExtensionWelcomeNotification with the specified delegate. 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static ExtensionWelcomeNotification* Create(Profile* const profile, 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Delegate* const delegate); 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // PrefServiceSyncableObserver 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void OnIsSyncingChanged() OVERRIDE; 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Adds in the welcome notification if required for components built 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // into Chrome that show notifications like Chrome Now. 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void ShowWelcomeNotificationIfNecessary(const Notification& notification); 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Handles Preference Registration for the Welcome Notification. 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* prefs); 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) enum PopUpRequest { POP_UP_HIDDEN = 0, POP_UP_SHOWN = 1, }; 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ExtensionWelcomeNotification( 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile* const profile, 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ExtensionWelcomeNotification::Delegate* const delegate); 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Gets the message center from the delegate. 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::MessageCenter* GetMessageCenter() const; 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Unconditionally shows the welcome notification. 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void ShowWelcomeNotification(const base::string16& display_source, 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const PopUpRequest pop_up_request); 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Hides the welcome notification. 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void HideWelcomeNotification(); 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Whether the notification has been dismissed. 1060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch bool UserHasDismissedWelcomeNotification() const; 1070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Called when the Welcome Notification Dismissed pref has been changed. 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void OnWelcomeNotificationDismissedChanged(); 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Starts the welcome notification expiration timer. 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void StartExpirationTimer(); 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Stops the welcome notification expiration timer. 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void StopExpirationTimer(); 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Expires the welcome notification by hiding it and marking it dismissed. 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void ExpireWelcomeNotification(); 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Gets the expiration timestamp or a null time is there is none. 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Time GetExpirationTimestamp() const; 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Sets the expiration timestamp from now. 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void SetExpirationTimestampFromNow(); 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // True if the welcome notification has expired, false otherwise. 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool IsWelcomeNotificationExpired() const; 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Prefs listener for welcome_notification_dismissed. 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BooleanPrefMember welcome_notification_dismissed_pref_; 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Prefs listener for welcome_notification_dismissed_local. 1330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Dismissal flag migrated from a synced pref to a local one. 1340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch BooleanPrefMember welcome_notification_dismissed_local_pref_; 1350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The notifier for the extension that we're listening for. 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::NotifierId notifier_id_; 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The profile which owns this object. 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile* profile_; 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Notification ID of the Welcome Notification. 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string welcome_notification_id_; 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If the preferences are still syncing, store the last notification here 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // so we can replay ShowWelcomeNotificationIfNecessary once the sync finishes. 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Simplifying Assumption: The delayed notification has passed the 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // extension ID check. This means we do not need to store all of the 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // notifications that may also show a welcome notification. 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<Notification> delayed_notification_; 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If the welcome notification is shown, this timer tracks when to hide the 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // welcome notification. 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::OneShotTimer<ExtensionWelcomeNotification> > 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) expiration_timer_; 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Delegate for Chrome global calls like base::Time::GetTime() for 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // testability. 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<Delegate> delegate_; 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ExtensionWelcomeNotification); 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif // CHROME_BROWSER_NOTIFICATIONS_EXTENSION_WELCOME_NOTIFICATION_H_ 165