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)#include "chrome/browser/notifications/extension_welcome_notification.h" 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/guid.h" 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/lazy_instance.h" 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/message_loop/message_loop.h" 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/prefs/pref_service.h" 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/browser_process.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/notifications/notification.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/prefs/pref_service_syncable.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/ui/browser_navigator.h" 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/common/pref_names.h" 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/common/url_constants.h" 1903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "chrome/grit/generated_resources.h" 20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/pref_registry/pref_registry_syncable.h" 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "grit/theme_resources.h" 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/message_center/message_center.h" 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/message_center/notification.h" 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/message_center/notification_delegate.h" 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/message_center/notification_types.h" 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochconst int ExtensionWelcomeNotification::kRequestedShowTimeDays = 14; 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst char ExtensionWelcomeNotification::kChromeNowExtensionID[] = 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "pafkbggdmjlpgkdkcbjmhmfcdpncadgh"; 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class NotificationCallbacks 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : public message_center::NotificationDelegate { 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NotificationCallbacks( 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile* profile, 400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const message_center::NotifierId notifier_id, 410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::string& welcome_notification_id, 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ExtensionWelcomeNotification::Delegate* delegate) 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : profile_(profile), 440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch notifier_id_(notifier_id.type, notifier_id.id), 450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch welcome_notification_id_(welcome_notification_id), 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delegate_(delegate) { 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Overridden from NotificationDelegate: 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void Display() OVERRIDE {} 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void Error() OVERRIDE {} 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void Close(bool by_user) OVERRIDE { 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (by_user) { 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Setting the preference here may cause the notification erasing 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // to reenter. Posting a task avoids this issue. 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delegate_->PostTask( 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&NotificationCallbacks::MarkAsDismissed, this)); 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void Click() OVERRIDE {} 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void ButtonClick(int index) OVERRIDE { 650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (index == 0) { 660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch OpenNotificationLearnMoreTab(); 670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else if (index == 1) { 680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DisableNotificationProvider(); 690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Close(true); 700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else { 710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch NOTREACHED(); 720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void MarkAsDismissed() { 770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch profile_->GetPrefs()->SetBoolean(prefs::kWelcomeNotificationDismissedLocal, 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) true); 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void OpenNotificationLearnMoreTab() { 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) chrome::NavigateParams params( 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) profile_, 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL(chrome::kNotificationWelcomeLearnMoreURL), 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ui::PAGE_TRANSITION_LINK); 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) params.disposition = NEW_FOREGROUND_TAB; 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) params.window_action = chrome::NavigateParams::SHOW_WINDOW; 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) chrome::Navigate(¶ms); 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch void DisableNotificationProvider() { 920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch message_center::Notifier notifier(notifier_id_, base::string16(), true); 930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch message_center::MessageCenter* message_center = 940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch delegate_->GetMessageCenter(); 950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch message_center->DisableNotificationsByNotifier(notifier_id_); 965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu message_center->RemoveNotification(welcome_notification_id_, false); 970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch message_center->GetNotifierSettingsProvider()->SetNotifierEnabled( 980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch notifier, false); 990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual ~NotificationCallbacks() {} 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile* const profile_; 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const message_center::NotifierId notifier_id_; 1060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::string welcome_notification_id_; 1080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Weak ref owned by ExtensionWelcomeNotification. 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ExtensionWelcomeNotification::Delegate* const delegate_; 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(NotificationCallbacks); 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class DefaultDelegate : public ExtensionWelcomeNotification::Delegate { 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DefaultDelegate() {} 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual message_center::MessageCenter* GetMessageCenter() OVERRIDE { 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return g_browser_process->message_center(); 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual base::Time GetCurrentTime() OVERRIDE { 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return base::Time::Now(); 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void PostTask( 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const tracked_objects::Location& from_here, 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Closure& task) OVERRIDE { 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::MessageLoop::current()->PostTask(from_here, task); 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(DefaultDelegate); 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ExtensionWelcomeNotification::ExtensionWelcomeNotification( 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile* const profile, 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ExtensionWelcomeNotification::Delegate* const delegate) 1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : notifier_id_(message_center::NotifierId::APPLICATION, 1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci kChromeNowExtensionID), 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) profile_(profile), 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delegate_(delegate) { 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) welcome_notification_dismissed_pref_.Init( 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) prefs::kWelcomeNotificationDismissed, 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) profile_->GetPrefs(), 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind( 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &ExtensionWelcomeNotification::OnWelcomeNotificationDismissedChanged, 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Unretained(this))); 1520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch welcome_notification_dismissed_local_pref_.Init( 1530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch prefs::kWelcomeNotificationDismissedLocal, 1540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch profile_->GetPrefs()); 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static 1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciExtensionWelcomeNotification* ExtensionWelcomeNotification::Create( 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile* const profile) { 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return Create(profile, new DefaultDelegate()); 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciExtensionWelcomeNotification* ExtensionWelcomeNotification::Create( 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Profile* const profile, Delegate* const delegate) { 1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return new ExtensionWelcomeNotification(profile, delegate); 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ExtensionWelcomeNotification::~ExtensionWelcomeNotification() { 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (delayed_notification_) { 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delayed_notification_.reset(); 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PrefServiceSyncable::FromProfile(profile_)->RemoveObserver(this); 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HideWelcomeNotification(); 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionWelcomeNotification::OnIsSyncingChanged() { 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(delayed_notification_); 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PrefServiceSyncable* const pref_service_syncable = 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PrefServiceSyncable::FromProfile(profile_); 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (pref_service_syncable->IsSyncing()) { 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pref_service_syncable->RemoveObserver(this); 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<Notification> previous_notification( 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delayed_notification_.release()); 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ShowWelcomeNotificationIfNecessary(*(previous_notification.get())); 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionWelcomeNotification::ShowWelcomeNotificationIfNecessary( 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const Notification& notification) { 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if ((notification.notifier_id() == notifier_id_) && !delayed_notification_) { 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PrefServiceSyncable* const pref_service_syncable = 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PrefServiceSyncable::FromProfile(profile_); 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (pref_service_syncable->IsSyncing()) { 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PrefService* const pref_service = profile_->GetPrefs(); 1970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!UserHasDismissedWelcomeNotification()) { 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const PopUpRequest pop_up_request = 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pref_service->GetBoolean( 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) prefs::kWelcomeNotificationPreviouslyPoppedUp) 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ? POP_UP_HIDDEN 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : POP_UP_SHOWN; 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (pop_up_request == POP_UP_SHOWN) { 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pref_service->SetBoolean( 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) prefs::kWelcomeNotificationPreviouslyPoppedUp, true); 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (IsWelcomeNotificationExpired()) { 2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ExpireWelcomeNotification(); 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ShowWelcomeNotification( 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) notification.display_source(), pop_up_request); 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delayed_notification_.reset(new Notification(notification)); 2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pref_service_syncable->AddObserver(this); 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionWelcomeNotification::RegisterProfilePrefs( 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) user_prefs::PrefRegistrySyncable* prefs) { 2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) prefs->RegisterBooleanPref(prefs::kWelcomeNotificationDismissed, 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) false, 2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 2280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch prefs->RegisterBooleanPref(prefs::kWelcomeNotificationDismissedLocal, 2290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch false, 2300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) prefs->RegisterBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp, 2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) false, 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) prefs->RegisterInt64Pref(prefs::kWelcomeNotificationExpirationTimestamp, 2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 0, 2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)message_center::MessageCenter* 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ExtensionWelcomeNotification::GetMessageCenter() const { 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return delegate_->GetMessageCenter(); 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionWelcomeNotification::ShowWelcomeNotification( 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::string16& display_source, 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const PopUpRequest pop_up_request) { 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::ButtonInfo learn_more( 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_NOTIFICATION_WELCOME_BUTTON_LEARN_MORE)); 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) learn_more.icon = ui::ResourceBundle::GetSharedInstance().GetImageNamed( 2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IDR_NOTIFICATION_WELCOME_LEARN_MORE); 2510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch message_center::ButtonInfo disable( 2520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch l10n_util::GetStringUTF16(IDS_NOTIFIER_WELCOME_BUTTON)); 2530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch disable.icon = ui::ResourceBundle::GetSharedInstance().GetImageNamed( 2540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch IDR_NOTIFIER_BLOCK_BUTTON); 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::RichNotificationData rich_notification_data; 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) rich_notification_data.priority = 2; 2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) rich_notification_data.buttons.push_back(learn_more); 2590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch rich_notification_data.buttons.push_back(disable); 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (welcome_notification_id_.empty()) 2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) welcome_notification_id_ = base::GenerateGUID(); 2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!welcome_notification_id_.empty()) { 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<message_center::Notification> message_center_notification( 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new message_center::Notification( 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::NOTIFICATION_TYPE_BASE_FORMAT, 2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) welcome_notification_id_, 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_NOTIFICATION_WELCOME_TITLE), 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_NOTIFICATION_WELCOME_BODY), 2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ui::ResourceBundle::GetSharedInstance().GetImageNamed( 2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IDR_NOTIFICATION_WELCOME_ICON), 2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) display_source, 2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) notifier_id_, 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) rich_notification_data, 2760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch new NotificationCallbacks( 2770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch profile_, notifier_id_, welcome_notification_id_, 2780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch delegate_.get()))); 2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (pop_up_request == POP_UP_HIDDEN) 2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center_notification->set_shown_as_popup(true); 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetMessageCenter()->AddNotification(message_center_notification.Pass()); 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) StartExpirationTimer(); 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionWelcomeNotification::HideWelcomeNotification() { 2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!welcome_notification_id_.empty() && 290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GetMessageCenter()->FindVisibleNotificationById( 291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) welcome_notification_id_) != NULL) { 2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetMessageCenter()->RemoveNotification(welcome_notification_id_, false); 2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) StopExpirationTimer(); 2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool ExtensionWelcomeNotification::UserHasDismissedWelcomeNotification() const { 2980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // This was previously a syncable preference; now it's per-machine. 2990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Only the local pref will be written moving forward, but check for both so 3000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // users won't be double-toasted. 3010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch bool shown_synced = profile_->GetPrefs()->GetBoolean( 3020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch prefs::kWelcomeNotificationDismissed); 3030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch bool shown_local = profile_->GetPrefs()->GetBoolean( 3040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch prefs::kWelcomeNotificationDismissedLocal); 3050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return (shown_synced || shown_local); 3060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 3070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionWelcomeNotification::OnWelcomeNotificationDismissedChanged() { 3090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (UserHasDismissedWelcomeNotification()) { 3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HideWelcomeNotification(); 3110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionWelcomeNotification::StartExpirationTimer() { 3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!expiration_timer_ && !IsWelcomeNotificationExpired()) { 3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Time expiration_timestamp = GetExpirationTimestamp(); 3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (expiration_timestamp.is_null()) { 3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetExpirationTimestampFromNow(); 3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) expiration_timestamp = GetExpirationTimestamp(); 3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!expiration_timestamp.is_null()); 3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) expiration_timer_.reset( 3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new base::OneShotTimer<ExtensionWelcomeNotification>()); 3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) expiration_timer_->Start( 3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) expiration_timestamp - delegate_->GetCurrentTime(), 3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) this, 3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &ExtensionWelcomeNotification::ExpireWelcomeNotification); 3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionWelcomeNotification::StopExpirationTimer() { 3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (expiration_timer_) { 3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) expiration_timer_->Stop(); 3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) expiration_timer_.reset(); 3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionWelcomeNotification::ExpireWelcomeNotification() { 3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(IsWelcomeNotificationExpired()); 3410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch profile_->GetPrefs()->SetBoolean( 3420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch prefs::kWelcomeNotificationDismissedLocal, true); 3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HideWelcomeNotification(); 3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::Time ExtensionWelcomeNotification::GetExpirationTimestamp() const { 3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PrefService* const pref_service = profile_->GetPrefs(); 3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const int64 expiration_timestamp = 3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pref_service->GetInt64(prefs::kWelcomeNotificationExpirationTimestamp); 3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return (expiration_timestamp == 0) 3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ? base::Time() 3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : base::Time::FromInternalValue(expiration_timestamp); 3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionWelcomeNotification::SetExpirationTimestampFromNow() { 3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PrefService* const pref_service = profile_->GetPrefs(); 3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pref_service->SetInt64( 3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) prefs::kWelcomeNotificationExpirationTimestamp, 3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (delegate_->GetCurrentTime() + 3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::TimeDelta::FromDays(kRequestedShowTimeDays)).ToInternalValue()); 3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ExtensionWelcomeNotification::IsWelcomeNotificationExpired() const { 3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Time expiration_timestamp = GetExpirationTimestamp(); 3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return !expiration_timestamp.is_null() && 3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (expiration_timestamp <= delegate_->GetCurrentTime()); 3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 368