OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2013 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. | |
4 | |
5 // Custom bindings for the downloads API. | |
6 | |
7 var downloadsNatives = requireNative('downloads'); | |
8 var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); | |
9 var sendRequest = require('sendRequest').sendRequest; | |
10 | |
11 function DownloadsEvent(eventName, | |
12 opt_argSchemas, | |
13 ignored_extraArgSchemas, | |
14 opt_eventOptions) { | |
15 if (typeof eventName != 'string') | |
16 throw new Error('chrome.DownloadsEvent requires an event name.'); | |
17 // onDeterminingFilename is the only special event in chrome.downloads. | |
18 if (eventName != 'downloads.onDeterminingFilename') { | |
19 return new chrome.Event(eventName, opt_argSchemas, opt_eventOptions); | |
20 } | |
21 | |
22 this.eventName_ = eventName; | |
23 // ExtensionDownloadsEventRouter can't send a SuggestFilenameCallback, so | |
24 // slice it out of the event schema, leaving only the DownloadItem. | |
25 this.argSchemas_ = opt_argSchemas.slice(0, 1); | |
26 this.eventOptions_ = chromeHidden.parseEventOptions(opt_eventOptions); | |
27 this.subEvents_ = []; | |
28 } | |
29 | |
30 // Test if the given callback is registered for this event. | |
31 DownloadsEvent.prototype.hasListener = function(cb) { | |
32 if (!this.eventOptions_.supportsListeners) | |
33 throw new Error('This event does not support listeners.'); | |
34 return this.findListener_(cb) > -1; | |
35 }; | |
36 | |
37 // Test if any callbacks are registered for this event. | |
38 DownloadsEvent.prototype.hasListeners = function() { | |
39 if (!this.eventOptions_.supportsListeners) | |
40 throw new Error('This event does not support listeners.'); | |
41 return (this.subEvents_.length > 0); | |
42 }; | |
43 | |
44 DownloadsEvent.prototype.addListener = function(cb) { | |
45 if (!this.eventOptions_.supportsListeners) | |
46 throw new Error('This event does not support listeners.'); | |
47 var entry = {callback: cb}; | |
48 entry.determiner_id = downloadsNatives.GetFilenameDeterminerId(); | |
49 entry.subEvent = new chrome.Event( | |
50 this.eventName_ + '/' + entry.determiner_id, this.argSchemas_); | |
51 chromeHidden.internalAPIs.downloadsInternal.addFilenameDeterminer( | |
52 entry.determiner_id); | |
53 entry.subEventCallback = function() { | |
54 var downloadItem = arguments[0]; | |
55 // Copy the id so that extensions can't change downloadItem.id. | |
56 var downloadId = downloadItem.id; | |
57 var suggestable = true; | |
58 function suggest(result) { | |
59 if (!suggestable) | |
60 return; | |
Matt Perry
2013/02/22 01:43:43
set suggestable to false here too
benjhayden
2013/02/22 20:43:23
Done.
| |
61 if ((typeof(result) == 'object') && | |
62 result.filename && | |
63 (typeof(result.filename) == 'string') && | |
64 ((result.overwrite === undefined) || | |
65 (typeof(result.overwrite) == 'boolean'))) { | |
66 chromeHidden.internalAPIs.downloadsInternal.determineFilename( | |
67 entry.determiner_id, | |
68 downloadId, | |
69 result.filename, | |
70 result.overwrite || false); | |
71 } else { | |
72 chromeHidden.internalAPIs.downloadsInternal.determineFilename( | |
73 entry.determiner_id, | |
74 downloadId); | |
75 } | |
76 } | |
77 try { | |
78 cb.apply(null, [downloadItem, suggest]); | |
Matt Perry
2013/02/22 01:43:43
I'd recommend requiring the user to return true fr
benjhayden
2013/02/22 20:43:23
Done.
| |
79 } catch (e) { | |
80 chromeHidden.internalAPIs.downloadsInternal.determineFilename( | |
81 entry.determiner_id, | |
82 downloadId); | |
83 suggestable = false; | |
84 throw e; | |
85 } | |
86 }; | |
87 this.subEvents_.push(entry); | |
88 entry.subEvent.addListener(entry.subEventCallback); | |
89 }; | |
90 | |
91 DownloadsEvent.prototype.removeListener = function(cb) { | |
92 if (!this.eventOptions_.supportsListeners) | |
93 throw new Error('This event does not support listeners.'); | |
94 var idx; | |
95 while ((idx = this.findListener_(cb)) >= 0) { | |
96 var e = this.subEvents_[idx]; | |
97 e.subEvent.removeListener(e.subEventCallback); | |
98 chromeHidden.internalAPIs.downloadsInternal.removeFilenameDeterminer( | |
99 e.determiner_id); | |
100 if (e.subEvent.hasListeners()) { | |
101 console.error('Internal error: subEvent has orphaned listeners.'); | |
102 } | |
103 this.subEvents_.splice(idx, 1); | |
104 } | |
105 }; | |
106 | |
107 DownloadsEvent.prototype.findListener_ = function(cb) { | |
108 for (var i in this.subEvents_) { | |
109 var e = this.subEvents_[i]; | |
110 if (e.callback === cb) { | |
111 if (e.subEvent.findListener_(e.subEventCallback) > -1) | |
112 return i; | |
113 console.error('Internal error: subEvent has no callback.'); | |
114 } | |
115 } | |
116 | |
117 return -1; | |
118 }; | |
119 | |
120 DownloadsEvent.prototype.addRules = function(rules, opt_cb) { | |
121 if (!this.eventOptions_.supportsRules) | |
122 throw new Error('This event does not support rules.'); | |
123 this.eventForRules_.addRules(rules, opt_cb); | |
124 } | |
125 | |
126 DownloadsEvent.prototype.removeRules = function(ruleIdentifiers, opt_cb) { | |
127 if (!this.eventOptions_.supportsRules) | |
128 throw new Error('This event does not support rules.'); | |
129 this.eventForRules_.removeRules(ruleIdentifiers, opt_cb); | |
130 } | |
131 | |
132 DownloadsEvent.prototype.getRules = function(ruleIdentifiers, cb) { | |
133 if (!this.eventOptions_.supportsRules) | |
134 throw new Error('This event does not support rules.'); | |
135 this.eventForRules_.getRules(ruleIdentifiers, cb); | |
136 } | |
137 | |
138 chromeHidden.registerCustomEvent('downloads', DownloadsEvent); | |
OLD | NEW |