зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1629113 - Move prompt classes to its own modules. r=snorp
Differential Revision: https://phabricator.services.mozilla.com/D75877
This commit is contained in:
Родитель
903fea5453
Коммит
7cdda27e40
|
@ -0,0 +1,46 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = ["ColorPickerDelegate"];
|
||||
|
||||
const { GeckoViewUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/GeckoViewUtils.jsm"
|
||||
);
|
||||
|
||||
const { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
GeckoViewPrompter: "resource://gre/modules/GeckoViewPrompter.jsm",
|
||||
});
|
||||
|
||||
const { debug, warn } = GeckoViewUtils.initLogging("ColorPickerDelegate"); // eslint-disable-line no-unused-vars
|
||||
|
||||
class ColorPickerDelegate {
|
||||
init(aParent, aTitle, aInitialColor) {
|
||||
this._prompt = new GeckoViewPrompter(aParent);
|
||||
this._msg = {
|
||||
type: "color",
|
||||
title: aTitle,
|
||||
value: aInitialColor,
|
||||
};
|
||||
}
|
||||
|
||||
open(aColorPickerShownCallback) {
|
||||
this._prompt.asyncShowPrompt(this._msg, result => {
|
||||
// OK: result
|
||||
// Cancel: !result
|
||||
aColorPickerShownCallback.done((result && result.color) || "");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ColorPickerDelegate.prototype.classID = Components.ID(
|
||||
"{aa0dd6fc-73dd-4621-8385-c0b377e02cee}"
|
||||
);
|
||||
ColorPickerDelegate.prototype.QueryInterface = ChromeUtils.generateQI([
|
||||
Ci.nsIColorPicker,
|
||||
]);
|
|
@ -0,0 +1,197 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = ["FilePickerDelegate"];
|
||||
|
||||
const { GeckoViewUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/GeckoViewUtils.jsm"
|
||||
);
|
||||
|
||||
const { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
FileUtils: "resource://gre/modules/FileUtils.jsm",
|
||||
GeckoViewPrompter: "resource://gre/modules/GeckoViewPrompter.jsm",
|
||||
Services: "resource://gre/modules/Services.jsm",
|
||||
});
|
||||
|
||||
const { debug, warn } = GeckoViewUtils.initLogging("FilePickerDelegate"); // eslint-disable-line no-unused-vars
|
||||
|
||||
class FilePickerDelegate {
|
||||
/* ---------- nsIFilePicker ---------- */
|
||||
init(aParent, aTitle, aMode) {
|
||||
if (
|
||||
aMode === Ci.nsIFilePicker.modeGetFolder ||
|
||||
aMode === Ci.nsIFilePicker.modeSave
|
||||
) {
|
||||
throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED);
|
||||
}
|
||||
this._prompt = new GeckoViewPrompter(aParent);
|
||||
this._msg = {
|
||||
type: "file",
|
||||
title: aTitle,
|
||||
mode: aMode === Ci.nsIFilePicker.modeOpenMultiple ? "multiple" : "single",
|
||||
};
|
||||
this._mode = aMode;
|
||||
this._mimeTypes = [];
|
||||
this._capture = 0;
|
||||
}
|
||||
|
||||
get mode() {
|
||||
return this._mode;
|
||||
}
|
||||
|
||||
appendRawFilter(aFilter) {
|
||||
this._mimeTypes.push(aFilter);
|
||||
}
|
||||
|
||||
show() {
|
||||
throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
open(aFilePickerShownCallback) {
|
||||
this._msg.mimeTypes = this._mimeTypes;
|
||||
this._msg.capture = this._capture;
|
||||
this._prompt.asyncShowPrompt(this._msg, result => {
|
||||
// OK: result
|
||||
// Cancel: !result
|
||||
if (!result || !result.files || !result.files.length) {
|
||||
aFilePickerShownCallback.done(Ci.nsIFilePicker.returnCancel);
|
||||
} else {
|
||||
this._resolveFiles(result.files, aFilePickerShownCallback);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async _resolveFiles(aFiles, aCallback) {
|
||||
const fileData = [];
|
||||
|
||||
try {
|
||||
for (const file of aFiles) {
|
||||
const domFile = await this._getDOMFile(file);
|
||||
fileData.push({
|
||||
file,
|
||||
domFile,
|
||||
});
|
||||
}
|
||||
} catch (ex) {
|
||||
warn`Error resolving files from file picker: ${ex}`;
|
||||
aCallback.done(Ci.nsIFilePicker.returnCancel);
|
||||
return;
|
||||
}
|
||||
|
||||
this._fileData = fileData;
|
||||
aCallback.done(Ci.nsIFilePicker.returnOK);
|
||||
}
|
||||
|
||||
get file() {
|
||||
if (!this._fileData) {
|
||||
throw Components.Exception("", Cr.NS_ERROR_NOT_AVAILABLE);
|
||||
}
|
||||
const fileData = this._fileData[0];
|
||||
if (!fileData) {
|
||||
return null;
|
||||
}
|
||||
return new FileUtils.File(fileData.file);
|
||||
}
|
||||
|
||||
get fileURL() {
|
||||
return Services.io.newFileURI(this.file);
|
||||
}
|
||||
|
||||
*_getEnumerator(aDOMFile) {
|
||||
if (!this._fileData) {
|
||||
throw Components.Exception("", Cr.NS_ERROR_NOT_AVAILABLE);
|
||||
}
|
||||
|
||||
for (const fileData of this._fileData) {
|
||||
if (aDOMFile) {
|
||||
yield fileData.domFile;
|
||||
}
|
||||
yield new FileUtils.File(fileData.file);
|
||||
}
|
||||
}
|
||||
|
||||
get files() {
|
||||
return this._getEnumerator(/* aDOMFile */ false);
|
||||
}
|
||||
|
||||
_getDOMFile(aPath) {
|
||||
if (this._prompt.domWin) {
|
||||
return this._prompt.domWin.File.createFromFileName(aPath);
|
||||
}
|
||||
return File.createFromFileName(aPath);
|
||||
}
|
||||
|
||||
get domFileOrDirectory() {
|
||||
if (!this._fileData) {
|
||||
throw Components.Exception("", Cr.NS_ERROR_NOT_AVAILABLE);
|
||||
}
|
||||
return this._fileData[0] ? this._fileData[0].domFile : null;
|
||||
}
|
||||
|
||||
get domFileOrDirectoryEnumerator() {
|
||||
return this._getEnumerator(/* aDOMFile */ true);
|
||||
}
|
||||
|
||||
get defaultString() {
|
||||
return "";
|
||||
}
|
||||
|
||||
set defaultString(aValue) {}
|
||||
|
||||
get defaultExtension() {
|
||||
return "";
|
||||
}
|
||||
|
||||
set defaultExtension(aValue) {}
|
||||
|
||||
get filterIndex() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
set filterIndex(aValue) {}
|
||||
|
||||
get displayDirectory() {
|
||||
return null;
|
||||
}
|
||||
|
||||
set displayDirectory(aValue) {}
|
||||
|
||||
get displaySpecialDirectory() {
|
||||
return "";
|
||||
}
|
||||
|
||||
set displaySpecialDirectory(aValue) {}
|
||||
|
||||
get addToRecentDocs() {
|
||||
return false;
|
||||
}
|
||||
|
||||
set addToRecentDocs(aValue) {}
|
||||
|
||||
get okButtonLabel() {
|
||||
return "";
|
||||
}
|
||||
|
||||
set okButtonLabel(aValue) {}
|
||||
|
||||
get capture() {
|
||||
return this._capture;
|
||||
}
|
||||
|
||||
set capture(aValue) {
|
||||
this._capture = aValue;
|
||||
}
|
||||
}
|
||||
|
||||
FilePickerDelegate.prototype.classID = Components.ID(
|
||||
"{e4565e36-f101-4bf5-950b-4be0887785a9}"
|
||||
);
|
||||
FilePickerDelegate.prototype.QueryInterface = ChromeUtils.generateQI([
|
||||
Ci.nsIFilePicker,
|
||||
]);
|
|
@ -3,13 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = [
|
||||
"ColorPickerDelegate",
|
||||
"FilePickerDelegate",
|
||||
"LoginStorageDelegate",
|
||||
"PromptFactory",
|
||||
"ShareDelegate",
|
||||
];
|
||||
var EXPORTED_SYMBOLS = ["PromptFactory"];
|
||||
|
||||
const { GeckoViewUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/GeckoViewUtils.jsm"
|
||||
|
@ -20,18 +14,10 @@ const { XPCOMUtils } = ChromeUtils.import(
|
|||
);
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
FileUtils: "resource://gre/modules/FileUtils.jsm",
|
||||
GeckoViewAutocomplete: "resource://gre/modules/GeckoViewAutocomplete.jsm",
|
||||
GeckoViewPrompter: "resource://gre/modules/GeckoViewPrompter.jsm",
|
||||
GeckoViewUtils: "resource://gre/modules/GeckoViewUtils.jsm",
|
||||
LoginEntry: "resource://gre/modules/GeckoViewAutocomplete.jsm",
|
||||
Services: "resource://gre/modules/Services.jsm",
|
||||
});
|
||||
|
||||
const domBundle = Services.strings.createBundle(
|
||||
"chrome://global/locale/dom/dom.properties"
|
||||
);
|
||||
|
||||
const { debug, warn } = GeckoViewUtils.initLogging("GeckoViewPrompt"); // eslint-disable-line no-unused-vars
|
||||
|
||||
function PromptFactory() {
|
||||
|
@ -911,361 +897,3 @@ PromptDelegate.prototype = {
|
|||
return { displayHost, realm };
|
||||
},
|
||||
};
|
||||
|
||||
class FilePickerDelegate {
|
||||
/* ---------- nsIFilePicker ---------- */
|
||||
init(aParent, aTitle, aMode) {
|
||||
if (
|
||||
aMode === Ci.nsIFilePicker.modeGetFolder ||
|
||||
aMode === Ci.nsIFilePicker.modeSave
|
||||
) {
|
||||
throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED);
|
||||
}
|
||||
this._prompt = new GeckoViewPrompter(aParent);
|
||||
this._msg = {
|
||||
type: "file",
|
||||
title: aTitle,
|
||||
mode: aMode === Ci.nsIFilePicker.modeOpenMultiple ? "multiple" : "single",
|
||||
};
|
||||
this._mode = aMode;
|
||||
this._mimeTypes = [];
|
||||
this._capture = 0;
|
||||
}
|
||||
|
||||
get mode() {
|
||||
return this._mode;
|
||||
}
|
||||
|
||||
appendRawFilter(aFilter) {
|
||||
this._mimeTypes.push(aFilter);
|
||||
}
|
||||
|
||||
show() {
|
||||
throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
open(aFilePickerShownCallback) {
|
||||
this._msg.mimeTypes = this._mimeTypes;
|
||||
this._msg.capture = this._capture;
|
||||
this._prompt.asyncShowPrompt(this._msg, result => {
|
||||
// OK: result
|
||||
// Cancel: !result
|
||||
if (!result || !result.files || !result.files.length) {
|
||||
aFilePickerShownCallback.done(Ci.nsIFilePicker.returnCancel);
|
||||
} else {
|
||||
this._resolveFiles(result.files, aFilePickerShownCallback);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async _resolveFiles(aFiles, aCallback) {
|
||||
const fileData = [];
|
||||
|
||||
try {
|
||||
for (const file of aFiles) {
|
||||
const domFile = await this._getDOMFile(file);
|
||||
fileData.push({
|
||||
file,
|
||||
domFile,
|
||||
});
|
||||
}
|
||||
} catch (ex) {
|
||||
warn`Error resolving files from file picker: ${ex}`;
|
||||
aCallback.done(Ci.nsIFilePicker.returnCancel);
|
||||
return;
|
||||
}
|
||||
|
||||
this._fileData = fileData;
|
||||
aCallback.done(Ci.nsIFilePicker.returnOK);
|
||||
}
|
||||
|
||||
get file() {
|
||||
if (!this._fileData) {
|
||||
throw Components.Exception("", Cr.NS_ERROR_NOT_AVAILABLE);
|
||||
}
|
||||
const fileData = this._fileData[0];
|
||||
if (!fileData) {
|
||||
return null;
|
||||
}
|
||||
return new FileUtils.File(fileData.file);
|
||||
}
|
||||
|
||||
get fileURL() {
|
||||
return Services.io.newFileURI(this.file);
|
||||
}
|
||||
|
||||
*_getEnumerator(aDOMFile) {
|
||||
if (!this._fileData) {
|
||||
throw Components.Exception("", Cr.NS_ERROR_NOT_AVAILABLE);
|
||||
}
|
||||
|
||||
for (const fileData of this._fileData) {
|
||||
if (aDOMFile) {
|
||||
yield fileData.domFile;
|
||||
}
|
||||
yield new FileUtils.File(fileData.file);
|
||||
}
|
||||
}
|
||||
|
||||
get files() {
|
||||
return this._getEnumerator(/* aDOMFile */ false);
|
||||
}
|
||||
|
||||
_getDOMFile(aPath) {
|
||||
if (this._prompt.domWin) {
|
||||
return this._prompt.domWin.File.createFromFileName(aPath);
|
||||
}
|
||||
return File.createFromFileName(aPath);
|
||||
}
|
||||
|
||||
get domFileOrDirectory() {
|
||||
if (!this._fileData) {
|
||||
throw Components.Exception("", Cr.NS_ERROR_NOT_AVAILABLE);
|
||||
}
|
||||
return this._fileData[0] ? this._fileData[0].domFile : null;
|
||||
}
|
||||
|
||||
get domFileOrDirectoryEnumerator() {
|
||||
return this._getEnumerator(/* aDOMFile */ true);
|
||||
}
|
||||
|
||||
get defaultString() {
|
||||
return "";
|
||||
}
|
||||
|
||||
set defaultString(aValue) {}
|
||||
|
||||
get defaultExtension() {
|
||||
return "";
|
||||
}
|
||||
|
||||
set defaultExtension(aValue) {}
|
||||
|
||||
get filterIndex() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
set filterIndex(aValue) {}
|
||||
|
||||
get displayDirectory() {
|
||||
return null;
|
||||
}
|
||||
|
||||
set displayDirectory(aValue) {}
|
||||
|
||||
get displaySpecialDirectory() {
|
||||
return "";
|
||||
}
|
||||
|
||||
set displaySpecialDirectory(aValue) {}
|
||||
|
||||
get addToRecentDocs() {
|
||||
return false;
|
||||
}
|
||||
|
||||
set addToRecentDocs(aValue) {}
|
||||
|
||||
get okButtonLabel() {
|
||||
return "";
|
||||
}
|
||||
|
||||
set okButtonLabel(aValue) {}
|
||||
|
||||
get capture() {
|
||||
return this._capture;
|
||||
}
|
||||
|
||||
set capture(aValue) {
|
||||
this._capture = aValue;
|
||||
}
|
||||
}
|
||||
|
||||
FilePickerDelegate.prototype.classID = Components.ID(
|
||||
"{e4565e36-f101-4bf5-950b-4be0887785a9}"
|
||||
);
|
||||
FilePickerDelegate.prototype.QueryInterface = ChromeUtils.generateQI([
|
||||
Ci.nsIFilePicker,
|
||||
]);
|
||||
|
||||
class ColorPickerDelegate {
|
||||
init(aParent, aTitle, aInitialColor) {
|
||||
this._prompt = new GeckoViewPrompter(aParent);
|
||||
this._msg = {
|
||||
type: "color",
|
||||
title: aTitle,
|
||||
value: aInitialColor,
|
||||
};
|
||||
}
|
||||
|
||||
open(aColorPickerShownCallback) {
|
||||
this._prompt.asyncShowPrompt(this._msg, result => {
|
||||
// OK: result
|
||||
// Cancel: !result
|
||||
aColorPickerShownCallback.done((result && result.color) || "");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ColorPickerDelegate.prototype.classID = Components.ID(
|
||||
"{aa0dd6fc-73dd-4621-8385-c0b377e02cee}"
|
||||
);
|
||||
ColorPickerDelegate.prototype.QueryInterface = ChromeUtils.generateQI([
|
||||
Ci.nsIColorPicker,
|
||||
]);
|
||||
|
||||
class ShareDelegate {
|
||||
init(aParent) {
|
||||
this._openerWindow = aParent;
|
||||
}
|
||||
|
||||
get openerWindow() {
|
||||
return this._openerWindow;
|
||||
}
|
||||
|
||||
async share(aTitle, aText, aUri) {
|
||||
const ABORT = 2;
|
||||
const FAILURE = 1;
|
||||
const SUCCESS = 0;
|
||||
|
||||
const msg = {
|
||||
type: "share",
|
||||
title: aTitle,
|
||||
text: aText,
|
||||
uri: aUri ? aUri.displaySpec : null,
|
||||
};
|
||||
const prompt = new GeckoViewPrompter(this._openerWindow);
|
||||
const result = await new Promise(resolve => {
|
||||
prompt.asyncShowPrompt(msg, resolve);
|
||||
});
|
||||
|
||||
if (!result) {
|
||||
// A null result is treated as a dismissal in GeckoViewPrompter.
|
||||
throw new DOMException(
|
||||
domBundle.GetStringFromName("WebShareAPI_Aborted"),
|
||||
"AbortError"
|
||||
);
|
||||
}
|
||||
|
||||
const res = result && result.response;
|
||||
switch (res) {
|
||||
case FAILURE:
|
||||
throw new DOMException(
|
||||
domBundle.GetStringFromName("WebShareAPI_Failed"),
|
||||
"DataError"
|
||||
);
|
||||
case ABORT: // Handle aborted attempt and invalid responses the same.
|
||||
throw new DOMException(
|
||||
domBundle.GetStringFromName("WebShareAPI_Aborted"),
|
||||
"AbortError"
|
||||
);
|
||||
case SUCCESS:
|
||||
return;
|
||||
default:
|
||||
throw new DOMException("Unknown error.", "UnknownError");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ShareDelegate.prototype.classID = Components.ID(
|
||||
"{1201d357-8417-4926-a694-e6408fbedcf8}"
|
||||
);
|
||||
ShareDelegate.prototype.QueryInterface = ChromeUtils.generateQI([
|
||||
Ci.nsISharePicker,
|
||||
]);
|
||||
|
||||
// Sync with LoginSaveOption.Hint in Autocomplete.java.
|
||||
const LoginStorageHint = {
|
||||
NONE: 0,
|
||||
GENERATED: 1 << 0,
|
||||
LOW_CONFIDENCE: 1 << 1,
|
||||
};
|
||||
|
||||
class LoginStorageDelegate {
|
||||
_createMessage({ dismissed, autoSavedLoginGuid }, aLogins) {
|
||||
let hint = LoginStorageHint.NONE;
|
||||
if (dismissed) {
|
||||
hint |= LoginStorageHint.LOW_CONFIDENCE;
|
||||
}
|
||||
if (autoSavedLoginGuid) {
|
||||
hint |= LoginStorageHint.GENERATED;
|
||||
}
|
||||
return {
|
||||
// Sync with GeckoSession.handlePromptEvent.
|
||||
type: "Autocomplete:Save:Login",
|
||||
hint,
|
||||
logins: aLogins,
|
||||
};
|
||||
}
|
||||
|
||||
promptToSavePassword(
|
||||
aBrowser,
|
||||
aLogin,
|
||||
dismissed = false,
|
||||
notifySaved = false
|
||||
) {
|
||||
const prompt = new GeckoViewPrompter(aBrowser.ownerGlobal);
|
||||
prompt.asyncShowPrompt(
|
||||
this._createMessage({ dismissed }, [LoginEntry.fromLoginInfo(aLogin)]),
|
||||
result => {
|
||||
const selectedLogin = result?.selection?.value;
|
||||
|
||||
if (!selectedLogin) {
|
||||
return;
|
||||
}
|
||||
|
||||
const loginInfo = LoginEntry.parse(selectedLogin).toLoginInfo();
|
||||
Services.obs.notifyObservers(loginInfo, "passwordmgr-prompt-save");
|
||||
|
||||
GeckoViewAutocomplete.onLoginSave(selectedLogin);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
promptToChangePassword(
|
||||
aBrowser,
|
||||
aOldLogin,
|
||||
aNewLogin,
|
||||
dismissed = false,
|
||||
notifySaved = false,
|
||||
autoSavedLoginGuid = ""
|
||||
) {
|
||||
const newLogin = LoginEntry.fromLoginInfo(aOldLogin || aNewLogin);
|
||||
const oldGuid = (aOldLogin && newLogin.guid) || null;
|
||||
newLogin.origin = aNewLogin.origin;
|
||||
newLogin.formActionOrigin = aNewLogin.formActionOrigin;
|
||||
newLogin.password = aNewLogin.password;
|
||||
newLogin.username = aNewLogin.username;
|
||||
|
||||
const prompt = new GeckoViewPrompter(aBrowser.ownerGlobal);
|
||||
prompt.asyncShowPrompt(
|
||||
this._createMessage({ dismissed, autoSavedLoginGuid }, [newLogin]),
|
||||
result => {
|
||||
const selectedLogin = result?.selection?.value;
|
||||
|
||||
if (!selectedLogin) {
|
||||
return;
|
||||
}
|
||||
|
||||
GeckoViewAutocomplete.onLoginSave(selectedLogin);
|
||||
|
||||
const loginInfo = LoginEntry.parse(selectedLogin).toLoginInfo();
|
||||
Services.obs.notifyObservers(
|
||||
loginInfo,
|
||||
"passwordmgr-prompt-change",
|
||||
oldGuid
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
promptToChangePasswordWithUsernames(aBrowser, aLogins, aNewLogin) {
|
||||
this.promptToChangePassword(aBrowser, null /* oldLogin */, aNewLogin);
|
||||
}
|
||||
}
|
||||
|
||||
LoginStorageDelegate.prototype.classID = Components.ID(
|
||||
"{3d765750-1c3d-11ea-aaef-0800200c9a66}"
|
||||
);
|
||||
LoginStorageDelegate.prototype.QueryInterface = ChromeUtils.generateQI([
|
||||
Ci.nsILoginManagerPrompter,
|
||||
]);
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = ["LoginStorageDelegate"];
|
||||
|
||||
const { GeckoViewUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/GeckoViewUtils.jsm"
|
||||
);
|
||||
|
||||
const { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
GeckoViewAutocomplete: "resource://gre/modules/GeckoViewAutocomplete.jsm",
|
||||
GeckoViewPrompter: "resource://gre/modules/GeckoViewPrompter.jsm",
|
||||
LoginEntry: "resource://gre/modules/GeckoViewAutocomplete.jsm",
|
||||
Services: "resource://gre/modules/Services.jsm",
|
||||
});
|
||||
|
||||
const { debug, warn } = GeckoViewUtils.initLogging("LoginStorageDelegate"); // eslint-disable-line no-unused-vars
|
||||
|
||||
// Sync with LoginSaveOption.Hint in Autocomplete.java.
|
||||
const LoginStorageHint = {
|
||||
NONE: 0,
|
||||
GENERATED: 1 << 0,
|
||||
LOW_CONFIDENCE: 1 << 1,
|
||||
};
|
||||
|
||||
class LoginStorageDelegate {
|
||||
_createMessage({ dismissed, autoSavedLoginGuid }, aLogins) {
|
||||
let hint = LoginStorageHint.NONE;
|
||||
if (dismissed) {
|
||||
hint |= LoginStorageHint.LOW_CONFIDENCE;
|
||||
}
|
||||
if (autoSavedLoginGuid) {
|
||||
hint |= LoginStorageHint.GENERATED;
|
||||
}
|
||||
return {
|
||||
// Sync with GeckoSession.handlePromptEvent.
|
||||
type: "Autocomplete:Save:Login",
|
||||
hint,
|
||||
logins: aLogins,
|
||||
};
|
||||
}
|
||||
|
||||
promptToSavePassword(
|
||||
aBrowser,
|
||||
aLogin,
|
||||
dismissed = false,
|
||||
notifySaved = false
|
||||
) {
|
||||
const prompt = new GeckoViewPrompter(aBrowser.ownerGlobal);
|
||||
prompt.asyncShowPrompt(
|
||||
this._createMessage({ dismissed }, [LoginEntry.fromLoginInfo(aLogin)]),
|
||||
result => {
|
||||
const selectedLogin = result?.selection?.value;
|
||||
|
||||
if (!selectedLogin) {
|
||||
return;
|
||||
}
|
||||
|
||||
const loginInfo = LoginEntry.parse(selectedLogin).toLoginInfo();
|
||||
Services.obs.notifyObservers(loginInfo, "passwordmgr-prompt-save");
|
||||
|
||||
GeckoViewAutocomplete.onLoginSave(selectedLogin);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
promptToChangePassword(
|
||||
aBrowser,
|
||||
aOldLogin,
|
||||
aNewLogin,
|
||||
dismissed = false,
|
||||
notifySaved = false,
|
||||
autoSavedLoginGuid = ""
|
||||
) {
|
||||
const newLogin = LoginEntry.fromLoginInfo(aOldLogin || aNewLogin);
|
||||
const oldGuid = (aOldLogin && newLogin.guid) || null;
|
||||
newLogin.origin = aNewLogin.origin;
|
||||
newLogin.formActionOrigin = aNewLogin.formActionOrigin;
|
||||
newLogin.password = aNewLogin.password;
|
||||
newLogin.username = aNewLogin.username;
|
||||
|
||||
const prompt = new GeckoViewPrompter(aBrowser.ownerGlobal);
|
||||
prompt.asyncShowPrompt(
|
||||
this._createMessage({ dismissed, autoSavedLoginGuid }, [newLogin]),
|
||||
result => {
|
||||
const selectedLogin = result?.selection?.value;
|
||||
|
||||
if (!selectedLogin) {
|
||||
return;
|
||||
}
|
||||
|
||||
GeckoViewAutocomplete.onLoginSave(selectedLogin);
|
||||
|
||||
const loginInfo = LoginEntry.parse(selectedLogin).toLoginInfo();
|
||||
Services.obs.notifyObservers(
|
||||
loginInfo,
|
||||
"passwordmgr-prompt-change",
|
||||
oldGuid
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
promptToChangePasswordWithUsernames(aBrowser, aLogins, aNewLogin) {
|
||||
this.promptToChangePassword(aBrowser, null /* oldLogin */, aNewLogin);
|
||||
}
|
||||
}
|
||||
|
||||
LoginStorageDelegate.prototype.classID = Components.ID(
|
||||
"{3d765750-1c3d-11ea-aaef-0800200c9a66}"
|
||||
);
|
||||
LoginStorageDelegate.prototype.QueryInterface = ChromeUtils.generateQI([
|
||||
Ci.nsILoginManagerPrompter,
|
||||
]);
|
|
@ -0,0 +1,85 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = ["ShareDelegate"];
|
||||
|
||||
const { GeckoViewUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/GeckoViewUtils.jsm"
|
||||
);
|
||||
|
||||
const { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
GeckoViewPrompter: "resource://gre/modules/GeckoViewPrompter.jsm",
|
||||
Services: "resource://gre/modules/Services.jsm",
|
||||
});
|
||||
|
||||
const domBundle = Services.strings.createBundle(
|
||||
"chrome://global/locale/dom/dom.properties"
|
||||
);
|
||||
|
||||
const { debug, warn } = GeckoViewUtils.initLogging("ShareDelegate"); // eslint-disable-line no-unused-vars
|
||||
|
||||
class ShareDelegate {
|
||||
init(aParent) {
|
||||
this._openerWindow = aParent;
|
||||
}
|
||||
|
||||
get openerWindow() {
|
||||
return this._openerWindow;
|
||||
}
|
||||
|
||||
async share(aTitle, aText, aUri) {
|
||||
const ABORT = 2;
|
||||
const FAILURE = 1;
|
||||
const SUCCESS = 0;
|
||||
|
||||
const msg = {
|
||||
type: "share",
|
||||
title: aTitle,
|
||||
text: aText,
|
||||
uri: aUri ? aUri.displaySpec : null,
|
||||
};
|
||||
const prompt = new GeckoViewPrompter(this._openerWindow);
|
||||
const result = await new Promise(resolve => {
|
||||
prompt.asyncShowPrompt(msg, resolve);
|
||||
});
|
||||
|
||||
if (!result) {
|
||||
// A null result is treated as a dismissal in GeckoViewPrompter.
|
||||
throw new DOMException(
|
||||
domBundle.GetStringFromName("WebShareAPI_Aborted"),
|
||||
"AbortError"
|
||||
);
|
||||
}
|
||||
|
||||
const res = result && result.response;
|
||||
switch (res) {
|
||||
case FAILURE:
|
||||
throw new DOMException(
|
||||
domBundle.GetStringFromName("WebShareAPI_Failed"),
|
||||
"DataError"
|
||||
);
|
||||
case ABORT: // Handle aborted attempt and invalid responses the same.
|
||||
throw new DOMException(
|
||||
domBundle.GetStringFromName("WebShareAPI_Aborted"),
|
||||
"AbortError"
|
||||
);
|
||||
case SUCCESS:
|
||||
return;
|
||||
default:
|
||||
throw new DOMException("Unknown error.", "UnknownError");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ShareDelegate.prototype.classID = Components.ID(
|
||||
"{1201d357-8417-4926-a694-e6408fbedcf8}"
|
||||
);
|
||||
ShareDelegate.prototype.QueryInterface = ChromeUtils.generateQI([
|
||||
Ci.nsISharePicker,
|
||||
]);
|
|
@ -23,28 +23,28 @@ Classes = [
|
|||
{
|
||||
'cid': '{aa0dd6fc-73dd-4621-8385-c0b377e02cee}',
|
||||
'contract_ids': ['@mozilla.org/colorpicker;1'],
|
||||
'jsm': 'resource://gre/modules/GeckoViewPrompt.jsm',
|
||||
'jsm': 'resource://gre/modules/ColorPickerDelegate.jsm',
|
||||
'constructor': 'ColorPickerDelegate',
|
||||
'processes': ProcessSelector.MAIN_PROCESS_ONLY,
|
||||
},
|
||||
{
|
||||
'cid': '{e4565e36-f101-4bf5-950b-4be0887785a9}',
|
||||
'contract_ids': ['@mozilla.org/filepicker;1'],
|
||||
'jsm': 'resource://gre/modules/GeckoViewPrompt.jsm',
|
||||
'jsm': 'resource://gre/modules/FilePickerDelegate.jsm',
|
||||
'constructor': 'FilePickerDelegate',
|
||||
'processes': ProcessSelector.MAIN_PROCESS_ONLY,
|
||||
},
|
||||
{
|
||||
'cid': '{1201d357-8417-4926-a694-e6408fbedcf8}',
|
||||
'contract_ids': ['@mozilla.org/sharepicker;1'],
|
||||
'jsm': 'resource://gre/modules/GeckoViewPrompt.jsm',
|
||||
'jsm': 'resource://gre/modules/ShareDelegate.jsm',
|
||||
'constructor': 'ShareDelegate',
|
||||
'processes': ProcessSelector.MAIN_PROCESS_ONLY,
|
||||
},
|
||||
{
|
||||
'cid': '{3d765750-1c3d-11ea-aaef-0800200c9a66}',
|
||||
'contract_ids': ['@mozilla.org/login-manager/prompter;1'],
|
||||
'jsm': 'resource://gre/modules/GeckoViewPrompt.jsm',
|
||||
'jsm': 'resource://gre/modules/LoginStorageDelegate.jsm',
|
||||
'constructor': 'LoginStorageDelegate',
|
||||
'processes': ProcessSelector.MAIN_PROCESS_ONLY,
|
||||
},
|
||||
|
|
|
@ -28,9 +28,13 @@ EXTRA_COMPONENTS += [
|
|||
]
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'ColorPickerDelegate.jsm',
|
||||
'FilePickerDelegate.jsm',
|
||||
'GeckoViewPrompt.jsm',
|
||||
'GeckoViewPrompter.jsm',
|
||||
'LoginStorageDelegate.jsm',
|
||||
'PromptCollection.jsm',
|
||||
'ShareDelegate.jsm',
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
|
Загрузка…
Ссылка в новой задаче