OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ppapi/proxy/ppb_flash_proxy.h" | 5 #include "ppapi/proxy/ppb_flash_proxy.h" |
6 | 6 |
7 #include <math.h> | |
8 | |
9 #include <limits> | 7 #include <limits> |
10 | 8 |
11 #include "base/containers/mru_cache.h" | |
12 #include "base/lazy_instance.h" | |
13 #include "base/logging.h" | 9 #include "base/logging.h" |
14 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
15 #include "base/time.h" | |
16 #include "build/build_config.h" | 11 #include "build/build_config.h" |
17 #include "ppapi/c/dev/ppb_var_deprecated.h" | 12 #include "ppapi/c/dev/ppb_var_deprecated.h" |
18 #include "ppapi/c/pp_errors.h" | 13 #include "ppapi/c/pp_errors.h" |
19 #include "ppapi/c/pp_resource.h" | 14 #include "ppapi/c/pp_resource.h" |
20 #include "ppapi/c/private/ppb_flash.h" | 15 #include "ppapi/c/private/ppb_flash.h" |
21 #include "ppapi/c/private/ppb_flash_print.h" | 16 #include "ppapi/c/private/ppb_flash_print.h" |
22 #include "ppapi/c/trusted/ppb_browser_font_trusted.h" | 17 #include "ppapi/c/trusted/ppb_browser_font_trusted.h" |
23 #include "ppapi/proxy/host_dispatcher.h" | 18 #include "ppapi/proxy/host_dispatcher.h" |
24 #include "ppapi/proxy/plugin_dispatcher.h" | 19 #include "ppapi/proxy/plugin_dispatcher.h" |
25 #include "ppapi/proxy/plugin_globals.h" | 20 #include "ppapi/proxy/plugin_globals.h" |
26 #include "ppapi/proxy/ppapi_messages.h" | 21 #include "ppapi/proxy/ppapi_messages.h" |
27 #include "ppapi/proxy/proxy_module.h" | 22 #include "ppapi/proxy/proxy_module.h" |
28 #include "ppapi/proxy/serialized_var.h" | 23 #include "ppapi/proxy/serialized_var.h" |
29 #include "ppapi/shared_impl/ppapi_globals.h" | 24 #include "ppapi/shared_impl/ppapi_globals.h" |
30 #include "ppapi/shared_impl/proxy_lock.h" | 25 #include "ppapi/shared_impl/proxy_lock.h" |
31 #include "ppapi/shared_impl/resource.h" | 26 #include "ppapi/shared_impl/resource.h" |
32 #include "ppapi/shared_impl/resource_tracker.h" | 27 #include "ppapi/shared_impl/resource_tracker.h" |
33 #include "ppapi/shared_impl/scoped_pp_resource.h" | 28 #include "ppapi/shared_impl/scoped_pp_resource.h" |
34 #include "ppapi/shared_impl/time_conversion.h" | |
35 #include "ppapi/shared_impl/var.h" | 29 #include "ppapi/shared_impl/var.h" |
36 #include "ppapi/shared_impl/var_tracker.h" | 30 #include "ppapi/shared_impl/var_tracker.h" |
37 #include "ppapi/thunk/enter.h" | 31 #include "ppapi/thunk/enter.h" |
38 #include "ppapi/thunk/ppb_instance_api.h" | 32 #include "ppapi/thunk/ppb_instance_api.h" |
39 #include "ppapi/thunk/ppb_url_request_info_api.h" | 33 #include "ppapi/thunk/ppb_url_request_info_api.h" |
40 #include "ppapi/thunk/resource_creation_api.h" | 34 #include "ppapi/thunk/resource_creation_api.h" |
41 | 35 |
42 using ppapi::thunk::EnterInstanceNoLock; | 36 using ppapi::thunk::EnterInstanceNoLock; |
43 using ppapi::thunk::EnterResourceNoLock; | 37 using ppapi::thunk::EnterResourceNoLock; |
44 | 38 |
45 namespace ppapi { | 39 namespace ppapi { |
46 namespace proxy { | 40 namespace proxy { |
47 | 41 |
48 namespace { | 42 namespace { |
49 | 43 |
50 struct LocalTimeZoneOffsetEntry { | |
51 base::TimeTicks expiration; | |
52 double offset; | |
53 }; | |
54 | |
55 class LocalTimeZoneOffsetCache | |
56 : public base::MRUCache<PP_Time, LocalTimeZoneOffsetEntry> { | |
57 public: | |
58 LocalTimeZoneOffsetCache() | |
59 : base::MRUCache<PP_Time, LocalTimeZoneOffsetEntry>(kCacheSize) {} | |
60 private: | |
61 static const size_t kCacheSize = 100; | |
62 }; | |
63 | |
64 base::LazyInstance<LocalTimeZoneOffsetCache>::Leaky | |
65 g_local_time_zone_offset_cache = LAZY_INSTANCE_INITIALIZER; | |
66 | |
67 void InvokePrinting(PP_Instance instance) { | 44 void InvokePrinting(PP_Instance instance) { |
68 ProxyAutoLock lock; | 45 ProxyAutoLock lock; |
69 | 46 |
70 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); | 47 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); |
71 if (dispatcher) { | 48 if (dispatcher) { |
72 dispatcher->Send(new PpapiHostMsg_PPBFlash_InvokePrinting( | 49 dispatcher->Send(new PpapiHostMsg_PPBFlash_InvokePrinting( |
73 API_ID_PPB_FLASH, instance)); | 50 API_ID_PPB_FLASH, instance)); |
74 } | 51 } |
75 } | 52 } |
76 | 53 |
(...skipping 21 matching lines...) Expand all Loading... |
98 if (!dispatcher()->permissions().HasPermission(PERMISSION_FLASH)) | 75 if (!dispatcher()->permissions().HasPermission(PERMISSION_FLASH)) |
99 return false; | 76 return false; |
100 | 77 |
101 bool handled = true; | 78 bool handled = true; |
102 IPC_BEGIN_MESSAGE_MAP(PPB_Flash_Proxy, msg) | 79 IPC_BEGIN_MESSAGE_MAP(PPB_Flash_Proxy, msg) |
103 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_SetInstanceAlwaysOnTop, | 80 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_SetInstanceAlwaysOnTop, |
104 OnHostMsgSetInstanceAlwaysOnTop) | 81 OnHostMsgSetInstanceAlwaysOnTop) |
105 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_DrawGlyphs, | 82 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_DrawGlyphs, |
106 OnHostMsgDrawGlyphs) | 83 OnHostMsgDrawGlyphs) |
107 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_Navigate, OnHostMsgNavigate) | 84 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_Navigate, OnHostMsgNavigate) |
108 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_GetLocalTimeZoneOffset, | |
109 OnHostMsgGetLocalTimeZoneOffset) | |
110 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_IsRectTopmost, | 85 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_IsRectTopmost, |
111 OnHostMsgIsRectTopmost) | 86 OnHostMsgIsRectTopmost) |
112 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_InvokePrinting, | 87 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_InvokePrinting, |
113 OnHostMsgInvokePrinting) | 88 OnHostMsgInvokePrinting) |
114 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_GetSetting, | 89 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_GetSetting, |
115 OnHostMsgGetSetting) | 90 OnHostMsgGetSetting) |
116 IPC_MESSAGE_UNHANDLED(handled = false) | 91 IPC_MESSAGE_UNHANDLED(handled = false) |
117 IPC_END_MESSAGE_MAP() | 92 IPC_END_MESSAGE_MAP() |
118 // TODO(brettw) handle bad messages! | 93 // TODO(brettw) handle bad messages! |
119 return handled; | 94 return handled; |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 int32_t PPB_Flash_Proxy::Navigate(PP_Instance instance, | 161 int32_t PPB_Flash_Proxy::Navigate(PP_Instance instance, |
187 const URLRequestInfoData& data, | 162 const URLRequestInfoData& data, |
188 const char* target, | 163 const char* target, |
189 PP_Bool from_user_action) { | 164 PP_Bool from_user_action) { |
190 int32_t result = PP_ERROR_FAILED; | 165 int32_t result = PP_ERROR_FAILED; |
191 dispatcher()->Send(new PpapiHostMsg_PPBFlash_Navigate( | 166 dispatcher()->Send(new PpapiHostMsg_PPBFlash_Navigate( |
192 API_ID_PPB_FLASH, instance, data, target, from_user_action, &result)); | 167 API_ID_PPB_FLASH, instance, data, target, from_user_action, &result)); |
193 return result; | 168 return result; |
194 } | 169 } |
195 | 170 |
196 double PPB_Flash_Proxy::GetLocalTimeZoneOffset(PP_Instance instance, | |
197 PP_Time t) { | |
198 LocalTimeZoneOffsetCache& cache = g_local_time_zone_offset_cache.Get(); | |
199 | |
200 // Get the minimum PP_Time value that shares the same minute as |t|. | |
201 // Use cached offset if cache hasn't expired and |t| is in the same minute as | |
202 // the time for the cached offset (assume offsets change on minute | |
203 // boundaries). | |
204 PP_Time t_minute_base = floor(t / 60.0) * 60.0; | |
205 LocalTimeZoneOffsetCache::iterator iter = cache.Get(t_minute_base); | |
206 base::TimeTicks now = base::TimeTicks::Now(); | |
207 if (iter != cache.end() && now < iter->second.expiration) | |
208 return iter->second.offset; | |
209 | |
210 // Cache the local offset for ten seconds, since it's slow on XP and Linux. | |
211 // Note that TimeTicks does not continue counting across sleep/resume on all | |
212 // platforms. This may be acceptable for 10 seconds, but if in the future this | |
213 // is changed to one minute or more, then we should consider using base::Time. | |
214 const int64 kMaxCachedLocalOffsetAgeInSeconds = 10; | |
215 base::TimeDelta expiration_delta = | |
216 base::TimeDelta::FromSeconds(kMaxCachedLocalOffsetAgeInSeconds); | |
217 | |
218 LocalTimeZoneOffsetEntry cache_entry; | |
219 cache_entry.expiration = now + expiration_delta; | |
220 cache_entry.offset = 0.0; | |
221 | |
222 // TODO(shess): Figure out why OSX needs the access, the sandbox | |
223 // warmup should handle it. http://crbug.com/149006 | |
224 #if defined(OS_LINUX) || defined(OS_MACOSX) | |
225 // On Linux localtime needs access to the filesystem, which is prohibited | |
226 // by the sandbox. It would be better to go directly to the browser process | |
227 // for this message rather than proxy it through some instance in a renderer. | |
228 dispatcher()->Send(new PpapiHostMsg_PPBFlash_GetLocalTimeZoneOffset( | |
229 API_ID_PPB_FLASH, instance, t, &cache_entry.offset)); | |
230 #else | |
231 base::Time cur = PPTimeToTime(t); | |
232 base::Time::Exploded exploded = { 0 }; | |
233 base::Time::Exploded utc_exploded = { 0 }; | |
234 cur.LocalExplode(&exploded); | |
235 cur.UTCExplode(&utc_exploded); | |
236 if (exploded.HasValidValues() && utc_exploded.HasValidValues()) { | |
237 base::Time adj_time = base::Time::FromUTCExploded(exploded); | |
238 base::Time cur = base::Time::FromUTCExploded(utc_exploded); | |
239 cache_entry.offset = (adj_time - cur).InSecondsF(); | |
240 } | |
241 #endif | |
242 | |
243 cache.Put(t_minute_base, cache_entry); | |
244 return cache_entry.offset; | |
245 } | |
246 | |
247 PP_Bool PPB_Flash_Proxy::IsRectTopmost(PP_Instance instance, | 171 PP_Bool PPB_Flash_Proxy::IsRectTopmost(PP_Instance instance, |
248 const PP_Rect* rect) { | 172 const PP_Rect* rect) { |
249 PP_Bool result = PP_FALSE; | 173 PP_Bool result = PP_FALSE; |
250 dispatcher()->Send(new PpapiHostMsg_PPBFlash_IsRectTopmost( | 174 dispatcher()->Send(new PpapiHostMsg_PPBFlash_IsRectTopmost( |
251 API_ID_PPB_FLASH, instance, *rect, &result)); | 175 API_ID_PPB_FLASH, instance, *rect, &result)); |
252 return result; | 176 return result; |
253 } | 177 } |
254 | 178 |
255 PP_Var PPB_Flash_Proxy::GetSetting(PP_Instance instance, | 179 PP_Var PPB_Flash_Proxy::GetSetting(PP_Instance instance, |
256 PP_FlashSetting setting) { | 180 PP_FlashSetting setting) { |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
341 // We need to allow re-entrancy here, because this may call into Javascript | 265 // We need to allow re-entrancy here, because this may call into Javascript |
342 // (e.g. with a "javascript:" URL), or do things like navigate away from the | 266 // (e.g. with a "javascript:" URL), or do things like navigate away from the |
343 // page, either one of which will need to re-enter into the plugin. | 267 // page, either one of which will need to re-enter into the plugin. |
344 // It is safe, because it is essentially equivalent to NPN_GetURL, where Flash | 268 // It is safe, because it is essentially equivalent to NPN_GetURL, where Flash |
345 // would expect re-entrancy. When running in-process, it does re-enter here. | 269 // would expect re-entrancy. When running in-process, it does re-enter here. |
346 host_dispatcher->set_allow_plugin_reentrancy(); | 270 host_dispatcher->set_allow_plugin_reentrancy(); |
347 *result = enter_instance.functions()->GetFlashAPI()->Navigate( | 271 *result = enter_instance.functions()->GetFlashAPI()->Navigate( |
348 instance, data, target.c_str(), from_user_action); | 272 instance, data, target.c_str(), from_user_action); |
349 } | 273 } |
350 | 274 |
351 void PPB_Flash_Proxy::OnHostMsgGetLocalTimeZoneOffset(PP_Instance instance, | |
352 PP_Time t, | |
353 double* result) { | |
354 EnterInstanceNoLock enter(instance); | |
355 if (enter.succeeded()) { | |
356 *result = enter.functions()->GetFlashAPI()->GetLocalTimeZoneOffset( | |
357 instance, t); | |
358 } else { | |
359 *result = 0.0; | |
360 } | |
361 } | |
362 | |
363 void PPB_Flash_Proxy::OnHostMsgIsRectTopmost(PP_Instance instance, | 275 void PPB_Flash_Proxy::OnHostMsgIsRectTopmost(PP_Instance instance, |
364 PP_Rect rect, | 276 PP_Rect rect, |
365 PP_Bool* result) { | 277 PP_Bool* result) { |
366 EnterInstanceNoLock enter(instance); | 278 EnterInstanceNoLock enter(instance); |
367 if (enter.succeeded()) | 279 if (enter.succeeded()) |
368 *result = enter.functions()->GetFlashAPI()->IsRectTopmost(instance, &rect); | 280 *result = enter.functions()->GetFlashAPI()->IsRectTopmost(instance, &rect); |
369 else | 281 else |
370 *result = PP_FALSE; | 282 *result = PP_FALSE; |
371 } | 283 } |
372 | 284 |
(...skipping 15 matching lines...) Expand all Loading... |
388 // It's rarely used enough that we just request this interface when needed. | 300 // It's rarely used enough that we just request this interface when needed. |
389 const PPB_Flash_Print_1_0* print_interface = | 301 const PPB_Flash_Print_1_0* print_interface = |
390 static_cast<const PPB_Flash_Print_1_0*>( | 302 static_cast<const PPB_Flash_Print_1_0*>( |
391 dispatcher()->local_get_interface()(PPB_FLASH_PRINT_INTERFACE_1_0)); | 303 dispatcher()->local_get_interface()(PPB_FLASH_PRINT_INTERFACE_1_0)); |
392 if (print_interface) | 304 if (print_interface) |
393 print_interface->InvokePrinting(instance); | 305 print_interface->InvokePrinting(instance); |
394 } | 306 } |
395 | 307 |
396 } // namespace proxy | 308 } // namespace proxy |
397 } // namespace ppapi | 309 } // namespace ppapi |
OLD | NEW |