Skip to content

Commit 70ccad7

Browse files
committed
Adding support to Media Converter extension
1 parent d1376e0 commit 70ccad7

File tree

9 files changed

+403
-13
lines changed

9 files changed

+403
-13
lines changed

config.js

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,19 @@
22

33
exports.ids = {
44
chrome: [
5-
'lmeddoobegbaiopohmpmmobpnpjifpii', // open in Firefox (Chrome)
6-
'agaecbnjediafcdopcfidcdiponjlmnk', // open in Explorer (Chrome)
7-
'hhalgjmpmjelidhhjldondajffjbcmcg', // open in Firefox (Opera)
8-
'poibpkhpegdblnblbkcppknekhkhmmlp', // open in Edge (Chrome)
9-
'amojccmdnkdlcjcplmkijeenigbhfbpd', // open in Opera (Chrome)
5+
'lmeddoobegbaiopohmpmmobpnpjifpii', // Open in Firefox (Chrome)
6+
'hhalgjmpmjelidhhjldondajffjbcmcg', // Open in Firefox (Opera)
7+
'agaecbnjediafcdopcfidcdiponjlmnk', // Open in IE (Chrome)
8+
'poibpkhpegdblnblbkcppknekhkhmmlp', // Open in Edge (Chrome)
9+
'jjlkfjglmelpbkgfeebcdipalggpapag', // Open in Edge (Opera)
10+
'amojccmdnkdlcjcplmkijeenigbhfbpd', // Open in Opera (Chrome)
11+
'eoenobhieedpimobhembbgdcdhdcdcig', // Open in Safari (Chrome)
12+
'noedpljikmfalclpadmnjbabbignpfge', // Open in IE (Opera)
13+
'ocnfecjfebnllnapjjoncgjnnkfmobjc', // Media Converter (Chrome)
14+
'fabccabfpmdadbhljpcmcbmepepfllnb', // Media Converter (Opera)
1015
],
1116
firefox: [
12-
'{5610edea-88c1-4370-b93d-86aa131971d1}', // open in Explorer
17+
'{5610edea-88c1-4370-b93d-86aa131971d1}', // Open in IE
18+
'{0ff128a1-c286-4e73-bffa-9ae879b244d5}', // Media Converter
1319
]
1420
};

