merge autoland to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2016-12-02 09:22:46 +01:00
commit c5e97a3963
90 changed files with 567 additions and 620 deletions

View File

@ -42,8 +42,18 @@ add_task(function* setup() {
let oldInternal = SyncedTabs._internal;
SyncedTabs._internal = mockedInternal;
// This test hacks some observer states to simulate a user being signed
// in to Sync - restore them when the test completes.
let initialObserverStates = {};
for (let id of ["sync-reauth-state", "sync-setup-state", "sync-syncnow-state"]) {
initialObserverStates[id] = document.getElementById(id).hidden;
}
registerCleanupFunction(() => {
SyncedTabs._internal = oldInternal;
for (let [id, initial] of Object.entries(initialObserverStates)) {
document.getElementById(id).hidden = initial;
}
});
});

View File

@ -85,6 +85,7 @@ def rust_triple_alias(host_or_target):
@imports(_from='mozbuild.configure.util', _import='LineIO')
@imports(_from='mozbuild.shellutil', _import='quote')
@imports(_from='tempfile', _import='mkstemp')
@imports(_from='textwrap', _import='dedent')
def rust_target(rustc, host_or_target):
# Rust's --target options are similar to, but not exactly the same
# as, the autoconf-derived targets we use. An example would be that
@ -155,7 +156,13 @@ def rust_triple_alias(host_or_target):
in_path,
]
def failed():
die('Cannot compile for {} with {}'.format(host_or_target.alias, rustc))
die(dedent('''\
Cannot compile for {} with {}
The target may be unsupported, or you may not have
a rust std library for that target installed. Try:
rustup target add {}
'''.format(host_or_target.alias, rustc, rustc_target)))
check_cmd_output(*cmd, onerror=failed)
if not os.path.exists(out_path) or os.path.getsize(out_path) == 0:
failed()

View File

@ -318,14 +318,6 @@ DevTools.prototype = {
theme.id == currTheme) {
Services.prefs.setCharPref("devtools.theme", "light");
let data = {
pref: "devtools.theme",
newValue: "light",
oldValue: currTheme
};
this.emit("pref-changed", data);
this.emit("theme-unregistered", theme);
}

View File

