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/files/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/pref_registry/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
33using content::BrowserThread;
34
35class 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
212PepperFlashSettingsManager::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
223PepperFlashSettingsManager::Core::~Core() {
224  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
225}
226
227void PepperFlashSettingsManager::Core::Initialize() {
228  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
229  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
230                          base::Bind(&Core::InitializeOnIOThread, this));
231}
232
233void 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
245void 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
255void 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
266void 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
279void 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
291void 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
299void 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
311bool 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
332void PepperFlashSettingsManager::Core::OnChannelError() {
333  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
334  if (state_ == STATE_DETACHED)
335    return;
336
337  NotifyErrorFromIOThread();
338}
339
340void 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_ = IPC::Channel::CreateClient(handle, 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
399void 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(base::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
424void 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.
456void 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
471void 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
489void 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
521void 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
557void 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
590void 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
619void 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
654void PepperFlashSettingsManager::Core::DetachOnIOThread() {
655  state_ = STATE_DETACHED;
656}
657
658void 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
679void
680PepperFlashSettingsManager::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
691void 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
704void 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
715void 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
726void 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
737void 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
746void 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
792void 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
815void 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
840void 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
863void 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
886void 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
907void 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
930PepperFlashSettingsManager::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
941PepperFlashSettingsManager::~PepperFlashSettingsManager() {
942  if (core_.get())
943    core_->Detach();
944}
945
946// static
947bool 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
971void 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
984uint32 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
999uint32 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
1009uint32 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
1022uint32 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
1033uint32 PepperFlashSettingsManager::GetSitesWithData() {
1034  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1035
1036  EnsureCoreExists();
1037  uint32 id = GetNextRequestId();
1038  core_->GetSitesWithData(id);
1039  return id;
1040}
1041
1042uint32 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
1053uint32 PepperFlashSettingsManager::GetNextRequestId() {
1054  return next_request_id_++;
1055}
1056
1057void PepperFlashSettingsManager::EnsureCoreExists() {
1058  if (!core_.get()) {
1059    core_ = new Core(weak_ptr_factory_.GetWeakPtr(), browser_context_);
1060    core_->Initialize();
1061  }
1062}
1063
1064void PepperFlashSettingsManager::OnError(Core* core) {
1065  DCHECK(core);
1066  if (core != core_.get())
1067    return;
1068
1069  core_->Detach();
1070  core_ = NULL;
1071}
1072