зеркало из https://github.com/mozilla/gecko-dev.git
Merge fx-team to central, a=merge
--HG-- extra : commitid : KwOnWVSJFTU
This commit is contained in:
Коммит
fbb52f9651
|
@ -382,6 +382,7 @@ html[dir="rtl"] .room-entry-context-actions > .dropdown-menu {
|
|||
right: 21px;
|
||||
bottom: auto;
|
||||
left: auto;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* Keep ".room-list > .room-entry > h2" in sync with these. */
|
||||
|
|
|
@ -727,7 +727,7 @@
|
|||
|
||||
let engine;
|
||||
let oneOff = this.selectedButton;
|
||||
if (oneOff && !this.selectionFromMouseOver) {
|
||||
if (oneOff) {
|
||||
if (!oneOff.engine) {
|
||||
oneOff.doCommand();
|
||||
this.mEnterEvent = null;
|
||||
|
@ -749,11 +749,19 @@
|
|||
<field name="_selectedButton"/>
|
||||
<property name="selectedButton" onget="return this._selectedButton;">
|
||||
<setter><![CDATA[
|
||||
// Set to true from the mouseover handler right after this setter call.
|
||||
this.selectionFromMouseOver = false;
|
||||
|
||||
if (this._selectedButton)
|
||||
this._selectedButton.removeAttribute("selected");
|
||||
this._changeVisuallySelectedButton(val, true);
|
||||
]]></setter>
|
||||
</property>
|
||||
<method name="_changeVisuallySelectedButton">
|
||||
<parameter name="val"/>
|
||||
<parameter name="aUpdateLogicallySelectedButton"/>
|
||||
<body><![CDATA[
|
||||
let list = this.getSelectableButtons();
|
||||
let visuallySelectedButton = list.find(button => {
|
||||
return button.getAttribute("selected") == "true"
|
||||
});
|
||||
if (visuallySelectedButton)
|
||||
visuallySelectedButton.removeAttribute("selected");
|
||||
|
||||
let textbox = document.getBindingParent(this).textbox;
|
||||
let header =
|
||||
|
@ -762,6 +770,7 @@
|
|||
// Avoid selecting dummy buttons.
|
||||
if (val && !val.classList.contains("dummy")) {
|
||||
val.setAttribute("selected", "true");
|
||||
if (aUpdateLogicallySelectedButton)
|
||||
this._selectedButton = val;
|
||||
if (val.classList.contains("searchbar-engine-one-off-item")) {
|
||||
let headerEngineText =
|
||||
|
@ -774,14 +783,14 @@
|
|||
header.selectedIndex = textbox.value ? 1 : 0;
|
||||
}
|
||||
this.setAttribute("aria-activedescendant", val.id);
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
header.selectedIndex = textbox.value ? 1 : 0;
|
||||
this.removeAttribute("aria-activedescendant");
|
||||
if (aUpdateLogicallySelectedButton)
|
||||
this._selectedButton = null;
|
||||
]]></setter>
|
||||
</property>
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="getSelectableButtons">
|
||||
<parameter name="aCycleEngines"/>
|
||||
|
@ -1368,23 +1377,30 @@
|
|||
target.classList.contains("addengine-item") ||
|
||||
target.classList.contains("search-setting-button")) {
|
||||
let textbox = document.getElementById("searchbar").textbox;
|
||||
textbox.selectedButton = target;
|
||||
textbox.selectionFromMouseOver = true;
|
||||
textbox._changeVisuallySelectedButton(target);
|
||||
}
|
||||
]]></handler>
|
||||
|
||||
<handler event="mouseout"><![CDATA[
|
||||
let target = event.originalTarget;
|
||||
if (target.localName != "button")
|
||||
if (target.localName != "button") {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't deselect the current button if the context menu is open.
|
||||
if (this._ignoreMouseEvents)
|
||||
return;
|
||||
|
||||
let textbox = document.getElementById("searchbar").textbox;
|
||||
if (textbox.selectedButton == target)
|
||||
textbox.selectedButton = null;
|
||||
// Unfortunately this will fire before mouseover hits another item.
|
||||
// If this button is selected, we replace that selection only if
|
||||
// we're not moving to a different one-off item:
|
||||
if (target.getAttribute("selected") == "true" &&
|
||||
(!event.relatedTarget ||
|
||||
!event.relatedTarget.classList.contains("searchbar-engine-one-off-item") ||
|
||||
event.relatedTarget.classList.contains("dummy"))) {
|
||||
textbox._changeVisuallySelectedButton(textbox.selectedButton);
|
||||
}
|
||||
]]></handler>
|
||||
|
||||
<handler event="click"><![CDATA[
|
||||
|
|
|
@ -13,6 +13,8 @@ var EventEmitter = require("devtools/shared/event-emitter");
|
|||
var clipboard = require("sdk/clipboard");
|
||||
var {HostType} = require("devtools/client/framework/toolbox").Toolbox;
|
||||
|
||||
loader.lazyRequireGetter(this, "CSS", "CSS");
|
||||
|
||||
loader.lazyGetter(this, "MarkupView", () => require("devtools/client/markupview/markup-view").MarkupView);
|
||||
loader.lazyGetter(this, "HTMLBreadcrumbs", () => require("devtools/client/inspector/breadcrumbs").HTMLBreadcrumbs);
|
||||
loader.lazyGetter(this, "ToolSidebar", () => require("devtools/client/framework/sidebar").ToolSidebar);
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
"use strict";
|
||||
|
||||
const {Cc, Ci, Cu} = require("chrome");
|
||||
Cu.importGlobalProperties(["CSS"]);
|
||||
loader.lazyRequireGetter(this, "CSS", "CSS");
|
||||
const promise = require("promise");
|
||||
Cu.import("resource://gre/modules/Task.jsm", this);
|
||||
loader.lazyGetter(this, "DOMUtils", () => {
|
||||
|
|
|
@ -28,13 +28,16 @@
|
|||
|
||||
.spectrum-slider-control {
|
||||
cursor: pointer;
|
||||
border: 1px solid black;
|
||||
background: white;
|
||||
opacity: .7;
|
||||
box-shadow: 0 0 2px rgba(0,0,0,.6);
|
||||
background: #fff;
|
||||
border-radius: 10px;
|
||||
opacity: .8;
|
||||
}
|
||||
|
||||
.spectrum-box {
|
||||
border: solid 1px #333;
|
||||
border: 1px solid rgba(0,0,0,0.2);
|
||||
border-radius: 2px;
|
||||
background-clip: content-box;
|
||||
}
|
||||
|
||||
/* Elements */
|
||||
|
@ -141,7 +144,7 @@ http://www.briangrinstead.com/blog/keep-aspect-ratio-with-html-and-css */
|
|||
height: 8px;
|
||||
width: 8px;
|
||||
border: 1px solid white;
|
||||
background: black;
|
||||
box-shadow: 0 0 2px rgba(0,0,0,.6);
|
||||
}
|
||||
|
||||
.spectrum-slider {
|
||||
|
|
|
@ -318,24 +318,32 @@ div.CodeMirror span.eval-text {
|
|||
|
||||
/* Overring panel arrow images to fit with our light and dark themes */
|
||||
|
||||
.theme-tooltip-panel .panel-arrow {
|
||||
--arrow-margin: -4px;
|
||||
}
|
||||
|
||||
:root[platform="win"] .theme-tooltip-panel .panel-arrow {
|
||||
--arrow-margin: -7px;
|
||||
}
|
||||
|
||||
.theme-tooltip-panel .panel-arrow[side="top"] {
|
||||
list-style-image: url("chrome://devtools/skin/tooltip/arrow-vertical-dark.png");
|
||||
margin-bottom: -4px;
|
||||
margin-bottom: var(--arrow-margin);
|
||||
}
|
||||
|
||||
.theme-tooltip-panel .panel-arrow[side="bottom"] {
|
||||
list-style-image: url("chrome://devtools/skin/tooltip/arrow-vertical-dark.png");
|
||||
margin-top: -4px;
|
||||
margin-top: var(--arrow-margin);
|
||||
}
|
||||
|
||||
.theme-tooltip-panel .panel-arrow[side="left"] {
|
||||
list-style-image: url("chrome://devtools/skin/tooltip/arrow-horizontal-dark.png");
|
||||
margin-right: -4px;
|
||||
margin-right: var(--arrow-margin);
|
||||
}
|
||||
|
||||
.theme-tooltip-panel .panel-arrow[side="right"] {
|
||||
list-style-image: url("chrome://devtools/skin/tooltip/arrow-horizontal-dark.png");
|
||||
margin-left: -4px;
|
||||
margin-left: var(--arrow-margin);
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
|
|
|
@ -327,24 +327,32 @@ div.CodeMirror span.eval-text {
|
|||
|
||||
/* Overring panel arrow images to fit with our light and dark themes */
|
||||
|
||||
.theme-tooltip-panel .panel-arrow {
|
||||
--arrow-margin: -4px;
|
||||
}
|
||||
|
||||
:root[platform="win"] .theme-tooltip-panel .panel-arrow {
|
||||
--arrow-margin: -7px;
|
||||
}
|
||||
|
||||
.theme-tooltip-panel .panel-arrow[side="top"] {
|
||||
list-style-image: url("chrome://devtools/skin/tooltip/arrow-vertical-light.png");
|
||||
margin-bottom: -4px;
|
||||
margin-bottom: var(--arrow-margin);
|
||||
}
|
||||
|
||||
.theme-tooltip-panel .panel-arrow[side="bottom"] {
|
||||
list-style-image: url("chrome://devtools/skin/tooltip/arrow-vertical-light.png");
|
||||
margin-top: -4px;
|
||||
margin-top: var(--arrow-margin);
|
||||
}
|
||||
|
||||
.theme-tooltip-panel .panel-arrow[side="left"] {
|
||||
list-style-image: url("chrome://devtools/skin/tooltip/arrow-horizontal-light.png");
|
||||
margin-right: -4px;
|
||||
margin-right: var(--arrow-margin);
|
||||
}
|
||||
|
||||
.theme-tooltip-panel .panel-arrow[side="right"] {
|
||||
list-style-image: url("chrome://devtools/skin/tooltip/arrow-horizontal-light.png");
|
||||
margin-left: -4px;
|
||||
margin-left: var(--arrow-margin);
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
|
|
|
@ -71,6 +71,9 @@ html, body, #app, #memory-tool {
|
|||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.devtools-toolbar > .toolbar-group > label {
|
||||
|
|
|
@ -78,6 +78,8 @@ const {
|
|||
const {getLayoutChangesObserver, releaseLayoutChangesObserver} =
|
||||
require("devtools/server/actors/layout");
|
||||
|
||||
loader.lazyRequireGetter(this, "CSS", "CSS");
|
||||
|
||||
const {EventParsers} = require("devtools/shared/event-parsers");
|
||||
|
||||
const FONT_FAMILY_PREVIEW_TEXT = "The quick brown fox jumps over the lazy dog";
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
/* 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/. */
|
||||
/* globals CSS */
|
||||
|
||||
"use strict";
|
||||
|
||||
|
@ -18,6 +17,8 @@ const {PSEUDO_ELEMENT_SET} = require("devtools/shared/styleinspector/css-logic")
|
|||
const {UPDATE_PRESERVING_RULES, UPDATE_GENERAL} =
|
||||
require("devtools/server/actors/stylesheets");
|
||||
|
||||
loader.lazyRequireGetter(this, "CSS", "CSS");
|
||||
|
||||
loader.lazyGetter(this, "CssLogic", () => {
|
||||
return require("devtools/shared/styleinspector/css-logic").CssLogic;
|
||||
});
|
||||
|
|
|
@ -735,9 +735,20 @@ WebConsoleActor.prototype =
|
|||
if (!this.consoleAPIListener) {
|
||||
break;
|
||||
}
|
||||
|
||||
let requestStartTime = this.window ?
|
||||
this.window.performance.timing.requestStart : 0;
|
||||
|
||||
let cache = this.consoleAPIListener
|
||||
.getCachedMessages(!this.parentActor.isRootActor);
|
||||
cache.forEach((aMessage) => {
|
||||
// Filter out messages that came from a ServiceWorker but happened
|
||||
// before the page was requested.
|
||||
if (aMessage.innerID === "ServiceWorker" &&
|
||||
requestStartTime > aMessage.timeStamp) {
|
||||
return;
|
||||
}
|
||||
|
||||
let message = this.prepareConsoleMessageForRemote(aMessage);
|
||||
message._type = type;
|
||||
messages.push(message);
|
||||
|
|
|
@ -67,6 +67,10 @@ XPCOMUtils.defineLazyGetter(loaderModules, "indexedDB", () => {
|
|||
}
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(loaderModules, "CSS", () => {
|
||||
return Cu.Sandbox(this, {wantGlobalProperties: ["CSS"]}).CSS;
|
||||
});
|
||||
|
||||
var sharedGlobalBlacklist = ["sdk/indexed-db"];
|
||||
|
||||
/**
|
||||
|
@ -378,6 +382,7 @@ DevToolsLoader.prototype = {
|
|||
this._provider.globals = {
|
||||
isWorker: false,
|
||||
reportError: Cu.reportError,
|
||||
atob: atob,
|
||||
btoa: btoa,
|
||||
_Iterator: Iterator,
|
||||
loader: {
|
||||
|
|
|
@ -75,9 +75,7 @@ exports.PSEUDO_ELEMENT_SET = PSEUDO_ELEMENT_SET;
|
|||
|
||||
// This should be ok because none of the functions that use this should be used
|
||||
// on the worker thread, where Cu is not available.
|
||||
if (Cu) {
|
||||
Cu.importGlobalProperties(["CSS"]);
|
||||
}
|
||||
loader.lazyRequireGetter(this, "CSS", "CSS");
|
||||
|
||||
function CssLogic()
|
||||
{
|
||||
|
|
|
@ -13,8 +13,6 @@ const Services = require("Services");
|
|||
const {DebuggerServer} = require("devtools/server/main");
|
||||
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
|
||||
Cu.importGlobalProperties(["atob"]);
|
||||
|
||||
loader.lazyGetter(this, "NetworkHelper", () => require("devtools/shared/webconsole/network-helper"));
|
||||
|
||||
// Helper tracer. Should be generic sharable by other modules (bug 1171927)
|
||||
|
|
|
@ -18,6 +18,7 @@ support-files =
|
|||
[test_consoleapi.html]
|
||||
[test_consoleapi_innerID.html]
|
||||
[test_console_serviceworker.html]
|
||||
[test_console_serviceworker_cached.html]
|
||||
[test_console_styling.html]
|
||||
[test_file_uri.html]
|
||||
[test_reflow.html]
|
||||
|
|
|
@ -133,6 +133,16 @@ function closeDebugger(aState, aCallback)
|
|||
aState.client = null;
|
||||
}
|
||||
|
||||
function checkConsoleAPICalls(consoleCalls, expectedConsoleCalls)
|
||||
{
|
||||
is(consoleCalls.length, expectedConsoleCalls.length,
|
||||
'received correct number of console calls');
|
||||
expectedConsoleCalls.forEach(function(aMessage, aIndex) {
|
||||
info("checking received console call #" + aIndex);
|
||||
checkConsoleAPICall(consoleCalls[aIndex], expectedConsoleCalls[aIndex]);
|
||||
});
|
||||
}
|
||||
|
||||
function checkConsoleAPICall(aCall, aExpected)
|
||||
{
|
||||
if (aExpected.level != "trace" && aExpected.arguments) {
|
||||
|
@ -243,3 +253,76 @@ function nextTest(aMessage)
|
|||
{
|
||||
return gTestState.driver.next(aMessage);
|
||||
}
|
||||
|
||||
function withFrame(url) {
|
||||
return new Promise(resolve => {
|
||||
let iframe = document.createElement("iframe");
|
||||
iframe.onload = function() {
|
||||
resolve(iframe);
|
||||
};
|
||||
iframe.src = url;
|
||||
document.body.appendChild(iframe);
|
||||
});
|
||||
}
|
||||
|
||||
function navigateFrame(iframe, url) {
|
||||
return new Promise(resolve => {
|
||||
iframe.onload = function() {
|
||||
resolve(iframe);
|
||||
};
|
||||
iframe.src = url;
|
||||
});
|
||||
}
|
||||
|
||||
function forceReloadFrame(iframe) {
|
||||
return new Promise(resolve => {
|
||||
iframe.onload = function() {
|
||||
resolve(iframe);
|
||||
};
|
||||
iframe.contentWindow.location.reload(true);
|
||||
});
|
||||
}
|
||||
|
||||
function withActiveServiceWorker(win, url, scope) {
|
||||
let opts = {};
|
||||
if (scope) {
|
||||
opts.scope = scope;
|
||||
}
|
||||
return win.navigator.serviceWorker.register(url, opts).then(swr => {
|
||||
if (swr.active) {
|
||||
return swr;
|
||||
}
|
||||
|
||||
// Unfortunately we can't just use navigator.serviceWorker.ready promise
|
||||
// here. If the service worker is for a scope that does not cover the window
|
||||
// then the ready promise will never resolve. Instead monitor the service
|
||||
// workers state change events to determine when its activated.
|
||||
return new Promise(resolve => {
|
||||
let sw = swr.waiting || swr.installing;
|
||||
sw.addEventListener('statechange', function stateHandler(evt) {
|
||||
if (sw.state === 'activated') {
|
||||
sw.removeEventListener('statechange', stateHandler);
|
||||
resolve(swr);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function messageServiceWorker(win, scope, message) {
|
||||
return win.navigator.serviceWorker.getRegistration(scope).then(swr => {
|
||||
return new Promise(resolve => {
|
||||
win.navigator.serviceWorker.onmessage = evt => {
|
||||
resolve();
|
||||
};
|
||||
let sw = swr.active || swr.waiting || swr.installing;
|
||||
sw.postMessage({ type: 'PING', message: message });
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
function unregisterServiceWorker(win) {
|
||||
return win.navigator.serviceWorker.ready.then(swr => {
|
||||
return swr.unregister();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -64,75 +64,6 @@ let startTest = Task.async(function*() {
|
|||
});
|
||||
addEventListener("load", startTest);
|
||||
|
||||
function withFrame(url) {
|
||||
return new Promise(resolve => {
|
||||
let iframe = document.createElement("iframe");
|
||||
iframe.onload = function() {
|
||||
resolve(iframe);
|
||||
};
|
||||
iframe.src = url;
|
||||
document.body.appendChild(iframe);
|
||||
});
|
||||
}
|
||||
|
||||
function navigateFrame(iframe, url) {
|
||||
return new Promise(resolve => {
|
||||
iframe.onload = function() {
|
||||
resolve(iframe);
|
||||
};
|
||||
iframe.src = url;
|
||||
});
|
||||
}
|
||||
|
||||
function forceReloadFrame(iframe) {
|
||||
return new Promise(resolve => {
|
||||
iframe.onload = function() {
|
||||
resolve(iframe);
|
||||
};
|
||||
iframe.contentWindow.location.reload(true);
|
||||
});
|
||||
}
|
||||
|
||||
function withActiveServiceWorker(win, url, scope) {
|
||||
return win.navigator.serviceWorker.register(url, { scope: scope }).then(swr => {
|
||||
if (swr.active) {
|
||||
return swr;
|
||||
}
|
||||
|
||||
// Unfortunately we can't just use navigator.serviceWorker.ready promise
|
||||
// here. If the service worker is for a scope that does not cover the window
|
||||
// then the ready promise will never resolve. Instead monitor the service
|
||||
// workers state change events to determine when its activated.
|
||||
return new Promise(resolve => {
|
||||
let sw = swr.waiting || swr.installing;
|
||||
sw.addEventListener('statechange', function stateHandler(evt) {
|
||||
if (sw.state === 'activated') {
|
||||
sw.removeEventListener('statechange', stateHandler);
|
||||
resolve(swr);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function messageServiceWorker(win, scope, message) {
|
||||
return win.navigator.serviceWorker.getRegistration(scope).then(swr => {
|
||||
return new Promise(resolve => {
|
||||
win.navigator.serviceWorker.onmessage = evt => {
|
||||
resolve();
|
||||
};
|
||||
let sw = swr.active || swr.waiting || swr.installing;
|
||||
sw.postMessage({ type: 'PING', message: message });
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
function unregisterServiceWorker(win) {
|
||||
return win.navigator.serviceWorker.ready.then(swr => {
|
||||
return swr.unregister();
|
||||
});
|
||||
}
|
||||
|
||||
let onAttach = Task.async(function*(state, response) {
|
||||
onConsoleAPICall = onConsoleAPICall.bind(null, state);
|
||||
state.dbgClient.addListener("consoleAPICall", onConsoleAPICall);
|
||||
|
@ -194,12 +125,7 @@ let onAttach = Task.async(function*(state, response) {
|
|||
|
||||
info('Service worker unregistered. Checking console calls.');
|
||||
state.dbgClient.removeListener("consoleAPICall", onConsoleAPICall);
|
||||
is(consoleCalls.length, expectedConsoleCalls.length,
|
||||
'received correct number of console calls');
|
||||
expectedConsoleCalls.forEach(function(aMessage, aIndex) {
|
||||
info("checking received console call #" + aIndex);
|
||||
checkConsoleAPICall(consoleCalls[aIndex], expectedConsoleCalls[aIndex]);
|
||||
});
|
||||
checkConsoleAPICalls(consoleCalls, expectedConsoleCalls);
|
||||
} catch(error) {
|
||||
ok(false, 'unexpected error: ' + error);
|
||||
} finally {
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Test for getCachedMessages and Service Workers</title>
|
||||
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript;version=1.8" src="common.js"></script>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
</head>
|
||||
<body>
|
||||
<p>Test for getCachedMessages and Service Workers</p>
|
||||
|
||||
<script class="testbody" type="text/javascript;version=1.8">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
let BASE_URL = "https://example.com/chrome/devtools/shared/webconsole/test/";
|
||||
let SERVICE_WORKER_URL = BASE_URL + "helper_serviceworker.js";
|
||||
let FRAME_URL = BASE_URL + "sandboxed_iframe.html";
|
||||
|
||||
let firstTabExpectedCalls = [
|
||||
{
|
||||
level: "log",
|
||||
filename: /helper_serviceworker/,
|
||||
arguments: ['script evaluation'],
|
||||
},
|
||||
{
|
||||
level: "log",
|
||||
filename: /helper_serviceworker/,
|
||||
arguments: ['install event'],
|
||||
},
|
||||
{
|
||||
level: "log",
|
||||
filename: /helper_serviceworker/,
|
||||
arguments: ['activate event'],
|
||||
},
|
||||
];
|
||||
|
||||
let secondTabExpectedCalls = [
|
||||
{
|
||||
level: "log",
|
||||
filename: /helper_serviceworker/,
|
||||
arguments: ['fetch event: ' + FRAME_URL],
|
||||
}
|
||||
];
|
||||
|
||||
let startTest = Task.async(function*() {
|
||||
removeEventListener("load", startTest);
|
||||
|
||||
yield new Promise(resolve => {
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["devtools.webconsole.filter.serviceworkers", true]
|
||||
]}, resolve);
|
||||
});
|
||||
|
||||
info("Adding a tab and attaching a service worker");
|
||||
let tab1 = yield addTab(FRAME_URL);
|
||||
let swr = yield withActiveServiceWorker(tab1.linkedBrowser.contentWindow,
|
||||
SERVICE_WORKER_URL);
|
||||
|
||||
yield new Promise(resolve => {
|
||||
info("Attaching console to tab 1");
|
||||
attachConsoleToTab(["ConsoleAPI"], function(state) {
|
||||
state.client.getCachedMessages(["ConsoleAPI"], function(calls) {
|
||||
checkConsoleAPICalls(calls.messages, firstTabExpectedCalls);
|
||||
closeDebugger(state, resolve);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Because this tab is being added after the original messages happened,
|
||||
// they shouldn't show up in a call to getCachedMessages.
|
||||
// However, there is a fetch event which is logged due to loading the tab.
|
||||
info("Adding a new tab at the same URL");
|
||||
let tab2 = yield addTab(FRAME_URL);
|
||||
yield new Promise(resolve => {
|
||||
info("Attaching console to tab 2");
|
||||
attachConsoleToTab(["ConsoleAPI"], function(state) {
|
||||
state.client.getCachedMessages(["ConsoleAPI"], function(calls) {
|
||||
checkConsoleAPICalls(calls.messages, secondTabExpectedCalls);
|
||||
closeDebugger(state, resolve);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
yield swr.unregister();
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
addEventListener("load", startTest);
|
||||
|
||||
// This test needs to add tabs that are controlled by a service worker
|
||||
// so use some special powers to dig around and find gBrowser
|
||||
let {gBrowser} = SpecialPowers._getTopChromeWindow(SpecialPowers.window.get());
|
||||
|
||||
SimpleTest.registerCleanupFunction(() => {
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
gBrowser.removeCurrentTab();
|
||||
}
|
||||
});
|
||||
|
||||
function addTab(url) {
|
||||
info("Adding a new tab with URL: '" + url + "'");
|
||||
return new Promise(resolve => {
|
||||
let tab = gBrowser.selectedTab = gBrowser.addTab(url);
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onload() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
|
||||
info("URL '" + url + "' loading complete");
|
||||
resolve(tab);
|
||||
}, true);
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -42,4 +42,19 @@ public class NativeCrypto {
|
|||
* Wrapper to perform SHA-1 in native code.
|
||||
*/
|
||||
public native static byte[] sha1(byte[] str);
|
||||
|
||||
/**
|
||||
* Wrapper to perform SHA-256 init in native code. Returns a SHA-256 context.
|
||||
*/
|
||||
public native static byte[] sha256init();
|
||||
|
||||
/**
|
||||
* Wrapper to update a SHA-256 context in native code.
|
||||
*/
|
||||
public native static void sha256update(byte[] ctx, byte[] str);
|
||||
|
||||
/**
|
||||
* Wrapper to finalize a SHA-256 context in native code. Returns digest.
|
||||
*/
|
||||
public native static byte[] sha256finalize(byte[] ctx);
|
||||
}
|
||||
|
|
|
@ -56,6 +56,10 @@ public class testNativeCrypto extends UITest {
|
|||
|
||||
_testSHA1();
|
||||
_testSHA1AgainstMessageDigest();
|
||||
|
||||
_testSHA256();
|
||||
_testSHA256MultiPart();
|
||||
_testSHA256AgainstMessageDigest();
|
||||
}
|
||||
|
||||
public void _testPBKDF2SHA256A() throws UnsupportedEncodingException, GeneralSecurityException {
|
||||
|
@ -163,6 +167,74 @@ public class testNativeCrypto extends UITest {
|
|||
}
|
||||
}
|
||||
|
||||
private void _testSHA256() throws UnsupportedEncodingException {
|
||||
final String[] inputs = new String[] {
|
||||
"abc",
|
||||
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
|
||||
"" // To be filled in below.
|
||||
};
|
||||
final String baseStr = "01234567";
|
||||
final int repetitions = 80;
|
||||
final StringBuilder builder = new StringBuilder(baseStr.length() * repetitions);
|
||||
for (int i = 0; i < repetitions; ++i) {
|
||||
builder.append(baseStr);
|
||||
}
|
||||
inputs[2] = builder.toString();
|
||||
|
||||
final String[] expecteds = new String[] {
|
||||
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
|
||||
"248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1",
|
||||
"594847328451bdfa85056225462cc1d867d877fb388df0ce35f25ab5562bfbb5"
|
||||
};
|
||||
|
||||
for (int i = 0; i < inputs.length; ++i) {
|
||||
final byte[] input = inputs[i].getBytes("US-ASCII");
|
||||
final String expected = expecteds[i];
|
||||
|
||||
final byte[] ctx = NativeCrypto.sha256init();
|
||||
NativeCrypto.sha256update(ctx, input);
|
||||
final byte[] actual = NativeCrypto.sha256finalize(ctx);
|
||||
fAssertNotNull("Hashed value is non-null", actual);
|
||||
assertExpectedBytes(expected, actual);
|
||||
}
|
||||
}
|
||||
|
||||
private void _testSHA256MultiPart() throws UnsupportedEncodingException {
|
||||
final String input = "01234567";
|
||||
final int repetitions = 80;
|
||||
final String expected = "594847328451bdfa85056225462cc1d867d877fb388df0ce35f25ab5562bfbb5";
|
||||
|
||||
final byte[] inputBytes = input.getBytes("US-ASCII");
|
||||
final byte[] ctx = NativeCrypto.sha256init();
|
||||
for (int i = 0; i < repetitions; ++i) {
|
||||
NativeCrypto.sha256update(ctx, inputBytes);
|
||||
}
|
||||
final byte[] actual = NativeCrypto.sha256finalize(ctx);
|
||||
fAssertNotNull("Hashed value is non-null", actual);
|
||||
assertExpectedBytes(expected, actual);
|
||||
}
|
||||
|
||||
private void _testSHA256AgainstMessageDigest() throws UnsupportedEncodingException,
|
||||
NoSuchAlgorithmException {
|
||||
final String[] inputs = {
|
||||
"password",
|
||||
"saranghae",
|
||||
"aoeusnthaoeusnthaoeusnth \0 12345098765432109876_!"
|
||||
};
|
||||
|
||||
final MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||
for (final String input : inputs) {
|
||||
final byte[] inputBytes = input.getBytes("US-ASCII");
|
||||
|
||||
final byte[] mdBytes = digest.digest(inputBytes);
|
||||
|
||||
final byte[] ctx = NativeCrypto.sha256init();
|
||||
NativeCrypto.sha256update(ctx, inputBytes);
|
||||
final byte[] ourBytes = NativeCrypto.sha256finalize(ctx);
|
||||
fAssertArrayEquals("MessageDigest hash is the same as NativeCrypto SHA-256 hash", mdBytes, ourBytes);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkPBKDF2SHA256(String p, String s, int c, int dkLen, final String expectedStr)
|
||||
throws GeneralSecurityException, UnsupportedEncodingException {
|
||||
final long start = SystemClock.elapsedRealtime();
|
||||
|
|
|
@ -73,3 +73,61 @@ extern "C" JNIEXPORT jbyteArray MOZ_JNICALL Java_org_mozilla_gecko_background_na
|
|||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to invoke native SHA-256 init with JNI arguments.
|
||||
*/
|
||||
extern "C" JNIEXPORT jbyteArray MOZ_JNICALL Java_org_mozilla_gecko_background_nativecode_NativeCrypto_sha256init
|
||||
(JNIEnv *env, jclass jc) {
|
||||
jbyteArray out = env->NewByteArray(sizeof(SHA256_CTX));
|
||||
if (nullptr == out) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SHA256_CTX *shaContext = (SHA256_CTX*)env->GetByteArrayElements(out, nullptr);
|
||||
SHA256_Init(shaContext);
|
||||
|
||||
env->ReleaseByteArrayElements(out, (jbyte*)shaContext, 0);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to invoke native SHA-256 update with JNI arguments.
|
||||
*/
|
||||
extern "C" JNIEXPORT void MOZ_JNICALL Java_org_mozilla_gecko_background_nativecode_NativeCrypto_sha256update
|
||||
(JNIEnv *env, jclass jc, jbyteArray jctx, jbyteArray jstr) {
|
||||
jbyte *str = env->GetByteArrayElements(jstr, nullptr);
|
||||
size_t strLen = env->GetArrayLength(jstr);
|
||||
|
||||
SHA256_CTX *shaContext = (SHA256_CTX*)env->GetByteArrayElements(jctx, nullptr);
|
||||
|
||||
SHA256_Update(shaContext, (void*)str, strLen);
|
||||
|
||||
env->ReleaseByteArrayElements(jstr, str, JNI_ABORT);
|
||||
env->ReleaseByteArrayElements(jctx, (jbyte*)shaContext, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to invoke native SHA-256 finalize with JNI arguments.
|
||||
*/
|
||||
extern "C" JNIEXPORT jbyteArray MOZ_JNICALL Java_org_mozilla_gecko_background_nativecode_NativeCrypto_sha256finalize
|
||||
(JNIEnv *env, jclass jc, jbyteArray jctx) {
|
||||
SHA256_CTX *shaContext = (SHA256_CTX*)env->GetByteArrayElements(jctx, nullptr);
|
||||
|
||||
unsigned char* digest = new unsigned char[32];
|
||||
SHA256_Final(digest, shaContext);
|
||||
|
||||
env->ReleaseByteArrayElements(jctx, (jbyte*)shaContext, JNI_ABORT);
|
||||
|
||||
jbyteArray out = env->NewByteArray(32);
|
||||
if (nullptr != out) {
|
||||
env->SetByteArrayRegion(out, 0, 32, (jbyte*)digest);
|
||||
}
|
||||
|
||||
delete digest;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,30 @@ JNIEXPORT jbyteArray JNICALL Java_org_mozilla_gecko_background_nativecode_Native
|
|||
JNIEXPORT jbyteArray JNICALL Java_org_mozilla_gecko_background_nativecode_NativeCrypto_sha1
|
||||
(JNIEnv *, jclass, jbyteArray);
|
||||
|
||||
/*
|
||||
* Class: org_mozilla_gecko_background_nativecode_NativeCrypto
|
||||
* Method: sha256init
|
||||
* Signature: ()[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_org_mozilla_gecko_background_nativecode_NativeCrypto_sha256init
|
||||
(JNIEnv *, jclass);
|
||||
|
||||
/*
|
||||
* Class: org_mozilla_gecko_background_nativecode_NativeCrypto
|
||||
* Method: sha256update
|
||||
* Signature: ([B[B)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_org_mozilla_gecko_background_nativecode_NativeCrypto_sha256update
|
||||
(JNIEnv *, jclass, jbyteArray, jbyteArray);
|
||||
|
||||
/*
|
||||
* Class: org_mozilla_gecko_background_nativecode_NativeCrypto
|
||||
* Method: sha256finalize
|
||||
* Signature: ([B)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_org_mozilla_gecko_background_nativecode_NativeCrypto_sha256finalize
|
||||
(JNIEnv *, jclass, jbyteArray);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -468,6 +468,16 @@
|
|||
"extended_statistics_ok": true,
|
||||
"description": "Resident memory size (KB)"
|
||||
},
|
||||
"MEMORY_UNIQUE": {
|
||||
"alert_emails": ["memshrink-telemetry-alerts@mozilla.com"],
|
||||
"bug_numbers": [1198209],
|
||||
"expires_in_version": "never",
|
||||
"kind": "exponential",
|
||||
"low": "32 * 1024",
|
||||
"high": "16 * 1024 * 1024",
|
||||
"n_buckets": 100,
|
||||
"description": "Unique Set Size (KB)"
|
||||
},
|
||||
"MEMORY_VSIZE": {
|
||||
"alert_emails": ["memshrink-telemetry-alerts@mozilla.com"],
|
||||
"expires_in_version": "never",
|
||||
|
|
|
@ -1042,6 +1042,7 @@ var Impl = {
|
|||
b("MEMORY_VSIZE", "vsize");
|
||||
b("MEMORY_VSIZE_MAX_CONTIGUOUS", "vsizeMaxContiguous");
|
||||
b("MEMORY_RESIDENT", "residentFast");
|
||||
b("MEMORY_UNIQUE", "residentUnique");
|
||||
b("MEMORY_HEAP_ALLOCATED", "heapAllocated");
|
||||
p("MEMORY_HEAP_COMMITTED_UNUSED_RATIO", "heapOverheadRatio");
|
||||
b("MEMORY_JS_GC_HEAP", "JSMainRuntimeGCHeap");
|
||||
|
|
|
@ -9,7 +9,7 @@ Cu.import("resource://gre/modules/Services.jsm", this);
|
|||
const PR_WRONLY = 0x2;
|
||||
const PR_CREATE_FILE = 0x8;
|
||||
const PR_TRUNCATE = 0x20;
|
||||
const RW_OWNER = 0600;
|
||||
const RW_OWNER = parseInt("0600", 8);
|
||||
|
||||
const STACK_SUFFIX1 = "stack1.txt";
|
||||
const STACK_SUFFIX2 = "stack2.txt";
|
||||
|
|
|
@ -12,7 +12,7 @@ const N_FAILED_LOCKS = 10;
|
|||
const PR_WRONLY = 0x2;
|
||||
const PR_CREATE_FILE = 0x8;
|
||||
const PR_TRUNCATE = 0x20;
|
||||
const RW_OWNER = 0600;
|
||||
const RW_OWNER = parseInt("0600", 8);
|
||||
|
||||
function write_string_to_file(file, contents) {
|
||||
let ostream = Cc["@mozilla.org/network/safe-file-output-stream;1"]
|
||||
|
|
|
@ -1638,10 +1638,10 @@ function displayPingData(ping, updatePayloadList = false) {
|
|||
|
||||
LateWritesSingleton.renderLateWrites(payload.lateWrites);
|
||||
|
||||
// Show basic system info gathered
|
||||
// Show basic session info gathered
|
||||
hasData = Object.keys(ping.payload.info).length > 0;
|
||||
setHasData("system-info-section", hasData);
|
||||
let infoSection = document.getElementById("system-info");
|
||||
setHasData("session-info-section", hasData);
|
||||
let infoSection = document.getElementById("session-info");
|
||||
removeAllChildNodes(infoSection);
|
||||
|
||||
if (hasData) {
|
||||
|
|
|
@ -120,12 +120,12 @@
|
|||
</div>
|
||||
</section>
|
||||
|
||||
<section id="system-info-section" class="data-section">
|
||||
<section id="session-info-section" class="data-section">
|
||||
<input type="checkbox" class="statebox"/>
|
||||
<h1 class="section-name">&aboutTelemetry.systemInfoSection;</h1>
|
||||
<h1 class="section-name">&aboutTelemetry.sessionInfoSection;</h1>
|
||||
<span class="toggle-caption">&aboutTelemetry.toggle;</span>
|
||||
<span class="empty-caption">&aboutTelemetry.emptySection;</span>
|
||||
<div id="system-info" class="data">
|
||||
<div id="session-info" class="data">
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
|
|
@ -108,8 +108,8 @@ Ping
|
|||
Late Writes
|
||||
">
|
||||
|
||||
<!ENTITY aboutTelemetry.systemInfoSection "
|
||||
System Information
|
||||
<!ENTITY aboutTelemetry.sessionInfoSection "
|
||||
Session Information
|
||||
">
|
||||
|
||||
<!ENTITY aboutTelemetry.addonHistogramsSection "
|
||||
|
|
Загрузка…
Ссылка в новой задаче