Home | History | Annotate | Download | only in proxy
      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 "ppapi/proxy/flash_resource.h"
      6 
      7 #include <cmath>
      8 
      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"
     26 
     27 using ppapi::thunk::EnterResourceNoLock;
     28 
     29 namespace ppapi {
     30 namespace proxy {
     31 
     32 namespace {
     33 
     34 struct LocalTimeZoneOffsetEntry {
     35   base::TimeTicks expiration;
     36   double offset;
     37 };
     38 
     39 class LocalTimeZoneOffsetCache
     40     : public base::MRUCache<PP_Time, LocalTimeZoneOffsetEntry> {
     41  public:
     42   LocalTimeZoneOffsetCache()
     43       : base::MRUCache<PP_Time, LocalTimeZoneOffsetEntry>(kCacheSize) {}
     44  private:
     45   static const size_t kCacheSize = 100;
     46 };
     47 
     48 base::LazyInstance<LocalTimeZoneOffsetCache>::Leaky
     49     g_local_time_zone_offset_cache = LAZY_INSTANCE_INITIALIZER;
     50 
     51 } //  namespace
     52 
     53 FlashResource::FlashResource(Connection connection,
     54                              PP_Instance instance,
     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());
     60 }
     61 
     62 FlashResource::~FlashResource() {
     63 }
     64 
     65 thunk::PPB_Flash_Functions_API* FlashResource::AsPPB_Flash_Functions_API() {
     66   return this;
     67 }
     68 
     69 PP_Var FlashResource::GetProxyForURL(PP_Instance instance,
     70                                      const std::string& url) {
     71   std::string proxy;
     72   int32_t result = SyncCall<PpapiPluginMsg_Flash_GetProxyForURLReply>(RENDERER,
     73       PpapiHostMsg_Flash_GetProxyForURL(url), &proxy);
     74 
     75   if (result == PP_OK)
     76     return StringVar::StringToPPVar(proxy);
     77   return PP_MakeUndefined();
     78 }
     79 
     80 void FlashResource::UpdateActivity(PP_Instance instance) {
     81   Post(BROWSER, PpapiHostMsg_Flash_UpdateActivity());
     82 }
     83 
     84 PP_Bool FlashResource::SetCrashData(PP_Instance instance,
     85                                     PP_FlashCrashKey key,
     86                                     PP_Var value) {
     87   StringVar* url_string_var(StringVar::FromPPVar(value));
     88   if (!url_string_var)
     89     return PP_FALSE;
     90   switch (key) {
     91     case PP_FLASHCRASHKEY_URL: {
     92       PluginGlobals::Get()->SetActiveURL(url_string_var->value());
     93       return PP_TRUE;
     94     }
     95     case PP_FLASHCRASHKEY_RESOURCE_URL: {
     96       base::debug::SetCrashKeyValue("subresource_url", url_string_var->value());
     97       return PP_TRUE;
     98     }
     99   }
    100   return PP_FALSE;
    101 }
    102 
    103 double FlashResource::GetLocalTimeZoneOffset(PP_Instance instance,
    104                                              PP_Time t) {
    105   LocalTimeZoneOffsetCache& cache = g_local_time_zone_offset_cache.Get();
    106 
    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
    110   // boundaries).
    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;
    116 
    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);
    124 
    125   LocalTimeZoneOffsetEntry cache_entry;
    126   cache_entry.expiration = now + expiration_delta;
    127   cache_entry.offset = 0.0;
    128 
    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>(
    135       BROWSER,
    136       PpapiHostMsg_Flash_GetLocalTimeZoneOffset(PPTimeToTime(t)),
    137       &cache_entry.offset);
    138   if (result != PP_OK)
    139     cache_entry.offset = 0.0;
    140 #else
    141   cache_entry.offset = PPGetLocalTimeZoneOffset(PPTimeToTime(t));
    142 #endif
    143 
    144   cache.Put(t_minute_base, cache_entry);
    145   return cache_entry.offset;
    146 }
    147 
    148 PP_Var FlashResource::GetSetting(PP_Instance instance,
    149                                  PP_FlashSetting setting) {
    150   switch (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:
    166       return PP_MakeInt32(
    167           plugin_dispatcher_->preferences().number_of_cpu_cores);
    168     case PP_FLASHSETTING_LSORESTRICTIONS: {
    169       int32_t restrictions;
    170       int32_t result =
    171           SyncCall<PpapiPluginMsg_Flash_GetLocalDataRestrictionsReply>(BROWSER,
    172               PpapiHostMsg_Flash_GetLocalDataRestrictions(), &restrictions);
    173       if (result != PP_OK)
    174         return PP_MakeInt32(PP_FLASHLSORESTRICTIONS_NONE);
    175       return PP_MakeInt32(restrictions);
    176     }
    177   }
    178   return PP_MakeUndefined();
    179 }
    180 
    181 void FlashResource::SetInstanceAlwaysOnTop(PP_Instance instance,
    182                                            PP_Bool on_top) {
    183   Post(RENDERER, PpapiHostMsg_Flash_SetInstanceAlwaysOnTop(PP_ToBool(on_top)));
    184 }
    185 
    186 PP_Bool FlashResource::DrawGlyphs(
    187     PP_Instance instance,
    188     PP_Resource pp_image_data,
    189     const PP_BrowserFont_Trusted_Description* font_desc,
    190     uint32_t color,
    191     const PP_Point* position,
    192     const PP_Rect* clip,
    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);
    199   if (enter.failed())
    200     return PP_FALSE;
    201   // The instance parameter isn't strictly necessary but we check that it
    202   // matches anyway.
    203   if (enter.resource()->pp_instance() != instance)
    204     return PP_FALSE;
    205 
    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;
    211   params.clip = *clip;
    212   for (int i = 0; i < 3; i++) {
    213     for (int j = 0; j < 3; j++)
    214       params.transformation[i][j] = transformation[i][j];
    215   }
    216   params.allow_subpixel_aa = allow_subpixel_aa;
    217 
    218   params.glyph_indices.insert(params.glyph_indices.begin(),
    219                               &glyph_indices[0],
    220                               &glyph_indices[glyph_count]);
    221   params.glyph_advances.insert(params.glyph_advances.begin(),
    222                                &glyph_advances[0],
    223                                &glyph_advances[glyph_count]);
    224 
    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);
    230 }
    231 
    232 int32_t FlashResource::Navigate(PP_Instance instance,
    233                                 PP_Resource request_info,
    234                                 const char* target,
    235                                 PP_Bool from_user_action) {
    236   EnterResourceNoLock<thunk::PPB_URLRequestInfo_API> enter(request_info,
    237                                                                   true);
    238   if (enter.failed())
    239     return PP_ERROR_BADRESOURCE;
    240   return SyncCall<IPC::Message>(RENDERER, PpapiHostMsg_Flash_Navigate(
    241       enter.object()->GetData(), target, PP_ToBool(from_user_action)));
    242 }
    243 
    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);
    249 }
    250 
    251 void FlashResource::InvokePrinting(PP_Instance instance) {
    252   Post(RENDERER, PpapiHostMsg_Flash_InvokePrinting());
    253 }
    254 
    255 }  // namespace proxy
    256 }  // namespace ppapi
    257