| Index: chrome/renderer/resources/event_bindings.js
|
| diff --git a/chrome/renderer/resources/event_bindings.js b/chrome/renderer/resources/event_bindings.js
|
| index f11ec78645c408f218eaff8085a315c9d3e4edbd..78a1ceb66c233b26dc88131ee7e111da3b604e6c 100644
|
| --- a/chrome/renderer/resources/event_bindings.js
|
| +++ b/chrome/renderer/resources/event_bindings.js
|
| @@ -1,5 +1,5 @@
|
| -// Copyright (c) 2009 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| +// Copyright (c) 2009 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.
|
|
|
| // -----------------------------------------------------------------------------
|
| @@ -9,8 +9,12 @@
|
|
|
| var chrome = chrome || {};
|
| (function () {
|
| + native function GetChromeHidden();
|
| native function AttachEvent(eventName);
|
| native function DetachEvent(eventName);
|
| + native function GetNextRequestId();
|
| +
|
| + var chromeHidden = GetChromeHidden();
|
|
|
| // Event object. If opt_eventName is provided, this object represents
|
| // the unique instance of that named event, and dispatching an event
|
| @@ -19,7 +23,7 @@ var chrome = chrome || {};
|
| // Example:
|
| // chrome.tabs.onChanged = new chrome.Event("tab-changed");
|
| // chrome.tabs.onChanged.addListener(function(data) { alert(data); });
|
| - // chrome.Event.dispatch_("tab-changed", "hi");
|
| + // chromeHidden.Event.dispatch("tab-changed", "hi");
|
| // will result in an alert dialog that says 'hi'.
|
| chrome.Event = function(opt_eventName) {
|
| this.eventName_ = opt_eventName;
|
| @@ -27,26 +31,31 @@ var chrome = chrome || {};
|
| };
|
|
|
| // A map of event names to the event object that is registered to that name.
|
| - chrome.Event.attached_ = {};
|
| + var attachedNamedEvents = {};
|
| +
|
| + // An array of all attached event objects, used for detaching on unload.
|
| + var allAttachedEvents = [];
|
| +
|
| + chromeHidden.Event = {};
|
|
|
| // Dispatches a named event with the given JSON array, which is deserialized
|
| // before dispatch. The JSON array is the list of arguments that will be
|
| // sent with the event callback.
|
| - chrome.Event.dispatchJSON_ = function(name, args) {
|
| - if (chrome.Event.attached_[name]) {
|
| + chromeHidden.Event.dispatchJSON = function(name, args) {
|
| + if (attachedNamedEvents[name]) {
|
| if (args) {
|
| args = JSON.parse(args);
|
| }
|
| - chrome.Event.attached_[name].dispatch.apply(
|
| - chrome.Event.attached_[name], args);
|
| + attachedNamedEvents[name].dispatch.apply(
|
| + attachedNamedEvents[name], args);
|
| }
|
| };
|
|
|
| // Dispatches a named event with the given arguments, supplied as an array.
|
| - chrome.Event.dispatch_ = function(name, args) {
|
| - if (chrome.Event.attached_[name]) {
|
| - chrome.Event.attached_[name].dispatch.apply(
|
| - chrome.Event.attached_[name], args);
|
| + chromeHidden.Event.dispatch = function(name, args) {
|
| + if (attachedNamedEvents[name]) {
|
| + attachedNamedEvents[name].dispatch.apply(
|
| + attachedNamedEvents[name], args);
|
| }
|
| };
|
|
|
| @@ -105,31 +114,82 @@ var chrome = chrome || {};
|
| // name.
|
| chrome.Event.prototype.attach_ = function() {
|
| AttachEvent(this.eventName_);
|
| - this.unloadHandler_ = this.detach_.bind(this);
|
| - window.addEventListener('unload', this.unloadHandler_, false);
|
| + allAttachedEvents[allAttachedEvents.length] = this;
|
| if (!this.eventName_)
|
| return;
|
|
|
| - if (chrome.Event.attached_[this.eventName_]) {
|
| + if (attachedNamedEvents[this.eventName_]) {
|
| throw new Error("chrome.Event '" + this.eventName_ +
|
| "' is already attached.");
|
| }
|
|
|
| - chrome.Event.attached_[this.eventName_] = this;
|
| + attachedNamedEvents[this.eventName_] = this;
|
| };
|
|
|
| // Detaches this event object from its name.
|
| chrome.Event.prototype.detach_ = function() {
|
| - window.removeEventListener('unload', this.unloadHandler_, false);
|
| + var i = allAttachedEvents.indexOf(this);
|
| + if (i >= 0)
|
| + delete allAttachedEvents[i];
|
| DetachEvent(this.eventName_);
|
| if (!this.eventName_)
|
| return;
|
|
|
| - if (!chrome.Event.attached_[this.eventName_]) {
|
| + if (!attachedNamedEvents[this.eventName_]) {
|
| throw new Error("chrome.Event '" + this.eventName_ +
|
| "' is not attached.");
|
| }
|
|
|
| - delete chrome.Event.attached_[this.eventName_];
|
| + delete attachedNamedEvents[this.eventName_];
|
| };
|
| +
|
| + // Callback handling.
|
| + var callbacks = [];
|
| + chromeHidden.handleResponse = function(requestId, name,
|
| + success, response, error) {
|
| + try {
|
| + if (!success) {
|
| + if (!error)
|
| + error = "Unknown error."
|
| + console.error("Error during " + name + ": " + error);
|
| + return;
|
| + }
|
| +
|
| + if (callbacks[requestId]) {
|
| + if (response) {
|
| + callbacks[requestId](JSON.parse(response));
|
| + } else {
|
| + callbacks[requestId]();
|
| + }
|
| + }
|
| + } finally {
|
| + delete callbacks[requestId];
|
| + }
|
| + };
|
| +
|
| + // Send an API request and optionally register a callback.
|
| + chromeHidden.sendRequest = function(request, args, callback) {
|
| + // JSON.stringify doesn't support a root object which is undefined.
|
| + if (args === undefined)
|
| + args = null;
|
| + var sargs = JSON.stringify(args);
|
| + var requestId = GetNextRequestId();
|
| + var hasCallback = false;
|
| + if (callback) {
|
| + hasCallback = true;
|
| + callbacks[requestId] = callback;
|
| + }
|
| + request(sargs, requestId, hasCallback);
|
| + }
|
| +
|
| + // Special unload event: we don't use the DOM unload because that slows
|
| + // down tab shutdown. On the other hand, this might not always fire, since
|
| + // Chrome will terminate renderers on shutdown (SuddenTermination).
|
| + chromeHidden.onUnload = new chrome.Event();
|
| +
|
| + chromeHidden.dispatchOnUnload = function() {
|
| + chromeHidden.onUnload.dispatch();
|
| + for (var i in allAttachedEvents)
|
| + allAttachedEvents[i].detach_();
|
| + }
|
| })();
|
|
|