| Index: ppapi/examples/extensions/extensions.cc
|
| diff --git a/ppapi/examples/extensions/extensions.cc b/ppapi/examples/extensions/extensions.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..659d1d8096e3e106d3d85db54a1fa5961947fa35
|
| --- /dev/null
|
| +++ b/ppapi/examples/extensions/extensions.cc
|
| @@ -0,0 +1,374 @@
|
| +// Copyright (c) 2013 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/c/dev/ppb_alarms_dev.h"
|
| +#include "ppapi/c/dev/ppb_memory_dev.h"
|
| +#include "ppapi/c/ppb_console.h"
|
| +#include "ppapi/c/ppb_input_event.h"
|
| +#include "ppapi/c/ppb_var.h"
|
| +#include "ppapi/cpp/dev/alarms_dev.h"
|
| +#include "ppapi/cpp/graphics_2d.h"
|
| +#include "ppapi/cpp/image_data.h"
|
| +#include "ppapi/cpp/input_event.h"
|
| +#include "ppapi/cpp/instance.h"
|
| +#include "ppapi/cpp/logging.h"
|
| +#include "ppapi/cpp/module.h"
|
| +#include "ppapi/cpp/rect.h"
|
| +#include "ppapi/cpp/var.h"
|
| +#include "ppapi/utility/completion_callback_factory.h"
|
| +
|
| +using namespace pp;
|
| +
|
| +const PPB_Console* console = NULL;
|
| +const PPB_Alarms_Dev* alarms_interface = NULL;
|
| +const PPB_Var* var_interface = NULL;
|
| +
|
| +class MyInstance : public Instance {
|
| + public:
|
| + explicit MyInstance(PP_Instance instance)
|
| + : Instance(instance),
|
| + width_(0),
|
| + height_(0),
|
| + pending_paint_(false),
|
| + waiting_for_flush_completion_(false),
|
| + callback_factory_(this),
|
| + alarms_(InstanceHandle(instance)) {
|
| + }
|
| + virtual ~MyInstance() {
|
| + }
|
| +
|
| + virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
|
| + console = static_cast<const PPB_Console*>(
|
| + Module::Get()->GetBrowserInterface(PPB_CONSOLE_INTERFACE));
|
| + if (!console)
|
| + return false;
|
| +
|
| + alarms_interface = static_cast<const PPB_Alarms_Dev*>(
|
| + Module::Get()->GetBrowserInterface(PPB_ALARMS_DEV_INTERFACE));
|
| + if (!alarms_interface)
|
| + return false;
|
| +
|
| + var_interface = static_cast<const PPB_Var*>(
|
| + Module::Get()->GetBrowserInterface(PPB_VAR_INTERFACE));
|
| + if (!var_interface)
|
| + return false;
|
| +
|
| + RequestInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD);
|
| + return true;
|
| + }
|
| +
|
| + virtual bool HandleInputEvent(const InputEvent& event) {
|
| + switch (event.GetType()) {
|
| + case PP_INPUTEVENT_TYPE_KEYDOWN: {
|
| + KeyboardInputEvent key_event(event);
|
| + switch (key_event.GetKeyCode()) {
|
| + /////////////////////////////////////////////////////////////////////
|
| + // Exercise the C interface PPB_Alarms_Dev.
|
| + /////////////////////////////////////////////////////////////////////
|
| + case '1' : { // Create()
|
| + PP_Var name = var_interface->VarFromUtf8("alarms2",
|
| + strlen("alarms2"));
|
| + PP_Alarms_AlarmCreateInfo_Dev create_info = {
|
| + {0, PP_FALSE},
|
| + {1, PP_TRUE},
|
| + {1, PP_TRUE}
|
| + };
|
| +
|
| + alarms_interface->Create(pp_instance(), name, &create_info);
|
| +
|
| + var_interface->Release(name);
|
| + break;
|
| + }
|
| + case '2' : { // Get()
|
| + PP_Var name = var_interface->VarFromUtf8("alarms2",
|
| + strlen("alarms2"));
|
| + PP_Alarms_Alarm_Dev* alarm = new PP_Alarms_Alarm_Dev();
|
| +
|
| + // GetCallbackInC() will delete |alarm|.
|
| + // NOTE: |callback_factory_| should not be used in this case.
|
| + // Otherwise, |alarm| is leaked if this object is destroyed before
|
| + // the callback is executed.
|
| + PP_CompletionCallback callback = PP_MakeCompletionCallback(
|
| + &MyInstance::GetCallbackInC, alarm);
|
| +
|
| + int32_t result = alarms_interface->Get(pp_instance(), name, alarm,
|
| + callback);
|
| + PP_DCHECK(result == PP_OK_COMPLETIONPENDING);
|
| + var_interface->Release(name);
|
| + break;
|
| + }
|
| + case '3' : { // GetAll()
|
| + PP_Alarms_Alarm_Array_Dev* alarms = new PP_Alarms_Alarm_Array_Dev();
|
| + PP_ArrayOutput array_allocator =
|
| + { &MyInstance::GetDataBuffer, NULL };
|
| +
|
| + // GetAllCallbackInC() will delete |alarms|.
|
| + // NOTE: |callback_factory_| should not be used in this case.
|
| + // Otherwise, |alarms| is leaked if this object is destroyed before
|
| + // the callback is executed.
|
| + PP_CompletionCallback callback = PP_MakeCompletionCallback(
|
| + &MyInstance::GetAllCallbackInC, alarms);
|
| +
|
| + int32_t result = alarms_interface->GetAll(
|
| + pp_instance(), alarms, array_allocator, callback);
|
| + PP_DCHECK(result == PP_OK_COMPLETIONPENDING);
|
| + break;
|
| + }
|
| + case '4' : { // Clear()
|
| + PP_Var name = var_interface->VarFromUtf8("alarms2",
|
| + strlen("alarms2"));
|
| + alarms_interface->Clear(pp_instance(), name);
|
| + var_interface->Release(name);
|
| + break;
|
| + }
|
| + case '5' : { // Register event
|
| + break;
|
| + }
|
| + case '6' : { // Unregister event
|
| + break;
|
| + }
|
| +
|
| + //////////////////////////////////////////////////////////////////////
|
| + // Exercise the C++ interface pp::alarms::Alarms_Dev.
|
| + //////////////////////////////////////////////////////////////////////
|
| + case 'A' : { // Create()
|
| + std::string name("alarm1");
|
| +
|
| + alarms::AlarmCreateInfo_Dev create_info;
|
| + create_info.set_delay_in_minutes(1);
|
| + create_info.set_period_in_minutes(1);
|
| +
|
| + alarms_.Create(name, create_info);
|
| + break;
|
| + }
|
| + case 'B' : { // Get()
|
| + std::string name("alarm1");
|
| +
|
| + CompletionCallbackWithOutput<alarms::Alarm_Dev>
|
| + callback = callback_factory_.NewCallbackWithOutput(
|
| + &MyInstance::GetCallbackInCpp);
|
| +
|
| + int32_t result = alarms_.Get(name, callback);
|
| + PP_DCHECK(result == PP_OK_COMPLETIONPENDING);
|
| + break;
|
| + }
|
| + case 'C' : { // GetAll()
|
| + CompletionCallbackWithOutput<Array<alarms::Alarm_Dev> >
|
| + callback = callback_factory_.NewCallbackWithOutput(
|
| + &MyInstance::GetAllCallbackInCpp);
|
| +
|
| + int32_t result = alarms_.GetAll(callback);
|
| + PP_DCHECK(result == PP_OK_COMPLETIONPENDING);
|
| + break;
|
| + }
|
| + case 'D' : { // Clear()
|
| + std::string name("alarm1");
|
| + alarms_.Clear(name);
|
| + break;
|
| + }
|
| + case 'E' : { // Register event
|
| + break;
|
| + }
|
| + case 'F' : { // Unregister event
|
| + break;
|
| + }
|
| + default:
|
| + break;
|
| + }
|
| + return true;
|
| + }
|
| + default:
|
| + return false;
|
| + }
|
| + }
|
| +
|
| + virtual void DidChangeView(const Rect& position, const Rect& clip) {
|
| + if (position.size().width() == width_ &&
|
| + position.size().height() == height_)
|
| + return; // We don't care about the position, only the size.
|
| +
|
| + width_ = position.size().width();
|
| + height_ = position.size().height();
|
| +
|
| + device_context_ = Graphics2D(this, Size(width_, height_), false);
|
| + if (!BindGraphics(device_context_))
|
| + return;
|
| +
|
| + Paint();
|
| + }
|
| +
|
| + private:
|
| + //////////////////////////////////////////////////////////////////////////////
|
| + // Exercise the C interface.
|
| + //////////////////////////////////////////////////////////////////////////////
|
| + static void DestroyAlarmStruct(PP_Alarms_Alarm_Dev* alarm) {
|
| + var_interface->Release(alarm->name);
|
| + alarm->name = PP_MakeUndefined();
|
| + }
|
| +
|
| + static void* GetDataBuffer(void* user_data, uint32_t count, uint32_t size) {
|
| + if (size != sizeof(PP_Alarms_Alarm_Dev)) {
|
| + PP_NOTREACHED();
|
| + return NULL;
|
| + }
|
| +
|
| + if (count == 0)
|
| + return NULL;
|
| +
|
| + // We don't have to remember the pointer. The browser is responsible to
|
| + // update |elements| and |size| in PP_Alarms_Alarm_Array_Dev.
|
| + return calloc(count, size);
|
| + }
|
| +
|
| + static void DestroyAlarmArrayStruct(PP_Alarms_Alarm_Array_Dev* alarms) {
|
| + for (uint32_t i = 0; i < alarms->size; ++i)
|
| + DestroyAlarmStruct(alarms->elements + i);
|
| +
|
| + free(alarms->elements);
|
| + alarms->elements = NULL;
|
| + alarms->size = 0;
|
| + }
|
| +
|
| + static void GetAllCallbackInC(void* user_data, int32_t result) {
|
| + PP_Alarms_Alarm_Array_Dev* alarms =
|
| + static_cast<PP_Alarms_Alarm_Array_Dev*>(user_data);
|
| + if (result == PP_OK) {
|
| + for (uint32_t i = 0; i < alarms->size; ++i) {
|
| + PP_Alarms_Alarm_Dev& element = alarms->elements[i];
|
| + // The following fields are available.
|
| + element.name;
|
| + element.scheduled_time;
|
| + if (element.period_in_minutes.is_set)
|
| + element.period_in_minutes.value;
|
| + }
|
| + }
|
| + DestroyAlarmArrayStruct(alarms);
|
| + delete alarms;
|
| + }
|
| +
|
| + static void GetCallbackInC(void* user_data, int32_t result) {
|
| + PP_Alarms_Alarm_Dev* alarm = static_cast<PP_Alarms_Alarm_Dev*>(user_data);
|
| + if (result == PP_OK) {
|
| + // The following fields are available.
|
| + alarm->name;
|
| + alarm->scheduled_time;
|
| + if (alarm->period_in_minutes.is_set)
|
| + alarm->period_in_minutes.value;
|
| + }
|
| + DestroyAlarmStruct(alarm);
|
| + delete alarm;
|
| + }
|
| +
|
| + //////////////////////////////////////////////////////////////////////////////
|
| + // Exercise the C++ interface.
|
| + //////////////////////////////////////////////////////////////////////////////
|
| + void GetAllCallbackInCpp(int32_t result,
|
| + Array<alarms::Alarm_Dev>& alarms) {
|
| + if (result == PP_OK) {
|
| + for (size_t i = 0; i < alarms.size(); ++i) {
|
| + // The following fields are available.
|
| + alarms::Alarm_Dev& alarm = alarms[i];
|
| + alarm.name();
|
| + alarm.scheduled_time();
|
| + if (alarm.is_period_in_minutes_set())
|
| + alarm.period_in_minutes();
|
| + }
|
| + }
|
| + }
|
| +
|
| + void GetCallbackInCpp(int32_t result, alarms::Alarm_Dev& alarm) {
|
| + if (result == PP_OK) {
|
| + // The following fields are available.
|
| + alarm.name();
|
| + alarm.scheduled_time();
|
| + if (alarm.is_period_in_minutes_set())
|
| + alarm.period_in_minutes();
|
| + }
|
| + }
|
| +
|
| + void DidFlush(int32_t result) {
|
| + waiting_for_flush_completion_ = false;
|
| + if (pending_paint_) {
|
| + pending_paint_ = false;
|
| + Paint();
|
| + }
|
| + }
|
| +
|
| + void Paint() {
|
| + if (waiting_for_flush_completion_) {
|
| + pending_paint_ = true;
|
| + return;
|
| + }
|
| +
|
| + ImageData image = PaintImage(width_, height_);
|
| + if (!image.is_null()) {
|
| + device_context_.ReplaceContents(&image);
|
| + waiting_for_flush_completion_ = true;
|
| + device_context_.Flush(
|
| + callback_factory_.NewCallback(&MyInstance::DidFlush));
|
| + }
|
| + }
|
| +
|
| + ImageData PaintImage(int width, int height) {
|
| + ImageData image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL,
|
| + Size(width, height), false);
|
| + if (image.is_null())
|
| + return image;
|
| +
|
| + for (int y = 0; y < image.size().height(); ++y) {
|
| + for (int x = 0; x < image.size().width(); ++x) {
|
| + *image.GetAddr32(Point(x, y)) = 0xfff0f0f0;
|
| + }
|
| + }
|
| +
|
| + return image;
|
| + }
|
| +
|
| + void Log(PP_LogLevel level, const char* format, ...) {
|
| + va_list args;
|
| + va_start(args, format);
|
| + char buf[512];
|
| + vsnprintf(buf, sizeof(buf) - 1, format, args);
|
| + buf[sizeof(buf) - 1] = '\0';
|
| + va_end(args);
|
| +
|
| + Var value(buf);
|
| + console->Log(pp_instance(), level, value.pp_var());
|
| + }
|
| +
|
| + int width_;
|
| + int height_;
|
| +
|
| + bool pending_paint_;
|
| + bool waiting_for_flush_completion_;
|
| +
|
| + CompletionCallbackFactory<MyInstance> callback_factory_;
|
| +
|
| + alarms::Alarms_Dev alarms_;
|
| +
|
| + Graphics2D device_context_;
|
| +};
|
| +
|
| +// This object is the global object representing this plugin library as long
|
| +// as it is loaded.
|
| +class MyModule : public Module {
|
| + public:
|
| + MyModule() : Module() {}
|
| + virtual ~MyModule() {}
|
| +
|
| + // Override CreateInstance to create your customized Instance object.
|
| + virtual Instance* CreateInstance(PP_Instance instance) {
|
| + return new MyInstance(instance);
|
| + }
|
| +};
|
| +
|
| +namespace pp {
|
| +
|
| +// Factory function for your specialization of the Module object.
|
| +Module* CreateModule() {
|
| + return new MyModule();
|
| +}
|
| +
|
| +} // namespace pp
|
| +
|
|
|