3
Copyright (C) 2006-2010 LeahScape, Inc.
4
http://foxyproxy.mozdev.org/
7
This source code is released under the GPL license,
8
available in the LICENSE file at the root of this installation
9
and also online at http://www.gnu.org/licenses/gpl.txt
12
// Thanks for the template, doron (http://www.nexgenmedia.net/docs/protocol/)
13
const kSCHEME = "proxy";
14
const kPROTOCOL_NAME = "FoxyProxy Protocol";
15
const kPROTOCOL_CONTRACTID = "@mozilla.org/network/protocol;1?name=" + kSCHEME;
16
const kPROTOCOL_CID = Components.ID("d1362868-da85-4faa-b1bf-24bfd936b0a6");
17
var CI = Components.interfaces, CC = Components.classes, CR = Components.results;
19
const kSIMPLEURI_CONTRACTID = "@mozilla.org/network/simple-uri;1";
20
const kIOSERVICE_CONTRACTID = "@mozilla.org/network/io-service;1";
21
const nsISupports = Components.interfaces.nsISupports;
22
const nsIIOService = Components.interfaces.nsIIOService;
23
const nsIProtocolHandler = Components.interfaces.nsIProtocolHandler;
24
const nsIURI = Components.interfaces.nsIURI;
25
const IOS = CC[kIOSERVICE_CONTRACTID].
26
getService(nsIIOService).getProtocolHandler("file").
27
QueryInterface(CI.nsIFileProtocolHandler);
29
function Protocol() {}
31
Protocol.prototype = {
32
QueryInterface: function(iid) {
33
if (!iid.equals(nsIProtocolHandler) &&
34
!iid.equals(nsISupports))
35
throw Components.results.NS_ERROR_NO_INTERFACE;
41
protocolFlags: nsIProtocolHandler.URI_LOADABLE_BY_ANYONE,
43
allowPort: function(port, scheme) {
47
newURI: function(spec, charset, baseURI) {
48
var uri = CC[kSIMPLEURI_CONTRACTID].createInstance(nsIURI);
53
processURI : function(aURI) {
54
// aURI is a nsIUri, so get a string from it using .spec
56
// strip away the proxy: part
57
uri = uri.substring(uri.indexOf(":") + 1, uri.length);
58
// and, optionally, leading // as in proxy://
59
if (uri.indexOf("//") == 0)
60
uri = uri.substring(2);
62
// e.g. proxy:ip=xx.xx.xx.xx&port=yyyyy
63
// Parse query params into nameValuePairs array
64
var count = 0, nameValuePairs = [], queryParams = uri.split('&'), foundSomeInput;
65
for (var i in queryParams) {
66
var pair = queryParams[i].split('=');
67
if (pair.length == 2) {
68
nameValuePairs[pair[0]] = pair[1];
69
foundSomeInput = true;
72
if (!foundSomeInput) return;
73
var proxy = CC["@leahscape.org/foxyproxy/proxy;1"].createInstance().wrappedJSObject;
74
proxy.fromAssociateArray(nameValuePairs);
75
// We accept URIs like this:
76
// proxy:foxyProxyMode=disabled
77
// with no other parameters. In cases like that, we must skip the
78
// create/update/delete proxy code otherwise we'll create an empty/useless proxy
79
// Note: |uri| has been stripped of its scheme at this point.
80
var fp = CC["@leahscape.org/foxyproxy/service;1"].getService().wrappedJSObject;
81
if (!(/^foxyProxyMode=[^&]*$/.test(uri))) {
82
// Are we adding a new proxy, or deleting or updating an existing one? Default is to updateOrAdd.
83
if (!nameValuePairs["action"]) { /* no action was specified */
84
nameValuePairs["action"] = "updateOrAdd";
86
switch (nameValuePairs["action"]) {
88
var p = fp.proxies.mergeByName(proxy, nameValuePairs);
91
fp.broadcast(null, "foxyproxy-proxy-change");
95
fp.proxies.insertAt(nameValuePairs["position"], proxy);
96
fp.broadcast(null, "foxyproxy-proxy-change");
98
case "delete": /* deliberate fall-through */
100
fp.proxies.deleteByName(proxy.name, false);
101
fp.broadcast(null, "foxyproxy-proxy-change");
103
case "deleteMultiple":
104
fp.proxies.deleteByName(proxy.name, true);
105
fp.broadcast(null, "foxyproxy-proxy-change");
108
var p = fp.proxies.mergeByName(proxy, nameValuePairs);
112
fp.proxies.insertAt(nameValuePairs["position"], proxy);
113
fp.broadcast(null, "foxyproxy-proxy-change");
116
fp.writeSettings(); // Save to disk
119
// If foxyProxyMode was specified as "this", translate that to something that fp.setMode() understands.
120
// Can't set mode to "this" if you're deleting.
121
if (nameValuePairs["foxyProxyMode"] == "this") {
122
nameValuePairs["foxyProxyMode"] =
123
nameValuePairs["action"] == "delete" || nameValuePairs["action"] == "deleteOne" || nameValuePairs["action"] == "deleteMultiple" ?
127
// If a proxy name was specifed, get its ID and use that for new foxyproxy mode.
128
else if (nameValuePairs["foxyProxyMode"] != "patterns" && nameValuePairs["foxyProxyMode"] != "disabled" &&
129
nameValuePairs["foxyProxyMode"] != "random" && nameValuePairs["foxyProxyMode"] != "previous" &&
130
nameValuePairs["foxyProxyMode"] != "roundrobin" && !fp.proxies.getProxyById(nameValuePairs["foxyProxyMode"])) {
131
var proxy = fp.proxies.getProxyByName(nameValuePairs["foxyProxyMode"]);
133
nameValuePairs["foxyProxyMode"] = proxy.id;
136
// Set mode last in case user is setting mode to the proxy we just configured.
137
// (In that case, setting mode earlier will result in the proxy not being found)
138
if (nameValuePairs["foxyProxyMode"]) {
139
fp.setMode(nameValuePairs["foxyProxyMode"], true);
140
fp.broadcast(null, "foxyproxy-mode-change");
144
if (nameValuePairs["confirmation"] == "popup") {
145
fp.notifier.alert(fp.getMessage("foxyproxy"), fp.getMessage("proxy.configured", [nameValuePairs["name"]]));
148
else if (nameValuePairs["confirmation"]) {
149
// Is it a valid URL?
151
CC["@mozilla.org/network/io-service;1"]
152
.getService(CI.nsIIOService).newURI(nameValuePairs["confirmation"], "UTF-8", null);
154
catch(e) {/* not a valid URL */ return; }
155
CC["@leahscape.org/foxyproxy/common;1"].getService().wrappedJSObject
156
.openTab(nameValuePairs["confirmation"]);
160
newChannel: function(aURI) {
161
var fp = CC["@leahscape.org/foxyproxy/service;1"].getService().wrappedJSObject;
162
if (fp.ignoreProxyScheme) return new nsDummyChannel();
164
// user notification first
165
var fpc = CC["@leahscape.org/foxyproxy/common;1"].getService().wrappedJSObject
167
fpc.notify("proxy.scheme.warning.2", null, function() {fpph.processURI(aURI)});
168
return new nsDummyChannel();
172
// BEGIN: Dummy channel implementation - thanks mark finkle and http://mxr.mozilla.org/mobile-browser/source/components/protocols/nsTelProtocolHandler.js#49
173
function nsDummyChannel() {}
175
nsDummyChannel.prototype.QueryInterface =
176
function bc_QueryInterface(iid) {
177
if (!iid.equals(CI.nsIChannel) && !iid.equals(CI.nsIRequest) &&
178
!iid.equals(CI.nsISupports))
179
throw CR.NS_ERROR_NO_INTERFACE;
184
nsDummyChannel.prototype.loadAttributes = null;
185
nsDummyChannel.prototype.contentLength = 0;
186
nsDummyChannel.prototype.owner = null;
187
nsDummyChannel.prototype.loadGroup = null;
188
nsDummyChannel.prototype.notificationCallbacks = null;
189
nsDummyChannel.prototype.securityInfo = null;
191
nsDummyChannel.prototype.open =
192
nsDummyChannel.prototype.asyncOpen =
193
function bc_open(observer, ctxt) {
194
// We don't throw this (a number, not a real 'resultcode') because it
195
// upsets xpconnect if we do (error in the js console).
196
Components.returnCode = CR.NS_ERROR_NO_CONTENT;
199
nsDummyChannel.prototype.asyncRead =
200
function bc_asyncRead(listener, ctxt) {
201
throw CR.NS_ERROR_NOT_IMPLEMENTED;
205
nsDummyChannel.prototype.isPending =
206
function bc_isPending() {
210
nsDummyChannel.prototype.status = CR.NS_OK;
212
nsDummyChannel.prototype.cancel =
213
function bc_cancel(status) {
214
this.status = status;
217
nsDummyChannel.prototype.suspend =
218
nsDummyChannel.prototype.resume =
219
function bc_suspres() {
220
throw CR.NS_ERROR_NOT_IMPLEMENTED;
222
// END: Dummy channel implementation - thanks mark finkle and http://mxr.mozilla.org/mobile-browser/source/components/protocols/nsTelProtocolHandler.js#49
224
var ProtocolFactory = new Object();
226
ProtocolFactory.createInstance = function (outer, iid) {
228
throw Components.results.NS_ERROR_NO_AGGREGATION;
229
if (!iid.equals(nsIProtocolHandler) &&
230
!iid.equals(nsISupports))
231
throw Components.results.NS_ERROR_NO_INTERFACE;
232
var p = new Protocol();
237
* JS XPCOM boilerplate component registration code.
239
var prochandler = new Object();
241
prochandler.registerSelf = function (compMgr, fileSpec, location, type) {
242
compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
243
compMgr.registerFactoryLocation(kPROTOCOL_CID,
245
kPROTOCOL_CONTRACTID,
251
prochandler.getClassObject = function (compMgr, cid, iid) {
252
if (!cid.equals(kPROTOCOL_CID))
253
throw Components.results.NS_ERROR_NO_INTERFACE;
255
if (!iid.equals(Components.interfaces.nsIFactory))
256
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
257
return ProtocolFactory;
260
prochandler.canUnload = function (compMgr) {
264
function NSGetModule(compMgr, fileSpec){