| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // ----------------------------------------------------------------------------- | 5 // ----------------------------------------------------------------------------- |
| 6 // NOTE: If you change this file you need to touch renderer_resources.grd to | 6 // NOTE: If you change this file you need to touch renderer_resources.grd to |
| 7 // have your change take effect. | 7 // have your change take effect. |
| 8 // ----------------------------------------------------------------------------- | 8 // ----------------------------------------------------------------------------- |
| 9 | 9 |
| 10 var chrome = chrome || {}; | 10 var chrome = chrome || {}; |
| 11 (function () { | 11 (function () { |
| 12 native function GetChromeHidden(); |
| 12 native function AttachEvent(eventName); | 13 native function AttachEvent(eventName); |
| 13 native function DetachEvent(eventName); | 14 native function DetachEvent(eventName); |
| 15 native function GetNextRequestId(); |
| 16 |
| 17 var chromeHidden = GetChromeHidden(); |
| 14 | 18 |
| 15 // Event object. If opt_eventName is provided, this object represents | 19 // Event object. If opt_eventName is provided, this object represents |
| 16 // the unique instance of that named event, and dispatching an event | 20 // the unique instance of that named event, and dispatching an event |
| 17 // with that name will route through this object's listeners. | 21 // with that name will route through this object's listeners. |
| 18 // | 22 // |
| 19 // Example: | 23 // Example: |
| 20 // chrome.tabs.onChanged = new chrome.Event("tab-changed"); | 24 // chrome.tabs.onChanged = new chrome.Event("tab-changed"); |
| 21 // chrome.tabs.onChanged.addListener(function(data) { alert(data); }); | 25 // chrome.tabs.onChanged.addListener(function(data) { alert(data); }); |
| 22 // chrome.Event.dispatch_("tab-changed", "hi"); | 26 // chromeHidden.Event.dispatch("tab-changed", "hi"); |
| 23 // will result in an alert dialog that says 'hi'. | 27 // will result in an alert dialog that says 'hi'. |
| 24 chrome.Event = function(opt_eventName) { | 28 chrome.Event = function(opt_eventName) { |
| 25 this.eventName_ = opt_eventName; | 29 this.eventName_ = opt_eventName; |
| 26 this.listeners_ = []; | 30 this.listeners_ = []; |
| 27 }; | 31 }; |
| 28 | 32 |
| 29 // A map of event names to the event object that is registered to that name. | 33 // A map of event names to the event object that is registered to that name. |
| 30 chrome.Event.attached_ = {}; | 34 var attachedNamedEvents = {}; |
| 35 |
| 36 // An array of all attached event objects, used for detaching on unload. |
| 37 var allAttachedEvents = []; |
| 38 |
| 39 chromeHidden.Event = {}; |
| 31 | 40 |
| 32 // Dispatches a named event with the given JSON array, which is deserialized | 41 // Dispatches a named event with the given JSON array, which is deserialized |
| 33 // before dispatch. The JSON array is the list of arguments that will be | 42 // before dispatch. The JSON array is the list of arguments that will be |
| 34 // sent with the event callback. | 43 // sent with the event callback. |
| 35 chrome.Event.dispatchJSON_ = function(name, args) { | 44 chromeHidden.Event.dispatchJSON = function(name, args) { |
| 36 if (chrome.Event.attached_[name]) { | 45 if (attachedNamedEvents[name]) { |
| 37 if (args) { | 46 if (args) { |
| 38 args = JSON.parse(args); | 47 args = JSON.parse(args); |
| 39 } | 48 } |
| 40 chrome.Event.attached_[name].dispatch.apply( | 49 attachedNamedEvents[name].dispatch.apply( |
| 41 chrome.Event.attached_[name], args); | 50 attachedNamedEvents[name], args); |
| 42 } | 51 } |
| 43 }; | 52 }; |
| 44 | 53 |
| 45 // Dispatches a named event with the given arguments, supplied as an array. | 54 // Dispatches a named event with the given arguments, supplied as an array. |
| 46 chrome.Event.dispatch_ = function(name, args) { | 55 chromeHidden.Event.dispatch = function(name, args) { |
| 47 if (chrome.Event.attached_[name]) { | 56 if (attachedNamedEvents[name]) { |
| 48 chrome.Event.attached_[name].dispatch.apply( | 57 attachedNamedEvents[name].dispatch.apply( |
| 49 chrome.Event.attached_[name], args); | 58 attachedNamedEvents[name], args); |
| 50 } | 59 } |
| 51 }; | 60 }; |
| 52 | 61 |
| 53 // Registers a callback to be called when this event is dispatched. | 62 // Registers a callback to be called when this event is dispatched. |
| 54 chrome.Event.prototype.addListener = function(cb) { | 63 chrome.Event.prototype.addListener = function(cb) { |
| 55 this.listeners_.push(cb); | 64 this.listeners_.push(cb); |
| 56 if (this.listeners_.length == 1) { | 65 if (this.listeners_.length == 1) { |
| 57 this.attach_(); | 66 this.attach_(); |
| 58 } | 67 } |
| 59 }; | 68 }; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 98 } catch (e) { | 107 } catch (e) { |
| 99 console.error(e); | 108 console.error(e); |
| 100 } | 109 } |
| 101 } | 110 } |
| 102 }; | 111 }; |
| 103 | 112 |
| 104 // Attaches this event object to its name. Only one object can have a given | 113 // Attaches this event object to its name. Only one object can have a given |
| 105 // name. | 114 // name. |
| 106 chrome.Event.prototype.attach_ = function() { | 115 chrome.Event.prototype.attach_ = function() { |
| 107 AttachEvent(this.eventName_); | 116 AttachEvent(this.eventName_); |
| 108 this.unloadHandler_ = this.detach_.bind(this); | 117 allAttachedEvents[allAttachedEvents.length] = this; |
| 109 window.addEventListener('unload', this.unloadHandler_, false); | |
| 110 if (!this.eventName_) | 118 if (!this.eventName_) |
| 111 return; | 119 return; |
| 112 | 120 |
| 113 if (chrome.Event.attached_[this.eventName_]) { | 121 if (attachedNamedEvents[this.eventName_]) { |
| 114 throw new Error("chrome.Event '" + this.eventName_ + | 122 throw new Error("chrome.Event '" + this.eventName_ + |
| 115 "' is already attached."); | 123 "' is already attached."); |
| 116 } | 124 } |
| 117 | 125 |
| 118 chrome.Event.attached_[this.eventName_] = this; | 126 attachedNamedEvents[this.eventName_] = this; |
| 119 }; | 127 }; |
| 120 | 128 |
| 121 // Detaches this event object from its name. | 129 // Detaches this event object from its name. |
| 122 chrome.Event.prototype.detach_ = function() { | 130 chrome.Event.prototype.detach_ = function() { |
| 123 window.removeEventListener('unload', this.unloadHandler_, false); | 131 var i = allAttachedEvents.indexOf(this); |
| 132 if (i >= 0) |
| 133 delete allAttachedEvents[i]; |
| 124 DetachEvent(this.eventName_); | 134 DetachEvent(this.eventName_); |
| 125 if (!this.eventName_) | 135 if (!this.eventName_) |
| 126 return; | 136 return; |
| 127 | 137 |
| 128 if (!chrome.Event.attached_[this.eventName_]) { | 138 if (!attachedNamedEvents[this.eventName_]) { |
| 129 throw new Error("chrome.Event '" + this.eventName_ + | 139 throw new Error("chrome.Event '" + this.eventName_ + |
| 130 "' is not attached."); | 140 "' is not attached."); |
| 131 } | 141 } |
| 132 | 142 |
| 133 delete chrome.Event.attached_[this.eventName_]; | 143 delete attachedNamedEvents[this.eventName_]; |
| 134 }; | 144 }; |
| 145 |
| 146 // Callback handling. |
| 147 var callbacks = []; |
| 148 chromeHidden.handleResponse = function(requestId, name, |
| 149 success, response, error) { |
| 150 try { |
| 151 if (!success) { |
| 152 if (!error) |
| 153 error = "Unknown error." |
| 154 console.error("Error during " + name + ": " + error); |
| 155 return; |
| 156 } |
| 157 |
| 158 if (callbacks[requestId]) { |
| 159 if (response) { |
| 160 callbacks[requestId](JSON.parse(response)); |
| 161 } else { |
| 162 callbacks[requestId](); |
| 163 } |
| 164 } |
| 165 } finally { |
| 166 delete callbacks[requestId]; |
| 167 } |
| 168 }; |
| 169 |
| 170 // Send an API request and optionally register a callback. |
| 171 chromeHidden.sendRequest = function(request, args, callback) { |
| 172 // JSON.stringify doesn't support a root object which is undefined. |
| 173 if (args === undefined) |
| 174 args = null; |
| 175 var sargs = JSON.stringify(args); |
| 176 var requestId = GetNextRequestId(); |
| 177 var hasCallback = false; |
| 178 if (callback) { |
| 179 hasCallback = true; |
| 180 callbacks[requestId] = callback; |
| 181 } |
| 182 request(sargs, requestId, hasCallback); |
| 183 } |
| 184 |
| 185 // Special unload event: we don't use the DOM unload because that slows |
| 186 // down tab shutdown. On the other hand, this might not always fire, since |
| 187 // Chrome will terminate renderers on shutdown (SuddenTermination). |
| 188 chromeHidden.onUnload = new chrome.Event(); |
| 189 |
| 190 chromeHidden.dispatchOnUnload = function() { |
| 191 chromeHidden.onUnload.dispatch(); |
| 192 for (var i in allAttachedEvents) |
| 193 allAttachedEvents[i].detach_(); |
| 194 } |
| 135 })(); | 195 })(); |
| OLD | NEW |