@ -12,6 +12,7 @@
var doc = null, toolbox = null, panelWin = null, modifiedPrefs = [];
const {LocalizationHelper} = require("devtools/shared/l10n");
const L10N = new LocalizationHelper("devtools/client/locales/toolbox.properties");
const {PrefObserver} = require("devtools/client/shared/prefs");
add_task(function* () {
const URL = "data:text/html;charset=utf8,test for dynamically registering " +
@ -151,14 +152,13 @@ function* testSelect(select) {
continue;
}
let observer = new PrefObserver("devtools.");
let deferred = defer();
gDevTools.once("pref-changed", (event, data) => {
if (data.pref == pref) {
ok(true, "Correct pref was changed");
is(GetPref(pref), option.value, "Preference been switched for " + pref);
} else {
ok(false, "Pref " + pref + " was not changed correctly");
}
let changeSeen = false;
observer.once(pref, () => {
changeSeen = true;
is(GetPref(pref), option.value, "Preference been switched for " + pref);
deferred.resolve();
});
@ -167,21 +167,22 @@ function* testSelect(select) {
select.dispatchEvent(changeEvent);
yield deferred.promise;
ok(changeSeen, "Correct pref was changed");
observer.destroy();
}
}
function* testMouseClick(node, prefValue) {
let deferred = defer();
let observer = new PrefObserver("devtools.");
let pref = node.getAttribute("data-pref");
gDevTools.once("pref-changed", (event, data) => {
if (data.pref == pref) {
ok(true, "Correct pref was changed");
is(data.oldValue, prefValue, "Previous value is correct for " + pref);
is(data.newValue, !prefValue, "New value is correct for " + pref);
} else {
ok(false, "Pref " + pref + " was not changed correctly");
}
let changeSeen = false;
observer.once(pref, () => {
changeSeen = true;
is(GetPref(pref), !prefValue, "New value is correct for " + pref);
deferred.resolve();
});
@ -195,6 +196,9 @@ function* testMouseClick(node, prefValue) {
});
yield deferred.promise;
ok(changeSeen, "Correct pref was changed");
observer.destroy();
}
function* testToggleTools() {

View File

@ -275,7 +275,7 @@ OptionsPanel.prototype = {
inputRadio.setAttribute("value", theme.id);
inputRadio.setAttribute("name", "devtools-theme-item");
inputRadio.addEventListener("change", function (e) {
setPrefAndEmit(themeBox.getAttribute("data-pref"),
SetPref(themeBox.getAttribute("data-pref"),
e.target.value);
});
@ -305,7 +305,7 @@ OptionsPanel.prototype = {
}
prefCheckbox.addEventListener("change", function (e) {
let checkbox = e.target;
setPrefAndEmit(checkbox.getAttribute("data-pref"), checkbox.checked);
SetPref(checkbox.getAttribute("data-pref"), checkbox.checked);
});
}
// Themes radio inputs are handled in setupThemeList
@ -320,7 +320,7 @@ OptionsPanel.prototype = {
}
radioInput.addEventListener("change", function (e) {
setPrefAndEmit(radioGroup.getAttribute("data-pref"),
SetPref(radioGroup.getAttribute("data-pref"),
e.target.value);
});
}
@ -340,7 +340,7 @@ OptionsPanel.prototype = {
prefSelect.addEventListener("change", function (e) {
let select = e.target;
setPrefAndEmit(select.getAttribute("data-pref"),
SetPref(select.getAttribute("data-pref"),
select.options[select.selectedIndex].value);
});
}
@ -422,17 +422,3 @@ OptionsPanel.prototype = {
return this.destroyPromise;
}
};
/* Set a pref and emit the pref-changed event if needed. */
function setPrefAndEmit(prefName, newValue) {
let data = {
pref: prefName,
newValue: newValue
};
data.oldValue = GetPref(data.pref);
SetPref(data.pref, data.newValue);
if (data.newValue != data.oldValue) {
gDevTools.emit("pref-changed", data);
}
}

View File

@ -113,7 +113,9 @@ function Toolbox(target, selectedTool, hostType, contentWindow, frameId) {
this.highlighterUtils = getHighlighterUtils(this);
this._highlighterReady = this._highlighterReady.bind(this);
this._highlighterHidden = this._highlighterHidden.bind(this);
this._prefChanged = this._prefChanged.bind(this);
this._applyCacheSettings = this._applyCacheSettings.bind(this);
this._applyServiceWorkersTestingSettings =
this._applyServiceWorkersTestingSettings.bind(this);
this._saveSplitConsoleHeight = this._saveSplitConsoleHeight.bind(this);
this._onFocus = this._onFocus.bind(this);
this._onBrowserMessage = this._onBrowserMessage.bind(this);
@ -367,7 +369,10 @@ Toolbox.prototype = {
this.closeButton = this.doc.getElementById("toolbox-close");
this.closeButton.addEventListener("click", this.destroy, true);
gDevTools.on("pref-changed", this._prefChanged);
Services.prefs.addObserver("devtools.cache.disabled", this._applyCacheSettings,
false);
Services.prefs.addObserver("devtools.serviceWorkers.testing.enabled",
this._applyServiceWorkersTestingSettings, false);
let framesMenu = this.doc.getElementById("command-button-frames");
framesMenu.addEventListener("click", this.showFramesMenu, false);
@ -485,29 +490,6 @@ Toolbox.prototype = {
this._telemetry.log(HOST_HISTOGRAM, this._getTelemetryHostId());
},
/**
* Because our panels are lazy loaded this is a good place to watch for
* "pref-changed" events.
* @param {String} event
* The event type, "pref-changed".
* @param {Object} data
* {
* newValue: The new value
* oldValue: The old value
* pref: The name of the preference that has changed
* }
*/
_prefChanged: function (event, data) {
switch (data.pref) {
case "devtools.cache.disabled":
this._applyCacheSettings();
break;
case "devtools.serviceWorkers.testing.enabled":
this._applyServiceWorkersTestingSettings();
break;
}
},
_buildOptions: function () {
let selectOptions = (name, event) => {
// Flip back to the last used panel if we are already
@ -2214,7 +2196,9 @@ Toolbox.prototype = {
gDevTools.off("tool-registered", this._toolRegistered);
gDevTools.off("tool-unregistered", this._toolUnregistered);
gDevTools.off("pref-changed", this._prefChanged);
Services.prefs.removeObserver("devtools.cache.disabled", this._applyCacheSettings);
Services.prefs.removeObserver("devtools.serviceWorkers.testing.enabled",
this._applyServiceWorkersTestingSettings);
this._lastFocusedElement = null;
if (this._sourceMapService) {

View File

@ -13,7 +13,7 @@ const promise = require("promise");
const defer = require("devtools/shared/defer");
const Services = require("Services");
const {OutputParser} = require("devtools/client/shared/output-parser");
const {PrefObserver, PREF_ORIG_SOURCES} = require("devtools/client/styleeditor/utils");
const {PrefObserver} = require("devtools/client/shared/prefs");
const {createChild} = require("devtools/client/inspector/shared/utils");
const {gDevTools} = require("devtools/client/framework/devtools");
const {getCssProperties} = require("devtools/shared/fronts/css-properties");
@ -33,6 +33,8 @@ const STYLE_INSPECTOR_PROPERTIES = "devtools/shared/locales/styleinspector.prope
const {LocalizationHelper} = require("devtools/shared/l10n");
const STYLE_INSPECTOR_L10N = new LocalizationHelper(STYLE_INSPECTOR_PROPERTIES);
const PREF_ORIG_SOURCES = "devtools.styleeditor.source-maps-enabled";
const FILTER_CHANGED_TIMEOUT = 150;
const HTML_NS = "http://www.w3.org/1999/xhtml";
@ -196,14 +198,13 @@ function CssComputedView(inspector, document, pageStyle) {
// No results text.
this.noResults = this.styleDocument.getElementById("computedview-no-results");
// Refresh panel when color unit changed.
// Refresh panel when color unit changed or pref for showing
// original sources changes.
this._handlePrefChange = this._handlePrefChange.bind(this);
gDevTools.on("pref-changed", this._handlePrefChange);
// Refresh panel when pref for showing original sources changes
this._onSourcePrefChanged = this._onSourcePrefChanged.bind(this);
this._prefObserver = new PrefObserver("devtools.");
this._prefObserver.on(PREF_ORIG_SOURCES, this._onSourcePrefChanged);
this._prefObserver.on("devtools.defaultColorUnit", this._handlePrefChange);
// The element that we're inspecting, and the document that it comes from.
this._viewedElement = null;
@ -260,8 +261,7 @@ CssComputedView.prototype = {
},
_handlePrefChange: function (event, data) {
if (this._computed && (data.pref === "devtools.defaultColorUnit" ||
data.pref === PREF_ORIG_SOURCES)) {
if (this._computed) {
this.refreshPanel();
}
},
@ -598,6 +598,7 @@ CssComputedView.prototype = {
},
_onSourcePrefChanged: function () {
this._handlePrefChange();
for (let propView of this.propertyViews) {
propView.updateSourceLinks();
}
@ -732,9 +733,8 @@ CssComputedView.prototype = {
this._viewedElement = null;
this._outputParser = null;
gDevTools.off("pref-changed", this._handlePrefChange);
this._prefObserver.off(PREF_ORIG_SOURCES, this._onSourcePrefChanged);
this._prefObserver.off("devtools.defaultColorUnit", this._handlePrefChange);
this._prefObserver.destroy();
// Cancel tree construction

View File

@ -19,7 +19,7 @@ const {KeyShortcuts} = require("devtools/client/shared/key-shortcuts");
const {scrollIntoViewIfNeeded} = require("devtools/client/shared/scroll");
const {UndoStack} = require("devtools/client/shared/undo");
const {HTMLTooltip} = require("devtools/client/shared/widgets/tooltip/HTMLTooltip");
const {PrefObserver} = require("devtools/client/styleeditor/utils");
const {PrefObserver} = require("devtools/client/shared/prefs");
const HTMLEditor = require("devtools/client/inspector/markup/views/html-editor");
const MarkupElementContainer = require("devtools/client/inspector/markup/views/element-container");
const MarkupReadOnlyContainer = require("devtools/client/inspector/markup/views/read-only-container");

View File

@ -13,7 +13,7 @@ const {Tools} = require("devtools/client/definitions");
const {l10n} = require("devtools/shared/inspector/css-logic");
const {ELEMENT_STYLE} = require("devtools/shared/specs/styles");
const {OutputParser} = require("devtools/client/shared/output-parser");
const {PrefObserver, PREF_ORIG_SOURCES} = require("devtools/client/styleeditor/utils");
const {PrefObserver} = require("devtools/client/shared/prefs");
const {ElementStyle} = require("devtools/client/inspector/rules/models/element-style");
const {Rule} = require("devtools/client/inspector/rules/models/rule");
const {RuleEditor} = require("devtools/client/inspector/rules/views/rule-editor");
@ -40,6 +40,7 @@ const PREF_DEFAULT_COLOR_UNIT = "devtools.defaultColorUnit";
const PREF_ENABLE_MDN_DOCS_TOOLTIP =
"devtools.inspector.mdnDocsTooltip.enabled";
const FILTER_CHANGED_TIMEOUT = 150;
const PREF_ORIG_SOURCES = "devtools.styleeditor.source-maps-enabled";
// This is used to parse user input when filtering.
const FILTER_PROP_RE = /\s*([^:\s]*)\s*:\s*(.*?)\s*;?$/;

View File

@ -14,7 +14,7 @@
"use strict";
const { PrefObserver } = require("devtools/client/styleeditor/utils");
const { PrefObserver } = require("devtools/client/shared/prefs");
const PREF_ENABLE_MDN_DOCS_TOOLTIP =
"devtools.inspector.mdnDocsTooltip.enabled";
const PROPERTY_NAME_CLASS = "ruleview-propertyname";

View File

@ -8,7 +8,7 @@
// it is preffed on.
var PREF_UA_STYLES = "devtools.inspector.showUserAgentStyles";
const { PrefObserver } = require("devtools/client/styleeditor/utils");
const { PrefObserver } = require("devtools/client/shared/prefs");
const TEST_URI = URL_ROOT + "doc_author-sheet.html";

View File

@ -6,7 +6,6 @@
const {l10n} = require("devtools/shared/inspector/css-logic");
const {ELEMENT_STYLE} = require("devtools/shared/specs/styles");
const {PREF_ORIG_SOURCES} = require("devtools/client/styleeditor/utils");
const {Rule} = require("devtools/client/inspector/rules/models/rule");
const {InplaceEditor, editableField, editableItem} =
require("devtools/client/shared/inplace-editor");
@ -33,6 +32,8 @@ const STYLE_INSPECTOR_PROPERTIES = "devtools/shared/locales/styleinspector.prope
const {LocalizationHelper} = require("devtools/shared/l10n");
const STYLE_INSPECTOR_L10N = new LocalizationHelper(STYLE_INSPECTOR_PROPERTIES);
const PREF_ORIG_SOURCES = "devtools.styleeditor.source-maps-enabled";
/**
* RuleEditor is responsible for the following:
* Owns a Rule object and creates a list of TextPropertyEditors

View File

@ -6,7 +6,6 @@
"use strict";
const {PREF_ORIG_SOURCES} = require("devtools/client/styleeditor/utils");
const Services = require("Services");
const {Task} = require("devtools/shared/task");
@ -28,6 +27,7 @@ const STYLE_INSPECTOR_L10N = new LocalizationHelper(STYLE_INSPECTOR_PROPERTIES);
const PREF_ENABLE_MDN_DOCS_TOOLTIP =
"devtools.inspector.mdnDocsTooltip.enabled";
const PREF_ORIG_SOURCES = "devtools.styleeditor.source-maps-enabled";
/**
* Style inspector context menu

View File

@ -16,7 +16,7 @@ var { loader, require } = BrowserLoaderModule.BrowserLoader({
var { Task } = require("devtools/shared/task");
/* exported Heritage, ViewHelpers, WidgetMethods, setNamedTimeout, clearNamedTimeout */
var { Heritage, ViewHelpers, WidgetMethods, setNamedTimeout, clearNamedTimeout } = require("devtools/client/shared/widgets/view-helpers");
var { gDevTools } = require("devtools/client/framework/devtools");
var { PrefObserver } = require("devtools/client/shared/prefs");
// Events emitted by various objects in the panel.
var EVENTS = require("devtools/client/performance/events");
@ -143,7 +143,8 @@ var PerformanceController = {
RecordingsView.on(EVENTS.UI_RECORDING_SELECTED, this._onRecordingSelectFromView);
DetailsView.on(EVENTS.UI_DETAILS_VIEW_SELECTED, this._pipe);
gDevTools.on("pref-changed", this._onThemeChanged);
this._prefObserver = new PrefObserver("devtools.");
this._prefObserver.on("devtools.theme", this._onThemeChanged);
}),
/**
@ -163,7 +164,8 @@ var PerformanceController = {
RecordingsView.off(EVENTS.UI_RECORDING_SELECTED, this._onRecordingSelectFromView);
DetailsView.off(EVENTS.UI_DETAILS_VIEW_SELECTED, this._pipe);
gDevTools.off("pref-changed", this._onThemeChanged);
this._prefObserver.off("devtools.theme", this._onThemeChanged);
this._prefObserver.destroy();
},
/**
@ -402,14 +404,9 @@ var PerformanceController = {
/*
* Called when the developer tools theme changes.
*/
_onThemeChanged: function (_, data) {
// Right now, gDevTools only emits `pref-changed` for the theme,
// but this could change in the future.
if (data.pref !== "devtools.theme") {
return;
}
this.emit(EVENTS.THEME_CHANGED, data.newValue);
_onThemeChanged: function () {
let newValue = Services.prefs.getCharPref("devtools.theme");
this.emit(EVENTS.THEME_CHANGED, newValue);
},
/**

View File

@ -16,7 +16,7 @@ const { getToplevelWindow } = require("sdk/window/utils");
const { Task: { spawn } } = require("devtools/shared/task");
const e10s = require("../utils/e10s");
const audioCamera = new window.Audio("resource://devtools/client/themes/audio/shutter.wav");
const CAMERA_AUDIO_URL = "resource://devtools/client/themes/audio/shutter.wav";
const animationFrame = () => new Promise(resolve => {
window.requestAnimationFrame(resolve);
@ -54,7 +54,8 @@ function saveToFile(data, filename) {
}
function simulateCameraEffects(node) {
audioCamera.play();
let cameraAudio = new window.Audio(CAMERA_AUDIO_URL);
cameraAudio.play();
node.animate({ opacity: [ 0, 1 ] }, 500);
}

View File

@ -107,6 +107,17 @@ function swapToInnerBrowser({ tab, containerURL, getInnerBrowser }) {
tunnel = tunnelToInnerBrowser(tab.linkedBrowser, innerBrowser);
yield tunnel.start();
// Swapping browsers disconnects the find bar UI from the browser.
// If the find bar has been initialized, reconnect it.
if (gBrowser.isFindBarInitialized(tab)) {
let findBar = gBrowser.getFindBar(tab);
findBar.browser = tab.linkedBrowser;
if (!findBar.hidden) {
// Force the find bar to activate again, restoring the search string.
findBar.onFindCommand();
}
}
// Force the browser UI to match the new state of the tab and browser.
thawNavigationState(tab);
gBrowser.setTabTitle(tab);
@ -147,6 +158,18 @@ function swapToInnerBrowser({ tab, containerURL, getInnerBrowser }) {
// `swapBrowsersAndCloseOther`.
dispatchDevToolsBrowserSwap(contentBrowser, tab.linkedBrowser);
gBrowser.swapBrowsersAndCloseOther(tab, contentTab);
// Swapping browsers disconnects the find bar UI from the browser.
// If the find bar has been initialized, reconnect it.
if (gBrowser.isFindBarInitialized(tab)) {
let findBar = gBrowser.getFindBar(tab);
findBar.browser = tab.linkedBrowser;
if (!findBar.hidden) {
// Force the find bar to activate again, restoring the search string.
findBar.onFindCommand();
}
}
gBrowser = null;
// The focus manager seems to get a little dizzy after all this swapping. If a

View File

@ -23,6 +23,7 @@ function debug(msg) {
* list at /devtools/client/responsive.html/docs/browser-swap.md.
*/
const SWAPPED_BROWSER_STATE = [
"_remoteFinder",
"_securityUI",
"_documentURI",
"_documentContentType",

View File

@ -7,9 +7,9 @@
const HTML_NS = "http://www.w3.org/1999/xhtml";
const Services = require("Services");
const {gDevTools} = require("devtools/client/framework/devtools");
const {HTMLTooltip} = require("devtools/client/shared/widgets/tooltip/HTMLTooltip");
const EventEmitter = require("devtools/shared/event-emitter");
const {PrefObserver} = require("devtools/client/shared/prefs");
let itemIdCounter = 0;
/**
@ -47,7 +47,9 @@ function AutocompletePopup(toolboxDoc, options = {}) {
this.autoThemeEnabled = true;
// Setup theme change listener.
this._handleThemeChange = this._handleThemeChange.bind(this);
gDevTools.on("pref-changed", this._handleThemeChange);
this._prefObserver = new PrefObserver("devtools.");
this._prefObserver.on("devtools.theme", this._handleThemeChange);
this._currentTheme = theme;
}
// Create HTMLTooltip instance
@ -194,7 +196,8 @@ AutocompletePopup.prototype = {
this._list.removeEventListener("click", this.onClick, false);
if (this.autoThemeEnabled) {
gDevTools.off("pref-changed", this._handleThemeChange);
this._prefObserver.off("devtools.theme", this._handleThemeChange);
this._prefObserver.destroy();
}
this._list.remove();
@ -562,25 +565,17 @@ AutocompletePopup.prototype = {
/**
* Manages theme switching for the popup based on the devtools.theme pref.
*
* @private
*
* @param {String} event
* The name of the event. In this case, "pref-changed".
* @param {Object} data
* An object passed by the emitter of the event. In this case, the
* object consists of three properties:
* - pref {String} The name of the preference that was modified.
* - newValue {Object} The new value of the preference.
* - oldValue {Object} The old value of the preference.
*/
_handleThemeChange: function (event, data) {
if (data.pref === "devtools.theme") {
this._tooltip.panel.classList.toggle(data.oldValue + "-theme", false);
this._tooltip.panel.classList.toggle(data.newValue + "-theme", true);
this._list.classList.toggle(data.oldValue + "-theme", false);
this._list.classList.toggle(data.newValue + "-theme", true);
}
_handleThemeChange: function () {
const oldValue = this._currentTheme;
const newValue = Services.prefs.getCharPref("devtools.theme");
this._tooltip.panel.classList.toggle(oldValue + "-theme", false);
this._tooltip.panel.classList.toggle(newValue + "-theme", true);
this._list.classList.toggle(oldValue + "-theme", false);
this._list.classList.toggle(newValue + "-theme", true);
this._currentTheme = newValue;
},
/**

View File

@ -176,3 +176,31 @@ function makeObserver(self, cache, prefsRoot, prefsBlueprint) {
}
exports.PrefsHelper = PrefsHelper;
/**
* A PreferenceObserver observes a pref branch for pref changes.
* It emits an event for each preference change.
*/
function PrefObserver(branchName) {
this.branchName = branchName;
this.branch = Services.prefs.getBranch(branchName);
this.branch.addObserver("", this, false);
EventEmitter.decorate(this);
}
exports.PrefObserver = PrefObserver;
PrefObserver.prototype = {
observe: function (subject, topic, data) {
if (topic == "nsPref:changed") {
this.emit(this.branchName + data);
}
},
destroy: function () {
if (this.branch) {
this.branch.removeObserver("", this);
}
},
};

View File

@ -7,6 +7,7 @@
// Tests that theme utilities work
const {getColor, getTheme, setTheme} = require("devtools/client/shared/theme");
const {PrefObserver} = require("devtools/client/shared/prefs");
add_task(function* () {
testGetTheme();
@ -31,13 +32,14 @@ function testGetTheme() {
function testSetTheme() {
let originalTheme = getTheme();
gDevTools.once("pref-changed", (_, { pref, oldValue, newValue }) => {
let prefObserver = new PrefObserver("devtools.");
prefObserver.once("devtools.theme", pref => {
is(pref, "devtools.theme",
"The 'pref-changed' event triggered by setTheme has correct pref.");
is(oldValue, originalTheme,
"The 'pref-changed' event triggered by setTheme has correct oldValue.");
"A preference event triggered by setTheme has correct pref.");
let newValue = Services.prefs.getCharPref("devtools.theme");
is(newValue, "dark",
"The 'pref-changed' event triggered by setTheme has correct newValue.");
"A preference event triggered by setTheme comes after the value is set.");
});
setTheme("dark");
is(Services.prefs.getCharPref("devtools.theme"), "dark",
@ -52,6 +54,8 @@ function testSetTheme() {
is(Services.prefs.getCharPref("devtools.theme"), "unknown",
"setTheme() correctly sets an unknown theme.");
Services.prefs.setCharPref("devtools.theme", originalTheme);
prefObserver.destroy();
}
function testGetColor() {

View File

@ -10,7 +10,6 @@
*/
const Services = require("Services");
const { gDevTools } = require("devtools/client/framework/devtools");
const variableFileContents = require("raw!devtools/client/themes/variables.css");
@ -67,18 +66,9 @@ const getColor = exports.getColor = (type, theme) => {
};
/**
* Mimics selecting the theme selector in the toolbox;
* sets the preference and emits an event on gDevTools to trigger
* the themeing.
* Set the theme preference.
*/
const setTheme = exports.setTheme = (newTheme) => {
let oldTheme = getTheme();
Services.prefs.setCharPref("devtools.theme", newTheme);
gDevTools.emit("pref-changed", {
pref: "devtools.theme",
newValue: newTheme,
oldValue: oldTheme
});
};
/* eslint-enable */

View File

@ -51,9 +51,11 @@ version over:
* cp build/react-with-addons.js <gecko-dev>/devtools/client/shared/vendor/react.js
You also need to copy the ReactDOM package. It requires React, so
You also need to copy the ReactDOM and ReactDOMServer package. It requires React, so
right now we are just manually changing the path from `react` to
`devtools/client/shared/vendor/react`.
* cp build/react-dom.js <gecko-dev>/devtools/client/shared/vendor/react-dom.js
* (change `require('react')` at the top of the file to the right path)
* cp build/react-dom.js <gecko-dev>/devtools/client/shared/vendor/react-dom-server.js
* (change `require('react')` at the top of the file to the right path)

View File

@ -16,6 +16,7 @@ if CONFIG['DEBUG_JS_MODULES'] or CONFIG['MOZ_DEBUG']:
modules += ['react-dev.js']
modules += [
'react-dom-server.js',
'react-dom.js',
'react-proxy.js',
'react-redux.js',

View File

@ -0,0 +1,42 @@
/**
* ReactDOMServer v15.3.2
*
* Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
// Based off https://github.com/ForbesLindesay/umd/blob/master/template.js
;(function(f) {
// CommonJS
if (typeof exports === "object" && typeof module !== "undefined") {
module.exports = f(require('react'));
// RequireJS
} else if (typeof define === "function" && define.amd) {
define(['react'], f);
// <script>
} else {
var g;
if (typeof window !== "undefined") {
g = window;
} else if (typeof global !== "undefined") {
g = global;
} else if (typeof self !== "undefined") {
g = self;
} else {
// works providing we're not in "use strict";
// needed for Java 8 Nashorn
// see https://github.com/facebook/react/issues/3037
g = this;
}
g.ReactDOMServer = f(g.React);
}
})(function(React) {
return React.__SECRET_DOM_SERVER_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
});

View File

@ -32,7 +32,7 @@ const RE_JUMP_TO_LINE = /^(\d+):?(\d+)?/;
const Services = require("Services");
const promise = require("promise");
const events = require("devtools/shared/event-emitter");
const { PrefObserver } = require("devtools/client/styleeditor/utils");
const { PrefObserver } = require("devtools/client/shared/prefs");
const { getClientCssProperties } = require("devtools/shared/fronts/css-properties");
const {KeyShortcuts} = require("devtools/client/shared/key-shortcuts");

View File

@ -26,7 +26,7 @@ const {
const {SplitView} = require("resource://devtools/client/shared/SplitView.jsm");
const {StyleSheetEditor} = require("resource://devtools/client/styleeditor/StyleSheetEditor.jsm");
const {PluralForm} = require("devtools/shared/plural-form");
const {PrefObserver, PREF_ORIG_SOURCES} = require("devtools/client/styleeditor/utils");
const {PrefObserver} = require("devtools/client/shared/prefs");
const csscoverage = require("devtools/shared/fronts/csscoverage");
const {console} = require("resource://gre/modules/Console.jsm");
const promise = require("promise");
@ -41,6 +41,7 @@ const SELECTOR_HIGHLIGHTER_TYPE = "SelectorHighlighter";
const PREF_MEDIA_SIDEBAR = "devtools.styleeditor.showMediaSidebar";
const PREF_SIDEBAR_WIDTH = "devtools.styleeditor.mediaSidebarWidth";
const PREF_NAV_WIDTH = "devtools.styleeditor.navSidebarWidth";
const PREF_ORIG_SOURCES = "devtools.styleeditor.source-maps-enabled";
/**
* StyleEditorUI is controls and builds the UI of the Style Editor, including

View File

@ -12,5 +12,4 @@ DevToolsModules(
'StyleEditorUI.jsm',
'StyleEditorUtil.jsm',
'StyleSheetEditor.jsm',
'utils.js',
)

View File

@ -1,40 +0,0 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* 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";
const Services = require("Services");
const EventEmitter = require("devtools/shared/event-emitter");
exports.PREF_ORIG_SOURCES = "devtools.styleeditor.source-maps-enabled";
/**
* A PreferenceObserver observes a pref branch for pref changes.
* It emits an event for each preference change.
*/
function PrefObserver(branchName) {
this.branchName = branchName;
this.branch = Services.prefs.getBranch(branchName);
this.branch.addObserver("", this, false);
EventEmitter.decorate(this);
}
exports.PrefObserver = PrefObserver;
PrefObserver.prototype = {
observe: function (subject, topic, data) {
if (topic == "nsPref:changed") {
this.emit(this.branchName + data);
}
},
destroy: function () {
if (this.branch) {
this.branch.removeObserver("", this);
}
}
};

View File

@ -2,6 +2,8 @@
* 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/. */
const {PrefObserver} = require("devtools/client/shared/prefs");
/**
* A collection of `AudioNodeModel`s used throughout the editor
* to keep track of audio nodes within the audio context.
@ -58,7 +60,9 @@ var WebAudioEditorController = {
// Hook into theme change so we can change
// the graph's marker styling, since we can't do this
// with CSS
gDevTools.on("pref-changed", this._onThemeChange);
this._prefObserver = new PrefObserver("");
this._prefObserver.on("devtools.theme", this._onThemeChange);
// Store the AudioNode definitions from the WebAudioFront, if the method exists.
// If not, get the JSON directly. Using the actor method is preferable so the client
@ -90,7 +94,8 @@ var WebAudioEditorController = {
gFront.off("disconnect-node", this._onDisconnectNode);
gFront.off("change-param", this._onChangeParam);
gFront.off("destroy-node", this._onDestroyNode);
gDevTools.off("pref-changed", this._onThemeChange);
this._prefObserver.off("devtools.theme", this._onThemeChange);
this._prefObserver.destroy();
},
/**
@ -129,8 +134,9 @@ var WebAudioEditorController = {
* so that the graph can update marker styling, as that
* cannot currently be done with CSS.
*/
_onThemeChange: function (event, data) {
window.emit(EVENTS.THEME_CHANGE, data.newValue);
_onThemeChange: function () {
let newValue = Services.prefs.getCharPref("devtools.theme");
window.emit(EVENTS.THEME_CHANGE, newValue);
},
/**

View File

@ -8,6 +8,8 @@
"use strict";
const {PrefObserver} = require("devtools/client/shared/prefs");
const TEST_URI = "data:text/html;charset=utf-8,Web Console test for " +
"bug 1307871 - preference for toggling timestamps in messages";
const PREF_MESSAGE_TIMESTAMP = "devtools.webconsole.timestampMessages";
@ -19,9 +21,11 @@ add_task(function* () {
testPrefDefaults(outputEl);
let observer = new PrefObserver("");
let toolbox = gDevTools.getToolbox(hud.target);
let optionsPanel = yield toolbox.selectTool("options");
yield togglePref(optionsPanel);
yield togglePref(optionsPanel, observer);
observer.destroy();
yield testChangedPref(outputEl);
@ -35,13 +39,11 @@ function testPrefDefaults(outputEl) {
"Messages should have no timestamp (class name check)");
}
function* togglePref(panel) {
function* togglePref(panel, observer) {
info("Options panel opened");
info("Changing pref");
let prefChanged = new Promise(resolve => {
gDevTools.once("pref-changed", resolve);
});
let prefChanged = observer.once(PREF_MESSAGE_TIMESTAMP, () => {});
let checkbox = panel.panelDoc.getElementById("webconsole-timestamp-messages");
checkbox.click();

View File

@ -8,8 +8,9 @@ requireHacker.global_hook("default", path => {
switch (path) {
// For Enzyme
case "react-dom":
return `const ReactDOM = require('devtools/client/shared/vendor/react-dom'); module.exports = ReactDOM`;
case "react-dom/server":
return `const React = require('devtools/client/shared/vendor/react-dev'); module.exports = React`;
return `const ReactDOMServer = require('devtools/client/shared/vendor/react-dom-server'); module.exports = ReactDOMServer`;
case "react-addons-test-utils":
return `const React = require('devtools/client/shared/vendor/react-dev'); module.exports = React.addons.TestUtils`;
case "react-redux":

View File

@ -8,6 +8,8 @@
"use strict";
const {PrefObserver} = require("devtools/client/shared/prefs");
const TEST_URI = "data:text/html;charset=utf-8,Web Console test for " +
"bug 722267 - preference for toggling timestamps in messages";
const PREF_MESSAGE_TIMESTAMP = "devtools.webconsole.timestampMessages";
@ -19,8 +21,10 @@ add_task(function* () {
hud = yield openConsole();
let panel = yield consoleOpened();
yield onOptionsPanelSelected(panel);
let observer = new PrefObserver("");
yield onOptionsPanelSelected(panel, observer);
onPrefChanged();
observer.destroy();
Services.prefs.clearUserPref(PREF_MESSAGE_TIMESTAMP);
hud = null;
@ -37,10 +41,10 @@ function consoleOpened() {
return toolbox.selectTool("options");
}
function onOptionsPanelSelected(panel) {
function onOptionsPanelSelected(panel, observer) {
info("options panel opened");
let prefChanged = gDevTools.once("pref-changed", onPrefChanged);
let prefChanged = observer.once(PREF_MESSAGE_TIMESTAMP, () => {});
let checkbox = panel.panelDoc.getElementById("webconsole-timestamp-messages");
checkbox.click();

View File

@ -17,6 +17,7 @@ Cu.import("resource://devtools/client/shared/browser-loader.js", BrowserLoaderMo
const promise = require("promise");
const Services = require("Services");
const Telemetry = require("devtools/client/shared/telemetry");
const {PrefObserver} = require("devtools/client/shared/prefs");
loader.lazyServiceGetter(this, "clipboardHelper",
"@mozilla.org/widget/clipboardhelper;1",
@ -636,11 +637,9 @@ WebConsoleFrame.prototype = {
});
// Toggle the timestamp on preference change
gDevTools.on("pref-changed", this._onToolboxPrefChanged);
this._onToolboxPrefChanged("pref-changed", {
pref: PREF_MESSAGE_TIMESTAMP,
newValue: Services.prefs.getBoolPref(PREF_MESSAGE_TIMESTAMP),
});
this._prefObserver = new PrefObserver("");
this._prefObserver.on(PREF_MESSAGE_TIMESTAMP, this._onToolboxPrefChanged);
this._onToolboxPrefChanged();
this._initShortcuts();
@ -2691,25 +2690,16 @@ WebConsoleFrame.prototype = {
},
/**
* Handler for the pref-changed event coming from the toolbox.
* Currently this function only handles the timestamps preferences.
*
* @private
* @param object event
* This parameter is a string that holds the event name
* pref-changed in this case.
* @param object data
* This is the pref-changed data object.
*/
_onToolboxPrefChanged: function (event, data) {
if (data.pref == PREF_MESSAGE_TIMESTAMP) {
if (this.NEW_CONSOLE_OUTPUT_ENABLED) {
this.newConsoleOutput.dispatchTimestampsToggle(data.newValue);
} else if (data.newValue) {
this.outputNode.classList.remove("hideTimestamps");
} else {
this.outputNode.classList.add("hideTimestamps");
}
* Called when the message timestamp pref changes.
*/
_onToolboxPrefChanged: function () {
let newValue = Services.prefs.getBoolPref(PREF_MESSAGE_TIMESTAMP);
if (this.NEW_CONSOLE_OUTPUT_ENABLED) {
this.newConsoleOutput.dispatchTimestampsToggle(newValue);
} else if (newValue) {
this.outputNode.classList.remove("hideTimestamps");
} else {
this.outputNode.classList.add("hideTimestamps");
}
},
@ -2818,7 +2808,8 @@ WebConsoleFrame.prototype = {
toolbox.off("webconsole-selected", this._onPanelSelected);
}
gDevTools.off("pref-changed", this._onToolboxPrefChanged);
this._prefObserver.off(PREF_MESSAGE_TIMESTAMP, this._onToolboxPrefChanged);
this._prefObserver.destroy();
this.window.removeEventListener("resize", this.resize, true);
this._repeatNodes = {};

View File

@ -340,7 +340,7 @@ VRManager::RefreshVRControllers()
{
nsTArray<RefPtr<gfx::VRControllerHost>> controllers;
ScanForDevices();
ScanForControllers();
for (uint32_t i = 0; i < mControllerManagers.Length()
&& controllers.Length() == 0; ++i) {
@ -372,13 +372,22 @@ VRManager::RefreshVRControllers()
}
void
VRManager::ScanForDevices()
VRManager::ScanForControllers()
{
for (uint32_t i = 0; i < mControllerManagers.Length(); ++i) {
mControllerManagers[i]->ScanForDevices();
}
}
void
VRManager::RemoveControllers()
{
for (uint32_t i = 0; i < mControllerManagers.Length(); ++i) {
mControllerManagers[i]->RemoveDevices();
}
mVRControllers.Clear();
}
template<class T>
void
VRManager::NotifyGamepadChange(const T& aInfo)

View File

@ -38,7 +38,8 @@ public:
void NotifyVsync(const TimeStamp& aVsyncTimestamp);
void NotifyVRVsync(const uint32_t& aDisplayID);
void RefreshVRDisplays(bool aMustDispatch = false);
void ScanForDevices();
void ScanForControllers();
void RemoveControllers();
template<class T> void NotifyGamepadChange(const T& aInfo);
RefPtr<gfx::VRDisplayHost> GetDisplay(const uint32_t& aDisplayID);
void GetVRDisplayInfo(nsTArray<VRDisplayInfo>& aDisplayInfo);

View File

@ -254,6 +254,7 @@ public:
virtual void HandleInput() = 0;
virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>& aControllerResult) = 0;
virtual void ScanForDevices() = 0;
virtual void RemoveDevices() = 0;
void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed);
void NewAxisMove(uint32_t aIndex, uint32_t aAxis, double aValue);
void NewPoseState(uint32_t aIndex, const dom::GamepadPoseState& aPose);

View File

@ -567,7 +567,7 @@ VRControllerManagerOpenVR::Init()
void
VRControllerManagerOpenVR::Destroy()
{
mOpenVRController.Clear();
RemoveDevices();
mOpenVRInstalled = false;
}
@ -760,4 +760,11 @@ VRControllerManagerOpenVR::ScanForDevices()
#endif
}
}
}
void
VRControllerManagerOpenVR::RemoveDevices()
{
mOpenVRController.Clear();
mControllerCount = 0;
}

View File

@ -115,6 +115,7 @@ public:
virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>&
aControllerResult) override;
virtual void ScanForDevices() override;
virtual void RemoveDevices() override;
private:
VRControllerManagerOpenVR();

View File

@ -297,14 +297,15 @@ VRManagerParent::RecvControllerListenerAdded()
{
VRManager* vm = VRManager::Get();
// Ask the connected gamepads to be added to GamepadManager
vm->ScanForDevices();
vm->ScanForControllers();
return IPC_OK();
}
mozilla::ipc::IPCResult
VRManagerParent::RecvControllerListenerRemoved()
{
VRManager* vm = VRManager::Get();
vm->RemoveControllers();
return IPC_OK();
}

View File

@ -769,11 +769,10 @@ nsRubyBaseContainerFrame::PullOneColumn(nsLineLayout* aLineLayout,
// We are not pulling an intra-level whitespace, which means all
// elements we are going to pull can have non-whitespace content,
// which may contain float which we need to reparent.
nsBlockFrame* oldFloatCB = nullptr;
for (nsIFrame* frame : aColumn) {
oldFloatCB = nsLayoutUtils::GetFloatContainingBlock(frame);
break;
}
MOZ_ASSERT(aColumn.begin() != aColumn.end(),
"Ruby column shouldn't be empty");
nsBlockFrame* oldFloatCB =
nsLayoutUtils::GetFloatContainingBlock(*aColumn.begin());
#ifdef DEBUG
MOZ_ASSERT(oldFloatCB, "Must have found a float containing block");
for (nsIFrame* frame : aColumn) {

View File

@ -87,3 +87,18 @@ if CONFIG['MOZ_DEBUG']:
elif not CONFIG['RELEASE_OR_BETA']:
# Enable fast assertions in opt builds of Nightly and Aurora.
DEFINES['ASSERT_LEVEL'] = 1
# clang-cl's <intrin.h> doesn't work the same as MSVC's. For details, see:
#
# http://lists.llvm.org/pipermail/cfe-dev/2016-September/050943.html
#
# As a temporary workaround while upstream decides how to address this,
# we enable modules to make <intrin.h> more MSVC-compatible.
if CONFIG['CLANG_CL']:
CFLAGS += [
'-Xclang',
'-fmodules',
'-Xclang',
'-fmodules-cache-path=' + TOPOBJDIR + '/media/ffpvx',
'-fbuiltin-module-map',
]

View File

@ -229,7 +229,7 @@ NSSDialogs.prototype = {
for (let i = 0; i < certList.length; i++) {
let cert = certList.queryElementAt(i, Ci.nsIX509Cert);
certNickList.push(this.formatString("clientAuthAsk.nickAndSerial",
[cert.nickname, cert.serialNumber]));
[cert.displayName, cert.serialNumber]));
certDetailsList.push(this.getCertDetails(cert));
}

View File

@ -128,7 +128,7 @@ function readFile(file) {
function addCertFromFile(certdb, filename, trustString) {
let certFile = do_get_file(filename, false);
let der = readFile(certFile);
certdb.addCert(der, trustString, null);
certdb.addCert(der, trustString);
}
function makeChan(origin) {

View File

@ -1111,5 +1111,5 @@ function readFile(file) {
function addCertFromFile(certdb, filename, trustString) {
let certFile = do_get_file(filename, false);
let der = readFile(certFile);
certdb.addCert(der, trustString, null);
certdb.addCert(der, trustString);
}

View File

@ -52,7 +52,7 @@ function readFile(file) {
function addCertFromFile(certdb, filename, trustString) {
let certFile = do_get_file(filename, false);
let der = readFile(certFile);
certdb.addCert(der, trustString, null);
certdb.addCert(der, trustString);
}
function makeChan(origin, path) {

View File

@ -284,7 +284,6 @@ certErrorCodePrefix2=Error code: <a id="errorCode" title="%1$S">%1$S</a>
P12DefaultNickname=Imported Certificate
CertUnknown=Unknown
CertNoNickname=(no nickname)
CertNoEmailAddress=(no email address)
CaCertExists=This certificate is already installed as a certificate authority.
NotACACert=This is not a certificate authority certificate, so it cant be imported into the certificate authority list.

View File

@ -44,18 +44,12 @@ function doPrompt(msg)
*/
function AddCertChain(node, chain)
{
var child = document.getElementById(node);
var currCert;
var displayVal;
let child = document.getElementById(node);
for (let i = chain.length - 1; i >= 0; i--) {
currCert = chain.queryElementAt(i, nsIX509Cert);
if (currCert.commonName) {
displayVal = currCert.commonName;
} else {
displayVal = currCert.windowTitle;
}
let currCert = chain.queryElementAt(i, nsIX509Cert);
let displayValue = currCert.displayName;
let addTwistie = i != 0;
child = addChildrenToTree(child, displayVal, currCert.dbKey, addTwistie);
child = addChildrenToTree(child, displayValue, currCert.dbKey, addTwistie);
}
}
@ -82,7 +76,7 @@ function setWindowName()
let cert = window.arguments[0].QueryInterface(Ci.nsIX509Cert);
document.title = bundle.getFormattedString("certViewerTitle",
[cert.windowTitle]);
[cert.displayName]);
//
// Set the cert attributes for viewing

View File

@ -89,7 +89,7 @@ function onLoad() {
let cert = certArray.queryElementAt(i, Ci.nsIX509Cert);
let nickAndSerial =
bundle.getFormattedString("clientAuthNickAndSerial",
[cert.nickname, cert.serialNumber]);
[cert.displayName, cert.serialNumber]);
menuItemNode.setAttribute("value", i);
menuItemNode.setAttribute("label", nickAndSerial); // This is displayed.
selectElement.firstChild.appendChild(menuItemNode);

View File

@ -85,10 +85,7 @@ const DEFAULT_CERT_EXTENSION = "crt";
* Generated filename.
*/
function certToFilename(cert) {
let filename = cert.commonName;
if (!filename) {
filename = cert.windowTitle;
}
let filename = cert.displayName;
// Remove unneeded and/or unsafe characters.
filename = filename.replace(/\s/g, "")

View File

@ -13,7 +13,6 @@
#include "nsIPK11Token.h"
#include "nsIPK11TokenDB.h"
#include "nsIX509Cert.h"
#include "nsIX509CertDB.h"
#include "nsIX509CertValidity.h"
#include "nsLiteralString.h"
#include "nsProxyRelease.h"
@ -23,6 +22,44 @@
namespace mozilla {
// Given a name, searches the internal certificate/key database for a
// self-signed certificate with subject and issuer distinguished name equal to
// "CN={name}". This assumes that the user has already authenticated to the
// internal DB if necessary.
static nsresult
FindLocalCertByName(const nsACString& aName,
/*out*/ UniqueCERTCertificate& aResult)
{
aResult.reset(nullptr);
NS_NAMED_LITERAL_CSTRING(commonNamePrefix, "CN=");
nsAutoCString expectedDistinguishedName(commonNamePrefix + aName);
UniquePK11SlotInfo slot(PK11_GetInternalKeySlot());
if (!slot) {
return mozilla::psm::GetXPCOMFromNSSError(PR_GetError());
}
UniqueCERTCertList certList(PK11_ListCertsInSlot(slot.get()));
if (!certList) {
return NS_ERROR_UNEXPECTED;
}
for (const CERTCertListNode* node = CERT_LIST_HEAD(certList);
!CERT_LIST_END(node, certList); node = CERT_LIST_NEXT(node)) {
// If this isn't a self-signed cert, it's not what we're interested in.
if (!node->cert->isRoot) {
continue;
}
if (!expectedDistinguishedName.Equals(node->cert->subjectName)) {
continue; // Subject should match nickname
}
if (!expectedDistinguishedName.Equals(node->cert->issuerName)) {
continue; // Issuer should match nickname
}
// We found a match.
aResult.reset(CERT_DupCertificate(node->cert));
return NS_OK;
}
return NS_OK;
}
class LocalCertTask : public CryptoTask
{
protected:
@ -33,33 +70,20 @@ protected:
nsresult RemoveExisting()
{
// Search for any existing certs with this name and remove them
nsresult rv;
// Search for any existing self-signed certs with this name and remove them
for (;;) {
UniqueCERTCertificate cert(
PK11_FindCertFromNickname(mNickname.get(), nullptr));
UniqueCERTCertificate cert;
nsresult rv = FindLocalCertByName(mNickname, cert);
if (NS_FAILED(rv)) {
return rv;
}
// If we didn't find a match, we're done.
if (!cert) {
return NS_OK; // All done
return NS_OK;
}
// Found a cert, check if generated by this service
if (!cert->isRoot) {
return NS_ERROR_UNEXPECTED; // Should be self-signed
}
NS_NAMED_LITERAL_CSTRING(commonNamePrefix, "CN=");
nsAutoCString subjectNameFromNickname(commonNamePrefix + mNickname);
if (!subjectNameFromNickname.Equals(cert->subjectName)) {
return NS_ERROR_UNEXPECTED; // Subject should match nickname
}
if (!subjectNameFromNickname.Equals(cert->issuerName)) {
return NS_ERROR_UNEXPECTED; // Issuer should match nickname
}
rv = MapSECStatus(PK11_DeleteTokenCertAndKey(cert.get(), nullptr));
if (NS_FAILED(rv)) {
return rv; // Some error, abort the loop
return rv;
}
}
}
@ -253,19 +277,15 @@ private:
nsresult GetFromDB()
{
nsCOMPtr<nsIX509CertDB> certDB = do_GetService(NS_X509CERTDB_CONTRACTID);
if (!certDB) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIX509Cert> certFromDB;
nsresult rv;
rv = certDB->FindCertByNickname(NS_ConvertASCIItoUTF16(mNickname),
getter_AddRefs(certFromDB));
UniqueCERTCertificate cert;
nsresult rv = FindLocalCertByName(mNickname, cert);
if (NS_FAILED(rv)) {
return rv;
}
mCert = certFromDB;
if (!cert) {
return NS_ERROR_FAILURE;
}
mCert = nsNSSCertificate::Create(cert.get());
return NS_OK;
}

View File

@ -1075,30 +1075,9 @@ nsCertTree::GetCellText(int32_t row, nsITreeColumn* col,
if (NS_LITERAL_STRING("certcol").Equals(colID)) {
if (!cert) {
mNSSComponent->GetPIPNSSBundleString("CertNotStored", _retval);
}
else {
rv = cert->GetCommonName(_retval);
if (NS_FAILED(rv) || _retval.IsEmpty()) {
// kaie: I didn't invent the idea to cut off anything before
// the first colon. :-)
nsAutoString nick;
rv = cert->GetNickname(nick);
nsAString::const_iterator start, end, end2;
nick.BeginReading(start);
nick.EndReading(end);
end2 = end;
if (FindInReadable(NS_LITERAL_STRING(":"), start, end)) {
// found. end points to the first char after the colon,
// that's what we want.
_retval = Substring(end, end2);
}
else {
_retval = nick;
}
}
rv = mNSSComponent->GetPIPNSSBundleString("CertNotStored", _retval);
} else {
rv = cert->GetDisplayName(_retval);
}
} else if (NS_LITERAL_STRING("tokencol").Equals(colID) && cert) {
rv = cert->GetTokenName(_retval);

View File

@ -28,11 +28,6 @@ interface nsICertVerificationListener;
[scriptable, uuid(bdc3979a-5422-4cd5-8589-696b6e96ea83)]
interface nsIX509Cert : nsISupports {
/**
* A nickname for the certificate.
*/
readonly attribute AString nickname;
/**
* The primary email address of the certificate, if present.
*/
@ -145,7 +140,7 @@ interface nsIX509Cert : nsISupports {
/**
* A human readable identifier to label this certificate.
*/
readonly attribute AString windowTitle;
readonly attribute AString displayName;
/**
* Constants to classify the type of a certificate.

View File

@ -74,17 +74,6 @@ interface nsIX509CertDB : nsISupports {
const unsigned long TRUSTED_EMAIL = 1 << 1;
const unsigned long TRUSTED_OBJSIGN = 1 << 2;
/**
* Given a nickname,
* locate the matching certificate.
*
* @param aNickname The nickname to be used as the key
* to find a certificate.
*
* @return The matching certificate if found.
*/
nsIX509Cert findCertByNickname(in AString aNickname);
/**
* Will find a certificate based on its dbkey
* retrieved by getting the dbKey attribute of
@ -95,26 +84,6 @@ interface nsIX509CertDB : nsISupports {
*/
nsIX509Cert findCertByDBKey(in string aDBkey);
/**
* Find user's own email encryption certificate by nickname.
*
* @param aNickname The nickname to be used as the key
* to find the certificate.
*
* @return The matching certificate if found.
*/
nsIX509Cert findEmailEncryptionCert(in AString aNickname);
/**
* Find user's own email signing certificate by nickname.
*
* @param aNickname The nickname to be used as the key
* to find the certificate.
*
* @return The matching certificate if found.
*/
nsIX509Cert findEmailSigningCert(in AString aNickname);
/**
* Find a certificate by email address.
*
@ -338,13 +307,13 @@ interface nsIX509CertDB : nsISupports {
* Add a cert to a cert DB from a binary string.
*
* @param certDER The raw DER encoding of a certificate.
* @param aTrust decoded by CERT_DecodeTrustString. 3 comma separated characters,
* indicating SSL, Email, and Obj signing trust
* @param aName name of the cert for display purposes.
* TODO(bug 857627): aName is currently ignored. It should either
* not be ignored, or be removed.
* @param trust String describing the trust settings to assign the
* certificate. Decoded by CERT_DecodeTrustString. Consists of 3
* comma separated sets of characters, indicating SSL, Email, and
* Object signing trust.
* @return nsIX509Cert the resulting certificate
*/
void addCert(in ACString certDER, in ACString aTrust, in AUTF8String aName);
nsIX509Cert addCert(in ACString certDER, in ACString trust);
// Flags for verifyCertNow (these must match the values in CertVerifier.cpp):
// Prevent network traffic. Doesn't work with classic verification.
@ -407,16 +376,14 @@ interface nsIX509CertDB : nsISupports {
/*
* Add a cert to a cert DB from a base64 encoded string.
*
* @param base64 The raw representation of a certificate,
* encoded as Base 64.
* @param aTrust decoded by CERT_DecodeTrustString. 3 comma separated characters,
* indicating SSL, Email, and Obj signing trust
* @param aName name of the cert for display purposes.
* TODO(bug 857627): aName is currently ignored. It should either
* not be ignored, or be removed.
* @param base64 The raw representation of a certificate, encoded as Base 64.
* @param trust String describing the trust settings to assign the
* certificate. Decoded by CERT_DecodeTrustString. Consists of 3
* comma separated sets of characters, indicating SSL, Email, and
* Object signing trust.
* @return nsIX509Cert the resulting certificate
*/
void addCertFromBase64(in ACString base64, in ACString aTrust,
in AUTF8String aName);
nsIX509Cert addCertFromBase64(in ACString base64, in ACString trust);
/*
* Get all the known certs in the database

View File

@ -1967,13 +1967,16 @@ nsNSSCertificate::CreateASN1Struct(nsIASN1Object** aRetVal)
nsCOMPtr<nsIMutableArray> asn1Objects;
sequence->GetASN1Objects(getter_AddRefs(asn1Objects));
nsAutoString title;
nsresult rv = GetWindowTitle(title);
nsAutoString displayName;
nsresult rv = GetDisplayName(displayName);
if (NS_FAILED(rv)) {
return rv;
}
sequence->SetDisplayName(title);
rv = sequence->SetDisplayName(displayName);
if (NS_FAILED(rv)) {
return rv;
}
sequence.forget(aRetVal);
// This sequence will be contain the tbsCertificate, signatureAlgorithm,

View File

@ -9,6 +9,7 @@
#include "ExtendedValidation.h"
#include "NSSCertDBTrustDomain.h"
#include "certdb.h"
#include "mozilla/Assertions.h"
#include "mozilla/Base64.h"
#include "mozilla/Casting.h"
#include "mozilla/NotNull.h"
@ -366,34 +367,67 @@ nsNSSCertificate::GetDbKey(const UniqueCERTCertificate& cert, nsACString& aDbKey
}
NS_IMETHODIMP
nsNSSCertificate::GetWindowTitle(nsAString& aWindowTitle)
nsNSSCertificate::GetDisplayName(nsAString& aDisplayName)
{
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown()) {
return NS_ERROR_NOT_AVAILABLE;
}
aWindowTitle.Truncate();
aDisplayName.Truncate();
MOZ_ASSERT(mCert, "mCert should not be null in GetDisplayName");
if (!mCert) {
NS_ERROR("Somehow got nullptr for mCert in nsNSSCertificate.");
return NS_ERROR_FAILURE;
}
UniquePORTString commonName(CERT_GetCommonName(&mCert->subject));
UniquePORTString organizationalUnitName(CERT_GetOrgUnitName(&mCert->subject));
UniquePORTString organizationName(CERT_GetOrgName(&mCert->subject));
const char* titleOptions[] = {
mCert->nickname,
bool isBuiltInRoot;
nsresult rv = GetIsBuiltInRoot(&isBuiltInRoot);
if (NS_FAILED(rv)) {
return rv;
}
// Only use the nickname for built-in roots where we already have a hard-coded
// reasonable display name (unfortunately we have to strip off the leading
// slot identifier followed by a ':'). Otherwise, attempt to use the following
// in order:
// - the common name, if present
// - an organizational unit name, if present
// - an organization name, if present
// - the entire subject distinguished name, if non-empty
// - an email address, if one can be found
// In the unlikely event that none of these fields are present and non-empty
// (the subject really shouldn't be empty), an empty string is returned.
nsAutoCString builtInRootNickname;
if (isBuiltInRoot) {
nsAutoCString fullNickname(mCert->nickname);
int32_t index = fullNickname.Find(":");
if (index != kNotFound) {
// Substring will gracefully handle the case where index is the last
// character in the string (that is, if the nickname is just
// "Builtin Object Token:"). In that case, we'll get an empty string.
builtInRootNickname = Substring(fullNickname,
AssertedCast<uint32_t>(index + 1));
}
}
const char* nameOptions[] = {
builtInRootNickname.get(),
commonName.get(),
organizationalUnitName.get(),
organizationName.get(),
mCert->subjectName,
mCert->emailAddr
};
nsAutoCString titleOption;
for (size_t i = 0; i < ArrayLength(titleOptions); i++) {
titleOption = titleOptions[i];
if (titleOption.Length() > 0 && IsUTF8(titleOption)) {
CopyUTF8toUTF16(titleOption, aWindowTitle);
nsAutoCString nameOption;
for (auto nameOptionPtr : nameOptions) {
nameOption.Assign(nameOptionPtr);
if (nameOption.Length() > 0 && IsUTF8(nameOption)) {
CopyUTF8toUTF16(nameOption, aDisplayName);
return NS_OK;
}
}
@ -401,26 +435,6 @@ nsNSSCertificate::GetWindowTitle(nsAString& aWindowTitle)
return NS_OK;
}
NS_IMETHODIMP
nsNSSCertificate::GetNickname(nsAString& aNickname)
{
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown())
return NS_ERROR_NOT_AVAILABLE;
if (mCert->nickname) {
CopyUTF8toUTF16(mCert->nickname, aNickname);
} else {
nsresult rv;
nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
if (NS_FAILED(rv) || !nssComponent) {
return NS_ERROR_FAILURE;
}
nssComponent->GetPIPNSSBundleString("CertNoNickname", aNickname);
}
return NS_OK;
}
NS_IMETHODIMP
nsNSSCertificate::GetEmailAddress(nsAString& aEmailAddress)
{
@ -655,7 +669,6 @@ nsNSSCertificate::GetChain(nsIArray** _rvChain)
return NS_ERROR_NOT_AVAILABLE;
NS_ENSURE_ARG(_rvChain);
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Getting chain for \"%s\"\n", mCert->nickname));
mozilla::pkix::Time now(mozilla::pkix::Now());
@ -689,9 +702,6 @@ nsNSSCertificate::GetChain(nsIArray** _rvChain)
if ((usage & otherUsagesToTest) == 0) {
continue;
}
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("pipnss: PKIX attempting chain(%d) for '%s'\n",
usage, mCert->nickname));
if (certVerifier->VerifyCert(mCert.get(), usage, now,
nullptr, /*XXX fixme*/
nullptr, /*hostname*/
@ -707,9 +717,6 @@ nsNSSCertificate::GetChain(nsIArray** _rvChain)
// There is not verified path for the chain, however we still want to
// present to the user as much of a possible chain as possible, in the case
// where there was a problem with the cert or the issuers.
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("pipnss: getchain :CertVerify failed to get chain for '%s'\n",
mCert->nickname));
nssChain = UniqueCERTCertList(
CERT_GetCertChainFromCert(mCert.get(), PR_Now(), certUsageSSLClient));
}
@ -726,8 +733,6 @@ nsNSSCertificate::GetChain(nsIArray** _rvChain)
for (node = CERT_LIST_HEAD(nssChain.get());
!CERT_LIST_END(node, nssChain.get());
node = CERT_LIST_NEXT(node)) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("adding %s to chain\n", node->cert->nickname));
nsCOMPtr<nsIX509Cert> cert = nsNSSCertificate::Create(node->cert);
array->AppendElement(cert, false);
}
@ -749,7 +754,6 @@ nsNSSCertificate::GetAllTokenNames(uint32_t* aLength, char16_t*** aTokenNames)
*aTokenNames = nullptr;
// Get the slots from NSS
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Getting slots for \"%s\"\n", mCert->nickname));
UniquePK11SlotList slots(PK11_GetAllSlotsForCert(mCert.get(), nullptr));
if (!slots) {
if (PORT_GetError() == SEC_ERROR_NO_TOKEN) {

View File

@ -11,6 +11,7 @@
#include "SharedSSLState.h"
#include "certdb.h"
#include "mozilla/Base64.h"
#include "mozilla/Assertions.h"
#include "mozilla/Casting.h"
#include "mozilla/Unused.h"
#include "nsArray.h"
@ -93,36 +94,6 @@ nsNSSCertificateDB::~nsNSSCertificateDB()
shutdown(ShutdownCalledFrom::Object);
}
NS_IMETHODIMP
nsNSSCertificateDB::FindCertByNickname(const nsAString& nickname,
nsIX509Cert** _rvCert)
{
NS_ENSURE_ARG_POINTER(_rvCert);
*_rvCert = nullptr;
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown()) {
return NS_ERROR_NOT_AVAILABLE;
}
char *asciiname = nullptr;
NS_ConvertUTF16toUTF8 aUtf8Nickname(nickname);
asciiname = const_cast<char*>(aUtf8Nickname.get());
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Getting \"%s\"\n", asciiname));
UniqueCERTCertificate cert(PK11_FindCertFromNickname(asciiname, nullptr));
if (!cert) {
cert.reset(CERT_FindCertByNickname(CERT_GetDefaultCertDB(), asciiname));
}
if (cert) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("got it\n"));
nsCOMPtr<nsIX509Cert> pCert = nsNSSCertificate::Create(cert.get());
if (pCert) {
pCert.forget(_rvCert);
return NS_OK;
}
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsNSSCertificateDB::FindCertByDBKey(const char* aDBKey,nsIX509Cert** _cert)
{
@ -1037,80 +1008,6 @@ nsNSSCertificateDB::ExportPKCS12File(nsISupports* aToken,
return blob.ExportToFile(aFile, certs, count);
}
NS_IMETHODIMP
nsNSSCertificateDB::FindEmailEncryptionCert(const nsAString& aNickname,
nsIX509Cert** _retval)
{
NS_ENSURE_ARG_POINTER(_retval);
*_retval = nullptr;
if (aNickname.IsEmpty())
return NS_OK;
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown()) {
return NS_ERROR_NOT_AVAILABLE;
}
nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
char *asciiname = nullptr;
NS_ConvertUTF16toUTF8 aUtf8Nickname(aNickname);
asciiname = const_cast<char*>(aUtf8Nickname.get());
/* Find a good cert in the user's database */
UniqueCERTCertificate cert(CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(),
asciiname,
certUsageEmailRecipient,
true, ctx));
if (!cert) {
return NS_OK;
}
nsCOMPtr<nsIX509Cert> nssCert = nsNSSCertificate::Create(cert.get());
if (!nssCert) {
return NS_ERROR_OUT_OF_MEMORY;
}
nssCert.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
nsNSSCertificateDB::FindEmailSigningCert(const nsAString& aNickname,
nsIX509Cert** _retval)
{
NS_ENSURE_ARG_POINTER(_retval);
*_retval = nullptr;
if (aNickname.IsEmpty())
return NS_OK;
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown()) {
return NS_ERROR_NOT_AVAILABLE;
}
nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
char *asciiname = nullptr;
NS_ConvertUTF16toUTF8 aUtf8Nickname(aNickname);
asciiname = const_cast<char*>(aUtf8Nickname.get());
/* Find a good cert in the user's database */
UniqueCERTCertificate cert(CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(),
asciiname,
certUsageEmailSigner,
true, ctx));
if (!cert) {
return NS_OK;
}
nsCOMPtr<nsIX509Cert> nssCert = nsNSSCertificate::Create(cert.get());
if (!nssCert) {
return NS_ERROR_OUT_OF_MEMORY;
}
nssCert.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
nsNSSCertificateDB::FindCertByEmailAddress(const char* aEmailAddress,
nsIX509Cert** _retval)
@ -1332,8 +1229,14 @@ nsNSSCertificateDB::get_default_nickname(CERTCertificate *cert,
NS_IMETHODIMP
nsNSSCertificateDB::AddCertFromBase64(const nsACString& aBase64,
const nsACString& aTrust,
const nsACString& /*aName*/)
nsIX509Cert** addedCertificate)
{
MOZ_ASSERT(addedCertificate);
if (!addedCertificate) {
return NS_ERROR_INVALID_ARG;
}
*addedCertificate = nullptr;
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown()) {
return NS_ERROR_NOT_AVAILABLE;
@ -1359,7 +1262,12 @@ nsNSSCertificateDB::AddCertFromBase64(const nsACString& aBase64,
// If there's already a certificate that matches this one in the database, we
// still want to set its trust to the given value.
if (tmpCert->isperm) {
return SetCertTrustFromString(newCert, aTrust);
rv = SetCertTrustFromString(newCert, aTrust);
if (NS_FAILED(rv)) {
return rv;
}
newCert.forget(addedCertificate);
return NS_OK;
}
UniquePORTString nickname(CERT_MakeCANickname(tmpCert.get()));
@ -1373,17 +1281,22 @@ nsNSSCertificateDB::AddCertFromBase64(const nsACString& aBase64,
SECStatus srv = CERT_AddTempCertToPerm(tmpCert.get(), nickname.get(),
trust.GetTrust());
return MapSECStatus(srv);
if (srv != SECSuccess) {
return MapSECStatus(srv);
}
newCert.forget(addedCertificate);
return NS_OK;
}
NS_IMETHODIMP
nsNSSCertificateDB::AddCert(const nsACString& aCertDER, const nsACString& aTrust,
const nsACString& aName)
nsNSSCertificateDB::AddCert(const nsACString& aCertDER,
const nsACString& aTrust,
nsIX509Cert** addedCertificate)
{
nsCString base64;
nsresult rv = Base64Encode(aCertDER, base64);
NS_ENSURE_SUCCESS(rv, rv);
return AddCertFromBase64(base64, aTrust, aName);
return AddCertFromBase64(base64, aTrust, addedCertificate);
}
NS_IMETHODIMP

View File

@ -36,14 +36,7 @@ nsNSSCertificateFakeTransport::GetDbKey(nsACString&)
}
NS_IMETHODIMP
nsNSSCertificateFakeTransport::GetWindowTitle(nsAString&)
{
NS_NOTREACHED("Unimplemented on content process");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsNSSCertificateFakeTransport::GetNickname(nsAString&)
nsNSSCertificateFakeTransport::GetDisplayName(nsAString&)
{
NS_NOTREACHED("Unimplemented on content process");
return NS_ERROR_NOT_IMPLEMENTED;

View File

@ -70,7 +70,7 @@ function checkDialogContents(win, notBefore, notAfter) {
"Actual and expected issuer organization should be equal");
Assert.equal(win.document.getElementById("nicknames").label,
"test client certificate [03]",
"Mochitest client [03]",
"Actual and expected selected cert nickname and serial should " +
"be equal");
@ -90,8 +90,19 @@ function checkDialogContents(win, notBefore, notAfter) {
"Actual and expected token name should be equal");
}
function findCertByCommonName(commonName) {
let certEnumerator = certDB.getCerts().getEnumerator();
while (certEnumerator.hasMoreElements()) {
let cert = certEnumerator.getNext().QueryInterface(Ci.nsIX509Cert);
if (cert.commonName == commonName) {
return cert;
}
}
return null;
}
add_task(function* setup() {
cert = certDB.findCertByNickname("test client certificate");
cert = findCertByCommonName("Mochitest client");
Assert.notEqual(cert, null, "Should be able to find the test client cert");
});

View File

@ -51,7 +51,7 @@ function readCertificate(filename, trustString) {
let certdb = Cc["@mozilla.org/security/x509certdb;1"]
.getService(Ci.nsIX509CertDB);
let base64 = pemToBase64(pem);
certdb.addCertFromBase64(base64, trustString, "unused");
certdb.addCertFromBase64(base64, trustString);
let cert = certdb.constructX509FromBase64(base64);
gImportedCerts.push(cert);
return cert;

View File

@ -139,15 +139,11 @@ function readFile(file) {
function addCertFromFile(certdb, filename, trustString) {
let certFile = do_get_file(filename, false);
let certBytes = readFile(certFile);
let successful = false;
try {
certdb.addCert(certBytes, trustString, null);
successful = true;
return certdb.addCert(certBytes, trustString);
} catch (e) {}
if (!successful) {
// It might be PEM instead of DER.
certdb.addCertFromBase64(pemToBase64(certBytes), trustString, null);
}
// It might be PEM instead of DER.
return certdb.addCertFromBase64(pemToBase64(certBytes), trustString);
}
function constructCertFromFile(filename) {

View File

@ -14,7 +14,7 @@ var certDB = Cc["@mozilla.org/security/x509certdb;1"]
function load_cert(cert, trust) {
let file = "test_intermediate_basic_usage_constraints/" + cert + ".pem";
addCertFromFile(certDB, file, trust);
return addCertFromFile(certDB, file, trust);
}
function getDERString(cert) {
@ -27,19 +27,18 @@ function getDERString(cert) {
function run_test() {
load_cert("ca", "CTu,CTu,CTu");
load_cert("int-limited-depth", "CTu,CTu,CTu");
let int_cert = load_cert("int-limited-depth", "CTu,CTu,CTu");
let file = "test_intermediate_basic_usage_constraints/ee-int-limited-depth.pem";
let cert_pem = readFile(do_get_file(file));
let ee = certDB.constructX509FromBase64(pemToBase64(cert_pem));
checkCertErrorGeneric(certDB, ee, PRErrorCodeSuccess,
certificateUsageSSLServer);
// Change the already existing intermediate certificate's trust using
// addCertFromBase64(). We use findCertByNickname first to ensure that the
// certificate already exists.
let int_cert = certDB.findCertByNickname("int-limited-depth");
// addCertFromBase64().
notEqual(int_cert, null, "Intermediate cert should be in the cert DB");
let base64_cert = btoa(getDERString(int_cert));
certDB.addCertFromBase64(base64_cert, "p,p,p", "ignored_argument");
let returnedEE = certDB.addCertFromBase64(base64_cert, "p,p,p");
notEqual(returnedEE, null, "addCertFromBase64 should return a certificate");
checkCertErrorGeneric(certDB, ee, SEC_ERROR_UNTRUSTED_ISSUER,
certificateUsageSSLServer);
}

View File

@ -68,11 +68,21 @@ function getCertAsByteArray(certPath) {
return byteArray;
}
function findCertByCommonName(commonName) {
let certEnumerator = gCertDB.getCerts().getEnumerator();
while (certEnumerator.hasMoreElements()) {
let cert = certEnumerator.getNext().QueryInterface(Ci.nsIX509Cert);
if (cert.commonName == commonName) {
return cert;
}
}
return null;
}
function testImportCACert() {
// Sanity check the CA cert is missing.
throws(() => gCertDB.findCertByNickname(CA_CERT_COMMON_NAME),
/NS_ERROR_FAILURE/,
"CA cert should not be in the database before import");
equal(findCertByCommonName(CA_CERT_COMMON_NAME), null,
"CA cert should not be in the database before import");
// Import and check for success.
let caArray = getCertAsByteArray("test_certDB_import/importedCA.pem");
@ -81,7 +91,7 @@ function testImportCACert() {
equal(gCACertImportDialogCount, 1,
"Confirmation dialog for the CA cert should only be shown once");
let caCert = gCertDB.findCertByNickname(CA_CERT_COMMON_NAME);
let caCert = findCertByCommonName(CA_CERT_COMMON_NAME);
notEqual(caCert, null, "CA cert should now be found in the database");
ok(gCertDB.isCertTrusted(caCert, Ci.nsIX509Cert.CA_CERT,
Ci.nsIX509CertDB.TRUSTED_EMAIL),

View File

@ -39,7 +39,7 @@ function readAndTamperWithNthByte(certificatePath, n) {
const BYTE_IN_SIGNATURE = -8;
function addSignatureTamperedCertificate(certificatePath) {
let base64 = readAndTamperWithNthByte(certificatePath, BYTE_IN_SIGNATURE);
certdb.addCertFromBase64(base64, ",,", null);
certdb.addCertFromBase64(base64, ",,");
}
function ensureSignatureVerificationFailure(certificatePath) {
@ -74,7 +74,7 @@ const BYTE_IN_SERIAL_NUMBER = 17;
function addSerialNumberTamperedCertificate(certificatePath) {
let base64 = readAndTamperWithNthByte(certificatePath,
BYTE_IN_SERIAL_NUMBER);
certdb.addCertFromBase64(base64, ",,", null);
certdb.addCertFromBase64(base64, ",,");
}
function tamperWithSerialNumberAndEnsureVerificationFailure(certificatePath) {

View File

@ -9,15 +9,10 @@ do_get_profile(); // must be called before getting nsIX509CertDB
const certdb = Cc["@mozilla.org/security/x509certdb;1"]
.getService(Ci.nsIX509CertDB);
var certList = [
'ee',
'int',
'ca',
];
function load_cert(cert_name, trust_string) {
let cert_filename = cert_name + ".pem";
addCertFromFile(certdb, "test_cert_trust/" + cert_filename, trust_string);
return addCertFromFile(certdb, "test_cert_trust/" + cert_filename,
trust_string);
}
function setup_basic_trusts(ca_cert, int_cert) {
@ -50,7 +45,7 @@ function test_ca_distrust(ee_cert, cert_to_modify_trust, isRootCA) {
// Test of active distrust. No usage should pass.
setCertTrust(cert_to_modify_trust, 'p,p,p');
setCertTrust(cert_to_modify_trust, "p,p,p");
checkCertErrorGeneric(certdb, ee_cert, SEC_ERROR_UNTRUSTED_ISSUER,
certificateUsageSSLServer);
checkCertErrorGeneric(certdb, ee_cert, SEC_ERROR_UNTRUSTED_ISSUER,
@ -70,7 +65,7 @@ function test_ca_distrust(ee_cert, cert_to_modify_trust, isRootCA) {
// Trust set to T - trusted CA to issue client certs, where client cert is
// usageSSLClient.
setCertTrust(cert_to_modify_trust, 'T,T,T');
setCertTrust(cert_to_modify_trust, "T,T,T");
checkCertErrorGeneric(certdb, ee_cert, isRootCA ? SEC_ERROR_UNKNOWN_ISSUER
: PRErrorCodeSuccess,
certificateUsageSSLServer);
@ -101,7 +96,7 @@ function test_ca_distrust(ee_cert, cert_to_modify_trust, isRootCA) {
// Now tests on the SSL trust bit
setCertTrust(cert_to_modify_trust, 'p,C,C');
setCertTrust(cert_to_modify_trust, "p,C,C");
checkCertErrorGeneric(certdb, ee_cert, SEC_ERROR_UNTRUSTED_ISSUER,
certificateUsageSSLServer);
@ -122,7 +117,7 @@ function test_ca_distrust(ee_cert, cert_to_modify_trust, isRootCA) {
certificateUsageStatusResponder);
// Inherited trust SSL
setCertTrust(cert_to_modify_trust, ',C,C');
setCertTrust(cert_to_modify_trust, ",C,C");
checkCertErrorGeneric(certdb, ee_cert, isRootCA ? SEC_ERROR_UNKNOWN_ISSUER
: PRErrorCodeSuccess,
certificateUsageSSLServer);
@ -143,7 +138,7 @@ function test_ca_distrust(ee_cert, cert_to_modify_trust, isRootCA) {
certificateUsageStatusResponder);
// Now tests on the EMAIL trust bit
setCertTrust(cert_to_modify_trust, 'C,p,C');
setCertTrust(cert_to_modify_trust, "C,p,C");
checkCertErrorGeneric(certdb, ee_cert, PRErrorCodeSuccess,
certificateUsageSSLServer);
checkCertErrorGeneric(certdb, ee_cert, SEC_ERROR_UNTRUSTED_ISSUER,
@ -163,7 +158,7 @@ function test_ca_distrust(ee_cert, cert_to_modify_trust, isRootCA) {
//inherited EMAIL Trust
setCertTrust(cert_to_modify_trust, 'C,,C');
setCertTrust(cert_to_modify_trust, "C,,C");
checkCertErrorGeneric(certdb, ee_cert, PRErrorCodeSuccess,
certificateUsageSSLServer);
checkCertErrorGeneric(certdb, ee_cert, isRootCA ? SEC_ERROR_UNKNOWN_ISSUER
@ -187,16 +182,22 @@ function test_ca_distrust(ee_cert, cert_to_modify_trust, isRootCA) {
function run_test() {
let certList = [
"ca",
"int",
"ee",
];
let loadedCerts = [];
for (let i = 0 ; i < certList.length; i++) {
load_cert(certList[i], ',,');
loadedCerts.push(load_cert(certList[i], ",,"));
}
let ca_cert = certdb.findCertByNickname('ca');
notEqual(ca_cert, null, "CA cert should be in the cert DB");
let int_cert = certdb.findCertByNickname('int');
notEqual(int_cert, null, "Intermediate cert should be in the cert DB");
let ee_cert = certdb.findCertByNickname('ee');
notEqual(ee_cert, null, "EE cert should be in the cert DB");
let ca_cert = loadedCerts[0];
notEqual(ca_cert, null, "CA cert should have successfully loaded");
let int_cert = loadedCerts[1];
notEqual(int_cert, null, "Intermediate cert should have successfully loaded");
let ee_cert = loadedCerts[2];
notEqual(ee_cert, null, "EE cert should have successfully loaded");
setup_basic_trusts(ca_cert, int_cert);
test_ca_distrust(ee_cert, ca_cert, true);

View File

@ -36,7 +36,7 @@ do_register_cleanup(() => {
Services.prefs.setCharPref("network.dns.localDomains", "www.example.com");
Services.prefs.setIntPref("security.OCSP.enabled", 1);
addCertFromFile(certdb, "test_ev_certs/evroot.pem", "CTu,,");
const evroot = addCertFromFile(certdb, "test_ev_certs/evroot.pem", "CTu,,");
addCertFromFile(certdb, "test_ev_certs/non-evroot-ca.pem", "CTu,,");
const SERVER_PORT = 8888;
@ -214,7 +214,6 @@ add_task(function* expectDVFallbackTests() {
// causes the verifications to succeed again).
add_task(function* evRootTrustTests() {
clearOCSPCache();
let evroot = certdb.findCertByNickname("evroot");
do_print("untrusting evroot");
certdb.setCertTrust(evroot, Ci.nsIX509Cert.CA_CERT,
Ci.nsIX509CertDB.UNTRUSTED);

View File

@ -67,12 +67,15 @@ function run_test() {
clearOCSPCache();
clearSessionCache();
let ee_cert = null;
for (let cert of certList) {
addCertFromFile(certdb, `test_getchain/${cert}.pem`, ",,");
let result = addCertFromFile(certdb, `test_getchain/${cert}.pem`, ",,");
if (cert == "ee") {
ee_cert = result;
}
}
let ee_cert = certdb.findCertByNickname('ee');
notEqual(ee_cert, null, "EE cert should be in the cert DB");
notEqual(ee_cert, null, "EE cert should have successfully loaded");
let ca = get_ca_array();

View File

@ -49,11 +49,15 @@ add_task(function* () {
ok(!certService.loginPromptRequired);
let certA = yield getOrCreateCert(gNickname);
equal(certA.nickname, gNickname);
// The local cert service implementation takes the given nickname and uses it
// as the common name for the certificate it creates. nsIX509Cert.displayName
// uses the common name if it is present, so these should match. Should either
// implementation change to do something else, this won't necessarily work.
equal(certA.displayName, gNickname);
// Getting again should give the same cert
let certB = yield getOrCreateCert(gNickname);
equal(certB.nickname, gNickname);
equal(certB.displayName, gNickname);
// Should be matching instances
ok(certA.equals(certB));

View File

@ -45,8 +45,6 @@ function run_test() {
"hD/h2nawrCFwc5gJW10aLJGFL/mcS7ViAIT9HCVk23j4TuBjsVmnZ0VKxB5edux+" +
"LIEqtU428UVHZWU/I5ngLw==");
equal(cert.nickname, "(no nickname)",
"Actual and expected nickname should match");
equal(cert.emailAddress, "ludek.rasek@centrum.cz",
"Actual and expected emailAddress should match");
equal(cert.subjectName, "serialNumber=ICA - 10003769,SN=Rašek,name=Luděk Rašek,initials=LR,givenName=Luděk,E=ludek.rasek@centrum.cz,L=\"Pacov, Nádražní 769\",ST=Vysočina,CN=Luděk Rašek,C=CZ",
@ -57,8 +55,8 @@ function run_test() {
"Actual and expected organization should match");
equal(cert.organizationalUnit, "",
"Actual and expected organizationalUnit should match");
equal(cert.windowTitle, "Luděk Rašek",
"Actual and expected windowTitle should match");
equal(cert.displayName, "Luděk Rašek",
"Actual and expected displayName should match");
equal(cert.issuerName, "OU=Akreditovaný poskytovatel certifikačních služeb,O=První certifikační autorita a.s.,L=\"Podvinný mlýn 2178/6, 190 00 Praha 9\",C=CZ,CN=I.CA - Qualified root certificate (kvalifikovaný certifikát poskytovatele) - PSEUDONYM",
"Actual and expected issuerName should match");
equal(cert.issuerCommonName, "I.CA - Qualified root certificate (kvalifikovaný certifikát poskytovatele) - PSEUDONYM",

View File

@ -58,20 +58,11 @@ function downloadRoots() {
}
function makeFormattedNickname(cert) {
if (cert.nickname.startsWith("Builtin Object Token:")) {
return `"${cert.nickname.substring("Builtin Object Token:".length)}"`;
if (cert.isBuiltInRoot) {
return `"${cert.displayName}"`;
}
// Otherwise, this isn't a built-in and we have to comment it out.
if (cert.commonName) {
return `// "${cert.commonName}"`;
}
if (cert.organizationalUnit) {
return `// "${cert.organizationalUnit}"`;
}
if (cert.organization) {
return `// "${cert.organization}"`;
}
throw new Error(`couldn't make nickname for ${cert.subjectName}`);
return `// "${cert.displayName}"`;
}
var roots = downloadRoots();

View File

@ -28,7 +28,6 @@ var { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
var gCertDB = Cc["@mozilla.org/security/x509certdb;1"]
.getService(Ci.nsIX509CertDB);
const BUILT_IN_NICK_PREFIX = "Builtin Object Token:";
const SHA256_PREFIX = "sha256/";
const GOOGLE_PIN_PREFIX = "GOOGLE_PIN_";
@ -402,7 +401,7 @@ function loadNSSCertinfo(extraCertificates) {
if (!isCertBuiltIn(cert)) {
continue;
}
let name = cert.nickname.substr(BUILT_IN_NICK_PREFIX.length);
let name = cert.displayName;
let SKD = cert.sha256SubjectPublicKeyInfoDigest;
certNameToSKD[name] = SKD;
certSKDToName[SKD] = name;

View File

@ -653,7 +653,7 @@ Engine.prototype = {
// If this is false, we'll throw, otherwise, we'll ignore the record and
// continue. This currently can only happen due to the record being larger
// than the record upload limit.
allowSkippedRecord: false,
allowSkippedRecord: true,
get prefName() {
return this.name;

View File

@ -275,6 +275,7 @@ BookmarksEngine.prototype = {
_defaultSort: "index",
syncPriority: 4,
allowSkippedRecord: false,
// A diagnostic helper to get the string value for a bookmark's URL given
// its ID. Always returns a string - on error will return a string in the

View File

@ -81,6 +81,7 @@ ClientEngine.prototype = {
_storeObj: ClientStore,
_recordObj: ClientsRec,
_trackerObj: ClientsTracker,
allowSkippedRecord: false,
// Always sync client data as it controls other sync behavior
get enabled() {

View File

@ -41,6 +41,7 @@ ExtensionStorageEngine.prototype = {
_recordObj: undefined,
syncPriority: 10,
allowSkippedRecord: false,
_sync: function () {
return Async.promiseSpinningly(ExtensionStorageSync.syncAll());

View File

@ -111,7 +111,6 @@ FormEngine.prototype = {
_trackerObj: FormTracker,
_recordObj: FormRec,
applyIncomingBatchSize: FORMS_STORE_BATCH_SIZE,
allowSkippedRecord: true,
syncPriority: 6,

View File

@ -42,7 +42,6 @@ HistoryEngine.prototype = {
_trackerObj: HistoryTracker,
downloadLimit: MAX_HISTORY_DOWNLOAD,
applyIncomingBatchSize: HISTORY_STORE_BATCH_SIZE,
allowSkippedRecord: true,
syncPriority: 7,

View File

@ -42,6 +42,7 @@ PrefsEngine.prototype = {
version: 2,
syncPriority: 1,
allowSkippedRecord: false,
getChangedIDs: function () {
// No need for a proper timestamp (no conflict resolution needed).

View File

@ -1552,7 +1552,7 @@ add_task(async function test_uploadOutgoing_largeRecords() {
let collection = new ServerCollection();
let engine = makeRotaryEngine();
engine.allowSkippedRecord = false;
engine._store.items["large-item"] = "Y".repeat(MAX_UPLOAD_BYTES*2);
engine._tracker.addChangedID("large-item", 0);
collection.insert("large-item");

View File

@ -53,7 +53,7 @@ class TestAboutPrivateBrowsing(PuppeteerMixin, MarionetteTestCase):
link.click()
tab = pb_window.tabbar.open_tab(trigger=tab_opener)
Wait(self.marionette, timeout=self.browser.timeout_page_load).until(
Wait(self.marionette, timeout=self.marionette.timeout.page_load).until(
lambda _: tab.location == self.pb_url)
finally:

View File

@ -45,7 +45,7 @@ class TestMixedScriptContentBlocking(PuppeteerMixin, MarionetteTestCase):
)
# First call to Wait() needs a longer timeout due to the reload of the web page.
Wait(self.marionette, timeout=self.browser.timeout_page_load).until(
Wait(self.marionette, timeout=self.marionette.timeout.page_load).until(
lambda _: self.locationbar.identity_box.get_attribute('className') == identity,
message='Expected identity "{}" not found'.format(identity)
)

View File

@ -94,7 +94,7 @@ class TestSafeBrowsingNotificationBar(PuppeteerMixin, MarionetteTestCase):
button = self.marionette.find_element(By.ID, 'ignoreWarningButton')
button.click()
Wait(self.marionette, timeout=self.browser.timeout_page_load).until(
Wait(self.marionette, timeout=self.marionette.timeout.page_load).until(
expected.element_present(By.ID, 'main-feature'),
message='Expected target element "#main-feature" has not been found',
)
@ -113,7 +113,7 @@ class TestSafeBrowsingNotificationBar(PuppeteerMixin, MarionetteTestCase):
self.browser.tabbar.open_tab(lambda _: button.click())
Wait(self.marionette, timeout=self.browser.timeout_page_load).until(
Wait(self.marionette, timeout=self.marionette.timeout.page_load).until(
lambda mn: report_page in mn.get_url(),
message='The expected safe-browsing report page has not been opened',
)
@ -129,7 +129,7 @@ class TestSafeBrowsingNotificationBar(PuppeteerMixin, MarionetteTestCase):
.find_element('anon attribute', {'label': label}))
button.click()
Wait(self.marionette, timeout=self.browser.timeout_page_load).until(
Wait(self.marionette, timeout=self.marionette.timeout.page_load).until(
lambda mn: self.browser.default_homepage in mn.get_url(),
message='The default home page has not been loaded',
)
@ -143,7 +143,7 @@ class TestSafeBrowsingNotificationBar(PuppeteerMixin, MarionetteTestCase):
{'class': 'messageCloseButton close-icon tabbable'}))
button.click()
Wait(self.marionette, timeout=self.browser.timeout_page_load).until(
Wait(self.marionette, timeout=self.marionette.timeout.page_load).until(
expected.element_stale(button),
message='The notification bar has not been closed',
)

View File

@ -69,7 +69,7 @@ class TestSafeBrowsingWarningPages(PuppeteerMixin, MarionetteTestCase):
button = self.marionette.find_element(By.ID, "getMeOutButton")
button.click()
Wait(self.marionette, timeout=self.browser.timeout_page_load).until(
Wait(self.marionette, timeout=self.marionette.timeout.page_load).until(
lambda mn: self.browser.default_homepage in mn.get_url())
def check_report_button(self, unsafe_page):
@ -86,12 +86,12 @@ class TestSafeBrowsingWarningPages(PuppeteerMixin, MarionetteTestCase):
# Wait for the button to become stale, whereby a longer timeout is needed
# here to not fail in case of slow connections.
Wait(self.marionette, timeout=self.browser.timeout_page_load).until(
Wait(self.marionette, timeout=self.marionette.timeout.page_load).until(
expected.element_stale(button))
# Wait for page load to be completed, so we can verify the URL even if a redirect happens.
# TODO: Bug 1140470: use replacement for mozmill's waitforPageLoad
Wait(self.marionette, timeout=self.browser.timeout_page_load).until(
Wait(self.marionette, timeout=self.marionette.timeout.page_load).until(
lambda mn: mn.execute_script('return document.readyState == "DOMContentLoaded" ||'
' document.readyState == "complete";')
)
@ -103,7 +103,7 @@ class TestSafeBrowsingWarningPages(PuppeteerMixin, MarionetteTestCase):
button = self.marionette.find_element(By.ID, 'ignoreWarningButton')
button.click()
Wait(self.marionette, timeout=self.browser.timeout_page_load).until(
Wait(self.marionette, timeout=self.marionette.timeout.page_load).until(
expected.element_present(By.ID, 'main-feature'))
self.assertEquals(self.marionette.get_url(), self.browser.get_final_url(unsafe_page))

View File

@ -56,5 +56,5 @@ class TestSSLDisabledErrorPage(PuppeteerMixin, MarionetteTestCase):
reset_button.click()
# With the preferences reset, the page has to load correctly
Wait(self.marionette, timeout=self.browser.timeout_page_load).until(
Wait(self.marionette, timeout=self.marionette.timeout.page_load).until(
expected.element_present(By.LINK_TEXT, 'http://quality.mozilla.org'))

View File

@ -46,7 +46,7 @@ class TestSubmitUnencryptedInfoWarning(PuppeteerMixin, MarionetteTestCase):
try:
Wait(self.marionette,
ignored_exceptions=NoAlertPresentException,
timeout=self.browser.timeout_page_load).until(
timeout=self.marionette.timeout.page_load).until(
lambda _: warning.text == message)
finally:
warning.accept()
@ -55,7 +55,7 @@ class TestSubmitUnencryptedInfoWarning(PuppeteerMixin, MarionetteTestCase):
Wait(self.marionette).until(expected.element_stale(searchbox))
# TODO: Bug 1140470: use replacement for mozmill's waitforPageLoad
Wait(self.marionette, timeout=self.browser.timeout_page_load).until(
Wait(self.marionette, timeout=self.marionette.timeout.page_load).until(
lambda mn: mn.execute_script('return document.readyState == "DOMContentLoaded" ||'
' document.readyState == "complete";')
)

View File

@ -31,5 +31,5 @@ class TestUntrustedConnectionErrorPage(PuppeteerMixin, MarionetteTestCase):
button = self.marionette.find_element(By.ID, "returnButton")
button.click()
Wait(self.marionette, timeout=self.browser.timeout_page_load).until(
Wait(self.marionette, timeout=self.marionette.timeout.page_load).until(
lambda mn: target_url == self.marionette.get_url())

View File

@ -45,9 +45,6 @@ class BrowserWindow(BaseWindow):
self._navbar = None
self._tabbar = None
# Timeout for loading remote web pages
self.timeout_page_load = 30
@property
def default_homepage(self):
"""The default homepage as used by the current locale.

View File

@ -357,7 +357,7 @@ config = {
],
},
"marionette": {
"run_filename": os.path.join("marionette","runtests.py"),
"run_filename": os.path.join("harness", "marionette", "runtests.py"),
"testsdir": "marionette",
"options": [
"--emulator",

View File

@ -326,20 +326,24 @@ class Talos(TestingMixin, MercurialScript, BlobUploadMixin, TooltoolMixin):
self.suite = self.config['suite']
# now that have the suite name, check if pageset is required, if so download it
# the --no-download option will override this
if self.query_pagesets_name():
self.info("Downloading pageset with tooltool...")
self.src_talos_webdir = os.path.join(self.talos_path, 'talos')
src_talos_pageset = os.path.join(self.src_talos_webdir, 'tests')
manifest_file = os.path.join(self.talos_path, 'tp5n-pageset.manifest')
self.tooltool_fetch(
manifest_file,
output_dir=src_talos_pageset,
cache=self.config.get('tooltool_cache')
)
archive = os.path.join(src_talos_pageset, self.pagesets_name)
unzip = self.query_exe('unzip')
unzip_cmd = [unzip, '-q', '-o', archive, '-d', src_talos_pageset]
self.run_command(unzip_cmd, halt_on_failure=True)
if '--no-download' not in self.config['talos_extra_options']:
self.info("Downloading pageset with tooltool...")
self.src_talos_webdir = os.path.join(self.talos_path, 'talos')
src_talos_pageset = os.path.join(self.src_talos_webdir, 'tests')
manifest_file = os.path.join(self.talos_path, 'tp5n-pageset.manifest')
self.tooltool_fetch(
manifest_file,
output_dir=src_talos_pageset,
cache=self.config.get('tooltool_cache')
)
archive = os.path.join(src_talos_pageset, self.pagesets_name)
unzip = self.query_exe('unzip')
unzip_cmd = [unzip, '-q', '-o', archive, '-d', src_talos_pageset]
self.run_command(unzip_cmd, halt_on_failure=True)
else:
self.info("Not downloading pageset because the no-download option was specified")
# Action methods. {{{1
# clobber defined in BaseScript

View File

@ -155,7 +155,7 @@ class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin
dirs['abs_mochitest_dir'] = os.path.join(
dirs['abs_test_install_dir'], 'mochitest')
dirs['abs_marionette_dir'] = os.path.join(
dirs['abs_test_install_dir'], 'marionette', 'marionette')
dirs['abs_test_install_dir'], 'marionette', 'harness', 'marionette')
dirs['abs_marionette_tests_dir'] = os.path.join(
dirs['abs_test_install_dir'], 'marionette', 'tests', 'testing',
'marionette', 'harness', 'marionette', 'tests')

View File

@ -127,6 +127,8 @@ def create_parser(mach_interface=False):
' the manifest')
add_arg('--tpdelay', type=int,
help="length of the pageloader delay")
add_arg('--no-download', action="store_true", dest="no_download",
help="Do not download the talos test pagesets")
add_arg('--sourcestamp',
help='Specify the hg revision or sourcestamp for the changeset'
' we are testing. This will use the value found in'