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.
5 #include "ppapi/proxy/flash_resource.h"
9 #include "base/containers/mru_cache.h"
10 #include "base/debug/crash_logging.h"
11 #include "base/lazy_instance.h"
12 #include "base/time/time.h"
13 #include "ppapi/c/pp_errors.h"
14 #include "ppapi/c/private/ppb_flash.h"
15 #include "ppapi/c/trusted/ppb_browser_font_trusted.h"
16 #include "ppapi/proxy/plugin_dispatcher.h"
17 #include "ppapi/proxy/plugin_globals.h"
18 #include "ppapi/proxy/ppapi_messages.h"
19 #include "ppapi/proxy/serialized_structs.h"
20 #include "ppapi/shared_impl/ppapi_preferences.h"
21 #include "ppapi/shared_impl/scoped_pp_var.h"
22 #include "ppapi/shared_impl/time_conversion.h"
23 #include "ppapi/shared_impl/var.h"
24 #include "ppapi/thunk/enter.h"
25 #include "ppapi/thunk/ppb_url_request_info_api.h"
27 using ppapi::thunk::EnterResourceNoLock
;
34 struct LocalTimeZoneOffsetEntry
{
35 base::TimeTicks expiration
;
39 class LocalTimeZoneOffsetCache
40 : public base::MRUCache
<PP_Time
, LocalTimeZoneOffsetEntry
> {
42 LocalTimeZoneOffsetCache()
43 : base::MRUCache
<PP_Time
, LocalTimeZoneOffsetEntry
>(kCacheSize
) {}
45 static const size_t kCacheSize
= 100;
48 base::LazyInstance
<LocalTimeZoneOffsetCache
>::Leaky
49 g_local_time_zone_offset_cache
= LAZY_INSTANCE_INITIALIZER
;
53 FlashResource::FlashResource(Connection connection
,
55 PluginDispatcher
* plugin_dispatcher
)
56 : PluginResource(connection
, instance
),
57 plugin_dispatcher_(plugin_dispatcher
) {
58 SendCreate(RENDERER
, PpapiHostMsg_Flash_Create());
59 SendCreate(BROWSER
, PpapiHostMsg_Flash_Create());
62 FlashResource::~FlashResource() {
65 thunk::PPB_Flash_Functions_API
* FlashResource::AsPPB_Flash_Functions_API() {
69 PP_Var
FlashResource::GetProxyForURL(PP_Instance instance
,
70 const std::string
& url
) {
72 int32_t result
= SyncCall
<PpapiPluginMsg_Flash_GetProxyForURLReply
>(RENDERER
,
73 PpapiHostMsg_Flash_GetProxyForURL(url
), &proxy
);
76 return StringVar::StringToPPVar(proxy
);
77 return PP_MakeUndefined();
80 void FlashResource::UpdateActivity(PP_Instance instance
) {
81 Post(BROWSER
, PpapiHostMsg_Flash_UpdateActivity());
84 PP_Bool
FlashResource::SetCrashData(PP_Instance instance
,
87 StringVar
* url_string_var(StringVar::FromPPVar(value
));
91 case PP_FLASHCRASHKEY_URL
: {
92 PluginGlobals::Get()->SetActiveURL(url_string_var
->value());
95 case PP_FLASHCRASHKEY_RESOURCE_URL
: {
96 base::debug::SetCrashKeyValue("subresource_url", url_string_var
->value());
103 double FlashResource::GetLocalTimeZoneOffset(PP_Instance instance
,
105 LocalTimeZoneOffsetCache
& cache
= g_local_time_zone_offset_cache
.Get();
107 // Get the minimum PP_Time value that shares the same minute as |t|.
108 // Use cached offset if cache hasn't expired and |t| is in the same minute as
109 // the time for the cached offset (assume offsets change on minute
111 PP_Time t_minute_base
= floor(t
/ 60.0) * 60.0;
112 LocalTimeZoneOffsetCache::iterator iter
= cache
.Get(t_minute_base
);
113 base::TimeTicks now
= base::TimeTicks::Now();
114 if (iter
!= cache
.end() && now
< iter
->second
.expiration
)
115 return iter
->second
.offset
;
117 // Cache the local offset for ten seconds, since it's slow on XP and Linux.
118 // Note that TimeTicks does not continue counting across sleep/resume on all
119 // platforms. This may be acceptable for 10 seconds, but if in the future this
120 // is changed to one minute or more, then we should consider using base::Time.
121 const int64 kMaxCachedLocalOffsetAgeInSeconds
= 10;
122 base::TimeDelta expiration_delta
=
123 base::TimeDelta::FromSeconds(kMaxCachedLocalOffsetAgeInSeconds
);
125 LocalTimeZoneOffsetEntry cache_entry
;
126 cache_entry
.expiration
= now
+ expiration_delta
;
127 cache_entry
.offset
= 0.0;
129 // We can't do the conversion here on Linux because the localtime calls
130 // require filesystem access prohibited by the sandbox.
131 // TODO(shess): Figure out why OSX needs the access, the sandbox warmup should
132 // handle it. http://crbug.com/149006
133 #if defined(OS_LINUX) || defined(OS_MACOSX)
134 int32_t result
= SyncCall
<PpapiPluginMsg_Flash_GetLocalTimeZoneOffsetReply
>(
136 PpapiHostMsg_Flash_GetLocalTimeZoneOffset(PPTimeToTime(t
)),
137 &cache_entry
.offset
);
139 cache_entry
.offset
= 0.0;
141 cache_entry
.offset
= PPGetLocalTimeZoneOffset(PPTimeToTime(t
));
144 cache
.Put(t_minute_base
, cache_entry
);
145 return cache_entry
.offset
;
148 PP_Var
FlashResource::GetSetting(PP_Instance instance
,
149 PP_FlashSetting setting
) {
151 case PP_FLASHSETTING_3DENABLED
:
152 return PP_MakeBool(PP_FromBool(
153 plugin_dispatcher_
->preferences().is_3d_supported
));
154 case PP_FLASHSETTING_INCOGNITO
:
155 return PP_MakeBool(PP_FromBool(plugin_dispatcher_
->incognito()));
156 case PP_FLASHSETTING_STAGE3DENABLED
:
157 return PP_MakeBool(PP_FromBool(
158 plugin_dispatcher_
->preferences().is_stage3d_supported
));
159 case PP_FLASHSETTING_STAGE3DBASELINEENABLED
:
160 return PP_MakeBool(PP_FromBool(
161 plugin_dispatcher_
->preferences().is_stage3d_baseline_supported
));
162 case PP_FLASHSETTING_LANGUAGE
:
163 return StringVar::StringToPPVar(
164 PluginGlobals::Get()->GetUILanguage());
165 case PP_FLASHSETTING_NUMCORES
:
167 plugin_dispatcher_
->preferences().number_of_cpu_cores
);
168 case PP_FLASHSETTING_LSORESTRICTIONS
: {
169 int32_t restrictions
;
171 SyncCall
<PpapiPluginMsg_Flash_GetLocalDataRestrictionsReply
>(BROWSER
,
172 PpapiHostMsg_Flash_GetLocalDataRestrictions(), &restrictions
);
174 return PP_MakeInt32(PP_FLASHLSORESTRICTIONS_NONE
);
175 return PP_MakeInt32(restrictions
);
178 return PP_MakeUndefined();
181 void FlashResource::SetInstanceAlwaysOnTop(PP_Instance instance
,
183 Post(RENDERER
, PpapiHostMsg_Flash_SetInstanceAlwaysOnTop(PP_ToBool(on_top
)));
186 PP_Bool
FlashResource::DrawGlyphs(
187 PP_Instance instance
,
188 PP_Resource pp_image_data
,
189 const PP_BrowserFont_Trusted_Description
* font_desc
,
191 const PP_Point
* position
,
193 const float transformation
[3][3],
194 PP_Bool allow_subpixel_aa
,
195 uint32_t glyph_count
,
196 const uint16_t glyph_indices
[],
197 const PP_Point glyph_advances
[]) {
198 EnterResourceNoLock
<thunk::PPB_ImageData_API
> enter(pp_image_data
, true);
201 // The instance parameter isn't strictly necessary but we check that it
203 if (enter
.resource()->pp_instance() != instance
)
206 PPBFlash_DrawGlyphs_Params params
;
207 params
.image_data
= enter
.resource()->host_resource();
208 params
.font_desc
.SetFromPPBrowserFontDescription(*font_desc
);
209 params
.color
= color
;
210 params
.position
= *position
;
212 for (int i
= 0; i
< 3; i
++) {
213 for (int j
= 0; j
< 3; j
++)
214 params
.transformation
[i
][j
] = transformation
[i
][j
];
216 params
.allow_subpixel_aa
= allow_subpixel_aa
;
218 params
.glyph_indices
.insert(params
.glyph_indices
.begin(),
220 &glyph_indices
[glyph_count
]);
221 params
.glyph_advances
.insert(params
.glyph_advances
.begin(),
223 &glyph_advances
[glyph_count
]);
225 // This has to be synchronous because the caller may want to composite on
226 // top of the resulting text after the call is complete.
227 int32_t result
= SyncCall
<IPC::Message
>(RENDERER
,
228 PpapiHostMsg_Flash_DrawGlyphs(params
));
229 return PP_FromBool(result
== PP_OK
);
232 int32_t FlashResource::Navigate(PP_Instance instance
,
233 PP_Resource request_info
,
235 PP_Bool from_user_action
) {
236 EnterResourceNoLock
<thunk::PPB_URLRequestInfo_API
> enter(request_info
,
239 return PP_ERROR_BADRESOURCE
;
240 return SyncCall
<IPC::Message
>(RENDERER
, PpapiHostMsg_Flash_Navigate(
241 enter
.object()->GetData(), target
, PP_ToBool(from_user_action
)));
244 PP_Bool
FlashResource::IsRectTopmost(PP_Instance instance
,
245 const PP_Rect
* rect
) {
246 int32_t result
= SyncCall
<IPC::Message
>(RENDERER
,
247 PpapiHostMsg_Flash_IsRectTopmost(*rect
));
248 return PP_FromBool(result
== PP_OK
);
251 void FlashResource::InvokePrinting(PP_Instance instance
) {
252 Post(RENDERER
, PpapiHostMsg_Flash_InvokePrinting());