зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to autoland
--HG-- extra : rebase_source : da41c9831b781517597aebd0878c5ada415fd00b
This commit is contained in:
Коммит
b613e3c213
|
@ -1,19 +1,19 @@
|
|||
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const AndroidEvents = {
|
||||
ANDROID_VIEW_CLICKED: 0x01,
|
||||
ANDROID_VIEW_LONG_CLICKED: 0x02,
|
||||
ANDROID_VIEW_SELECTED: 0x04,
|
||||
ANDROID_VIEW_FOCUSED: 0x08,
|
||||
ANDROID_VIEW_TEXT_CHANGED: 0x10,
|
||||
ANDROID_WINDOW_STATE_CHANGED: 0x20,
|
||||
ANDROID_VIEW_HOVER_ENTER: 0x80,
|
||||
ANDROID_VIEW_HOVER_EXIT: 0x100,
|
||||
ANDROID_VIEW_SCROLLED: 0x1000,
|
||||
ANDROID_VIEW_TEXT_SELECTION_CHANGED: 0x2000,
|
||||
ANDROID_ANNOUNCEMENT: 0x4000,
|
||||
ANDROID_VIEW_ACCESSIBILITY_FOCUSED: 0x8000,
|
||||
ANDROID_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY: 0x20000,
|
||||
VIEW_CLICKED: 0x01,
|
||||
VIEW_LONG_CLICKED: 0x02,
|
||||
VIEW_SELECTED: 0x04,
|
||||
VIEW_FOCUSED: 0x08,
|
||||
VIEW_TEXT_CHANGED: 0x10,
|
||||
WINDOW_STATE_CHANGED: 0x20,
|
||||
VIEW_HOVER_ENTER: 0x80,
|
||||
VIEW_HOVER_EXIT: 0x100,
|
||||
VIEW_SCROLLED: 0x1000,
|
||||
VIEW_TEXT_SELECTION_CHANGED: 0x2000,
|
||||
ANNOUNCEMENT: 0x4000,
|
||||
VIEW_ACCESSIBILITY_FOCUSED: 0x8000,
|
||||
VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY: 0x20000,
|
||||
};
|
||||
|
||||
function ConstantsMap(aObject, aPrefix, aMap = {}, aModifier = null) {
|
||||
|
|
|
@ -44,13 +44,13 @@ class AndroidPresentor {
|
|||
let isExploreByTouch = (aReason == Ci.nsIAccessiblePivot.REASON_POINT &&
|
||||
Utils.AndroidSdkVersion >= 14);
|
||||
let focusEventType = (Utils.AndroidSdkVersion >= 16) ?
|
||||
AndroidEvents.ANDROID_VIEW_ACCESSIBILITY_FOCUSED :
|
||||
AndroidEvents.ANDROID_VIEW_FOCUSED;
|
||||
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED :
|
||||
AndroidEvents.VIEW_FOCUSED;
|
||||
|
||||
if (isExploreByTouch) {
|
||||
// This isn't really used by TalkBack so this is a half-hearted attempt
|
||||
// for now.
|
||||
androidEvents.push({eventType: AndroidEvents.ANDROID_VIEW_HOVER_EXIT, text: []});
|
||||
androidEvents.push({eventType: AndroidEvents.VIEW_HOVER_EXIT, text: []});
|
||||
}
|
||||
|
||||
if (aReason === Ci.nsIAccessiblePivot.REASON_TEXT) {
|
||||
|
@ -58,7 +58,7 @@ class AndroidPresentor {
|
|||
let adjustedText = context.textAndAdjustedOffsets;
|
||||
|
||||
androidEvents.push({
|
||||
eventType: AndroidEvents.ANDROID_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
|
||||
eventType: AndroidEvents.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
|
||||
text: [adjustedText.text],
|
||||
fromIndex: adjustedText.startOffset,
|
||||
toIndex: adjustedText.endOffset
|
||||
|
@ -67,7 +67,7 @@ class AndroidPresentor {
|
|||
} else {
|
||||
let state = Utils.getState(context.accessible);
|
||||
androidEvents.push({eventType: (isExploreByTouch) ?
|
||||
AndroidEvents.ANDROID_VIEW_HOVER_ENTER : focusEventType,
|
||||
AndroidEvents.VIEW_HOVER_ENTER : focusEventType,
|
||||
text: Utils.localize(UtteranceGenerator.genForContext(
|
||||
context)),
|
||||
bounds: context.bounds,
|
||||
|
@ -105,7 +105,7 @@ class AndroidPresentor {
|
|||
}
|
||||
|
||||
return [{
|
||||
eventType: AndroidEvents.ANDROID_VIEW_CLICKED,
|
||||
eventType: AndroidEvents.VIEW_CLICKED,
|
||||
text,
|
||||
checked: state.contains(States.CHECKED)
|
||||
}];
|
||||
|
@ -116,7 +116,7 @@ class AndroidPresentor {
|
|||
*/
|
||||
textChanged(aAccessible, aIsInserted, aStart, aLength, aText, aModifiedText) {
|
||||
let androidEvent = {
|
||||
eventType: AndroidEvents.ANDROID_VIEW_TEXT_CHANGED,
|
||||
eventType: AndroidEvents.VIEW_TEXT_CHANGED,
|
||||
text: [aText],
|
||||
fromIndex: aStart,
|
||||
removedCount: 0,
|
||||
|
@ -144,7 +144,7 @@ class AndroidPresentor {
|
|||
|
||||
if (Utils.AndroidSdkVersion >= 14 && !aIsFromUserInput) {
|
||||
androidEvents.push({
|
||||
eventType: AndroidEvents.ANDROID_VIEW_TEXT_SELECTION_CHANGED,
|
||||
eventType: AndroidEvents.VIEW_TEXT_SELECTION_CHANGED,
|
||||
text: [aText],
|
||||
fromIndex: aStart,
|
||||
toIndex: aEnd,
|
||||
|
@ -156,7 +156,7 @@ class AndroidPresentor {
|
|||
let [from, to] = aOldStart < aStart ?
|
||||
[aOldStart, aStart] : [aStart, aOldStart];
|
||||
androidEvents.push({
|
||||
eventType: AndroidEvents.ANDROID_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
|
||||
eventType: AndroidEvents.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
|
||||
text: [aText],
|
||||
fromIndex: from,
|
||||
toIndex: to
|
||||
|
@ -229,7 +229,7 @@ class AndroidPresentor {
|
|||
}
|
||||
|
||||
let events = [{
|
||||
eventType: AndroidEvents.ANDROID_VIEW_SCROLLED,
|
||||
eventType: AndroidEvents.VIEW_SCROLLED,
|
||||
text: [],
|
||||
scrollX: aWindow.scrollX,
|
||||
scrollY: aWindow.scrollY,
|
||||
|
@ -241,7 +241,7 @@ class AndroidPresentor {
|
|||
let currentAcc = currentContext.accessibleForBounds;
|
||||
if (Utils.isAliveAndVisible(currentAcc)) {
|
||||
events.push({
|
||||
eventType: AndroidEvents.ANDROID_VIEW_ACCESSIBILITY_FOCUSED,
|
||||
eventType: AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED,
|
||||
bounds: Utils.getBounds(currentAcc)
|
||||
});
|
||||
}
|
||||
|
@ -264,8 +264,8 @@ class AndroidPresentor {
|
|||
let localizedAnnouncement = Utils.localize(aAnnouncement).join(" ");
|
||||
return [{
|
||||
eventType: (Utils.AndroidSdkVersion >= 16) ?
|
||||
AndroidEvents.ANDROID_ANNOUNCEMENT :
|
||||
AndroidEvents.ANDROID_VIEW_TEXT_CHANGED,
|
||||
AndroidEvents.ANNOUNCEMENT :
|
||||
AndroidEvents.VIEW_TEXT_CHANGED,
|
||||
text: [localizedAnnouncement],
|
||||
addedCount: localizedAnnouncement.length,
|
||||
removedCount: 0,
|
||||
|
@ -280,7 +280,7 @@ class AndroidPresentor {
|
|||
*/
|
||||
noMove(aMoveMethod) {
|
||||
return [{
|
||||
eventType: AndroidEvents.ANDROID_VIEW_ACCESSIBILITY_FOCUSED,
|
||||
eventType: AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED,
|
||||
exitView: aMoveMethod,
|
||||
text: [""]
|
||||
}];
|
||||
|
|
|
@ -551,7 +551,7 @@ ExpectedPresent.prototype.ignore = function(aMessage) {
|
|||
|
||||
let firstEvent = (aMessage.json || [])[0];
|
||||
|
||||
return firstEvent && firstEvent.eventType === AndroidEvents.ANDROID_VIEW_SCROLLED;
|
||||
return firstEvent && firstEvent.eventType === AndroidEvents.VIEW_SCROLLED;
|
||||
};
|
||||
|
||||
function ExpectedCursorChange(aSpeech, aOptions) {
|
||||
|
@ -564,7 +564,7 @@ ExpectedCursorChange.prototype = Object.create(ExpectedPresent.prototype);
|
|||
|
||||
function ExpectedCursorTextChange(aSpeech, aStartOffset, aEndOffset, aOptions) {
|
||||
ExpectedPresent.call(this, [{
|
||||
eventType: AndroidEvents.ANDROID_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
|
||||
eventType: AndroidEvents.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
|
||||
fromIndex: aStartOffset,
|
||||
toIndex: aEndOffset
|
||||
}], aOptions);
|
||||
|
@ -578,7 +578,7 @@ ExpectedCursorTextChange.prototype =
|
|||
|
||||
function ExpectedClickAction(aOptions) {
|
||||
ExpectedPresent.call(this, [{
|
||||
eventType: AndroidEvents.ANDROID_VIEW_CLICKED
|
||||
eventType: AndroidEvents.VIEW_CLICKED
|
||||
}], aOptions);
|
||||
}
|
||||
|
||||
|
@ -586,7 +586,7 @@ ExpectedClickAction.prototype = Object.create(ExpectedPresent.prototype);
|
|||
|
||||
function ExpectedCheckAction(aChecked, aOptions) {
|
||||
ExpectedPresent.call(this, [{
|
||||
eventType: AndroidEvents.ANDROID_VIEW_CLICKED,
|
||||
eventType: AndroidEvents.VIEW_CLICKED,
|
||||
checked: aChecked
|
||||
}], aOptions);
|
||||
}
|
||||
|
@ -595,7 +595,7 @@ ExpectedCheckAction.prototype = Object.create(ExpectedPresent.prototype);
|
|||
|
||||
function ExpectedSwitchAction(aSwitched, aOptions) {
|
||||
ExpectedPresent.call(this, [{
|
||||
eventType: AndroidEvents.ANDROID_VIEW_CLICKED,
|
||||
eventType: AndroidEvents.VIEW_CLICKED,
|
||||
checked: aSwitched
|
||||
}], aOptions);
|
||||
}
|
||||
|
@ -619,7 +619,7 @@ ExpectedValueChange.prototype = Object.create(ExpectedPresent.prototype);
|
|||
// XXX: Implement Android event?
|
||||
function ExpectedTextChanged(aValue, aOptions) {
|
||||
ExpectedPresent.call(this, [{
|
||||
eventType: AndroidEvents.ANDROID_VIEW_TEXT_CHANGED
|
||||
eventType: AndroidEvents.VIEW_TEXT_CHANGED
|
||||
}], aOptions);
|
||||
}
|
||||
|
||||
|
@ -634,7 +634,7 @@ ExpectedEditState.prototype = Object.create(ExpectedMessage.prototype);
|
|||
|
||||
function ExpectedTextSelectionChanged(aStart, aEnd, aOptions) {
|
||||
ExpectedPresent.call(this, [{
|
||||
eventType: AndroidEvents.ANDROID_VIEW_TEXT_SELECTION_CHANGED,
|
||||
eventType: AndroidEvents.VIEW_TEXT_SELECTION_CHANGED,
|
||||
}], aOptions);
|
||||
}
|
||||
|
||||
|
@ -643,7 +643,7 @@ ExpectedTextSelectionChanged.prototype =
|
|||
|
||||
function ExpectedTextCaretChanged(aFrom, aTo, aOptions) {
|
||||
ExpectedPresent.call(this, [{
|
||||
eventType: AndroidEvents.ANDROID_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
|
||||
eventType: AndroidEvents.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
|
||||
fromIndex: aFrom,
|
||||
toIndex: aTo
|
||||
}], aOptions);
|
||||
|
@ -653,7 +653,7 @@ ExpectedTextCaretChanged.prototype = Object.create(ExpectedPresent.prototype);
|
|||
|
||||
function ExpectedAnnouncement(aAnnouncement, aOptions) {
|
||||
ExpectedPresent.call(this, [{
|
||||
eventType: AndroidEvents.ANDROID_ANNOUNCEMENT,
|
||||
eventType: AndroidEvents.ANNOUNCEMENT,
|
||||
text: [ aAnnouncement],
|
||||
addedCount: aAnnouncement.length
|
||||
}], aOptions);
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
|
||||
var tests = [{
|
||||
expected: [{
|
||||
"eventType": AndroidEvents.ANDROID_ANNOUNCEMENT,
|
||||
"eventType": AndroidEvents.ANNOUNCEMENT,
|
||||
"text": ["hidden I will be hidden"],
|
||||
"addedCount": "hidden I will be hidden".length,
|
||||
"removedCount": 0,
|
||||
|
@ -71,7 +71,7 @@
|
|||
}
|
||||
}, {
|
||||
expected: [{
|
||||
"eventType": AndroidEvents.ANDROID_ANNOUNCEMENT,
|
||||
"eventType": AndroidEvents.ANNOUNCEMENT,
|
||||
"text": ["hidden I will be hidden"],
|
||||
"addedCount": "hidden I will be hidden".length,
|
||||
"removedCount": 0,
|
||||
|
@ -86,7 +86,7 @@
|
|||
}
|
||||
}, {
|
||||
expected: [{
|
||||
"eventType": AndroidEvents.ANDROID_ANNOUNCEMENT,
|
||||
"eventType": AndroidEvents.ANNOUNCEMENT,
|
||||
"text": ["I will be shown"],
|
||||
"addedCount": "I will be shown".length,
|
||||
"removedCount": 0,
|
||||
|
@ -100,7 +100,7 @@
|
|||
}
|
||||
}, {
|
||||
expected: [{
|
||||
"eventType": AndroidEvents.ANDROID_ANNOUNCEMENT,
|
||||
"eventType": AndroidEvents.ANNOUNCEMENT,
|
||||
"text": ["I will be shown"],
|
||||
"addedCount": "I will be shown".length,
|
||||
"removedCount": 0,
|
||||
|
@ -115,7 +115,7 @@
|
|||
}
|
||||
}, {
|
||||
expected: [{
|
||||
"eventType": AndroidEvents.ANDROID_ANNOUNCEMENT,
|
||||
"eventType": AndroidEvents.ANNOUNCEMENT,
|
||||
"text": ["hidden I will be hidden"],
|
||||
"addedCount": "hidden I will be hidden".length,
|
||||
"removedCount": 0,
|
||||
|
@ -129,7 +129,7 @@
|
|||
}
|
||||
}, {
|
||||
expected: [{
|
||||
"eventType": AndroidEvents.ANDROID_ANNOUNCEMENT,
|
||||
"eventType": AndroidEvents.ANNOUNCEMENT,
|
||||
"text": ["hidden I will be hidden"],
|
||||
"addedCount": "hidden I will be hidden".length,
|
||||
"removedCount": 0,
|
||||
|
@ -144,7 +144,7 @@
|
|||
}
|
||||
}, {
|
||||
expected: [{
|
||||
"eventType": AndroidEvents.ANDROID_ANNOUNCEMENT,
|
||||
"eventType": AndroidEvents.ANNOUNCEMENT,
|
||||
"text": ["I will be shown"],
|
||||
"addedCount": "I will be shown".length,
|
||||
"removedCount": 0,
|
||||
|
@ -158,7 +158,7 @@
|
|||
}
|
||||
}, {
|
||||
expected: [{
|
||||
"eventType": AndroidEvents.ANDROID_ANNOUNCEMENT,
|
||||
"eventType": AndroidEvents.ANNOUNCEMENT,
|
||||
"text": ["I will be shown"],
|
||||
"addedCount": "I will be shown".length,
|
||||
"removedCount": 0,
|
||||
|
@ -173,7 +173,7 @@
|
|||
}
|
||||
}, {
|
||||
expected: [{
|
||||
"eventType": AndroidEvents.ANDROID_ANNOUNCEMENT,
|
||||
"eventType": AndroidEvents.ANNOUNCEMENT,
|
||||
"text": ["hidden I will be hidden"],
|
||||
"addedCount": "hidden I will be hidden".length,
|
||||
"removedCount": 0,
|
||||
|
@ -187,7 +187,7 @@
|
|||
}
|
||||
}, {
|
||||
expected: [{
|
||||
"eventType": AndroidEvents.ANDROID_ANNOUNCEMENT,
|
||||
"eventType": AndroidEvents.ANNOUNCEMENT,
|
||||
"text": ["hidden I will be hidden"],
|
||||
"addedCount": "hidden I will be hidden".length,
|
||||
"removedCount": 0,
|
||||
|
@ -201,7 +201,7 @@
|
|||
}
|
||||
}, {
|
||||
expected: [{
|
||||
"eventType": AndroidEvents.ANDROID_ANNOUNCEMENT,
|
||||
"eventType": AndroidEvents.ANNOUNCEMENT,
|
||||
"text": ["I will be shown"],
|
||||
"addedCount": "I will be shown".length,
|
||||
"removedCount": 0,
|
||||
|
@ -215,7 +215,7 @@
|
|||
}
|
||||
}, {
|
||||
expected: [{
|
||||
"eventType": AndroidEvents.ANDROID_ANNOUNCEMENT,
|
||||
"eventType": AndroidEvents.ANNOUNCEMENT,
|
||||
"text": ["I will be shown"],
|
||||
"addedCount": "I will be shown".length,
|
||||
"removedCount": 0,
|
||||
|
@ -229,7 +229,7 @@
|
|||
}
|
||||
}, {
|
||||
expected: [{
|
||||
"eventType": AndroidEvents.ANDROID_ANNOUNCEMENT,
|
||||
"eventType": AndroidEvents.ANNOUNCEMENT,
|
||||
"text": ["Text Added"],
|
||||
"addedCount": "Text Added".length,
|
||||
"removedCount": 0,
|
||||
|
@ -243,7 +243,7 @@
|
|||
}
|
||||
}, {
|
||||
expected: [{
|
||||
"eventType": AndroidEvents.ANDROID_ANNOUNCEMENT,
|
||||
"eventType": AndroidEvents.ANNOUNCEMENT,
|
||||
"text": ["Text Added"],
|
||||
"addedCount": "Text Added".length,
|
||||
"removedCount": 0,
|
||||
|
@ -257,7 +257,7 @@
|
|||
}
|
||||
}, {
|
||||
expected: [{
|
||||
"eventType": AndroidEvents.ANDROID_ANNOUNCEMENT,
|
||||
"eventType": AndroidEvents.ANNOUNCEMENT,
|
||||
"text": ["hidden Text Removed"],
|
||||
"addedCount": "hidden Text Removed".length,
|
||||
"removedCount": 0,
|
||||
|
@ -271,7 +271,7 @@
|
|||
}
|
||||
}, {
|
||||
expected: [{
|
||||
"eventType": AndroidEvents.ANDROID_ANNOUNCEMENT,
|
||||
"eventType": AndroidEvents.ANNOUNCEMENT,
|
||||
"text": ["Descendant Text Added"],
|
||||
"addedCount": "Descendant Text Added".length,
|
||||
"removedCount": 0,
|
||||
|
@ -285,7 +285,7 @@
|
|||
}
|
||||
}, {
|
||||
expected: [{
|
||||
"eventType": AndroidEvents.ANDROID_ANNOUNCEMENT,
|
||||
"eventType": AndroidEvents.ANNOUNCEMENT,
|
||||
"text": ["Descendant Text Added"],
|
||||
"addedCount": "Descendant Text Added".length,
|
||||
"removedCount": 0,
|
||||
|
@ -299,7 +299,7 @@
|
|||
}
|
||||
}, {
|
||||
expected: [{
|
||||
"eventType": AndroidEvents.ANDROID_ANNOUNCEMENT,
|
||||
"eventType": AndroidEvents.ANNOUNCEMENT,
|
||||
"text": ["hidden Descendant Text Removed"],
|
||||
"addedCount": "hidden Descendant Text Removed".length,
|
||||
"removedCount": 0,
|
||||
|
@ -313,7 +313,7 @@
|
|||
}
|
||||
}, {
|
||||
expected: [{
|
||||
"eventType": AndroidEvents.ANDROID_ANNOUNCEMENT,
|
||||
"eventType": AndroidEvents.ANNOUNCEMENT,
|
||||
"text": ["Descendant Text Added"],
|
||||
"addedCount": "Descendant Text Added".length,
|
||||
"removedCount": 0,
|
||||
|
@ -327,7 +327,7 @@
|
|||
}
|
||||
}, {
|
||||
expected: [{
|
||||
"eventType": AndroidEvents.ANDROID_ANNOUNCEMENT,
|
||||
"eventType": AndroidEvents.ANNOUNCEMENT,
|
||||
"text": ["Descendant Text Added"],
|
||||
"addedCount": "Descendant Text Added".length,
|
||||
"removedCount": 0,
|
||||
|
@ -341,7 +341,7 @@
|
|||
}
|
||||
}, {
|
||||
expected: [{
|
||||
"eventType": AndroidEvents.ANDROID_ANNOUNCEMENT,
|
||||
"eventType": AndroidEvents.ANNOUNCEMENT,
|
||||
"text": ["hidden Descendant Text Removed"],
|
||||
"addedCount": "hidden Descendant Text Removed".length,
|
||||
"removedCount": 0,
|
||||
|
@ -355,7 +355,7 @@
|
|||
}
|
||||
}, {
|
||||
expected: [{
|
||||
"eventType": AndroidEvents.ANDROID_ANNOUNCEMENT,
|
||||
"eventType": AndroidEvents.ANNOUNCEMENT,
|
||||
"text": ["I am replaced main"],
|
||||
"addedCount": "I am replaced main".length,
|
||||
"removedCount": 0,
|
||||
|
@ -370,7 +370,7 @@
|
|||
}
|
||||
}, {
|
||||
expected: [{
|
||||
"eventType": AndroidEvents.ANDROID_ANNOUNCEMENT,
|
||||
"eventType": AndroidEvents.ANNOUNCEMENT,
|
||||
"text": ["I am a replaced text"],
|
||||
"addedCount": "I am a replaced text".length,
|
||||
"removedCount": 0,
|
||||
|
@ -384,7 +384,7 @@
|
|||
}
|
||||
}, {
|
||||
expected: [{
|
||||
"eventType": AndroidEvents.ANDROID_ANNOUNCEMENT,
|
||||
"eventType": AndroidEvents.ANNOUNCEMENT,
|
||||
"text": ["I am a replaced text"],
|
||||
"addedCount": "I am a replaced text".length,
|
||||
"removedCount": 0,
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=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 https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "LauncherProcessWin.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/CmdLineAndEnvUtils.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/SafeMode.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsWindowsHelpers.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "ProcThreadAttributes.h"
|
||||
|
||||
/**
|
||||
* At this point the child process has been created in a suspended state. Any
|
||||
* additional startup work (eg, blocklist setup) should go here.
|
||||
*
|
||||
* @return true if browser startup should proceed, otherwise false.
|
||||
*/
|
||||
static bool
|
||||
PostCreationSetup(HANDLE aChildProcess, HANDLE aChildMainThread,
|
||||
const bool aIsSafeMode)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Any mitigation policies that should be set on the browser process should go
|
||||
* here.
|
||||
*/
|
||||
static void
|
||||
SetMitigationPolicies(mozilla::ProcThreadAttributes& aAttrs, const bool aIsSafeMode)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
ShowError(DWORD aError = ::GetLastError())
|
||||
{
|
||||
if (aError == ERROR_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
LPWSTR rawMsgBuf = nullptr;
|
||||
DWORD result = ::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS, nullptr,
|
||||
aError, 0, reinterpret_cast<LPWSTR>(&rawMsgBuf),
|
||||
0, nullptr);
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
|
||||
::MessageBoxW(nullptr, rawMsgBuf, L"Firefox", MB_OK | MB_ICONERROR);
|
||||
::LocalFree(rawMsgBuf);
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// Eventually we want to be able to set a build config flag such that, when set,
|
||||
// this function will always return true.
|
||||
bool
|
||||
RunAsLauncherProcess(int& argc, wchar_t** argv)
|
||||
{
|
||||
return CheckArg(argc, argv, L"launcher",
|
||||
static_cast<const wchar_t**>(nullptr),
|
||||
CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
|
||||
}
|
||||
|
||||
int
|
||||
LauncherMain(int argc, wchar_t* argv[])
|
||||
{
|
||||
UniquePtr<wchar_t[]> cmdLine(MakeCommandLine(argc, argv));
|
||||
if (!cmdLine) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
const Maybe<bool> isSafeMode = IsSafeModeRequested(argc, argv,
|
||||
SafeModeFlag::None);
|
||||
if (!isSafeMode) {
|
||||
ShowError(ERROR_INVALID_PARAMETER);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ProcThreadAttributes attrs;
|
||||
SetMitigationPolicies(attrs, isSafeMode.value());
|
||||
|
||||
HANDLE stdHandles[] = {
|
||||
::GetStdHandle(STD_INPUT_HANDLE),
|
||||
::GetStdHandle(STD_OUTPUT_HANDLE),
|
||||
::GetStdHandle(STD_ERROR_HANDLE)
|
||||
};
|
||||
|
||||
attrs.AddInheritableHandles(stdHandles);
|
||||
|
||||
DWORD creationFlags = CREATE_SUSPENDED | CREATE_UNICODE_ENVIRONMENT;
|
||||
|
||||
STARTUPINFOEXW siex;
|
||||
Maybe<bool> attrsOk = attrs.AssignTo(siex);
|
||||
if (!attrsOk) {
|
||||
ShowError();
|
||||
return 1;
|
||||
}
|
||||
|
||||
BOOL inheritHandles = FALSE;
|
||||
|
||||
if (attrsOk.value()) {
|
||||
creationFlags |= EXTENDED_STARTUPINFO_PRESENT;
|
||||
|
||||
siex.StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
|
||||
siex.StartupInfo.hStdInput = stdHandles[0];
|
||||
siex.StartupInfo.hStdOutput = stdHandles[1];
|
||||
siex.StartupInfo.hStdError = stdHandles[2];
|
||||
|
||||
// Since attrsOk == true, we have successfully set the handle inheritance
|
||||
// whitelist policy, so only the handles added to attrs will be inherited.
|
||||
inheritHandles = TRUE;
|
||||
}
|
||||
|
||||
PROCESS_INFORMATION pi = {};
|
||||
if (!::CreateProcessW(argv[0], cmdLine.get(), nullptr, nullptr, inheritHandles,
|
||||
creationFlags, nullptr, nullptr, &siex.StartupInfo, &pi)) {
|
||||
ShowError();
|
||||
return 1;
|
||||
}
|
||||
|
||||
nsAutoHandle process(pi.hProcess);
|
||||
nsAutoHandle mainThread(pi.hThread);
|
||||
|
||||
if (!PostCreationSetup(process.get(), mainThread.get(), isSafeMode.value()) ||
|
||||
::ResumeThread(mainThread.get()) == static_cast<DWORD>(-1)) {
|
||||
ShowError();
|
||||
::TerminateProcess(process.get(), 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,18 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=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 https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_LauncherProcessWin_h
|
||||
#define mozilla_LauncherProcessWin_h
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
bool RunAsLauncherProcess(int& argc, wchar_t* argv[]);
|
||||
int LauncherMain(int argc, wchar_t* argv[]);
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_LauncherProcessWin_h
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=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 https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_ProcThreadAttributes_h
|
||||
#define mozilla_ProcThreadAttributes_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/Vector.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class MOZ_RAII ProcThreadAttributes final
|
||||
{
|
||||
struct ProcThreadAttributeListDeleter
|
||||
{
|
||||
void operator()(LPPROC_THREAD_ATTRIBUTE_LIST aList)
|
||||
{
|
||||
::DeleteProcThreadAttributeList(aList);
|
||||
delete[] reinterpret_cast<char*>(aList);
|
||||
}
|
||||
};
|
||||
|
||||
using ProcThreadAttributeListPtr =
|
||||
UniquePtr<_PROC_THREAD_ATTRIBUTE_LIST, ProcThreadAttributeListDeleter>;
|
||||
|
||||
public:
|
||||
ProcThreadAttributes()
|
||||
: mMitigationPolicies(0)
|
||||
{
|
||||
}
|
||||
|
||||
~ProcThreadAttributes() = default;
|
||||
|
||||
ProcThreadAttributes(const ProcThreadAttributes&) = delete;
|
||||
ProcThreadAttributes(ProcThreadAttributes&&) = delete;
|
||||
ProcThreadAttributes& operator=(const ProcThreadAttributes&) = delete;
|
||||
ProcThreadAttributes& operator=(ProcThreadAttributes&&) = delete;
|
||||
|
||||
void AddMitigationPolicy(DWORD64 aPolicy)
|
||||
{
|
||||
mMitigationPolicies |= aPolicy;
|
||||
}
|
||||
|
||||
bool AddInheritableHandle(HANDLE aHandle)
|
||||
{
|
||||
return mInheritableHandles.append(aHandle);
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
bool AddInheritableHandles(HANDLE (&aHandles)[N])
|
||||
{
|
||||
return mInheritableHandles.append(aHandles, N);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Some(false) if the STARTUPINFOEXW::lpAttributeList was set to null
|
||||
* as expected based on the state of |this|;
|
||||
* Some(true) if the STARTUPINFOEXW::lpAttributeList was set to
|
||||
* non-null;
|
||||
* Nothing() if something went wrong in the assignment and we should
|
||||
* not proceed.
|
||||
*/
|
||||
Maybe<bool> AssignTo(STARTUPINFOEXW& aSiex)
|
||||
{
|
||||
ZeroMemory(&aSiex, sizeof(STARTUPINFOEXW));
|
||||
|
||||
// We'll set the size to sizeof(STARTUPINFOW) until we determine whether the
|
||||
// extended fields will be used.
|
||||
aSiex.StartupInfo.cb = sizeof(STARTUPINFOW);
|
||||
|
||||
DWORD numAttributes = 0;
|
||||
if (mMitigationPolicies) {
|
||||
++numAttributes;
|
||||
}
|
||||
|
||||
if (!mInheritableHandles.empty()) {
|
||||
++numAttributes;
|
||||
}
|
||||
|
||||
if (!numAttributes) {
|
||||
return Some(false);
|
||||
}
|
||||
|
||||
SIZE_T listSize = 0;
|
||||
if (!::InitializeProcThreadAttributeList(nullptr, numAttributes, 0,
|
||||
&listSize) &&
|
||||
::GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
auto buf = MakeUnique<char[]>(listSize);
|
||||
|
||||
LPPROC_THREAD_ATTRIBUTE_LIST tmpList =
|
||||
reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(buf.get());
|
||||
|
||||
if (!::InitializeProcThreadAttributeList(tmpList, numAttributes, 0,
|
||||
&listSize)) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
// Transfer buf to a ProcThreadAttributeListPtr - now that the list is
|
||||
// initialized, we are no longer dealing with a plain old char array. We
|
||||
// must now deinitialize the attribute list before deallocating the
|
||||
// underlying buffer.
|
||||
ProcThreadAttributeListPtr
|
||||
attrList(reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(buf.release()));
|
||||
|
||||
if (mMitigationPolicies) {
|
||||
if (!::UpdateProcThreadAttribute(attrList.get(), 0,
|
||||
PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY,
|
||||
&mMitigationPolicies,
|
||||
sizeof(mMitigationPolicies), nullptr,
|
||||
nullptr)) {
|
||||
return Nothing();
|
||||
}
|
||||
}
|
||||
|
||||
if (!mInheritableHandles.empty()) {
|
||||
if (!::UpdateProcThreadAttribute(attrList.get(), 0,
|
||||
PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
|
||||
mInheritableHandles.begin(),
|
||||
mInheritableHandles.length() * sizeof(HANDLE),
|
||||
nullptr, nullptr)) {
|
||||
return Nothing();
|
||||
}
|
||||
}
|
||||
|
||||
mAttrList = Move(attrList);
|
||||
aSiex.lpAttributeList = mAttrList.get();
|
||||
aSiex.StartupInfo.cb = sizeof(STARTUPINFOEXW);
|
||||
return Some(true);
|
||||
}
|
||||
|
||||
private:
|
||||
static const uint32_t kNumInline = 3; // Inline storage for the std handles
|
||||
|
||||
DWORD64 mMitigationPolicies;
|
||||
Vector<HANDLE, kNumInline> mInheritableHandles;
|
||||
ProcThreadAttributeListPtr mAttrList;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_ProcThreadAttributes_h
|
||||
|
|
@ -62,6 +62,9 @@ if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'):
|
|||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
RCINCLUDE = 'splash.rc'
|
||||
DEFINES['MOZ_PHOENIX'] = True
|
||||
SOURCES += [
|
||||
'LauncherProcessWin.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_ARCH'] == 'WINNT':
|
||||
# For sandbox includes and the include dependencies those have
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include "nsIFile.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
#include "LauncherProcessWin.h"
|
||||
|
||||
#define XRE_WANT_ENVIRON
|
||||
#define strcasecmp _stricmp
|
||||
#ifdef MOZ_SANDBOX
|
||||
|
|
|
@ -8,7 +8,14 @@
|
|||
PR_SetEnv requires its argument to be leaked, but does not appear on stacks. (See bug 793534.)
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:_ZL9SaveToEnvPKc
|
||||
fun:_ZN7mozilla9SaveToEnvEPKc
|
||||
...
|
||||
}
|
||||
{
|
||||
PR_SetEnv requires its argument to be leaked, but does not appear on stacks. (See bug 793534.)
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:SaveToEnv
|
||||
...
|
||||
}
|
||||
{
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
This is the debugger.html project output.
|
||||
See https://github.com/devtools-html/debugger.html
|
||||
|
||||
Version 45.1
|
||||
Version 46
|
||||
|
||||
Comparison: https://github.com/devtools-html/debugger.html/compare/release-45...release-45.1
|
||||
Comparison: https://github.com/devtools-html/debugger.html/compare/release-45.1...release-46
|
||||
|
||||
Packages:
|
||||
- babel-plugin-transform-es2015-modules-commonjs @6.26.0
|
||||
- babel-plugin-transform-es2015-modules-commonjs @6.26.2
|
||||
- babel-preset-react @6.24.1
|
||||
- react @16.2.0
|
||||
- react-dom @16.2.0
|
||||
|
|
|
@ -1965,18 +1965,6 @@ html .toggle-button.end.vertical svg {
|
|||
--comment-node-color: var(--theme-comment);
|
||||
}
|
||||
|
||||
.theme-firebug {
|
||||
--number-color: #000088;
|
||||
--string-color: #FF0000;
|
||||
--null-color: #787878;
|
||||
--object-color: DarkGreen;
|
||||
--caption-color: #444444;
|
||||
--location-color: #555555;
|
||||
--source-link-color: blue;
|
||||
--node-color: rgb(0, 0, 136);
|
||||
--reference-color: rgb(102, 102, 255);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
.inline {
|
||||
|
@ -2012,7 +2000,8 @@ html .toggle-button.end.vertical svg {
|
|||
color: var(--string-color);
|
||||
}
|
||||
|
||||
.objectBox-string a, .objectBox-string a:visited {
|
||||
.objectBox-string a,
|
||||
.objectBox-string a:visited {
|
||||
color: currentColor;
|
||||
text-decoration: none;
|
||||
font-style: italic;
|
||||
|
@ -2205,7 +2194,7 @@ button.open-inspector {
|
|||
display: inline-block;
|
||||
background-color: var(--comment-node-color);
|
||||
height: 16px;
|
||||
margin-left: .25em;
|
||||
margin-left: 0.25em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
|
@ -2223,7 +2212,7 @@ button.jump-definition {
|
|||
display: inline-block;
|
||||
background-color: var(--comment-node-color);
|
||||
height: 16px;
|
||||
margin-left: .25em;
|
||||
margin-left: 0.25em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
|
@ -2278,6 +2267,16 @@ button.jump-definition {
|
|||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* Focused styles */
|
||||
.tree.object-inspector .tree-node.focused * {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.tree-node.focused button.jump-definition,
|
||||
.tree-node.focused button.open-inspector {
|
||||
background-color: currentColor;
|
||||
}
|
||||
/* 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/>. */
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -12,10 +12,13 @@ add_task(async function() {
|
|||
await waitForPaused(dbg);
|
||||
await waitForLoadedSource(dbg, "switching-02");
|
||||
|
||||
// MAP_FRAMES triggers a new Scopes panel render cycle, which introduces
|
||||
// a race condition with the click event on the foo node.
|
||||
await waitForDispatch(dbg, "MAP_FRAMES");
|
||||
|
||||
is(getLabel(dbg, 1), "secondCall");
|
||||
is(getLabel(dbg, 2), "<this>");
|
||||
is(getLabel(dbg, 4), "foo()");
|
||||
|
||||
await toggleScopeNode(dbg, 4);
|
||||
is(getLabel(dbg, 5), "arguments");
|
||||
|
||||
|
|
|
@ -56,6 +56,5 @@ add_task(async function() {
|
|||
|
||||
// selecting another source keeps search open
|
||||
await selectSource(dbg, "simple2");
|
||||
pressKey(dbg, "Enter");
|
||||
is(state.posFrom.line, 0);
|
||||
ok(findElement(dbg, "searchField"), "Search field is still visible");
|
||||
});
|
||||
|
|
|
@ -1073,7 +1073,8 @@ const selectors = {
|
|||
outlineItem: i =>
|
||||
`.outline-list__element:nth-child(${i}) .function-signature`,
|
||||
outlineItems: ".outline-list__element",
|
||||
conditionalPanelInput: ".conditional-breakpoint-panel input"
|
||||
conditionalPanelInput: ".conditional-breakpoint-panel input",
|
||||
searchField: ".search-field",
|
||||
};
|
||||
|
||||
function getSelector(elementName, ...args) {
|
||||
|
|
|
@ -1,3 +1,87 @@
|
|||
/* 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/. */
|
||||
|
||||
.tree {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.tree.inline {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.tree.nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tree.noselect {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
-o-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.tree .tree-node {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.tree .tree-node:not(.focused):hover {
|
||||
background-color: var(--theme-selection-background-hover);
|
||||
}
|
||||
|
||||
.tree-indent {
|
||||
display: inline-block;
|
||||
width: 12px;
|
||||
margin-inline-start: 5px;
|
||||
border-inline-start: 1px solid #A2D1FF;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Align with expandables siblings (where we have the arrow) */
|
||||
.tree-node[data-expandable="false"] .tree-indent:last-of-type {
|
||||
margin-inline-end: 15px;
|
||||
}
|
||||
|
||||
/* For non expandable root nodes, we don't have .tree-indent elements, so we declare
|
||||
the margin on the start of the node */
|
||||
.tree-node[data-expandable="false"][aria-level="1"] {
|
||||
padding-inline-start: 15px
|
||||
}
|
||||
|
||||
.tree .tree-node[data-expandable="true"] {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.tree-node img.arrow {
|
||||
mask: url("chrome://devtools/skin/images/devtools-components/arrow.svg") no-repeat;
|
||||
mask-size: 100%;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
margin-inline-start: 1px;
|
||||
margin-inline-end: 4px;
|
||||
background-color: var(--theme-splitter-color, #9B9B9B);
|
||||
transform: rotate(-90deg);
|
||||
transition: transform 0.125s ease;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .tree-node img.arrow {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.tree-node img.arrow.expanded.expanded {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
.tree .tree-node.focused {
|
||||
color: white;
|
||||
background-color: var(--theme-selection-background, #0a84ff);
|
||||
}
|
||||
|
||||
.tree-node.focused img.arrow {
|
||||
background-color: currentColor;
|
||||
}
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* 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
|
||||
|
@ -52,7 +136,8 @@
|
|||
color: var(--string-color);
|
||||
}
|
||||
|
||||
.objectBox-string a, .objectBox-string a:visited {
|
||||
.objectBox-string a,
|
||||
.objectBox-string a:visited {
|
||||
color: currentColor;
|
||||
text-decoration: none;
|
||||
font-style: italic;
|
||||
|
@ -78,6 +163,12 @@
|
|||
margin-top: 3px;
|
||||
}
|
||||
|
||||
.objectBox-stackTrace-fn::before {
|
||||
content: "\3BB"; /* The "lambda" symbol */
|
||||
display: inline-block;
|
||||
margin: 0 0.3em;
|
||||
}
|
||||
|
||||
.objectBox-stackTrace-fn {
|
||||
color: var(--console-output-color);
|
||||
padding-inline-start: 17px;
|
||||
|
@ -239,7 +330,7 @@ button.open-inspector {
|
|||
display: inline-block;
|
||||
background-color: var(--comment-node-color);
|
||||
height: 16px;
|
||||
margin-left: .25em;
|
||||
margin-left: 0.25em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
|
@ -257,7 +348,7 @@ button.jump-definition {
|
|||
display: inline-block;
|
||||
background-color: var(--comment-node-color);
|
||||
height: 16px;
|
||||
margin-left: .25em;
|
||||
margin-left: 0.25em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
|
@ -274,90 +365,6 @@ button.jump-definition {
|
|||
* 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/. */
|
||||
|
||||
.tree {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.tree.inline {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.tree.nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tree.noselect {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
-o-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.tree .tree-node {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.tree .tree-node:not(.focused):hover {
|
||||
background-color: var(--theme-selection-background-hover);
|
||||
}
|
||||
|
||||
.tree-indent {
|
||||
display: inline-block;
|
||||
width: 12px;
|
||||
margin-inline-start: 5px;
|
||||
border-inline-start: 1px solid #A2D1FF;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Align with expandables siblings (where we have the arrow) */
|
||||
.tree-node[data-expandable="false"] .tree-indent:last-of-type {
|
||||
margin-inline-end: 15px;
|
||||
}
|
||||
|
||||
/* For non expandable root nodes, we don't have .tree-indent elements, so we declare
|
||||
the margin on the start of the node */
|
||||
.tree-node[data-expandable="false"][aria-level="1"] {
|
||||
padding-inline-start: 15px
|
||||
}
|
||||
|
||||
.tree .tree-node[data-expandable="true"] {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.tree-node img.arrow {
|
||||
mask: url("chrome://devtools/skin/images/devtools-components/arrow.svg") no-repeat;
|
||||
mask-size: 100%;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
margin-inline-start: 1px;
|
||||
margin-inline-end: 4px;
|
||||
background-color: var(--theme-splitter-color, #9B9B9B);
|
||||
transform: rotate(-90deg);
|
||||
transition: transform 0.125s ease;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .tree-node img.arrow {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.tree-node img.arrow.expanded.expanded {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
.tree .tree-node.focused {
|
||||
color: white;
|
||||
background-color: var(--theme-selection-background, #0a84ff);
|
||||
}
|
||||
|
||||
.tree-node.focused img.arrow {
|
||||
background-color: currentColor;
|
||||
}
|
||||
/* 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/. */
|
||||
|
||||
.tree.object-inspector .node.object-node {
|
||||
display: inline-block;
|
||||
}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -7,7 +7,7 @@
|
|||
var a = factory();
|
||||
for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
|
||||
}
|
||||
})(this, function() {
|
||||
})(typeof self !== 'undefined' ? self : this, function() {
|
||||
return /******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
|
@ -67,158 +67,22 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
||||
/******/
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
/******/ __webpack_require__.p = "/assets/build";
|
||||
/******/
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(__webpack_require__.s = 15);
|
||||
/******/ return __webpack_require__(__webpack_require__.s = 3646);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ([
|
||||
/* 0 */
|
||||
/***/ (function(module, exports) {
|
||||
/******/ ({
|
||||
|
||||
var charenc = {
|
||||
// UTF-8 encoding
|
||||
utf8: {
|
||||
// Convert a string to a byte array
|
||||
stringToBytes: function(str) {
|
||||
return charenc.bin.stringToBytes(unescape(encodeURIComponent(str)));
|
||||
},
|
||||
|
||||
// Convert a byte array to a string
|
||||
bytesToString: function(bytes) {
|
||||
return decodeURIComponent(escape(charenc.bin.bytesToString(bytes)));
|
||||
}
|
||||
},
|
||||
|
||||
// Binary encoding
|
||||
bin: {
|
||||
// Convert a string to a byte array
|
||||
stringToBytes: function(str) {
|
||||
for (var bytes = [], i = 0; i < str.length; i++)
|
||||
bytes.push(str.charCodeAt(i) & 0xFF);
|
||||
return bytes;
|
||||
},
|
||||
|
||||
// Convert a byte array to a string
|
||||
bytesToString: function(bytes) {
|
||||
for (var str = [], i = 0; i < bytes.length; i++)
|
||||
str.push(String.fromCharCode(bytes[i]));
|
||||
return str.join('');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = charenc;
|
||||
|
||||
|
||||
/***/ }),
|
||||
/* 1 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
/* 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/. */
|
||||
|
||||
const networkRequest = __webpack_require__(7);
|
||||
const workerUtils = __webpack_require__(8);
|
||||
|
||||
module.exports = {
|
||||
networkRequest,
|
||||
workerUtils
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
/* 2 */,
|
||||
/* 3 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
/* 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/. */
|
||||
|
||||
const md5 = __webpack_require__(4);
|
||||
|
||||
function originalToGeneratedId(originalId) {
|
||||
const match = originalId.match(/(.*)\/originalSource/);
|
||||
return match ? match[1] : "";
|
||||
}
|
||||
|
||||
function generatedToOriginalId(generatedId, url) {
|
||||
return `${generatedId}/originalSource-${md5(url)}`;
|
||||
}
|
||||
|
||||
function isOriginalId(id) {
|
||||
return !!id.match(/\/originalSource/);
|
||||
}
|
||||
|
||||
function isGeneratedId(id) {
|
||||
return !isOriginalId(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trims the query part or reference identifier of a URL string, if necessary.
|
||||
*/
|
||||
function trimUrlQuery(url) {
|
||||
let length = url.length;
|
||||
let q1 = url.indexOf("?");
|
||||
let q2 = url.indexOf("&");
|
||||
let q3 = url.indexOf("#");
|
||||
let q = Math.min(q1 != -1 ? q1 : length, q2 != -1 ? q2 : length, q3 != -1 ? q3 : length);
|
||||
|
||||
return url.slice(0, q);
|
||||
}
|
||||
|
||||
// Map suffix to content type.
|
||||
const contentMap = {
|
||||
"js": "text/javascript",
|
||||
"jsm": "text/javascript",
|
||||
"mjs": "text/javascript",
|
||||
"ts": "text/typescript",
|
||||
"tsx": "text/typescript-jsx",
|
||||
"jsx": "text/jsx",
|
||||
"coffee": "text/coffeescript",
|
||||
"elm": "text/elm",
|
||||
"cljs": "text/x-clojure"
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the content type for the specified URL. If no specific
|
||||
* content type can be determined, "text/plain" is returned.
|
||||
*
|
||||
* @return String
|
||||
* The content type.
|
||||
*/
|
||||
function getContentType(url) {
|
||||
url = trimUrlQuery(url);
|
||||
let dot = url.lastIndexOf(".");
|
||||
if (dot >= 0) {
|
||||
let name = url.substring(dot + 1);
|
||||
if (name in contentMap) {
|
||||
return contentMap[name];
|
||||
}
|
||||
}
|
||||
return "text/plain";
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
originalToGeneratedId,
|
||||
generatedToOriginalId,
|
||||
isOriginalId,
|
||||
isGeneratedId,
|
||||
getContentType,
|
||||
contentMapForTesting: contentMap
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
/* 4 */
|
||||
/***/ 248:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
(function(){
|
||||
var crypt = __webpack_require__(5),
|
||||
utf8 = __webpack_require__(0).utf8,
|
||||
isBuffer = __webpack_require__(6),
|
||||
bin = __webpack_require__(0).bin,
|
||||
var crypt = __webpack_require__(249),
|
||||
utf8 = __webpack_require__(250).utf8,
|
||||
isBuffer = __webpack_require__(251),
|
||||
bin = __webpack_require__(250).bin,
|
||||
|
||||
// The core
|
||||
md5 = function (message, options) {
|
||||
|
@ -377,7 +241,8 @@ module.exports = {
|
|||
|
||||
|
||||
/***/ }),
|
||||
/* 5 */
|
||||
|
||||
/***/ 249:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
(function() {
|
||||
|
@ -479,13 +344,54 @@ module.exports = {
|
|||
|
||||
|
||||
/***/ }),
|
||||
/* 6 */
|
||||
|
||||
/***/ 250:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
var charenc = {
|
||||
// UTF-8 encoding
|
||||
utf8: {
|
||||
// Convert a string to a byte array
|
||||
stringToBytes: function(str) {
|
||||
return charenc.bin.stringToBytes(unescape(encodeURIComponent(str)));
|
||||
},
|
||||
|
||||
// Convert a byte array to a string
|
||||
bytesToString: function(bytes) {
|
||||
return decodeURIComponent(escape(charenc.bin.bytesToString(bytes)));
|
||||
}
|
||||
},
|
||||
|
||||
// Binary encoding
|
||||
bin: {
|
||||
// Convert a string to a byte array
|
||||
stringToBytes: function(str) {
|
||||
for (var bytes = [], i = 0; i < str.length; i++)
|
||||
bytes.push(str.charCodeAt(i) & 0xFF);
|
||||
return bytes;
|
||||
},
|
||||
|
||||
// Convert a byte array to a string
|
||||
bytesToString: function(bytes) {
|
||||
for (var str = [], i = 0; i < bytes.length; i++)
|
||||
str.push(String.fromCharCode(bytes[i]));
|
||||
return str.join('');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = charenc;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 251:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
/*!
|
||||
* Determine if an object is a Buffer
|
||||
*
|
||||
* @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
|
||||
* @author Feross Aboukhadijeh <https://feross.org>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
|
@ -506,13 +412,177 @@ function isSlowBuffer (obj) {
|
|||
|
||||
|
||||
/***/ }),
|
||||
/* 7 */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
/***/ 3646:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
/* 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/>. */
|
||||
|
||||
const {
|
||||
originalToGeneratedId,
|
||||
generatedToOriginalId,
|
||||
isGeneratedId,
|
||||
isOriginalId
|
||||
} = __webpack_require__(3652);
|
||||
|
||||
const {
|
||||
workerUtils: { WorkerDispatcher }
|
||||
} = __webpack_require__(3651);
|
||||
|
||||
const dispatcher = new WorkerDispatcher();
|
||||
|
||||
const getOriginalURLs = dispatcher.task("getOriginalURLs");
|
||||
const getGeneratedRanges = dispatcher.task("getGeneratedRanges", {
|
||||
queue: true
|
||||
});
|
||||
const getGeneratedLocation = dispatcher.task("getGeneratedLocation", {
|
||||
queue: true
|
||||
});
|
||||
const getAllGeneratedLocations = dispatcher.task("getAllGeneratedLocations", {
|
||||
queue: true
|
||||
});
|
||||
const getOriginalLocation = dispatcher.task("getOriginalLocation");
|
||||
const getLocationScopes = dispatcher.task("getLocationScopes");
|
||||
const getOriginalSourceText = dispatcher.task("getOriginalSourceText");
|
||||
const applySourceMap = dispatcher.task("applySourceMap");
|
||||
const clearSourceMaps = dispatcher.task("clearSourceMaps");
|
||||
const hasMappedSource = dispatcher.task("hasMappedSource");
|
||||
|
||||
module.exports = {
|
||||
originalToGeneratedId,
|
||||
generatedToOriginalId,
|
||||
isGeneratedId,
|
||||
isOriginalId,
|
||||
hasMappedSource,
|
||||
getOriginalURLs,
|
||||
getGeneratedRanges,
|
||||
getGeneratedLocation,
|
||||
getAllGeneratedLocations,
|
||||
getOriginalLocation,
|
||||
getLocationScopes,
|
||||
getOriginalSourceText,
|
||||
applySourceMap,
|
||||
clearSourceMaps,
|
||||
startSourceMapWorker: dispatcher.start.bind(dispatcher),
|
||||
stopSourceMapWorker: dispatcher.stop.bind(dispatcher)
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 3651:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
/* 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/. */
|
||||
|
||||
const networkRequest = __webpack_require__(3653);
|
||||
const workerUtils = __webpack_require__(3654);
|
||||
|
||||
module.exports = {
|
||||
networkRequest,
|
||||
workerUtils
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 3652:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
/* 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/>. */
|
||||
|
||||
const md5 = __webpack_require__(248);
|
||||
|
||||
function originalToGeneratedId(originalId) {
|
||||
const match = originalId.match(/(.*)\/originalSource/);
|
||||
return match ? match[1] : "";
|
||||
}
|
||||
|
||||
function generatedToOriginalId(generatedId, url) {
|
||||
return `${generatedId}/originalSource-${md5(url)}`;
|
||||
}
|
||||
|
||||
function isOriginalId(id) {
|
||||
return !!id.match(/\/originalSource/);
|
||||
}
|
||||
|
||||
function isGeneratedId(id) {
|
||||
return !isOriginalId(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trims the query part or reference identifier of a URL string, if necessary.
|
||||
*/
|
||||
function trimUrlQuery(url) {
|
||||
const length = url.length;
|
||||
const q1 = url.indexOf("?");
|
||||
const q2 = url.indexOf("&");
|
||||
const q3 = url.indexOf("#");
|
||||
const q = Math.min(q1 != -1 ? q1 : length, q2 != -1 ? q2 : length, q3 != -1 ? q3 : length);
|
||||
|
||||
return url.slice(0, q);
|
||||
}
|
||||
|
||||
// Map suffix to content type.
|
||||
const contentMap = {
|
||||
js: "text/javascript",
|
||||
jsm: "text/javascript",
|
||||
mjs: "text/javascript",
|
||||
ts: "text/typescript",
|
||||
tsx: "text/typescript-jsx",
|
||||
jsx: "text/jsx",
|
||||
coffee: "text/coffeescript",
|
||||
elm: "text/elm",
|
||||
cljs: "text/x-clojure"
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the content type for the specified URL. If no specific
|
||||
* content type can be determined, "text/plain" is returned.
|
||||
*
|
||||
* @return String
|
||||
* The content type.
|
||||
*/
|
||||
function getContentType(url) {
|
||||
url = trimUrlQuery(url);
|
||||
const dot = url.lastIndexOf(".");
|
||||
if (dot >= 0) {
|
||||
const name = url.substring(dot + 1);
|
||||
if (name in contentMap) {
|
||||
return contentMap[name];
|
||||
}
|
||||
}
|
||||
return "text/plain";
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
originalToGeneratedId,
|
||||
generatedToOriginalId,
|
||||
isOriginalId,
|
||||
isGeneratedId,
|
||||
getContentType,
|
||||
contentMapForTesting: contentMap
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 3653:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
/* 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/>. */
|
||||
|
||||
function networkRequest(url, opts) {
|
||||
return fetch(url, {
|
||||
cache: opts.loadFromCache ? "default" : "no-cache"
|
||||
|
@ -527,7 +597,8 @@ function networkRequest(url, opts) {
|
|||
module.exports = networkRequest;
|
||||
|
||||
/***/ }),
|
||||
/* 8 */
|
||||
|
||||
/***/ 3654:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
|
||||
|
@ -537,7 +608,7 @@ function WorkerDispatcher() {
|
|||
this.worker = null;
|
||||
} /* 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/. */
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
WorkerDispatcher.prototype = {
|
||||
start(url) {
|
||||
|
@ -577,7 +648,11 @@ WorkerDispatcher.prototype = {
|
|||
calls.length = 0;
|
||||
|
||||
const id = this.msgId++;
|
||||
this.worker.postMessage({ id, method, calls: items.map(item => item[0]) });
|
||||
this.worker.postMessage({
|
||||
id,
|
||||
method,
|
||||
calls: items.map(item => item[0])
|
||||
});
|
||||
|
||||
const listener = ({ data: result }) => {
|
||||
if (result.id !== id) {
|
||||
|
@ -620,9 +695,8 @@ function workerHandler(publicInterface) {
|
|||
// Error can't be sent via postMessage, so be sure to
|
||||
// convert to string.
|
||||
err => ({ error: err.toString() }));
|
||||
} else {
|
||||
return { response };
|
||||
}
|
||||
return { response };
|
||||
} catch (error) {
|
||||
// Error can't be sent via postMessage, so be sure to convert to
|
||||
// string.
|
||||
|
@ -639,7 +713,7 @@ function streamingWorkerHandler(publicInterface, { timeout = 100 } = {}, worker
|
|||
var _ref = _asyncToGenerator(function* (id, tasks) {
|
||||
let isWorking = true;
|
||||
|
||||
const intervalId = setTimeout(function () {
|
||||
const timeoutId = setTimeout(function () {
|
||||
isWorking = false;
|
||||
}, timeout);
|
||||
|
||||
|
@ -650,7 +724,7 @@ function streamingWorkerHandler(publicInterface, { timeout = 100 } = {}, worker
|
|||
results.push(result);
|
||||
}
|
||||
worker.postMessage({ id, status: "pending", data: results });
|
||||
clearInterval(intervalId);
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
if (tasks.length !== 0) {
|
||||
yield streamingWorker(id, tasks);
|
||||
|
@ -692,61 +766,7 @@ module.exports = {
|
|||
streamingWorkerHandler
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
/* 9 */,
|
||||
/* 10 */,
|
||||
/* 11 */,
|
||||
/* 12 */,
|
||||
/* 13 */,
|
||||
/* 14 */,
|
||||
/* 15 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
/* 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/. */
|
||||
|
||||
const {
|
||||
originalToGeneratedId,
|
||||
generatedToOriginalId,
|
||||
isGeneratedId,
|
||||
isOriginalId
|
||||
} = __webpack_require__(3);
|
||||
|
||||
const { workerUtils: { WorkerDispatcher } } = __webpack_require__(1);
|
||||
|
||||
const dispatcher = new WorkerDispatcher();
|
||||
|
||||
const getOriginalURLs = dispatcher.task("getOriginalURLs");
|
||||
const getGeneratedRanges = dispatcher.task("getGeneratedRanges", { queue: true });
|
||||
const getGeneratedLocation = dispatcher.task("getGeneratedLocation", { queue: true });
|
||||
const getAllGeneratedLocations = dispatcher.task("getAllGeneratedLocations", { queue: true });
|
||||
const getOriginalLocation = dispatcher.task("getOriginalLocation");
|
||||
const getLocationScopes = dispatcher.task("getLocationScopes");
|
||||
const getOriginalSourceText = dispatcher.task("getOriginalSourceText");
|
||||
const applySourceMap = dispatcher.task("applySourceMap");
|
||||
const clearSourceMaps = dispatcher.task("clearSourceMaps");
|
||||
const hasMappedSource = dispatcher.task("hasMappedSource");
|
||||
|
||||
module.exports = {
|
||||
originalToGeneratedId,
|
||||
generatedToOriginalId,
|
||||
isGeneratedId,
|
||||
isOriginalId,
|
||||
hasMappedSource,
|
||||
getOriginalURLs,
|
||||
getGeneratedRanges,
|
||||
getGeneratedLocation,
|
||||
getAllGeneratedLocations,
|
||||
getOriginalLocation,
|
||||
getLocationScopes,
|
||||
getOriginalSourceText,
|
||||
applySourceMap,
|
||||
clearSourceMaps,
|
||||
startSourceMapWorker: dispatcher.start.bind(dispatcher),
|
||||
stopSourceMapWorker: dispatcher.stop.bind(dispatcher)
|
||||
};
|
||||
|
||||
/***/ })
|
||||
/******/ ]);
|
||||
|
||||
/******/ });
|
||||
});
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -606,7 +606,7 @@ static struct lutmABType *read_tag_lutmABType(struct mem_source *src, struct tag
|
|||
// 24bits * 3 won't overflow either
|
||||
clut_size = clut_size * num_out_channels;
|
||||
|
||||
if (clut_size > MAX_CLUT_SIZE)
|
||||
if (clut_size == 0 || clut_size > MAX_CLUT_SIZE)
|
||||
return NULL;
|
||||
|
||||
lut = malloc(sizeof(struct lutmABType) + (clut_size) * sizeof(float));
|
||||
|
|
|
@ -2353,11 +2353,6 @@ extern "C" {
|
|||
-> bool;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_shutdown_log_for_gpu_process() {
|
||||
// log does not support shutdown
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_root_scroll_node_id() -> usize {
|
||||
// The PipelineId doesn't matter here, since we just want the numeric part of the id
|
||||
|
|
|
@ -1587,10 +1587,6 @@ void wr_set_item_tag(WrState *aState,
|
|||
uint16_t aHitInfo)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE
|
||||
void wr_shutdown_log_for_gpu_process()
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE
|
||||
void wr_state_delete(WrState *aState)
|
||||
WR_DESTRUCTOR_SAFE_FUNC;
|
||||
|
|
|
@ -979,6 +979,10 @@ TraceParser(JSTracer* trc, AutoGCRooter* parser)
|
|||
bool
|
||||
ParserBase::setSourceMapInfo()
|
||||
{
|
||||
// Not all clients initialize ss. Can't update info to an object that isn't there.
|
||||
if (!ss)
|
||||
return true;
|
||||
|
||||
if (anyChars.hasDisplayURL()) {
|
||||
if (!ss->setDisplayURL(context, anyChars.displayURL()))
|
||||
return false;
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.mozilla.gecko.AppConstants;
|
|||
import org.mozilla.gecko.dlc.catalog.DownloadContent;
|
||||
import org.mozilla.gecko.dlc.catalog.DownloadContentBuilder;
|
||||
import org.mozilla.gecko.dlc.catalog.DownloadContentCatalog;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
|
@ -223,7 +224,7 @@ public class TestDownloadAction {
|
|||
verify(connection).getInputStream();
|
||||
verify(connection).setRequestProperty("Range", "bytes=1337-");
|
||||
|
||||
Assert.assertEquals("HelloWorld", new String(outputStream.toByteArray(), "UTF-8"));
|
||||
Assert.assertEquals("HelloWorld", new String(outputStream.toByteArray(), StringUtils.UTF_8));
|
||||
|
||||
verify(action).openFile(eq(temporaryFile), eq(true));
|
||||
verify(catalog).markAsDownloaded(content);
|
||||
|
@ -635,7 +636,7 @@ public class TestDownloadAction {
|
|||
HttpURLConnection connection = mock(HttpURLConnection.class);
|
||||
|
||||
doReturn(statusCode).when(connection).getResponseCode();
|
||||
doReturn(new ByteArrayInputStream(content.getBytes("UTF-8"))).when(connection).getInputStream();
|
||||
doReturn(new ByteArrayInputStream(content.getBytes(StringUtils.UTF_8))).when(connection).getInputStream();
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import org.junit.Assume;
|
|||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mozilla.gecko.AppConstants;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
|
@ -37,7 +38,7 @@ public class TestDownloadContentCatalog {
|
|||
@Test
|
||||
public void testUntouchedCatalogHasNotChangedAndWillNotBePersisted() throws Exception {
|
||||
AtomicFile file = mock(AtomicFile.class);
|
||||
doReturn("{content:[]}".getBytes("UTF-8")).when(file).readFully();
|
||||
doReturn("{content:[]}".getBytes(StringUtils.UTF_8)).when(file).readFully();
|
||||
|
||||
DownloadContentCatalog catalog = spy(new DownloadContentCatalog(file));
|
||||
catalog.loadFromDisk();
|
||||
|
|
|
@ -7,6 +7,7 @@ import org.junit.Assert;
|
|||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -57,7 +58,7 @@ public class TestPushState {
|
|||
FileOutputStream fos = null;
|
||||
try {
|
||||
fos = new FileOutputStream(file);
|
||||
fos.write("}".getBytes("UTF-8"));
|
||||
fos.write("}".getBytes(StringUtils.UTF_8));
|
||||
} finally {
|
||||
if (fos != null) {
|
||||
fos.close();
|
||||
|
|
|
@ -43,6 +43,7 @@ import org.mozilla.gecko.sync.SynchronizerConfiguration;
|
|||
import org.mozilla.gecko.sync.Utils;
|
||||
import org.mozilla.gecko.sync.repositories.android.RepoUtils;
|
||||
import org.mozilla.gecko.util.FileUtils;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
|
||||
import static org.mozilla.gecko.db.DBUtils.qualifyColumn;
|
||||
|
||||
|
@ -1782,18 +1783,13 @@ public class BrowserDatabaseHelper extends SQLiteOpenHelper {
|
|||
@RobocopTarget
|
||||
public static String getReaderCacheFileNameForURL(String url) {
|
||||
try {
|
||||
// On KitKat and above we can use java.nio.charset.StandardCharsets.UTF_8 in place of "UTF8"
|
||||
// which avoids having to handle UnsupportedCodingException
|
||||
byte[] utf8 = url.getBytes("UTF8");
|
||||
byte[] utf8 = url.getBytes(StringUtils.UTF_8);
|
||||
|
||||
final MessageDigest digester = MessageDigest.getInstance("MD5");
|
||||
byte[] hash = digester.digest(utf8);
|
||||
|
||||
final String hashString = new Base32().encodeAsString(hash);
|
||||
return hashString.substring(0, hashString.indexOf('=')) + ".json";
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
// This should never happen
|
||||
throw new IllegalStateException("UTF8 encoding not available - can't process readercache filename");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
// This should also never happen
|
||||
throw new IllegalStateException("MD5 digester unavailable - can't process readercache filename");
|
||||
|
|
|
@ -498,7 +498,7 @@ public class LoginsProvider extends SharedBrowserDatabaseProvider {
|
|||
private String encrypt(@NonNull String initialValue) {
|
||||
try {
|
||||
final Cipher cipher = getCipher(Cipher.ENCRYPT_MODE);
|
||||
return Base64.encodeToString(cipher.doFinal(initialValue.getBytes("UTF-8")), Base64.URL_SAFE);
|
||||
return Base64.encodeToString(cipher.doFinal(initialValue.getBytes(StringUtils.UTF_8)), Base64.URL_SAFE);
|
||||
} catch (Exception e) {
|
||||
debug("encryption failed : " + e);
|
||||
throw new IllegalStateException("Logins encryption failed", e);
|
||||
|
@ -509,7 +509,7 @@ public class LoginsProvider extends SharedBrowserDatabaseProvider {
|
|||
try {
|
||||
final Cipher cipher = getCipher(Cipher.DECRYPT_MODE);
|
||||
return new String(cipher.doFinal(Base64.decode(
|
||||
initialValue.getBytes("UTF-8"), Base64.URL_SAFE)), StringUtils.UTF_8);
|
||||
initialValue.getBytes(StringUtils.UTF_8), Base64.URL_SAFE)), StringUtils.UTF_8);
|
||||
} catch (Exception e) {
|
||||
debug("Decryption failed : " + e);
|
||||
throw new IllegalStateException("Logins decryption failed", e);
|
||||
|
|
|
@ -14,12 +14,12 @@ import android.util.Log;
|
|||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -218,7 +218,7 @@ public class DownloadContentCatalog {
|
|||
JSONObject catalog;
|
||||
|
||||
synchronized (file) {
|
||||
catalog = new JSONObject(new String(file.readFully(), "UTF-8"));
|
||||
catalog = new JSONObject(new String(file.readFully(), StringUtils.UTF_8));
|
||||
}
|
||||
|
||||
JSONArray array = catalog.getJSONArray(JSON_KEY_CONTENT);
|
||||
|
@ -233,10 +233,6 @@ public class DownloadContentCatalog {
|
|||
Log.w(LOGTAG, "Unable to parse catalog JSON. Re-creating empty catalog.", e);
|
||||
loadedContent = new ArrayMap<>();
|
||||
hasCatalogChanged = true; // Indicate that we want to persist the new catalog
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
AssertionError error = new AssertionError("Should not happen: This device does not speak UTF-8");
|
||||
error.initCause(e);
|
||||
throw error;
|
||||
} catch (IOException e) {
|
||||
Log.d(LOGTAG, "Can't read catalog due to IOException", e);
|
||||
}
|
||||
|
@ -275,15 +271,11 @@ public class DownloadContentCatalog {
|
|||
JSONObject catalog = new JSONObject();
|
||||
catalog.put(JSON_KEY_CONTENT, array);
|
||||
|
||||
outputStream.write(catalog.toString().getBytes("UTF-8"));
|
||||
outputStream.write(catalog.toString().getBytes(StringUtils.UTF_8));
|
||||
|
||||
file.finishWrite(outputStream);
|
||||
|
||||
hasCatalogChanged = false;
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
AssertionError error = new AssertionError("Should not happen: This device does not speak UTF-8");
|
||||
error.initCause(e);
|
||||
throw error;
|
||||
} catch (IOException | JSONException e) {
|
||||
Log.e(LOGTAG, "IOException during writing catalog", e);
|
||||
|
||||
|
|
|
@ -19,12 +19,12 @@ import org.mozilla.gecko.icons.IconRequest;
|
|||
import org.mozilla.gecko.icons.IconResponse;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
import org.mozilla.gecko.util.IOUtils;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.MessageDigest;
|
||||
|
||||
/**
|
||||
|
@ -257,10 +257,10 @@ public class DiskStorage {
|
|||
return null;
|
||||
}
|
||||
|
||||
byte[] data = prefix.getBytes("UTF-8");
|
||||
byte[] data = prefix.getBytes(StringUtils.UTF_8);
|
||||
NativeCrypto.sha256update(ctx, data, data.length);
|
||||
|
||||
data = url.getBytes("UTF-8");
|
||||
data = url.getBytes(StringUtils.UTF_8);
|
||||
NativeCrypto.sha256update(ctx, data, data.length);
|
||||
return Utils.byte2Hex(NativeCrypto.sha256finalize(ctx));
|
||||
} catch (NoClassDefFoundError | ExceptionInInitializerError error) {
|
||||
|
@ -269,15 +269,13 @@ public class DiskStorage {
|
|||
// we will have a lot of other problems if we can't load libmozglue.so
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
||||
md.update(prefix.getBytes("UTF-8"));
|
||||
md.update(url.getBytes("UTF-8"));
|
||||
md.update(prefix.getBytes(StringUtils.UTF_8));
|
||||
md.update(url.getBytes(StringUtils.UTF_8));
|
||||
return Utils.byte2Hex(md.digest());
|
||||
} catch (Exception e) {
|
||||
// Just give up. And let everyone know.
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new AssertionError("Should not happen: Device does not understand UTF-8");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ import android.util.Log;
|
|||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
@ -46,7 +47,7 @@ public class PushState {
|
|||
file = new AtomicFile(new File(context.getApplicationInfo().dataDir, fileName));
|
||||
synchronized (file) {
|
||||
try {
|
||||
final String s = new String(file.readFully(), "UTF-8");
|
||||
final String s = new String(file.readFully(), StringUtils.UTF_8);
|
||||
final JSONObject temp = new JSONObject(s);
|
||||
if (temp.optLong("version", 0L) != VERSION) {
|
||||
throw new JSONException("Unknown version!");
|
||||
|
@ -91,7 +92,7 @@ public class PushState {
|
|||
FileOutputStream fileOutputStream = null;
|
||||
try {
|
||||
fileOutputStream = file.startWrite();
|
||||
fileOutputStream.write(toJSONObject().toString().getBytes("UTF-8"));
|
||||
fileOutputStream.write(toJSONObject().toString().getBytes(StringUtils.UTF_8));
|
||||
file.finishWrite(fileOutputStream);
|
||||
return true;
|
||||
} catch (JSONException | IOException e) {
|
||||
|
|
|
@ -79,6 +79,8 @@ class GeckoViewModule {
|
|||
}
|
||||
self.messageManager.removeMessageListener("GeckoView:ContentRegistered",
|
||||
listener);
|
||||
self.messageManager.sendAsyncMessage("GeckoView:UpdateSettings",
|
||||
self.settings);
|
||||
self._eventProxy.enableQueuing(false);
|
||||
self._eventProxy.dispatchQueuedEvents();
|
||||
});
|
||||
|
|
|
@ -6,6 +6,7 @@ package org.mozilla.gecko.background.fxa;
|
|||
|
||||
import org.mozilla.gecko.sync.ExtendedJSONObject;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
@ -25,7 +26,6 @@ public class FxAccount20CreateDelegate {
|
|||
* @param preVerified
|
||||
* true if account should be marked already verified; only effective
|
||||
* for non-production auth servers.
|
||||
* @throws UnsupportedEncodingException
|
||||
* @throws GeneralSecurityException
|
||||
*/
|
||||
public FxAccount20CreateDelegate(byte[] emailUTF8, byte[] quickStretchedPW, boolean preVerified) throws UnsupportedEncodingException, GeneralSecurityException {
|
||||
|
@ -34,19 +34,15 @@ public class FxAccount20CreateDelegate {
|
|||
this.preVerified = preVerified;
|
||||
}
|
||||
|
||||
public ExtendedJSONObject getCreateBody() throws FxAccountClientException {
|
||||
public ExtendedJSONObject getCreateBody() {
|
||||
final ExtendedJSONObject body = new ExtendedJSONObject();
|
||||
try {
|
||||
body.put("email", new String(emailUTF8, "UTF-8"));
|
||||
body.put("authPW", Utils.byte2Hex(authPW));
|
||||
if (preVerified) {
|
||||
// Production endpoints do not allow preVerified; this assumes we only
|
||||
// set it when it's okay to send it.
|
||||
body.put("preVerified", preVerified);
|
||||
}
|
||||
return body;
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new FxAccountClientException(e);
|
||||
body.put("email", new String(emailUTF8, StringUtils.UTF_8));
|
||||
body.put("authPW", Utils.byte2Hex(authPW));
|
||||
if (preVerified) {
|
||||
// Production endpoints do not allow preVerified; this assumes we only
|
||||
// set it when it's okay to send it.
|
||||
body.put("preVerified", preVerified);
|
||||
}
|
||||
return body;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ package org.mozilla.gecko.background.fxa;
|
|||
|
||||
import org.mozilla.gecko.sync.ExtendedJSONObject;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
@ -23,14 +24,10 @@ public class FxAccount20LoginDelegate {
|
|||
this.authPW = FxAccountUtils.generateAuthPW(quickStretchedPW);
|
||||
}
|
||||
|
||||
public ExtendedJSONObject getCreateBody() throws FxAccountClientException {
|
||||
public ExtendedJSONObject getCreateBody() {
|
||||
final ExtendedJSONObject body = new ExtendedJSONObject();
|
||||
try {
|
||||
body.put("email", new String(emailUTF8, "UTF-8"));
|
||||
body.put("authPW", Utils.byte2Hex(authPW));
|
||||
return body;
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new FxAccountClientException(e);
|
||||
}
|
||||
body.put("email", new String(emailUTF8, StringUtils.UTF_8));
|
||||
body.put("authPW", Utils.byte2Hex(authPW));
|
||||
return body;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.mozilla.gecko.sync.net.HawkAuthHeaderProvider;
|
|||
import org.mozilla.gecko.sync.net.Resource;
|
||||
import org.mozilla.gecko.sync.net.SyncResponse;
|
||||
import org.mozilla.gecko.sync.net.SyncStorageResponse;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
@ -647,7 +648,7 @@ public class FxAccountClient20 implements FxAccountClient {
|
|||
if (getKeys) {
|
||||
keyFetchToken = Utils.hex2Byte(body.getString(JSON_KEY_KEYFETCHTOKEN));
|
||||
}
|
||||
LoginResponse loginResponse = new LoginResponse(new String(emailUTF8, "UTF-8"), uid, verified, sessionToken, keyFetchToken);
|
||||
LoginResponse loginResponse = new LoginResponse(new String(emailUTF8, StringUtils.UTF_8), uid, verified, sessionToken, keyFetchToken);
|
||||
|
||||
delegate.handleSuccess(loginResponse);
|
||||
}
|
||||
|
@ -697,7 +698,7 @@ public class FxAccountClient20 implements FxAccountClient {
|
|||
if (getKeys) {
|
||||
keyFetchToken = Utils.hex2Byte(body.getString(JSON_KEY_KEYFETCHTOKEN));
|
||||
}
|
||||
LoginResponse loginResponse = new LoginResponse(new String(emailUTF8, "UTF-8"), uid, verified, sessionToken, keyFetchToken);
|
||||
LoginResponse loginResponse = new LoginResponse(new String(emailUTF8, StringUtils.UTF_8), uid, verified, sessionToken, keyFetchToken);
|
||||
|
||||
delegate.handleSuccess(loginResponse);
|
||||
}
|
||||
|
@ -736,7 +737,7 @@ public class FxAccountClient20 implements FxAccountClient {
|
|||
final RequestDelegate<LoginResponse> delegate) {
|
||||
byte[] quickStretchedPW;
|
||||
try {
|
||||
FxAccountUtils.pii(LOG_TAG, "Trying user provided email: '" + new String(emailUTF8, "UTF-8") + "'" );
|
||||
FxAccountUtils.pii(LOG_TAG, "Trying user provided email: '" + new String(emailUTF8, StringUtils.UTF_8) + "'" );
|
||||
quickStretchedPW = stretcher.getQuickStretchedPW(emailUTF8);
|
||||
} catch (Exception e) {
|
||||
delegate.handleError(e);
|
||||
|
@ -768,7 +769,7 @@ public class FxAccountClient20 implements FxAccountClient {
|
|||
try {
|
||||
// Nota bene: this is not recursive, since we call the fixed password
|
||||
// signature here, which invokes a non-retrying version.
|
||||
byte[] alternateEmailUTF8 = alternateEmail.getBytes("UTF-8");
|
||||
byte[] alternateEmailUTF8 = alternateEmail.getBytes(StringUtils.UTF_8);
|
||||
byte[] alternateQuickStretchedPW = stretcher.getQuickStretchedPW(alternateEmailUTF8);
|
||||
login(alternateEmailUTF8, alternateQuickStretchedPW, getKeys, queryParameters, delegate);
|
||||
} catch (Exception innerException) {
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.mozilla.gecko.sync.Utils;
|
|||
import org.mozilla.gecko.sync.crypto.HKDF;
|
||||
import org.mozilla.gecko.sync.crypto.KeyBundle;
|
||||
import org.mozilla.gecko.sync.crypto.PBKDF2;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
|
@ -49,21 +50,21 @@ public class FxAccountUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static String bytes(String string) throws UnsupportedEncodingException {
|
||||
return Utils.byte2Hex(string.getBytes("UTF-8"));
|
||||
public static String bytes(String string) {
|
||||
return Utils.byte2Hex(string.getBytes(StringUtils.UTF_8));
|
||||
}
|
||||
|
||||
public static byte[] KW(String name) throws UnsupportedEncodingException {
|
||||
public static byte[] KW(String name) {
|
||||
return Utils.concatAll(
|
||||
KW_VERSION_STRING.getBytes("UTF-8"),
|
||||
name.getBytes("UTF-8"));
|
||||
KW_VERSION_STRING.getBytes(StringUtils.UTF_8),
|
||||
name.getBytes(StringUtils.UTF_8));
|
||||
}
|
||||
|
||||
public static byte[] KWE(String name, byte[] emailUTF8) throws UnsupportedEncodingException {
|
||||
public static byte[] KWE(String name, byte[] emailUTF8) {
|
||||
return Utils.concatAll(
|
||||
KW_VERSION_STRING.getBytes("UTF-8"),
|
||||
name.getBytes("UTF-8"),
|
||||
":".getBytes("UTF-8"),
|
||||
KW_VERSION_STRING.getBytes(StringUtils.UTF_8),
|
||||
name.getBytes(StringUtils.UTF_8),
|
||||
":".getBytes(StringUtils.UTF_8),
|
||||
emailUTF8);
|
||||
}
|
||||
|
||||
|
@ -71,8 +72,8 @@ public class FxAccountUtils {
|
|||
* Calculate the SRP verifier <tt>x</tt> value.
|
||||
*/
|
||||
public static BigInteger srpVerifierLowercaseX(byte[] emailUTF8, byte[] srpPWBytes, byte[] srpSaltBytes)
|
||||
throws NoSuchAlgorithmException, UnsupportedEncodingException {
|
||||
byte[] inner = Utils.sha256(Utils.concatAll(emailUTF8, ":".getBytes("UTF-8"), srpPWBytes));
|
||||
throws NoSuchAlgorithmException {
|
||||
byte[] inner = Utils.sha256(Utils.concatAll(emailUTF8, ":".getBytes(StringUtils.UTF_8), srpPWBytes));
|
||||
byte[] outer = Utils.sha256(Utils.concatAll(srpSaltBytes, inner));
|
||||
return new BigInteger(1, outer);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
|
||||
public class QuickPasswordStretcher implements PasswordStretcher {
|
||||
protected final String password;
|
||||
|
@ -26,7 +27,7 @@ public class QuickPasswordStretcher implements PasswordStretcher {
|
|||
}
|
||||
String key = Utils.byte2Hex(emailUTF8);
|
||||
if (!cache.containsKey(key)) {
|
||||
byte[] value = FxAccountUtils.generateQuickStretchedPW(emailUTF8, password.getBytes("UTF-8"));
|
||||
byte[] value = FxAccountUtils.generateQuickStretchedPW(emailUTF8, password.getBytes(StringUtils.UTF_8));
|
||||
cache.put(key, Utils.byte2Hex(value));
|
||||
return value;
|
||||
}
|
||||
|
|
|
@ -4,15 +4,16 @@
|
|||
|
||||
package org.mozilla.gecko.browserid;
|
||||
|
||||
import static org.mozilla.apache.commons.codec.binary.StringUtils.newStringUtf8;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
import org.mozilla.apache.commons.codec.binary.Base64;
|
||||
import org.mozilla.apache.commons.codec.binary.StringUtils;
|
||||
import org.mozilla.gecko.sync.ExtendedJSONObject;
|
||||
import org.mozilla.gecko.sync.NonObjectJSONException;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.TreeMap;
|
||||
|
@ -32,21 +33,21 @@ public class JSONWebTokenUtils {
|
|||
public static final String DEFAULT_CERTIFICATE_ISSUER = "127.0.0.1";
|
||||
public static final String DEFAULT_ASSERTION_ISSUER = "127.0.0.1";
|
||||
|
||||
public static String encode(String payload, SigningPrivateKey privateKey) throws UnsupportedEncodingException, GeneralSecurityException {
|
||||
public static String encode(String payload, SigningPrivateKey privateKey) throws GeneralSecurityException {
|
||||
final ExtendedJSONObject header = new ExtendedJSONObject();
|
||||
header.put("alg", privateKey.getAlgorithm());
|
||||
String encodedHeader = Base64.encodeBase64URLSafeString(header.toJSONString().getBytes("UTF-8"));
|
||||
String encodedPayload = Base64.encodeBase64URLSafeString(payload.getBytes("UTF-8"));
|
||||
String encodedHeader = Base64.encodeBase64URLSafeString(header.toJSONString().getBytes(StringUtils.UTF_8));
|
||||
String encodedPayload = Base64.encodeBase64URLSafeString(payload.getBytes(StringUtils.UTF_8));
|
||||
ArrayList<String> segments = new ArrayList<String>();
|
||||
segments.add(encodedHeader);
|
||||
segments.add(encodedPayload);
|
||||
byte[] message = Utils.toDelimitedString(".", segments).getBytes("UTF-8");
|
||||
byte[] message = Utils.toDelimitedString(".", segments).getBytes(StringUtils.UTF_8);
|
||||
byte[] signature = privateKey.signMessage(message);
|
||||
segments.add(Base64.encodeBase64URLSafeString(signature));
|
||||
return Utils.toDelimitedString(".", segments);
|
||||
}
|
||||
|
||||
public static String decode(String token, VerifyingPublicKey publicKey) throws GeneralSecurityException, UnsupportedEncodingException {
|
||||
public static String decode(String token, VerifyingPublicKey publicKey) throws GeneralSecurityException {
|
||||
if (token == null) {
|
||||
throw new IllegalArgumentException("token must not be null");
|
||||
}
|
||||
|
@ -54,13 +55,13 @@ public class JSONWebTokenUtils {
|
|||
if (segments == null || segments.length != 3) {
|
||||
throw new GeneralSecurityException("malformed token");
|
||||
}
|
||||
byte[] message = (segments[0] + "." + segments[1]).getBytes("UTF-8");
|
||||
byte[] message = (segments[0] + "." + segments[1]).getBytes(StringUtils.UTF_8);
|
||||
byte[] signature = Base64.decodeBase64(segments[2]);
|
||||
boolean verifies = publicKey.verifyMessage(message, signature);
|
||||
if (!verifies) {
|
||||
throw new GeneralSecurityException("bad signature");
|
||||
}
|
||||
String payload = StringUtils.newStringUtf8(Base64.decodeBase64(segments[1]));
|
||||
String payload = newStringUtf8(Base64.decodeBase64(segments[1]));
|
||||
return payload;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ import org.mozilla.gecko.sync.NonObjectJSONException;
|
|||
import org.mozilla.gecko.sync.ThreadPool;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
import org.mozilla.gecko.sync.setup.Constants;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -495,11 +496,7 @@ public class AndroidFxAccount {
|
|||
public ExtendedJSONObject toJSONObject() {
|
||||
ExtendedJSONObject o = unbundle();
|
||||
o.put("email", account.name);
|
||||
try {
|
||||
o.put("emailUTF8", Utils.byte2Hex(account.name.getBytes("UTF-8")));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
// Ignore.
|
||||
}
|
||||
o.put("emailUTF8", Utils.byte2Hex(account.name.getBytes(StringUtils.UTF_8)));
|
||||
o.put("fxaDeviceId", getDeviceId());
|
||||
o.put("fxaDeviceRegistrationVersion", getDeviceRegistrationVersion());
|
||||
o.put("fxaDeviceRegistrationTimestamp", getDeviceRegistrationTimestamp());
|
||||
|
|
|
@ -57,6 +57,7 @@ import org.mozilla.gecko.tokenserver.TokenServerClient;
|
|||
import org.mozilla.gecko.tokenserver.TokenServerClientDelegate;
|
||||
import org.mozilla.gecko.tokenserver.TokenServerException;
|
||||
import org.mozilla.gecko.tokenserver.TokenServerToken;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
@ -408,7 +409,7 @@ public class FxAccountSyncAdapter extends AbstractThreadedSyncAdapter {
|
|||
// so we explicitly do not send payload verification hashes to the
|
||||
// Sync storage endpoint.
|
||||
final boolean includePayloadVerificationHash = false;
|
||||
final AuthHeaderProvider authHeaderProvider = new HawkAuthHeaderProvider(token.id, token.key.getBytes("UTF-8"), includePayloadVerificationHash, storageServerSkew);
|
||||
final AuthHeaderProvider authHeaderProvider = new HawkAuthHeaderProvider(token.id, token.key.getBytes(StringUtils.UTF_8), includePayloadVerificationHash, storageServerSkew);
|
||||
|
||||
final Context context = getContext();
|
||||
final SyncConfiguration syncConfig = new SyncConfiguration(token.uid, authHeaderProvider, sharedPrefs, syncKeyBundle);
|
||||
|
|
|
@ -21,8 +21,8 @@ import org.mozilla.gecko.sync.repositories.NullCursorException;
|
|||
import org.mozilla.gecko.sync.repositories.android.ClientsDatabaseAccessor;
|
||||
import org.mozilla.gecko.sync.repositories.domain.ClientRecord;
|
||||
import org.mozilla.gecko.sync.telemetry.TelemetryEventCollector;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
@ -267,10 +267,10 @@ public class CommandProcessor {
|
|||
extra.put("flowID", command.flowID);
|
||||
}
|
||||
try {
|
||||
extra.put("deviceID", Utils.byte2Hex(Utils.sha256(clientID.concat(hashedFxAUID).getBytes("UTF-8"))));
|
||||
} catch (UnsupportedEncodingException | NoSuchAlgorithmException e) {
|
||||
extra.put("deviceID", Utils.byte2Hex(Utils.sha256(clientID.concat(hashedFxAUID).getBytes(StringUtils.UTF_8))));
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
// Should not happen.
|
||||
Log.e(LOG_TAG, "Either UTF-8 or SHA-256 are not supported", e);
|
||||
Log.e(LOG_TAG, "SHA-256 is not supported", e);
|
||||
}
|
||||
|
||||
TelemetryEventCollector.recordEvent(context, "sendcommand", command.commandType, null, extra);
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
package org.mozilla.gecko.sync;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
import org.mozilla.apache.commons.codec.binary.Base64;
|
||||
|
@ -56,11 +55,10 @@ public class CryptoRecord extends Record {
|
|||
* Input: JSONObject containing a valid payload (cipherText, IV, HMAC),
|
||||
* KeyBundle with keys for decryption. Output: byte[] clearText
|
||||
* @throws CryptoException
|
||||
* @throws UnsupportedEncodingException
|
||||
*/
|
||||
private static byte[] decryptPayload(ExtendedJSONObject payload, KeyBundle keybundle) throws CryptoException, UnsupportedEncodingException {
|
||||
byte[] ciphertext = Base64.decodeBase64(((String) payload.get(KEY_CIPHERTEXT)).getBytes("UTF-8"));
|
||||
byte[] iv = Base64.decodeBase64(((String) payload.get(KEY_IV)).getBytes("UTF-8"));
|
||||
private static byte[] decryptPayload(ExtendedJSONObject payload, KeyBundle keybundle) throws CryptoException {
|
||||
byte[] ciphertext = Base64.decodeBase64(((String) payload.get(KEY_CIPHERTEXT)).getBytes(StringUtils.UTF_8));
|
||||
byte[] iv = Base64.decodeBase64(((String) payload.get(KEY_IV)).getBytes(StringUtils.UTF_8));
|
||||
byte[] hmac = Utils.hex2Byte((String) payload.get(KEY_HMAC));
|
||||
|
||||
return CryptoInfo.decrypt(ciphertext, iv, hmac, keybundle).getMessage();
|
||||
|
@ -131,7 +129,7 @@ public class CryptoRecord extends Record {
|
|||
*/
|
||||
public static CryptoRecord fromJSONRecord(String jsonRecord)
|
||||
throws NonObjectJSONException, IOException, RecordParseException {
|
||||
byte[] bytes = jsonRecord.getBytes("UTF-8");
|
||||
byte[] bytes = jsonRecord.getBytes(StringUtils.UTF_8);
|
||||
ExtendedJSONObject object = ExtendedJSONObject.parseUTF8AsJSONObject(bytes);
|
||||
|
||||
return CryptoRecord.fromJSONRecord(object);
|
||||
|
@ -201,7 +199,7 @@ public class CryptoRecord extends Record {
|
|||
return this;
|
||||
}
|
||||
|
||||
public CryptoRecord encrypt() throws CryptoException, UnsupportedEncodingException {
|
||||
public CryptoRecord encrypt() throws CryptoException {
|
||||
if (this.keyBundle == null) {
|
||||
throw new NoKeyBundleException();
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.json.simple.parser.JSONParser;
|
|||
import org.json.simple.parser.ParseException;
|
||||
import org.mozilla.apache.commons.codec.binary.Base64;
|
||||
import org.mozilla.gecko.sync.UnexpectedJSONException.BadRequiredFieldJSONException;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
@ -138,7 +139,7 @@ public class ExtendedJSONObject implements Cloneable {
|
|||
*/
|
||||
public static ExtendedJSONObject parseUTF8AsJSONObject(byte[] in)
|
||||
throws NonObjectJSONException, IOException {
|
||||
return new ExtendedJSONObject(new String(in, "UTF-8"));
|
||||
return new ExtendedJSONObject(new String(in, StringUtils.UTF_8));
|
||||
}
|
||||
|
||||
public ExtendedJSONObject() {
|
||||
|
|
|
@ -7,7 +7,6 @@ package org.mozilla.gecko.sync;
|
|||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URLDecoder;
|
||||
|
@ -127,11 +126,9 @@ public class Utils {
|
|||
* An input string. Will be decoded as UTF-8.
|
||||
* @return
|
||||
* A byte array of decoded values.
|
||||
* @throws UnsupportedEncodingException
|
||||
* Should not occur.
|
||||
*/
|
||||
public static byte[] decodeBase64(String base64) throws UnsupportedEncodingException {
|
||||
return Base64.decodeBase64(base64.getBytes("UTF-8"));
|
||||
public static byte[] decodeBase64(String base64) {
|
||||
return Base64.decodeBase64(base64.getBytes(StringUtils.UTF_8));
|
||||
}
|
||||
|
||||
public static byte[] decodeFriendlyBase32(String base32) {
|
||||
|
@ -202,8 +199,8 @@ public class Utils {
|
|||
}
|
||||
|
||||
protected static byte[] sha1(final String utf8)
|
||||
throws NoSuchAlgorithmException, UnsupportedEncodingException {
|
||||
final byte[] bytes = utf8.getBytes("UTF-8");
|
||||
throws NoSuchAlgorithmException {
|
||||
final byte[] bytes = utf8.getBytes(StringUtils.UTF_8);
|
||||
try {
|
||||
return NativeCrypto.sha1(bytes);
|
||||
} catch (final LinkageError e) {
|
||||
|
@ -213,12 +210,12 @@ public class Utils {
|
|||
Logger.warn(LOG_TAG, "Got throwable stretching password using native sha1 implementation; " +
|
||||
"ignoring and using Java implementation.", e);
|
||||
final MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
|
||||
return sha1.digest(utf8.getBytes("UTF-8"));
|
||||
return sha1.digest(utf8.getBytes(StringUtils.UTF_8));
|
||||
}
|
||||
}
|
||||
|
||||
protected static String sha1Base32(final String utf8)
|
||||
throws NoSuchAlgorithmException, UnsupportedEncodingException {
|
||||
throws NoSuchAlgorithmException {
|
||||
return new Base32().encodeAsString(sha1(utf8)).toLowerCase(Locale.US);
|
||||
}
|
||||
|
||||
|
@ -229,10 +226,9 @@ public class Utils {
|
|||
* An account string.
|
||||
* @return
|
||||
* An acceptable string.
|
||||
* @throws UnsupportedEncodingException
|
||||
* @throws NoSuchAlgorithmException
|
||||
*/
|
||||
public static String usernameFromAccount(final String account) throws NoSuchAlgorithmException, UnsupportedEncodingException {
|
||||
public static String usernameFromAccount(final String account) throws NoSuchAlgorithmException {
|
||||
if (account == null || account.equals("")) {
|
||||
throw new IllegalArgumentException("No account name provided.");
|
||||
}
|
||||
|
@ -252,10 +248,9 @@ public class Utils {
|
|||
* @param version the version of preferences to reference.
|
||||
* @return the path.
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws UnsupportedEncodingException
|
||||
*/
|
||||
public static String getPrefsPath(final String product, final String accountKey, final String serverURL, final String profile, final long version)
|
||||
throws NoSuchAlgorithmException, UnsupportedEncodingException {
|
||||
throws NoSuchAlgorithmException {
|
||||
final String encodedAccount = sha1Base32(serverURL + ":" + usernameFromAccount(accountKey));
|
||||
|
||||
if (version <= 0) {
|
||||
|
@ -515,13 +510,13 @@ public class Utils {
|
|||
* This is the format produced by desktop Firefox when exchanging credentials
|
||||
* containing non-ASCII characters.
|
||||
*/
|
||||
public static String decodeUTF8(final String in) throws UnsupportedEncodingException {
|
||||
public static String decodeUTF8(final String in) {
|
||||
final int length = in.length();
|
||||
final byte[] asciiBytes = new byte[length];
|
||||
for (int i = 0; i < length; ++i) {
|
||||
asciiBytes[i] = (byte) in.codePointAt(i);
|
||||
}
|
||||
return new String(asciiBytes, "UTF-8");
|
||||
return new String(asciiBytes, StringUtils.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -12,6 +12,7 @@ import javax.crypto.Mac;
|
|||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
|
||||
/*
|
||||
* A standards-compliant implementation of RFC 5869
|
||||
|
@ -25,11 +26,7 @@ public class HKDF {
|
|||
* Used for conversion in cases in which you *know* the encoding exists.
|
||||
*/
|
||||
public static final byte[] bytes(String in) {
|
||||
try {
|
||||
return in.getBytes("UTF-8");
|
||||
} catch (java.io.UnsupportedEncodingException e) {
|
||||
return null;
|
||||
}
|
||||
return in.getBytes(StringUtils.UTF_8);
|
||||
}
|
||||
|
||||
public static final int BLOCKSIZE = 256 / 8;
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
package org.mozilla.gecko.sync.crypto;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
|
@ -14,6 +13,7 @@ import javax.crypto.Mac;
|
|||
|
||||
import org.mozilla.apache.commons.codec.binary.Base64;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
|
||||
public class KeyBundle {
|
||||
private static final String KEY_ALGORITHM_SPEC = "AES";
|
||||
|
@ -44,7 +44,7 @@ public class KeyBundle {
|
|||
// Hash appropriately.
|
||||
try {
|
||||
username = Utils.usernameFromAccount(username);
|
||||
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new IllegalArgumentException("Invalid username.");
|
||||
}
|
||||
|
||||
|
@ -77,9 +77,9 @@ public class KeyBundle {
|
|||
*
|
||||
* @return A KeyBundle with the specified keys.
|
||||
*/
|
||||
public static KeyBundle fromBase64EncodedKeys(String base64EncryptionKey, String base64HmacKey) throws UnsupportedEncodingException {
|
||||
return new KeyBundle(Base64.decodeBase64(base64EncryptionKey.getBytes("UTF-8")),
|
||||
Base64.decodeBase64(base64HmacKey.getBytes("UTF-8")));
|
||||
public static KeyBundle fromBase64EncodedKeys(String base64EncryptionKey, String base64HmacKey) {
|
||||
return new KeyBundle(Base64.decodeBase64(base64EncryptionKey.getBytes(StringUtils.UTF_8)),
|
||||
Base64.decodeBase64(base64HmacKey.getBytes(StringUtils.UTF_8)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
package org.mozilla.gecko.sync.middleware;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import org.mozilla.gecko.sync.CryptoRecord;
|
||||
|
@ -161,7 +160,7 @@ public class Crypto5MiddlewareRepositorySession extends MiddlewareRepositorySess
|
|||
rec.keyBundle = this.keyBundle;
|
||||
try {
|
||||
rec.encrypt();
|
||||
} catch (UnsupportedEncodingException | CryptoException e) {
|
||||
} catch (CryptoException e) {
|
||||
storeDelegate.onRecordStoreFailed(e, record.guid);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import javax.crypto.spec.SecretKeySpec;
|
|||
import org.mozilla.apache.commons.codec.binary.Base64;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
|
||||
import ch.boye.httpclientandroidlib.Header;
|
||||
import ch.boye.httpclientandroidlib.client.methods.HttpRequestBase;
|
||||
|
@ -197,11 +198,10 @@ public class HMACAuthHeaderProvider implements AuthHeaderProvider {
|
|||
* @return signature as base-64 encoded string.
|
||||
* @throws InvalidKeyException
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws UnsupportedEncodingException
|
||||
*/
|
||||
protected static String getSignature(String requestString, String key)
|
||||
throws InvalidKeyException, NoSuchAlgorithmException, UnsupportedEncodingException {
|
||||
String macString = Base64.encodeBase64String(sha1(requestString.getBytes("UTF-8"), key.getBytes("UTF-8")));
|
||||
throws InvalidKeyException, NoSuchAlgorithmException {
|
||||
String macString = Base64.encodeBase64String(sha1(requestString.getBytes(StringUtils.UTF_8), key.getBytes(StringUtils.UTF_8)));
|
||||
|
||||
return macString;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import javax.crypto.spec.SecretKeySpec;
|
|||
import org.mozilla.apache.commons.codec.binary.Base64;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
|
||||
import ch.boye.httpclientandroidlib.Header;
|
||||
import ch.boye.httpclientandroidlib.HttpEntity;
|
||||
|
@ -151,7 +152,7 @@ public class HawkAuthHeaderProvider implements AuthHeaderProvider {
|
|||
String app = null;
|
||||
String dlg = null;
|
||||
String requestString = getRequestString(request, "header", timestamp, nonce, payloadHash, extra, app, dlg);
|
||||
String macString = getSignature(requestString.getBytes("UTF-8"), this.key);
|
||||
String macString = getSignature(requestString.getBytes(StringUtils.UTF_8), this.key);
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Hawk id=\"");
|
||||
|
@ -191,12 +192,11 @@ public class HawkAuthHeaderProvider implements AuthHeaderProvider {
|
|||
* to compute hash for.
|
||||
* @return verification hash, or null if the request does not enclose an entity.
|
||||
* @throws IllegalArgumentException if the request does not enclose a valid non-null entity.
|
||||
* @throws UnsupportedEncodingException
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws IOException
|
||||
*/
|
||||
protected static String getPayloadHashString(HttpRequestBase request)
|
||||
throws UnsupportedEncodingException, NoSuchAlgorithmException, IOException, IllegalArgumentException {
|
||||
throws NoSuchAlgorithmException, IOException, IllegalArgumentException {
|
||||
final boolean shouldComputePayloadHash = request instanceof HttpEntityEnclosingRequest;
|
||||
if (!shouldComputePayloadHash) {
|
||||
Logger.debug(LOG_TAG, "Not computing payload verification hash for non-enclosing request.");
|
||||
|
@ -278,14 +278,14 @@ public class HawkAuthHeaderProvider implements AuthHeaderProvider {
|
|||
* @return hash.
|
||||
* @throws IllegalArgumentException if entity is not repeatable.
|
||||
*/
|
||||
protected static byte[] getPayloadHash(HttpEntity entity) throws UnsupportedEncodingException, IOException, NoSuchAlgorithmException {
|
||||
protected static byte[] getPayloadHash(HttpEntity entity) throws IOException, NoSuchAlgorithmException {
|
||||
if (!entity.isRepeatable()) {
|
||||
throw new IllegalArgumentException("entity must be repeatable");
|
||||
}
|
||||
final MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||
digest.update(("hawk." + HAWK_HEADER_VERSION + ".payload\n").getBytes("UTF-8"));
|
||||
digest.update(getBaseContentType(entity.getContentType()).getBytes("UTF-8"));
|
||||
digest.update("\n".getBytes("UTF-8"));
|
||||
digest.update(("hawk." + HAWK_HEADER_VERSION + ".payload\n").getBytes(StringUtils.UTF_8));
|
||||
digest.update(getBaseContentType(entity.getContentType()).getBytes(StringUtils.UTF_8));
|
||||
digest.update("\n".getBytes(StringUtils.UTF_8));
|
||||
InputStream stream = entity.getContent();
|
||||
try {
|
||||
int numRead;
|
||||
|
@ -295,7 +295,7 @@ public class HawkAuthHeaderProvider implements AuthHeaderProvider {
|
|||
digest.update(buffer, 0, numRead);
|
||||
}
|
||||
}
|
||||
digest.update("\n".getBytes("UTF-8")); // Trailing newline is specified by Hawk.
|
||||
digest.update("\n".getBytes(StringUtils.UTF_8)); // Trailing newline is specified by Hawk.
|
||||
return digest.digest();
|
||||
} finally {
|
||||
stream.close();
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.io.UnsupportedEncodingException;
|
|||
import org.json.simple.JSONObject;
|
||||
import org.mozilla.gecko.sync.CryptoRecord;
|
||||
import org.mozilla.gecko.sync.ExtendedJSONObject;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Record is the abstract base class for all entries that Sync processes:
|
||||
|
@ -259,12 +260,7 @@ public abstract class Record {
|
|||
}
|
||||
|
||||
public static byte[] stringToJSONBytes(String in) {
|
||||
try {
|
||||
return in.getBytes("UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
// Can't happen.
|
||||
return null;
|
||||
}
|
||||
return in.getBytes(StringUtils.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -11,7 +11,6 @@ import android.support.annotation.NonNull;
|
|||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
|
@ -672,8 +671,6 @@ public class SyncClientsEngineStage extends AbstractSessionManagingSyncStage {
|
|||
return null;
|
||||
}
|
||||
return cryptoRecord.encrypt();
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
doAbort(e, encryptionFailure + " Unsupported encoding.");
|
||||
} catch (CryptoException e) {
|
||||
doAbort(e, encryptionFailure);
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@ import org.mozilla.gecko.sync.net.SyncStorageResponse;
|
|||
import org.mozilla.gecko.sync.repositories.FetchFailedException;
|
||||
import org.mozilla.gecko.sync.repositories.StoreFailedException;
|
||||
import org.mozilla.gecko.sync.repositories.domain.ClientRecord;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
@ -77,11 +77,11 @@ public class TelemetryCollector {
|
|||
this.hashedUID = uid;
|
||||
try {
|
||||
this.hashedDeviceID = Utils.byte2Hex(Utils.sha256(
|
||||
deviceID.concat(uid).getBytes("UTF-8")
|
||||
deviceID.concat(uid).getBytes(StringUtils.UTF_8)
|
||||
));
|
||||
} catch (UnsupportedEncodingException | NoSuchAlgorithmException e) {
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
// Should not happen.
|
||||
Log.e(LOG_TAG, "Either UTF-8 or SHA-256 are not supported", e);
|
||||
Log.e(LOG_TAG, "SHA-256 is not supported", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,11 +128,11 @@ public class TelemetryCollector {
|
|||
try {
|
||||
device.putString(
|
||||
TelemetryContract.KEY_DEVICE_ID,
|
||||
Utils.byte2Hex(Utils.sha256(clientAndUid.getBytes("UTF-8")))
|
||||
Utils.byte2Hex(Utils.sha256(clientAndUid.getBytes(StringUtils.UTF_8)))
|
||||
);
|
||||
} catch (UnsupportedEncodingException | NoSuchAlgorithmException e) {
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
// Should not happen.
|
||||
Log.e(LOG_TAG, "Either UTF-8 or SHA-256 are not supported", e);
|
||||
Log.e(LOG_TAG, "SHA-256 is not supported", e);
|
||||
}
|
||||
devices.add(device);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.mozilla.gecko.sync.SharedPreferencesClientsDataDelegate;
|
|||
import org.mozilla.gecko.sync.Utils;
|
||||
import org.mozilla.gecko.sync.delegates.ClientsDataDelegate;
|
||||
import org.mozilla.gecko.sync.net.BaseResource;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.Charset;
|
||||
|
@ -126,10 +127,10 @@ public class TelemetryEventCollector {
|
|||
final ClientsDataDelegate clientsDataDelegate = new SharedPreferencesClientsDataDelegate(sharedPrefs, context);
|
||||
try {
|
||||
final String hashedDeviceID = Utils.byte2Hex(Utils.sha256(
|
||||
clientsDataDelegate.getAccountGUID().concat(hashedFxAUID).getBytes("UTF-8")
|
||||
clientsDataDelegate.getAccountGUID().concat(hashedFxAUID).getBytes(StringUtils.UTF_8)
|
||||
));
|
||||
event.putString(TelemetryContract.KEY_LOCAL_DEVICE_ID, hashedDeviceID);
|
||||
} catch (UnsupportedEncodingException | NoSuchAlgorithmException e) {
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
// Should not happen.
|
||||
Log.e(LOG_TAG, "Either UTF-8 or SHA-256 are not supported", e);
|
||||
return false;
|
||||
|
|
|
@ -22,7 +22,6 @@ import java.io.FileInputStream;
|
|||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.Provider;
|
||||
import java.security.SecureRandom;
|
||||
|
@ -330,10 +329,6 @@ public final class PRNGFixes {
|
|||
if (serial != null) {
|
||||
result.append(serial);
|
||||
}
|
||||
try {
|
||||
return result.toString().getBytes("UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException("UTF-8 encoding not supported");
|
||||
}
|
||||
return result.toString().getBytes(StringUtils.UTF_8);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import org.mozilla.gecko.sync.ExtendedJSONObject;
|
|||
import org.mozilla.gecko.sync.NonObjectJSONException;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
import org.mozilla.gecko.sync.net.BasicAuthHeaderProvider;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -53,7 +54,7 @@ public class TestCredentialsEndToEnd {
|
|||
final String decoded = Utils.decodeUTF8(password);
|
||||
|
||||
final byte[] expectedBytes = Utils.decodeBase64(BTOA_PASSWORD);
|
||||
final String expected = new String(expectedBytes, "UTF-8");
|
||||
final String expected = new String(expectedBytes, StringUtils.UTF_8);
|
||||
|
||||
assertEquals(DESKTOP_ASSERTED_SIZE, password.length());
|
||||
assertEquals(expected, decoded);
|
||||
|
|
|
@ -13,6 +13,7 @@ import org.mozilla.gecko.sync.NoCollectionKeysSetException;
|
|||
import org.mozilla.gecko.sync.NonObjectJSONException;
|
||||
import org.mozilla.gecko.sync.crypto.CryptoException;
|
||||
import org.mozilla.gecko.sync.crypto.KeyBundle;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -80,7 +81,7 @@ public class TestCollectionKeys {
|
|||
rec.encrypt();
|
||||
CollectionKeys ck = new CollectionKeys();
|
||||
ck.setKeyPairsFromWBO(rec, syncKeyBundle);
|
||||
byte[] input = "3fI6k1exImMgAKjilmMaAWxGqEIzFX/9K5EjEgH99vc=".getBytes("UTF-8");
|
||||
byte[] input = "3fI6k1exImMgAKjilmMaAWxGqEIzFX/9K5EjEgH99vc=".getBytes(StringUtils.UTF_8);
|
||||
byte[] expected = Base64.decodeBase64(input);
|
||||
assertSame(expected, ck.defaultKeyBundle().getEncryptionKey());
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.mozilla.gecko.sync.crypto.KeyBundle;
|
|||
import org.mozilla.gecko.sync.repositories.domain.ClientRecord;
|
||||
import org.mozilla.gecko.sync.repositories.domain.HistoryRecord;
|
||||
import org.mozilla.gecko.sync.repositories.domain.Record;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -109,8 +110,8 @@ public class TestCryptoRecord {
|
|||
payload.put("hmac", base16Hmac);
|
||||
body.put("payload", payload.toJSONString());
|
||||
CryptoRecord record = CryptoRecord.fromJSONRecord(body);
|
||||
byte[] decodedKey = Base64.decodeBase64(base64EncryptionKey.getBytes("UTF-8"));
|
||||
byte[] decodedHMAC = Base64.decodeBase64(base64HmacKey.getBytes("UTF-8"));
|
||||
byte[] decodedKey = Base64.decodeBase64(base64EncryptionKey.getBytes(StringUtils.UTF_8));
|
||||
byte[] decodedHMAC = Base64.decodeBase64(base64HmacKey.getBytes(StringUtils.UTF_8));
|
||||
record.keyBundle = new KeyBundle(decodedKey, decodedHMAC);
|
||||
|
||||
record.decrypt();
|
||||
|
@ -125,14 +126,14 @@ public class TestCryptoRecord {
|
|||
String user = "c6o7dvmr2c4ud2fyv6woz2u4zi22bcyd";
|
||||
|
||||
// Check our friendly base32 decoding.
|
||||
assertTrue(Arrays.equals(Utils.decodeFriendlyBase32(key), Base64.decodeBase64("8xbKrJfQYwbFkguKmlSm/g==".getBytes("UTF-8"))));
|
||||
assertTrue(Arrays.equals(Utils.decodeFriendlyBase32(key), Base64.decodeBase64("8xbKrJfQYwbFkguKmlSm/g==".getBytes(StringUtils.UTF_8))));
|
||||
KeyBundle bundle = new KeyBundle(user, key);
|
||||
String expectedEncryptKeyBase64 = "/8RzbFT396htpZu5rwgIg2WKfyARgm7dLzsF5pwrVz8=";
|
||||
String expectedHMACKeyBase64 = "NChGjrqoXYyw8vIYP2334cvmMtsjAMUZNqFwV2LGNkM=";
|
||||
byte[] computedEncryptKey = bundle.getEncryptionKey();
|
||||
byte[] computedHMACKey = bundle.getHMACKey();
|
||||
assertTrue(Arrays.equals(computedEncryptKey, Base64.decodeBase64(expectedEncryptKeyBase64.getBytes("UTF-8"))));
|
||||
assertTrue(Arrays.equals(computedHMACKey, Base64.decodeBase64(expectedHMACKeyBase64.getBytes("UTF-8"))));
|
||||
assertTrue(Arrays.equals(computedEncryptKey, Base64.decodeBase64(expectedEncryptKeyBase64.getBytes(StringUtils.UTF_8))));
|
||||
assertTrue(Arrays.equals(computedHMACKey, Base64.decodeBase64(expectedHMACKeyBase64.getBytes(StringUtils.UTF_8))));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -264,8 +265,8 @@ public class TestCryptoRecord {
|
|||
JSONArray keys = new ExtendedJSONObject(decrypted.payload.toJSONString()).getArray("default");
|
||||
KeyBundle keyBundle = KeyBundle.fromBase64EncodedKeys((String)keys.get(0), (String)keys.get(1));
|
||||
|
||||
assertArrayEquals(Base64.decodeBase64(expectedBase64EncryptionKey.getBytes("UTF-8")), keyBundle.getEncryptionKey());
|
||||
assertArrayEquals(Base64.decodeBase64(expectedBase64HmacKey.getBytes("UTF-8")), keyBundle.getHMACKey());
|
||||
assertArrayEquals(Base64.decodeBase64(expectedBase64EncryptionKey.getBytes(StringUtils.UTF_8)), keyBundle.getEncryptionKey());
|
||||
assertArrayEquals(Base64.decodeBase64(expectedBase64HmacKey.getBytes(StringUtils.UTF_8)), keyBundle.getHMACKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.mozilla.gecko.fxa.login.FxAccountLoginStateMachine.LoginStateMachineD
|
|||
import org.mozilla.gecko.fxa.login.FxAccountLoginTransition.Transition;
|
||||
import org.mozilla.gecko.fxa.login.State.StateLabel;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
@ -39,10 +40,10 @@ public class TestFxAccountLoginStateMachine {
|
|||
@Before
|
||||
public void setUp() throws Exception {
|
||||
if (TEST_EMAIL_UTF8 == null) {
|
||||
TEST_EMAIL_UTF8 = TEST_EMAIL.getBytes("UTF-8");
|
||||
TEST_EMAIL_UTF8 = TEST_EMAIL.getBytes(StringUtils.UTF_8);
|
||||
}
|
||||
if (TEST_PASSWORD_UTF8 == null) {
|
||||
TEST_PASSWORD_UTF8 = TEST_PASSWORD.getBytes("UTF-8");
|
||||
TEST_PASSWORD_UTF8 = TEST_PASSWORD.getBytes(StringUtils.UTF_8);
|
||||
}
|
||||
if (TEST_QUICK_STRETCHED_PW == null) {
|
||||
TEST_QUICK_STRETCHED_PW = FxAccountUtils.generateQuickStretchedPW(TEST_EMAIL_UTF8, TEST_PASSWORD_UTF8);
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.mozilla.gecko.sync.Utils;
|
|||
import org.mozilla.gecko.sync.crypto.CryptoException;
|
||||
import org.mozilla.gecko.sync.crypto.CryptoInfo;
|
||||
import org.mozilla.gecko.sync.crypto.KeyBundle;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
@ -24,17 +25,17 @@ import static org.junit.Assert.assertTrue;
|
|||
public class TestCryptoInfo {
|
||||
|
||||
@Test
|
||||
public void testEncryptedHMACIsSet() throws CryptoException, UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException {
|
||||
public void testEncryptedHMACIsSet() throws CryptoException, InvalidKeyException, NoSuchAlgorithmException {
|
||||
KeyBundle kb = KeyBundle.withRandomKeys();
|
||||
CryptoInfo encrypted = CryptoInfo.encrypt("plaintext".getBytes("UTF-8"), kb);
|
||||
CryptoInfo encrypted = CryptoInfo.encrypt("plaintext".getBytes(StringUtils.UTF_8), kb);
|
||||
assertSame(kb, encrypted.getKeys());
|
||||
assertTrue(encrypted.generatedHMACIsHMAC());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRandomEncryptedDecrypted() throws CryptoException, UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException {
|
||||
public void testRandomEncryptedDecrypted() throws CryptoException, InvalidKeyException, NoSuchAlgorithmException {
|
||||
KeyBundle kb = KeyBundle.withRandomKeys();
|
||||
byte[] plaintext = "plaintext".getBytes("UTF-8");
|
||||
byte[] plaintext = "plaintext".getBytes(StringUtils.UTF_8);
|
||||
CryptoInfo info = CryptoInfo.encrypt(plaintext, kb);
|
||||
byte[] iv = info.getIV();
|
||||
info.decrypt();
|
||||
|
@ -141,4 +142,4 @@ public class TestCryptoInfo {
|
|||
assertArrayEquals(Base64.decodeBase64(base64CipherText), encrypted.getMessage());
|
||||
assertArrayEquals(Utils.hex2Byte(base16Hmac), encrypted.getHMAC());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import org.junit.runner.RunWith;
|
|||
import org.mozilla.apache.commons.codec.binary.Base64;
|
||||
import org.mozilla.gecko.sync.crypto.CryptoException;
|
||||
import org.mozilla.gecko.sync.crypto.KeyBundle;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
@ -30,8 +31,8 @@ public class TestKeyBundle {
|
|||
"dKj0O+b0fwI=";
|
||||
|
||||
KeyBundle keys = new KeyBundle(username, friendlyBase32SyncKey);
|
||||
assertArrayEquals(keys.getEncryptionKey(), Base64.decodeBase64(base64EncryptionKey.getBytes("UTF-8")));
|
||||
assertArrayEquals(keys.getHMACKey(), Base64.decodeBase64(base64HmacKey.getBytes("UTF-8")));
|
||||
assertArrayEquals(keys.getEncryptionKey(), Base64.decodeBase64(base64EncryptionKey.getBytes(StringUtils.UTF_8)));
|
||||
assertArrayEquals(keys.getHMACKey(), Base64.decodeBase64(base64HmacKey.getBytes(StringUtils.UTF_8)));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -32,7 +32,7 @@ public class TestHMACAuthHeaderProvider {
|
|||
}
|
||||
|
||||
public static String getSignature(String requestString, String key)
|
||||
throws InvalidKeyException, NoSuchAlgorithmException, UnsupportedEncodingException {
|
||||
throws InvalidKeyException, NoSuchAlgorithmException {
|
||||
return HMACAuthHeaderProvider.getSignature(requestString, key);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import ch.boye.httpclientandroidlib.protocol.BasicHttpContext;
|
|||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mozilla.gecko.sync.net.HawkAuthHeaderProvider;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -46,7 +47,7 @@ public class TestHawkAuthHeaderProvider {
|
|||
// Public for testing.
|
||||
public static String getSignature(String requestString, String key)
|
||||
throws InvalidKeyException, NoSuchAlgorithmException, UnsupportedEncodingException {
|
||||
return HawkAuthHeaderProvider.getSignature(requestString.getBytes("UTF-8"), key.getBytes("UTF-8"));
|
||||
return HawkAuthHeaderProvider.getSignature(requestString.getBytes(StringUtils.UTF_8), key.getBytes(StringUtils.UTF_8));
|
||||
}
|
||||
|
||||
// Public for testing.
|
||||
|
@ -106,7 +107,7 @@ public class TestHawkAuthHeaderProvider {
|
|||
|
||||
@Test
|
||||
public void testSpecPayloadExample() throws Exception {
|
||||
LeakyHawkAuthHeaderProvider provider = new LeakyHawkAuthHeaderProvider("dh37fgj492je", "werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn".getBytes("UTF-8"));
|
||||
LeakyHawkAuthHeaderProvider provider = new LeakyHawkAuthHeaderProvider("dh37fgj492je", "werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn".getBytes(StringUtils.UTF_8));
|
||||
URI uri = new URI("http://example.com:8000/resource/1?b=1&a=2");
|
||||
HttpPost req = new HttpPost(uri);
|
||||
String body = "Thank you for flying Hawk";
|
||||
|
@ -119,7 +120,7 @@ public class TestHawkAuthHeaderProvider {
|
|||
|
||||
@Test
|
||||
public void testSpecAuthorizationHeader() throws Exception {
|
||||
LeakyHawkAuthHeaderProvider provider = new LeakyHawkAuthHeaderProvider("dh37fgj492je", "werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn".getBytes("UTF-8"));
|
||||
LeakyHawkAuthHeaderProvider provider = new LeakyHawkAuthHeaderProvider("dh37fgj492je", "werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn".getBytes(StringUtils.UTF_8));
|
||||
URI uri = new URI("http://example.com:8000/resource/1?b=1&a=2");
|
||||
HttpGet req = new HttpGet(uri);
|
||||
Header header = provider.getAuthHeader(req, null, null, 1353832234L, "j4h3g2", "some-app-ext-data", false);
|
||||
|
|
|
@ -19,6 +19,7 @@ import org.mozilla.gecko.sync.net.BaseResourceDelegate;
|
|||
import org.mozilla.gecko.sync.net.HawkAuthHeaderProvider;
|
||||
import org.mozilla.gecko.sync.net.Resource;
|
||||
import org.mozilla.gecko.sync.net.SyncResponse;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
@ -39,7 +40,7 @@ public class TestLiveHawkAuth {
|
|||
public void testHawkUsage() throws Exception {
|
||||
// Id and credentials are hard-coded in example/usage.js.
|
||||
final String id = "dh37fgj492je";
|
||||
final byte[] key = "werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn".getBytes("UTF-8");
|
||||
final byte[] key = "werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn".getBytes(StringUtils.UTF_8);
|
||||
final BaseResource resource = new BaseResource("http://localhost:8000/", false);
|
||||
|
||||
// Basic GET.
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.mozilla.gecko.sync.net.SyncStorageResponse;
|
|||
import org.mozilla.gecko.sync.repositories.FetchFailedException;
|
||||
import org.mozilla.gecko.sync.repositories.StoreFailedException;
|
||||
import org.mozilla.gecko.sync.repositories.domain.ClientRecord;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -51,7 +52,7 @@ public class TelemetryCollectorTest {
|
|||
assertEquals(uid, bundle.get("uid"));
|
||||
// Expect device ID to be hashed with the UID.
|
||||
assertEquals(
|
||||
Utils.byte2Hex(Utils.sha256(deviceID.concat(uid).getBytes("UTF-8"))),
|
||||
Utils.byte2Hex(Utils.sha256(deviceID.concat(uid).getBytes(StringUtils.UTF_8))),
|
||||
bundle.get("deviceID")
|
||||
);
|
||||
}
|
||||
|
@ -79,7 +80,7 @@ public class TelemetryCollectorTest {
|
|||
ArrayList<Bundle> devices = data.getParcelableArrayList("devices");
|
||||
assertEquals(1, devices.size());
|
||||
assertEquals(
|
||||
Utils.byte2Hex(Utils.sha256("client1-guid".concat("hashed-uid").getBytes("UTF-8"))),
|
||||
Utils.byte2Hex(Utils.sha256("client1-guid".concat("hashed-uid").getBytes(StringUtils.UTF_8))),
|
||||
devices.get(0).getString("id")
|
||||
);
|
||||
assertEquals("iOS", devices.get(0).getString("os"));
|
||||
|
@ -98,14 +99,14 @@ public class TelemetryCollectorTest {
|
|||
assertEquals("iOS", devices.get(0).getString("os"));
|
||||
assertEquals("1.33.7", devices.get(0).getString("version"));
|
||||
assertEquals(
|
||||
Utils.byte2Hex(Utils.sha256("client1-guid".concat("hashed-uid").getBytes("UTF-8"))),
|
||||
Utils.byte2Hex(Utils.sha256("client1-guid".concat("hashed-uid").getBytes(StringUtils.UTF_8))),
|
||||
devices.get(0).getString("id")
|
||||
);
|
||||
|
||||
assertEquals("Android", devices.get(1).getString("os"));
|
||||
assertEquals("55.0a1", devices.get(1).getString("version"));
|
||||
assertEquals(
|
||||
Utils.byte2Hex(Utils.sha256("client2-guid".concat("hashed-uid").getBytes("UTF-8"))),
|
||||
Utils.byte2Hex(Utils.sha256("client2-guid".concat("hashed-uid").getBytes(StringUtils.UTF_8))),
|
||||
devices.get(1).getString("id")
|
||||
);
|
||||
}
|
||||
|
@ -346,4 +347,4 @@ public class TelemetryCollectorTest {
|
|||
assertEquals("othererror", error.getString("name"));
|
||||
assertEquals("store:IllegalStateException", error.getString("error"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.mozilla.gecko.sync.ExtendedJSONObject;
|
|||
import org.mozilla.gecko.sync.NonArrayJSONException;
|
||||
import org.mozilla.gecko.sync.NonObjectJSONException;
|
||||
import org.mozilla.gecko.sync.UnexpectedJSONException.BadRequiredFieldJSONException;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -102,7 +103,7 @@ public class TestExtendedJSONObject {
|
|||
public void testParseUTF8AsJSONObject() throws Exception {
|
||||
String TEST = "{\"key\":\"value\"}";
|
||||
|
||||
ExtendedJSONObject o = ExtendedJSONObject.parseUTF8AsJSONObject(TEST.getBytes("UTF-8"));
|
||||
ExtendedJSONObject o = ExtendedJSONObject.parseUTF8AsJSONObject(TEST.getBytes(StringUtils.UTF_8));
|
||||
assertNotNull(o);
|
||||
assertEquals("value", o.getString("key"));
|
||||
}
|
||||
|
@ -117,7 +118,7 @@ public class TestExtendedJSONObject {
|
|||
}
|
||||
|
||||
try {
|
||||
ExtendedJSONObject.parseUTF8AsJSONObject("{".getBytes("UTF-8"));
|
||||
ExtendedJSONObject.parseUTF8AsJSONObject("{".getBytes(StringUtils.UTF_8));
|
||||
fail();
|
||||
} catch (NonObjectJSONException e) {
|
||||
// Do nothing.
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.mozilla.gecko.db.BrowserDB;
|
|||
import org.mozilla.gecko.db.URLMetadata;
|
||||
import org.mozilla.gecko.db.URLImageDataTable;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
|
||||
import android.content.ContentProviderOperation;
|
||||
import android.content.ContentProviderResult;
|
||||
|
@ -195,7 +196,7 @@ public class testBrowserProvider extends ContentProviderTest {
|
|||
|
||||
faviconEntry.put(BrowserContract.Favicons.PAGE_URL, pageUrl);
|
||||
faviconEntry.put(BrowserContract.Favicons.URL, pageUrl + "/favicon.ico");
|
||||
faviconEntry.put(BrowserContract.Favicons.DATA, data.getBytes("UTF8"));
|
||||
faviconEntry.put(BrowserContract.Favicons.DATA, data.getBytes(StringUtils.UTF_8));
|
||||
|
||||
return faviconEntry;
|
||||
}
|
||||
|
@ -204,7 +205,7 @@ public class testBrowserProvider extends ContentProviderTest {
|
|||
ContentValues thumbnailEntry = new ContentValues();
|
||||
|
||||
thumbnailEntry.put(BrowserContract.Thumbnails.URL, pageUrl);
|
||||
thumbnailEntry.put(BrowserContract.Thumbnails.DATA, data.getBytes("UTF8"));
|
||||
thumbnailEntry.put(BrowserContract.Thumbnails.DATA, data.getBytes(StringUtils.UTF_8));
|
||||
|
||||
return thumbnailEntry;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import java.security.NoSuchAlgorithmException;
|
|||
import org.mozilla.gecko.background.nativecode.NativeCrypto;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
import org.mozilla.gecko.tests.helpers.GeckoHelper;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
|
||||
import android.os.SystemClock;
|
||||
|
||||
|
@ -238,9 +239,9 @@ public class testNativeCrypto extends UITest {
|
|||
}
|
||||
}
|
||||
|
||||
private void _testSHA256WithMultipleUpdatesFromStream() throws UnsupportedEncodingException {
|
||||
private void _testSHA256WithMultipleUpdatesFromStream() {
|
||||
final String input = "HelloWorldThisIsASuperLongStringThatIsReadAsAStreamOfBytes";
|
||||
final ByteArrayInputStream stream = new ByteArrayInputStream(input.getBytes("UTF-8"));
|
||||
final ByteArrayInputStream stream = new ByteArrayInputStream(input.getBytes(StringUtils.UTF_8));
|
||||
final String expected = "8b5cb76b80f7eb6fb83ee138bfd31e2922e71dd245daa21a8d9876e8dee9eef5";
|
||||
|
||||
byte[] buffer = new byte[10];
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Types.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace interceptor {
|
||||
|
@ -165,7 +164,8 @@ public:
|
|||
return;
|
||||
}
|
||||
|
||||
MOZ_RELEASE_ASSERT(sPerProcVM->append(ProcMapEntry(aArgs...)));
|
||||
bool appended = sPerProcVM->append(ProcMapEntry(aArgs...));
|
||||
MOZ_RELEASE_ASSERT(appended);
|
||||
}
|
||||
|
||||
explicit operator bool() const
|
||||
|
@ -173,7 +173,8 @@ public:
|
|||
AutoCriticalSection lock(&sCS);
|
||||
|
||||
ProcMapEntry* entry;
|
||||
MOZ_RELEASE_ASSERT(find(mPid, &entry));
|
||||
bool found = find(mPid, &entry);
|
||||
MOZ_RELEASE_ASSERT(found);
|
||||
|
||||
return !!entry->mVMPolicy;
|
||||
}
|
||||
|
@ -183,7 +184,8 @@ public:
|
|||
AutoCriticalSection lock(&sCS);
|
||||
|
||||
ProcMapEntry* entry;
|
||||
MOZ_RELEASE_ASSERT(find(mPid, &entry));
|
||||
bool found = find(mPid, &entry);
|
||||
MOZ_RELEASE_ASSERT(found);
|
||||
|
||||
return entry->mVMPolicy;
|
||||
}
|
||||
|
@ -241,7 +243,8 @@ public:
|
|||
AutoCriticalSection lock(&sCS);
|
||||
|
||||
ProcMapEntry* entry;
|
||||
MOZ_RELEASE_ASSERT(find(mPid, &entry));
|
||||
bool found = find(mPid, &entry);
|
||||
MOZ_RELEASE_ASSERT(found);
|
||||
|
||||
TrampolineCollection<MMPolicy> items(Move(entry->mVMPolicy.Items()));
|
||||
|
||||
|
@ -292,12 +295,12 @@ private:
|
|||
static DWORD GetPid(HANDLE aHandle) { return ::GetProcessId(aHandle); }
|
||||
|
||||
DWORD mPid;
|
||||
static StaticAutoPtr<MapT> sPerProcVM;
|
||||
static MapT* sPerProcVM;
|
||||
static CRITICAL_SECTION sCS;
|
||||
};
|
||||
|
||||
template <typename MMPolicy, uint32_t kChunkSize>
|
||||
StaticAutoPtr<typename VMSharingPolicyShared<MMPolicy, kChunkSize>::MapT>
|
||||
typename VMSharingPolicyShared<MMPolicy, kChunkSize>::MapT *
|
||||
VMSharingPolicyShared<MMPolicy, kChunkSize>::sPerProcVM;
|
||||
|
||||
template <typename MMPolicy, uint32_t kChunkSize>
|
||||
|
|
|
@ -88,7 +88,7 @@ enum
|
|||
};
|
||||
|
||||
template <typename VMPolicy =
|
||||
mozilla::interceptor::VMSharingPolicyUnique<
|
||||
mozilla::interceptor::VMSharingPolicyShared<
|
||||
mozilla::interceptor::MMPolicyInProcess, kDefaultTrampolineSize>>
|
||||
class WindowsDllInterceptor final
|
||||
{
|
||||
|
|
|
@ -66,6 +66,7 @@ enum class SHA1ModeResult {
|
|||
enum class DistrustedCAPolicy : uint32_t {
|
||||
Permit = 0,
|
||||
DistrustSymantecRoots = 1,
|
||||
DistrustSymantecRootsRegardlessOfDate = 2,
|
||||
};
|
||||
|
||||
enum class NetscapeStepUpPolicy : uint32_t;
|
||||
|
|
|
@ -891,7 +891,7 @@ NSSCertDBTrustDomain::IsChainValid(const DERArray& certArray, Time time,
|
|||
// handshake. To determine this, we check mHostname: If it isn't set, this is
|
||||
// not TLS, so don't run the algorithm.
|
||||
if (mHostname && CertDNIsInList(root.get(), RootSymantecDNs) &&
|
||||
mDistrustedCAPolicy == DistrustedCAPolicy::DistrustSymantecRoots) {
|
||||
mDistrustedCAPolicy != DistrustedCAPolicy::Permit) {
|
||||
|
||||
rootCert = nullptr; // Clear the state for Segment...
|
||||
nsCOMPtr<nsIX509CertList> intCerts;
|
||||
|
@ -907,8 +907,13 @@ NSSCertDBTrustDomain::IsChainValid(const DERArray& certArray, Time time,
|
|||
// (new Date("2016-06-01T00:00:00Z")).getTime() * 1000
|
||||
static const PRTime JUNE_1_2016 = 1464739200000000;
|
||||
|
||||
PRTime permitAfterDate = 0; // 0 indicates there is no permitAfterDate
|
||||
if (mDistrustedCAPolicy == DistrustedCAPolicy::DistrustSymantecRoots) {
|
||||
permitAfterDate = JUNE_1_2016;
|
||||
}
|
||||
|
||||
bool isDistrusted = false;
|
||||
nsrv = CheckForSymantecDistrust(intCerts, eeCert, JUNE_1_2016,
|
||||
nsrv = CheckForSymantecDistrust(intCerts, eeCert, permitAfterDate,
|
||||
RootAppleAndGoogleSPKIs, isDistrusted);
|
||||
if (NS_FAILED(nsrv)) {
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
|
|
|
@ -1694,6 +1694,7 @@ void nsNSSComponent::setValidationOptions(bool isInitialSetting)
|
|||
switch(distrustedCAPolicy) {
|
||||
case DistrustedCAPolicy::Permit:
|
||||
case DistrustedCAPolicy::DistrustSymantecRoots:
|
||||
case DistrustedCAPolicy::DistrustSymantecRootsRegardlessOfDate:
|
||||
break;
|
||||
default:
|
||||
distrustedCAPolicy = defaultCAPolicyMode;
|
||||
|
|
|
@ -39,6 +39,23 @@ add_connection_test("symantec-not-whitelisted-before-cutoff.example.com",
|
|||
MOZILLA_PKIX_ERROR_ADDITIONAL_POLICY_CONSTRAINT_FAILED,
|
||||
null, null);
|
||||
|
||||
// Enable the Firefox 63 total distrust; before or after cutoff should now all
|
||||
// behave the same.
|
||||
add_test(function() {
|
||||
clearSessionCache();
|
||||
Services.prefs.setIntPref("security.pki.distrust_ca_policy",
|
||||
/* DistrustedCAPolicy::DistrustSymantecRootsRegardlessOfDate */ 2);
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_connection_test("symantec-not-whitelisted-before-cutoff.example.com",
|
||||
MOZILLA_PKIX_ERROR_ADDITIONAL_POLICY_CONSTRAINT_FAILED,
|
||||
null, null);
|
||||
|
||||
add_connection_test("symantec-not-whitelisted-after-cutoff.example.com",
|
||||
MOZILLA_PKIX_ERROR_ADDITIONAL_POLICY_CONSTRAINT_FAILED,
|
||||
null, null);
|
||||
|
||||
// Disable the distrust, should be back to the console warning
|
||||
add_test(function() {
|
||||
clearSessionCache();
|
||||
|
@ -77,6 +94,7 @@ add_task(async function() {
|
|||
// (as an external fetch is bad in the tests), disable OCSP first.
|
||||
Services.prefs.setIntPref("security.OCSP.enabled", 0);
|
||||
|
||||
// Try with the policy for 60
|
||||
Services.prefs.setIntPref("security.pki.distrust_ca_policy",
|
||||
/* DistrustedCAPolicy::DistrustSymantecRoots */ 1);
|
||||
|
||||
|
@ -85,4 +103,11 @@ add_task(async function() {
|
|||
|
||||
await checkCertErrorGenericAtTime(certDB, whitelistedCert, PRErrorCodeSuccess,
|
||||
certificateUsageSSLServer, VALIDATION_TIME);
|
||||
|
||||
// Try with the policy for 63
|
||||
Services.prefs.setIntPref("security.pki.distrust_ca_policy",
|
||||
/* DistrustedCAPolicy::DistrustSymantecRootsRegardlessOfDate */ 2);
|
||||
|
||||
await checkCertErrorGenericAtTime(certDB, whitelistedCert, PRErrorCodeSuccess,
|
||||
certificateUsageSSLServer, VALIDATION_TIME);
|
||||
});
|
||||
|
|
|
@ -12,24 +12,6 @@ transforms:
|
|||
kind-dependencies:
|
||||
- build
|
||||
|
||||
only-for-build-platforms:
|
||||
- linux64/opt
|
||||
- linux64/debug
|
||||
- linux64-nightly/opt
|
||||
- linux-nightly/opt
|
||||
- linux64-devedition-nightly/opt
|
||||
- linux-devedition-nightly/opt
|
||||
- android-aarch64-nightly/opt
|
||||
- android-api-16/opt
|
||||
- android-api-16-nightly/opt
|
||||
- android-x86-nightly/opt
|
||||
- macosx64-nightly/opt
|
||||
- macosx64-devedition-nightly/opt
|
||||
- win32-nightly/opt
|
||||
- win64-nightly/opt
|
||||
- win32-devedition-nightly/opt
|
||||
- win64-devedition-nightly/opt
|
||||
|
||||
job-template:
|
||||
description: Upload Symbols
|
||||
worker-type: aws-provisioner-v1/gecko-{level}-b-linux
|
||||
|
@ -53,4 +35,7 @@ job-template:
|
|||
run-on-projects:
|
||||
by-build-platform:
|
||||
.*devedition.*: ['mozilla-beta', 'maple']
|
||||
default: ['all']
|
||||
# Only upload symbols for nightlies on most branches.
|
||||
.*(?<!-devedition)-nightly: ['all']
|
||||
# Allow symbol upload for any build type on try.
|
||||
default: ['try']
|
||||
|
|
|
@ -40,14 +40,6 @@ def filter_on_platforms(task, platforms):
|
|||
return (platform in platforms)
|
||||
|
||||
|
||||
def filter_upload_symbols(task, parameters):
|
||||
# Filters out symbols when there are not part of a nightly or a release build
|
||||
# TODO Remove this too specific filter (bug 1353296)
|
||||
return '-upload-symbols' not in task.label or \
|
||||
task.attributes.get('nightly') or \
|
||||
parameters.get('project') in ('mozilla-beta', 'mozilla-release')
|
||||
|
||||
|
||||
def filter_beta_release_tasks(task, parameters, ignore_kinds=None, allow_l10n=False):
|
||||
if not standard_filter(task, parameters):
|
||||
return False
|
||||
|
@ -65,6 +57,8 @@ def filter_beta_release_tasks(task, parameters, ignore_kinds=None, allow_l10n=Fa
|
|||
# On beta, Nightly builds are already PGOs
|
||||
'linux-pgo', 'linux64-pgo',
|
||||
'win32-pgo', 'win64-pgo',
|
||||
# ASAN is central-only
|
||||
'linux64-asan-reporter-nightly',
|
||||
):
|
||||
return False
|
||||
if str(platform).startswith('android') and 'nightly' in str(platform):
|
||||
|
@ -94,7 +88,7 @@ def filter_beta_release_tasks(task, parameters, ignore_kinds=None, allow_l10n=Fa
|
|||
def standard_filter(task, parameters):
|
||||
return all(
|
||||
filter_func(task, parameters) for filter_func in
|
||||
(filter_out_nightly, filter_for_project, filter_upload_symbols)
|
||||
(filter_out_nightly, filter_for_project)
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -1473,6 +1473,7 @@ def build_task(config, tasks):
|
|||
extra['parent'] = os.environ.get('TASK_ID', '')
|
||||
task_th = task.get('treeherder')
|
||||
if task_th:
|
||||
extra.setdefault('treeherder-platform', task_th['platform'])
|
||||
treeherder = extra.setdefault('treeherder', {})
|
||||
|
||||
machine_platform, collection = task_th['platform'].split('/', 1)
|
||||
|
|
|
@ -33,20 +33,20 @@ def fill_template(config, tasks):
|
|||
attributes = task.setdefault('attributes', {})
|
||||
attributes['build_platform'] = build_platform
|
||||
attributes['build_type'] = build_type
|
||||
if 'nightly' in build_platform:
|
||||
if dep.attributes.get('nightly'):
|
||||
attributes['nightly'] = True
|
||||
|
||||
treeherder = task.get('treeherder', {})
|
||||
th = dep.task.get('extra')['treeherder']
|
||||
treeherder.setdefault('platform',
|
||||
"{}/{}".format(th['machine']['platform'],
|
||||
build_type))
|
||||
th_platform = dep.task['extra'].get('treeherder-platform',
|
||||
"{}/{}".format(th['machine']['platform'], build_type))
|
||||
treeherder.setdefault('platform', th_platform)
|
||||
treeherder.setdefault('tier', th['tier'])
|
||||
treeherder.setdefault('kind', th['jobKind'])
|
||||
if dep.attributes.get('nightly'):
|
||||
treeherder.setdefault('symbol', 'SymN')
|
||||
else:
|
||||
treeherder.setdefault('symbol', 'Sym')
|
||||
# Disambiguate the treeherder symbol.
|
||||
build_sym = th['symbol']
|
||||
sym = 'Sym' + (build_sym[1:] if build_sym.startswith('B') else build_sym)
|
||||
treeherder.setdefault('symbol', sym)
|
||||
task['treeherder'] = treeherder
|
||||
|
||||
# clear out the stuff that's not part of a task description
|
||||
|
|
|
@ -304,6 +304,7 @@ class cpstartup(PageloaderTest):
|
|||
tploadnocache = True
|
||||
unit = 'ms'
|
||||
preferences = {
|
||||
'addon.test.cpstartup.webserver': '${webserver}',
|
||||
# By default, Talos is configured to open links from
|
||||
# content in new windows. We're overriding them so that
|
||||
# they open in new tabs instead.
|
||||
|
|
|
@ -6,7 +6,9 @@ ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|||
|
||||
const PREALLOCATED_PREF = "dom.ipc.processPrelaunch.enabled";
|
||||
|
||||
const TARGET_URI = "chrome://cpstartup/content/target.html";
|
||||
const TARGET_PATH = "tests/cpstartup/content/target.html";
|
||||
const WEBSERVER = Services.prefs.getCharPref("addon.test.cpstartup.webserver");
|
||||
const TARGET_URI = `${WEBSERVER}/${TARGET_PATH}`;
|
||||
|
||||
/**
|
||||
* The purpose of this test it to measure the performance of a content process startup.
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#pragma comment(lib, "ole32.lib")
|
||||
#pragma comment(lib, "rpcrt4.lib")
|
||||
|
||||
#include "mozilla/CmdLineAndEnvUtils.h"
|
||||
#include "nsWindowsHelpers.h"
|
||||
|
||||
#include "workmonitor.h"
|
||||
|
@ -31,7 +32,6 @@
|
|||
// Updates usually take less than a minute so this seems like a
|
||||
// significantly large and safe amount of time to wait.
|
||||
static const int TIME_TO_WAIT_ON_UPDATER = 15 * 60 * 1000;
|
||||
wchar_t* MakeCommandLine(int argc, wchar_t** argv);
|
||||
BOOL WriteStatusFailure(LPCWSTR updateDirPath, int errorCode);
|
||||
BOOL PathGetSiblingFilePath(LPWSTR destinationBuffer, LPCWSTR siblingFilePath,
|
||||
LPCWSTR newFileName);
|
||||
|
@ -190,7 +190,7 @@ StartUpdateProcess(int argc,
|
|||
|
||||
// The updater command line is of the form:
|
||||
// updater.exe update-dir apply [wait-pid [callback-dir callback-path args]]
|
||||
LPWSTR cmdLine = MakeCommandLine(argc, argv);
|
||||
auto cmdLine = mozilla::MakeCommandLine(argc, argv);
|
||||
|
||||
int index = 3;
|
||||
if (IsOldCommandline(argc, argv)) {
|
||||
|
@ -212,8 +212,8 @@ StartUpdateProcess(int argc,
|
|||
// do anything special that it needs to do for service updates.
|
||||
// Search in updater.cpp for more info on MOZ_USING_SERVICE.
|
||||
putenv(const_cast<char*>("MOZ_USING_SERVICE=1"));
|
||||
LOG(("Starting service with cmdline: %ls", cmdLine));
|
||||
processStarted = CreateProcessW(argv[0], cmdLine,
|
||||
LOG(("Starting service with cmdline: %ls", cmdLine.get()));
|
||||
processStarted = CreateProcessW(argv[0], cmdLine.get(),
|
||||
nullptr, nullptr, FALSE,
|
||||
CREATE_DEFAULT_ERROR_MODE,
|
||||
nullptr,
|
||||
|
@ -279,13 +279,12 @@ StartUpdateProcess(int argc,
|
|||
DWORD lastError = GetLastError();
|
||||
LOG_WARN(("Could not create process as current user, "
|
||||
"updaterPath: %ls; cmdLine: %ls. (%d)",
|
||||
argv[0], cmdLine, lastError));
|
||||
argv[0], cmdLine.get(), lastError));
|
||||
}
|
||||
|
||||
// Empty value on putenv is how you remove an env variable in Windows
|
||||
putenv(const_cast<char*>("MOZ_USING_SERVICE="));
|
||||
|
||||
free(cmdLine);
|
||||
return updateWasSuccessful;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ import sys
|
|||
import atexit
|
||||
import shared_telemetry_utils as utils
|
||||
|
||||
from ctypes import c_int
|
||||
from shared_telemetry_utils import ParserError
|
||||
from collections import OrderedDict
|
||||
atexit.register(ParserError.exit_func)
|
||||
|
@ -517,6 +518,11 @@ associated with the histogram. Returns None if no guarding is necessary."""
|
|||
ParserError('Value for key "{0}" in histogram "{1}" should be {2}.'
|
||||
.format(key, name, nice_type_name(key_type))).handle_later()
|
||||
|
||||
# Make sure the max range is lower than or equal to INT_MAX
|
||||
if "high" in definition and not c_int(definition["high"]).value > 0:
|
||||
ParserError('Value for high in histogram "{0}" should be lower or equal to INT_MAX.'
|
||||
.format(nice_type_name(c_int))).handle_later()
|
||||
|
||||
for key, key_type in type_checked_list_fields.iteritems():
|
||||
if key not in definition:
|
||||
continue
|
||||
|
|
|
@ -122,6 +122,29 @@ class TestParser(unittest.TestCase):
|
|||
|
||||
parse_histograms.whitelists = None
|
||||
|
||||
def test_high_value(self):
|
||||
SAMPLE_HISTOGRAM = {
|
||||
"TEST_HISTOGRAM_WHITELIST_N_BUCKETS": {
|
||||
"record_in_processes": ["main", "content"],
|
||||
"alert_emails": ["team@mozilla.xyz"],
|
||||
"bug_numbers": [1383793],
|
||||
"expires_in_version": "never",
|
||||
"kind": "exponential",
|
||||
"low": 1024,
|
||||
"high": 2 ** 64,
|
||||
"n_buckets": 100,
|
||||
"description": "Test histogram",
|
||||
}
|
||||
}
|
||||
histograms = load_histogram(SAMPLE_HISTOGRAM)
|
||||
parse_histograms.load_whitelist()
|
||||
|
||||
parse_histograms.Histogram('TEST_HISTOGRAM_WHITELIST_N_BUCKETS',
|
||||
histograms['TEST_HISTOGRAM_WHITELIST_N_BUCKETS'],
|
||||
strict_type_checks=True)
|
||||
|
||||
self.assertRaises(SystemExit, ParserError.exit_func)
|
||||
|
||||
def test_high_n_buckets(self):
|
||||
SAMPLE_HISTOGRAM = {
|
||||
"TEST_HISTOGRAM_WHITELIST_N_BUCKETS": {
|
||||
|
|
|
@ -92,10 +92,6 @@ def main():
|
|||
# Allow overwriting of the upload url with an environmental variable
|
||||
if 'SOCORRO_SYMBOL_UPLOAD_URL' in os.environ:
|
||||
url = os.environ['SOCORRO_SYMBOL_UPLOAD_URL']
|
||||
elif os.environ.get('MOZ_SCM_LEVEL', '1') == '1':
|
||||
# Use the Tecken staging server for try uploads for now.
|
||||
# This will eventually be changed in bug 1138617.
|
||||
url = 'https://symbols.stage.mozaws.net/upload/'
|
||||
else:
|
||||
url = DEFAULT_URL
|
||||
|
||||
|
|
|
@ -3092,7 +3092,7 @@ int NS_main(int argc, NS_tchar **argv)
|
|||
return 1;
|
||||
}
|
||||
|
||||
wchar_t *cmdLine = MakeCommandLine(argc - 1, argv + 1);
|
||||
auto cmdLine = mozilla::MakeCommandLine(argc - 1, argv + 1);
|
||||
if (!cmdLine) {
|
||||
CloseHandle(elevatedFileHandle);
|
||||
return 1;
|
||||
|
@ -3238,12 +3238,11 @@ int NS_main(int argc, NS_tchar **argv)
|
|||
SEE_MASK_NOCLOSEPROCESS;
|
||||
sinfo.hwnd = nullptr;
|
||||
sinfo.lpFile = argv[0];
|
||||
sinfo.lpParameters = cmdLine;
|
||||
sinfo.lpParameters = cmdLine.get();
|
||||
sinfo.lpVerb = L"runas";
|
||||
sinfo.nShow = SW_SHOWNORMAL;
|
||||
|
||||
bool result = ShellExecuteEx(&sinfo);
|
||||
free(cmdLine);
|
||||
|
||||
if (result) {
|
||||
WaitForSingleObject(sinfo.hProcess, INFINITE);
|
||||
|
|
|
@ -17,3 +17,8 @@
|
|||
.toolbar-landscape-page {
|
||||
list-style-image: url("moz-icon://stock/gtk-orientation-landscape?size=button");
|
||||
}
|
||||
|
||||
#pageNumber {
|
||||
/* 3 chars + 4px padding left + 2px padding right + 2*6px border */
|
||||
width: calc(18px + 3ch);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,390 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=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 https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_CmdLineAndEnvUtils_h
|
||||
#define mozilla_CmdLineAndEnvUtils_h
|
||||
|
||||
// NB: This code may be used outside of xul and thus must not depend on XPCOM
|
||||
|
||||
#if defined(MOZILLA_INTERNAL_API)
|
||||
#include "prenv.h"
|
||||
#include "prprf.h"
|
||||
#include <string.h>
|
||||
#elif defined(XP_WIN)
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#if defined(XP_WIN)
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/Vector.h"
|
||||
|
||||
#include <wchar.h>
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
#include "mozilla/TypedEnumBits.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Undo X11/X.h's definition of None
|
||||
#undef None
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
enum ArgResult {
|
||||
ARG_NONE = 0,
|
||||
ARG_FOUND = 1,
|
||||
ARG_BAD = 2 // you wanted a param, but there isn't one
|
||||
};
|
||||
|
||||
template <typename CharT>
|
||||
inline void
|
||||
RemoveArg(int& argc, CharT **argv)
|
||||
{
|
||||
do {
|
||||
*argv = *(argv + 1);
|
||||
++argv;
|
||||
} while (*argv);
|
||||
|
||||
--argc;
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <typename FuncT, typename CharT>
|
||||
inline bool
|
||||
strimatch(FuncT aToLowerFn, const CharT* lowerstr, const CharT* mixedstr)
|
||||
{
|
||||
while(*lowerstr) {
|
||||
if (!*mixedstr) return false; // mixedstr is shorter
|
||||
if (static_cast<CharT>(aToLowerFn(*mixedstr)) != *lowerstr) return false; // no match
|
||||
|
||||
++lowerstr;
|
||||
++mixedstr;
|
||||
}
|
||||
|
||||
if (*mixedstr) return false; // lowerstr is shorter
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
inline bool
|
||||
strimatch(const char* lowerstr, const char* mixedstr)
|
||||
{
|
||||
return internal::strimatch(&tolower, lowerstr, mixedstr);
|
||||
}
|
||||
|
||||
inline bool
|
||||
strimatch(const wchar_t* lowerstr, const wchar_t* mixedstr)
|
||||
{
|
||||
return internal::strimatch(&towlower, lowerstr, mixedstr);
|
||||
}
|
||||
|
||||
enum class FlagLiteral
|
||||
{
|
||||
osint,
|
||||
safemode
|
||||
};
|
||||
|
||||
template <typename CharT, FlagLiteral Literal>
|
||||
inline const CharT* GetLiteral();
|
||||
|
||||
#define DECLARE_FLAG_LITERAL(enum_name, literal) \
|
||||
template <> inline \
|
||||
const char* GetLiteral<char, FlagLiteral::enum_name>() \
|
||||
{ \
|
||||
return literal; \
|
||||
} \
|
||||
\
|
||||
template <> inline \
|
||||
const wchar_t* GetLiteral<wchar_t, FlagLiteral::enum_name>() \
|
||||
{ \
|
||||
return L##literal; \
|
||||
}
|
||||
|
||||
DECLARE_FLAG_LITERAL(osint, "osint")
|
||||
DECLARE_FLAG_LITERAL(safemode, "safe-mode")
|
||||
|
||||
enum class CheckArgFlag : uint32_t
|
||||
{
|
||||
None = 0,
|
||||
CheckOSInt = (1 << 0), // Retrun ARG_BAD if osint arg is also present.
|
||||
RemoveArg = (1 << 1) // Remove the argument from the argv array.
|
||||
};
|
||||
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(CheckArgFlag)
|
||||
|
||||
/**
|
||||
* Check for a commandline flag. If the flag takes a parameter, the
|
||||
* parameter is returned in aParam. Flags may be in the form -arg or
|
||||
* --arg (or /arg on win32).
|
||||
*
|
||||
* @param aArgc The argc value.
|
||||
* @param aArgv The original argv.
|
||||
* @param aArg the parameter to check. Must be lowercase.
|
||||
* @param aParam if non-null, the -arg <data> will be stored in this pointer.
|
||||
* This is *not* allocated, but rather a pointer to the argv data.
|
||||
* @param aFlags Flags @see CheckArgFlag
|
||||
*/
|
||||
template <typename CharT>
|
||||
inline ArgResult
|
||||
CheckArg(int& aArgc, CharT** aArgv, const CharT* aArg, const CharT **aParam,
|
||||
CheckArgFlag aFlags)
|
||||
{
|
||||
MOZ_ASSERT(aArgv && aArg);
|
||||
|
||||
CharT **curarg = aArgv + 1; // skip argv[0]
|
||||
ArgResult ar = ARG_NONE;
|
||||
|
||||
while (*curarg) {
|
||||
CharT *arg = curarg[0];
|
||||
|
||||
if (arg[0] == '-'
|
||||
#if defined(XP_WIN)
|
||||
|| *arg == '/'
|
||||
#endif
|
||||
) {
|
||||
++arg;
|
||||
|
||||
if (*arg == '-') {
|
||||
++arg;
|
||||
}
|
||||
|
||||
if (strimatch(aArg, arg)) {
|
||||
if (aFlags & CheckArgFlag::RemoveArg) {
|
||||
RemoveArg(aArgc, curarg);
|
||||
} else {
|
||||
++curarg;
|
||||
}
|
||||
|
||||
if (!aParam) {
|
||||
ar = ARG_FOUND;
|
||||
break;
|
||||
}
|
||||
|
||||
if (*curarg) {
|
||||
if (**curarg == '-'
|
||||
#if defined(XP_WIN)
|
||||
|| **curarg == '/'
|
||||
#endif
|
||||
) {
|
||||
return ARG_BAD;
|
||||
}
|
||||
|
||||
*aParam = *curarg;
|
||||
|
||||
if (aFlags & CheckArgFlag::RemoveArg) {
|
||||
RemoveArg(aArgc, curarg);
|
||||
}
|
||||
|
||||
ar = ARG_FOUND;
|
||||
break;
|
||||
}
|
||||
|
||||
return ARG_BAD;
|
||||
}
|
||||
}
|
||||
|
||||
++curarg;
|
||||
}
|
||||
|
||||
if ((aFlags & CheckArgFlag::CheckOSInt) && ar == ARG_FOUND) {
|
||||
ArgResult arOSInt = CheckArg(aArgc, aArgv,
|
||||
GetLiteral<CharT, FlagLiteral::osint>(),
|
||||
static_cast<const CharT**>(nullptr),
|
||||
CheckArgFlag::None);
|
||||
if (arOSInt == ARG_FOUND) {
|
||||
ar = ARG_BAD;
|
||||
#if defined(MOZILLA_INTERNAL_API)
|
||||
PR_fprintf(PR_STDERR, "Error: argument --osint is invalid\n");
|
||||
#endif // defined(MOZILLA_INTERNAL_API)
|
||||
}
|
||||
}
|
||||
|
||||
return ar;
|
||||
}
|
||||
|
||||
#if defined(XP_WIN)
|
||||
|
||||
namespace internal {
|
||||
|
||||
/**
|
||||
* Get the length that the string will take and takes into account the
|
||||
* additional length if the string needs to be quoted and if characters need to
|
||||
* be escaped.
|
||||
*/
|
||||
inline int
|
||||
ArgStrLen(const wchar_t *s)
|
||||
{
|
||||
int backslashes = 0;
|
||||
int i = wcslen(s);
|
||||
bool hasDoubleQuote = wcschr(s, L'"') != nullptr;
|
||||
// Only add doublequotes if the string contains a space or a tab
|
||||
bool addDoubleQuotes = wcspbrk(s, L" \t") != nullptr;
|
||||
|
||||
if (addDoubleQuotes) {
|
||||
i += 2; // initial and final duoblequote
|
||||
}
|
||||
|
||||
if (hasDoubleQuote) {
|
||||
while (*s) {
|
||||
if (*s == '\\') {
|
||||
++backslashes;
|
||||
} else {
|
||||
if (*s == '"') {
|
||||
// Escape the doublequote and all backslashes preceding the doublequote
|
||||
i += backslashes + 1;
|
||||
}
|
||||
|
||||
backslashes = 0;
|
||||
}
|
||||
|
||||
++s;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy string "s" to string "d", quoting the argument as appropriate and
|
||||
* escaping doublequotes along with any backslashes that immediately precede
|
||||
* doublequotes.
|
||||
* The CRT parses this to retrieve the original argc/argv that we meant,
|
||||
* see STDARGV.C in the MSVC CRT sources.
|
||||
*
|
||||
* @return the end of the string
|
||||
*/
|
||||
inline wchar_t*
|
||||
ArgToString(wchar_t *d, const wchar_t *s)
|
||||
{
|
||||
int backslashes = 0;
|
||||
bool hasDoubleQuote = wcschr(s, L'"') != nullptr;
|
||||
// Only add doublequotes if the string contains a space or a tab
|
||||
bool addDoubleQuotes = wcspbrk(s, L" \t") != nullptr;
|
||||
|
||||
if (addDoubleQuotes) {
|
||||
*d = '"'; // initial doublequote
|
||||
++d;
|
||||
}
|
||||
|
||||
if (hasDoubleQuote) {
|
||||
int i;
|
||||
while (*s) {
|
||||
if (*s == '\\') {
|
||||
++backslashes;
|
||||
} else {
|
||||
if (*s == '"') {
|
||||
// Escape the doublequote and all backslashes preceding the doublequote
|
||||
for (i = 0; i <= backslashes; ++i) {
|
||||
*d = '\\';
|
||||
++d;
|
||||
}
|
||||
}
|
||||
|
||||
backslashes = 0;
|
||||
}
|
||||
|
||||
*d = *s;
|
||||
++d; ++s;
|
||||
}
|
||||
} else {
|
||||
wcscpy(d, s);
|
||||
d += wcslen(s);
|
||||
}
|
||||
|
||||
if (addDoubleQuotes) {
|
||||
*d = '"'; // final doublequote
|
||||
++d;
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
/**
|
||||
* Creates a command line from a list of arguments.
|
||||
*/
|
||||
inline UniquePtr<wchar_t[]>
|
||||
MakeCommandLine(int argc, wchar_t **argv)
|
||||
{
|
||||
int i;
|
||||
int len = 0;
|
||||
|
||||
// The + 1 of the last argument handles the allocation for null termination
|
||||
for (i = 0; i < argc; ++i) {
|
||||
len += internal::ArgStrLen(argv[i]) + 1;
|
||||
}
|
||||
|
||||
// Protect against callers that pass 0 arguments
|
||||
if (len == 0) {
|
||||
len = 1;
|
||||
}
|
||||
|
||||
auto s = MakeUnique<wchar_t[]>(len);
|
||||
if (!s) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wchar_t *c = s.get();
|
||||
for (i = 0; i < argc; ++i) {
|
||||
c = internal::ArgToString(c, argv[i]);
|
||||
if (i + 1 != argc) {
|
||||
*c = ' ';
|
||||
++c;
|
||||
}
|
||||
}
|
||||
|
||||
*c = '\0';
|
||||
|
||||
return Move(s);
|
||||
}
|
||||
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
// Save literal putenv string to environment variable.
|
||||
inline void
|
||||
SaveToEnv(const char *aEnvString)
|
||||
{
|
||||
#if defined(MOZILLA_INTERNAL_API)
|
||||
char *expr = strdup(aEnvString);
|
||||
if (expr) {
|
||||
PR_SetEnv(expr);
|
||||
}
|
||||
|
||||
// We intentionally leak |expr| here since it is required by PR_SetEnv.
|
||||
MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(expr);
|
||||
#elif defined(XP_WIN)
|
||||
// This is the same as the NSPR implementation
|
||||
// (Note that we don't need to do a strdup for this case; the CRT makes a copy)
|
||||
_putenv(aEnvString);
|
||||
#else
|
||||
#error "Not implemented for this configuration"
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool
|
||||
EnvHasValue(const char* aVarName)
|
||||
{
|
||||
#if defined(MOZILLA_INTERNAL_API)
|
||||
const char* val = PR_GetEnv(aVarName);
|
||||
return val && *val;
|
||||
#elif defined(XP_WIN)
|
||||
// This is the same as the NSPR implementation
|
||||
const char* val = getenv(aVarName);
|
||||
return val && *val;
|
||||
#else
|
||||
#error "Not implemented for this configuration"
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_CmdLineAndEnvUtils_h
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=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 https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_PolicyChecks_h
|
||||
#define mozilla_PolicyChecks_h
|
||||
|
||||
#if defined(XP_WIN)
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
// NB: This code must be able to run apart from XPCOM
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
inline bool
|
||||
PolicyHasRegValue(HKEY aKey, LPCWSTR aName, DWORD* aValue)
|
||||
{
|
||||
DWORD len = sizeof(DWORD);
|
||||
LONG ret = ::RegGetValueW(aKey, L"SOFTWARE\\Policies\\Mozilla\\Firefox", aName,
|
||||
RRF_RT_DWORD, nullptr, aValue, &len);
|
||||
return ret == ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
inline bool
|
||||
PolicyCheckBoolean(LPCWSTR aPolicyName)
|
||||
{
|
||||
DWORD value;
|
||||
if (PolicyHasRegValue(HKEY_LOCAL_MACHINE, aPolicyName, &value)) {
|
||||
return value == 1;
|
||||
}
|
||||
|
||||
if (PolicyHasRegValue(HKEY_CURRENT_USER, aPolicyName, &value)) {
|
||||
return value == 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
#endif // mozilla_PolicyChecks_h
|
|
@ -0,0 +1,93 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=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 https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_SafeMode_h
|
||||
#define mozilla_SafeMode_h
|
||||
|
||||
// NB: This code must be able to run apart from XPCOM
|
||||
|
||||
#include "mozilla/CmdLineAndEnvUtils.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
#include "mozilla/PolicyChecks.h"
|
||||
#include <windows.h>
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
// Undo X11/X.h's definition of None
|
||||
#undef None
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
enum class SafeModeFlag : uint32_t
|
||||
{
|
||||
None = 0,
|
||||
Unset = (1 << 0)
|
||||
};
|
||||
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(SafeModeFlag)
|
||||
|
||||
template <typename CharT>
|
||||
inline Maybe<bool>
|
||||
IsSafeModeRequested(int& aArgc, CharT* aArgv[],
|
||||
const SafeModeFlag aFlags = SafeModeFlag::Unset)
|
||||
{
|
||||
CheckArgFlag checkArgFlags = CheckArgFlag::CheckOSInt;
|
||||
if (aFlags & SafeModeFlag::Unset) {
|
||||
checkArgFlags |= CheckArgFlag::RemoveArg;
|
||||
}
|
||||
|
||||
ArgResult ar = CheckArg(aArgc, aArgv,
|
||||
GetLiteral<CharT, FlagLiteral::safemode>(),
|
||||
static_cast<const CharT**>(nullptr),
|
||||
checkArgFlags);
|
||||
if (ar == ARG_BAD) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
bool result = ar == ARG_FOUND;
|
||||
|
||||
#if defined(XP_WIN)
|
||||
// If the shift key is pressed and the ctrl and / or alt keys are not pressed
|
||||
// during startup, start in safe mode. GetKeyState returns a short and the high
|
||||
// order bit will be 1 if the key is pressed. By masking the returned short
|
||||
// with 0x8000 the result will be 0 if the key is not pressed and non-zero
|
||||
// otherwise.
|
||||
if ((GetKeyState(VK_SHIFT) & 0x8000) &&
|
||||
!(GetKeyState(VK_CONTROL) & 0x8000) &&
|
||||
!(GetKeyState(VK_MENU) & 0x8000) &&
|
||||
!EnvHasValue("MOZ_DISABLE_SAFE_MODE_KEY")) {
|
||||
result = true;
|
||||
}
|
||||
|
||||
if (result && PolicyCheckBoolean(L"DisableSafeMode")) {
|
||||
result = false;
|
||||
}
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
if ((GetCurrentEventKeyModifiers() & optionKey) &&
|
||||
!EnvHasValue("MOZ_DISABLE_SAFE_MODE_KEY")) {
|
||||
result = true;
|
||||
}
|
||||
#endif // defined(XP_MACOSX)
|
||||
|
||||
// The Safe Mode Policy should not be enforced for the env var case
|
||||
// (used by updater and crash-recovery).
|
||||
if (EnvHasValue("MOZ_SAFE_MODE_RESTART")) {
|
||||
result = true;
|
||||
if (aFlags & SafeModeFlag::Unset) {
|
||||
// unset the env variable
|
||||
SaveToEnv("MOZ_SAFE_MODE_RESTART=");
|
||||
}
|
||||
}
|
||||
|
||||
return Some(result);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_SafeMode_h
|
|
@ -30,13 +30,19 @@ EXPORTS += [
|
|||
'nsIAppStartupNotifier.h',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla += ['AutoSQLiteLifetime.h', 'Bootstrap.h']
|
||||
EXPORTS.mozilla += [
|
||||
'AutoSQLiteLifetime.h',
|
||||
'Bootstrap.h',
|
||||
'CmdLineAndEnvUtils.h',
|
||||
'SafeMode.h',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_INSTRUMENT_EVENT_LOOP']:
|
||||
EXPORTS += ['EventTracer.h']
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
EXPORTS.mozilla += [
|
||||
'PolicyChecks.h',
|
||||
'WinDllServices.h',
|
||||
]
|
||||
SOURCES += [
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ChaosMode.h"
|
||||
#include "mozilla/CmdLineAndEnvUtils.h"
|
||||
#include "mozilla/IOInterposer.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/MemoryChecking.h"
|
||||
|
@ -232,6 +233,7 @@
|
|||
#endif
|
||||
|
||||
#include "mozilla/mozalloc_oom.h"
|
||||
#include "SafeMode.h"
|
||||
|
||||
extern uint32_t gRestartMode;
|
||||
extern void InstallSignalHandlers(const char *ProgramName);
|
||||
|
@ -306,25 +308,6 @@ using mozilla::dom::ContentParent;
|
|||
using mozilla::dom::ContentChild;
|
||||
using mozilla::intl::LocaleService;
|
||||
|
||||
// Save literal putenv string to environment variable.
|
||||
static void
|
||||
SaveToEnv(const char *putenv)
|
||||
{
|
||||
char *expr = strdup(putenv);
|
||||
if (expr)
|
||||
PR_SetEnv(expr);
|
||||
// We intentionally leak |expr| here since it is required by PR_SetEnv.
|
||||
MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(expr);
|
||||
}
|
||||
|
||||
// Tests that an environment variable exists and has a value
|
||||
static bool
|
||||
EnvHasValue(const char *name)
|
||||
{
|
||||
const char *val = PR_GetEnv(name);
|
||||
return (val && *val);
|
||||
}
|
||||
|
||||
// Save the given word to the specified environment variable.
|
||||
static void
|
||||
SaveWordToEnv(const char *name, const nsACString & word)
|
||||
|
@ -400,22 +383,6 @@ SaveFileToEnvIfUnset(const char *name, nsIFile *file)
|
|||
SaveFileToEnv(name, file);
|
||||
}
|
||||
|
||||
static bool
|
||||
strimatch(const char* lowerstr, const char* mixedstr)
|
||||
{
|
||||
while(*lowerstr) {
|
||||
if (!*mixedstr) return false; // mixedstr is shorter
|
||||
if (tolower(*mixedstr) != *lowerstr) return false; // no match
|
||||
|
||||
++lowerstr;
|
||||
++mixedstr;
|
||||
}
|
||||
|
||||
if (*mixedstr) return false; // lowerstr is shorter
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool gIsExpectedExit = false;
|
||||
|
||||
void MozExpectedExit() {
|
||||
|
@ -482,94 +449,22 @@ enum RemoteResult {
|
|||
REMOTE_ARG_BAD = 2
|
||||
};
|
||||
|
||||
enum ArgResult {
|
||||
ARG_NONE = 0,
|
||||
ARG_FOUND = 1,
|
||||
ARG_BAD = 2 // you wanted a param, but there isn't one
|
||||
};
|
||||
|
||||
static void RemoveArg(char **argv)
|
||||
{
|
||||
do {
|
||||
*argv = *(argv + 1);
|
||||
++argv;
|
||||
} while (*argv);
|
||||
|
||||
--gArgc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for a commandline flag. If the flag takes a parameter, the
|
||||
* parameter is returned in aParam. Flags may be in the form -arg or
|
||||
* --arg (or /arg on win32).
|
||||
*
|
||||
* @param aArg the parameter to check. Must be lowercase.
|
||||
* @param aCheckOSInt if true returns ARG_BAD if the osint argument is present
|
||||
* when aArg is also present.
|
||||
* @param aParam if non-null, the -arg <data> will be stored in this pointer.
|
||||
* This is *not* allocated, but rather a pointer to the argv data.
|
||||
* @param aRemArg if true, the argument is removed from the gArgv array.
|
||||
* @param aFlags flags @see CheckArgFlag
|
||||
*/
|
||||
static ArgResult
|
||||
CheckArg(const char* aArg, bool aCheckOSInt = false, const char **aParam = nullptr, bool aRemArg = true)
|
||||
CheckArg(const char* aArg, const char** aParam = nullptr,
|
||||
CheckArgFlag aFlags = CheckArgFlag::RemoveArg)
|
||||
{
|
||||
MOZ_ASSERT(gArgv, "gArgv must be initialized before CheckArg()");
|
||||
|
||||
char **curarg = gArgv + 1; // skip argv[0]
|
||||
ArgResult ar = ARG_NONE;
|
||||
|
||||
while (*curarg) {
|
||||
char *arg = curarg[0];
|
||||
|
||||
if (arg[0] == '-'
|
||||
#if defined(XP_WIN)
|
||||
|| *arg == '/'
|
||||
#endif
|
||||
) {
|
||||
++arg;
|
||||
if (*arg == '-')
|
||||
++arg;
|
||||
|
||||
if (strimatch(aArg, arg)) {
|
||||
if (aRemArg)
|
||||
RemoveArg(curarg);
|
||||
else
|
||||
++curarg;
|
||||
if (!aParam) {
|
||||
ar = ARG_FOUND;
|
||||
break;
|
||||
}
|
||||
|
||||
if (*curarg) {
|
||||
if (**curarg == '-'
|
||||
#if defined(XP_WIN)
|
||||
|| **curarg == '/'
|
||||
#endif
|
||||
)
|
||||
return ARG_BAD;
|
||||
|
||||
*aParam = *curarg;
|
||||
if (aRemArg)
|
||||
RemoveArg(curarg);
|
||||
ar = ARG_FOUND;
|
||||
break;
|
||||
}
|
||||
return ARG_BAD;
|
||||
}
|
||||
}
|
||||
|
||||
++curarg;
|
||||
}
|
||||
|
||||
if (aCheckOSInt && ar == ARG_FOUND) {
|
||||
ArgResult arOSInt = CheckArg("osint");
|
||||
if (arOSInt == ARG_FOUND) {
|
||||
ar = ARG_BAD;
|
||||
PR_fprintf(PR_STDERR, "Error: argument --osint is invalid\n");
|
||||
}
|
||||
}
|
||||
|
||||
return ar;
|
||||
return CheckArg(gArgc, gArgv, aArg, aParam, aFlags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -582,38 +477,7 @@ CheckArg(const char* aArg, bool aCheckOSInt = false, const char **aParam = nullp
|
|||
static ArgResult
|
||||
CheckArgExists(const char* aArg)
|
||||
{
|
||||
char **curarg = gArgv + 1; // skip argv[0]
|
||||
while (*curarg) {
|
||||
char *arg = curarg[0];
|
||||
|
||||
if (arg[0] == '-'
|
||||
#if defined(XP_WIN)
|
||||
|| *arg == '/'
|
||||
#endif
|
||||
) {
|
||||
++arg;
|
||||
if (*arg == '-')
|
||||
++arg;
|
||||
|
||||
char delimiter = '=';
|
||||
#if defined(XP_WIN)
|
||||
delimiter = ':';
|
||||
#endif
|
||||
int i;
|
||||
for (i = 0; arg[i] && arg[i] != delimiter; i++) {}
|
||||
char tmp = arg[i];
|
||||
arg[i] = '\0';
|
||||
bool found = strimatch(aArg, arg);
|
||||
arg[i] = tmp;
|
||||
if (found) {
|
||||
return ARG_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
++curarg;
|
||||
}
|
||||
|
||||
return ARG_NONE;
|
||||
return CheckArg(aArg, nullptr, CheckArgFlag::None);
|
||||
}
|
||||
|
||||
#if defined(XP_WIN)
|
||||
|
@ -1799,14 +1663,14 @@ ParseRemoteCommandLine(nsCString& program,
|
|||
{
|
||||
ArgResult ar;
|
||||
|
||||
ar = CheckArg("p", false, profile, false);
|
||||
ar = CheckArg("p", profile, CheckArgFlag::None);
|
||||
if (ar == ARG_BAD) {
|
||||
// Leave it to the normal command line handling to handle this situation.
|
||||
return REMOTE_NOT_FOUND;
|
||||
}
|
||||
|
||||
const char *temp = nullptr;
|
||||
ar = CheckArg("a", true, &temp);
|
||||
ar = CheckArg("a", &temp, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument -a requires an application name\n");
|
||||
return REMOTE_ARG_BAD;
|
||||
|
@ -1815,7 +1679,7 @@ ParseRemoteCommandLine(nsCString& program,
|
|||
program.Assign(temp);
|
||||
}
|
||||
|
||||
ar = CheckArg("u", true, username);
|
||||
ar = CheckArg("u", username, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument -u requires a username\n");
|
||||
return REMOTE_ARG_BAD;
|
||||
|
@ -2322,7 +2186,7 @@ SelectProfile(nsIProfileLock* *aResult, nsIToolkitProfileService* aProfileSvc, n
|
|||
*aResult = nullptr;
|
||||
*aStartOffline = false;
|
||||
|
||||
ar = CheckArg("offline", true);
|
||||
ar = CheckArg("offline", nullptr, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument --offline is invalid when argument --osint is specified\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -2344,7 +2208,7 @@ SelectProfile(nsIProfileLock* *aResult, nsIToolkitProfileService* aProfileSvc, n
|
|||
}
|
||||
|
||||
// reset-profile and migration args need to be checked before any profiles are chosen below.
|
||||
ar = CheckArg("reset-profile", true);
|
||||
ar = CheckArg("reset-profile", nullptr, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument --reset-profile is invalid when argument --osint is specified\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -2353,7 +2217,7 @@ SelectProfile(nsIProfileLock* *aResult, nsIToolkitProfileService* aProfileSvc, n
|
|||
gDoProfileReset = true;
|
||||
}
|
||||
|
||||
ar = CheckArg("migration", true);
|
||||
ar = CheckArg("migration", nullptr, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument --migration is invalid when argument --osint is specified\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -2380,8 +2244,8 @@ SelectProfile(nsIProfileLock* *aResult, nsIToolkitProfileService* aProfileSvc, n
|
|||
|
||||
// Clear out flags that we handled (or should have handled!) last startup.
|
||||
const char *dummy;
|
||||
CheckArg("p", false, &dummy);
|
||||
CheckArg("profile", false, &dummy);
|
||||
CheckArg("p", &dummy);
|
||||
CheckArg("profile", &dummy);
|
||||
CheckArg("profilemanager");
|
||||
|
||||
if (gDoProfileReset) {
|
||||
|
@ -2410,7 +2274,7 @@ SelectProfile(nsIProfileLock* *aResult, nsIToolkitProfileService* aProfileSvc, n
|
|||
return NS_LockProfilePath(lf, localDir, nullptr, aResult);
|
||||
}
|
||||
|
||||
ar = CheckArg("profile", true, &arg);
|
||||
ar = CheckArg("profile", &arg, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument --profile requires a path\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -2444,7 +2308,7 @@ SelectProfile(nsIProfileLock* *aResult, nsIToolkitProfileService* aProfileSvc, n
|
|||
return ProfileLockedDialog(lf, lf, unlocker, aNative, aResult);
|
||||
}
|
||||
|
||||
ar = CheckArg("createprofile", true, &arg);
|
||||
ar = CheckArg("createprofile", &arg, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument --createprofile requires a profile name\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -2500,7 +2364,7 @@ SelectProfile(nsIProfileLock* *aResult, nsIToolkitProfileService* aProfileSvc, n
|
|||
rv = aProfileSvc->GetProfileCount(&count);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
ar = CheckArg("p", false, &arg);
|
||||
ar = CheckArg("p", &arg);
|
||||
if (ar == ARG_BAD) {
|
||||
ar = CheckArg("osint");
|
||||
if (ar == ARG_FOUND) {
|
||||
|
@ -2565,7 +2429,7 @@ SelectProfile(nsIProfileLock* *aResult, nsIToolkitProfileService* aProfileSvc, n
|
|||
}
|
||||
}
|
||||
|
||||
ar = CheckArg("profilemanager", true);
|
||||
ar = CheckArg("profilemanager", nullptr, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument --profilemanager is invalid when argument --osint is specified\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -3161,33 +3025,6 @@ public:
|
|||
#endif
|
||||
};
|
||||
|
||||
#ifdef XP_WIN
|
||||
namespace {
|
||||
|
||||
bool PolicyHasRegValue(HKEY aKey, LPCWSTR aName, DWORD* aValue)
|
||||
{
|
||||
DWORD len = sizeof(DWORD);
|
||||
LONG ret = ::RegGetValueW(aKey, L"SOFTWARE\\Policies\\Mozilla\\Firefox", aName,
|
||||
RRF_RT_DWORD, nullptr, aValue, &len);
|
||||
return ret == ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
bool SafeModeBlockedByPolicy()
|
||||
{
|
||||
LPCTSTR policyName = L"DisableSafeMode";
|
||||
DWORD value;
|
||||
if (PolicyHasRegValue(HKEY_LOCAL_MACHINE, policyName, &value)) {
|
||||
return value == 1;
|
||||
}
|
||||
if (PolicyHasRegValue(HKEY_CURRENT_USER, policyName, &value)) {
|
||||
return value == 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
#endif // XP_WIN
|
||||
|
||||
#if defined(XP_UNIX) && !defined(ANDROID)
|
||||
static SmprintfPointer
|
||||
FormatUid(uid_t aId)
|
||||
|
@ -3366,7 +3203,7 @@ XREMain::XRE_mainInit(bool* aExitFlag)
|
|||
|
||||
// Check for application.ini overrides
|
||||
const char* override = nullptr;
|
||||
ar = CheckArg("override", true, &override);
|
||||
ar = CheckArg("override", &override, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
|
||||
if (ar == ARG_BAD) {
|
||||
Output(true, "Incorrect number of arguments passed to --override");
|
||||
return 1;
|
||||
|
@ -3586,49 +3423,12 @@ XREMain::XRE_mainInit(bool* aExitFlag)
|
|||
|
||||
gRestartArgv[gRestartArgc] = nullptr;
|
||||
|
||||
|
||||
ar = CheckArg("safe-mode", true);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument --safe-mode is invalid when argument --osint is specified\n");
|
||||
Maybe<bool> safeModeRequested = IsSafeModeRequested(gArgc, gArgv);
|
||||
if (!safeModeRequested) {
|
||||
return 1;
|
||||
}
|
||||
if (ar == ARG_FOUND) {
|
||||
gSafeMode = true;
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
// If the shift key is pressed and the ctrl and / or alt keys are not pressed
|
||||
// during startup start in safe mode. GetKeyState returns a short and the high
|
||||
// order bit will be 1 if the key is pressed. By masking the returned short
|
||||
// with 0x8000 the result will be 0 if the key is not pressed and non-zero
|
||||
// otherwise.
|
||||
if ((GetKeyState(VK_SHIFT) & 0x8000) &&
|
||||
!(GetKeyState(VK_CONTROL) & 0x8000) &&
|
||||
!(GetKeyState(VK_MENU) & 0x8000) &&
|
||||
!EnvHasValue("MOZ_DISABLE_SAFE_MODE_KEY")) {
|
||||
gSafeMode = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
if ((GetCurrentEventKeyModifiers() & optionKey) &&
|
||||
!EnvHasValue("MOZ_DISABLE_SAFE_MODE_KEY"))
|
||||
gSafeMode = true;
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
if (gSafeMode && SafeModeBlockedByPolicy()) {
|
||||
gSafeMode = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// The Safe Mode Policy should not be enforced for the env var case
|
||||
// (used by updater and crash-recovery).
|
||||
if (EnvHasValue("MOZ_SAFE_MODE_RESTART")) {
|
||||
gSafeMode = true;
|
||||
// unset the env variable
|
||||
SaveToEnv("MOZ_SAFE_MODE_RESTART=");
|
||||
}
|
||||
gSafeMode = safeModeRequested.value();
|
||||
|
||||
#ifdef XP_WIN
|
||||
{
|
||||
|
@ -3681,7 +3481,7 @@ if (gSafeMode && SafeModeBlockedByPolicy()) {
|
|||
// Handle --no-remote and --new-instance command line arguments. Setup
|
||||
// the environment to better accommodate other components and various
|
||||
// restart scenarios.
|
||||
ar = CheckArg("no-remote", true);
|
||||
ar = CheckArg("no-remote", nullptr, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument --no-remote is invalid when argument --osint is specified\n");
|
||||
return 1;
|
||||
|
@ -3690,7 +3490,7 @@ if (gSafeMode && SafeModeBlockedByPolicy()) {
|
|||
SaveToEnv("MOZ_NO_REMOTE=1");
|
||||
}
|
||||
|
||||
ar = CheckArg("new-instance", true);
|
||||
ar = CheckArg("new-instance", nullptr, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument --new-instance is invalid when argument --osint is specified\n");
|
||||
return 1;
|
||||
|
@ -3717,7 +3517,7 @@ if (gSafeMode && SafeModeBlockedByPolicy()) {
|
|||
NS_ENSURE_SUCCESS(rv, 1);
|
||||
|
||||
// Check for --register, which registers chrome and then exits immediately.
|
||||
ar = CheckArg("register", true);
|
||||
ar = CheckArg("register", nullptr, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument --register is invalid when argument --osint is specified\n");
|
||||
return 1;
|
||||
|
@ -4253,7 +4053,7 @@ XREMain::XRE_mainStartup(bool* aExitFlag)
|
|||
// to make sure that the maintenance service successfully launches the
|
||||
// callback application.
|
||||
const char *logFile = nullptr;
|
||||
if (ARG_FOUND == CheckArg("dump-args", false, &logFile)) {
|
||||
if (ARG_FOUND == CheckArg("dump-args", &logFile)) {
|
||||
FILE* logFP = fopen(logFile, "wb");
|
||||
if (logFP) {
|
||||
for (int i = 1; i < gRestartArgc; ++i) {
|
||||
|
@ -5108,7 +4908,7 @@ XRE_InitCommandLine(int aArgc, char* aArgv[])
|
|||
#endif
|
||||
|
||||
const char *path = nullptr;
|
||||
ArgResult ar = CheckArg("greomni", false, &path);
|
||||
ArgResult ar = CheckArg("greomni", &path);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument --greomni requires a path argument\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -5124,7 +4924,7 @@ XRE_InitCommandLine(int aArgc, char* aArgv[])
|
|||
return rv;
|
||||
}
|
||||
|
||||
ar = CheckArg("appomni", false, &path);
|
||||
ar = CheckArg("appomni", &path);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument --appomni requires a path argument\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#define nsWindowsRestart_cpp
|
||||
#endif
|
||||
|
||||
#include "mozilla/CmdLineAndEnvUtils.h"
|
||||
#include "nsUTF8Utils.h"
|
||||
|
||||
#include <shellapi.h>
|
||||
|
@ -19,135 +20,6 @@
|
|||
#include <userenv.h>
|
||||
#pragma comment(lib, "userenv.lib")
|
||||
|
||||
/**
|
||||
* Get the length that the string will take and takes into account the
|
||||
* additional length if the string needs to be quoted and if characters need to
|
||||
* be escaped.
|
||||
*/
|
||||
static int ArgStrLen(const wchar_t *s)
|
||||
{
|
||||
int backslashes = 0;
|
||||
int i = wcslen(s);
|
||||
BOOL hasDoubleQuote = wcschr(s, L'"') != nullptr;
|
||||
// Only add doublequotes if the string contains a space or a tab
|
||||
BOOL addDoubleQuotes = wcspbrk(s, L" \t") != nullptr;
|
||||
|
||||
if (addDoubleQuotes) {
|
||||
i += 2; // initial and final duoblequote
|
||||
}
|
||||
|
||||
if (hasDoubleQuote) {
|
||||
while (*s) {
|
||||
if (*s == '\\') {
|
||||
++backslashes;
|
||||
} else {
|
||||
if (*s == '"') {
|
||||
// Escape the doublequote and all backslashes preceding the doublequote
|
||||
i += backslashes + 1;
|
||||
}
|
||||
|
||||
backslashes = 0;
|
||||
}
|
||||
|
||||
++s;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy string "s" to string "d", quoting the argument as appropriate and
|
||||
* escaping doublequotes along with any backslashes that immediately precede
|
||||
* doublequotes.
|
||||
* The CRT parses this to retrieve the original argc/argv that we meant,
|
||||
* see STDARGV.C in the MSVC CRT sources.
|
||||
*
|
||||
* @return the end of the string
|
||||
*/
|
||||
static wchar_t* ArgToString(wchar_t *d, const wchar_t *s)
|
||||
{
|
||||
int backslashes = 0;
|
||||
BOOL hasDoubleQuote = wcschr(s, L'"') != nullptr;
|
||||
// Only add doublequotes if the string contains a space or a tab
|
||||
BOOL addDoubleQuotes = wcspbrk(s, L" \t") != nullptr;
|
||||
|
||||
if (addDoubleQuotes) {
|
||||
*d = '"'; // initial doublequote
|
||||
++d;
|
||||
}
|
||||
|
||||
if (hasDoubleQuote) {
|
||||
int i;
|
||||
while (*s) {
|
||||
if (*s == '\\') {
|
||||
++backslashes;
|
||||
} else {
|
||||
if (*s == '"') {
|
||||
// Escape the doublequote and all backslashes preceding the doublequote
|
||||
for (i = 0; i <= backslashes; ++i) {
|
||||
*d = '\\';
|
||||
++d;
|
||||
}
|
||||
}
|
||||
|
||||
backslashes = 0;
|
||||
}
|
||||
|
||||
*d = *s;
|
||||
++d; ++s;
|
||||
}
|
||||
} else {
|
||||
wcscpy(d, s);
|
||||
d += wcslen(s);
|
||||
}
|
||||
|
||||
if (addDoubleQuotes) {
|
||||
*d = '"'; // final doublequote
|
||||
++d;
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a command line from a list of arguments. The returned
|
||||
* string is allocated with "malloc" and should be "free"d.
|
||||
*
|
||||
* argv is UTF8
|
||||
*/
|
||||
wchar_t*
|
||||
MakeCommandLine(int argc, wchar_t **argv)
|
||||
{
|
||||
int i;
|
||||
int len = 0;
|
||||
|
||||
// The + 1 of the last argument handles the allocation for null termination
|
||||
for (i = 0; i < argc; ++i)
|
||||
len += ArgStrLen(argv[i]) + 1;
|
||||
|
||||
// Protect against callers that pass 0 arguments
|
||||
if (len == 0)
|
||||
len = 1;
|
||||
|
||||
wchar_t *s = (wchar_t*) malloc(len * sizeof(wchar_t));
|
||||
if (!s)
|
||||
return nullptr;
|
||||
|
||||
wchar_t *c = s;
|
||||
for (i = 0; i < argc; ++i) {
|
||||
c = ArgToString(c, argv[i]);
|
||||
if (i + 1 != argc) {
|
||||
*c = ' ';
|
||||
++c;
|
||||
}
|
||||
}
|
||||
|
||||
*c = '\0';
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert UTF8 to UTF16 without using the normal XPCOM goop, which we
|
||||
* can't link to updater.exe.
|
||||
|
@ -222,10 +94,9 @@ WinLaunchChild(const wchar_t *exePath,
|
|||
HANDLE userToken,
|
||||
HANDLE *hProcess)
|
||||
{
|
||||
wchar_t *cl;
|
||||
BOOL ok;
|
||||
|
||||
cl = MakeCommandLine(argc, argv);
|
||||
mozilla::UniquePtr<wchar_t[]> cl(mozilla::MakeCommandLine(argc, argv));
|
||||
if (!cl) {
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -237,7 +108,7 @@ WinLaunchChild(const wchar_t *exePath,
|
|||
|
||||
if (userToken == nullptr) {
|
||||
ok = CreateProcessW(exePath,
|
||||
cl,
|
||||
cl.get(),
|
||||
nullptr, // no special security attributes
|
||||
nullptr, // no special thread attributes
|
||||
FALSE, // don't inherit filehandles
|
||||
|
@ -256,7 +127,7 @@ WinLaunchChild(const wchar_t *exePath,
|
|||
|
||||
ok = CreateProcessAsUserW(userToken,
|
||||
exePath,
|
||||
cl,
|
||||
cl.get(),
|
||||
nullptr, // no special security attributes
|
||||
nullptr, // no special thread attributes
|
||||
FALSE, // don't inherit filehandles
|
||||
|
@ -294,7 +165,5 @@ WinLaunchChild(const wchar_t *exePath,
|
|||
LocalFree(lpMsgBuf);
|
||||
}
|
||||
|
||||
free(cl);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
* 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/. */
|
||||
|
||||
#ifndef nsWindowsWMain_cpp
|
||||
#define nsWindowsWMain_cpp
|
||||
|
||||
// This file is a .cpp file meant to be included in nsBrowserApp.cpp and other
|
||||
// similar bootstrap code. It converts wide-character windows wmain into UTF-8
|
||||
// narrow-character strings.
|
||||
|
@ -101,6 +104,14 @@ int wmain(int argc, WCHAR **argv)
|
|||
SanitizeEnvironmentVariables();
|
||||
SetDllDirectoryW(L"");
|
||||
|
||||
// Only run this code if LauncherProcessWin.h was included beforehand, thus
|
||||
// signalling that the hosting process should support launcher mode.
|
||||
#if defined(mozilla_LauncherProcessWin_h)
|
||||
if (mozilla::RunAsLauncherProcess(argc, argv)) {
|
||||
return mozilla::LauncherMain(argc, argv);
|
||||
}
|
||||
#endif // defined(mozilla_LauncherProcessWin_h)
|
||||
|
||||
char **argvConverted = new char*[argc + 1];
|
||||
if (!argvConverted)
|
||||
return 127;
|
||||
|
@ -134,3 +145,5 @@ int wmain(int argc, WCHAR **argv)
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // nsWindowsWMain_cpp
|
||||
|
|
|
@ -69,10 +69,10 @@ verifyCmdLineCreation(wchar_t *inCmdLine,
|
|||
wcscat(inCmdLineNew, inCmdLine);
|
||||
LPWSTR *inArgv = CommandLineToArgvW(inCmdLineNew, &inArgc);
|
||||
|
||||
wchar_t *outCmdLine = MakeCommandLine(inArgc - 1, inArgv + 1);
|
||||
wchar_t *outCmdLineNew = (wchar_t *) malloc((wcslen(DUMMY_ARG1) + wcslen(outCmdLine) + 1) * sizeof(wchar_t));
|
||||
auto outCmdLine = mozilla::MakeCommandLine(inArgc - 1, inArgv + 1);
|
||||
wchar_t *outCmdLineNew = (wchar_t *) malloc((wcslen(DUMMY_ARG1) + wcslen(outCmdLine.get()) + 1) * sizeof(wchar_t));
|
||||
wcscpy(outCmdLineNew, DUMMY_ARG1);
|
||||
wcscat(outCmdLineNew, outCmdLine);
|
||||
wcscat(outCmdLineNew, outCmdLine.get());
|
||||
LPWSTR *outArgv = CommandLineToArgvW(outCmdLineNew, &outArgc);
|
||||
|
||||
if (VERBOSE) {
|
||||
|
@ -80,7 +80,7 @@ verifyCmdLineCreation(wchar_t *inCmdLine,
|
|||
wprintf(L"Verbose Output\n");
|
||||
wprintf(L"--------------\n");
|
||||
wprintf(L"Input command line : >%s<\n", inCmdLine);
|
||||
wprintf(L"MakeComandLine output: >%s<\n", outCmdLine);
|
||||
wprintf(L"MakeComandLine output: >%s<\n", outCmdLine.get());
|
||||
wprintf(L"Expected command line: >%s<\n", compareCmdLine);
|
||||
|
||||
wprintf(L"input argc : %d\n", inArgc - 1);
|
||||
|
@ -107,7 +107,6 @@ verifyCmdLineCreation(wchar_t *inCmdLine,
|
|||
LocalFree(outArgv);
|
||||
free(inCmdLineNew);
|
||||
free(outCmdLineNew);
|
||||
free(outCmdLine);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -123,12 +122,11 @@ verifyCmdLineCreation(wchar_t *inCmdLine,
|
|||
LocalFree(outArgv);
|
||||
free(inCmdLineNew);
|
||||
free(outCmdLineNew);
|
||||
free(outCmdLine);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
isEqual = (wcscmp(outCmdLine, compareCmdLine) == 0);
|
||||
isEqual = (wcscmp(outCmdLine.get(), compareCmdLine) == 0);
|
||||
if (!isEqual) {
|
||||
wprintf(L"TEST-%s-FAIL | %s | Command Line Comparison (check %2d)\n",
|
||||
passes ? L"UNEXPECTED" : L"KNOWN", TEST_NAME, testNum);
|
||||
|
@ -139,7 +137,6 @@ verifyCmdLineCreation(wchar_t *inCmdLine,
|
|||
LocalFree(outArgv);
|
||||
free(inCmdLineNew);
|
||||
free(outCmdLineNew);
|
||||
free(outCmdLine);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -156,7 +153,6 @@ verifyCmdLineCreation(wchar_t *inCmdLine,
|
|||
LocalFree(outArgv);
|
||||
free(inCmdLineNew);
|
||||
free(outCmdLineNew);
|
||||
free(outCmdLine);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче