1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // Event management for GuestViewContainers.
7 var EventBindings
= require('event_bindings');
8 var GuestViewInternalNatives
= requireNative('guest_view_internal');
9 var MessagingNatives
= requireNative('messaging_natives');
11 var CreateEvent = function(name
) {
12 var eventOpts
= {supportsListeners
: true, supportsFilters
: true};
13 return new EventBindings
.Event(name
, undefined, eventOpts
);
16 function GuestViewEvents(view
) {
22 // |setupEventProperty| is normally called automatically, but these events are
23 // are registered here because they are dispatched from GuestViewContainer
24 // instead of in response to extension events.
25 this.setupEventProperty('contentresize');
26 this.setupEventProperty('resize');
30 // |GuestViewEvents.EVENTS| is a dictionary of extension events to be listened
31 // for, which specifies how each event should be handled. The events are
32 // organized by name, and by default will be dispatched as DOM events with
34 // |cancelable| (default: false) specifies whether the DOM event's default
35 // behavior can be canceled. If the default action associated with the event
36 // is prevented, then its dispatch function will return false in its event
37 // handler. The event must have a specified |handler| for this to be
39 // |evt| specifies a descriptor object for the extension event. An event
40 // listener will be attached to this descriptor.
41 // |fields| (default: none) specifies the public-facing fields in the DOM event
42 // that are accessible to developers.
43 // |handler| specifies the name of a handler function to be called each time
44 // that extension event is caught by its event listener. The DOM event
45 // should be dispatched within this handler function (if desired). With no
46 // handler function, the DOM event will be dispatched by default each time
47 // the extension event is caught.
48 // |internal| (default: false) specifies that the event will not be dispatched
49 // as a DOM event, and will also not appear as an on* property on the view’s
50 // element. A |handler| should be specified for all internal events, and
51 // |fields| and |cancelable| should be left unspecified (as they are only
52 // meaningful for DOM events).
53 GuestViewEvents
.EVENTS
= {};
55 // Attaches |listener| onto the event descriptor object |evt|, and registers it
56 // to be removed once this GuestViewEvents object is garbage collected.
57 GuestViewEvents
.prototype.addScopedListener = function(
58 evt
, listener
, listenerOpts
) {
59 this.listenersToBeRemoved
.push({ 'evt': evt
, 'listener': listener
});
60 evt
.addListener(listener
, listenerOpts
);
63 // Sets up the handling of events.
64 GuestViewEvents
.prototype.setupEvents = function() {
65 // An array of registerd event listeners that should be removed when this
66 // GuestViewEvents is garbage collected.
67 this.listenersToBeRemoved
= [];
68 MessagingNatives
.BindToGC(this, function(listenersToBeRemoved
) {
69 for (var i
= 0; i
!= listenersToBeRemoved
.length
; ++i
) {
70 listenersToBeRemoved
[i
].evt
.removeListener(
71 listenersToBeRemoved
[i
].listener
);
72 listenersToBeRemoved
[i
] = null;
74 }.bind(undefined, this.listenersToBeRemoved
), -1 /* portId */);
76 // Set up the GuestView events.
77 for (var eventName
in GuestViewEvents
.EVENTS
) {
78 this.setupEvent(eventName
, GuestViewEvents
.EVENTS
[eventName
]);
81 // Set up the derived view's events.
82 var events
= this.getEvents();
83 for (var eventName
in events
) {
84 this.setupEvent(eventName
, events
[eventName
]);
88 // Sets up the handling of the |eventName| event.
89 GuestViewEvents
.prototype.setupEvent = function(eventName
, eventInfo
) {
90 if (!eventInfo
.internal) {
91 this.setupEventProperty(eventName
);
94 var listenerOpts
= { instanceId
: this.view
.viewInstanceId
};
95 if (eventInfo
.handler
) {
96 this.addScopedListener(eventInfo
.evt
, this.weakWrapper(function(e
) {
97 this[eventInfo
.handler
](e
, eventName
);
102 // Internal events are not dispatched as DOM events.
103 if (eventInfo
.internal) {
107 this.addScopedListener(eventInfo
.evt
, this.weakWrapper(function(e
) {
108 var domEvent
= this.makeDomEvent(e
, eventName
);
109 this.view
.dispatchEvent(domEvent
);
113 // Constructs a DOM event based on the info for the |eventName| event provided
114 // in either |GuestViewEvents.EVENTS| or getEvents().
115 GuestViewEvents
.prototype.makeDomEvent = function(event
, eventName
) {
117 GuestViewEvents
.EVENTS
[eventName
] || this.getEvents()[eventName
];
119 // Internal events are not dispatched as DOM events.
120 if (eventInfo
.internal) {
124 var details
= { bubbles
: true };
125 if (eventInfo
.cancelable
) {
126 details
.cancelable
= true;
128 var domEvent
= new Event(eventName
, details
);
129 if (eventInfo
.fields
) {
130 $Array
.forEach(eventInfo
.fields
, function(field
) {
131 if (event
[field
] !== undefined) {
132 domEvent
[field
] = event
[field
];
140 // Adds an 'on<event>' property on the view, which can be used to set/unset
142 GuestViewEvents
.prototype.setupEventProperty = function(eventName
) {
143 var propertyName
= 'on' + eventName
.toLowerCase();
144 $Object
.defineProperty(this.view
.element
, propertyName
, {
146 return this.on
[propertyName
];
148 set: function(value
) {
149 if (this.on
[propertyName
]) {
150 this.view
.element
.removeEventListener(eventName
, this.on
[propertyName
]);
152 this.on
[propertyName
] = value
;
154 this.view
.element
.addEventListener(eventName
, value
);
161 // returns a wrapper for |func| with a weak reference to |this|.
162 GuestViewEvents
.prototype.weakWrapper = function(func
) {
163 var viewInstanceId
= this.view
.viewInstanceId
;
165 var view
= GuestViewInternalNatives
.GetViewFromID(viewInstanceId
);
169 return $Function
.apply(func
, view
.events
, $Array
.slice(arguments
));
173 // Implemented by the derived event manager, if one exists.
174 GuestViewEvents
.prototype.getEvents = function() { return {}; };
177 exports
.GuestViewEvents
= GuestViewEvents
;
178 exports
.CreateEvent
= CreateEvent
;