// 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/pepper_flash_settings_manager.h"
#include <map>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/file_util.h"
#include "base/prefs/pref_service.h"
#include "base/sequenced_task_runner_helpers.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/plugins/plugin_prefs.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/renderer_host/pepper/device_id_fetcher.h"
#include "chrome/common/pref_names.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/pepper_flash_settings_helper.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/webplugininfo.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_listener.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "url/gurl.h"
using content::BrowserThread;
class PepperFlashSettingsManager::Core
: public IPC::Listener,
public base::RefCountedThreadSafe<Core, BrowserThread::DeleteOnIOThread> {
public:
Core(base::WeakPtr<PepperFlashSettingsManager> manager,
content::BrowserContext* browser_context);
void Initialize();
// Notifies the core that it has been detached. Afterwards, no method should
// be called any more.
void Detach();
void DeauthorizeContentLicenses(uint32 request_id);
void GetPermissionSettings(
uint32 request_id,
PP_Flash_BrowserOperations_SettingType setting_type);
void SetDefaultPermission(
uint32 request_id,
PP_Flash_BrowserOperations_SettingType setting_type,
PP_Flash_BrowserOperations_Permission permission,
bool clear_site_specific);
void SetSitePermission(uint32 request_id,
PP_Flash_BrowserOperations_SettingType setting_type,
const ppapi::FlashSiteSettings& sites);
void GetSitesWithData(uint32 request_id);
void ClearSiteData(uint32 request_id,
const std::string& site,
uint64 flags,
uint64 max_age);
// IPC::Listener implementation.
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
virtual void OnChannelError() OVERRIDE;
private:
friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>;
friend class base::DeleteHelper<Core>;
enum RequestType {
INVALID_REQUEST_TYPE = 0,
DEAUTHORIZE_CONTENT_LICENSES,
GET_PERMISSION_SETTINGS,
SET_DEFAULT_PERMISSION,
SET_SITE_PERMISSION,
GET_SITES_WITH_DATA,
CLEAR_SITE_DATA,
};
enum State {
STATE_UNINITIALIZED = 0,
STATE_INITIALIZED,
STATE_ERROR,
STATE_DETACHED,
};
struct PendingRequest {
PendingRequest()
: id(0),
type(INVALID_REQUEST_TYPE),
setting_type(PP_FLASH_BROWSEROPERATIONS_SETTINGTYPE_CAMERAMIC),
permission(PP_FLASH_BROWSEROPERATIONS_PERMISSION_DEFAULT),
clear_site_specific(false),
flags(0),
max_age(0) {
}
uint32 id;
RequestType type;
// Used by GET_PERMISSION_SETTINGS, SET_DEFAULT_PERMISSION and
// SET_SITE_PERMISSION.
PP_Flash_BrowserOperations_SettingType setting_type;
// Used by SET_DEFAULT_PERMISSION.
PP_Flash_BrowserOperations_Permission permission;
bool clear_site_specific;
// Used by SET_SITE_PERMISSION.
ppapi::FlashSiteSettings sites;
// Used by CLEAR_SITE_DATA
std::string site;
uint64 flags;
uint64 max_age;
};
virtual ~Core();
void ConnectToChannel(bool success, const IPC::ChannelHandle& handle);
void InitializeOnIOThread();
void DeauthorizeContentLicensesOnIOThread(uint32 request_id);
void DeauthorizeContentLicensesOnBlockingPool(
uint32 request_id,
const base::FilePath& profile_path);
void DeauthorizeContentLicensesInPlugin(uint32 request_id, bool success);
void GetPermissionSettingsOnIOThread(
uint32 request_id,
PP_Flash_BrowserOperations_SettingType setting_type);
void SetDefaultPermissionOnIOThread(
uint32 request_id,
PP_Flash_BrowserOperations_SettingType setting_type,
PP_Flash_BrowserOperations_Permission permission,
bool clear_site_specific);
void SetSitePermissionOnIOThread(
uint32 request_id,
PP_Flash_BrowserOperations_SettingType setting_type,
const ppapi::FlashSiteSettings& sites);
void GetSitesWithDataOnIOThread(uint32 request_id);
void ClearSiteDataOnIOThread(uint32 request_id,
const std::string& site,
uint64 flags,
uint64 max_age);
void DetachOnIOThread();
void NotifyErrorFromIOThread();
void NotifyDeauthorizeContentLicensesCompleted(uint32 request_id,
bool success);
void NotifyGetPermissionSettingsCompleted(
uint32 request_id,
bool success,
PP_Flash_BrowserOperations_Permission default_permission,
const ppapi::FlashSiteSettings& sites);
void NotifySetDefaultPermissionCompleted(uint32 request_id, bool success);
void NotifySetSitePermissionCompleted(uint32 request_id, bool success);
void NotifyGetSitesWithDataCompleted(uint32 request_id,
const std::vector<std::string>& sites);
void NotifyClearSiteDataCompleted(uint32 request_id, bool success);
void NotifyError(
const std::vector<std::pair<uint32, RequestType> >& notifications);
// Message handlers.
void OnDeauthorizeContentLicensesResult(uint32 request_id, bool success);
void OnGetPermissionSettingsResult(
uint32 request_id,
bool success,
PP_Flash_BrowserOperations_Permission default_permission,
const ppapi::FlashSiteSettings& sites);
void OnSetDefaultPermissionResult(uint32 request_id, bool success);
void OnSetSitePermissionResult(uint32 request_id, bool success);
void OnGetSitesWithDataResult(uint32 request_id,
const std::vector<std::string>& sites);
void OnClearSiteDataResult(uint32 request_id, bool success);
// Used only on the UI thread.
base::WeakPtr<PepperFlashSettingsManager> manager_;
// Used only on the I/O thread.
base::FilePath plugin_data_path_;
// The channel is NULL until we have opened a connection to the broker
// process. Used only on the I/O thread.
scoped_ptr<IPC::Channel> channel_;
// Used only on the I/O thread.
State state_;
// Requests that need to be sent once the channel to the broker process is
// established. Used only on the I/O thread.
std::vector<PendingRequest> pending_requests_;
// Requests that have been sent but haven't got replied. Used only on the
// I/O thread.
std::map<uint32, RequestType> pending_responses_;
// Used only on the I/O thread.
scoped_refptr<content::PepperFlashSettingsHelper> helper_;
// Path for the current profile. Must be retrieved on the UI thread from the
// browser context when we start so we can use it later on the I/O thread.
base::FilePath browser_context_path_;
scoped_refptr<PluginPrefs> plugin_prefs_;
};
PepperFlashSettingsManager::Core::Core(
base::WeakPtr<PepperFlashSettingsManager> manager,
content::BrowserContext* browser_context)
: manager_(manager),
state_(STATE_UNINITIALIZED),
browser_context_path_(browser_context->GetPath()),
plugin_prefs_(PluginPrefs::GetForProfile(
Profile::FromBrowserContext(browser_context))) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
PepperFlashSettingsManager::Core::~Core() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
}
void PepperFlashSettingsManager::Core::Initialize() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::Bind(&Core::InitializeOnIOThread, this));
}
void PepperFlashSettingsManager::Core::Detach() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// This call guarantees that one ref is retained until we get to the DETACHED
// state. This is important. Otherwise, if the ref count drops to zero on the
// UI thread (which posts a task to delete this object on the I/O thread)
// while the I/O thread doesn't know about it, methods on the I/O thread might
// increase the ref count again and cause double deletion.
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE, base::Bind(&Core::DetachOnIOThread, this));
}
void PepperFlashSettingsManager::Core::DeauthorizeContentLicenses(
uint32 request_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&Core::DeauthorizeContentLicensesOnIOThread, this,
request_id));
}
void PepperFlashSettingsManager::Core::GetPermissionSettings(
uint32 request_id,
PP_Flash_BrowserOperations_SettingType setting_type) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&Core::GetPermissionSettingsOnIOThread, this, request_id,
setting_type));
}
void PepperFlashSettingsManager::Core::SetDefaultPermission(
uint32 request_id,
PP_Flash_BrowserOperations_SettingType setting_type,
PP_Flash_BrowserOperations_Permission permission,
bool clear_site_specific) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&Core::SetDefaultPermissionOnIOThread, this, request_id,
setting_type, permission, clear_site_specific));
}
void PepperFlashSettingsManager::Core::SetSitePermission(
uint32 request_id,
PP_Flash_BrowserOperations_SettingType setting_type,
const ppapi::FlashSiteSettings& sites) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&Core::SetSitePermissionOnIOThread, this, request_id,
setting_type, sites));
}
void PepperFlashSettingsManager::Core::GetSitesWithData(uint32 request_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&Core::GetSitesWithDataOnIOThread, this, request_id));
}
void PepperFlashSettingsManager::Core::ClearSiteData(uint32 request_id,
const std::string& site,
uint64 flags,
uint64 max_age) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&Core::ClearSiteDataOnIOThread, this, request_id,
site, flags, max_age));
}
bool PepperFlashSettingsManager::Core::OnMessageReceived(
const IPC::Message& message) {
IPC_BEGIN_MESSAGE_MAP(Core, message)
IPC_MESSAGE_HANDLER(PpapiHostMsg_DeauthorizeContentLicensesResult,
OnDeauthorizeContentLicensesResult)
IPC_MESSAGE_HANDLER(PpapiHostMsg_GetPermissionSettingsResult,
OnGetPermissionSettingsResult)
IPC_MESSAGE_HANDLER(PpapiHostMsg_SetDefaultPermissionResult,
OnSetDefaultPermissionResult)
IPC_MESSAGE_HANDLER(PpapiHostMsg_SetSitePermissionResult,
OnSetSitePermissionResult)
IPC_MESSAGE_HANDLER(PpapiHostMsg_GetSitesWithDataResult,
OnGetSitesWithDataResult)
IPC_MESSAGE_HANDLER(PpapiHostMsg_ClearSiteDataResult,
OnClearSiteDataResult)
IPC_MESSAGE_UNHANDLED_ERROR()
IPC_END_MESSAGE_MAP()
return true;
}
void PepperFlashSettingsManager::Core::OnChannelError() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (state_ == STATE_DETACHED)
return;
NotifyErrorFromIOThread();
}
void PepperFlashSettingsManager::Core::ConnectToChannel(
bool success,
const IPC::ChannelHandle& handle) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (state_ == STATE_DETACHED)
return;
DCHECK(state_ == STATE_UNINITIALIZED);
DCHECK(!channel_.get());
if (!success) {
DLOG(ERROR) << "Couldn't open plugin channel";
NotifyErrorFromIOThread();
return;
}
channel_ = IPC::Channel::CreateClient(handle, this);
if (!channel_->Connect()) {
DLOG(ERROR) << "Couldn't connect to plugin";
NotifyErrorFromIOThread();
return;
}
state_ = STATE_INITIALIZED;
std::vector<PendingRequest> temp_pending_requests;
temp_pending_requests.swap(pending_requests_);
for (std::vector<PendingRequest>::iterator iter =
temp_pending_requests.begin();
iter != temp_pending_requests.end(); ++iter) {
switch (iter->type) {
case INVALID_REQUEST_TYPE:
NOTREACHED();
break;
case DEAUTHORIZE_CONTENT_LICENSES:
DeauthorizeContentLicensesOnIOThread(iter->id);
break;
case GET_PERMISSION_SETTINGS:
GetPermissionSettingsOnIOThread(iter->id, iter->setting_type);
break;
case SET_DEFAULT_PERMISSION:
SetDefaultPermissionOnIOThread(
iter->id, iter->setting_type, iter->permission,
iter->clear_site_specific);
break;
case SET_SITE_PERMISSION:
SetSitePermissionOnIOThread(iter->id, iter->setting_type, iter->sites);
break;
case GET_SITES_WITH_DATA:
GetSitesWithDataOnIOThread(iter->id);
break;
case CLEAR_SITE_DATA:
ClearSiteDataOnIOThread(iter->id, iter->site, iter->flags,
iter->max_age);
break;
}
}
}
void PepperFlashSettingsManager::Core::InitializeOnIOThread() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK_EQ(STATE_UNINITIALIZED, state_);
content::WebPluginInfo plugin_info;
if (!PepperFlashSettingsManager::IsPepperFlashInUse(plugin_prefs_.get(),
&plugin_info)) {
NotifyErrorFromIOThread();
return;
}
base::FilePath profile_path =
browser_context_path_.Append(content::kPepperDataDirname);
#if defined(OS_WIN)
plugin_data_path_ = profile_path.Append(plugin_info.name);
#else
plugin_data_path_ = profile_path.Append(base::UTF16ToUTF8(plugin_info.name));
#endif
helper_ = content::PepperFlashSettingsHelper::Create();
content::PepperFlashSettingsHelper::OpenChannelCallback callback =
base::Bind(&Core::ConnectToChannel, this);
helper_->OpenChannelToBroker(plugin_info.path, callback);
}
void PepperFlashSettingsManager::Core::DeauthorizeContentLicensesOnIOThread(
uint32 request_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK_NE(STATE_DETACHED, state_);
if (state_ == STATE_UNINITIALIZED) {
PendingRequest request;
request.id = request_id;
request.type = DEAUTHORIZE_CONTENT_LICENSES;
pending_requests_.push_back(request);
return;
}
pending_responses_.insert(
std::make_pair(request_id, DEAUTHORIZE_CONTENT_LICENSES));
if (state_ == STATE_ERROR) {
NotifyErrorFromIOThread();
return;
}
#if defined(OS_CHROMEOS)
BrowserThread::PostBlockingPoolTask(FROM_HERE,
base::Bind(&Core::DeauthorizeContentLicensesOnBlockingPool, this,
request_id, browser_context_path_));
#else
DeauthorizeContentLicensesInPlugin(request_id, true);
#endif
}
// TODO(raymes): This is temporary code to migrate ChromeOS devices to the new
// scheme for generating device IDs. Delete this once we are sure most ChromeOS
// devices have been migrated.
void PepperFlashSettingsManager::Core::DeauthorizeContentLicensesOnBlockingPool(
uint32 request_id,
const base::FilePath& profile_path) {
// ChromeOS used to store the device ID in a file but this is no longer used.
// Wipe that file.
const base::FilePath& device_id_path =
chrome::DeviceIDFetcher::GetLegacyDeviceIDPath(profile_path);
bool success = base::DeleteFile(device_id_path, false);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&Core::DeauthorizeContentLicensesInPlugin, this, request_id,
success));
}
void PepperFlashSettingsManager::Core::DeauthorizeContentLicensesInPlugin(
uint32 request_id,
bool success) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (!success) {
NotifyErrorFromIOThread();
return;
}
IPC::Message* msg =
new PpapiMsg_DeauthorizeContentLicenses(request_id, plugin_data_path_);
if (!channel_->Send(msg)) {
DLOG(ERROR) << "Couldn't send DeauthorizeContentLicenses message";
// A failure notification for the current request will be sent since
// |pending_responses_| has been updated.
NotifyErrorFromIOThread();
}
}
void PepperFlashSettingsManager::Core::GetPermissionSettingsOnIOThread(
uint32 request_id,
PP_Flash_BrowserOperations_SettingType setting_type) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK_NE(STATE_DETACHED, state_);
if (state_ == STATE_UNINITIALIZED) {
PendingRequest request;
request.id = request_id;
request.type = GET_PERMISSION_SETTINGS;
request.setting_type = setting_type;
pending_requests_.push_back(request);
return;
}
pending_responses_.insert(
std::make_pair(request_id, GET_PERMISSION_SETTINGS));
if (state_ == STATE_ERROR) {
NotifyErrorFromIOThread();
return;
}
IPC::Message* msg = new PpapiMsg_GetPermissionSettings(
request_id, plugin_data_path_, setting_type);
if (!channel_->Send(msg)) {
DLOG(ERROR) << "Couldn't send GetPermissionSettings message";
// A failure notification for the current request will be sent since
// |pending_responses_| has been updated.
NotifyErrorFromIOThread();
}
}
void PepperFlashSettingsManager::Core::SetDefaultPermissionOnIOThread(
uint32 request_id,
PP_Flash_BrowserOperations_SettingType setting_type,
PP_Flash_BrowserOperations_Permission permission,
bool clear_site_specific) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK_NE(STATE_DETACHED, state_);
if (state_ == STATE_UNINITIALIZED) {
PendingRequest request;
request.id = request_id;
request.type = SET_DEFAULT_PERMISSION;
request.setting_type = setting_type;
request.permission = permission;
request.clear_site_specific = clear_site_specific;
pending_requests_.push_back(request);
return;
}
pending_responses_.insert(std::make_pair(request_id, SET_DEFAULT_PERMISSION));
if (state_ == STATE_ERROR) {
NotifyErrorFromIOThread();
return;
}
IPC::Message* msg = new PpapiMsg_SetDefaultPermission(
request_id, plugin_data_path_, setting_type, permission,
clear_site_specific);
if (!channel_->Send(msg)) {
DLOG(ERROR) << "Couldn't send SetDefaultPermission message";
// A failure notification for the current request will be sent since
// |pending_responses_| has been updated.
NotifyErrorFromIOThread();
}
}
void PepperFlashSettingsManager::Core::SetSitePermissionOnIOThread(
uint32 request_id,
PP_Flash_BrowserOperations_SettingType setting_type,
const ppapi::FlashSiteSettings& sites) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK_NE(STATE_DETACHED, state_);
if (state_ == STATE_UNINITIALIZED) {
pending_requests_.push_back(PendingRequest());
PendingRequest& request = pending_requests_.back();
request.id = request_id;
request.type = SET_SITE_PERMISSION;
request.setting_type = setting_type;
request.sites = sites;
return;
}
pending_responses_.insert(std::make_pair(request_id, SET_SITE_PERMISSION));
if (state_ == STATE_ERROR) {
NotifyErrorFromIOThread();
return;
}
IPC::Message* msg = new PpapiMsg_SetSitePermission(
request_id, plugin_data_path_, setting_type, sites);
if (!channel_->Send(msg)) {
DLOG(ERROR) << "Couldn't send SetSitePermission message";
// A failure notification for the current request will be sent since
// |pending_responses_| has been updated.
NotifyErrorFromIOThread();
}
}
void PepperFlashSettingsManager::Core::GetSitesWithDataOnIOThread(
uint32 request_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK_NE(STATE_DETACHED, state_);
if (state_ == STATE_UNINITIALIZED) {
pending_requests_.push_back(PendingRequest());
PendingRequest& request = pending_requests_.back();
request.id = request_id;
request.type = GET_SITES_WITH_DATA;
return;
}
pending_responses_.insert(std::make_pair(request_id, GET_SITES_WITH_DATA));
if (state_ == STATE_ERROR) {
NotifyErrorFromIOThread();
return;
}
IPC::Message* msg = new PpapiMsg_GetSitesWithData(
request_id, plugin_data_path_);
if (!channel_->Send(msg)) {
DLOG(ERROR) << "Couldn't send GetSitesWithData message";
// A failure notification for the current request will be sent since
// |pending_responses_| has been updated.
NotifyErrorFromIOThread();
}
}
void PepperFlashSettingsManager::Core::ClearSiteDataOnIOThread(
uint32 request_id,
const std::string& site,
uint64 flags,
uint64 max_age) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK_NE(STATE_DETACHED, state_);
if (state_ == STATE_UNINITIALIZED) {
pending_requests_.push_back(PendingRequest());
PendingRequest& request = pending_requests_.back();
request.id = request_id;
request.type = CLEAR_SITE_DATA;
request.site = site;
request.flags = flags;
request.max_age = max_age;
return;
}
pending_responses_.insert(std::make_pair(request_id, CLEAR_SITE_DATA));
if (state_ == STATE_ERROR) {
NotifyErrorFromIOThread();
return;
}
IPC::Message* msg = new PpapiMsg_ClearSiteData(
request_id, plugin_data_path_, site, flags, max_age);
if (!channel_->Send(msg)) {
DLOG(ERROR) << "Couldn't send ClearSiteData message";
// A failure notification for the current request will be sent since
// |pending_responses_| has been updated.
NotifyErrorFromIOThread();
}
}
void PepperFlashSettingsManager::Core::DetachOnIOThread() {
state_ = STATE_DETACHED;
}
void PepperFlashSettingsManager::Core::NotifyErrorFromIOThread() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (state_ == STATE_DETACHED)
return;
state_ = STATE_ERROR;
std::vector<std::pair<uint32, RequestType> > notifications;
for (std::vector<PendingRequest>::iterator iter = pending_requests_.begin();
iter != pending_requests_.end(); ++iter) {
notifications.push_back(std::make_pair(iter->id, iter->type));
}
pending_requests_.clear();
notifications.insert(notifications.end(), pending_responses_.begin(),
pending_responses_.end());
pending_responses_.clear();
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&Core::NotifyError, this, notifications));
}
void
PepperFlashSettingsManager::Core::NotifyDeauthorizeContentLicensesCompleted(
uint32 request_id,
bool success) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (manager_.get()) {
manager_->client_->OnDeauthorizeContentLicensesCompleted(
request_id, success);
}
}
void PepperFlashSettingsManager::Core::NotifyGetPermissionSettingsCompleted(
uint32 request_id,
bool success,
PP_Flash_BrowserOperations_Permission default_permission,
const ppapi::FlashSiteSettings& sites) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (manager_.get()) {
manager_->client_->OnGetPermissionSettingsCompleted(
request_id, success, default_permission, sites);
}
}
void PepperFlashSettingsManager::Core::NotifySetDefaultPermissionCompleted(
uint32 request_id,
bool success) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (manager_.get()) {
manager_->client_->OnSetDefaultPermissionCompleted(
request_id, success);
}
}
void PepperFlashSettingsManager::Core::NotifySetSitePermissionCompleted(
uint32 request_id,
bool success) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (manager_.get()) {
manager_->client_->OnSetSitePermissionCompleted(
request_id, success);
}
}
void PepperFlashSettingsManager::Core::NotifyGetSitesWithDataCompleted(
uint32 request_id,
const std::vector<std::string>& sites) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (manager_.get()) {
manager_->client_->OnGetSitesWithDataCompleted(
request_id, sites);
}
}
void PepperFlashSettingsManager::Core::NotifyClearSiteDataCompleted(
uint32 request_id,
bool success) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (manager_.get())
manager_->client_->OnClearSiteDataCompleted(request_id, success);
}
void PepperFlashSettingsManager::Core::NotifyError(
const std::vector<std::pair<uint32, RequestType> >& notifications) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
scoped_refptr<Core> protector(this);
for (std::vector<std::pair<uint32, RequestType> >::const_iterator iter =
notifications.begin(); iter != notifications.end(); ++iter) {
// Check |manager_| for each iteration in case it is destroyed in one of
// the callbacks.
if (!manager_.get())
return;
switch (iter->second) {
case INVALID_REQUEST_TYPE:
NOTREACHED();
break;
case DEAUTHORIZE_CONTENT_LICENSES:
manager_->client_->OnDeauthorizeContentLicensesCompleted(
iter->first, false);
break;
case GET_PERMISSION_SETTINGS:
manager_->client_->OnGetPermissionSettingsCompleted(
iter->first, false, PP_FLASH_BROWSEROPERATIONS_PERMISSION_DEFAULT,
ppapi::FlashSiteSettings());
break;
case SET_DEFAULT_PERMISSION:
manager_->client_->OnSetDefaultPermissionCompleted(
iter->first, false);
break;
case SET_SITE_PERMISSION:
manager_->client_->OnSetSitePermissionCompleted(iter->first, false);
break;
case GET_SITES_WITH_DATA:
manager_->client_->OnGetSitesWithDataCompleted(
iter->first, std::vector<std::string>());
break;
case CLEAR_SITE_DATA:
manager_->client_->OnClearSiteDataCompleted(iter->first, false);
break;
}
}
if (manager_.get())
manager_->OnError(this);
}
void PepperFlashSettingsManager::Core::OnDeauthorizeContentLicensesResult(
uint32 request_id,
bool success) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (state_ == STATE_DETACHED)
return;
DLOG_IF(ERROR, !success) << "DeauthorizeContentLicenses returned error";
std::map<uint32, RequestType>::iterator iter =
pending_responses_.find(request_id);
if (iter == pending_responses_.end())
return;
DCHECK_EQ(iter->second, DEAUTHORIZE_CONTENT_LICENSES);
pending_responses_.erase(iter);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&Core::NotifyDeauthorizeContentLicensesCompleted, this,
request_id, success));
}
void PepperFlashSettingsManager::Core::OnGetPermissionSettingsResult(
uint32 request_id,
bool success,
PP_Flash_BrowserOperations_Permission default_permission,
const ppapi::FlashSiteSettings& sites) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (state_ == STATE_DETACHED)
return;
DLOG_IF(ERROR, !success) << "GetPermissionSettings returned error";
std::map<uint32, RequestType>::iterator iter =
pending_responses_.find(request_id);
if (iter == pending_responses_.end())
return;
DCHECK_EQ(iter->second, GET_PERMISSION_SETTINGS);
pending_responses_.erase(iter);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&Core::NotifyGetPermissionSettingsCompleted, this,
request_id, success, default_permission, sites));
}
void PepperFlashSettingsManager::Core::OnSetDefaultPermissionResult(
uint32 request_id,
bool success) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (state_ == STATE_DETACHED)
return;
DLOG_IF(ERROR, !success) << "SetDefaultPermission returned error";
std::map<uint32, RequestType>::iterator iter =
pending_responses_.find(request_id);
if (iter == pending_responses_.end())
return;
DCHECK_EQ(iter->second, SET_DEFAULT_PERMISSION);
pending_responses_.erase(iter);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&Core::NotifySetDefaultPermissionCompleted, this,
request_id, success));
}
void PepperFlashSettingsManager::Core::OnSetSitePermissionResult(
uint32 request_id,
bool success) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (state_ == STATE_DETACHED)
return;
DLOG_IF(ERROR, !success) << "SetSitePermission returned error";
std::map<uint32, RequestType>::iterator iter =
pending_responses_.find(request_id);
if (iter == pending_responses_.end())
return;
DCHECK_EQ(iter->second, SET_SITE_PERMISSION);
pending_responses_.erase(iter);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&Core::NotifySetSitePermissionCompleted, this, request_id,
success));
}
void PepperFlashSettingsManager::Core::OnGetSitesWithDataResult(
uint32 request_id,
const std::vector<std::string>& sites) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (state_ == STATE_DETACHED)
return;
std::map<uint32, RequestType>::iterator iter =
pending_responses_.find(request_id);
if (iter == pending_responses_.end())
return;
DCHECK_EQ(iter->second, GET_SITES_WITH_DATA);
pending_responses_.erase(iter);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&Core::NotifyGetSitesWithDataCompleted, this, request_id,
sites));
}
void PepperFlashSettingsManager::Core::OnClearSiteDataResult(
uint32 request_id,
bool success) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (state_ == STATE_DETACHED)
return;
DLOG_IF(ERROR, !success) << "ClearSiteData returned error";
std::map<uint32, RequestType>::iterator iter =
pending_responses_.find(request_id);
if (iter == pending_responses_.end())
return;
DCHECK_EQ(iter->second, CLEAR_SITE_DATA);
pending_responses_.erase(iter);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&Core::NotifyClearSiteDataCompleted, this, request_id,
success));
}
PepperFlashSettingsManager::PepperFlashSettingsManager(
Client* client,
content::BrowserContext* browser_context)
: client_(client),
browser_context_(browser_context),
next_request_id_(1),
weak_ptr_factory_(this) {
DCHECK(client);
DCHECK(browser_context);
}
PepperFlashSettingsManager::~PepperFlashSettingsManager() {
if (core_.get())
core_->Detach();
}
// static
bool PepperFlashSettingsManager::IsPepperFlashInUse(
PluginPrefs* plugin_prefs,
content::WebPluginInfo* plugin_info) {
if (!plugin_prefs)
return false;
content::PluginService* plugin_service =
content::PluginService::GetInstance();
std::vector<content::WebPluginInfo> plugins;
plugin_service->GetPluginInfoArray(
GURL(), content::kFlashPluginSwfMimeType, false, &plugins, NULL);
for (std::vector<content::WebPluginInfo>::iterator iter = plugins.begin();
iter != plugins.end(); ++iter) {
if (iter->is_pepper_plugin() && plugin_prefs->IsPluginEnabled(*iter)) {
if (plugin_info)
*plugin_info = *iter;
return true;
}
}
return false;
}
// static
void PepperFlashSettingsManager::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
registry->RegisterBooleanPref(
prefs::kDeauthorizeContentLicenses,
false,
user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
registry->RegisterBooleanPref(
prefs::kPepperFlashSettingsEnabled,
true,
user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
}
uint32 PepperFlashSettingsManager::DeauthorizeContentLicenses(
PrefService* prefs) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// Clear the device ID salt which has the effect of regenerating a device
// ID. Since this happens synchronously (and on the UI thread), we don't have
// to add it to a pending request.
prefs->ClearPref(prefs::kDRMSalt);
EnsureCoreExists();
uint32 id = GetNextRequestId();
core_->DeauthorizeContentLicenses(id);
return id;
}
uint32 PepperFlashSettingsManager::GetPermissionSettings(
PP_Flash_BrowserOperations_SettingType setting_type) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
EnsureCoreExists();
uint32 id = GetNextRequestId();
core_->GetPermissionSettings(id, setting_type);
return id;
}
uint32 PepperFlashSettingsManager::SetDefaultPermission(
PP_Flash_BrowserOperations_SettingType setting_type,
PP_Flash_BrowserOperations_Permission permission,
bool clear_site_specific) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
EnsureCoreExists();
uint32 id = GetNextRequestId();
core_->SetDefaultPermission(id, setting_type, permission,
clear_site_specific);
return id;
}
uint32 PepperFlashSettingsManager::SetSitePermission(
PP_Flash_BrowserOperations_SettingType setting_type,
const ppapi::FlashSiteSettings& sites) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
EnsureCoreExists();
uint32 id = GetNextRequestId();
core_->SetSitePermission(id, setting_type, sites);
return id;
}
uint32 PepperFlashSettingsManager::GetSitesWithData() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
EnsureCoreExists();
uint32 id = GetNextRequestId();
core_->GetSitesWithData(id);
return id;
}
uint32 PepperFlashSettingsManager::ClearSiteData(const std::string& site,
uint64 flags,
uint64 max_age) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
EnsureCoreExists();
uint32 id = GetNextRequestId();
core_->ClearSiteData(id, site, flags, max_age);
return id;
}
uint32 PepperFlashSettingsManager::GetNextRequestId() {
return next_request_id_++;
}
void PepperFlashSettingsManager::EnsureCoreExists() {
if (!core_.get()) {
core_ = new Core(weak_ptr_factory_.GetWeakPtr(), browser_context_);
core_->Initialize();
}
}
void PepperFlashSettingsManager::OnError(Core* core) {
DCHECK(core);
if (core != core_.get())
return;
core_->Detach();
core_ = NULL;
}