1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
3
* You can obtain one at http://mozilla.org/MPL/2.0/ */
6
const {FilterManager} = require("support/filtermanager");
7
const constants = require("constants");
8
const {COMPLETE, FINISHING} = constants;
15
const _ = (function(global) {
16
let bundles = new StringBundles([
17
"chrome://dta/locale/common.properties",
18
"chrome://dta/locale/manager.properties"
21
if (arguments.length === 1) {
22
return bundles.getString(arguments[0]);
24
return bundles.getFormattedString.apply(bundles, arguments);
32
getMatcher: function(params) {
35
.replace(/^\s+|\s+$/g, '')
36
.replace(/([/{}()\[\]\\^$.])/g, "\\$1")
42
return function TextMatcher(d) {
44
[d.urlManager.usable, d.description, d.fileName, d.destinationName].join(' ')
54
getItems: function*() {
55
for (let f of FilterManager.enumAll()) {
56
if (f.id === "deffilter-all") {
65
getMatcher: function(params) {
67
for (let id of params) {
69
filters.push(FilterManager.getFilter(id));
72
log(LOG_ERROR, "not a filter: " + id, ex);
73
// no op; might have changed
76
if (!filters.length) {
77
log(LOG_DEBUG, "No filters available for: " + params);
80
let _m = FilterManager.getMatcherFor(filters);
81
return function FilterMatcher(d) { return _m(d.urlManager.spec); };
89
getItems: function*(downloads) {
90
let paths = filterInSitu(
91
downloads.map(d => d.destinationPath),
93
return !((e in this) || (this[e] = null));
97
for (let p of paths) {
104
getMatcher: function(params) {
105
params = params.map(e => atob(e));
106
return function PathMatcher(d) {
107
return params.indexOf(d.destinationPath) >= 0;
112
const RemainderMatch = {
116
getItems: function*() {
118
label: _('soonfinished'),
123
label: _('next10mins'),
128
label: _('nexthour'),
133
label: _('next6hours'),
143
getMatcher: function(params) {
146
for (let p of params) {
147
let n = parseInt(p, 10);
148
if (isFinite(n) && n > est) {
152
return function RemainderMatcher(d) { return d.estimated <= est; };
155
const StatusMatch = {
157
return 'statusmatch';
159
getItems: function*() {
160
for (let s of ['QUEUED', 'PAUSED', 'RUNNING', 'COMPLETE', 'CANCELED']) {
162
label: _(s.toLowerCase()),
167
getMatcher: function(params) {
168
let state = params.reduce((p, c) => p | constants[c], 0);
169
if (state & COMPLETE) {
172
return function StatusMatcher(d) { return d.state & state; };
175
requireJoined(StatusMatch, "constants");
178
['-0', _('unknown')],
179
['0-1024', _('verysmallfiles')],
180
['1024-1048576', _('smallfiles')],
181
['1048576-262144000', _('mediumfiles')],
182
['262144000-524288000', _('largefiles')],
183
['524288000-4294967296', _('verylargefiles')],
184
['4294967296-', _('hugefiles')]
190
getItems: function*() {
191
for (let [p, l] of SIZES) {
198
getMatcher: function(params) {
199
function parseInt10(v) {
200
return parseInt(v, 10);
203
for (let x of params) {
204
let [l,h] = x.split('-').map(parseInt10);
205
ranges.push({low: l, high: h});
207
if (!ranges.length) {
211
for (let i = ranges.length - 2; i >= 0; --i) {
212
if (ranges[i].high === ranges[i+1].low) {
213
ranges[i].high = ranges[i+1].high;
214
ranges.splice(i+1,1);
218
// map to fastpath functions
219
ranges = ranges.map(function(r) {
222
if (!isFinite(low)) {
223
return function(size) { return size <= high; };
225
if (!isFinite(high)) {
226
return function(size) { return size > low; };
228
return function(size) { return size > low && size <= high; };
231
if (ranges.length === 1) {
232
let rf = ranges.shift();
233
return function(d) { return rf(d.totalSize); };
236
return ranges.some(function(rf) { return rf(d.totalSize); });
241
const DomainMatch = {
243
return 'domainmatch';
245
getItems: function*(downloads) {
246
let domains = filterInSitu(
247
downloads.map(d => d.urlManager.domain),
249
return !((e in this) || (this[e] = null));
253
for (let p of domains) {
260
getMatcher: function(params) {
261
params = params.map(e => atob(e));
262
return function(d) { return params.indexOf(d.urlManager.domain) >= 0; };
266
function MatcherTee(a, b) {
270
MatcherTee.prototype = {
272
return this.a + ";" + this.b;
274
getItems: function*(downloads) {
275
for (let a of this.a.getItems(downloads)) {
276
a.param = "a:" + a.param;
280
for (let b of this.b.getItems(downloads)) {
281
b.param = "b:" + b.param;
285
getMatcher: function(params) {
287
params.forEach(function(p) {
288
return this[p[0]].push(p.substr(2));
290
if (a.length && !b.length) {
291
return this.a.getMatcher(a);
293
if (!a.length && b.length) {
294
return this.b.getMatcher(b);
296
if (!a.length && !b.length) {
299
a = this.a.getMatcher(a);
300
b = this.b.getMatcher(b);
301
return function(d) { return a(d) && b(d); };
307
this._matchersLength = 0;
309
Matcher.prototype = {
311
'textmatch': TextMatch,
312
'downloadmatch': new MatcherTee(FilterMatch, DomainMatch),
313
'pathmatch': PathMatch,
314
'statusmatch': new MatcherTee(StatusMatch, RemainderMatch),
315
'sizematch': SizeMatch,
316
'domainmatch': DomainMatch
318
getItems: function*(name, downloads) {
319
for (let i of this._available[name].getItems(downloads)) {
323
addMatcher: function(name, params) {
324
if (!(name in this._available)) {
325
log(LOG_ERROR, "trying to add a matcher that does not exist");
328
this.removeMatcher(name);
329
let m = this._available[name].getMatcher(params);
331
log(LOG_DEBUG, "adding the matcher");
332
this._matchers.push({name: name, isMatch: m});
333
this._matchersLength = this._matchers.length;
336
removeMatcher: function(name) {
337
this._matchersLength = filterInSitu(this._matchers, m => m.name !== name).length;
340
return !!this._matchersLength;
342
filter: function(array) {
343
// jshint strict:true, globalstrict:true, loopfunc:true
345
for (let i = 0, e = this._matchers.length; i < e; ++i) {
346
let m = this._matchers[i];
348
let fnm = function(e) {
349
let rv = m.isMatch(e);
350
e.filteredPosition = rv ? j++ : -1;
354
rv = array.filter(fnm);
357
filterInSitu(rv, fnm);
362
shouldDisplay: function(d) {
363
for (let i = 0, e = this._matchers.length; i < e; ++i) {
364
if (!this._matchers[i].isMatch(d)) {
372
exports.Matcher = Matcher;