blob: a8767f7b0d7737f5f9d9a42e68eb2c5230293c15 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ppapi/proxy/ppb_flash_proxy.h"
#include <limits>
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/time.h"
#include "build/build_config.h"
#include "ppapi/c/dev/ppb_font_dev.h"
#include "ppapi/c/dev/ppb_var_deprecated.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/pp_resource.h"
#include "ppapi/c/private/ppb_flash.h"
#include "ppapi/c/private/ppb_flash_print.h"
#include "ppapi/proxy/host_dispatcher.h"
#include "ppapi/proxy/pepper_file_messages.h"
#include "ppapi/proxy/plugin_dispatcher.h"
#include "ppapi/proxy/plugin_globals.h"
#include "ppapi/proxy/plugin_proxy_delegate.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/proxy_module.h"
#include "ppapi/proxy/serialized_var.h"
#include "ppapi/shared_impl/dir_contents.h"
#include "ppapi/shared_impl/file_type_conversion.h"
#include "ppapi/shared_impl/ppapi_globals.h"
#include "ppapi/shared_impl/proxy_lock.h"
#include "ppapi/shared_impl/resource.h"
#include "ppapi/shared_impl/resource_tracker.h"
#include "ppapi/shared_impl/scoped_pp_resource.h"
#include "ppapi/shared_impl/time_conversion.h"
#include "ppapi/shared_impl/var.h"
#include "ppapi/thunk/enter.h"
#include "ppapi/thunk/ppb_instance_api.h"
#include "ppapi/thunk/ppb_url_request_info_api.h"
#include "ppapi/thunk/resource_creation_api.h"
using ppapi::thunk::EnterInstanceNoLock;
using ppapi::thunk::EnterResourceNoLock;
namespace ppapi {
namespace proxy {
namespace {
IPC::PlatformFileForTransit PlatformFileToPlatformFileForTransit(
Dispatcher* dispatcher,
int32_t* error,
base::PlatformFile file) {
if (*error != PP_OK)
return IPC::InvalidPlatformFileForTransit();
IPC::PlatformFileForTransit out_handle =
dispatcher->ShareHandleWithRemote(file, true);
if (out_handle == IPC::InvalidPlatformFileForTransit())
*error = PP_ERROR_NOACCESS;
return out_handle;
}
void InvokePrinting(PP_Instance instance) {
PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
if (dispatcher) {
dispatcher->Send(new PpapiHostMsg_PPBFlash_InvokePrinting(
API_ID_PPB_FLASH, instance));
}
}
const PPB_Flash_Print_1_0 g_flash_print_interface = {
&InvokePrinting
};
} // namespace
// -----------------------------------------------------------------------------
PPB_Flash_Proxy::PPB_Flash_Proxy(Dispatcher* dispatcher)
: InterfaceProxy(dispatcher) {
}
PPB_Flash_Proxy::~PPB_Flash_Proxy() {
}
// static
const PPB_Flash_Print_1_0* PPB_Flash_Proxy::GetFlashPrintInterface() {
return &g_flash_print_interface;
}
bool PPB_Flash_Proxy::OnMessageReceived(const IPC::Message& msg) {
// Prevent the dispatcher from going away during a call to Navigate.
// This must happen OUTSIDE of OnMsgNavigate since the handling code use
// the dispatcher upon return of the function (sending the reply message).
ScopedModuleReference death_grip(dispatcher());
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PPB_Flash_Proxy, msg)
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_SetInstanceAlwaysOnTop,
OnHostMsgSetInstanceAlwaysOnTop)
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_DrawGlyphs,
OnHostMsgDrawGlyphs)
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_GetProxyForURL,
OnHostMsgGetProxyForURL)
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_Navigate, OnHostMsgNavigate)
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_RunMessageLoop,
OnHostMsgRunMessageLoop)
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_QuitMessageLoop,
OnHostMsgQuitMessageLoop)
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_GetLocalTimeZoneOffset,
OnHostMsgGetLocalTimeZoneOffset)
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_IsRectTopmost,
OnHostMsgIsRectTopmost)
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_FlashSetFullscreen,
OnHostMsgFlashSetFullscreen)
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_FlashGetScreenSize,
OnHostMsgFlashGetScreenSize)
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_IsClipboardFormatAvailable,
OnHostMsgIsClipboardFormatAvailable)
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_ReadClipboardData,
OnHostMsgReadClipboardData)
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_WriteClipboardData,
OnHostMsgWriteClipboardData)
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_OpenFileRef,
OnHostMsgOpenFileRef)
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_QueryFileRef,
OnHostMsgQueryFileRef)
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_GetDeviceID,
OnHostMsgGetDeviceID)
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_InvokePrinting,
OnHostMsgInvokePrinting)
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_GetSetting,
OnHostMsgGetSetting)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
// TODO(brettw) handle bad messages!
return handled;
}
void PPB_Flash_Proxy::SetInstanceAlwaysOnTop(PP_Instance instance,
PP_Bool on_top) {
dispatcher()->Send(new PpapiHostMsg_PPBFlash_SetInstanceAlwaysOnTop(
API_ID_PPB_FLASH, instance, on_top));
}
PP_Bool PPB_Flash_Proxy::DrawGlyphs(PP_Instance instance,
PP_Resource pp_image_data,
const PP_FontDescription_Dev* font_desc,
uint32_t color,
const PP_Point* position,
const PP_Rect* clip,
const float transformation[3][3],
PP_Bool allow_subpixel_aa,
uint32_t glyph_count,
const uint16_t glyph_indices[],
const PP_Point glyph_advances[]) {
Resource* image_data =
PpapiGlobals::Get()->GetResourceTracker()->GetResource(pp_image_data);
if (!image_data)
return PP_FALSE;
// The instance parameter isn't strictly necessary but we check that it
// matches anyway.
if (image_data->pp_instance() != instance)
return PP_FALSE;
PPBFlash_DrawGlyphs_Params params;
params.image_data = image_data->host_resource();
params.font_desc.SetFromPPFontDescription(dispatcher(), *font_desc, true);
params.color = color;
params.position = *position;
params.clip = *clip;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++)
params.transformation[i][j] = transformation[i][j];
}
params.allow_subpixel_aa = allow_subpixel_aa;
params.glyph_indices.insert(params.glyph_indices.begin(),
&glyph_indices[0],
&glyph_indices[glyph_count]);
params.glyph_advances.insert(params.glyph_advances.begin(),
&glyph_advances[0],
&glyph_advances[glyph_count]);
PP_Bool result = PP_FALSE;
dispatcher()->Send(new PpapiHostMsg_PPBFlash_DrawGlyphs(
API_ID_PPB_FLASH, instance, params, &result));
return result;
}
PP_Var PPB_Flash_Proxy::GetProxyForURL(PP_Instance instance, const char* url) {
ReceiveSerializedVarReturnValue result;
dispatcher()->Send(new PpapiHostMsg_PPBFlash_GetProxyForURL(
API_ID_PPB_FLASH, instance, url, &result));
return result.Return(dispatcher());
}
int32_t PPB_Flash_Proxy::Navigate(PP_Instance instance,
PP_Resource request_info,
const char* target,
PP_Bool from_user_action) {
thunk::EnterResourceNoLock<thunk::PPB_URLRequestInfo_API> enter(
request_info, true);
if (enter.failed())
return PP_ERROR_BADRESOURCE;
return Navigate(instance, enter.object()->GetData(), target,
from_user_action);
}
int32_t PPB_Flash_Proxy::Navigate(PP_Instance instance,
const URLRequestInfoData& data,
const char* target,
PP_Bool from_user_action) {
int32_t result = PP_ERROR_FAILED;
dispatcher()->Send(new PpapiHostMsg_PPBFlash_Navigate(
API_ID_PPB_FLASH, instance, data, target, from_user_action, &result));
return result;
}
void PPB_Flash_Proxy::RunMessageLoop(PP_Instance instance) {
IPC::SyncMessage* msg = new PpapiHostMsg_PPBFlash_RunMessageLoop(
API_ID_PPB_FLASH, instance);
msg->EnableMessagePumping();
dispatcher()->Send(msg);
}
void PPB_Flash_Proxy::QuitMessageLoop(PP_Instance instance) {
dispatcher()->Send(new PpapiHostMsg_PPBFlash_QuitMessageLoop(
API_ID_PPB_FLASH, instance));
}
double PPB_Flash_Proxy::GetLocalTimeZoneOffset(PP_Instance instance,
PP_Time t) {
static double s_local_offset = 0.0;
static int64 s_last_updated = std::numeric_limits<int64>::min();
// Cache the local offset for ten seconds, since it's slow on XP and Linux.
const int64 kMaxCachedLocalOffsetAgeInSeconds = 10;
base::TimeTicks now = base::TimeTicks::Now();
base::TimeTicks expiration =
base::TimeTicks::FromInternalValue(s_last_updated) +
base::TimeDelta::FromSeconds(kMaxCachedLocalOffsetAgeInSeconds);
if (now < expiration)
return s_local_offset;
s_last_updated = now.ToInternalValue();
// TODO(shess): Figure out why OSX needs the access, the sandbox
// warmup should handle it. http://crbug.com/149006
#if defined(OS_LINUX) || defined(OS_MACOSX)
// On Linux localtime needs access to the filesystem, which is prohibited
// by the sandbox. It would be better to go directly to the browser process
// for this message rather than proxy it through some instance in a renderer.
dispatcher()->Send(new PpapiHostMsg_PPBFlash_GetLocalTimeZoneOffset(
API_ID_PPB_FLASH, instance, t, &s_local_offset));
#else
base::Time cur = PPTimeToTime(t);
base::Time::Exploded exploded = { 0 };
base::Time::Exploded utc_exploded = { 0 };
cur.LocalExplode(&exploded);
cur.UTCExplode(&utc_exploded);
if (exploded.HasValidValues() && utc_exploded.HasValidValues()) {
base::Time adj_time = base::Time::FromUTCExploded(exploded);
base::Time cur = base::Time::FromUTCExploded(utc_exploded);
s_local_offset = (adj_time - cur).InSecondsF();
} else {
s_local_offset = 0.0;
}
#endif
return s_local_offset;
}
PP_Bool PPB_Flash_Proxy::IsRectTopmost(PP_Instance instance,
const PP_Rect* rect) {
PP_Bool result = PP_FALSE;
dispatcher()->Send(new PpapiHostMsg_PPBFlash_IsRectTopmost(
API_ID_PPB_FLASH, instance, *rect, &result));
return result;
}
void PPB_Flash_Proxy::UpdateActivity(PP_Instance instance) {
PluginGlobals::Get()->plugin_proxy_delegate()->SendToBrowser(
new PpapiHostMsg_PPBFlash_UpdateActivity(API_ID_PPB_FLASH));
}
PP_Var PPB_Flash_Proxy::GetDeviceID(PP_Instance instance) {
ReceiveSerializedVarReturnValue result;
dispatcher()->Send(new PpapiHostMsg_PPBFlash_GetDeviceID(
API_ID_PPB_FLASH, instance, &result));
return result.Return(dispatcher());
}
int32_t PPB_Flash_Proxy::GetSettingInt(PP_Instance instance,
PP_FlashSetting setting) {
// Note: Don't add support for any more settings here. This method is
// deprecated.
switch (setting) {
case PP_FLASHSETTING_3DENABLED:
return static_cast<PluginDispatcher*>(dispatcher())->preferences().
is_3d_supported;
case PP_FLASHSETTING_INCOGNITO:
return static_cast<PluginDispatcher*>(dispatcher())->incognito();
case PP_FLASHSETTING_STAGE3DENABLED:
return static_cast<PluginDispatcher*>(dispatcher())->preferences().
is_stage3d_supported;
default:
return -1;
}
}
PP_Var PPB_Flash_Proxy::GetSetting(PP_Instance instance,
PP_FlashSetting setting) {
PluginDispatcher* plugin_dispatcher =
static_cast<PluginDispatcher*>(dispatcher());
switch (setting) {
case PP_FLASHSETTING_3DENABLED:
return PP_MakeBool(PP_FromBool(
plugin_dispatcher->preferences().is_3d_supported));
case PP_FLASHSETTING_INCOGNITO:
return PP_MakeBool(PP_FromBool(plugin_dispatcher->incognito()));
case PP_FLASHSETTING_STAGE3DENABLED:
return PP_MakeBool(PP_FromBool(
plugin_dispatcher->preferences().is_stage3d_supported));
case PP_FLASHSETTING_LANGUAGE:
return StringVar::StringToPPVar(
PluginGlobals::Get()->plugin_proxy_delegate()->GetUILanguage());
case PP_FLASHSETTING_NUMCORES:
return PP_MakeInt32(plugin_dispatcher->preferences().number_of_cpu_cores);
case PP_FLASHSETTING_LSORESTRICTIONS: {
ReceiveSerializedVarReturnValue result;
dispatcher()->Send(new PpapiHostMsg_PPBFlash_GetSetting(
API_ID_PPB_FLASH, instance, setting, &result));
return result.Return(dispatcher());
}
}
return PP_MakeUndefined();
}
PP_Bool PPB_Flash_Proxy::SetCrashData(PP_Instance instance,
PP_FlashCrashKey key,
PP_Var value) {
switch (key) {
case PP_FLASHCRASHKEY_URL:
StringVar *url_string_var(StringVar::FromPPVar(value));
if (!url_string_var)
return PP_FALSE;
std::string url_string(url_string_var->value());
PluginGlobals::Get()->plugin_proxy_delegate()->SetActiveURL(url_string);
return PP_TRUE;
}
return PP_FALSE;
}
PP_Bool PPB_Flash_Proxy::IsClipboardFormatAvailable(
PP_Instance instance,
PP_Flash_Clipboard_Type clipboard_type,
PP_Flash_Clipboard_Format format) {
if (!IsValidClipboardType(clipboard_type) || !IsValidClipboardFormat(format))
return PP_FALSE;
bool result = false;
dispatcher()->Send(new PpapiHostMsg_PPBFlash_IsClipboardFormatAvailable(
API_ID_PPB_FLASH,
instance,
static_cast<int>(clipboard_type),
static_cast<int>(format),
&result));
return PP_FromBool(result);
}
PP_Var PPB_Flash_Proxy::ReadClipboardData(
PP_Instance instance,
PP_Flash_Clipboard_Type clipboard_type,
PP_Flash_Clipboard_Format format) {
if (!IsValidClipboardType(clipboard_type) || !IsValidClipboardFormat(format))
return PP_MakeUndefined();
ReceiveSerializedVarReturnValue result;
dispatcher()->Send(new PpapiHostMsg_PPBFlash_ReadClipboardData(
API_ID_PPB_FLASH, instance,
static_cast<int>(clipboard_type), static_cast<int>(format), &result));
return result.Return(dispatcher());
}
int32_t PPB_Flash_Proxy::WriteClipboardData(
PP_Instance instance,
PP_Flash_Clipboard_Type clipboard_type,
uint32_t data_item_count,
const PP_Flash_Clipboard_Format formats[],
const PP_Var data_items[]) {
if (!IsValidClipboardType(clipboard_type))
return PP_ERROR_BADARGUMENT;
std::vector<SerializedVar> data_items_vector;
SerializedVarSendInput::ConvertVector(
dispatcher(),
data_items,
data_item_count,
&data_items_vector);
for (size_t i = 0; i < data_item_count; ++i) {
if (!IsValidClipboardFormat(formats[i]))
return PP_ERROR_BADARGUMENT;
}
std::vector<int> formats_vector(formats, formats + data_item_count);
dispatcher()->Send(new PpapiHostMsg_PPBFlash_WriteClipboardData(
API_ID_PPB_FLASH,
instance,
static_cast<int>(clipboard_type),
formats_vector,
data_items_vector));
// Assume success, since it allows us to avoid a sync IPC.
return PP_OK;
}
bool PPB_Flash_Proxy::CreateThreadAdapterForInstance(PP_Instance instance) {
return true;
}
void PPB_Flash_Proxy::ClearThreadAdapterForInstance(PP_Instance instance) {
}
int32_t PPB_Flash_Proxy::OpenFile(PP_Instance,
const char* path,
int32_t mode,
PP_FileHandle* file) {
int flags = 0;
if (!path ||
!ppapi::PepperFileOpenFlagsToPlatformFileFlags(mode, &flags) ||
!file)
return PP_ERROR_BADARGUMENT;
base::PlatformFileError error;
IPC::PlatformFileForTransit transit_file;
ppapi::PepperFilePath pepper_path(ppapi::PepperFilePath::DOMAIN_MODULE_LOCAL,
FilePath::FromUTF8Unsafe(path));
if (PluginGlobals::Get()->plugin_proxy_delegate()->SendToBrowser(
new PepperFileMsg_OpenFile(pepper_path, flags,
&error, &transit_file))) {
*file = IPC::PlatformFileForTransitToPlatformFile(transit_file);
} else {
*file = base::kInvalidPlatformFileValue;
error = base::PLATFORM_FILE_ERROR_FAILED;
}
return ppapi::PlatformFileErrorToPepperError(error);
}
int32_t PPB_Flash_Proxy::RenameFile(PP_Instance,
const char* from_path,
const char* to_path) {
base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
ppapi::PepperFilePath pepper_from(ppapi::PepperFilePath::DOMAIN_MODULE_LOCAL,
FilePath::FromUTF8Unsafe(from_path));
ppapi::PepperFilePath pepper_to(ppapi::PepperFilePath::DOMAIN_MODULE_LOCAL,
FilePath::FromUTF8Unsafe(to_path));
PluginGlobals::Get()->plugin_proxy_delegate()->SendToBrowser(
new PepperFileMsg_RenameFile(pepper_from, pepper_to, &error));
return ppapi::PlatformFileErrorToPepperError(error);
}
int32_t PPB_Flash_Proxy::DeleteFileOrDir(PP_Instance,
const char* path,
PP_Bool recursive) {
base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
ppapi::PepperFilePath pepper_path(ppapi::PepperFilePath::DOMAIN_MODULE_LOCAL,
FilePath::FromUTF8Unsafe(path));
PluginGlobals::Get()->plugin_proxy_delegate()->SendToBrowser(
new PepperFileMsg_DeleteFileOrDir(pepper_path,
PP_ToBool(recursive),
&error));
return ppapi::PlatformFileErrorToPepperError(error);
}
int32_t PPB_Flash_Proxy::CreateDir(PP_Instance, const char* path) {
base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
ppapi::PepperFilePath pepper_path(ppapi::PepperFilePath::DOMAIN_MODULE_LOCAL,
FilePath::FromUTF8Unsafe(path));
PluginGlobals::Get()->plugin_proxy_delegate()->SendToBrowser(
new PepperFileMsg_CreateDir(pepper_path, &error));
return ppapi::PlatformFileErrorToPepperError(error);
}
int32_t PPB_Flash_Proxy::QueryFile(PP_Instance,
const char* path,
PP_FileInfo* info) {
base::PlatformFileInfo file_info;
base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
ppapi::PepperFilePath pepper_path(ppapi::PepperFilePath::DOMAIN_MODULE_LOCAL,
FilePath::FromUTF8Unsafe(path));
PluginGlobals::Get()->plugin_proxy_delegate()->SendToBrowser(
new PepperFileMsg_QueryFile(pepper_path, &file_info, &error));
if (error == base::PLATFORM_FILE_OK) {
info->size = file_info.size;
info->creation_time = TimeToPPTime(file_info.creation_time);
info->last_access_time = TimeToPPTime(file_info.last_accessed);
info->last_modified_time = TimeToPPTime(file_info.last_modified);
info->system_type = PP_FILESYSTEMTYPE_EXTERNAL;
if (file_info.is_directory)
info->type = PP_FILETYPE_DIRECTORY;
else
info->type = PP_FILETYPE_REGULAR;
}
return ppapi::PlatformFileErrorToPepperError(error);
}
int32_t PPB_Flash_Proxy::GetDirContents(PP_Instance,
const char* path,
PP_DirContents_Dev** contents) {
ppapi::DirContents entries;
base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
ppapi::PepperFilePath pepper_path(ppapi::PepperFilePath::DOMAIN_MODULE_LOCAL,
FilePath::FromUTF8Unsafe(path));
PluginGlobals::Get()->plugin_proxy_delegate()->SendToBrowser(
new PepperFileMsg_GetDirContents(pepper_path, &entries, &error));
if (error == base::PLATFORM_FILE_OK) {
// Copy the serialized dir entries to the output struct.
*contents = new PP_DirContents_Dev;
(*contents)->count = static_cast<int32_t>(entries.size());
(*contents)->entries = new PP_DirEntry_Dev[entries.size()];
for (size_t i = 0; i < entries.size(); i++) {
const ppapi::DirEntry& source = entries[i];
PP_DirEntry_Dev* dest = &(*contents)->entries[i];
std::string name = source.name.AsUTF8Unsafe();
char* name_copy = new char[name.size() + 1];
memcpy(name_copy, name.c_str(), name.size() + 1);
dest->name = name_copy;
dest->is_dir = PP_FromBool(source.is_dir);
}
}
return ppapi::PlatformFileErrorToPepperError(error);
}
int32_t PPB_Flash_Proxy::CreateTemporaryFile(PP_Instance instance,
PP_FileHandle* file) {
if (!file)
return PP_ERROR_BADARGUMENT;
base::PlatformFileError error;
IPC::PlatformFileForTransit transit_file;
if (PluginGlobals::Get()->plugin_proxy_delegate()->SendToBrowser(
new PepperFileMsg_CreateTemporaryFile(&error, &transit_file))) {
*file = IPC::PlatformFileForTransitToPlatformFile(transit_file);
} else {
error = base::PLATFORM_FILE_ERROR_FAILED;
*file = base::kInvalidPlatformFileValue;
}
return ppapi::PlatformFileErrorToPepperError(error);
}
int32_t PPB_Flash_Proxy::OpenFileRef(PP_Instance instance,
PP_Resource file_ref_id,
int32_t mode,
PP_FileHandle* file) {
EnterResourceNoLock<thunk::PPB_FileRef_API> enter(file_ref_id, true);
if (enter.failed())
return PP_ERROR_BADRESOURCE;
int32_t result = PP_ERROR_FAILED;
IPC::PlatformFileForTransit transit;
dispatcher()->Send(new PpapiHostMsg_PPBFlash_OpenFileRef(
API_ID_PPB_FLASH, instance, enter.resource()->host_resource(), mode,
&transit, &result));
*file = IPC::PlatformFileForTransitToPlatformFile(transit);
return result;
}
int32_t PPB_Flash_Proxy::QueryFileRef(PP_Instance instance,
PP_Resource file_ref_id,
PP_FileInfo* info) {
EnterResourceNoLock<thunk::PPB_FileRef_API> enter(file_ref_id, true);
if (enter.failed())
return PP_ERROR_BADRESOURCE;
int32_t result = PP_ERROR_FAILED;
dispatcher()->Send(new PpapiHostMsg_PPBFlash_QueryFileRef(
API_ID_PPB_FLASH, instance, enter.resource()->host_resource(), info,
&result));
return result;
}
PP_Bool PPB_Flash_Proxy::FlashIsFullscreen(PP_Instance instance) {
InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())->
GetInstanceData(instance);
if (!data)
return PP_FALSE;
return data->flash_fullscreen;
}
PP_Bool PPB_Flash_Proxy::FlashSetFullscreen(PP_Instance instance,
PP_Bool fullscreen) {
PP_Bool result = PP_FALSE;
dispatcher()->Send(new PpapiHostMsg_PPBFlash_FlashSetFullscreen(
API_ID_PPB_FLASH, instance, fullscreen, &result));
return result;
}
PP_Bool PPB_Flash_Proxy::FlashGetScreenSize(PP_Instance instance,
PP_Size* size) {
PP_Bool result = PP_FALSE;
dispatcher()->Send(new PpapiHostMsg_PPBFlash_FlashGetScreenSize(
API_ID_PPB_FLASH, instance, &result, size));
return result;
}
void PPB_Flash_Proxy::OnHostMsgSetInstanceAlwaysOnTop(PP_Instance instance,
PP_Bool on_top) {
EnterInstanceNoLock enter(instance);
if (enter.succeeded())
enter.functions()->GetFlashAPI()->SetInstanceAlwaysOnTop(instance, on_top);
}
void PPB_Flash_Proxy::OnHostMsgDrawGlyphs(
PP_Instance instance,
const PPBFlash_DrawGlyphs_Params& params,
PP_Bool* result) {
*result = PP_FALSE;
EnterInstanceNoLock enter(instance);
if (enter.failed())
return;
PP_FontDescription_Dev font_desc;
params.font_desc.SetToPPFontDescription(dispatcher(), &font_desc, false);
if (params.glyph_indices.size() != params.glyph_advances.size() ||
params.glyph_indices.empty())
return;
*result = enter.functions()->GetFlashAPI()->DrawGlyphs(
0, // Unused instance param.
params.image_data.host_resource(), &font_desc,
params.color, &params.position, &params.clip,
const_cast<float(*)[3]>(params.transformation),
params.allow_subpixel_aa,
static_cast<uint32_t>(params.glyph_indices.size()),
const_cast<uint16_t*>(&params.glyph_indices[0]),
const_cast<PP_Point*>(&params.glyph_advances[0]));
}
void PPB_Flash_Proxy::OnHostMsgGetProxyForURL(PP_Instance instance,
const std::string& url,
SerializedVarReturnValue result) {
EnterInstanceNoLock enter(instance);
if (enter.succeeded()) {
result.Return(dispatcher(),
enter.functions()->GetFlashAPI()->GetProxyForURL(
instance, url.c_str()));
} else {
result.Return(dispatcher(), PP_MakeUndefined());
}
}
void PPB_Flash_Proxy::OnHostMsgNavigate(PP_Instance instance,
const URLRequestInfoData& data,
const std::string& target,
PP_Bool from_user_action,
int32_t* result) {
EnterInstanceNoLock enter_instance(instance);
if (enter_instance.failed()) {
*result = PP_ERROR_BADARGUMENT;
return;
}
DCHECK(!dispatcher()->IsPlugin());
// Validate the PP_Instance since we'll be constructing resources on its
// behalf.
HostDispatcher* host_dispatcher = static_cast<HostDispatcher*>(dispatcher());
if (HostDispatcher::GetForInstance(instance) != host_dispatcher) {
NOTREACHED();
*result = PP_ERROR_BADARGUMENT;
return;
}
// We need to allow re-entrancy here, because this may call into Javascript
// (e.g. with a "javascript:" URL), or do things like navigate away from the
// page, either one of which will need to re-enter into the plugin.
// It is safe, because it is essentially equivalent to NPN_GetURL, where Flash
// would expect re-entrancy. When running in-process, it does re-enter here.
host_dispatcher->set_allow_plugin_reentrancy();
*result = enter_instance.functions()->GetFlashAPI()->Navigate(
instance, data, target.c_str(), from_user_action);
}
void PPB_Flash_Proxy::OnHostMsgRunMessageLoop(PP_Instance instance) {
EnterInstanceNoLock enter(instance);
if (enter.succeeded())
enter.functions()->GetFlashAPI()->RunMessageLoop(instance);
}
void PPB_Flash_Proxy::OnHostMsgQuitMessageLoop(PP_Instance instance) {
EnterInstanceNoLock enter(instance);
if (enter.succeeded())
enter.functions()->GetFlashAPI()->QuitMessageLoop(instance);
}
void PPB_Flash_Proxy::OnHostMsgGetLocalTimeZoneOffset(PP_Instance instance,
PP_Time t,
double* result) {
EnterInstanceNoLock enter(instance);
if (enter.succeeded()) {
*result = enter.functions()->GetFlashAPI()->GetLocalTimeZoneOffset(
instance, t);
} else {
*result = 0.0;
}
}
void PPB_Flash_Proxy::OnHostMsgIsRectTopmost(PP_Instance instance,
PP_Rect rect,
PP_Bool* result) {
EnterInstanceNoLock enter(instance);
if (enter.succeeded())
*result = enter.functions()->GetFlashAPI()->IsRectTopmost(instance, &rect);
else
*result = PP_FALSE;
}
void PPB_Flash_Proxy::OnHostMsgFlashSetFullscreen(PP_Instance instance,
PP_Bool fullscreen,
PP_Bool* result) {
EnterInstanceNoLock enter(instance);
if (enter.succeeded()) {
*result = enter.functions()->GetFlashAPI()->FlashSetFullscreen(
instance, fullscreen);
} else {
*result = PP_FALSE;
}
}
void PPB_Flash_Proxy::OnHostMsgFlashGetScreenSize(PP_Instance instance,
PP_Bool* result,
PP_Size* size) {
EnterInstanceNoLock enter(instance);
if (enter.succeeded()) {
*result = enter.functions()->GetFlashAPI()->FlashGetScreenSize(
instance, size);
} else {
size->width = 0;
size->height = 0;
}
}
void PPB_Flash_Proxy::OnHostMsgIsClipboardFormatAvailable(
PP_Instance instance,
int clipboard_type,
int format,
bool* result) {
EnterInstanceNoLock enter(instance);
if (enter.succeeded()) {
*result = PP_ToBool(
enter.functions()->GetFlashAPI()->IsClipboardFormatAvailable(
instance,
static_cast<PP_Flash_Clipboard_Type>(clipboard_type),
static_cast<PP_Flash_Clipboard_Format>(format)));
} else {
*result = false;
}
}
void PPB_Flash_Proxy::OnHostMsgReadClipboardData(
PP_Instance instance,
int clipboard_type,
int format,
SerializedVarReturnValue result) {
EnterInstanceNoLock enter(instance);
if (enter.succeeded()) {
result.Return(dispatcher(),
enter.functions()->GetFlashAPI()->ReadClipboardData(
instance,
static_cast<PP_Flash_Clipboard_Type>(clipboard_type),
static_cast<PP_Flash_Clipboard_Format>(format)));
}
}
void PPB_Flash_Proxy::OnHostMsgWriteClipboardData(
PP_Instance instance,
int clipboard_type,
const std::vector<int>& formats,
SerializedVarVectorReceiveInput data_items) {
EnterInstanceNoLock enter(instance);
if (enter.succeeded()) {
uint32_t data_item_count;
PP_Var* data_items_array = data_items.Get(dispatcher(), &data_item_count);
CHECK(data_item_count == formats.size());
scoped_array<PP_Flash_Clipboard_Format> formats_array(
new PP_Flash_Clipboard_Format[formats.size()]);
for (uint32_t i = 0; i < formats.size(); ++i)
formats_array[i] = static_cast<PP_Flash_Clipboard_Format>(formats[i]);
int32_t result = enter.functions()->GetFlashAPI()->WriteClipboardData(
instance,
static_cast<PP_Flash_Clipboard_Type>(clipboard_type),
data_item_count,
formats_array.get(),
data_items_array);
DLOG_IF(WARNING, result != PP_OK)
<< "Write to clipboard failed unexpectedly.";
(void)result; // Prevent warning in release mode.
}
}
void PPB_Flash_Proxy::OnHostMsgOpenFileRef(
PP_Instance instance,
const HostResource& host_resource,
int32_t mode,
IPC::PlatformFileForTransit* file_handle,
int32_t* result) {
EnterInstanceNoLock enter(instance);
if (enter.failed()) {
*result = PP_ERROR_BADARGUMENT;
return;
}
base::PlatformFile file;
*result = enter.functions()->GetFlashAPI()->OpenFileRef(
instance, host_resource.host_resource(), mode, &file);
*file_handle = PlatformFileToPlatformFileForTransit(dispatcher(),
result, file);
}
void PPB_Flash_Proxy::OnHostMsgQueryFileRef(
PP_Instance instance,
const HostResource& host_resource,
PP_FileInfo* info,
int32_t* result) {
EnterInstanceNoLock enter(instance);
if (enter.failed()) {
*result = PP_ERROR_BADARGUMENT;
return;
}
*result = enter.functions()->GetFlashAPI()->QueryFileRef(
instance, host_resource.host_resource(), info);
}
void PPB_Flash_Proxy::OnHostMsgGetSetting(PP_Instance instance,
PP_FlashSetting setting,
SerializedVarReturnValue id) {
EnterInstanceNoLock enter(instance);
if (enter.succeeded()) {
id.Return(dispatcher(),
enter.functions()->GetFlashAPI()->GetSetting(
instance, setting));
} else {
id.Return(dispatcher(), PP_MakeUndefined());
}
}
void PPB_Flash_Proxy::OnHostMsgGetDeviceID(PP_Instance instance,
SerializedVarReturnValue id) {
EnterInstanceNoLock enter(instance);
if (enter.succeeded()) {
id.Return(dispatcher(),
enter.functions()->GetFlashAPI()->GetDeviceID(
instance));
} else {
id.Return(dispatcher(), PP_MakeUndefined());
}
}
void PPB_Flash_Proxy::OnHostMsgInvokePrinting(PP_Instance instance) {
// This function is actually implemented in the PPB_Flash_Print interface.
// It's rarely used enough that we just request this interface when needed.
const PPB_Flash_Print_1_0* print_interface =
static_cast<const PPB_Flash_Print_1_0*>(
dispatcher()->local_get_interface()(PPB_FLASH_PRINT_INTERFACE_1_0));
if (print_interface)
print_interface->InvokePrinting(instance);
}
} // namespace proxy
} // namespace ppapi