Index: chrome/renderer/resources/extensions/downloads_custom_bindings.js |
diff --git a/chrome/renderer/resources/extensions/downloads_custom_bindings.js b/chrome/renderer/resources/extensions/downloads_custom_bindings.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..1c54b7b41b77a97a9911630136c6e690afa312b8 |
--- /dev/null |
+++ b/chrome/renderer/resources/extensions/downloads_custom_bindings.js |
@@ -0,0 +1,141 @@ |
+// Copyright (c) 2013 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. |
+ |
+// Custom bindings for the downloads API. |
+ |
+var downloadsNatives = requireNative('downloads'); |
+var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); |
+var sendRequest = require('sendRequest').sendRequest; |
+ |
+function DownloadsEvent(eventName, opt_argSchemas, opt_extraArgSchemas, |
+ opt_eventOptions) { |
+ if (typeof eventName != 'string') |
+ throw new Error('chrome.DownloadsEvent requires an event name.'); |
+ |
+ this.eventName_ = eventName; |
+ this.determiningFilename_ = (eventName == 'downloads.onDeterminingFilename'); |
+ this.argSchemas_ = opt_argSchemas; |
+ this.extraArgSchemas_ = opt_extraArgSchemas; |
+ this.eventOptions_ = chromeHidden.parseEventOptions(opt_eventOptions); |
+ if (this.determiningFilename_) { |
+ this.subEvents_ = []; |
+ } else { |
+ this.actualEvent_ = |
+ new chrome.Event(eventName, opt_argSchemas, opt_eventOptions); |
Matt Perry
2013/02/05 20:49:39
I'm not a JS expert, but I believe it's possible t
benjhayden
2013/02/05 21:12:19
Unfortunately, registerCustomEvent does 'new Downl
Matt Perry
2013/02/05 21:57:10
I know, but I think it still works. For example, t
benjhayden
2013/02/21 22:29:33
8-O
...
Done.
|
+ } |
+} |
+ |
+// Test if the given callback is registered for this event. |
+DownloadsEvent.prototype.hasListener = function(cb) { |
+ if (!this.eventOptions_.supportsListeners) |
+ throw new Error('This event does not support listeners.'); |
+ return this.findListener_(cb) > -1; |
+}; |
+ |
+// Test if any callbacks are registered for this event. |
+DownloadsEvent.prototype.hasListeners = function() { |
+ if (!this.eventOptions_.supportsListeners) |
+ throw new Error('This event does not support listeners.'); |
+ return (this.determiningFilename_ ? (this.subEvents_.length > 0) : |
+ this.actualEvent_.hasListeners()); |
+}; |
+ |
+DownloadsEvent.prototype.addListener = function(cb) { |
+ if (!this.eventOptions_.supportsListeners) |
+ throw new Error('This event does not support listeners.'); |
+ if (!this.determiningFilename_) { |
+ this.actualEvent_.addListener(cb); |
+ return; |
+ } |
+ var entry = {callback: cb}; |
+ entry.determiner_id = downloadsNatives.GetFilenameDeterminerId(); |
+ entry.subEvent = new chrome.Event( |
+ this.eventName_ + '/' + entry.determiner_id, this.argSchemas_); |
+ chromeHidden.internalAPIs.downloadsInternal.addFilenameDeterminer( |
+ entry.determiner_id); |
+ entry.subEventCallback = function() { |
+ var download_id = arguments[0].id; |
+ try { |
+ var result = cb.apply(null, arguments); |
+ if ((typeof(result) == 'object') && |
+ result.filename && |
+ (typeof(result.filename) == 'string') && |
+ ((result.overwrite === undefined) || |
+ (typeof(result.overwrite) == 'boolean'))) { |
+ chromeHidden.internalAPIs.downloadsInternal.determineFilename( |
+ entry.determiner_id, |
+ download_id, |
+ result.filename, |
+ result.overwrite || false); |
+ } else { |
+ chromeHidden.internalAPIs.downloadsInternal.determineFilename( |
+ entry.determiner_id, |
+ download_id); |
+ } |
+ } catch (e) { |
+ chromeHidden.internalAPIs.downloadsInternal.determineFilename( |
+ entry.determiner_id, |
+ download_id); |
+ throw e; |
+ } |
+ }; |
+ this.subEvents_.push(entry); |
+ entry.subEvent.addListener(entry.subEventCallback); |
+}; |
+ |
+DownloadsEvent.prototype.removeListener = function(cb) { |
Matt Perry
2013/02/07 00:10:13
This is only called when the extension explicitly
benjhayden
2013/02/21 22:29:33
I already Observe NOTIFICATION_EXTENSION_UNLOADED.
Matt Perry
2013/02/21 23:07:49
Yes - in the case of a popup closing, for example.
benjhayden
2013/02/22 20:43:23
Done -- I assumed that I should also use OnListene
|
+ if (!this.eventOptions_.supportsListeners) |
+ throw new Error('This event does not support listeners.'); |
+ if (!this.determiningFilename_) { |
+ this.actualEvent_.removeListener(cb); |
+ return; |
+ } |
+ var idx; |
+ while ((idx = this.findListener_(cb)) >= 0) { |
+ var e = this.subEvents_[idx]; |
+ e.subEvent.removeListener(e.subEventCallback); |
+ chromeHidden.internalAPIs.downloadsInternal.removeFilenameDeterminer( |
+ e.determiner_id); |
+ if (e.subEvent.hasListeners()) { |
+ console.error('Internal error: subEvent has orphaned listeners.'); |
+ } |
+ this.subEvents_.splice(idx, 1); |
+ } |
+}; |
+ |
+DownloadsEvent.prototype.findListener_ = function(cb) { |
+ if (!this.determiningFilename_) { |
+ return this.actualEvent_.findListener(cb); |
+ } |
+ for (var i in this.subEvents_) { |
+ var e = this.subEvents_[i]; |
+ if (e.callback === cb) { |
+ if (e.subEvent.findListener_(e.subEventCallback) > -1) |
+ return i; |
+ console.error('Internal error: subEvent has no callback.'); |
+ } |
+ } |
+ |
+ return -1; |
+}; |
+ |
+DownloadsEvent.prototype.addRules = function(rules, opt_cb) { |
+ if (!this.eventOptions_.supportsRules) |
+ throw new Error('This event does not support rules.'); |
+ this.eventForRules_.addRules(rules, opt_cb); |
+} |
+ |
+DownloadsEvent.prototype.removeRules = function(ruleIdentifiers, opt_cb) { |
+ if (!this.eventOptions_.supportsRules) |
+ throw new Error('This event does not support rules.'); |
+ this.eventForRules_.removeRules(ruleIdentifiers, opt_cb); |
+} |
+ |
+DownloadsEvent.prototype.getRules = function(ruleIdentifiers, cb) { |
+ if (!this.eventOptions_.supportsRules) |
+ throw new Error('This event does not support rules.'); |
+ this.eventForRules_.getRules(ruleIdentifiers, cb); |
+} |
+ |
+chromeHidden.registerCustomEvent('downloads', DownloadsEvent); |