普通文本  |  205行  |  7.13 KB

// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/notifications/welcome_notification.h"

#include "base/guid.h"
#include "base/lazy_instance.h"
#include "base/message_loop/message_loop.h"
#include "base/prefs/pref_service.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/prefs/pref_service_syncable.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser_navigator.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "components/user_prefs/pref_registry_syncable.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/message_center/message_center.h"
#include "ui/message_center/notification.h"
#include "ui/message_center/notification_delegate.h"
#include "ui/message_center/notification_types.h"

const char kChromeNowExtensionID[] = "pafkbggdmjlpgkdkcbjmhmfcdpncadgh";

class WelcomeNotificationDelegate
    : public message_center::NotificationDelegate {
 public:
  WelcomeNotificationDelegate(const std::string& id, Profile* profile)
      : profile_(profile) {}

  // Overridden from NotificationDelegate:
  virtual void Display() OVERRIDE {}
  virtual void Error() OVERRIDE {}

  virtual void Close(bool by_user) OVERRIDE {
    if (by_user) {
      // Setting the preference here may cause the notification erasing
      // to reenter. Posting a task avoids this issue.
      base::MessageLoop::current()->PostTask(
          FROM_HERE,
          base::Bind(&WelcomeNotificationDelegate::MarkAsDismissed, this));
    }
  }

  virtual void Click() OVERRIDE {}
  virtual void ButtonClick(int index) OVERRIDE {
    DCHECK(index == 0);
    OpenNotificationLearnMoreTab();
  }

 private:
  void MarkAsDismissed() {
    profile_->GetPrefs()->
        SetBoolean(prefs::kWelcomeNotificationDismissed, true);
  }

  void OpenNotificationLearnMoreTab() {
    chrome::NavigateParams params(
        profile_,
        GURL(chrome::kNotificationWelcomeLearnMoreURL),
        content::PAGE_TRANSITION_LINK);
    params.disposition = NEW_FOREGROUND_TAB;
    params.window_action = chrome::NavigateParams::SHOW_WINDOW;
    chrome::Navigate(&params);
  }

  virtual ~WelcomeNotificationDelegate() {}

  Profile* const profile_;

  DISALLOW_COPY_AND_ASSIGN(WelcomeNotificationDelegate);
};

WelcomeNotification::WelcomeNotification(
    Profile* profile,
    message_center::MessageCenter* message_center)
    : profile_(profile),
      message_center_(message_center) {
  welcome_notification_dismissed_pref_.Init(
    prefs::kWelcomeNotificationDismissed,
    profile_->GetPrefs(),
    base::Bind(
        &WelcomeNotification::OnWelcomeNotificationDismissedChanged,
        base::Unretained(this)));
}

WelcomeNotification::~WelcomeNotification() {
  if (delayed_notification_) {
    delayed_notification_.reset();
    PrefServiceSyncable::FromProfile(profile_)->RemoveObserver(this);
  }
}

void WelcomeNotification::OnIsSyncingChanged() {
  DCHECK(delayed_notification_);
  PrefServiceSyncable* pref_service_syncable =
      PrefServiceSyncable::FromProfile(profile_);
  if (pref_service_syncable->IsSyncing()) {
    pref_service_syncable->RemoveObserver(this);
    scoped_ptr<Notification> previous_notification(
        delayed_notification_.release());
    ShowWelcomeNotificationIfNecessary(*(previous_notification.get()));
  }
}

void WelcomeNotification::ShowWelcomeNotificationIfNecessary(
    const Notification& notification) {
  message_center::NotifierId notifier_id = notification.notifier_id();
  if ((notifier_id.id == kChromeNowExtensionID) && !delayed_notification_) {
    PrefServiceSyncable* pref_service_syncable =
        PrefServiceSyncable::FromProfile(profile_);
    if (pref_service_syncable->IsSyncing()) {
      PrefService* pref_service = profile_->GetPrefs();
      if (!pref_service->GetBoolean(prefs::kWelcomeNotificationDismissed)) {
        PopUpRequest pop_up_request =
            pref_service->GetBoolean(
                prefs::kWelcomeNotificationPreviouslyPoppedUp)
            ? POP_UP_HIDDEN
            : POP_UP_SHOWN;
        if (pop_up_request == POP_UP_SHOWN) {
          pref_service->SetBoolean(
              prefs::kWelcomeNotificationPreviouslyPoppedUp, true);
        }

        ShowWelcomeNotification(notifier_id,
                                notification.display_source(),
                                pop_up_request);
      }
    } else {
      delayed_notification_.reset(new Notification(notification));
      pref_service_syncable->AddObserver(this);
    }
  }
}

// Static
void WelcomeNotification::RegisterProfilePrefs(
    user_prefs::PrefRegistrySyncable* prefs) {
  prefs->RegisterBooleanPref(
      prefs::kWelcomeNotificationDismissed,
      false,
      user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
  prefs->RegisterBooleanPref(
      prefs::kWelcomeNotificationPreviouslyPoppedUp,
      false,
      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
}

void WelcomeNotification::ShowWelcomeNotification(
    const message_center::NotifierId notifier_id,
    const base::string16& display_source,
    PopUpRequest pop_up_request) {
  message_center::ButtonInfo learn_more(
      l10n_util::GetStringUTF16(IDS_NOTIFICATION_WELCOME_BUTTON_LEARN_MORE));
  learn_more.icon = ui::ResourceBundle::GetSharedInstance().GetImageNamed(
      IDR_NOTIFICATION_WELCOME_LEARN_MORE);

  message_center::RichNotificationData rich_notification_data;
  rich_notification_data.priority = 2;
  rich_notification_data.buttons.push_back(learn_more);

  if (welcome_notification_id_.empty())
    welcome_notification_id_ = base::GenerateGUID();

  if (!welcome_notification_id_.empty()) {
    scoped_ptr<message_center::Notification> message_center_notification(
        new message_center::Notification(
            message_center::NOTIFICATION_TYPE_BASE_FORMAT,
            welcome_notification_id_,
            l10n_util::GetStringUTF16(IDS_NOTIFICATION_WELCOME_TITLE),
            l10n_util::GetStringUTF16(IDS_NOTIFICATION_WELCOME_BODY),
            ui::ResourceBundle::GetSharedInstance().GetImageNamed(
                IDR_NOTIFICATION_WELCOME_ICON),
            display_source,
            notifier_id,
            rich_notification_data,
            new WelcomeNotificationDelegate(
                welcome_notification_id_, profile_)));

    if (pop_up_request == POP_UP_HIDDEN)
      message_center_notification->set_shown_as_popup(true);

    message_center_->AddNotification(message_center_notification.Pass());
  }
}

void WelcomeNotification::HideWelcomeNotification() {
  if (!welcome_notification_id_.empty() &&
      message_center_->HasNotification(welcome_notification_id_)) {
    message_center_->RemoveNotification(welcome_notification_id_, false);
  }
}

void WelcomeNotification::OnWelcomeNotificationDismissedChanged() {
  const bool welcome_notification_dismissed =
      profile_->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed);
  if (welcome_notification_dismissed)
    HideWelcomeNotification();
}