broker_process_dispatcher.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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 "content/ppapi_plugin/broker_process_dispatcher.h"
6
7#include "base/bind.h"
8#include "base/bind_helpers.h"
9#include "base/memory/scoped_ptr.h"
10#include "base/utf_string_conversions.h"
11#include "content/common/child_process.h"
12#include "ppapi/c/pp_bool.h"
13#include "ppapi/c/private/ppp_flash_browser_operations.h"
14#include "ppapi/proxy/ppapi_messages.h"
15
16namespace content {
17namespace {
18
19// How long we wait before releasing the broker process.
20const int kBrokerReleaseTimeSeconds = 30;
21
22std::string ConvertPluginDataPath(const FilePath& plugin_data_path) {
23  // The string is always 8-bit, convert on Windows.
24#if defined(OS_WIN)
25  return WideToUTF8(plugin_data_path.value());
26#else
27  return plugin_data_path.value();
28#endif
29}
30
31struct GetPermissionSettingsContext {
32  GetPermissionSettingsContext(
33      const base::WeakPtr<BrokerProcessDispatcher> in_dispatcher,
34      uint32 in_request_id)
35      : dispatcher(in_dispatcher),
36        request_id(in_request_id) {
37  }
38
39  base::WeakPtr<BrokerProcessDispatcher> dispatcher;
40  uint32 request_id;
41};
42
43void GetPermissionSettingsCallback(
44    void* user_data,
45    PP_Bool success,
46    PP_Flash_BrowserOperations_Permission default_permission,
47    uint32_t site_count,
48    const PP_Flash_BrowserOperations_SiteSetting sites[]) {
49  scoped_ptr<GetPermissionSettingsContext> context(
50      reinterpret_cast<GetPermissionSettingsContext*>(user_data));
51
52  if (!context->dispatcher)
53    return;
54
55  ppapi::FlashSiteSettings site_vector;
56  if (success) {
57    site_vector.reserve(site_count);
58    for (uint32_t i = 0; i < site_count; ++i) {
59      if (!sites[i].site) {
60        success = PP_FALSE;
61        break;
62      }
63      site_vector.push_back(
64          ppapi::FlashSiteSetting(sites[i].site, sites[i].permission));
65    }
66
67    if (!success)
68      site_vector.clear();
69  }
70  context->dispatcher->OnGetPermissionSettingsCompleted(
71      context->request_id, PP_ToBool(success), default_permission, site_vector);
72}
73
74}  // namespace
75
76BrokerProcessDispatcher::BrokerProcessDispatcher(
77    PP_GetInterface_Func get_plugin_interface,
78    PP_ConnectInstance_Func connect_instance)
79    : ppapi::proxy::BrokerSideDispatcher(connect_instance),
80      get_plugin_interface_(get_plugin_interface),
81      flash_browser_operations_1_3_(NULL),
82      flash_browser_operations_1_2_(NULL),
83      flash_browser_operations_1_0_(NULL) {
84  ChildProcess::current()->AddRefProcess();
85
86  if (get_plugin_interface) {
87    flash_browser_operations_1_0_ =
88        static_cast<const PPP_Flash_BrowserOperations_1_0*>(
89            get_plugin_interface_(PPP_FLASH_BROWSEROPERATIONS_INTERFACE_1_0));
90
91    flash_browser_operations_1_2_ =
92        static_cast<const PPP_Flash_BrowserOperations_1_2*>(
93            get_plugin_interface_(PPP_FLASH_BROWSEROPERATIONS_INTERFACE_1_2));
94
95    flash_browser_operations_1_3_ =
96        static_cast<const PPP_Flash_BrowserOperations_1_3*>(
97            get_plugin_interface_(PPP_FLASH_BROWSEROPERATIONS_INTERFACE_1_3));
98  }
99}
100
101BrokerProcessDispatcher::~BrokerProcessDispatcher() {
102  DVLOG(1) << "BrokerProcessDispatcher::~BrokerProcessDispatcher()";
103  // Don't free the process right away. This timer allows the child process
104  // to be re-used if the user rapidly goes to a new page that requires this
105  // plugin. This is the case for common plugins where they may be used on a
106  // source and destination page of a navigation. We don't want to tear down
107  // and re-start processes each time in these cases.
108  MessageLoop::current()->PostDelayedTask(
109      FROM_HERE,
110      base::Bind(&ChildProcess::ReleaseProcess,
111                 base::Unretained(ChildProcess::current())),
112      base::TimeDelta::FromSeconds(kBrokerReleaseTimeSeconds));
113}
114
115bool BrokerProcessDispatcher::OnMessageReceived(const IPC::Message& msg) {
116  IPC_BEGIN_MESSAGE_MAP(BrokerProcessDispatcher, msg)
117    IPC_MESSAGE_HANDLER(PpapiMsg_GetSitesWithData, OnMsgGetSitesWithData)
118    IPC_MESSAGE_HANDLER(PpapiMsg_ClearSiteData, OnMsgClearSiteData)
119    IPC_MESSAGE_HANDLER(PpapiMsg_DeauthorizeContentLicenses,
120                        OnMsgDeauthorizeContentLicenses)
121    IPC_MESSAGE_HANDLER(PpapiMsg_GetPermissionSettings,
122                        OnMsgGetPermissionSettings)
123    IPC_MESSAGE_HANDLER(PpapiMsg_SetDefaultPermission,
124                        OnMsgSetDefaultPermission)
125    IPC_MESSAGE_HANDLER(PpapiMsg_SetSitePermission, OnMsgSetSitePermission)
126    IPC_MESSAGE_UNHANDLED(return BrokerSideDispatcher::OnMessageReceived(msg))
127  IPC_END_MESSAGE_MAP()
128  return true;
129}
130
131void BrokerProcessDispatcher::OnGetPermissionSettingsCompleted(
132    uint32 request_id,
133    bool success,
134    PP_Flash_BrowserOperations_Permission default_permission,
135    const ppapi::FlashSiteSettings& sites) {
136  Send(new PpapiHostMsg_GetPermissionSettingsResult(
137      request_id, success, default_permission, sites));
138}
139
140void BrokerProcessDispatcher::OnMsgGetSitesWithData(
141    uint32 request_id,
142    const FilePath& plugin_data_path) {
143  std::vector<std::string> sites;
144  GetSitesWithData(plugin_data_path, &sites);
145  Send(new PpapiHostMsg_GetSitesWithDataResult(request_id, sites));
146}
147
148void BrokerProcessDispatcher::OnMsgClearSiteData(
149    uint32 request_id,
150    const FilePath& plugin_data_path,
151    const std::string& site,
152    uint64 flags,
153    uint64 max_age) {
154  Send(new PpapiHostMsg_ClearSiteDataResult(
155      request_id, ClearSiteData(plugin_data_path, site, flags, max_age)));
156}
157
158void BrokerProcessDispatcher::OnMsgDeauthorizeContentLicenses(
159    uint32 request_id,
160    const FilePath& plugin_data_path) {
161  Send(new PpapiHostMsg_DeauthorizeContentLicensesResult(
162      request_id, DeauthorizeContentLicenses(plugin_data_path)));
163}
164
165void BrokerProcessDispatcher::OnMsgGetPermissionSettings(
166    uint32 request_id,
167    const FilePath& plugin_data_path,
168    PP_Flash_BrowserOperations_SettingType setting_type) {
169  if (flash_browser_operations_1_3_) {
170    std::string data_str = ConvertPluginDataPath(plugin_data_path);
171    // The GetPermissionSettingsContext object will be deleted in
172    // GetPermissionSettingsCallback().
173    flash_browser_operations_1_3_->GetPermissionSettings(
174        data_str.c_str(), setting_type, &GetPermissionSettingsCallback,
175        new GetPermissionSettingsContext(AsWeakPtr(), request_id));
176    return;
177  }
178
179  if (flash_browser_operations_1_2_) {
180    std::string data_str = ConvertPluginDataPath(plugin_data_path);
181    // The GetPermissionSettingsContext object will be deleted in
182    // GetPermissionSettingsCallback().
183    flash_browser_operations_1_2_->GetPermissionSettings(
184        data_str.c_str(), setting_type, &GetPermissionSettingsCallback,
185        new GetPermissionSettingsContext(AsWeakPtr(), request_id));
186    return;
187  }
188
189  OnGetPermissionSettingsCompleted(
190      request_id, false, PP_FLASH_BROWSEROPERATIONS_PERMISSION_DEFAULT,
191      ppapi::FlashSiteSettings());
192  return;
193}
194
195void BrokerProcessDispatcher::OnMsgSetDefaultPermission(
196    uint32 request_id,
197    const FilePath& plugin_data_path,
198    PP_Flash_BrowserOperations_SettingType setting_type,
199    PP_Flash_BrowserOperations_Permission permission,
200    bool clear_site_specific) {
201  Send(new PpapiHostMsg_SetDefaultPermissionResult(
202      request_id,
203      SetDefaultPermission(plugin_data_path, setting_type, permission,
204                           clear_site_specific)));
205}
206
207void BrokerProcessDispatcher::OnMsgSetSitePermission(
208    uint32 request_id,
209    const FilePath& plugin_data_path,
210    PP_Flash_BrowserOperations_SettingType setting_type,
211    const ppapi::FlashSiteSettings& sites) {
212  Send(new PpapiHostMsg_SetSitePermissionResult(
213      request_id, SetSitePermission(plugin_data_path, setting_type, sites)));
214}
215
216void BrokerProcessDispatcher::GetSitesWithData(
217    const FilePath& plugin_data_path,
218    std::vector<std::string>* site_vector) {
219  std::string data_str = ConvertPluginDataPath(plugin_data_path);
220  if (flash_browser_operations_1_3_) {
221    char** sites = NULL;
222    flash_browser_operations_1_3_->GetSitesWithData(data_str.c_str(), &sites);
223    if (!sites)
224      return;
225
226    for (size_t i = 0; sites[i]; ++i)
227      site_vector->push_back(sites[i]);
228
229    flash_browser_operations_1_3_->FreeSiteList(sites);
230  }
231}
232
233bool BrokerProcessDispatcher::ClearSiteData(const FilePath& plugin_data_path,
234                                            const std::string& site,
235                                            uint64 flags,
236                                            uint64 max_age) {
237  std::string data_str = ConvertPluginDataPath(plugin_data_path);
238  if (flash_browser_operations_1_3_) {
239    flash_browser_operations_1_3_->ClearSiteData(
240        data_str.c_str(), site.empty() ? NULL : site.c_str(), flags, max_age);
241    return true;
242  }
243
244  // TODO(viettrungluu): Remove this (and the 1.0 interface) sometime after M21
245  // goes to Stable.
246  if (flash_browser_operations_1_2_) {
247    flash_browser_operations_1_2_->ClearSiteData(
248        data_str.c_str(), site.empty() ? NULL : site.c_str(), flags, max_age);
249    return true;
250  }
251
252  if (flash_browser_operations_1_0_) {
253    flash_browser_operations_1_0_->ClearSiteData(
254        data_str.c_str(), site.empty() ? NULL : site.c_str(), flags, max_age);
255    return true;
256  }
257
258  return false;
259}
260
261bool BrokerProcessDispatcher::DeauthorizeContentLicenses(
262    const FilePath& plugin_data_path) {
263  if (flash_browser_operations_1_3_) {
264    std::string data_str = ConvertPluginDataPath(plugin_data_path);
265    return PP_ToBool(flash_browser_operations_1_3_->DeauthorizeContentLicenses(
266        data_str.c_str()));
267  }
268
269  if (flash_browser_operations_1_2_) {
270    std::string data_str = ConvertPluginDataPath(plugin_data_path);
271    return PP_ToBool(flash_browser_operations_1_2_->DeauthorizeContentLicenses(
272        data_str.c_str()));
273  }
274
275  return false;
276}
277
278bool BrokerProcessDispatcher::SetDefaultPermission(
279    const FilePath& plugin_data_path,
280    PP_Flash_BrowserOperations_SettingType setting_type,
281    PP_Flash_BrowserOperations_Permission permission,
282    bool clear_site_specific) {
283  if (flash_browser_operations_1_3_) {
284    std::string data_str = ConvertPluginDataPath(plugin_data_path);
285    return PP_ToBool(flash_browser_operations_1_3_->SetDefaultPermission(
286        data_str.c_str(), setting_type, permission,
287        PP_FromBool(clear_site_specific)));
288  }
289
290  if (flash_browser_operations_1_2_) {
291    std::string data_str = ConvertPluginDataPath(plugin_data_path);
292    return PP_ToBool(flash_browser_operations_1_2_->SetDefaultPermission(
293        data_str.c_str(), setting_type, permission,
294        PP_FromBool(clear_site_specific)));
295  }
296
297  return false;
298}
299
300bool BrokerProcessDispatcher::SetSitePermission(
301    const FilePath& plugin_data_path,
302    PP_Flash_BrowserOperations_SettingType setting_type,
303    const ppapi::FlashSiteSettings& sites) {
304  if (sites.empty())
305    return true;
306
307  std::string data_str = ConvertPluginDataPath(plugin_data_path);
308  scoped_array<PP_Flash_BrowserOperations_SiteSetting> site_array(
309      new PP_Flash_BrowserOperations_SiteSetting[sites.size()]);
310
311  for (size_t i = 0; i < sites.size(); ++i) {
312    site_array[i].site = sites[i].site.c_str();
313    site_array[i].permission = sites[i].permission;
314  }
315
316  if (flash_browser_operations_1_3_) {
317    PP_Bool result = flash_browser_operations_1_3_->SetSitePermission(
318        data_str.c_str(), setting_type, sites.size(), site_array.get());
319
320    return PP_ToBool(result);
321  }
322
323  if (flash_browser_operations_1_2_) {
324    PP_Bool result = flash_browser_operations_1_2_->SetSitePermission(
325        data_str.c_str(), setting_type, sites.size(), site_array.get());
326
327    return PP_ToBool(result);
328  }
329
330  return false;
331}
332
333}  // namespace content
334