// Copyright (c) 2011 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/extension_disabled_infobar_delegate.h"
#include <string>
#include "base/utf_string_conversions.h"
#include "chrome/browser/extensions/extension_install_ui.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/tab_contents/confirm_infobar_delegate.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/common/extensions/extension_file_util.h"
#include "chrome/common/extensions/extension_resource.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "content/common/notification_details.h"
#include "content/common/notification_registrar.h"
#include "content/common/notification_source.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
// ExtensionDisabledDialogDelegate --------------------------------------------
class ExtensionDisabledDialogDelegate
: public ExtensionInstallUI::Delegate,
public base::RefCountedThreadSafe<ExtensionDisabledDialogDelegate> {
public:
ExtensionDisabledDialogDelegate(Profile* profile,
ExtensionService* service,
const Extension* extension);
private:
friend class base::RefCountedThreadSafe<ExtensionDisabledDialogDelegate>;
virtual ~ExtensionDisabledDialogDelegate();
// ExtensionInstallUI::Delegate:
virtual void InstallUIProceed();
virtual void InstallUIAbort();
// The UI for showing the install dialog when enabling.
scoped_ptr<ExtensionInstallUI> install_ui_;
ExtensionService* service_;
const Extension* extension_;
};
ExtensionDisabledDialogDelegate::ExtensionDisabledDialogDelegate(
Profile* profile,
ExtensionService* service,
const Extension* extension)
: service_(service), extension_(extension) {
AddRef(); // Balanced in Proceed or Abort.
install_ui_.reset(new ExtensionInstallUI(profile));
install_ui_->ConfirmReEnable(this, extension_);
}
ExtensionDisabledDialogDelegate::~ExtensionDisabledDialogDelegate() {
}
void ExtensionDisabledDialogDelegate::InstallUIProceed() {
service_->GrantPermissionsAndEnableExtension(extension_);
Release();
}
void ExtensionDisabledDialogDelegate::InstallUIAbort() {
ExtensionService::RecordPermissionMessagesHistogram(
extension_, "Extensions.Permissions_ReEnableCancel");
// Do nothing. The extension will remain disabled.
Release();
}
// ExtensionDisabledInfobarDelegate -------------------------------------------
class ExtensionDisabledInfobarDelegate : public ConfirmInfoBarDelegate,
public NotificationObserver {
public:
ExtensionDisabledInfobarDelegate(TabContents* tab_contents,
ExtensionService* service,
const Extension* extension);
private:
virtual ~ExtensionDisabledInfobarDelegate();
// ConfirmInfoBarDelegate:
virtual void InfoBarClosed();
virtual string16 GetMessageText() const;
virtual int GetButtons() const;
virtual string16 GetButtonLabel(InfoBarButton button) const;
virtual bool Accept();
// NotificationObserver:
virtual void Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details);
NotificationRegistrar registrar_;
TabContents* tab_contents_;
ExtensionService* service_;
const Extension* extension_;
};
ExtensionDisabledInfobarDelegate::ExtensionDisabledInfobarDelegate(
TabContents* tab_contents,
ExtensionService* service,
const Extension* extension)
: ConfirmInfoBarDelegate(tab_contents),
tab_contents_(tab_contents),
service_(service),
extension_(extension) {
// The user might re-enable the extension in other ways, so watch for that.
registrar_.Add(this, NotificationType::EXTENSION_LOADED,
Source<Profile>(service->profile()));
registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
Source<Profile>(service->profile()));
}
ExtensionDisabledInfobarDelegate::~ExtensionDisabledInfobarDelegate() {
}
void ExtensionDisabledInfobarDelegate::InfoBarClosed() {
delete this;
}
string16 ExtensionDisabledInfobarDelegate::GetMessageText() const {
return l10n_util::GetStringFUTF16(extension_->is_app() ?
IDS_APP_DISABLED_INFOBAR_LABEL : IDS_EXTENSION_DISABLED_INFOBAR_LABEL,
UTF8ToUTF16(extension_->name()));
}
int ExtensionDisabledInfobarDelegate::GetButtons() const {
return BUTTON_OK;
}
string16 ExtensionDisabledInfobarDelegate::GetButtonLabel(
InfoBarButton button) const {
DCHECK_EQ(BUTTON_OK, button);
return l10n_util::GetStringUTF16(
IDS_EXTENSION_DISABLED_INFOBAR_ENABLE_BUTTON);
}
bool ExtensionDisabledInfobarDelegate::Accept() {
// This object manages its own lifetime.
new ExtensionDisabledDialogDelegate(tab_contents_->profile(), service_,
extension_);
return true;
}
void ExtensionDisabledInfobarDelegate::Observe(
NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
// TODO(mpcomplete): RemoveInfoBar doesn't seem to always result in us getting
// deleted.
const Extension* extension;
if (type.value == NotificationType::EXTENSION_LOADED) {
extension = Details<const Extension>(details).ptr();
} else {
DCHECK_EQ(NotificationType::EXTENSION_UNLOADED, type.value);
UnloadedExtensionInfo* info = Details<UnloadedExtensionInfo>(details).ptr();
extension = (info->reason == UnloadedExtensionInfo::DISABLE) ?
info->extension : NULL;
}
if (extension == extension_)
tab_contents_->RemoveInfoBar(this);
}
// Globals --------------------------------------------------------------------
void ShowExtensionDisabledUI(ExtensionService* service, Profile* profile,
const Extension* extension) {
Browser* browser = BrowserList::GetLastActiveWithProfile(profile);
if (!browser)
return;
TabContents* tab_contents = browser->GetSelectedTabContents();
if (!tab_contents)
return;
tab_contents->AddInfoBar(new ExtensionDisabledInfobarDelegate(
tab_contents, service, extension));
}
void ShowExtensionDisabledDialog(ExtensionService* service, Profile* profile,
const Extension* extension) {
// This object manages its own lifetime.
new ExtensionDisabledDialogDelegate(profile, service, extension);
}