blob: ba7192da554093ad0f185e2401066d350a48266b [file] [log] [blame]
[email protected]18a4d63c82012-05-25 23:37:031// 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
[email protected]1a559442012-05-27 07:18:467#include <map>
8#include <utility>
[email protected]18a4d63c82012-05-25 23:37:039#include <vector>
10
[email protected]1a559442012-05-27 07:18:4611#include "base/bind.h"
12#include "base/compiler_specific.h"
13#include "base/sequenced_task_runner_helpers.h"
14#include "base/utf_string_conversions.h"
[email protected]18a4d63c82012-05-25 23:37:0315#include "chrome/browser/plugin_prefs.h"
16#include "chrome/browser/prefs/pref_service.h"
[email protected]1a559442012-05-27 07:18:4617#include "chrome/browser/profiles/profile.h"
[email protected]18a4d63c82012-05-25 23:37:0318#include "chrome/common/pref_names.h"
[email protected]1a559442012-05-27 07:18:4619#include "content/public/browser/browser_context.h"
20#include "content/public/browser/browser_thread.h"
21#include "content/public/browser/pepper_flash_settings_helper.h"
[email protected]18a4d63c82012-05-25 23:37:0322#include "content/public/browser/plugin_service.h"
[email protected]1a559442012-05-27 07:18:4623#include "content/public/common/content_constants.h"
[email protected]18a4d63c82012-05-25 23:37:0324#include "googleurl/src/gurl.h"
[email protected]1a559442012-05-27 07:18:4625#include "ipc/ipc_channel.h"
26#include "ppapi/proxy/ppapi_messages.h"
[email protected]18a4d63c82012-05-25 23:37:0327#include "webkit/plugins/plugin_constants.h"
28#include "webkit/plugins/webplugininfo.h"
29
[email protected]1a559442012-05-27 07:18:4630using content::BrowserThread;
31
32class PepperFlashSettingsManager::Core
33 : public IPC::Channel::Listener,
34 public base::RefCountedThreadSafe<Core, BrowserThread::DeleteOnIOThread> {
35 public:
36 Core(PepperFlashSettingsManager* manager,
37 content::BrowserContext* browser_context);
38
39 // Stops sending notifications to |manager_| and sets it to NULL.
40 void Detach();
41
42 void DeauthorizeContentLicenses(uint32 request_id);
43
44 // IPC::Channel::Listener implementation.
45 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
46 virtual void OnChannelError() OVERRIDE;
47
48 private:
49 friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>;
50 friend class base::DeleteHelper<Core>;
51
52 enum RequestType {
53 INVALID_REQUEST_TYPE = 0,
54 DEAUTHORIZE_CONTENT_LICENSES
55 };
56
57 struct PendingRequest {
58 PendingRequest() : id(0), type(INVALID_REQUEST_TYPE) {}
59
60 uint32 id;
61 RequestType type;
62 };
63
64 virtual ~Core();
65
66 void Initialize();
67 void ConnectToChannel(bool success, const IPC::ChannelHandle& handle);
68
69 void DeauthorizeContentLicensesOnIOThread(uint32 request_id);
70 void NotifyErrorFromIOThread();
71
72 void NotifyDeauthorizeContentLicensesCompleted(uint32 request_id,
73 bool success);
74 void NotifyError(
75 const std::vector<std::pair<uint32, RequestType> >& notifications);
76
77 // Message handlers.
78 void OnDeauthorizeContentLicensesResult(uint32 request_id, bool success);
79
80 // Used only on the UI thread.
81 PepperFlashSettingsManager* manager_;
82
83 // Used only on the I/O thread.
84 FilePath plugin_data_path_;
85
86 // The channel is NULL until we have opened a connection to the broker
87 // process. Used only on the I/O thread.
88 scoped_ptr<IPC::Channel> channel_;
89
90 // Used only on the I/O thread.
91 bool initialized_;
92
93 // Requests that need to be sent once the channel to the broker process is
94 // established. Used only on the I/O thread.
95 std::vector<PendingRequest> pending_requests_;
96 // Requests that have been sent but haven't got replied. Used only on the
97 // I/O thread.
98 std::map<uint32, RequestType> pending_responses_;
99
100 // Used only on the I/O thread.
101 scoped_refptr<content::PepperFlashSettingsHelper> helper_;
102
103 // Path for the current profile. Must be retrieved on the UI thread from the
104 // browser context when we start so we can use it later on the I/O thread.
105 FilePath browser_context_path_;
106
107 scoped_refptr<PluginPrefs> plugin_prefs_;
108};
109
110PepperFlashSettingsManager::Core::Core(PepperFlashSettingsManager* manager,
111 content::BrowserContext* browser_context)
112 : manager_(manager),
113 initialized_(false),
114 browser_context_path_(browser_context->GetPath()),
115 plugin_prefs_(PluginPrefs::GetForProfile(
116 Profile::FromBrowserContext(browser_context))) {
117 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
118
119 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
120 base::Bind(&Core::Initialize, this));
121}
122
123PepperFlashSettingsManager::Core::~Core() {
124 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
125}
126
127void PepperFlashSettingsManager::Core::Detach() {
128 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
129
130 manager_ = NULL;
131}
132
133void PepperFlashSettingsManager::Core::DeauthorizeContentLicenses(
134 uint32 request_id) {
135 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
136
137 BrowserThread::PostTask(
138 BrowserThread::IO, FROM_HERE,
139 base::Bind(&Core::DeauthorizeContentLicensesOnIOThread, this,
140 request_id));
141}
142
143bool PepperFlashSettingsManager::Core::OnMessageReceived(
144 const IPC::Message& message) {
145 IPC_BEGIN_MESSAGE_MAP(Core, message)
146 IPC_MESSAGE_HANDLER(PpapiHostMsg_DeauthorizeContentLicensesResult,
147 OnDeauthorizeContentLicensesResult)
148 IPC_MESSAGE_UNHANDLED_ERROR()
149 IPC_END_MESSAGE_MAP()
150
151 return true;
152}
153
154void PepperFlashSettingsManager::Core::OnChannelError() {
155 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
156
157 NotifyErrorFromIOThread();
158}
159
160void PepperFlashSettingsManager::Core::Initialize() {
161 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
162 DCHECK(!initialized_);
163
164 webkit::WebPluginInfo plugin_info;
165 if (!PepperFlashSettingsManager::IsPepperFlashInUse(plugin_prefs_.get(),
166 &plugin_info)) {
167 NotifyErrorFromIOThread();
168 return;
169 }
170
171 FilePath profile_path =
172 browser_context_path_.Append(content::kPepperDataDirname);
173#if defined(OS_WIN)
174 plugin_data_path_ = profile_path.Append(plugin_info.name);
175#else
176 plugin_data_path_ = profile_path.Append(UTF16ToUTF8(plugin_info.name));
177#endif
178
179 helper_ = content::PepperFlashSettingsHelper::Create();
180 content::PepperFlashSettingsHelper::OpenChannelCallback callback =
181 base::Bind(&Core::ConnectToChannel, this);
182 helper_->OpenChannelToBroker(plugin_info.path, callback);
183}
184
185void PepperFlashSettingsManager::Core::ConnectToChannel(
186 bool success,
187 const IPC::ChannelHandle& handle) {
188 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
189 DCHECK(!initialized_);
190 DCHECK(!channel_.get());
191
192 if (!success) {
193 LOG(ERROR) << "Couldn't open plugin channel";
194 NotifyErrorFromIOThread();
195 return;
196 }
197
198 channel_.reset(new IPC::Channel(handle, IPC::Channel::MODE_CLIENT, this));
199 if (!channel_->Connect()) {
200 LOG(ERROR) << "Couldn't connect to plugin";
201 NotifyErrorFromIOThread();
202 return;
203 }
204
205 initialized_ = true;
206
207 std::vector<PendingRequest> temp_pending_requests;
208 temp_pending_requests.swap(pending_requests_);
209 for (std::vector<PendingRequest>::iterator iter =
210 temp_pending_requests.begin();
211 iter != temp_pending_requests.end(); ++iter) {
212 switch (iter->type) {
213 case DEAUTHORIZE_CONTENT_LICENSES:
214 DeauthorizeContentLicensesOnIOThread(iter->id);
215 break;
216 default:
217 NOTREACHED();
218 break;
219 }
220 }
221}
222
223void PepperFlashSettingsManager::Core::DeauthorizeContentLicensesOnIOThread(
224 uint32 request_id) {
225 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
226
227 if (!initialized_) {
228 PendingRequest request;
229 request.id = request_id;
230 request.type = DEAUTHORIZE_CONTENT_LICENSES;
231 pending_requests_.push_back(request);
232 return;
233 }
234
235 pending_responses_.insert(
236 std::make_pair(request_id, DEAUTHORIZE_CONTENT_LICENSES));
237 IPC::Message* msg =
238 new PpapiMsg_DeauthorizeContentLicenses(request_id, plugin_data_path_);
239 if (!channel_->Send(msg)) {
240 LOG(ERROR) << "Couldn't send DeauthorizeContentLicenses message";
241 // A failure notification for the current request will be sent since
242 // |pending_responses_| has been updated.
243 NotifyErrorFromIOThread();
244 }
245}
246
247void PepperFlashSettingsManager::Core::NotifyErrorFromIOThread() {
248 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
249
250 std::vector<std::pair<uint32, RequestType> > notifications;
251 for (std::vector<PendingRequest>::iterator iter = pending_requests_.begin();
252 iter != pending_requests_.end(); ++iter) {
253 notifications.push_back(std::make_pair(iter->id, iter->type));
254 }
255 pending_requests_.clear();
256 notifications.insert(notifications.end(), pending_responses_.begin(),
257 pending_responses_.end());
258 pending_responses_.clear();
259
260 BrowserThread::PostTask(
261 BrowserThread::UI, FROM_HERE,
262 base::Bind(&Core::NotifyError, this, notifications));
263}
264
265void
266PepperFlashSettingsManager::Core::NotifyDeauthorizeContentLicensesCompleted(
267 uint32 request_id,
268 bool success) {
269 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
270
271 if (manager_) {
272 manager_->client_->OnDeauthorizeContentLicensesCompleted(
273 request_id, success);
274 }
275}
276
277void PepperFlashSettingsManager::Core::NotifyError(
278 const std::vector<std::pair<uint32, RequestType> >& notifications) {
279 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
280
281 scoped_refptr<Core> protector(this);
282 for (std::vector<std::pair<uint32, RequestType> >::const_iterator iter =
283 notifications.begin(); iter != notifications.end(); ++iter) {
284 // Check |manager_| for each iteration in case Detach() happens in one of
285 // the callbacks.
286 if (manager_) {
287 switch (iter->second) {
288 case DEAUTHORIZE_CONTENT_LICENSES:
289 manager_->client_->OnDeauthorizeContentLicensesCompleted(iter->first,
290 false);
291 break;
292 default:
293 NOTREACHED();
294 break;
295 }
296 }
297 }
298
299 if (manager_)
300 manager_->OnError();
301}
302
303void PepperFlashSettingsManager::Core::OnDeauthorizeContentLicensesResult(
304 uint32 request_id,
305 bool success) {
306 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
307 LOG_IF(ERROR, !success) << "DeauthorizeContentLicenses returned error";
308
309 std::map<uint32, RequestType>::iterator iter =
310 pending_responses_.find(request_id);
311 if (iter != pending_responses_.end()) {
312 DCHECK_EQ(iter->second, DEAUTHORIZE_CONTENT_LICENSES);
313
314 pending_responses_.erase(iter);
315 BrowserThread::PostTask(
316 BrowserThread::UI, FROM_HERE,
317 base::Bind(&Core::NotifyDeauthorizeContentLicensesCompleted, this,
318 request_id, success));
319 }
320}
321
322PepperFlashSettingsManager::PepperFlashSettingsManager(
323 Client* client,
324 content::BrowserContext* browser_context)
325 : client_(client),
326 browser_context_(browser_context),
327 next_request_id_(1) {
328 DCHECK(client);
329 DCHECK(browser_context);
330}
331
332PepperFlashSettingsManager::~PepperFlashSettingsManager() {
333 if (core_.get()) {
334 core_->Detach();
335 core_ = NULL;
336 }
337}
338
[email protected]18a4d63c82012-05-25 23:37:03339// static
340bool PepperFlashSettingsManager::IsPepperFlashInUse(
341 PluginPrefs* plugin_prefs,
342 webkit::WebPluginInfo* plugin_info) {
343 if (!plugin_prefs)
344 return false;
345
346 content::PluginService* plugin_service =
347 content::PluginService::GetInstance();
348 std::vector<webkit::WebPluginInfo> plugins;
349 plugin_service->GetPluginInfoArray(
350 GURL(), kFlashPluginSwfMimeType, false, &plugins, NULL);
351
352 for (std::vector<webkit::WebPluginInfo>::iterator iter = plugins.begin();
353 iter != plugins.end(); ++iter) {
354 if (webkit::IsPepperPlugin(*iter) && plugin_prefs->IsPluginEnabled(*iter)) {
355 if (plugin_info)
356 *plugin_info = *iter;
357 return true;
358 }
359 }
360 return false;
361}
362
363// static
364void PepperFlashSettingsManager::RegisterUserPrefs(PrefService* prefs) {
365 prefs->RegisterBooleanPref(prefs::kDeauthorizeContentLicenses,
366 false,
367 PrefService::UNSYNCABLE_PREF);
368
369 prefs->RegisterBooleanPref(prefs::kPepperFlashSettingsEnabled,
370 true,
371 PrefService::UNSYNCABLE_PREF);
372}
[email protected]1a559442012-05-27 07:18:46373
374uint32 PepperFlashSettingsManager::DeauthorizeContentLicenses() {
375 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
376
377 EnsureCoreExists();
378 uint32 id = GetNextRequestId();
379 core_->DeauthorizeContentLicenses(id);
380 return id;
381}
382
383uint32 PepperFlashSettingsManager::GetNextRequestId() {
384 return next_request_id_++;
385}
386
387void PepperFlashSettingsManager::EnsureCoreExists() {
388 if (!core_.get())
389 core_ = new Core(this, browser_context_);
390}
391
392void PepperFlashSettingsManager::OnError() {
393 if (core_.get()) {
394 core_->Detach();
395 core_ = NULL;
396 } else {
397 NOTREACHED();
398 }
399}
400