- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / pepper_flash_settings_manager.cc
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 }