2009-09-02 09:15:26 -07:00
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
|
|
|
*
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 2009
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
* Fabrice Desré <fabrice.desre@gmail.com>, Original author
|
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
const Ci = Components.interfaces;
|
|
|
|
const Cc = Components.classes;
|
|
|
|
const Cr = Components.results;
|
|
|
|
const Cu = Components.utils;
|
|
|
|
|
|
|
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
2010-07-13 07:36:09 -07:00
|
|
|
Cu.import("resource://gre/modules/Services.jsm");
|
2009-09-02 09:15:26 -07:00
|
|
|
|
2010-09-03 12:17:00 -07:00
|
|
|
var gPromptService = null;
|
|
|
|
|
2010-06-25 13:29:47 -07:00
|
|
|
function PromptService() {
|
2010-09-03 12:17:00 -07:00
|
|
|
// Depending on if we are in the parent or child, prepare to remote
|
|
|
|
// certain calls
|
|
|
|
var appInfo = Cc["@mozilla.org/xre/app-info;1"];
|
|
|
|
if (!appInfo || appInfo.getService(Ci.nsIXULRuntime).processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT) {
|
|
|
|
// Parent process
|
|
|
|
|
|
|
|
this.inContentProcess = false;
|
|
|
|
|
|
|
|
// Used for wakeups service. FIXME: clean up with bug 593407
|
|
|
|
this.wrappedJSObject = this;
|
|
|
|
|
|
|
|
// Setup listener for child messages. We don't need to call
|
|
|
|
// addMessageListener as the wakeup service will do that for us.
|
|
|
|
this.receiveMessage = function(aMessage) {
|
|
|
|
var json = aMessage.json;
|
|
|
|
switch (aMessage.name) {
|
|
|
|
case "Prompt:Call":
|
|
|
|
// List of methods we remote - to check against malicious data.
|
|
|
|
// For example, it would be dangerous to allow content to show
|
2010-09-09 06:48:32 -07:00
|
|
|
// auth prompts.
|
|
|
|
const ALL_METHODS = ["alert", "alertCheck", "confirm", "prompt", "confirmEx", "confirmCheck", "select"];
|
2010-09-03 12:17:00 -07:00
|
|
|
var method = aMessage.json.method;
|
|
|
|
if (ALL_METHODS.indexOf(method) == -1)
|
2010-09-09 06:48:32 -07:00
|
|
|
throw "PromptServiceRemoter received an invalid method "+method;
|
2010-09-03 12:17:00 -07:00
|
|
|
var arguments = aMessage.json.arguments;
|
|
|
|
arguments.unshift(null); // No need for window, child is already on top
|
|
|
|
// (see mobile browser's PromptService.js)
|
|
|
|
var ret = this[method].apply(this, arguments);
|
|
|
|
// Return multiple return values in objects of form { value: ... },
|
|
|
|
// and also with the actual return value at the end
|
|
|
|
arguments.push(ret);
|
|
|
|
return arguments;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
// Child process
|
|
|
|
|
|
|
|
this.inContentProcess = true;
|
|
|
|
|
|
|
|
this.messageManager = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsISyncMessageSender);
|
|
|
|
}
|
|
|
|
|
|
|
|
gPromptService = this;
|
2009-09-02 09:15:26 -07:00
|
|
|
}
|
|
|
|
|
2010-06-25 13:29:47 -07:00
|
|
|
PromptService.prototype = {
|
2009-09-02 09:15:26 -07:00
|
|
|
classID: Components.ID("{9a61149b-2276-4a0a-b79c-be994ad106cf}"),
|
2009-11-12 21:09:38 -08:00
|
|
|
|
2010-06-25 13:29:47 -07:00
|
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPromptFactory, Ci.nsIPromptService, Ci.nsIPromptService2]),
|
|
|
|
|
|
|
|
/* ---------- nsIPromptFactory ---------- */
|
|
|
|
|
|
|
|
// XXX Copied from nsPrompter.js.
|
|
|
|
getPrompt: function getPrompt(domWin, iid) {
|
|
|
|
// This is still kind of dumb; the C++ code delegated to login manager
|
|
|
|
// here, which in turn calls back into us via nsIPromptService2.
|
|
|
|
if (iid.equals(Ci.nsIAuthPrompt2) || iid.equals(Ci.nsIAuthPrompt)) {
|
|
|
|
try {
|
|
|
|
let pwmgr = Cc["@mozilla.org/passwordmanager/authpromptfactory;1"].
|
|
|
|
getService(Ci.nsIPromptFactory);
|
|
|
|
return pwmgr.getPrompt(domWin, iid);
|
|
|
|
} catch (e) {
|
|
|
|
Cu.reportError("nsPrompter: Delegation to password manager failed: " + e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-02 09:15:26 -07:00
|
|
|
let doc = this.getDocument();
|
2010-09-03 12:17:00 -07:00
|
|
|
if (!doc && !this.inContentProcess) {
|
2010-06-25 13:29:47 -07:00
|
|
|
let fallback = this._getFallbackService();
|
|
|
|
return fallback.getPrompt(domWin, iid);
|
2009-11-12 21:09:38 -08:00
|
|
|
}
|
2010-06-25 13:29:47 -07:00
|
|
|
let p = new Prompt(domWin, doc);
|
|
|
|
p.QueryInterface(iid);
|
|
|
|
return p;
|
2009-09-02 09:15:26 -07:00
|
|
|
},
|
2010-06-25 13:29:47 -07:00
|
|
|
|
|
|
|
/* ---------- private memebers ---------- */
|
2010-09-03 12:17:00 -07:00
|
|
|
|
2010-06-25 13:29:47 -07:00
|
|
|
_getFallbackService: function _getFallbackService() {
|
|
|
|
return Components.classesByID["{7ad1b327-6dfa-46ec-9234-f2a620ea7e00}"]
|
|
|
|
.getService(Ci.nsIPromptService);
|
|
|
|
},
|
|
|
|
|
|
|
|
getDocument: function getDocument() {
|
2010-07-13 07:36:09 -07:00
|
|
|
let win = Services.wm.getMostRecentWindow("navigator:browser");
|
2010-06-25 13:29:47 -07:00
|
|
|
return win ? win.document : null;
|
|
|
|
},
|
|
|
|
|
|
|
|
// nsIPromptService and nsIPromptService2 methods proxy to our Prompt class
|
|
|
|
// if we can show in-document popups, or to the fallback service otherwise.
|
|
|
|
callProxy: function(aMethod, aArguments) {
|
2010-09-03 12:17:00 -07:00
|
|
|
if (this.inContentProcess) {
|
|
|
|
// Bring this tab to the front, so prompt appears on the right tab
|
|
|
|
var window = aArguments[0];
|
|
|
|
if (window && window.document) {
|
|
|
|
var event = window.document.createEvent("Events");
|
|
|
|
event.initEvent("DOMWillOpenModalDialog", true, false);
|
|
|
|
window.dispatchEvent(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send message to parent
|
|
|
|
var json = { method: aMethod,
|
|
|
|
arguments: Array.prototype.slice.call(aArguments, 1) };
|
|
|
|
// We send all prompts as sync, even alert (which has no important
|
|
|
|
// return value), as otherwise program flow will continue, and the
|
|
|
|
// script can theoretically show several alerts at once. In particular
|
|
|
|
// this can lead to a bug where you cannot click the earlier one, which
|
|
|
|
// is now hidden by a new one (and Fennec is helplessly frozen).
|
|
|
|
var response =
|
|
|
|
this.messageManager.sendSyncMessage("Prompt:Call", json)[0];
|
|
|
|
// Args copying - for methods that have out values
|
|
|
|
const ARGS_COPY_MAP = {
|
|
|
|
'prompt': [3,5],
|
|
|
|
};
|
|
|
|
if (ARGS_COPY_MAP[aMethod]) {
|
|
|
|
ARGS_COPY_MAP[aMethod].forEach(function(i) { aArguments[i].value = response[i].value; });
|
|
|
|
}
|
|
|
|
return response.pop(); // final return value was given at the end
|
|
|
|
}
|
|
|
|
|
2009-09-02 09:15:26 -07:00
|
|
|
let doc = this.getDocument();
|
2009-11-12 21:09:38 -08:00
|
|
|
if (!doc) {
|
2010-06-25 13:29:47 -07:00
|
|
|
let fallback = this._getFallbackService();
|
|
|
|
return fallback[aMethod].apply(fallback, aArguments);
|
2009-11-12 21:09:38 -08:00
|
|
|
}
|
2010-06-25 13:29:47 -07:00
|
|
|
let domWin = aArguments[0];
|
|
|
|
let p = new Prompt(domWin, doc);
|
|
|
|
return p[aMethod].apply(p, Array.prototype.slice.call(aArguments, 1));
|
2009-09-02 09:15:26 -07:00
|
|
|
},
|
2009-11-12 21:09:38 -08:00
|
|
|
|
2010-06-25 13:29:47 -07:00
|
|
|
/* ---------- nsIPromptService ---------- */
|
2009-11-12 21:09:38 -08:00
|
|
|
|
2010-06-25 13:29:47 -07:00
|
|
|
alert: function() {
|
|
|
|
return this.callProxy("alert", arguments);
|
2009-09-02 09:15:26 -07:00
|
|
|
},
|
2010-06-25 13:29:47 -07:00
|
|
|
alertCheck: function() {
|
|
|
|
return this.callProxy("alertCheck", arguments);
|
|
|
|
},
|
|
|
|
confirm: function() {
|
|
|
|
return this.callProxy("confirm", arguments);
|
|
|
|
},
|
|
|
|
confirmCheck: function() {
|
|
|
|
return this.callProxy("confirmCheck", arguments);
|
|
|
|
},
|
|
|
|
confirmEx: function() {
|
|
|
|
return this.callProxy("confirmEx", arguments);
|
|
|
|
},
|
|
|
|
prompt: function() {
|
|
|
|
return this.callProxy("prompt", arguments);
|
|
|
|
},
|
|
|
|
promptUsernameAndPassword: function() {
|
|
|
|
return this.callProxy("promptUsernameAndPassword", arguments);
|
|
|
|
},
|
|
|
|
promptPassword: function() {
|
|
|
|
return this.callProxy("promptPassword", arguments);
|
|
|
|
},
|
|
|
|
select: function() {
|
|
|
|
return this.callProxy("select", arguments);
|
|
|
|
},
|
|
|
|
|
|
|
|
/* ---------- nsIPromptService2 ---------- */
|
|
|
|
|
|
|
|
promptAuth: function() {
|
|
|
|
return this.callProxy("promptAuth", arguments);
|
|
|
|
},
|
|
|
|
asyncPromptAuth: function() {
|
|
|
|
return this.callProxy("asyncPromptAuth", arguments);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
function Prompt(aDomWin, aDocument) {
|
|
|
|
this._domWin = aDomWin;
|
|
|
|
this._doc = aDocument;
|
|
|
|
}
|
|
|
|
|
|
|
|
Prompt.prototype = {
|
|
|
|
_domWin: null,
|
|
|
|
_doc: null,
|
2009-11-12 21:09:38 -08:00
|
|
|
|
2010-06-25 13:29:47 -07:00
|
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPrompt, Ci.nsIAuthPrompt, Ci.nsIAuthPrompt2]),
|
|
|
|
|
|
|
|
/* ---------- internal methods ---------- */
|
|
|
|
|
|
|
|
openDialog: function openDialog(aSrc, aParams) {
|
2010-07-13 07:36:09 -07:00
|
|
|
let browser = Services.wm.getMostRecentWindow("navigator:browser");
|
2010-06-25 13:29:47 -07:00
|
|
|
return browser.importDialog(this._domWin, aSrc, aParams);
|
|
|
|
},
|
|
|
|
|
|
|
|
commonPrompt: function commonPrompt(aTitle, aText, aValue, aCheckMsg, aCheckState, isPassword) {
|
2009-09-02 09:15:26 -07:00
|
|
|
var params = new Object();
|
|
|
|
params.result = false;
|
|
|
|
params.checkbox = aCheckState;
|
2010-06-25 13:29:47 -07:00
|
|
|
params.value = aValue;
|
2009-11-12 21:09:38 -08:00
|
|
|
|
2010-06-25 13:29:47 -07:00
|
|
|
let dialog = this.openDialog("chrome://browser/content/prompt/prompt.xul", params);
|
|
|
|
let doc = this._doc;
|
|
|
|
doc.getElementById("prompt-prompt-title").value = aTitle;
|
|
|
|
doc.getElementById("prompt-prompt-message").appendChild(doc.createTextNode(aText));
|
|
|
|
|
|
|
|
doc.getElementById("prompt-prompt-checkbox").checked = aCheckState.value;
|
|
|
|
this.setLabelForNode(doc.getElementById("prompt-prompt-checkbox-label"), aCheckMsg);
|
|
|
|
doc.getElementById("prompt-prompt-textbox").value = aValue.value;
|
|
|
|
if (aCheckMsg)
|
|
|
|
doc.getElementById("prompt-prompt-checkbox").removeAttribute("collapsed");
|
|
|
|
|
|
|
|
if (isPassword)
|
|
|
|
doc.getElementById("prompt-prompt-textbox").type = "password";
|
2009-09-04 10:40:03 -07:00
|
|
|
|
2009-09-02 09:15:26 -07:00
|
|
|
dialog.waitForClose();
|
|
|
|
return params.result;
|
|
|
|
},
|
2010-06-25 13:29:47 -07:00
|
|
|
|
2009-09-02 09:15:26 -07:00
|
|
|
//
|
|
|
|
// Copied from chrome://global/content/commonDialog.js
|
|
|
|
//
|
2010-06-25 13:29:47 -07:00
|
|
|
setLabelForNode: function setLabelForNode(aNode, aLabel) {
|
2009-09-02 09:15:26 -07:00
|
|
|
// This is for labels which may contain embedded access keys.
|
|
|
|
// If we end in (&X) where X represents the access key, optionally preceded
|
|
|
|
// by spaces and/or followed by the ':' character, store the access key and
|
|
|
|
// remove the access key placeholder + leading spaces from the label.
|
|
|
|
// Otherwise a character preceded by one but not two &s is the access key.
|
|
|
|
// Store it and remove the &.
|
|
|
|
|
|
|
|
// Note that if you change the following code, see the comment of
|
|
|
|
// nsTextBoxFrame::UpdateAccessTitle.
|
2009-09-24 22:58:08 -07:00
|
|
|
|
|
|
|
if (!aLabel)
|
|
|
|
return;
|
|
|
|
|
2009-09-02 09:15:26 -07:00
|
|
|
var accessKey = null;
|
|
|
|
if (/ *\(\&([^&])\)(:)?$/.test(aLabel)) {
|
|
|
|
aLabel = RegExp.leftContext + RegExp.$2;
|
|
|
|
accessKey = RegExp.$1;
|
|
|
|
} else if (/^(.*[^&])?\&(([^&]).*$)/.test(aLabel)) {
|
|
|
|
aLabel = RegExp.$1 + RegExp.$2;
|
|
|
|
accessKey = RegExp.$3;
|
|
|
|
}
|
|
|
|
|
|
|
|
// && is the magic sequence to embed an & in your label.
|
|
|
|
aLabel = aLabel.replace(/\&\&/g, "&");
|
2009-09-22 21:58:34 -07:00
|
|
|
if (aNode instanceof Ci.nsIDOMXULLabelElement) {
|
2009-09-02 09:15:26 -07:00
|
|
|
aNode.setAttribute("value", aLabel);
|
2009-09-22 21:58:34 -07:00
|
|
|
} else if (aNode instanceof Ci.nsIDOMXULDescriptionElement) {
|
2009-10-09 11:26:45 -07:00
|
|
|
let text = aNode.ownerDocument.createTextNode(aLabel);
|
2009-09-22 21:58:34 -07:00
|
|
|
aNode.appendChild(text);
|
2009-09-02 09:15:26 -07:00
|
|
|
} else { // Set text for other xul elements
|
|
|
|
aNode.setAttribute("label", aLabel);
|
|
|
|
}
|
|
|
|
|
|
|
|
// XXXjag bug 325251
|
|
|
|
// Need to set this after aNode.setAttribute("value", aLabel);
|
|
|
|
if (accessKey)
|
|
|
|
aNode.setAttribute("accesskey", accessKey);
|
|
|
|
},
|
2010-06-25 13:29:47 -07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* ---------- interface disambiguation ----------
|
|
|
|
*
|
|
|
|
* XXX Copied from nsPrompter.js.
|
|
|
|
*
|
|
|
|
* nsIPrompt and nsIAuthPrompt share 3 method names with slightly
|
|
|
|
* different arguments. All but prompt() have the same number of
|
|
|
|
* arguments, so look at the arg types to figure out how we're being
|
|
|
|
* called. :-(
|
|
|
|
*/
|
|
|
|
prompt: function prompt() {
|
|
|
|
// also, the nsIPrompt flavor has 5 args instead of 6.
|
|
|
|
if (typeof arguments[2] == "object")
|
|
|
|
return this.nsIPrompt_prompt.apply(this, arguments);
|
|
|
|
else
|
|
|
|
return this.nsIAuthPrompt_prompt.apply(this, arguments);
|
|
|
|
},
|
2009-09-02 09:15:26 -07:00
|
|
|
|
2010-06-25 13:29:47 -07:00
|
|
|
promptUsernameAndPassword: function promptUsernameAndPassword() {
|
|
|
|
// Both have 6 args, so use types.
|
|
|
|
if (typeof arguments[2] == "object")
|
|
|
|
return this.nsIPrompt_promptUsernameAndPassword.apply(this, arguments);
|
|
|
|
else
|
|
|
|
return this.nsIAuthPrompt_promptUsernameAndPassword.apply(this, arguments);
|
|
|
|
},
|
|
|
|
|
|
|
|
promptPassword: function promptPassword() {
|
|
|
|
// Both have 5 args, so use types.
|
|
|
|
if (typeof arguments[2] == "object")
|
|
|
|
return this.nsIPrompt_promptPassword.apply(this, arguments);
|
|
|
|
else
|
|
|
|
return this.nsIAuthPrompt_promptPassword.apply(this, arguments);
|
|
|
|
},
|
|
|
|
|
|
|
|
/* ---------- nsIPrompt ---------- */
|
|
|
|
|
|
|
|
alert: function alert(aTitle, aText) {
|
2010-09-03 12:17:00 -07:00
|
|
|
// In addition to the remoting above, C++ can directly request this
|
|
|
|
// kind of prompt, so we remote that as well. This can happen, for
|
|
|
|
// example, if an invalid scheme is entered (e.g. garbage://something).
|
|
|
|
// That shows an alert() through this code here.
|
|
|
|
if (gPromptService.inContentProcess) {
|
|
|
|
return gPromptService.callProxy("alert", ['Alert'].concat(Array.prototype.slice.call(arguments, 0)));
|
|
|
|
}
|
|
|
|
|
2010-06-25 13:29:47 -07:00
|
|
|
let dialog = this.openDialog("chrome://browser/content/prompt/alert.xul", null);
|
|
|
|
let doc = this._doc;
|
|
|
|
doc.getElementById("prompt-alert-title").value = aTitle;
|
|
|
|
doc.getElementById("prompt-alert-message").appendChild(doc.createTextNode(aText));
|
|
|
|
|
|
|
|
dialog.waitForClose();
|
|
|
|
},
|
|
|
|
|
|
|
|
alertCheck: function alertCheck(aTitle, aText, aCheckMsg, aCheckState) {
|
|
|
|
let dialog = this.openDialog("chrome://browser/content/prompt/alert.xul", aCheckState);
|
|
|
|
let doc = this._doc;
|
|
|
|
doc.getElementById("prompt-alert-title").value = aTitle;
|
|
|
|
doc.getElementById("prompt-alert-message").appendChild(doc.createTextNode(aText));
|
|
|
|
|
|
|
|
doc.getElementById("prompt-alert-checkbox").checked = aCheckState.value;
|
|
|
|
this.setLabelForNode(doc.getElementById("prompt-alert-checkbox-label"), aCheckMsg);
|
|
|
|
doc.getElementById("prompt-alert-checkbox").removeAttribute("collapsed");
|
|
|
|
|
|
|
|
dialog.waitForClose();
|
|
|
|
},
|
|
|
|
|
|
|
|
confirm: function confirm(aTitle, aText) {
|
|
|
|
var params = new Object();
|
|
|
|
params.result = false;
|
|
|
|
|
|
|
|
let dialog = this.openDialog("chrome://browser/content/prompt/confirm.xul", params);
|
|
|
|
let doc = this._doc;
|
|
|
|
doc.getElementById("prompt-confirm-title").value = aTitle;
|
|
|
|
doc.getElementById("prompt-confirm-message").appendChild(doc.createTextNode(aText));
|
|
|
|
|
|
|
|
dialog.waitForClose();
|
|
|
|
return params.result;
|
|
|
|
},
|
|
|
|
|
|
|
|
confirmCheck: function confirmCheck(aTitle, aText, aCheckMsg, aCheckState) {
|
|
|
|
var params = new Object();
|
|
|
|
params.result = false;
|
|
|
|
params.checkbox = aCheckState;
|
|
|
|
|
|
|
|
let dialog = this.openDialog("chrome://browser/content/prompt/confirm.xul", params);
|
|
|
|
let doc = this._doc;
|
|
|
|
doc.getElementById("prompt-confirm-title").value = aTitle;
|
|
|
|
doc.getElementById("prompt-confirm-message").appendChild(doc.createTextNode(aText));
|
|
|
|
|
|
|
|
doc.getElementById("prompt-confirm-checkbox").checked = aCheckState.value;
|
|
|
|
this.setLabelForNode(doc.getElementById("prompt-confirm-checkbox-label"), aCheckMsg);
|
|
|
|
doc.getElementById("prompt-confirm-checkbox").removeAttribute("collapsed");
|
|
|
|
|
|
|
|
dialog.waitForClose();
|
|
|
|
return params.result;
|
|
|
|
},
|
2009-11-12 21:09:38 -08:00
|
|
|
|
2010-06-25 13:29:47 -07:00
|
|
|
confirmEx: function confirmEx(aTitle, aText, aButtonFlags, aButton0,
|
|
|
|
aButton1, aButton2, aCheckMsg, aCheckState) {
|
2009-09-02 09:15:26 -07:00
|
|
|
let numButtons = 0;
|
|
|
|
let titles = [aButton0, aButton1, aButton2];
|
2010-04-08 21:59:23 -07:00
|
|
|
|
|
|
|
let defaultButton = 0;
|
|
|
|
if (aButtonFlags & Ci.nsIPromptService.BUTTON_POS_1_DEFAULT)
|
|
|
|
defaultButton = 1;
|
|
|
|
if (aButtonFlags & Ci.nsIPromptService.BUTTON_POS_2_DEFAULT)
|
|
|
|
defaultButton = 2;
|
2009-09-02 09:15:26 -07:00
|
|
|
|
2010-04-08 21:59:23 -07:00
|
|
|
var params = {
|
|
|
|
result: false,
|
|
|
|
checkbox: aCheckState,
|
|
|
|
defaultButton: defaultButton
|
|
|
|
}
|
2009-11-12 21:09:38 -08:00
|
|
|
|
2010-06-25 13:29:47 -07:00
|
|
|
let dialog = this.openDialog("chrome://browser/content/prompt/confirm.xul", params);
|
|
|
|
let doc = this._doc;
|
2009-09-02 09:15:26 -07:00
|
|
|
doc.getElementById("prompt-confirm-title").value = aTitle;
|
|
|
|
doc.getElementById("prompt-confirm-message").appendChild(doc.createTextNode(aText));
|
2009-09-04 10:40:03 -07:00
|
|
|
|
2009-09-02 09:15:26 -07:00
|
|
|
doc.getElementById("prompt-confirm-checkbox").checked = aCheckState.value;
|
2010-04-29 22:00:27 -07:00
|
|
|
this.setLabelForNode(doc.getElementById("prompt-confirm-checkbox-label"), aCheckMsg);
|
2010-05-05 06:21:35 -07:00
|
|
|
if (aCheckMsg)
|
|
|
|
doc.getElementById("prompt-confirm-checkbox").removeAttribute("collapsed");
|
|
|
|
|
|
|
|
|
2010-04-29 22:00:27 -07:00
|
|
|
let bbox = doc.getElementById("prompt-confirm-buttons-box");
|
2010-05-05 06:21:35 -07:00
|
|
|
while (bbox.lastChild)
|
2009-09-02 09:15:26 -07:00
|
|
|
bbox.removeChild(bbox.lastChild);
|
2010-05-05 06:21:35 -07:00
|
|
|
|
2009-09-02 09:15:26 -07:00
|
|
|
for (let i = 0; i < 3; i++) {
|
|
|
|
let bTitle = null;
|
|
|
|
switch (aButtonFlags & 0xff) {
|
|
|
|
case Ci.nsIPromptService.BUTTON_TITLE_OK :
|
2010-06-25 13:29:47 -07:00
|
|
|
bTitle = PromptUtils.getLocaleString("OK");
|
2009-09-02 09:15:26 -07:00
|
|
|
break;
|
|
|
|
case Ci.nsIPromptService.BUTTON_TITLE_CANCEL :
|
2010-06-25 13:29:47 -07:00
|
|
|
bTitle = PromptUtils.getLocaleString("Cancel");
|
2009-09-02 09:15:26 -07:00
|
|
|
break;
|
|
|
|
case Ci.nsIPromptService.BUTTON_TITLE_YES :
|
2010-06-25 13:29:47 -07:00
|
|
|
bTitle = PromptUtils.getLocaleString("Yes");
|
2009-09-02 09:15:26 -07:00
|
|
|
break;
|
|
|
|
case Ci.nsIPromptService.BUTTON_TITLE_NO :
|
2010-06-25 13:29:47 -07:00
|
|
|
bTitle = PromptUtils.getLocaleString("No");
|
2009-09-02 09:15:26 -07:00
|
|
|
break;
|
|
|
|
case Ci.nsIPromptService.BUTTON_TITLE_SAVE :
|
2010-06-25 13:29:47 -07:00
|
|
|
bTitle = PromptUtils.getLocaleString("Save");
|
2009-09-02 09:15:26 -07:00
|
|
|
break;
|
|
|
|
case Ci.nsIPromptService.BUTTON_TITLE_DONT_SAVE :
|
2010-06-25 13:29:47 -07:00
|
|
|
bTitle = PromptUtils.getLocaleString("DontSave");
|
2009-09-02 09:15:26 -07:00
|
|
|
break;
|
|
|
|
case Ci.nsIPromptService.BUTTON_TITLE_REVERT :
|
2010-06-25 13:29:47 -07:00
|
|
|
bTitle = PromptUtils.getLocaleString("Revert");
|
2009-09-02 09:15:26 -07:00
|
|
|
break;
|
|
|
|
case Ci.nsIPromptService.BUTTON_TITLE_IS_STRING :
|
|
|
|
bTitle = titles[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bTitle) {
|
|
|
|
let button = doc.createElement("button");
|
2010-07-30 12:03:03 -07:00
|
|
|
button.className = "prompt-button";
|
2009-09-22 21:58:34 -07:00
|
|
|
this.setLabelForNode(button, bTitle);
|
2010-04-15 07:40:43 -07:00
|
|
|
if (i == defaultButton) {
|
|
|
|
button.setAttribute("command", "cmd_ok");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
button.setAttribute("oncommand",
|
|
|
|
"document.getElementById('prompt-confirm-dialog').PromptHelper.closeConfirm(" + i + ")");
|
|
|
|
}
|
2009-09-02 09:15:26 -07:00
|
|
|
bbox.appendChild(button);
|
|
|
|
}
|
|
|
|
|
|
|
|
aButtonFlags >>= 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
dialog.waitForClose();
|
|
|
|
return params.result;
|
|
|
|
},
|
|
|
|
|
2010-06-25 13:29:47 -07:00
|
|
|
nsIPrompt_prompt: function nsIPrompt_prompt(aTitle, aText, aValue, aCheckMsg, aCheckState) {
|
|
|
|
return this.commonPrompt(aTitle, aText, aValue, aCheckMsg, aCheckState, false);
|
2009-09-02 09:15:26 -07:00
|
|
|
},
|
|
|
|
|
2010-06-25 13:29:47 -07:00
|
|
|
nsIPrompt_promptPassword: function nsIPrompt_promptPassword(
|
|
|
|
aTitle, aText, aPassword, aCheckMsg, aCheckState) {
|
|
|
|
return this.commonPrompt(aTitle, aText, aPassword, aCheckMsg, aCheckState, true);
|
2009-09-02 09:15:26 -07:00
|
|
|
},
|
|
|
|
|
2010-06-25 13:29:47 -07:00
|
|
|
nsIPrompt_promptUsernameAndPassword: function nsIPrompt_promptUsernameAndPassword(
|
|
|
|
aTitle, aText, aUsername, aPassword, aCheckMsg, aCheckState) {
|
2009-09-02 09:15:26 -07:00
|
|
|
var params = new Object();
|
|
|
|
params.result = false;
|
|
|
|
params.checkbox = aCheckState;
|
|
|
|
params.user = aUsername;
|
|
|
|
params.password = aPassword;
|
2009-11-12 21:09:38 -08:00
|
|
|
|
2010-06-25 13:29:47 -07:00
|
|
|
let dialog = this.openDialog("chrome://browser/content/prompt/promptPassword.xul", params);
|
|
|
|
let doc = this._doc;
|
2009-09-02 09:15:26 -07:00
|
|
|
doc.getElementById("prompt-password-title").value = aTitle;
|
|
|
|
doc.getElementById("prompt-password-message").appendChild(doc.createTextNode(aText));
|
|
|
|
doc.getElementById("prompt-password-checkbox").checked = aCheckState.value;
|
2009-09-04 10:40:03 -07:00
|
|
|
|
2009-09-02 09:15:26 -07:00
|
|
|
doc.getElementById("prompt-password-user").value = aUsername.value;
|
|
|
|
doc.getElementById("prompt-password-password").value = aPassword.value;
|
|
|
|
if (aCheckMsg) {
|
2010-05-05 06:21:35 -07:00
|
|
|
doc.getElementById("prompt-password-checkbox").removeAttribute("collapsed");
|
2010-04-29 22:00:27 -07:00
|
|
|
this.setLabelForNode(doc.getElementById("prompt-password-checkbox-label"), aCheckMsg);
|
2009-09-02 09:15:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
dialog.waitForClose();
|
|
|
|
return params.result;
|
|
|
|
},
|
|
|
|
|
2010-06-25 13:29:47 -07:00
|
|
|
select: function select(aTitle, aText, aCount, aSelectList, aOutSelection) {
|
|
|
|
var params = new Object();
|
|
|
|
params.result = false;
|
|
|
|
params.selection = aOutSelection;
|
|
|
|
|
|
|
|
let dialog = this.openDialog("chrome://browser/content/prompt/select.xul", params);
|
|
|
|
let doc = this._doc;
|
|
|
|
doc.getElementById("prompt-select-title").value = aTitle;
|
|
|
|
doc.getElementById("prompt-select-message").appendChild(doc.createTextNode(aText));
|
|
|
|
|
|
|
|
let list = doc.getElementById("prompt-select-list");
|
|
|
|
for (let i = 0; i < aCount; i++)
|
|
|
|
list.appendItem(aSelectList[i], null, null);
|
|
|
|
|
|
|
|
// select the first one
|
|
|
|
list.selectedIndex = 0;
|
|
|
|
|
|
|
|
dialog.waitForClose();
|
|
|
|
return params.result;
|
|
|
|
},
|
|
|
|
|
|
|
|
/* ---------- nsIAuthPrompt ---------- */
|
|
|
|
|
|
|
|
nsIAuthPrompt_prompt : function (title, text, passwordRealm, savePassword, defaultText, result) {
|
|
|
|
// The passwordRealm and savePassword args were ignored by nsPrompt.cpp
|
|
|
|
if (defaultText)
|
|
|
|
result.value = defaultText;
|
|
|
|
return this.nsIPrompt_prompt(title, text, result, null, {});
|
|
|
|
},
|
|
|
|
|
|
|
|
nsIAuthPrompt_promptUsernameAndPassword : function (title, text, passwordRealm, savePassword, user, pass) {
|
|
|
|
// The passwordRealm and savePassword args were ignored by nsPrompt.cpp
|
|
|
|
return this.nsIPrompt_promptUsernameAndPassword(title, text, user, pass, null, {});
|
|
|
|
},
|
|
|
|
|
|
|
|
nsIAuthPrompt_promptPassword : function (title, text, passwordRealm, savePassword, pass) {
|
|
|
|
// The passwordRealm and savePassword args were ignored by nsPrompt.cpp
|
|
|
|
return this.nsIPrompt_promptPassword(title, text, pass, null, {});
|
|
|
|
},
|
|
|
|
|
|
|
|
/* ---------- nsIAuthPrompt2 ---------- */
|
|
|
|
|
|
|
|
promptAuth: function promptAuth(aChannel, aLevel, aAuthInfo, aCheckMsg, aCheckState) {
|
|
|
|
let res = false;
|
|
|
|
|
|
|
|
let defaultUser = aAuthInfo.username;
|
|
|
|
if ((aAuthInfo.flags & aAuthInfo.NEED_DOMAIN) && (aAuthInfo.domain.length > 0))
|
|
|
|
defaultUser = aAuthInfo.domain + "\\" + defaultUser;
|
|
|
|
|
|
|
|
let username = { value: defaultUser };
|
|
|
|
let password = { value: aAuthInfo.password };
|
|
|
|
|
|
|
|
let message = PromptUtils.makeDialogText(aChannel, aAuthInfo);
|
|
|
|
let title = PromptUtils.getLocaleString("PromptUsernameAndPassword2");
|
|
|
|
|
|
|
|
if (aAuthInfo.flags & aAuthInfo.ONLY_PASSWORD)
|
|
|
|
res = this.promptPassword(title, message, password, aCheckMsg, aCheckState);
|
|
|
|
else
|
|
|
|
res = this.promptUsernameAndPassword(title, message, username, password, aCheckMsg, aCheckState);
|
|
|
|
|
|
|
|
if (res) {
|
|
|
|
aAuthInfo.username = username.value;
|
|
|
|
aAuthInfo.password = password.value;
|
2009-09-04 10:40:03 -07:00
|
|
|
}
|
2010-06-25 13:29:47 -07:00
|
|
|
|
2009-09-04 10:40:03 -07:00
|
|
|
return res;
|
|
|
|
},
|
|
|
|
|
2010-06-25 13:29:47 -07:00
|
|
|
asyncPromptAuth: function asyncPromptAuth(aChannel, aCallback, aContext, aLevel, aAuthInfo, aCheckMsg, aCheckState) {
|
|
|
|
// bug 514196
|
|
|
|
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let PromptUtils = {
|
|
|
|
getLocaleString: function getLocaleString(key) {
|
|
|
|
return this.bundle.GetStringFromName(key);
|
|
|
|
},
|
|
|
|
|
2009-09-04 10:40:03 -07:00
|
|
|
// JS port of http://mxr.mozilla.org/mozilla-central/source/embedding/components/windowwatcher/src/nsPrompt.cpp#388
|
2010-06-25 13:29:47 -07:00
|
|
|
makeDialogText: function makeDialogText(aChannel, aAuthInfo) {
|
2009-09-04 10:40:03 -07:00
|
|
|
let HostPort = this.getAuthHostPort(aChannel, aAuthInfo);
|
|
|
|
let displayHost = HostPort.host;
|
|
|
|
let uri = aChannel.URI;
|
|
|
|
let scheme = uri.scheme;
|
|
|
|
let username = aAuthInfo.username;
|
|
|
|
let proxyAuth = (aAuthInfo.flags & aAuthInfo.AUTH_PROXY) != 0;
|
|
|
|
let realm = aAuthInfo.realm;
|
|
|
|
if (realm.length > 100) { // truncate and add ellipsis
|
2010-07-13 07:36:09 -07:00
|
|
|
let pref = Services.prefs;
|
2009-09-04 10:40:03 -07:00
|
|
|
let ellipsis = pref.getComplexValue("intl.ellipsis", Ci.nsIPrefLocalizedString).data;
|
|
|
|
if (!ellipsis)
|
|
|
|
ellipsis = "...";
|
|
|
|
realm = realm.substring(0, 100) + ellipsis;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (HostPort.port != -1)
|
|
|
|
displayHost += ":" + HostPort.port;
|
|
|
|
|
|
|
|
let text = null;
|
|
|
|
if (proxyAuth) {
|
|
|
|
text = "EnterLoginForProxy";
|
|
|
|
} else {
|
|
|
|
text = "EnterLoginForRealm";
|
|
|
|
displayHost = scheme + "://" + displayHost;
|
|
|
|
}
|
|
|
|
|
|
|
|
let strings = [realm, displayHost];
|
|
|
|
let count = 2;
|
|
|
|
if (aAuthInfo.flags & aAuthInfo.ONLY_PASSWORD) {
|
|
|
|
text = "EnterPasswordFor";
|
|
|
|
strings[0] = username;
|
|
|
|
} else if (!proxyAuth && (realm.length == 0)) {
|
|
|
|
text = "EnterUserPasswordFor";
|
|
|
|
count = 1;
|
|
|
|
strings[0] = strings[1];
|
|
|
|
}
|
|
|
|
|
2010-06-25 13:29:47 -07:00
|
|
|
return this.bundle.formatStringFromName(text, strings, count);
|
2009-09-04 10:40:03 -07:00
|
|
|
},
|
|
|
|
|
2010-06-25 13:29:47 -07:00
|
|
|
// JS port of http://mxr.mozilla.org/mozilla-central/source/embedding/components/windowwatcher/public/nsPromptUtils.h#89
|
|
|
|
getAuthHostPort: function getAuthHostPort(aChannel, aAuthInfo) {
|
|
|
|
let uri = aChannel.URI;
|
|
|
|
let res = { host: null, port: -1 };
|
|
|
|
if (aAuthInfo.flags & aAuthInfo.AUTH_PROXY) {
|
|
|
|
let proxy = aChannel.QueryInterface(Ci.nsIProxiedChannel);
|
|
|
|
res.host = proxy.proxyInfo.host;
|
|
|
|
res.port = proxy.proxyInfo.port;
|
|
|
|
} else {
|
|
|
|
res.host = uri.host;
|
|
|
|
res.port = uri.port;
|
2009-09-04 10:40:03 -07:00
|
|
|
}
|
|
|
|
return res;
|
2009-09-02 09:15:26 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2010-06-25 13:29:47 -07:00
|
|
|
XPCOMUtils.defineLazyGetter(PromptUtils, "bundle", function () {
|
2010-07-13 07:36:09 -07:00
|
|
|
return Services.strings.createBundle("chrome://global/locale/commonDialogs.properties");
|
2010-06-25 13:29:47 -07:00
|
|
|
});
|
|
|
|
|
2010-06-29 14:02:25 -07:00
|
|
|
const NSGetFactory = XPCOMUtils.generateNSGetFactory([PromptService]);
|