blob: 5eafabee209360140587b5df3c62c00789441fac [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 "build/build_config.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/c/trusted/ppb_browser_font_trusted.h"
#include "ppapi/proxy/host_dispatcher.h"
#include "ppapi/proxy/plugin_dispatcher.h"
#include "ppapi/proxy/plugin_globals.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/proxy_module.h"
#include "ppapi/proxy/serialized_var.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/var.h"
#include "ppapi/shared_impl/var_tracker.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 {
void InvokePrinting(PP_Instance instance) {
ProxyAutoLock lock;
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) {
if (!dispatcher()->permissions().HasPermission(PERMISSION_FLASH))
return false;
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_Navigate, OnHostMsgNavigate)
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_IsRectTopmost,
OnHostMsgIsRectTopmost)
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_BrowserFont_Trusted_Description* 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.SetFromPPBrowserFontDescription(*font_desc);
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;
}
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;
}
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;
}
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()->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();
}
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;
if (params.glyph_indices.size() != params.glyph_advances.size() ||
params.glyph_indices.empty())
return;
PP_BrowserFont_Trusted_Description font_desc;
params.font_desc.SetToPPBrowserFontDescription(&font_desc);
*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]));
// SetToPPFontDescription() creates a var which is owned by the caller.
PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(font_desc.face);
}
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::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::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::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