Home | History | Annotate | Download | only in browser
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/pepper_flash_settings_manager.h"
      6 
      7 #include <map>
      8 #include <utility>
      9 #include <vector>
     10 
     11 #include "base/bind.h"
     12 #include "base/compiler_specific.h"
     13 #include "base/file_util.h"
     14 #include "base/prefs/pref_service.h"
     15 #include "base/sequenced_task_runner_helpers.h"
     16 #include "base/strings/utf_string_conversions.h"
     17 #include "chrome/browser/plugins/plugin_prefs.h"
     18 #include "chrome/browser/profiles/profile.h"
     19 #include "chrome/browser/renderer_host/pepper/device_id_fetcher.h"
     20 #include "chrome/common/pref_names.h"
     21 #include "components/user_prefs/pref_registry_syncable.h"
     22 #include "content/public/browser/browser_context.h"
     23 #include "content/public/browser/browser_thread.h"
     24 #include "content/public/browser/pepper_flash_settings_helper.h"
     25 #include "content/public/browser/plugin_service.h"
     26 #include "content/public/common/content_constants.h"
     27 #include "content/public/common/webplugininfo.h"
     28 #include "ipc/ipc_channel.h"
     29 #include "ipc/ipc_listener.h"
     30 #include "ppapi/proxy/ppapi_messages.h"
     31 #include "url/gurl.h"
     32 
     33 using content::BrowserThread;
     34 
     35 class PepperFlashSettingsManager::Core
     36     : public IPC::Listener,
     37       public base::RefCountedThreadSafe<Core, BrowserThread::DeleteOnIOThread> {
     38  public:
     39   Core(base::WeakPtr<PepperFlashSettingsManager> manager,
     40        content::BrowserContext* browser_context);
     41 
     42   void Initialize();
     43 
     44   // Notifies the core that it has been detached. Afterwards, no method should
     45   // be called any more.
     46   void Detach();
     47 
     48   void DeauthorizeContentLicenses(uint32 request_id);
     49   void GetPermissionSettings(
     50       uint32 request_id,
     51       PP_Flash_BrowserOperations_SettingType setting_type);
     52   void SetDefaultPermission(
     53       uint32 request_id,
     54       PP_Flash_BrowserOperations_SettingType setting_type,
     55       PP_Flash_BrowserOperations_Permission permission,
     56       bool clear_site_specific);
     57   void SetSitePermission(uint32 request_id,
     58                          PP_Flash_BrowserOperations_SettingType setting_type,
     59                          const ppapi::FlashSiteSettings& sites);
     60   void GetSitesWithData(uint32 request_id);
     61   void ClearSiteData(uint32 request_id,
     62                      const std::string& site,
     63                      uint64 flags,
     64                      uint64 max_age);
     65 
     66   // IPC::Listener implementation.
     67   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
     68   virtual void OnChannelError() OVERRIDE;
     69 
     70  private:
     71   friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>;
     72   friend class base::DeleteHelper<Core>;
     73 
     74   enum RequestType {
     75     INVALID_REQUEST_TYPE = 0,
     76     DEAUTHORIZE_CONTENT_LICENSES,
     77     GET_PERMISSION_SETTINGS,
     78     SET_DEFAULT_PERMISSION,
     79     SET_SITE_PERMISSION,
     80     GET_SITES_WITH_DATA,
     81     CLEAR_SITE_DATA,
     82   };
     83 
     84   enum State {
     85     STATE_UNINITIALIZED = 0,
     86     STATE_INITIALIZED,
     87     STATE_ERROR,
     88     STATE_DETACHED,
     89   };
     90 
     91   struct PendingRequest {
     92     PendingRequest()
     93         : id(0),
     94           type(INVALID_REQUEST_TYPE),
     95           setting_type(PP_FLASH_BROWSEROPERATIONS_SETTINGTYPE_CAMERAMIC),
     96           permission(PP_FLASH_BROWSEROPERATIONS_PERMISSION_DEFAULT),
     97           clear_site_specific(false),
     98           flags(0),
     99           max_age(0) {
    100     }
    101 
    102     uint32 id;
    103     RequestType type;
    104 
    105     // Used by GET_PERMISSION_SETTINGS, SET_DEFAULT_PERMISSION and
    106     // SET_SITE_PERMISSION.
    107     PP_Flash_BrowserOperations_SettingType setting_type;
    108 
    109     // Used by SET_DEFAULT_PERMISSION.
    110     PP_Flash_BrowserOperations_Permission permission;
    111     bool clear_site_specific;
    112 
    113     // Used by SET_SITE_PERMISSION.
    114     ppapi::FlashSiteSettings sites;
    115 
    116     // Used by CLEAR_SITE_DATA
    117     std::string site;
    118     uint64 flags;
    119     uint64 max_age;
    120   };
    121 
    122   virtual ~Core();
    123 
    124   void ConnectToChannel(bool success, const IPC::ChannelHandle& handle);
    125 
    126   void InitializeOnIOThread();
    127   void DeauthorizeContentLicensesOnIOThread(uint32 request_id);
    128   void DeauthorizeContentLicensesOnBlockingPool(
    129       uint32 request_id,
    130       const base::FilePath& profile_path);
    131   void DeauthorizeContentLicensesInPlugin(uint32 request_id, bool success);
    132   void GetPermissionSettingsOnIOThread(
    133       uint32 request_id,
    134       PP_Flash_BrowserOperations_SettingType setting_type);
    135   void SetDefaultPermissionOnIOThread(
    136       uint32 request_id,
    137       PP_Flash_BrowserOperations_SettingType setting_type,
    138       PP_Flash_BrowserOperations_Permission permission,
    139       bool clear_site_specific);
    140   void SetSitePermissionOnIOThread(
    141       uint32 request_id,
    142       PP_Flash_BrowserOperations_SettingType setting_type,
    143       const ppapi::FlashSiteSettings& sites);
    144   void GetSitesWithDataOnIOThread(uint32 request_id);
    145   void ClearSiteDataOnIOThread(uint32 request_id,
    146                                const std::string& site,
    147                                uint64 flags,
    148                                uint64 max_age);
    149   void DetachOnIOThread();
    150 
    151   void NotifyErrorFromIOThread();
    152 
    153   void NotifyDeauthorizeContentLicensesCompleted(uint32 request_id,
    154                                                  bool success);
    155   void NotifyGetPermissionSettingsCompleted(
    156       uint32 request_id,
    157       bool success,
    158       PP_Flash_BrowserOperations_Permission default_permission,
    159       const ppapi::FlashSiteSettings& sites);
    160   void NotifySetDefaultPermissionCompleted(uint32 request_id, bool success);
    161   void NotifySetSitePermissionCompleted(uint32 request_id, bool success);
    162   void NotifyGetSitesWithDataCompleted(uint32 request_id,
    163                                        const std::vector<std::string>& sites);
    164   void NotifyClearSiteDataCompleted(uint32 request_id, bool success);
    165 
    166   void NotifyError(
    167       const std::vector<std::pair<uint32, RequestType> >& notifications);
    168 
    169   // Message handlers.
    170   void OnDeauthorizeContentLicensesResult(uint32 request_id, bool success);
    171   void OnGetPermissionSettingsResult(
    172       uint32 request_id,
    173       bool success,
    174       PP_Flash_BrowserOperations_Permission default_permission,
    175       const ppapi::FlashSiteSettings& sites);
    176   void OnSetDefaultPermissionResult(uint32 request_id, bool success);
    177   void OnSetSitePermissionResult(uint32 request_id, bool success);
    178   void OnGetSitesWithDataResult(uint32 request_id,
    179                                 const std::vector<std::string>& sites);
    180   void OnClearSiteDataResult(uint32 request_id, bool success);
    181 
    182   // Used only on the UI thread.
    183   base::WeakPtr<PepperFlashSettingsManager> manager_;
    184 
    185   // Used only on the I/O thread.
    186   base::FilePath plugin_data_path_;
    187 
    188   // The channel is NULL until we have opened a connection to the broker
    189   // process. Used only on the I/O thread.
    190   scoped_ptr<IPC::Channel> channel_;
    191 
    192   // Used only on the I/O thread.
    193   State state_;
    194 
    195   // Requests that need to be sent once the channel to the broker process is
    196   // established. Used only on the I/O thread.
    197   std::vector<PendingRequest> pending_requests_;
    198   // Requests that have been sent but haven't got replied. Used only on the
    199   // I/O thread.
    200   std::map<uint32, RequestType> pending_responses_;
    201 
    202   // Used only on the I/O thread.
    203   scoped_refptr<content::PepperFlashSettingsHelper> helper_;
    204 
    205   // Path for the current profile. Must be retrieved on the UI thread from the
    206   // browser context when we start so we can use it later on the I/O thread.
    207   base::FilePath browser_context_path_;
    208 
    209   scoped_refptr<PluginPrefs> plugin_prefs_;
    210 };
    211 
    212 PepperFlashSettingsManager::Core::Core(
    213     base::WeakPtr<PepperFlashSettingsManager> manager,
    214     content::BrowserContext* browser_context)
    215     : manager_(manager),
    216       state_(STATE_UNINITIALIZED),
    217       browser_context_path_(browser_context->GetPath()),
    218       plugin_prefs_(PluginPrefs::GetForProfile(
    219           Profile::FromBrowserContext(browser_context))) {
    220   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    221 }
    222 
    223 PepperFlashSettingsManager::Core::~Core() {
    224   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    225 }
    226 
    227 void PepperFlashSettingsManager::Core::Initialize() {
    228   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    229   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
    230                           base::Bind(&Core::InitializeOnIOThread, this));
    231 }
    232 
    233 void PepperFlashSettingsManager::Core::Detach() {
    234   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    235 
    236   // This call guarantees that one ref is retained until we get to the DETACHED
    237   // state. This is important. Otherwise, if the ref count drops to zero on the
    238   // UI thread (which posts a task to delete this object on the I/O thread)
    239   // while the I/O thread doesn't know about it, methods on the I/O thread might
    240   // increase the ref count again and cause double deletion.
    241   BrowserThread::PostTask(
    242       BrowserThread::IO, FROM_HERE, base::Bind(&Core::DetachOnIOThread, this));
    243 }
    244 
    245 void PepperFlashSettingsManager::Core::DeauthorizeContentLicenses(
    246     uint32 request_id) {
    247   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    248 
    249   BrowserThread::PostTask(
    250       BrowserThread::IO, FROM_HERE,
    251       base::Bind(&Core::DeauthorizeContentLicensesOnIOThread, this,
    252                  request_id));
    253 }
    254 
    255 void PepperFlashSettingsManager::Core::GetPermissionSettings(
    256     uint32 request_id,
    257     PP_Flash_BrowserOperations_SettingType setting_type) {
    258   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    259 
    260   BrowserThread::PostTask(
    261       BrowserThread::IO, FROM_HERE,
    262       base::Bind(&Core::GetPermissionSettingsOnIOThread, this, request_id,
    263                  setting_type));
    264 }
    265 
    266 void PepperFlashSettingsManager::Core::SetDefaultPermission(
    267     uint32 request_id,
    268     PP_Flash_BrowserOperations_SettingType setting_type,
    269     PP_Flash_BrowserOperations_Permission permission,
    270     bool clear_site_specific) {
    271   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    272 
    273   BrowserThread::PostTask(
    274       BrowserThread::IO, FROM_HERE,
    275       base::Bind(&Core::SetDefaultPermissionOnIOThread, this, request_id,
    276                  setting_type, permission, clear_site_specific));
    277 }
    278 
    279 void PepperFlashSettingsManager::Core::SetSitePermission(
    280     uint32 request_id,
    281     PP_Flash_BrowserOperations_SettingType setting_type,
    282     const ppapi::FlashSiteSettings& sites) {
    283   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    284 
    285   BrowserThread::PostTask(
    286       BrowserThread::IO, FROM_HERE,
    287       base::Bind(&Core::SetSitePermissionOnIOThread, this, request_id,
    288                  setting_type, sites));
    289 }
    290 
    291 void PepperFlashSettingsManager::Core::GetSitesWithData(uint32 request_id) {
    292   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    293 
    294   BrowserThread::PostTask(
    295       BrowserThread::IO, FROM_HERE,
    296       base::Bind(&Core::GetSitesWithDataOnIOThread, this, request_id));
    297 }
    298 
    299 void PepperFlashSettingsManager::Core::ClearSiteData(uint32 request_id,
    300                                                      const std::string& site,
    301                                                      uint64 flags,
    302                                                      uint64 max_age) {
    303   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    304 
    305   BrowserThread::PostTask(
    306       BrowserThread::IO, FROM_HERE,
    307       base::Bind(&Core::ClearSiteDataOnIOThread, this, request_id,
    308                  site, flags, max_age));
    309 }
    310 
    311 bool PepperFlashSettingsManager::Core::OnMessageReceived(
    312     const IPC::Message& message) {
    313   IPC_BEGIN_MESSAGE_MAP(Core, message)
    314     IPC_MESSAGE_HANDLER(PpapiHostMsg_DeauthorizeContentLicensesResult,
    315                         OnDeauthorizeContentLicensesResult)
    316     IPC_MESSAGE_HANDLER(PpapiHostMsg_GetPermissionSettingsResult,
    317                         OnGetPermissionSettingsResult)
    318     IPC_MESSAGE_HANDLER(PpapiHostMsg_SetDefaultPermissionResult,
    319                         OnSetDefaultPermissionResult)
    320     IPC_MESSAGE_HANDLER(PpapiHostMsg_SetSitePermissionResult,
    321                         OnSetSitePermissionResult)
    322     IPC_MESSAGE_HANDLER(PpapiHostMsg_GetSitesWithDataResult,
    323                         OnGetSitesWithDataResult)
    324     IPC_MESSAGE_HANDLER(PpapiHostMsg_ClearSiteDataResult,
    325                         OnClearSiteDataResult)
    326     IPC_MESSAGE_UNHANDLED_ERROR()
    327   IPC_END_MESSAGE_MAP()
    328 
    329   return true;
    330 }
    331 
    332 void PepperFlashSettingsManager::Core::OnChannelError() {
    333   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    334   if (state_ == STATE_DETACHED)
    335     return;
    336 
    337   NotifyErrorFromIOThread();
    338 }
    339 
    340 void PepperFlashSettingsManager::Core::ConnectToChannel(
    341     bool success,
    342     const IPC::ChannelHandle& handle) {
    343   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    344   if (state_ == STATE_DETACHED)
    345     return;
    346 
    347   DCHECK(state_ == STATE_UNINITIALIZED);
    348   DCHECK(!channel_.get());
    349 
    350   if (!success) {
    351     DLOG(ERROR) << "Couldn't open plugin channel";
    352     NotifyErrorFromIOThread();
    353     return;
    354   }
    355 
    356   channel_.reset(new IPC::Channel(handle, IPC::Channel::MODE_CLIENT, this));
    357   if (!channel_->Connect()) {
    358     DLOG(ERROR) << "Couldn't connect to plugin";
    359     NotifyErrorFromIOThread();
    360     return;
    361   }
    362 
    363   state_ = STATE_INITIALIZED;
    364 
    365   std::vector<PendingRequest> temp_pending_requests;
    366   temp_pending_requests.swap(pending_requests_);
    367   for (std::vector<PendingRequest>::iterator iter =
    368            temp_pending_requests.begin();
    369        iter != temp_pending_requests.end(); ++iter) {
    370     switch (iter->type) {
    371       case INVALID_REQUEST_TYPE:
    372         NOTREACHED();
    373         break;
    374       case DEAUTHORIZE_CONTENT_LICENSES:
    375         DeauthorizeContentLicensesOnIOThread(iter->id);
    376         break;
    377       case GET_PERMISSION_SETTINGS:
    378         GetPermissionSettingsOnIOThread(iter->id, iter->setting_type);
    379         break;
    380       case SET_DEFAULT_PERMISSION:
    381         SetDefaultPermissionOnIOThread(
    382             iter->id, iter->setting_type, iter->permission,
    383             iter->clear_site_specific);
    384         break;
    385       case SET_SITE_PERMISSION:
    386         SetSitePermissionOnIOThread(iter->id, iter->setting_type, iter->sites);
    387         break;
    388       case GET_SITES_WITH_DATA:
    389         GetSitesWithDataOnIOThread(iter->id);
    390         break;
    391       case CLEAR_SITE_DATA:
    392         ClearSiteDataOnIOThread(iter->id, iter->site, iter->flags,
    393                                 iter->max_age);
    394         break;
    395     }
    396   }
    397 }
    398 
    399 void PepperFlashSettingsManager::Core::InitializeOnIOThread() {
    400   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    401   DCHECK_EQ(STATE_UNINITIALIZED, state_);
    402 
    403   content::WebPluginInfo plugin_info;
    404   if (!PepperFlashSettingsManager::IsPepperFlashInUse(plugin_prefs_.get(),
    405                                                       &plugin_info)) {
    406     NotifyErrorFromIOThread();
    407     return;
    408   }
    409 
    410   base::FilePath profile_path =
    411       browser_context_path_.Append(content::kPepperDataDirname);
    412 #if defined(OS_WIN)
    413   plugin_data_path_ = profile_path.Append(plugin_info.name);
    414 #else
    415   plugin_data_path_ = profile_path.Append(UTF16ToUTF8(plugin_info.name));
    416 #endif
    417 
    418   helper_ = content::PepperFlashSettingsHelper::Create();
    419   content::PepperFlashSettingsHelper::OpenChannelCallback callback =
    420       base::Bind(&Core::ConnectToChannel, this);
    421   helper_->OpenChannelToBroker(plugin_info.path, callback);
    422 }
    423 
    424 void PepperFlashSettingsManager::Core::DeauthorizeContentLicensesOnIOThread(
    425     uint32 request_id) {
    426   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    427   DCHECK_NE(STATE_DETACHED, state_);
    428 
    429   if (state_ == STATE_UNINITIALIZED) {
    430     PendingRequest request;
    431     request.id = request_id;
    432     request.type = DEAUTHORIZE_CONTENT_LICENSES;
    433     pending_requests_.push_back(request);
    434     return;
    435   }
    436 
    437   pending_responses_.insert(
    438       std::make_pair(request_id, DEAUTHORIZE_CONTENT_LICENSES));
    439   if (state_ == STATE_ERROR) {
    440     NotifyErrorFromIOThread();
    441     return;
    442   }
    443 
    444 #if defined(OS_CHROMEOS)
    445   BrowserThread::PostBlockingPoolTask(FROM_HERE,
    446       base::Bind(&Core::DeauthorizeContentLicensesOnBlockingPool, this,
    447                  request_id, browser_context_path_));
    448 #else
    449   DeauthorizeContentLicensesInPlugin(request_id, true);
    450 #endif
    451 }
    452 
    453 // TODO(raymes): This is temporary code to migrate ChromeOS devices to the new
    454 // scheme for generating device IDs. Delete this once we are sure most ChromeOS
    455 // devices have been migrated.
    456 void PepperFlashSettingsManager::Core::DeauthorizeContentLicensesOnBlockingPool(
    457     uint32 request_id,
    458     const base::FilePath& profile_path) {
    459   // ChromeOS used to store the device ID in a file but this is no longer used.
    460   // Wipe that file.
    461   const base::FilePath& device_id_path =
    462       chrome::DeviceIDFetcher::GetLegacyDeviceIDPath(profile_path);
    463   bool success = base::DeleteFile(device_id_path, false);
    464 
    465   BrowserThread::PostTask(
    466       BrowserThread::IO, FROM_HERE,
    467       base::Bind(&Core::DeauthorizeContentLicensesInPlugin, this, request_id,
    468                  success));
    469 }
    470 
    471 void PepperFlashSettingsManager::Core::DeauthorizeContentLicensesInPlugin(
    472     uint32 request_id,
    473     bool success) {
    474   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    475   if (!success) {
    476     NotifyErrorFromIOThread();
    477     return;
    478   }
    479   IPC::Message* msg =
    480       new PpapiMsg_DeauthorizeContentLicenses(request_id, plugin_data_path_);
    481   if (!channel_->Send(msg)) {
    482     DLOG(ERROR) << "Couldn't send DeauthorizeContentLicenses message";
    483     // A failure notification for the current request will be sent since
    484     // |pending_responses_| has been updated.
    485     NotifyErrorFromIOThread();
    486   }
    487 }
    488 
    489 void PepperFlashSettingsManager::Core::GetPermissionSettingsOnIOThread(
    490     uint32 request_id,
    491     PP_Flash_BrowserOperations_SettingType setting_type) {
    492   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    493   DCHECK_NE(STATE_DETACHED, state_);
    494 
    495   if (state_ == STATE_UNINITIALIZED) {
    496     PendingRequest request;
    497     request.id = request_id;
    498     request.type = GET_PERMISSION_SETTINGS;
    499     request.setting_type = setting_type;
    500     pending_requests_.push_back(request);
    501     return;
    502   }
    503 
    504   pending_responses_.insert(
    505       std::make_pair(request_id, GET_PERMISSION_SETTINGS));
    506   if (state_ == STATE_ERROR) {
    507     NotifyErrorFromIOThread();
    508     return;
    509   }
    510 
    511   IPC::Message* msg = new PpapiMsg_GetPermissionSettings(
    512       request_id, plugin_data_path_, setting_type);
    513   if (!channel_->Send(msg)) {
    514     DLOG(ERROR) << "Couldn't send GetPermissionSettings message";
    515     // A failure notification for the current request will be sent since
    516     // |pending_responses_| has been updated.
    517     NotifyErrorFromIOThread();
    518   }
    519 }
    520 
    521 void PepperFlashSettingsManager::Core::SetDefaultPermissionOnIOThread(
    522     uint32 request_id,
    523     PP_Flash_BrowserOperations_SettingType setting_type,
    524     PP_Flash_BrowserOperations_Permission permission,
    525     bool clear_site_specific) {
    526   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    527   DCHECK_NE(STATE_DETACHED, state_);
    528 
    529   if (state_ == STATE_UNINITIALIZED) {
    530     PendingRequest request;
    531     request.id = request_id;
    532     request.type = SET_DEFAULT_PERMISSION;
    533     request.setting_type = setting_type;
    534     request.permission = permission;
    535     request.clear_site_specific = clear_site_specific;
    536     pending_requests_.push_back(request);
    537     return;
    538   }
    539 
    540   pending_responses_.insert(std::make_pair(request_id, SET_DEFAULT_PERMISSION));
    541   if (state_ == STATE_ERROR) {
    542     NotifyErrorFromIOThread();
    543     return;
    544   }
    545 
    546   IPC::Message* msg = new PpapiMsg_SetDefaultPermission(
    547       request_id, plugin_data_path_, setting_type, permission,
    548       clear_site_specific);
    549   if (!channel_->Send(msg)) {
    550     DLOG(ERROR) << "Couldn't send SetDefaultPermission message";
    551     // A failure notification for the current request will be sent since
    552     // |pending_responses_| has been updated.
    553     NotifyErrorFromIOThread();
    554   }
    555 }
    556 
    557 void PepperFlashSettingsManager::Core::SetSitePermissionOnIOThread(
    558     uint32 request_id,
    559     PP_Flash_BrowserOperations_SettingType setting_type,
    560     const ppapi::FlashSiteSettings& sites) {
    561   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    562   DCHECK_NE(STATE_DETACHED, state_);
    563 
    564   if (state_ == STATE_UNINITIALIZED) {
    565     pending_requests_.push_back(PendingRequest());
    566     PendingRequest& request = pending_requests_.back();
    567     request.id = request_id;
    568     request.type = SET_SITE_PERMISSION;
    569     request.setting_type = setting_type;
    570     request.sites = sites;
    571     return;
    572   }
    573 
    574   pending_responses_.insert(std::make_pair(request_id, SET_SITE_PERMISSION));
    575   if (state_ == STATE_ERROR) {
    576     NotifyErrorFromIOThread();
    577     return;
    578   }
    579 
    580   IPC::Message* msg = new PpapiMsg_SetSitePermission(
    581       request_id, plugin_data_path_, setting_type, sites);
    582   if (!channel_->Send(msg)) {
    583     DLOG(ERROR) << "Couldn't send SetSitePermission message";
    584     // A failure notification for the current request will be sent since
    585     // |pending_responses_| has been updated.
    586     NotifyErrorFromIOThread();
    587   }
    588 }
    589 
    590 void PepperFlashSettingsManager::Core::GetSitesWithDataOnIOThread(
    591     uint32 request_id) {
    592   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    593   DCHECK_NE(STATE_DETACHED, state_);
    594 
    595   if (state_ == STATE_UNINITIALIZED) {
    596     pending_requests_.push_back(PendingRequest());
    597     PendingRequest& request = pending_requests_.back();
    598     request.id = request_id;
    599     request.type = GET_SITES_WITH_DATA;
    600     return;
    601   }
    602 
    603   pending_responses_.insert(std::make_pair(request_id, GET_SITES_WITH_DATA));
    604   if (state_ == STATE_ERROR) {
    605     NotifyErrorFromIOThread();
    606     return;
    607   }
    608 
    609   IPC::Message* msg = new PpapiMsg_GetSitesWithData(
    610       request_id, plugin_data_path_);
    611   if (!channel_->Send(msg)) {
    612     DLOG(ERROR) << "Couldn't send GetSitesWithData message";
    613     // A failure notification for the current request will be sent since
    614     // |pending_responses_| has been updated.
    615     NotifyErrorFromIOThread();
    616   }
    617 }
    618 
    619 void PepperFlashSettingsManager::Core::ClearSiteDataOnIOThread(
    620     uint32 request_id,
    621     const std::string& site,
    622     uint64 flags,
    623     uint64 max_age) {
    624   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    625   DCHECK_NE(STATE_DETACHED, state_);
    626 
    627   if (state_ == STATE_UNINITIALIZED) {
    628     pending_requests_.push_back(PendingRequest());
    629     PendingRequest& request = pending_requests_.back();
    630     request.id = request_id;
    631     request.type = CLEAR_SITE_DATA;
    632     request.site = site;
    633     request.flags = flags;
    634     request.max_age = max_age;
    635     return;
    636   }
    637 
    638   pending_responses_.insert(std::make_pair(request_id, CLEAR_SITE_DATA));
    639   if (state_ == STATE_ERROR) {
    640     NotifyErrorFromIOThread();
    641     return;
    642   }
    643 
    644   IPC::Message* msg = new PpapiMsg_ClearSiteData(
    645       request_id, plugin_data_path_, site, flags, max_age);
    646   if (!channel_->Send(msg)) {
    647     DLOG(ERROR) << "Couldn't send ClearSiteData message";
    648     // A failure notification for the current request will be sent since
    649     // |pending_responses_| has been updated.
    650     NotifyErrorFromIOThread();
    651   }
    652 }
    653 
    654 void PepperFlashSettingsManager::Core::DetachOnIOThread() {
    655   state_ = STATE_DETACHED;
    656 }
    657 
    658 void PepperFlashSettingsManager::Core::NotifyErrorFromIOThread() {
    659   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    660   if (state_ == STATE_DETACHED)
    661     return;
    662 
    663   state_ = STATE_ERROR;
    664   std::vector<std::pair<uint32, RequestType> > notifications;
    665   for (std::vector<PendingRequest>::iterator iter = pending_requests_.begin();
    666        iter != pending_requests_.end(); ++iter) {
    667     notifications.push_back(std::make_pair(iter->id, iter->type));
    668   }
    669   pending_requests_.clear();
    670   notifications.insert(notifications.end(), pending_responses_.begin(),
    671                        pending_responses_.end());
    672   pending_responses_.clear();
    673 
    674   BrowserThread::PostTask(
    675       BrowserThread::UI, FROM_HERE,
    676       base::Bind(&Core::NotifyError, this, notifications));
    677 }
    678 
    679 void
    680 PepperFlashSettingsManager::Core::NotifyDeauthorizeContentLicensesCompleted(
    681     uint32 request_id,
    682     bool success) {
    683   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    684 
    685   if (manager_.get()) {
    686     manager_->client_->OnDeauthorizeContentLicensesCompleted(
    687         request_id, success);
    688   }
    689 }
    690 
    691 void PepperFlashSettingsManager::Core::NotifyGetPermissionSettingsCompleted(
    692     uint32 request_id,
    693     bool success,
    694     PP_Flash_BrowserOperations_Permission default_permission,
    695     const ppapi::FlashSiteSettings& sites) {
    696   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    697 
    698   if (manager_.get()) {
    699     manager_->client_->OnGetPermissionSettingsCompleted(
    700         request_id, success, default_permission, sites);
    701   }
    702 }
    703 
    704 void PepperFlashSettingsManager::Core::NotifySetDefaultPermissionCompleted(
    705     uint32 request_id,
    706     bool success) {
    707   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    708 
    709   if (manager_.get()) {
    710     manager_->client_->OnSetDefaultPermissionCompleted(
    711         request_id, success);
    712   }
    713 }
    714 
    715 void PepperFlashSettingsManager::Core::NotifySetSitePermissionCompleted(
    716     uint32 request_id,
    717     bool success) {
    718   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    719 
    720   if (manager_.get()) {
    721     manager_->client_->OnSetSitePermissionCompleted(
    722         request_id, success);
    723   }
    724 }
    725 
    726 void PepperFlashSettingsManager::Core::NotifyGetSitesWithDataCompleted(
    727     uint32 request_id,
    728     const std::vector<std::string>& sites) {
    729   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    730 
    731   if (manager_.get()) {
    732     manager_->client_->OnGetSitesWithDataCompleted(
    733         request_id, sites);
    734   }
    735 }
    736 
    737 void PepperFlashSettingsManager::Core::NotifyClearSiteDataCompleted(
    738     uint32 request_id,
    739     bool success) {
    740   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    741 
    742   if (manager_.get())
    743     manager_->client_->OnClearSiteDataCompleted(request_id, success);
    744 }
    745 
    746 void PepperFlashSettingsManager::Core::NotifyError(
    747     const std::vector<std::pair<uint32, RequestType> >& notifications) {
    748   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    749 
    750   scoped_refptr<Core> protector(this);
    751   for (std::vector<std::pair<uint32, RequestType> >::const_iterator iter =
    752       notifications.begin(); iter != notifications.end(); ++iter) {
    753     // Check |manager_| for each iteration in case it is destroyed in one of
    754     // the callbacks.
    755     if (!manager_.get())
    756       return;
    757 
    758     switch (iter->second) {
    759       case INVALID_REQUEST_TYPE:
    760         NOTREACHED();
    761         break;
    762       case DEAUTHORIZE_CONTENT_LICENSES:
    763         manager_->client_->OnDeauthorizeContentLicensesCompleted(
    764             iter->first, false);
    765         break;
    766       case GET_PERMISSION_SETTINGS:
    767         manager_->client_->OnGetPermissionSettingsCompleted(
    768             iter->first, false, PP_FLASH_BROWSEROPERATIONS_PERMISSION_DEFAULT,
    769             ppapi::FlashSiteSettings());
    770         break;
    771       case SET_DEFAULT_PERMISSION:
    772         manager_->client_->OnSetDefaultPermissionCompleted(
    773             iter->first, false);
    774         break;
    775       case SET_SITE_PERMISSION:
    776         manager_->client_->OnSetSitePermissionCompleted(iter->first, false);
    777         break;
    778       case GET_SITES_WITH_DATA:
    779         manager_->client_->OnGetSitesWithDataCompleted(
    780             iter->first, std::vector<std::string>());
    781         break;
    782       case CLEAR_SITE_DATA:
    783         manager_->client_->OnClearSiteDataCompleted(iter->first, false);
    784         break;
    785     }
    786   }
    787 
    788   if (manager_.get())
    789     manager_->OnError(this);
    790 }
    791 
    792 void PepperFlashSettingsManager::Core::OnDeauthorizeContentLicensesResult(
    793     uint32 request_id,
    794     bool success) {
    795   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    796   if (state_ == STATE_DETACHED)
    797     return;
    798 
    799   DLOG_IF(ERROR, !success) << "DeauthorizeContentLicenses returned error";
    800 
    801   std::map<uint32, RequestType>::iterator iter =
    802       pending_responses_.find(request_id);
    803   if (iter == pending_responses_.end())
    804     return;
    805 
    806   DCHECK_EQ(iter->second, DEAUTHORIZE_CONTENT_LICENSES);
    807 
    808   pending_responses_.erase(iter);
    809   BrowserThread::PostTask(
    810       BrowserThread::UI, FROM_HERE,
    811       base::Bind(&Core::NotifyDeauthorizeContentLicensesCompleted, this,
    812                  request_id, success));
    813 }
    814 
    815 void PepperFlashSettingsManager::Core::OnGetPermissionSettingsResult(
    816     uint32 request_id,
    817     bool success,
    818     PP_Flash_BrowserOperations_Permission default_permission,
    819     const ppapi::FlashSiteSettings& sites) {
    820   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    821   if (state_ == STATE_DETACHED)
    822     return;
    823 
    824   DLOG_IF(ERROR, !success) << "GetPermissionSettings returned error";
    825 
    826   std::map<uint32, RequestType>::iterator iter =
    827       pending_responses_.find(request_id);
    828   if (iter == pending_responses_.end())
    829     return;
    830 
    831   DCHECK_EQ(iter->second, GET_PERMISSION_SETTINGS);
    832 
    833   pending_responses_.erase(iter);
    834   BrowserThread::PostTask(
    835       BrowserThread::UI, FROM_HERE,
    836       base::Bind(&Core::NotifyGetPermissionSettingsCompleted, this,
    837                  request_id, success, default_permission, sites));
    838 }
    839 
    840 void PepperFlashSettingsManager::Core::OnSetDefaultPermissionResult(
    841     uint32 request_id,
    842     bool success) {
    843   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    844   if (state_ == STATE_DETACHED)
    845     return;
    846 
    847   DLOG_IF(ERROR, !success) << "SetDefaultPermission returned error";
    848 
    849   std::map<uint32, RequestType>::iterator iter =
    850       pending_responses_.find(request_id);
    851   if (iter == pending_responses_.end())
    852     return;
    853 
    854   DCHECK_EQ(iter->second, SET_DEFAULT_PERMISSION);
    855 
    856   pending_responses_.erase(iter);
    857   BrowserThread::PostTask(
    858       BrowserThread::UI, FROM_HERE,
    859       base::Bind(&Core::NotifySetDefaultPermissionCompleted, this,
    860                  request_id, success));
    861 }
    862 
    863 void PepperFlashSettingsManager::Core::OnSetSitePermissionResult(
    864     uint32 request_id,
    865     bool success) {
    866   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    867   if (state_ == STATE_DETACHED)
    868     return;
    869 
    870   DLOG_IF(ERROR, !success) << "SetSitePermission returned error";
    871 
    872   std::map<uint32, RequestType>::iterator iter =
    873       pending_responses_.find(request_id);
    874   if (iter == pending_responses_.end())
    875     return;
    876 
    877   DCHECK_EQ(iter->second, SET_SITE_PERMISSION);
    878 
    879   pending_responses_.erase(iter);
    880   BrowserThread::PostTask(
    881       BrowserThread::UI, FROM_HERE,
    882       base::Bind(&Core::NotifySetSitePermissionCompleted, this, request_id,
    883       success));
    884 }
    885 
    886 void PepperFlashSettingsManager::Core::OnGetSitesWithDataResult(
    887     uint32 request_id,
    888     const std::vector<std::string>& sites) {
    889   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    890   if (state_ == STATE_DETACHED)
    891     return;
    892 
    893   std::map<uint32, RequestType>::iterator iter =
    894       pending_responses_.find(request_id);
    895   if (iter == pending_responses_.end())
    896     return;
    897 
    898   DCHECK_EQ(iter->second, GET_SITES_WITH_DATA);
    899 
    900   pending_responses_.erase(iter);
    901   BrowserThread::PostTask(
    902       BrowserThread::UI, FROM_HERE,
    903       base::Bind(&Core::NotifyGetSitesWithDataCompleted, this, request_id,
    904       sites));
    905 }
    906 
    907 void PepperFlashSettingsManager::Core::OnClearSiteDataResult(
    908     uint32 request_id,
    909     bool success) {
    910   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    911   if (state_ == STATE_DETACHED)
    912     return;
    913 
    914   DLOG_IF(ERROR, !success) << "ClearSiteData returned error";
    915 
    916   std::map<uint32, RequestType>::iterator iter =
    917       pending_responses_.find(request_id);
    918   if (iter == pending_responses_.end())
    919     return;
    920 
    921   DCHECK_EQ(iter->second, CLEAR_SITE_DATA);
    922 
    923   pending_responses_.erase(iter);
    924   BrowserThread::PostTask(
    925       BrowserThread::UI, FROM_HERE,
    926       base::Bind(&Core::NotifyClearSiteDataCompleted, this, request_id,
    927       success));
    928 }
    929 
    930 PepperFlashSettingsManager::PepperFlashSettingsManager(
    931     Client* client,
    932     content::BrowserContext* browser_context)
    933     : client_(client),
    934       browser_context_(browser_context),
    935       next_request_id_(1),
    936       weak_ptr_factory_(this) {
    937   DCHECK(client);
    938   DCHECK(browser_context);
    939 }
    940 
    941 PepperFlashSettingsManager::~PepperFlashSettingsManager() {
    942   if (core_.get())
    943     core_->Detach();
    944 }
    945 
    946 // static
    947 bool PepperFlashSettingsManager::IsPepperFlashInUse(
    948     PluginPrefs* plugin_prefs,
    949     content::WebPluginInfo* plugin_info) {
    950   if (!plugin_prefs)
    951     return false;
    952 
    953   content::PluginService* plugin_service =
    954       content::PluginService::GetInstance();
    955   std::vector<content::WebPluginInfo> plugins;
    956   plugin_service->GetPluginInfoArray(
    957       GURL(), content::kFlashPluginSwfMimeType, false, &plugins, NULL);
    958 
    959   for (std::vector<content::WebPluginInfo>::iterator iter = plugins.begin();
    960        iter != plugins.end(); ++iter) {
    961     if (iter->is_pepper_plugin() && plugin_prefs->IsPluginEnabled(*iter)) {
    962       if (plugin_info)
    963         *plugin_info = *iter;
    964       return true;
    965     }
    966   }
    967   return false;
    968 }
    969 
    970 // static
    971 void PepperFlashSettingsManager::RegisterProfilePrefs(
    972     user_prefs::PrefRegistrySyncable* registry) {
    973   registry->RegisterBooleanPref(
    974       prefs::kDeauthorizeContentLicenses,
    975       false,
    976       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
    977 
    978   registry->RegisterBooleanPref(
    979       prefs::kPepperFlashSettingsEnabled,
    980       true,
    981       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
    982 }
    983 
    984 uint32 PepperFlashSettingsManager::DeauthorizeContentLicenses(
    985     PrefService* prefs) {
    986   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    987 
    988   // Clear the device ID salt which has the effect of regenerating a device
    989   // ID. Since this happens synchronously (and on the UI thread), we don't have
    990   // to add it to a pending request.
    991   prefs->ClearPref(prefs::kDRMSalt);
    992 
    993   EnsureCoreExists();
    994   uint32 id = GetNextRequestId();
    995   core_->DeauthorizeContentLicenses(id);
    996   return id;
    997 }
    998 
    999 uint32 PepperFlashSettingsManager::GetPermissionSettings(
   1000     PP_Flash_BrowserOperations_SettingType setting_type) {
   1001   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   1002 
   1003   EnsureCoreExists();
   1004   uint32 id = GetNextRequestId();
   1005   core_->GetPermissionSettings(id, setting_type);
   1006   return id;
   1007 }
   1008 
   1009 uint32 PepperFlashSettingsManager::SetDefaultPermission(
   1010     PP_Flash_BrowserOperations_SettingType setting_type,
   1011     PP_Flash_BrowserOperations_Permission permission,
   1012     bool clear_site_specific) {
   1013   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   1014 
   1015   EnsureCoreExists();
   1016   uint32 id = GetNextRequestId();
   1017   core_->SetDefaultPermission(id, setting_type, permission,
   1018                               clear_site_specific);
   1019   return id;
   1020 }
   1021 
   1022 uint32 PepperFlashSettingsManager::SetSitePermission(
   1023     PP_Flash_BrowserOperations_SettingType setting_type,
   1024     const ppapi::FlashSiteSettings& sites) {
   1025   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   1026 
   1027   EnsureCoreExists();
   1028   uint32 id = GetNextRequestId();
   1029   core_->SetSitePermission(id, setting_type, sites);
   1030   return id;
   1031 }
   1032 
   1033 uint32 PepperFlashSettingsManager::GetSitesWithData() {
   1034   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   1035 
   1036   EnsureCoreExists();
   1037   uint32 id = GetNextRequestId();
   1038   core_->GetSitesWithData(id);
   1039   return id;
   1040 }
   1041 
   1042 uint32 PepperFlashSettingsManager::ClearSiteData(const std::string& site,
   1043                                                  uint64 flags,
   1044                                                  uint64 max_age) {
   1045   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   1046 
   1047   EnsureCoreExists();
   1048   uint32 id = GetNextRequestId();
   1049   core_->ClearSiteData(id, site, flags, max_age);
   1050   return id;
   1051 }
   1052 
   1053 uint32 PepperFlashSettingsManager::GetNextRequestId() {
   1054   return next_request_id_++;
   1055 }
   1056 
   1057 void PepperFlashSettingsManager::EnsureCoreExists() {
   1058   if (!core_.get()) {
   1059     core_ = new Core(weak_ptr_factory_.GetWeakPtr(), browser_context_);
   1060     core_->Initialize();
   1061   }
   1062 }
   1063 
   1064 void PepperFlashSettingsManager::OnError(Core* core) {
   1065   DCHECK(core);
   1066   if (core != core_.get())
   1067     return;
   1068 
   1069   core_->Detach();
   1070   core_ = NULL;
   1071 }
   1072