blob: 53afc127647a670a8d06cc31e9f9908a5ad4cb1b [file] [log] [blame]
// Copyright (c) 2012 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/extensions/app_notify_channel_ui.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/infobars/infobar_tab_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/signin_manager.h"
#include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/tab_contents/confirm_infobar_delegate.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/browser/ui/webui/signin/login_ui_service.h"
#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
class AppNotifyChannelUIImpl::InfoBar : public ConfirmInfoBarDelegate {
public:
InfoBar(AppNotifyChannelUIImpl* creator,
InfoBarTabHelper* helper,
const std::string& app_name);
virtual ~InfoBar();
// ConfirmInfoBarDelegate.
virtual string16 GetMessageText() const OVERRIDE;
virtual string16 GetButtonLabel(InfoBarButton button) const OVERRIDE;
virtual bool Accept() OVERRIDE;
virtual bool Cancel() OVERRIDE;
virtual void InfoBarDismissed() OVERRIDE;
private:
AppNotifyChannelUIImpl* creator_;
std::string app_name_;
DISALLOW_COPY_AND_ASSIGN(InfoBar);
};
AppNotifyChannelUIImpl::InfoBar::InfoBar(
AppNotifyChannelUIImpl* creator,
InfoBarTabHelper* helper,
const std::string& app_name)
: ConfirmInfoBarDelegate(helper), creator_(creator), app_name_(app_name) {
}
AppNotifyChannelUIImpl::InfoBar::~InfoBar() {}
string16 AppNotifyChannelUIImpl::InfoBar::GetMessageText() const {
return l10n_util::GetStringFUTF16(IDS_APP_NOTIFICATION_NEED_SIGNIN,
UTF8ToUTF16(app_name_));
}
string16 AppNotifyChannelUIImpl::InfoBar::GetButtonLabel(
InfoBarButton button) const {
if (button == BUTTON_OK) {
return l10n_util::GetStringUTF16(IDS_APP_NOTIFICATION_NEED_SIGNIN_ACCEPT);
} else if (button == BUTTON_CANCEL) {
return l10n_util::GetStringUTF16(IDS_APP_NOTIFICATION_NEED_SIGNIN_CANCEL);
} else {
NOTREACHED();
}
return string16();
}
bool AppNotifyChannelUIImpl::InfoBar::Accept() {
creator_->OnInfoBarResult(true);
return true;
}
bool AppNotifyChannelUIImpl::InfoBar::Cancel() {
creator_->OnInfoBarResult(false);
return true;
}
void AppNotifyChannelUIImpl::InfoBar::InfoBarDismissed() {
Cancel();
}
AppNotifyChannelUIImpl::AppNotifyChannelUIImpl(
Profile* profile,
TabContentsWrapper* wrapper,
const std::string& app_name,
AppNotifyChannelUI::UIType ui_type)
: profile_(profile->GetOriginalProfile()),
wrapper_(wrapper),
app_name_(app_name),
ui_type_(ui_type),
delegate_(NULL),
observing_sync_(false),
wizard_shown_to_user_(false) {
}
AppNotifyChannelUIImpl::~AppNotifyChannelUIImpl() {
// We should have either not started observing sync, or already called
// StopObservingSync by this point.
CHECK(!observing_sync_);
}
void AppNotifyChannelUIImpl::PromptSyncSetup(
AppNotifyChannelUI::Delegate* delegate) {
CHECK(delegate_ == NULL);
delegate_ = delegate;
if (!ProfileSyncServiceFactory::GetInstance()->HasProfileSyncService(
profile_)) {
delegate_->OnSyncSetupResult(false);
return;
}
if (ui_type_ == NO_INFOBAR) {
OnInfoBarResult(true);
return;
}
InfoBarTabHelper* helper = wrapper_->infobar_tab_helper();
helper->AddInfoBar(new AppNotifyChannelUIImpl::InfoBar(
this, helper, app_name_));
}
void AppNotifyChannelUIImpl::OnInfoBarResult(bool accepted) {
if (accepted) {
StartObservingSync();
// Bring up the login page.
LoginUIService* login_ui_service =
LoginUIServiceFactory::GetForProfile(profile_);
LoginUIService::LoginUI* login_ui = login_ui_service->current_login_ui();
if (login_ui) {
// Some sort of login UI is already visible.
SigninManager* signin = SigninManagerFactory::GetForProfile(profile_);
if (signin->GetAuthenticatedUsername().empty()) {
// User is not logged in yet, so just bring up the login UI (could be
// the promo UI).
login_ui->FocusUI();
return;
} else {
// User is already logged in, so close whatever sync config UI the
// user is looking at and display new login UI.
login_ui->CloseUI();
DCHECK(!login_ui_service->current_login_ui());
}
}
// Any existing UI is now closed - display new login UI.
Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);
if (browser) {
browser->ShowOptionsTab(chrome::kSyncSetupForceLoginSubPage);
return;
}
// Should not be possible to have no browser here, since we're in an
// infobar callback.
NOTREACHED();
}
delegate_->OnSyncSetupResult(false);
}
void AppNotifyChannelUIImpl::OnStateChanged() {
#if !defined(OS_ANDROID)
ProfileSyncService* sync_service =
ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile_);
LoginUIService* login_service =
LoginUIServiceFactory::GetForProfile(profile_);
bool wizard_visible = (login_service->current_login_ui() != NULL);
// ProfileSyncService raises OnStateChanged many times. Even multiple
// times before the wizard actually becomes visible for the first time.
// So we have to wait for the wizard to become visible once and then we
// wait for it to get dismissed.
bool finished = wizard_shown_to_user_ && !wizard_visible;
if (wizard_visible)
wizard_shown_to_user_ = true;
if (finished) {
StopObservingSync();
delegate_->OnSyncSetupResult(sync_service->HasSyncSetupCompleted());
}
#endif // !defined(OS_ANDROID)
}
void AppNotifyChannelUIImpl::StartObservingSync() {
CHECK(!observing_sync_);
observing_sync_ = true;
ProfileSyncServiceFactory::GetInstance()->GetForProfile(
profile_)->AddObserver(this);
}
void AppNotifyChannelUIImpl::StopObservingSync() {
CHECK(observing_sync_);
observing_sync_ = false;
ProfileSyncServiceFactory::GetInstance()->GetForProfile(
profile_)->RemoveObserver(this);
}