// 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 #include #include #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/user_prefs/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 { public: Core(base::WeakPtr 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; friend class base::DeleteHelper; 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& sites); void NotifyClearSiteDataCompleted(uint32 request_id, bool success); void NotifyError( const std::vector >& 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& sites); void OnClearSiteDataResult(uint32 request_id, bool success); // Used only on the UI thread. base::WeakPtr 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 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 pending_requests_; // Requests that have been sent but haven't got replied. Used only on the // I/O thread. std::map pending_responses_; // Used only on the I/O thread. scoped_refptr 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 plugin_prefs_; }; PepperFlashSettingsManager::Core::Core( base::WeakPtr 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_.reset(new IPC::Channel(handle, IPC::Channel::MODE_CLIENT, this)); if (!channel_->Connect()) { DLOG(ERROR) << "Couldn't connect to plugin"; NotifyErrorFromIOThread(); return; } state_ = STATE_INITIALIZED; std::vector temp_pending_requests; temp_pending_requests.swap(pending_requests_); for (std::vector::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 > notifications; for (std::vector::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& 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 >& notifications) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); scoped_refptr protector(this); for (std::vector >::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()); 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::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::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::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::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& sites) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); if (state_ == STATE_DETACHED) return; std::map::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::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 plugins; plugin_service->GetPluginInfoArray( GURL(), content::kFlashPluginSwfMimeType, false, &plugins, NULL); for (std::vector::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; }