[Author: zork]
[google-gears.git] / gears / base / common / html_event_monitor_np.cc
blob7919e2ca68925e5eb9273f607122087fe23dd295
1 // Copyright 2007, Google Inc.
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are met:
5 //
6 // 1. Redistributions of source code must retain the above copyright notice,
7 // this list of conditions and the following disclaimer.
8 // 2. Redistributions in binary form must reproduce the above copyright notice,
9 // this list of conditions and the following disclaimer in the documentation
10 // and/or other materials provided with the distribution.
11 // 3. Neither the name of Google Inc. nor the names of its contributors may be
12 // used to endorse or promote products derived from this software without
13 // specific prior written permission.
15 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
18 // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // This implementation makes use of window.addEventListener() to watch the
27 // event. IE does not support this, but it's not a target for the NPAPI port,
28 // so we're OK.
30 #include "gears/base/common/html_event_monitor.h"
32 #include <assert.h>
34 #include "gears/base/common/dispatcher.h"
35 #include "gears/base/common/string_utils.h"
36 #include "gears/base/npapi/np_utils.h"
37 #include "gears/base/npapi/plugin.h"
38 #include "gears/base/npapi/scoped_npapi_handles.h"
40 DECLARE_DISPATCHER(HtmlEventMonitorHook);
42 class HtmlEventMonitorHook : public PluginBase {
43 public:
44 HtmlEventMonitorHook(NPP instance)
45 : PluginBase(instance), dispatcher_(this) {
46 PluginBase::Init(&dispatcher_);
49 void Init(HtmlEventMonitor::HtmlEventCallback function, void *user_param) {
50 function_ = function;
51 user_param_ = user_param;
54 void HandleEvent(JsCallContext *context) {
55 function_(user_param_); // invoke user callback
58 private:
59 HtmlEventMonitor::HtmlEventCallback function_;
60 void *user_param_;
62 Dispatcher<HtmlEventMonitorHook> dispatcher_;
64 DISALLOW_EVIL_CONSTRUCTORS(HtmlEventMonitorHook);
67 // static
68 template <>
69 void Dispatcher<HtmlEventMonitorHook>::Init() {
70 // Safari treats "handleEvent" as a method, while Firefox treats it as a
71 // property. Go figure.
72 RegisterMethod("handleEvent", &HtmlEventMonitorHook::HandleEvent);
73 RegisterProperty("handleEvent", &HtmlEventMonitorHook::HandleEvent, NULL);
76 HtmlEventMonitorHook* CreateHtmlEventMonitorHook(JsContextPtr context) {
77 return static_cast<HtmlEventMonitorHook *>(
78 NPN_CreateObject(context, GetNPClass<HtmlEventMonitorHook>()));
82 // HtmlEventMonitor
85 bool HtmlEventMonitor::Start(NPP context, NPObject *event_source) {
86 assert(!event_hook_);
87 assert(NPVARIANT_IS_VOID(event_source_));
89 // create the event hook
90 HtmlEventMonitorHook *event_hook = CreateHtmlEventMonitorHook(context);
91 ScopedNPObject event_hook_scoped(event_hook);
92 event_hook->Init(function_, user_param_);
94 // call window.addEventListener(event_name, event_hook, false)
95 NPObject* window = event_source;
97 NPIdentifier add_event_listener_id =
98 NPN_GetStringIdentifier("addEventListener");
100 std::string event_name_utf8;
101 if (!String16ToUTF8(&event_name_[2], &event_name_utf8)) // skip leading "on"
102 return false;
104 NPVariant args[3];
105 STDSTRING_TO_NPVARIANT(event_name_utf8, args[0]);
106 OBJECT_TO_NPVARIANT(event_hook, args[1]);
107 BOOLEAN_TO_NPVARIANT(false, args[2]);
109 // call the method
110 ScopedNPVariant result;
111 if (!NPN_Invoke(context, window, add_event_listener_id, args,
112 ARRAYSIZE(args), &result))
113 return false;
115 // only modify data members if everything succeeded
116 event_hook_scoped.release();
117 event_context_ = context;
118 event_hook_ = event_hook;
119 event_source_.Reset(event_source);
120 return true;
123 void HtmlEventMonitor::Stop() {
124 assert(NPVARIANT_IS_OBJECT(event_source_));
125 assert(event_hook_);
127 // call window.removeEventListener(event_name, event_hook, false)
128 NPObject* window = NPVARIANT_TO_OBJECT(event_source_);
130 NPIdentifier remove_event_listener_id =
131 NPN_GetStringIdentifier("removeEventListener");
133 std::string event_name_utf8;
134 if (!String16ToUTF8(&event_name_[2], &event_name_utf8)) // skip leading "on"
135 return;
137 NPVariant args[3];
138 STDSTRING_TO_NPVARIANT(event_name_utf8, args[0]);
139 OBJECT_TO_NPVARIANT(event_hook_, args[1]);
140 BOOLEAN_TO_NPVARIANT(false, args[2]);
142 // call the method
143 ScopedNPVariant result;
144 if (!NPN_Invoke(event_context_, window, remove_event_listener_id,
145 args, 3, &result))
146 return;
148 // destroy the event hook
149 NPN_ReleaseObject(event_hook_);
150 event_context_ = NULL;
151 event_hook_ = NULL;
152 event_source_.Reset();