123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432 |
- // Copyright 2015 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.
- //
- // A simple C++ Pepper plugin for exercising deprecated PPAPI interfaces in
- // Blink layout tests.
- //
- // Most layout tests should prefer to use the normal Blink test plugin, with the
- // MIME type application/x-blink-test-plugin. For layout tests that absolutely
- // need to test deprecated synchronous scripting interfaces, this plugin can be
- // instantiated using the application/x-blink-deprecated-test-plugin MIME type.
- //
- // The plugin exposes the following interface:
- //
- // Attributes:
- // testwindowopen: if set, the plugin will synchronously attempt to open a
- // window from DidCreateInstance, and log a message if successful.
- //
- // keydownscript: if set, the plugin will execute the value of the attribute as
- // a script on a key down.
- //
- // mousedownscript: if set, the plugin will execute the value of the attribute
- // as a script on a mouse button down.
- //
- //
- // Functions:
- // * plugin.normalize(): synchronously calls window.pluginCallback.
- //
- // * plugin.remember(value): keeps a reference on |value| in the plugin.
- //
- // * plugin.testCloneObject(): creates and returns another instance of the
- // plugin object.
- //
- // * plugin.testCreateTestObject(): creates and returns a new TestObject
- // instance (see below).
- //
- // * plugin.testExecuteScript(script): synchronously evaluates |script| and
- // returns the result.
- //
- // * plugin.testGetProperty(property): returns the property named |property|
- // from the window object.
- //
- // * plugin.testPassTestObject(function, object): synchronously calls the
- // function named |function| on the window object, passing it |object| as a
- // parameter, and returns its result.
- //
- // * plugin.testScriptObjectInvoke(function, value): synchronously calls the
- // function named |function| on the window object, passing it |value| as a
- // parameter, and returns its result.
- //
- //
- // Properties:
- // * plugin.testObject (read-only): a TestObject instance (see below).
- //
- // * plugin.testObjectCount (read-only): the number of TestObject instance
- // created.
- //
- // * plugin.testGetUndefined (read-only): returns undefined.
- //
- //
- // TestObject exposes the following interface:
- // Properties:
- // * object.testObject (read-only: another TestObject instance.
- #include <stdint.h>
- #include <map>
- #include <sstream>
- #include <unordered_map>
- #include <utility>
- #include "base/bind.h"
- #include "base/callback.h"
- #include "base/callback_helpers.h"
- #include "base/strings/stringprintf.h"
- #include "ppapi/cpp/dev/scriptable_object_deprecated.h"
- #include "ppapi/cpp/input_event.h"
- #include "ppapi/cpp/module.h"
- #include "ppapi/cpp/private/instance_private.h"
- #include "ppapi/cpp/private/var_private.h"
- #include "ppapi/cpp/var.h"
- namespace {
- class ScriptableBase : public pp::deprecated::ScriptableObject {
- public:
- explicit ScriptableBase(pp::InstancePrivate* instance)
- : instance_(instance) {}
- ~ScriptableBase() override {}
- // pp::deprecated::ScriptableObject overrides:
- bool HasMethod(const pp::Var& name, pp::Var* exception) override {
- return FindMethod(name) != methods_.end();
- }
- bool HasProperty(const pp::Var& name, pp::Var* exception) override {
- return FindProperty(name) != properties_.end();
- }
- pp::Var Call(const pp::Var& method_name,
- const std::vector<pp::Var>& args,
- pp::Var* exception) override {
- auto method = FindMethod(method_name);
- if (method != methods_.end()) {
- return method->second.Run(args, exception);
- }
- return ScriptableObject::Call(method_name, args, exception);
- }
- pp::Var GetProperty(const pp::Var& name, pp::Var* exception) override {
- auto accessor = FindProperty(name);
- if (accessor != properties_.end()) {
- pp::Var value;
- accessor->second.Run(false, &value);
- return value;
- }
- return ScriptableObject::GetProperty(name, exception);
- }
- void SetProperty(const pp::Var& name,
- const pp::Var& value,
- pp::Var* exception) override {
- auto accessor = FindProperty(name);
- if (accessor != properties_.end())
- accessor->second.Run(true, const_cast<pp::Var*>(&value));
- else
- ScriptableObject::SetProperty(name, value, exception);
- }
- protected:
- using MethodMap = std::map<
- std::string,
- base::RepeatingCallback<pp::Var(const std::vector<pp::Var>&, pp::Var*)>>;
- using PropertyMap =
- std::map<std::string, base::RepeatingCallback<void(bool, pp::Var*)>>;
- MethodMap::iterator FindMethod(const pp::Var& name) {
- if (!name.is_string())
- return methods_.end();
- return methods_.find(name.AsString());
- }
- PropertyMap::iterator FindProperty(const pp::Var& name) {
- if (!name.is_string())
- return properties_.end();
- return properties_.find(name.AsString());
- }
- pp::InstancePrivate* const instance_;
- MethodMap methods_;
- PropertyMap properties_;
- };
- class TestObjectSO : public ScriptableBase {
- public:
- explicit TestObjectSO(pp::InstancePrivate* instance)
- : ScriptableBase(instance) {
- ++count_;
- properties_.insert(std::make_pair(
- "testObject", base::BindRepeating(&TestObjectSO::TestObjectAccessor,
- base::Unretained(this))));
- }
- ~TestObjectSO() override {
- --count_;
- }
- static int32_t count() { return count_; }
- private:
- void TestObjectAccessor(bool set, pp::Var* var) {
- if (set)
- return;
- if (test_object_.is_undefined())
- test_object_ = pp::VarPrivate(instance_, new TestObjectSO(instance_));
- *var = test_object_;
- }
- static int32_t count_;
- pp::VarPrivate test_object_;
- };
- int32_t TestObjectSO::count_ = 0;
- class InstanceSO : public ScriptableBase {
- public:
- explicit InstanceSO(pp::InstancePrivate* instance)
- : ScriptableBase(instance) {
- methods_.insert(std::make_pair(
- "normalize",
- base::BindRepeating(&InstanceSO::Normalize, base::Unretained(this))));
- methods_.insert(std::make_pair(
- "remember",
- base::BindRepeating(&InstanceSO::Remember, base::Unretained(this))));
- methods_.insert(std::make_pair(
- "testCloneObject", base::BindRepeating(&InstanceSO::TestCloneObject,
- base::Unretained(this))));
- methods_.insert(
- std::make_pair("testCreateTestObject",
- base::BindRepeating(&InstanceSO::TestCreateTestObject,
- base::Unretained(this))));
- methods_.insert(std::make_pair(
- "testExecuteScript", base::BindRepeating(&InstanceSO::TestExecuteScript,
- base::Unretained(this))));
- methods_.insert(std::make_pair(
- "testGetProperty", base::BindRepeating(&InstanceSO::TestGetProperty,
- base::Unretained(this))));
- methods_.insert(
- std::make_pair("testPassTestObject",
- base::BindRepeating(&InstanceSO::TestPassTestObject,
- base::Unretained(this))));
- // Note: the semantics of testScriptObjectInvoke are identical to the
- // semantics of testPassTestObject: call args[0] with args[1] as a
- // parameter.
- methods_.insert(
- std::make_pair("testScriptObjectInvoke",
- base::BindRepeating(&InstanceSO::TestPassTestObject,
- base::Unretained(this))));
- properties_.insert(std::make_pair(
- "testObject", base::BindRepeating(&InstanceSO::TestObjectAccessor,
- base::Unretained(this))));
- properties_.insert(
- std::make_pair("testObjectCount",
- base::BindRepeating(&InstanceSO::TestObjectCountAccessor,
- base::Unretained(this))));
- properties_.insert(std::make_pair(
- "testGetUndefined",
- base::BindRepeating(&InstanceSO::TestGetUndefinedAccessor,
- base::Unretained(this))));
- }
- ~InstanceSO() override = default;
- private:
- // Requires no argument.
- pp::Var Normalize(const std::vector<pp::Var>& args, pp::Var* exception) {
- pp::VarPrivate object = instance_->GetWindowObject();
- return object.Call(pp::Var("pluginCallback"), exception);
- }
- // Requires 1 argument. The argument is retained into remembered_
- pp::Var Remember(const std::vector<pp::Var>& args, pp::Var* exception) {
- if (args.size() != 1) {
- *exception = pp::Var("remember requires one argument");
- return pp::Var();
- }
- remembered_ = args[0];
- return pp::Var();
- }
- // Requires no argument.
- pp::Var TestCloneObject(const std::vector<pp::Var>& args,
- pp::Var* exception) {
- return pp::VarPrivate(instance_, new InstanceSO(instance_));
- }
- // Requires no argument.
- pp::Var TestCreateTestObject(const std::vector<pp::Var>& args,
- pp::Var* exception) {
- return pp::VarPrivate(instance_, new TestObjectSO(instance_));
- }
- // Requires one argument. The argument is passed through as-is to
- // pp::InstancePrivate::ExecuteScript().
- pp::Var TestExecuteScript(const std::vector<pp::Var>& args,
- pp::Var* exception) {
- if (args.size() != 1) {
- *exception = pp::Var("testExecuteScript requires one argument");
- return pp::Var();
- }
- return instance_->ExecuteScript(args[0], exception);
- }
- // Requires one or more arguments. Roughly analogous to NPN_GetProperty.
- // The arguments are the chain of properties to traverse, starting with the
- // global context.
- pp::Var TestGetProperty(const std::vector<pp::Var>& args,
- pp::Var* exception) {
- if (args.size() < 1) {
- *exception = pp::Var("testGetProperty requires at least one argument");
- return pp::Var();
- }
- pp::VarPrivate object = instance_->GetWindowObject();
- for (const auto& arg : args) {
- if (!object.HasProperty(arg, exception))
- return pp::Var();
- object = object.GetProperty(arg, exception);
- }
- return object;
- }
- // Requires 2 or more arguments. The first argument is the name of a function
- // to invoke, and the second argument is a value to pass to that function.
- pp::Var TestPassTestObject(const std::vector<pp::Var>& args,
- pp::Var* exception) {
- if (args.size() < 2) {
- *exception = pp::Var("testPassTestObject requires at least 2 arguments");
- return pp::Var();
- }
- pp::VarPrivate object = instance_->GetWindowObject();
- return object.Call(args[0], args[1], exception);
- }
- void TestObjectAccessor(bool set, pp::Var* var) {
- if (set)
- return;
- if (test_object_.is_undefined())
- test_object_ = pp::VarPrivate(instance_, new TestObjectSO(instance_));
- *var = test_object_;
- }
- void TestObjectCountAccessor(bool set, pp::Var* var) {
- if (set)
- return;
- *var = pp::Var(TestObjectSO::count());
- }
- void TestGetUndefinedAccessor(bool set, pp::Var* var) {
- if (set)
- return;
- *var = pp::Var();
- }
- pp::VarPrivate test_object_;
- pp::Var remembered_;
- };
- class BlinkDeprecatedTestInstance : public pp::InstancePrivate {
- public:
- explicit BlinkDeprecatedTestInstance(PP_Instance instance)
- : pp::InstancePrivate(instance) {}
- ~BlinkDeprecatedTestInstance() override {
- LogMessage("%s", "Destroying");
- }
- // pp::Instance overrides
- bool Init(uint32_t argc, const char* argn[], const char* argv[]) override {
- for (uint32_t i = 0; i < argc; ++i)
- attributes_[argn[i]] = argv[i];
- if (HasAttribute("testwindowopen"))
- return TestWindowOpen();
- if (HasAttribute("initscript"))
- ExecuteScript(attributes_["initscript"]);
- uint32_t event_classes = 0;
- if (HasAttribute("keydownscript"))
- event_classes |= PP_INPUTEVENT_CLASS_KEYBOARD;
- if (HasAttribute("mousedownscript"))
- event_classes |= PP_INPUTEVENT_CLASS_MOUSE;
- RequestFilteringInputEvents(event_classes);
- return true;
- }
- virtual bool HandleInputEvent(const pp::InputEvent& event) override {
- switch (event.GetType()) {
- case PP_INPUTEVENT_TYPE_MOUSEDOWN:
- if (HasAttribute("mousedownscript"))
- ExecuteScript(attributes_["mousedownscript"]);
- return true;
- case PP_INPUTEVENT_TYPE_KEYDOWN:
- if (HasAttribute("keydownscript"))
- ExecuteScript(attributes_["keydownscript"]);
- return true;
- default:
- return false;
- }
- }
- // pp::InstancePrivate overrides:
- pp::Var GetInstanceObject() override {
- if (instance_var_.is_undefined()) {
- instance_so_ = new InstanceSO(this);
- instance_var_ = pp::VarPrivate(this, instance_so_);
- }
- return instance_var_;
- }
- void NotifyTestCompletion() {
- ExecuteScript("window.testRunner.notifyDone()");
- }
- bool TestWindowOpen() {
- pp::Var result = GetWindowObject().Call(
- pp::Var("open"), pp::Var("about:blank"), pp::Var("_blank"));
- if (result.is_object())
- LogMessage("PLUGIN: WINDOW OPEN SUCCESS");
- NotifyTestCompletion();
- return true;
- }
- void LogMessage(const char* format...) {
- va_list args;
- va_start(args, format);
- LogToConsoleWithSource(PP_LOGLEVEL_LOG,
- pp::Var("Blink Deprecated Test Plugin"),
- pp::Var(base::StringPrintV(format, args)));
- va_end(args);
- }
- private:
- bool HasAttribute(const std::string& name) {
- return attributes_.find(name) != attributes_.end();
- }
- std::unordered_map<std::string, std::string> attributes_;
- pp::VarPrivate instance_var_;
- // Owned by |instance_var_|.
- InstanceSO* instance_so_;
- };
- class BlinkDeprecatedTestModule : public pp::Module {
- public:
- BlinkDeprecatedTestModule() {}
- ~BlinkDeprecatedTestModule() override {}
- pp::Instance* CreateInstance(PP_Instance instance) override {
- return new BlinkDeprecatedTestInstance(instance);
- }
- };
- } // namespace
- namespace pp {
- Module* CreateModule() {
- return new BlinkDeprecatedTestModule();
- }
- } // namespace pp
|