follow-redirects.js

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
'use strict';
2+
var url = require('url');
3+
var assert = require('assert');
4+
var http = require('http');
5+
var https = require('https');
6+
var Writable = require('stream').Writable;
7+
8+
var nativeProtocols = {'http:': http, 'https:': https};
9+
var schemes = {};
10+
var exports = module.exports = {
11+
maxRedirects: 21
12+
};
13+
// RFC7231§4.2.1: Of the request methods defined by this specification,
14+
// the GET, HEAD, OPTIONS, and TRACE methods are defined to be safe.
15+
var safeMethods = {GET: true, HEAD: true, OPTIONS: true, TRACE: true};
16+
17+
// Create handlers that pass events from native requests
18+
var eventHandlers = Object.create(null);
19+
['abort', 'aborted', 'error', 'socket'].forEach(function (event) {
20+
eventHandlers[event] = function (arg) {
21+
this._redirectable.emit(event, arg);
22+
};
23+
});
24+
25+
// An HTTP(S) request that can be redirected
26+
function RedirectableRequest(options, responseCallback) {
27+
// Initialize the request
28+
Writable.call(this);
29+
this._options = options;
30+
this._redirectCount = 0;
31+
this._bufferedWrites = [];
32+
33+
// Attach a callback if passed
34+
if (responseCallback) {
35+
this.on('response', responseCallback);
36+
}
37+
38+
// React to responses of native requests
39+
var self = this;
40+
this._onNativeResponse = function (response) {
41+
self._processResponse(response);
42+
};
43+
44+
// Perform the first request
45+
this._performRequest();
46+
}
47+
RedirectableRequest.prototype = Object.create(Writable.prototype);
48+
49+
// Executes the next native request (initial or redirect)
50+
RedirectableRequest.prototype._performRequest = function () {
51+
// If specified, use the agent corresponding to the protocol
52+
// (HTTP and HTTPS use different types of agents)
53+
var protocol = this._options.protocol;
54+
if (this._options.agents) {
55+
this._options.agent = this._options.agents[schemes[protocol]];
56+
}
57+
58+
// Create the native request
59+
var nativeProtocol = nativeProtocols[this._options.protocol];
60+
var request = this._currentRequest =
61+
nativeProtocol.request(this._options, this._onNativeResponse);
62+
this._currentUrl = url.format(this._options);
63+
64+
// Set up event handlers
65+
request._redirectable = this;
66+
for (var event in eventHandlers) {
67+
if (event) {
68+
request.on(event, eventHandlers[event]);
69+
}
70+
}
71+
72+
// End a redirected request
73+
// (The first request must be ended explicitly with RedirectableRequest#end)
74+
if (this._currentResponse) {
75+
// If no body was written to the original request, or the method was changed to GET,
76+
// end the redirected request (without writing a body).
77+
var bufferedWrites = this._bufferedWrites;
78+
if (bufferedWrites.length === 0 || this._options.method === 'GET') {
79+
request.end();
80+
// The body of the original request must be added to the redirected request.
81+
} else {
82+
var i = 0;
83+
(function writeNext() {
84+
if (i < bufferedWrites.length) {
85+
var bufferedWrite = bufferedWrites[i++];
86+
request.write(bufferedWrite.data, bufferedWrite.encoding, writeNext);
87+
} else {
88+
request.end();
89+
}
90+
})();
91+
}
92+
}
93+
};
94+
95+
// Processes a response from the current native request
96+
RedirectableRequest.prototype._processResponse = function (response) {
97+
// RFC7231§6.4: The 3xx (Redirection) class of status code indicates
98+
// that further action needs to be taken by the user agent in order to
99+
// fulfill the request. If a Location header field is provided,
100+
// the user agent MAY automatically redirect its request to the URI
101+
// referenced by the Location field value,
102+
// even if the specific status code is not understood.
103+
var location = response.headers.location;
104+
if (location && this._options.followRedirects !== false &&
105+
response.statusCode >= 300 && response.statusCode < 400) {
106+
// RFC7231§6.4: A client SHOULD detect and intervene
107+
// in cyclical redirections (i.e., "infinite" redirection loops).
108+
if (++this._redirectCount > this._options.maxRedirects) {
109+
return this.emit('error', new Error('Max redirects exceeded.'));
110+
}
111+
112+
// RFC7231§6.4.7: The 307 (Temporary Redirect) status code indicates
113+
// that the target resource resides temporarily under a different URI
114+
// and the user agent MUST NOT change the request method
115+
// if it performs an automatic redirection to that URI.
116+
if (response.statusCode !== 307) {
117+
// RFC7231§6.4: Automatic redirection needs to done with
118+
// care for methods not known to be safe […],
119+
// since the user might not wish to redirect an unsafe request.
120+
if (!(this._options.method in safeMethods)) {
121+
this._options.method = 'GET';
122+
}
123+
}
124+
125+
// Perform the redirected request
126+
var redirectUrl = url.resolve(this._currentUrl, location);
127+
Object.assign(this._options, url.parse(redirectUrl));
128+
this._currentResponse = response;
129+
this._performRequest();
130+
} else {
131+
// The response is not a redirect; return it as-is
132+
response.responseUrl = this._currentUrl;
133+
this.emit('response', response);
134+
135+
// Clean up
136+
delete this._options;
137+
delete this._bufferedWrites;
138+
}
139+
};
140+
141+
// Aborts the current native request
142+
RedirectableRequest.prototype.abort = function () {
143+
this._currentRequest.abort();
144+
};
145+
146+
// Flushes the headers of the current native request
147+
RedirectableRequest.prototype.flushHeaders = function () {
148+
this._currentRequest.flushHeaders();
149+
};
150+
151+
// Sets the noDelay option of the current native request
152+
RedirectableRequest.prototype.setNoDelay = function (noDelay) {
153+
this._currentRequest.setNoDelay(noDelay);
154+
};
155+
156+
// Sets the socketKeepAlive option of the current native request
157+
RedirectableRequest.prototype.setSocketKeepAlive = function (enable, initialDelay) {
158+
this._currentRequest.setSocketKeepAlive(enable, initialDelay);
159+
};
160+
161+
// Sets the timeout option of the current native request
162+
RedirectableRequest.prototype.setTimeout = function (timeout, callback) {
163+
this._currentRequest.setTimeout(timeout, callback);
164+
};
165+
166+
// Writes buffered data to the current native request
167+
RedirectableRequest.prototype._write = function (data, encoding, callback) {
168+
this._currentRequest.write(data, encoding, callback);
169+
this._bufferedWrites.push({data: data, encoding: encoding});
170+
};
171+
172+
// Ends the current native request
173+
RedirectableRequest.prototype.end = function (data, encoding, callback) {
174+
this._currentRequest.end(data, encoding, callback);
175+
if (data) {
176+
this._bufferedWrites.push({data: data, encoding: encoding});
177+
}
178+
};
179+
180+
// Export a redirecting wrapper for each native protocol
181+
Object.keys(nativeProtocols).forEach(function (protocol) {
182+
var scheme = schemes[protocol] = protocol.substr(0, protocol.length - 1);
183+
var nativeProtocol = nativeProtocols[protocol];
184+
var wrappedProtocol = exports[scheme] = Object.create(nativeProtocol);
185+
186+
// Executes an HTTP request, following redirects
187+
wrappedProtocol.request = function (options, callback) {
188+
if (typeof options === 'string') {
189+
options = url.parse(options);
190+
options.maxRedirects = exports.maxRedirects;
191+
} else {
192+
options = Object.assign({
193+
maxRedirects: exports.maxRedirects,
194+
protocol: protocol
195+
}, options);
196+
}
197+
assert.equal(options.protocol, protocol, 'protocol mismatch');
198+
199+
return new RedirectableRequest(options, callback);
200+
};
201+
202+
// Executes a GET request, following redirects
203+
wrappedProtocol.get = function (options, callback) {
204+
var request = wrappedProtocol.request(options, callback);
205+
request.end();
206+
return request;
207+
};
208+
});

0 commit comments

Comments
 (0)