зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to inbound, a=merge
MozReview-Commit-ID: 3HW7YWDqTBQ
This commit is contained in:
Коммит
e28b562783
|
@ -0,0 +1,252 @@
|
|||
/* 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/. */
|
||||
|
||||
this.EXPORTED_SYMBOLS = [
|
||||
"Panel",
|
||||
];
|
||||
|
||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Timer.jsm");
|
||||
|
||||
this.Panel = function(panelElt, iframeURL) {
|
||||
this.p = panelElt;
|
||||
this.iframeURL = iframeURL;
|
||||
this._initPanel();
|
||||
this.urlbar.addEventListener("keydown", this);
|
||||
this.urlbar.addEventListener("input", this);
|
||||
this._emitQueue = [];
|
||||
};
|
||||
|
||||
this.Panel.prototype = {
|
||||
|
||||
get document() {
|
||||
return this.p.ownerDocument;
|
||||
},
|
||||
|
||||
get window() {
|
||||
return this.document.defaultView;
|
||||
},
|
||||
|
||||
get urlbar() {
|
||||
return this.window.gURLBar;
|
||||
},
|
||||
|
||||
iframe: null,
|
||||
|
||||
get iframeDocument() {
|
||||
return this.iframe.contentDocument;
|
||||
},
|
||||
|
||||
get iframeWindow() {
|
||||
return this.iframe.contentWindow;
|
||||
},
|
||||
|
||||
destroy() {
|
||||
this.p.destroyAddonIframe(this);
|
||||
this.urlbar.removeEventListener("keydown", this);
|
||||
this.urlbar.removeEventListener("input", this);
|
||||
},
|
||||
|
||||
_initPanel() {
|
||||
this.iframe = this.p.initAddonIframe(this, {
|
||||
_invalidate: this._invalidate.bind(this),
|
||||
});
|
||||
if (!this.iframe) {
|
||||
// This will be the case when somebody else already owns the iframe.
|
||||
// First consumer wins right now.
|
||||
return;
|
||||
}
|
||||
let onLoad = event => {
|
||||
this.iframe.removeEventListener("load", onLoad, true);
|
||||
this._initIframeContent(event.target.defaultView);
|
||||
};
|
||||
this.iframe.addEventListener("load", onLoad, true);
|
||||
this.iframe.setAttribute("src", this.iframeURL);
|
||||
},
|
||||
|
||||
_initIframeContent(win) {
|
||||
// Clone the urlbar API functions into the iframe window.
|
||||
win = XPCNativeWrapper.unwrap(win);
|
||||
let apiInstance = Cu.cloneInto(iframeAPIPrototype, win, {
|
||||
cloneFunctions: true,
|
||||
});
|
||||
apiInstance._panel = this;
|
||||
Object.defineProperty(win, "urlbar", {
|
||||
get() {
|
||||
return apiInstance;
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
// This is called by the popup directly. It overrides the popup's own
|
||||
// _invalidate method.
|
||||
_invalidate() {
|
||||
this._emit("reset");
|
||||
this._currentIndex = 0;
|
||||
if (this._appendResultTimeout) {
|
||||
this.window.clearTimeout(this._appendResultTimeout);
|
||||
}
|
||||
this._appendCurrentResult();
|
||||
},
|
||||
|
||||
// This emulates the popup's own _appendCurrentResult method, except instead
|
||||
// of appending results to the popup, it emits "result" events to the iframe.
|
||||
_appendCurrentResult() {
|
||||
let controller = this.p.mInput.controller;
|
||||
for (let i = 0; i < this.p.maxResults; i++) {
|
||||
let idx = this._currentIndex;
|
||||
if (idx >= this.p._matchCount) {
|
||||
break;
|
||||
}
|
||||
let url = controller.getValueAt(idx);
|
||||
let action = this.urlbar._parseActionUrl(url);
|
||||
this._emit("result", {
|
||||
url: url,
|
||||
action: action,
|
||||
image: controller.getImageAt(idx),
|
||||
title: controller.getCommentAt(idx),
|
||||
type: controller.getStyleAt(idx),
|
||||
text: controller.searchString.replace(/^\s+/, "").replace(/\s+$/, ""),
|
||||
});
|
||||
this._currentIndex++;
|
||||
}
|
||||
if (this._currentIndex < this.p.matchCount) {
|
||||
this._appendResultTimeout = this.window.setTimeout(() => {
|
||||
this._appendCurrentResult();
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
get height() {
|
||||
return this.iframe.getBoundingClientRect().height;
|
||||
},
|
||||
|
||||
set height(val) {
|
||||
this.p.removeAttribute("height");
|
||||
this.iframe.style.height = val + "px";
|
||||
},
|
||||
|
||||
handleEvent(event) {
|
||||
let methName = "_on" + event.type[0].toUpperCase() + event.type.substr(1);
|
||||
this[methName](event);
|
||||
},
|
||||
|
||||
_onKeydown(event) {
|
||||
let emittedEvent = this._emitUrlbarEvent(event);
|
||||
if (emittedEvent && emittedEvent.defaultPrevented) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
},
|
||||
|
||||
_onInput(event) {
|
||||
this._emitUrlbarEvent(event);
|
||||
},
|
||||
|
||||
_emitUrlbarEvent(event) {
|
||||
let properties = [
|
||||
"altKey",
|
||||
"code",
|
||||
"ctrlKey",
|
||||
"key",
|
||||
"metaKey",
|
||||
"shiftKey",
|
||||
];
|
||||
let detail = properties.reduce((memo, prop) => {
|
||||
memo[prop] = event[prop];
|
||||
return memo;
|
||||
}, {});
|
||||
return this._emit(event.type, detail);
|
||||
},
|
||||
|
||||
_emit(eventName, detailObj = null) {
|
||||
this._emitQueue.push({
|
||||
name: eventName,
|
||||
detail: detailObj,
|
||||
});
|
||||
return this._processEmitQueue();
|
||||
},
|
||||
|
||||
_processEmitQueue() {
|
||||
if (!this._emitQueue.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// iframe.contentWindow can be undefined right after the iframe is created,
|
||||
// even after a number of seconds have elapsed. Don't know why. But that's
|
||||
// entirely the reason for having a queue instead of simply dispatching
|
||||
// events as they're created, unfortunately.
|
||||
if (!this.iframeWindow) {
|
||||
if (!this._processEmitQueueTimer) {
|
||||
this._processEmitQueueTimer = setInterval(() => {
|
||||
this._processEmitQueue();
|
||||
}, 100);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this._processEmitQueueTimer) {
|
||||
clearInterval(this._processEmitQueueTimer);
|
||||
delete this._processEmitQueueTimer;
|
||||
}
|
||||
|
||||
let { name, detail } = this._emitQueue.shift();
|
||||
let win = XPCNativeWrapper.unwrap(this.iframeWindow);
|
||||
let event = new this.iframeWindow.CustomEvent(name, {
|
||||
detail: Cu.cloneInto(detail, win),
|
||||
cancelable: true,
|
||||
});
|
||||
this.iframeWindow.dispatchEvent(event);
|
||||
|
||||
// More events may be queued up, so recurse. Do it after a turn of the
|
||||
// event loop to avoid growing the stack as big as the queue, and to let the
|
||||
// caller handle the returned event first.
|
||||
setTimeout(() => {
|
||||
this._processEmitQueue();
|
||||
}, 100);
|
||||
|
||||
return event;
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
// This is the consumer API that's cloned into the iframe window. Be careful of
|
||||
// defining static values on this, or even getters and setters (that aren't real
|
||||
// functions). The cloning process means that such values are copied by value,
|
||||
// at the time of cloning, which is probably not what you want. That's why some
|
||||
// of these are functions even though it'd be nicer if they were getters and
|
||||
// setters.
|
||||
let iframeAPIPrototype = {
|
||||
|
||||
getPanelHeight() {
|
||||
return this._panel.height;
|
||||
},
|
||||
|
||||
setPanelHeight(val) {
|
||||
this._panel.height = val;
|
||||
},
|
||||
|
||||
getValue() {
|
||||
return this._panel.urlbar.value;
|
||||
},
|
||||
|
||||
setValue(val) {
|
||||
this._panel.urlbar.value = val;
|
||||
},
|
||||
|
||||
getMaxResults() {
|
||||
return this._panel.p.maxResults;
|
||||
},
|
||||
|
||||
setMaxResults(val) {
|
||||
this._panel.p.maxResults = val;
|
||||
},
|
||||
|
||||
enter() {
|
||||
this._panel.urlbar.handleCommand();
|
||||
},
|
||||
};
|
|
@ -49,6 +49,12 @@ support-files =
|
|||
moz.png
|
||||
[browser_tabMatchesInAwesomebar_perwindowpb.js]
|
||||
skip-if = os == 'linux' # Bug 1104755
|
||||
[browser_urlbarAddonIframe.js]
|
||||
support-files =
|
||||
Panel.jsm
|
||||
urlbarAddonIframe.html
|
||||
urlbarAddonIframe.js
|
||||
urlbarAddonIframeContentScript.js
|
||||
[browser_urlbarAboutHomeLoading.js]
|
||||
[browser_urlbarAutoFillTrimURLs.js]
|
||||
[browser_urlbarCopying.js]
|
||||
|
|
|
@ -0,0 +1,220 @@
|
|||
"use strict";
|
||||
|
||||
// The purpose of this test is to test the urlbar popup's add-on iframe. It has
|
||||
// a few parts:
|
||||
//
|
||||
// (1) This file, a normal browser mochitest.
|
||||
// (2) html/js files that are loaded in the urlbar popup's add-on iframe:
|
||||
// urlbarAddonIframe.{html,js}
|
||||
// (3) A content script that mediates between the first two parts:
|
||||
// urlbarAddonIframeContentScript.js
|
||||
//
|
||||
// The main test file (this file) sends messages to the content script, which
|
||||
// forwards them as events to the iframe. These messages tell the iframe js to
|
||||
// do various things like call functions on the urlbar API and expect events.
|
||||
// In response, the iframe js dispatches ack events to the content script, which
|
||||
// forwards them as messages to the main test file.
|
||||
//
|
||||
// The content script may not be necessary right now since the iframe is not
|
||||
// remote. But this structure ensures that if the iframe is made remote in the
|
||||
// future, then the test won't have to change very much, and ideally not at all.
|
||||
//
|
||||
// Actually there's one other part:
|
||||
//
|
||||
// (4) The Panel.jsm that's bundled with add-ons that use the iframe.
|
||||
//
|
||||
// Panel.jsm defines the API that's made available to add-on scripts running in
|
||||
// the iframe. This API is orthogonal to the add-on iframe itself. You could
|
||||
// load any html/js in the iframe, technically. But the purpose of the iframe
|
||||
// is to support this Panel.jsm API, so that's what this test tests.
|
||||
|
||||
const PANEL_JSM_BASENAME = "Panel.jsm";
|
||||
const IFRAME_BASENAME = "urlbarAddonIframe.html";
|
||||
const CONTENT_SCRIPT_BASENAME = "urlbarAddonIframeContentScript.js";
|
||||
|
||||
// The iframe's message manager.
|
||||
let gMsgMan;
|
||||
|
||||
add_task(function* () {
|
||||
let rootDirURL = getRootDirectory(gTestPath);
|
||||
let jsmURL = rootDirURL + PANEL_JSM_BASENAME;
|
||||
let iframeURL = rootDirURL + IFRAME_BASENAME;
|
||||
let contentScriptURL = rootDirURL + CONTENT_SCRIPT_BASENAME;
|
||||
|
||||
let { Panel } = Cu.import(jsmURL, {});
|
||||
let panel = new Panel(gURLBar.popup, iframeURL);
|
||||
registerCleanupFunction(() => {
|
||||
panel.destroy();
|
||||
Assert.ok(gURLBar.popup._addonIframe === null, "iframe should be gone");
|
||||
});
|
||||
|
||||
let iframe = gURLBar.popup._addonIframe;
|
||||
Assert.ok(!!iframe, "iframe should not be null");
|
||||
|
||||
gMsgMan =
|
||||
iframe.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader.messageManager;
|
||||
gMsgMan.loadFrameScript(contentScriptURL, false);
|
||||
|
||||
yield promiseIframeLoad();
|
||||
|
||||
// urlbar.getValue
|
||||
let value = "this value set by the test";
|
||||
gURLBar.value = value;
|
||||
let readValue = yield promiseUrlbarFunctionCall("getValue");
|
||||
Assert.equal(readValue, value, "value");
|
||||
|
||||
// urlbar.setValue
|
||||
value = "this value set by the iframe";
|
||||
yield promiseUrlbarFunctionCall("setValue", value);
|
||||
Assert.equal(gURLBar.value, value, "setValue");
|
||||
|
||||
// urlbar.getMaxResults
|
||||
let maxResults = gURLBar.popup.maxResults;
|
||||
Assert.equal(typeof(maxResults), "number", "Sanity check");
|
||||
let readMaxResults = yield promiseUrlbarFunctionCall("getMaxResults");
|
||||
Assert.equal(readMaxResults, maxResults, "getMaxResults");
|
||||
|
||||
// urlbar.setMaxResults
|
||||
let newMaxResults = maxResults + 10;
|
||||
yield promiseUrlbarFunctionCall("setMaxResults", newMaxResults);
|
||||
Assert.equal(gURLBar.popup.maxResults, newMaxResults, "setMaxResults");
|
||||
gURLBar.popup.maxResults = maxResults;
|
||||
|
||||
// urlbar.enter
|
||||
value = "http://mochi.test:8888/";
|
||||
yield promiseUrlbarFunctionCall("setValue", value);
|
||||
Assert.equal(gURLBar.value, value, "setValue");
|
||||
yield promiseUrlbarFunctionCall("enter");
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
yield BrowserTestUtils.browserLoaded(browser);
|
||||
Assert.equal(browser.currentURI.spec, value,
|
||||
"enter should have loaded the URL");
|
||||
|
||||
// input, reset, and result events. There should always be at least one
|
||||
// result, the heuristic result.
|
||||
value = "test";
|
||||
let promiseValues = yield Promise.all([
|
||||
promiseEvent("input")[1],
|
||||
promiseEvent("reset")[1],
|
||||
promiseEvent("result")[1],
|
||||
promiseAutocompleteResultPopup(value, window, true),
|
||||
]);
|
||||
|
||||
// Check the heuristic result.
|
||||
let result = promiseValues[2];
|
||||
let engineName = Services.search.currentEngine.name;
|
||||
Assert.equal(result.url,
|
||||
`moz-action:searchengine,{"engineName":"${engineName}","input":"test","searchQuery":"test"}`,
|
||||
"result.url");
|
||||
Assert.ok("action" in result, "result.action");
|
||||
Assert.equal(result.action.type, "searchengine", "result.action.type");
|
||||
Assert.ok("params" in result.action, "result.action.params");
|
||||
Assert.equal(result.action.params.engineName, engineName,
|
||||
"result.action.params.engineName");
|
||||
Assert.equal(typeof(result.image), "string", "result.image");
|
||||
Assert.equal(result.title, engineName, "result.title");
|
||||
Assert.equal(result.type, "action searchengine heuristic", "result.type");
|
||||
Assert.equal(result.text, value, "result.text");
|
||||
|
||||
// keydown event. promiseEvent sends an async message to the iframe, but
|
||||
// synthesizeKey is sync, so we need to wait until the content JS receives
|
||||
// the message and adds its event listener before synthesizing the key.
|
||||
let keydownPromises = promiseEvent("keydown");
|
||||
yield keydownPromises[0];
|
||||
EventUtils.synthesizeKey("KEY_ArrowDown", {
|
||||
type: "keydown",
|
||||
code: "ArrowDown",
|
||||
});
|
||||
yield keydownPromises[1];
|
||||
|
||||
// urlbar.getPanelHeight
|
||||
let height = iframe.getBoundingClientRect().height;
|
||||
let readHeight = yield promiseUrlbarFunctionCall("getPanelHeight");
|
||||
Assert.equal(readHeight, height, "getPanelHeight");
|
||||
|
||||
// urlbar.setPanelHeight
|
||||
let newHeight = height + 100;
|
||||
yield promiseUrlbarFunctionCall("setPanelHeight", newHeight);
|
||||
yield new Promise(resolve => {
|
||||
// The height change is animated, so give it time to complete. Again, wait
|
||||
// a sec to be safe.
|
||||
setTimeout(resolve, 1000);
|
||||
});
|
||||
Assert.equal(iframe.getBoundingClientRect().height, newHeight,
|
||||
"setPanelHeight");
|
||||
});
|
||||
|
||||
function promiseIframeLoad() {
|
||||
let msgName = "TestIframeLoadAck";
|
||||
return new Promise(resolve => {
|
||||
info("Waiting for iframe load ack");
|
||||
gMsgMan.addMessageListener(msgName, function onMsg(msg) {
|
||||
info("Received iframe load ack");
|
||||
gMsgMan.removeMessageListener(msgName, onMsg);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a single promise that's resolved when the content JS has called the
|
||||
* function.
|
||||
*/
|
||||
function promiseUrlbarFunctionCall(...args) {
|
||||
return promiseMessage("function", args)[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns two promises in an array. The first is resolved when the content JS
|
||||
* has added its event listener. The second is resolved when the content JS
|
||||
* has received the event.
|
||||
*/
|
||||
function promiseEvent(type) {
|
||||
return promiseMessage("event", type, 2);
|
||||
}
|
||||
|
||||
let gNextMessageID = 1;
|
||||
|
||||
/**
|
||||
* Returns an array of promises, one per ack. Each is resolved when the content
|
||||
* JS acks the message. numExpectedAcks is the number of acks you expect.
|
||||
*/
|
||||
function promiseMessage(type, data, numExpectedAcks = 1) {
|
||||
let testMsgName = "TestMessage";
|
||||
let ackMsgName = "TestMessageAck";
|
||||
let msgID = gNextMessageID++;
|
||||
gMsgMan.sendAsyncMessage(testMsgName, {
|
||||
type: type,
|
||||
messageID: msgID,
|
||||
data: data,
|
||||
});
|
||||
let ackPromises = [];
|
||||
for (let i = 0; i < numExpectedAcks; i++) {
|
||||
let ackIndex = i;
|
||||
ackPromises.push(new Promise(resolve => {
|
||||
info("Waiting for message ack: " + JSON.stringify({
|
||||
type: type,
|
||||
msgID: msgID,
|
||||
ackIndex: ackIndex,
|
||||
}));
|
||||
gMsgMan.addMessageListener(ackMsgName, function onMsg(msg) {
|
||||
// Messages have IDs so that an ack can be correctly paired with the
|
||||
// initial message it's replying to. It's not an error if the ack's ID
|
||||
// isn't equal to msgID here. That will happen when multiple messages
|
||||
// have been sent in a single turn of the event loop so that they're all
|
||||
// waiting on acks. Same goes for ackIndex.
|
||||
if (msg.data.messageID != msgID || msg.data.ackIndex != ackIndex) {
|
||||
return;
|
||||
}
|
||||
info("Received message ack: " + JSON.stringify({
|
||||
type: type,
|
||||
msgID: msg.data.messageID,
|
||||
ackIndex: ackIndex,
|
||||
}));
|
||||
gMsgMan.removeMessageListener(ackMsgName, onMsg);
|
||||
resolve(msg.data.data);
|
||||
});
|
||||
}));
|
||||
}
|
||||
return ackPromises;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
<html>
|
||||
<head>
|
||||
<script src="http://mochi.test:8888/browser/browser/base/content/test/urlbar/urlbarAddonIframe.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
Hello
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,52 @@
|
|||
// Listen for messages from the test.
|
||||
addEventListener("TestEvent", event => {
|
||||
let type = event.detail.type;
|
||||
dump("urlbarAddonIframe.js got TestEvent, type=" + type +
|
||||
" messageID=" + event.detail.messageID + "\n");
|
||||
switch (type) {
|
||||
case "function":
|
||||
callUrlbarFunction(event.detail);
|
||||
break;
|
||||
case "event":
|
||||
expectEvent(event.detail);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// Calls a urlbar API function.
|
||||
function callUrlbarFunction(detail) {
|
||||
let args = detail.data;
|
||||
let methodName = args.shift();
|
||||
dump("urlbarAddonIframe.js calling urlbar." + methodName + "\n");
|
||||
let rv = urlbar[methodName](...args);
|
||||
ack(detail, rv);
|
||||
}
|
||||
|
||||
// Waits for an event of a specified type to happen.
|
||||
function expectEvent(detail) {
|
||||
let type = detail.data;
|
||||
dump("urlbarAddonIframe.js expecting event of type " + type + "\n");
|
||||
// Ack that the message was received and an event listener was added.
|
||||
ack(detail, null, 0);
|
||||
addEventListener(type, function onEvent(event) {
|
||||
dump("urlbarAddonIframe.js got event of type " + type + "\n");
|
||||
if (event.type != type) {
|
||||
return;
|
||||
}
|
||||
dump("urlbarAddonIframe.js got expected event\n");
|
||||
removeEventListener(type, onEvent);
|
||||
// Ack that the event was received.
|
||||
ack(detail, event.detail, 1);
|
||||
});
|
||||
}
|
||||
|
||||
// Sends an ack to the test.
|
||||
function ack(originalEventDetail, ackData = null, ackIndex = 0) {
|
||||
dispatchEvent(new CustomEvent("TestEventAck", {
|
||||
detail: {
|
||||
messageID: originalEventDetail.messageID,
|
||||
ackIndex: ackIndex,
|
||||
data: ackData,
|
||||
},
|
||||
}));
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
// Forward messages from the test to the iframe as events.
|
||||
addMessageListener("TestMessage", msg => {
|
||||
content.dispatchEvent(new content.CustomEvent("TestEvent", {
|
||||
detail: Components.utils.cloneInto(msg.data, content),
|
||||
}));
|
||||
});
|
||||
|
||||
// Forward events from the iframe to the test as messages.
|
||||
addEventListener("TestEventAck", event => {
|
||||
// The waiveXrays call is copied from the contentSearch.js part of
|
||||
// browser_ContentSearch.js test. Not sure whether it's necessary here.
|
||||
sendAsyncMessage("TestMessageAck", Components.utils.waiveXrays(event.detail));
|
||||
}, true, true);
|
||||
|
||||
// Send a message to the test when the iframe is loaded.
|
||||
if (content.document.readyState == "complete") {
|
||||
sendAsyncMessage("TestIframeLoadAck");
|
||||
} else {
|
||||
addEventListener("load", function onLoad(event) {
|
||||
removeEventListener("load", onLoad);
|
||||
sendAsyncMessage("TestIframeLoadAck");
|
||||
}, true, true);
|
||||
}
|
|
@ -1459,7 +1459,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||
</getter>
|
||||
</property>
|
||||
|
||||
<property name="maxResults" readonly="true">
|
||||
<property name="maxResults">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
if (!this._maxResults) {
|
||||
|
@ -1471,6 +1471,11 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||
return this._maxResults;
|
||||
]]>
|
||||
</getter>
|
||||
<setter>
|
||||
<![CDATA[
|
||||
return this._maxResults = parseInt(val);
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
|
||||
<method name="openAutocompletePopup">
|
||||
|
@ -1817,6 +1822,99 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||
]]></body>
|
||||
</method>
|
||||
|
||||
<field name="_addonIframe">null</field>
|
||||
<field name="_addonIframeOwner">null</field>
|
||||
<field name="_addonIframeOverriddenFunctionsByName">{}</field>
|
||||
|
||||
<!-- These methods must be overridden and properly handled by the API
|
||||
runtime so that it doesn't break the popup. If any of these methods
|
||||
is not overridden, then initAddonIframe should throw. -->
|
||||
<field name="_addonIframeOverrideFunctionNames">[
|
||||
"_invalidate",
|
||||
]</field>
|
||||
|
||||
<field name="_addonIframeHiddenAnonids">[
|
||||
"search-suggestions-notification",
|
||||
"richlistbox",
|
||||
"one-off-search-buttons",
|
||||
]</field>
|
||||
<field name="_addonIframeHiddenDisplaysByAnonid">{}</field>
|
||||
|
||||
<method name="initAddonIframe">
|
||||
<parameter name="owner"/>
|
||||
<parameter name="overrides"/>
|
||||
<body><![CDATA[
|
||||
if (this._addonIframeOwner) {
|
||||
// Another add-on has already requested the iframe. Return null to
|
||||
// signal to the calling add-on that it should not take over the
|
||||
// popup. First add-on wins for now.
|
||||
return null;
|
||||
}
|
||||
// Make sure all overrides are provided before doing anything.
|
||||
for (let name of this._addonIframeOverrideFunctionNames) {
|
||||
if (typeof(overrides[name]) != "function") {
|
||||
throw new Error(
|
||||
"Override for method '" + name + "' must be given"
|
||||
);
|
||||
}
|
||||
}
|
||||
// OK, insert the iframe.
|
||||
this._addonIframeOwner = owner;
|
||||
this._addonIframe = this._makeAddonIframe();
|
||||
this._addonIframeOverriddenFunctionsByName = {};
|
||||
for (let name of this._addonIframeOverrideFunctionNames) {
|
||||
this._addonIframeOverriddenFunctionsByName[name] = this[name];
|
||||
this[name] = overrides[name];
|
||||
}
|
||||
return this._addonIframe;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="destroyAddonIframe">
|
||||
<parameter name="owner"/>
|
||||
<body><![CDATA[
|
||||
if (this._addonIframeOwner != owner) {
|
||||
throw new Error("You're not the iframe owner");
|
||||
}
|
||||
this._addonIframeOwner = null;
|
||||
this._addonIframe.remove();
|
||||
this._addonIframe = null;
|
||||
for (let anonid of this._addonIframeHiddenAnonids) {
|
||||
let child = document.getAnonymousElementByAttribute(
|
||||
this, "anonid", anonid
|
||||
);
|
||||
child.style.display =
|
||||
this._addonIframeHiddenDisplaysByAnonid[anonid];
|
||||
}
|
||||
for (let name in this._addonIframeOverriddenFunctionsByName) {
|
||||
this[name] = this._addonIframeOverriddenFunctionsByName[name];
|
||||
}
|
||||
this._addonIframeOverriddenFunctionsByName = {};
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="_makeAddonIframe">
|
||||
<body><![CDATA[
|
||||
this._addonIframeHiddenDisplaysByAnonid = {};
|
||||
for (let anonid of this._addonIframeHiddenAnonids) {
|
||||
let child = document.getAnonymousElementByAttribute(
|
||||
this, "anonid", anonid
|
||||
);
|
||||
this._addonIframeHiddenDisplaysByAnonid[anonid] =
|
||||
child.style.display;
|
||||
child.style.display = "none";
|
||||
}
|
||||
let XUL_NS =
|
||||
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
let iframe = document.createElementNS(XUL_NS, "iframe");
|
||||
iframe.setAttribute("type", "content");
|
||||
iframe.setAttribute("flex", "1");
|
||||
iframe.style.transition = "height 100ms";
|
||||
this.appendChild(iframe);
|
||||
return iframe;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
</implementation>
|
||||
<handlers>
|
||||
|
||||
|
|
|
@ -9,9 +9,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "clearTimeout",
|
|||
XPCOMUtils.defineLazyModuleGetter(this, "setTimeout",
|
||||
"resource://gre/modules/Timer.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "colorUtils", () => {
|
||||
return require("devtools/shared/css/color").colorUtils;
|
||||
});
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "DOMUtils",
|
||||
"@mozilla.org/inspector/dom-utils;1",
|
||||
"inIDOMUtils");
|
||||
|
||||
Cu.import("resource://devtools/shared/event-emitter.js");
|
||||
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
|
||||
|
@ -528,7 +528,7 @@ extensions.registerSchemaAPI("browserAction", "addon_parent", context => {
|
|||
let tab = details.tabId !== null ? TabManager.getTab(details.tabId, context) : null;
|
||||
let color = details.color;
|
||||
if (!Array.isArray(color)) {
|
||||
let col = colorUtils.colorToRGBA(color);
|
||||
let col = DOMUtils.colorToRGBA(color);
|
||||
color = col && [col.r, col.g, col.b, Math.round(col.a * 255)];
|
||||
}
|
||||
BrowserAction.for(extension).setProperty(tab, "badgeBackgroundColor", color);
|
||||
|
|
|
@ -17,10 +17,6 @@ XPCOMUtils.defineLazyServiceGetter(this, "styleSheetService",
|
|||
"@mozilla.org/content/style-sheet-service;1",
|
||||
"nsIStyleSheetService");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "colorUtils", () => {
|
||||
return require("devtools/shared/css/color").colorUtils;
|
||||
});
|
||||
|
||||
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
|
||||
Cu.import("resource://gre/modules/AppConstants.jsm");
|
||||
|
||||
|
|
|
@ -88,7 +88,9 @@ TooltipsOverlay.prototype = {
|
|||
|
||||
if (this.isRuleView) {
|
||||
// Color picker tooltip
|
||||
this.colorPicker = new SwatchColorPickerTooltip(toolbox.doc, this.view.inspector);
|
||||
this.colorPicker = new SwatchColorPickerTooltip(toolbox.doc,
|
||||
this.view.inspector,
|
||||
this._cssProperties);
|
||||
// Cubic bezier tooltip
|
||||
this.cubicBezier = new SwatchCubicBezierTooltip(toolbox.doc);
|
||||
// Filter editor tooltip
|
||||
|
|
|
@ -40,8 +40,11 @@ const CSS_GRID_ENABLED_PREF = "layout.css.grid.enabled";
|
|||
* where CSS_TYPES is defined in devtools/shared/css/properties-db.js
|
||||
* @param {Function} isValidOnClient - A function that checks if a css property
|
||||
* name/value combo is valid.
|
||||
* @param {Function} supportsCssColor4ColorFunction - A function for checking
|
||||
* the supporting of css-color-4 color function.
|
||||
*/
|
||||
function OutputParser(document, {supportsType, isValidOnClient}) {
|
||||
function OutputParser(document,
|
||||
{supportsType, isValidOnClient, supportsCssColor4ColorFunction}) {
|
||||
this.parsed = [];
|
||||
this.doc = document;
|
||||
this.supportsType = supportsType;
|
||||
|
@ -50,6 +53,8 @@ function OutputParser(document, {supportsType, isValidOnClient}) {
|
|||
this.angleSwatches = new WeakMap();
|
||||
this._onColorSwatchMouseDown = this._onColorSwatchMouseDown.bind(this);
|
||||
this._onAngleSwatchMouseDown = this._onAngleSwatchMouseDown.bind(this);
|
||||
|
||||
this.cssColor4 = supportsCssColor4ColorFunction();
|
||||
}
|
||||
|
||||
OutputParser.prototype = {
|
||||
|
@ -186,7 +191,8 @@ OutputParser.prototype = {
|
|||
|
||||
if (options.expectCubicBezier && token.text === "cubic-bezier") {
|
||||
this._appendCubicBezier(functionText, options);
|
||||
} else if (colorOK() && colorUtils.isValidCSSColor(functionText)) {
|
||||
} else if (colorOK() &&
|
||||
colorUtils.isValidCSSColor(functionText, this.cssColor4)) {
|
||||
this._appendColor(functionText, options);
|
||||
} else {
|
||||
this._appendTextNode(functionText);
|
||||
|
@ -203,7 +209,8 @@ OutputParser.prototype = {
|
|||
options.expectDisplay && token.text === "grid" &&
|
||||
text === token.text) {
|
||||
this._appendGrid(token.text, options);
|
||||
} else if (colorOK() && colorUtils.isValidCSSColor(token.text)) {
|
||||
} else if (colorOK() &&
|
||||
colorUtils.isValidCSSColor(token.text, this.cssColor4)) {
|
||||
this._appendColor(token.text, options);
|
||||
} else if (angleOK(token.text)) {
|
||||
this._appendAngle(token.text, options);
|
||||
|
@ -216,7 +223,7 @@ OutputParser.prototype = {
|
|||
case "id":
|
||||
case "hash": {
|
||||
let original = text.substring(token.startOffset, token.endOffset);
|
||||
if (colorOK() && colorUtils.isValidCSSColor(original)) {
|
||||
if (colorOK() && colorUtils.isValidCSSColor(original, this.cssColor4)) {
|
||||
this._appendColor(original, options);
|
||||
} else {
|
||||
this._appendTextNode(original);
|
||||
|
@ -392,7 +399,7 @@ OutputParser.prototype = {
|
|||
* _mergeOptions().
|
||||
*/
|
||||
_appendColor: function (color, options = {}) {
|
||||
let colorObj = new colorUtils.CssColor(color);
|
||||
let colorObj = new colorUtils.CssColor(color, this.cssColor4);
|
||||
|
||||
if (this._isValidColor(colorObj)) {
|
||||
let container = this._createNode("span", {
|
||||
|
|
|
@ -42,15 +42,15 @@ const CSS_COLOR_4_TESTS = [
|
|||
|
||||
function run_test() {
|
||||
for (let test of OLD_STYLE_TESTS) {
|
||||
let ours = colorUtils.colorToRGBA(test, true);
|
||||
let ours = colorUtils.colorToRGBA(test, false);
|
||||
let platform = DOMUtils.colorToRGBA(test);
|
||||
deepEqual(ours, platform, "color " + test + " matches DOMUtils");
|
||||
ok(ours !== null, "'" + test + "' is a color");
|
||||
}
|
||||
|
||||
for (let test of CSS_COLOR_4_TESTS) {
|
||||
let oursOld = colorUtils.colorToRGBA(test, true);
|
||||
let oursNew = colorUtils.colorToRGBA(test, false);
|
||||
let oursOld = colorUtils.colorToRGBA(test, false);
|
||||
let oursNew = colorUtils.colorToRGBA(test, true);
|
||||
let platform = DOMUtils.colorToRGBA(test);
|
||||
notEqual(oursOld, platform, "old style parser for color " + test +
|
||||
" should not match DOMUtils");
|
||||
|
|
|
@ -28,8 +28,12 @@ const XHTML_NS = "http://www.w3.org/1999/xhtml";
|
|||
* inline editor.
|
||||
* @param {InspectorPanel} inspector
|
||||
* The inspector panel, needed for the eyedropper.
|
||||
* @param {Function} supportsCssColor4ColorFunction
|
||||
* A function for checking the supporting of css-color-4 color function.
|
||||
*/
|
||||
function SwatchColorPickerTooltip(document, inspector) {
|
||||
function SwatchColorPickerTooltip(document,
|
||||
inspector,
|
||||
{supportsCssColor4ColorFunction}) {
|
||||
let stylesheet = "chrome://devtools/content/shared/widgets/spectrum.css";
|
||||
SwatchBasedEditorTooltip.call(this, document, stylesheet);
|
||||
|
||||
|
@ -40,6 +44,7 @@ function SwatchColorPickerTooltip(document, inspector) {
|
|||
this.spectrum = this.setColorPickerContent([0, 0, 0, 1]);
|
||||
this._onSpectrumColorChange = this._onSpectrumColorChange.bind(this);
|
||||
this._openEyeDropper = this._openEyeDropper.bind(this);
|
||||
this.cssColor4 = supportsCssColor4ColorFunction();
|
||||
}
|
||||
|
||||
SwatchColorPickerTooltip.prototype = Heritage.extend(SwatchBasedEditorTooltip.prototype, {
|
||||
|
@ -157,14 +162,14 @@ SwatchColorPickerTooltip.prototype = Heritage.extend(SwatchBasedEditorTooltip.pr
|
|||
},
|
||||
|
||||
_colorToRgba: function (color) {
|
||||
color = new colorUtils.CssColor(color);
|
||||
color = new colorUtils.CssColor(color, this.cssColor4);
|
||||
let rgba = color._getRGBATuple();
|
||||
return [rgba.r, rgba.g, rgba.b, rgba.a];
|
||||
},
|
||||
|
||||
_toDefaultType: function (color) {
|
||||
let colorObj = new colorUtils.CssColor(color);
|
||||
colorObj.setAuthoredUnitFromColor(this._originalColor);
|
||||
colorObj.setAuthoredUnitFromColor(this._originalColor, this.cssColor4);
|
||||
return colorObj.toString();
|
||||
},
|
||||
|
||||
|
|
|
@ -30,8 +30,12 @@ exports.CssPropertiesActor = ActorClassWithSpec(cssPropertiesSpec, {
|
|||
getCSSDatabase() {
|
||||
const properties = generateCssProperties();
|
||||
const pseudoElements = DOMUtils.getCSSPseudoElementNames();
|
||||
const supportedFeature = {
|
||||
// checking for css-color-4 color function support.
|
||||
"css-color-4-color-function": DOMUtils.isValidCSSColor("rgb(1 1 1 / 100%"),
|
||||
};
|
||||
|
||||
return { properties, pseudoElements };
|
||||
return { properties, pseudoElements, supportedFeature };
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -28,6 +28,10 @@ const SPECIALVALUES = new Set([
|
|||
* Usage:
|
||||
* let {colorUtils} = require("devtools/shared/css/color");
|
||||
* let color = new colorUtils.CssColor("red");
|
||||
* // In order to support css-color-4 color function, pass true to the
|
||||
* // second argument.
|
||||
* // e.g.
|
||||
* // let color = new colorUtils.CssColor("red", true);
|
||||
*
|
||||
* color.authored === "red"
|
||||
* color.hasAlpha === false
|
||||
|
@ -58,8 +62,9 @@ const SPECIALVALUES = new Set([
|
|||
* Valid values for COLOR_UNIT_PREF are contained in CssColor.COLORUNIT.
|
||||
*/
|
||||
|
||||
function CssColor(colorValue) {
|
||||
function CssColor(colorValue, supportsCssColor4ColorFunction = false) {
|
||||
this.newColor(colorValue);
|
||||
this.cssColor4 = supportsCssColor4ColorFunction;
|
||||
}
|
||||
|
||||
module.exports.colorUtils = {
|
||||
|
@ -92,6 +97,9 @@ CssColor.prototype = {
|
|||
// A lower-cased copy of |authored|.
|
||||
lowerCased: null,
|
||||
|
||||
// Whether the value should be parsed using css-color-4 rules.
|
||||
cssColor4: false,
|
||||
|
||||
_setColorUnitUppercase: function (color) {
|
||||
// Specifically exclude the case where the color is
|
||||
// case-insensitive. This makes it so that "#000" isn't
|
||||
|
@ -136,7 +144,7 @@ CssColor.prototype = {
|
|||
},
|
||||
|
||||
get valid() {
|
||||
return isValidCSSColor(this.authored);
|
||||
return isValidCSSColor(this.authored, this.cssColor4);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -393,7 +401,7 @@ CssColor.prototype = {
|
|||
* appropriate.
|
||||
*/
|
||||
_getRGBATuple: function () {
|
||||
let tuple = colorToRGBA(this.authored);
|
||||
let tuple = colorToRGBA(this.authored, this.cssColor4);
|
||||
|
||||
tuple.a = parseFloat(tuple.a.toFixed(1));
|
||||
|
||||
|
@ -481,11 +489,13 @@ function roundTo(number, digits) {
|
|||
* Color in the form of hex, hsl, hsla, rgb, rgba.
|
||||
* @param {Number} alpha
|
||||
* Alpha value for the color, between 0 and 1.
|
||||
* @param {Boolean} useCssColor4ColorFunction
|
||||
* use css-color-4 color function or not.
|
||||
* @return {String}
|
||||
* Converted color with `alpha` value in rgba form.
|
||||
*/
|
||||
function setAlpha(colorValue, alpha) {
|
||||
let color = new CssColor(colorValue);
|
||||
function setAlpha(colorValue, alpha, useCssColor4ColorFunction = false) {
|
||||
let color = new CssColor(colorValue, useCssColor4ColorFunction);
|
||||
|
||||
// Throw if the color supplied is not valid.
|
||||
if (!color.valid) {
|
||||
|
@ -1049,12 +1059,11 @@ function parseOldStyleRgb(lexer, hasAlpha) {
|
|||
* color's components. Any valid CSS color form can be passed in.
|
||||
*
|
||||
* @param {String} name the color
|
||||
* @param {Boolean} oldColorFunctionSyntax use old color function syntax or the
|
||||
* css-color-4 syntax
|
||||
* @param {Boolean} useCssColor4ColorFunction use css-color-4 color function or not.
|
||||
* @return {Object} an object of the form {r, g, b, a}; or null if the
|
||||
* name was not a valid color
|
||||
*/
|
||||
function colorToRGBA(name, oldColorFunctionSyntax = true) {
|
||||
function colorToRGBA(name, useCssColor4ColorFunction = false) {
|
||||
name = name.trim().toLowerCase();
|
||||
|
||||
if (name in cssColors) {
|
||||
|
@ -1089,7 +1098,7 @@ function colorToRGBA(name, oldColorFunctionSyntax = true) {
|
|||
let hsl = func.text === "hsl" || func.text === "hsla";
|
||||
|
||||
let vals;
|
||||
if (oldColorFunctionSyntax) {
|
||||
if (!useCssColor4ColorFunction) {
|
||||
let hasAlpha = (func.text === "rgba" || func.text === "hsla");
|
||||
vals = hsl ? parseOldStyleHsl(lexer, hasAlpha) : parseOldStyleRgb(lexer, hasAlpha);
|
||||
} else {
|
||||
|
@ -1110,8 +1119,9 @@ function colorToRGBA(name, oldColorFunctionSyntax = true) {
|
|||
* Check whether a string names a valid CSS color.
|
||||
*
|
||||
* @param {String} name The string to check
|
||||
* @param {Boolean} useCssColor4ColorFunction use css-color-4 color function or not.
|
||||
* @return {Boolean} True if the string is a CSS color name.
|
||||
*/
|
||||
function isValidCSSColor(name) {
|
||||
return colorToRGBA(name) !== null;
|
||||
function isValidCSSColor(name, useCssColor4ColorFunction = false) {
|
||||
return colorToRGBA(name, useCssColor4ColorFunction) !== null;
|
||||
}
|
||||
|
|
|
@ -46,6 +46,20 @@ const CssPropertiesFront = FrontClassWithSpec(cssPropertiesSpec, {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Query the feature supporting status in the featureSet.
|
||||
*
|
||||
* @param {Hashmap} featureSet the feature set hashmap
|
||||
* @param {String} feature the feature name string
|
||||
* @return {Boolean} has the feature or not
|
||||
*/
|
||||
function hasFeature(featureSet, feature) {
|
||||
if (feature in featureSet) {
|
||||
return featureSet[feature];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask questions to a CSS database. This class does not care how the database
|
||||
* gets loaded in, only the questions that you can ask to it.
|
||||
|
@ -62,10 +76,16 @@ function CssProperties(db) {
|
|||
this.properties = db.properties;
|
||||
this.pseudoElements = db.pseudoElements;
|
||||
|
||||
// supported feature
|
||||
this.cssColor4ColorFunction = hasFeature(db.supportedFeature,
|
||||
"css-color-4-color-function");
|
||||
|
||||
this.isKnown = this.isKnown.bind(this);
|
||||
this.isInherited = this.isInherited.bind(this);
|
||||
this.supportsType = this.supportsType.bind(this);
|
||||
this.isValidOnClient = this.isValidOnClient.bind(this);
|
||||
this.supportsCssColor4ColorFunction =
|
||||
this.supportsCssColor4ColorFunction.bind(this);
|
||||
|
||||
// A weakly held dummy HTMLDivElement to test CSS properties on the client.
|
||||
this._dummyElements = new WeakMap();
|
||||
|
@ -181,6 +201,15 @@ CssProperties.prototype = {
|
|||
}
|
||||
return [];
|
||||
},
|
||||
|
||||
/**
|
||||
* Checking for the css-color-4 color function support.
|
||||
*
|
||||
* @return {Boolean} Return true if the server supports css-color-4 color function.
|
||||
*/
|
||||
supportsCssColor4ColorFunction() {
|
||||
return this.cssColor4ColorFunction;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -296,6 +325,11 @@ function normalizeCssData(db) {
|
|||
|
||||
reattachCssColorValues(db);
|
||||
|
||||
// If there is no supportedFeature in db, create an empty one.
|
||||
if (!db.supportedFeature) {
|
||||
db.supportedFeature = {};
|
||||
}
|
||||
|
||||
return db;
|
||||
}
|
||||
|
||||
|
|
|
@ -10952,7 +10952,8 @@ nsDocShell::DoURILoad(nsIURI* aURI,
|
|||
if (aBaseURI) {
|
||||
nsCOMPtr<nsIViewSourceChannel> vsc = do_QueryInterface(channel);
|
||||
if (vsc) {
|
||||
vsc->SetBaseURI(aBaseURI);
|
||||
rv = vsc->SetBaseURI(aBaseURI);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -18965,7 +18965,7 @@ DatabaseMaintenance::DetermineMaintenanceAction(
|
|||
|
||||
bool lowDiskSpace = IndexedDatabaseManager::InLowDiskSpaceMode();
|
||||
|
||||
if (QuotaManager::kRunningXPCShellTests) {
|
||||
if (QuotaManager::IsRunningXPCShellTests()) {
|
||||
// If we're running XPCShell then we want to test both the low disk space
|
||||
// and normal disk space code paths so pick semi-randomly based on the
|
||||
// current time.
|
||||
|
|
|
@ -129,7 +129,6 @@ protected:
|
|||
layers::ImageContainer* mImageContainer;
|
||||
const VideoInfo& mConfig;
|
||||
RefPtr<AndroidSurfaceTexture> mSurfaceTexture;
|
||||
RefPtr<SamplesWaitingForKey> mSamplesWaitingForKey;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1797,11 +1797,13 @@ nsNPAPIPluginInstance::WindowVolumeChanged(float aVolume, bool aMuted)
|
|||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "SetMuted failed");
|
||||
if (mMuted != aMuted) {
|
||||
mMuted = aMuted;
|
||||
AudioChannelService::AudibleState audible = aMuted ?
|
||||
AudioChannelService::AudibleState::eNotAudible :
|
||||
AudioChannelService::AudibleState::eAudible;
|
||||
mAudioChannelAgent->NotifyStartedAudible(audible,
|
||||
AudioChannelService::AudibleChangedReasons::eVolumeChanged);
|
||||
if (mAudioChannelAgent) {
|
||||
AudioChannelService::AudibleState audible = aMuted ?
|
||||
AudioChannelService::AudibleState::eNotAudible :
|
||||
AudioChannelService::AudibleState::eAudible;
|
||||
mAudioChannelAgent->NotifyStartedAudible(audible,
|
||||
AudioChannelService::AudibleChangedReasons::eVolumeChanged);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -106,8 +106,6 @@ namespace quota {
|
|||
|
||||
using namespace mozilla::ipc;
|
||||
|
||||
const bool QuotaManager::kRunningXPCShellTests = !!PR_GetEnv("XPCSHELL_TEST_PROFILE_DIR");
|
||||
|
||||
// We want profiles to be platform-independent so we always need to replace
|
||||
// the same characters on every platform. Windows has the most extensive set
|
||||
// of illegal characters so we use its FILE_ILLEGAL_CHARACTERS and
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include "Client.h"
|
||||
#include "PersistenceType.h"
|
||||
|
||||
#include "prenv.h"
|
||||
|
||||
#define QUOTA_MANAGER_CONTRACTID "@mozilla.org/dom/quota/manager;1"
|
||||
|
||||
class mozIStorageConnection;
|
||||
|
@ -113,7 +115,11 @@ private:
|
|||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(QuotaManager)
|
||||
|
||||
static const bool kRunningXPCShellTests;
|
||||
static bool IsRunningXPCShellTests()
|
||||
{
|
||||
static bool kRunningXPCShellTests = !!PR_GetEnv("XPCSHELL_TEST_PROFILE_DIR");
|
||||
return kRunningXPCShellTests;
|
||||
}
|
||||
|
||||
static const char kReplaceChars[];
|
||||
|
||||
|
|
|
@ -438,7 +438,7 @@ QuotaManagerService::PerformIdleMaintenance()
|
|||
#ifdef MOZ_WIDGET_ANDROID
|
||||
// Android XPCShell doesn't load the AndroidBridge that is needed to make
|
||||
// GetCurrentBatteryInformation work...
|
||||
if (!QuotaManager::kRunningXPCShellTests)
|
||||
if (!QuotaManager::IsRunningXPCShellTests())
|
||||
#endif
|
||||
{
|
||||
// In order to give the correct battery level, hal must have registered
|
||||
|
@ -450,7 +450,7 @@ QuotaManagerService::PerformIdleMaintenance()
|
|||
|
||||
// If we're running XPCShell because we always want to be able to test this
|
||||
// code so pretend that we're always charging.
|
||||
if (QuotaManager::kRunningXPCShellTests) {
|
||||
if (QuotaManager::IsRunningXPCShellTests()) {
|
||||
batteryInfo.level() = 100;
|
||||
batteryInfo.charging() = true;
|
||||
}
|
||||
|
@ -459,7 +459,7 @@ QuotaManagerService::PerformIdleMaintenance()
|
|||
return;
|
||||
}
|
||||
|
||||
if (QuotaManager::kRunningXPCShellTests) {
|
||||
if (QuotaManager::IsRunningXPCShellTests()) {
|
||||
// We don't want user activity to impact this code if we're running tests.
|
||||
Unused << Observe(nullptr, OBSERVER_TOPIC_IDLE, nullptr);
|
||||
} else if (!mIdleObserverRegistered) {
|
||||
|
|
|
@ -1201,12 +1201,23 @@ EditorBase::SetAttribute(nsIDOMElement* aElement,
|
|||
const nsAString& aAttribute,
|
||||
const nsAString& aValue)
|
||||
{
|
||||
if (NS_WARN_IF(aAttribute.IsEmpty())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsCOMPtr<Element> element = do_QueryInterface(aElement);
|
||||
NS_ENSURE_TRUE(element, NS_ERROR_NULL_POINTER);
|
||||
nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
|
||||
|
||||
return SetAttribute(element, attribute, aValue);
|
||||
}
|
||||
|
||||
nsresult
|
||||
EditorBase::SetAttribute(Element* aElement,
|
||||
nsIAtom* aAttribute,
|
||||
const nsAString& aValue)
|
||||
{
|
||||
RefPtr<ChangeAttributeTransaction> transaction =
|
||||
CreateTxnForSetAttribute(*element, *attribute, aValue);
|
||||
CreateTxnForSetAttribute(*aElement, *aAttribute, aValue);
|
||||
return DoTransaction(transaction);
|
||||
}
|
||||
|
||||
|
@ -1235,12 +1246,22 @@ NS_IMETHODIMP
|
|||
EditorBase::RemoveAttribute(nsIDOMElement* aElement,
|
||||
const nsAString& aAttribute)
|
||||
{
|
||||
if (NS_WARN_IF(aAttribute.IsEmpty())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsCOMPtr<Element> element = do_QueryInterface(aElement);
|
||||
NS_ENSURE_TRUE(element, NS_ERROR_NULL_POINTER);
|
||||
nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
|
||||
|
||||
return RemoveAttribute(element, attribute);
|
||||
}
|
||||
|
||||
nsresult
|
||||
EditorBase::RemoveAttribute(Element* aElement,
|
||||
nsIAtom* aAttribute)
|
||||
{
|
||||
RefPtr<ChangeAttributeTransaction> transaction =
|
||||
CreateTxnForRemoveAttribute(*element, *attribute);
|
||||
CreateTxnForRemoveAttribute(*aElement, *aAttribute);
|
||||
return DoTransaction(transaction);
|
||||
}
|
||||
|
||||
|
@ -2180,25 +2201,28 @@ EditorBase::CloneAttribute(const nsAString& aAttribute,
|
|||
nsIDOMNode* aSourceNode)
|
||||
{
|
||||
NS_ENSURE_TRUE(aDestNode && aSourceNode, NS_ERROR_NULL_POINTER);
|
||||
|
||||
nsCOMPtr<nsIDOMElement> destElement = do_QueryInterface(aDestNode);
|
||||
nsCOMPtr<nsIDOMElement> sourceElement = do_QueryInterface(aSourceNode);
|
||||
NS_ENSURE_TRUE(destElement && sourceElement, NS_ERROR_NO_INTERFACE);
|
||||
|
||||
nsAutoString attrValue;
|
||||
bool isAttrSet;
|
||||
nsresult rv = GetAttributeValue(sourceElement,
|
||||
aAttribute,
|
||||
attrValue,
|
||||
&isAttrSet);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (isAttrSet) {
|
||||
rv = SetAttribute(destElement, aAttribute, attrValue);
|
||||
} else {
|
||||
rv = RemoveAttribute(destElement, aAttribute);
|
||||
if (NS_WARN_IF(aAttribute.IsEmpty())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return rv;
|
||||
nsCOMPtr<Element> destElement = do_QueryInterface(aDestNode);
|
||||
nsCOMPtr<Element> sourceElement = do_QueryInterface(aSourceNode);
|
||||
NS_ENSURE_TRUE(destElement && sourceElement, NS_ERROR_NO_INTERFACE);
|
||||
|
||||
nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
|
||||
return CloneAttribute(attribute, destElement, sourceElement);
|
||||
}
|
||||
|
||||
nsresult
|
||||
EditorBase::CloneAttribute(nsIAtom* aAttribute,
|
||||
Element* aDestElement,
|
||||
Element* aSourceElement)
|
||||
{
|
||||
nsAutoString attrValue;
|
||||
if (aSourceElement->GetAttr(kNameSpaceID_None, aAttribute, attrValue)) {
|
||||
return SetAttribute(aDestElement, aAttribute, attrValue);
|
||||
}
|
||||
return RemoveAttribute(aDestElement, aAttribute);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2237,11 +2261,9 @@ EditorBase::CloneAttributes(Element* aDest,
|
|||
RefPtr<nsDOMAttributeMap> destAttributes = aDest->Attributes();
|
||||
while (RefPtr<Attr> attr = destAttributes->Item(0)) {
|
||||
if (destInBody) {
|
||||
RemoveAttribute(static_cast<nsIDOMElement*>(GetAsDOMNode(aDest)),
|
||||
attr->NodeName());
|
||||
RemoveAttribute(aDest, attr->NodeInfo()->NameAtom());
|
||||
} else {
|
||||
ErrorResult ignored;
|
||||
aDest->RemoveAttribute(attr->NodeName(), ignored);
|
||||
aDest->UnsetAttr(kNameSpaceID_None, attr->NodeInfo()->NameAtom(), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2253,13 +2275,13 @@ EditorBase::CloneAttributes(Element* aDest,
|
|||
nsAutoString value;
|
||||
attr->GetValue(value);
|
||||
if (destInBody) {
|
||||
SetAttributeOrEquivalent(static_cast<nsIDOMElement*>(GetAsDOMNode(aDest)),
|
||||
attr->NodeName(), value, false);
|
||||
SetAttributeOrEquivalent(aDest, attr->NodeInfo()->NameAtom(), value,
|
||||
false);
|
||||
} else {
|
||||
// The element is not inserted in the document yet, we don't want to put
|
||||
// a transaction on the UndoStack
|
||||
SetAttributeOrEquivalent(static_cast<nsIDOMElement*>(GetAsDOMNode(aDest)),
|
||||
attr->NodeName(), value, true);
|
||||
SetAttributeOrEquivalent(aDest, attr->NodeInfo()->NameAtom(), value,
|
||||
true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4590,21 +4612,32 @@ EditorBase::CreateHTMLContent(nsIAtom* aTag)
|
|||
kNameSpaceID_XHTML);
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
EditorBase::SetAttributeOrEquivalent(nsIDOMElement* aElement,
|
||||
const nsAString& aAttribute,
|
||||
const nsAString& aValue,
|
||||
bool aSuppressTransaction)
|
||||
{
|
||||
return SetAttribute(aElement, aAttribute, aValue);
|
||||
nsCOMPtr<Element> element = do_QueryInterface(aElement);
|
||||
if (NS_WARN_IF(!element)) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
|
||||
return SetAttributeOrEquivalent(element, attribute, aValue,
|
||||
aSuppressTransaction);
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
EditorBase::RemoveAttributeOrEquivalent(nsIDOMElement* aElement,
|
||||
const nsAString& aAttribute,
|
||||
bool aSuppressTransaction)
|
||||
{
|
||||
return RemoveAttribute(aElement, aAttribute);
|
||||
nsCOMPtr<Element> element = do_QueryInterface(aElement);
|
||||
if (NS_WARN_IF(!element)) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
|
||||
return RemoveAttributeOrEquivalent(element, attribute, aSuppressTransaction);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -234,6 +234,19 @@ public:
|
|||
nsresult JoinNodes(nsINode& aLeftNode, nsINode& aRightNode);
|
||||
nsresult MoveNode(nsIContent* aNode, nsINode* aParent, int32_t aOffset);
|
||||
|
||||
nsresult CloneAttribute(nsIAtom* aAttribute, Element* aDestElement,
|
||||
Element* aSourceElement);
|
||||
nsresult RemoveAttribute(Element* aElement, nsIAtom* aAttribute);
|
||||
virtual nsresult RemoveAttributeOrEquivalent(Element* aElement,
|
||||
nsIAtom* aAttribute,
|
||||
bool aSuppressTransaction) = 0;
|
||||
nsresult SetAttribute(Element* aElement, nsIAtom* aAttribute,
|
||||
const nsAString& aValue);
|
||||
virtual nsresult SetAttributeOrEquivalent(Element* aElement,
|
||||
nsIAtom* aAttribute,
|
||||
const nsAString& aValue,
|
||||
bool aSuppressTransaction) = 0;
|
||||
|
||||
/**
|
||||
* Method to replace certain CreateElementNS() calls.
|
||||
*
|
||||
|
|
|
@ -3278,15 +3278,15 @@ HTMLEditRules::WillMakeList(Selection* aSelection,
|
|||
}
|
||||
}
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
nsCOMPtr<nsIDOMElement> curElement = do_QueryInterface(curNode);
|
||||
NS_NAMED_LITERAL_STRING(typestr, "type");
|
||||
nsCOMPtr<Element> curElement = do_QueryInterface(curNode);
|
||||
if (aBulletType && !aBulletType->IsEmpty()) {
|
||||
rv = mHTMLEditor->SetAttribute(curElement, typestr, *aBulletType);
|
||||
rv = mHTMLEditor->SetAttribute(curElement, nsGkAtoms::type,
|
||||
*aBulletType);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
} else {
|
||||
rv = mHTMLEditor->RemoveAttribute(curElement, typestr);
|
||||
rv = mHTMLEditor->RemoveAttribute(curElement, nsGkAtoms::type);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -4807,7 +4807,6 @@ HTMLEditRules::AlignBlockContents(nsIDOMNode* aNode,
|
|||
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
|
||||
NS_ENSURE_TRUE(node && alignType, NS_ERROR_NULL_POINTER);
|
||||
nsCOMPtr<nsIContent> firstChild, lastChild;
|
||||
nsCOMPtr<Element> divNode;
|
||||
|
||||
bool useCSS = mHTMLEditor->IsCSSEnabled();
|
||||
|
||||
|
@ -4815,24 +4814,25 @@ HTMLEditRules::AlignBlockContents(nsIDOMNode* aNode,
|
|||
firstChild = mHTMLEditor->GetFirstEditableChild(*node);
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
lastChild = mHTMLEditor->GetLastEditableChild(*node);
|
||||
NS_NAMED_LITERAL_STRING(attr, "align");
|
||||
if (!firstChild) {
|
||||
// this cell has no content, nothing to align
|
||||
} else if (firstChild == lastChild &&
|
||||
firstChild->IsHTMLElement(nsGkAtoms::div)) {
|
||||
// the cell already has a div containing all of its content: just
|
||||
// act on this div.
|
||||
nsCOMPtr<nsIDOMElement> divElem = do_QueryInterface(firstChild);
|
||||
RefPtr<Element> divElem = firstChild->AsElement();
|
||||
if (useCSS) {
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
nsresult rv = mHTMLEditor->SetAttributeOrEquivalent(divElem, attr,
|
||||
nsresult rv = mHTMLEditor->SetAttributeOrEquivalent(divElem,
|
||||
nsGkAtoms::align,
|
||||
*alignType, false);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
} else {
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
nsresult rv = mHTMLEditor->SetAttribute(divElem, attr, *alignType);
|
||||
nsresult rv = mHTMLEditor->SetAttribute(divElem, nsGkAtoms::align,
|
||||
*alignType);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -4840,28 +4840,29 @@ HTMLEditRules::AlignBlockContents(nsIDOMNode* aNode,
|
|||
} else {
|
||||
// else we need to put in a div, set the alignment, and toss in all the children
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
divNode = mHTMLEditor->CreateNode(nsGkAtoms::div, node, 0);
|
||||
NS_ENSURE_STATE(divNode);
|
||||
RefPtr<Element> divElem = mHTMLEditor->CreateNode(nsGkAtoms::div, node, 0);
|
||||
NS_ENSURE_STATE(divElem);
|
||||
// set up the alignment on the div
|
||||
nsCOMPtr<nsIDOMElement> divElem = do_QueryInterface(divNode);
|
||||
if (useCSS) {
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
nsresult rv =
|
||||
mHTMLEditor->SetAttributeOrEquivalent(divElem, attr, *alignType, false);
|
||||
mHTMLEditor->SetAttributeOrEquivalent(divElem, nsGkAtoms::align,
|
||||
*alignType, false);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
} else {
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
nsresult rv = mHTMLEditor->SetAttribute(divElem, attr, *alignType);
|
||||
nsresult rv =
|
||||
mHTMLEditor->SetAttribute(divElem, nsGkAtoms::align, *alignType);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
// tuck the children into the end of the active div
|
||||
while (lastChild && (lastChild != divNode)) {
|
||||
while (lastChild && (lastChild != divElem)) {
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
nsresult rv = mHTMLEditor->MoveNode(lastChild, divNode, 0);
|
||||
nsresult rv = mHTMLEditor->MoveNode(lastChild, divElem, 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
lastChild = mHTMLEditor->GetLastEditableChild(*node);
|
||||
|
@ -6460,9 +6461,9 @@ HTMLEditRules::SplitParagraph(nsIDOMNode *aPara,
|
|||
}
|
||||
|
||||
// remove ID attribute on the paragraph we just created
|
||||
nsCOMPtr<nsIDOMElement> rightElt = do_QueryInterface(rightPara);
|
||||
RefPtr<Element> rightElt = rightPara->AsElement();
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
rv = mHTMLEditor->RemoveAttribute(rightElt, NS_LITERAL_STRING("id"));
|
||||
rv = mHTMLEditor->RemoveAttribute(rightElt, nsGkAtoms::id);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// check both halves of para to see if we need mozBR
|
||||
|
@ -8321,18 +8322,18 @@ HTMLEditRules::RemoveAlignment(nsIDOMNode* aNode,
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else if (isBlock || HTMLEditUtils::IsHR(child)) {
|
||||
// the current node is a block element
|
||||
nsCOMPtr<nsIDOMElement> curElem = do_QueryInterface(child);
|
||||
nsCOMPtr<Element> curElem = do_QueryInterface(child);
|
||||
if (HTMLEditUtils::SupportsAlignAttr(child)) {
|
||||
// remove the ALIGN attribute if this element can have it
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
rv = mHTMLEditor->RemoveAttribute(curElem, NS_LITERAL_STRING("align"));
|
||||
rv = mHTMLEditor->RemoveAttribute(curElem, nsGkAtoms::align);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
if (useCSS) {
|
||||
if (HTMLEditUtils::IsTable(child) || HTMLEditUtils::IsHR(child)) {
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
rv = mHTMLEditor->SetAttributeOrEquivalent(curElem,
|
||||
NS_LITERAL_STRING("align"),
|
||||
nsGkAtoms::align,
|
||||
aAlignType, false);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
|
@ -8452,21 +8453,17 @@ HTMLEditRules::AlignBlock(Element& aElement,
|
|||
nsresult rv = RemoveAlignment(aElement.AsDOMNode(), aAlignType,
|
||||
aContentsOnly == ContentsOnly::yes);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_NAMED_LITERAL_STRING(attr, "align");
|
||||
if (htmlEditor->IsCSSEnabled()) {
|
||||
// Let's use CSS alignment; we use margin-left and margin-right for tables
|
||||
// and text-align for other block-level elements
|
||||
rv = htmlEditor->SetAttributeOrEquivalent(
|
||||
static_cast<nsIDOMElement*>(aElement.AsDOMNode()),
|
||||
attr, aAlignType, false);
|
||||
&aElement, nsGkAtoms::align, aAlignType, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else {
|
||||
// HTML case; this code is supposed to be called ONLY if the element
|
||||
// supports the align attribute but we'll never know...
|
||||
if (HTMLEditUtils::SupportsAlignAttr(aElement.AsDOMNode())) {
|
||||
rv = htmlEditor->SetAttribute(
|
||||
static_cast<nsIDOMElement*>(aElement.AsDOMNode()),
|
||||
attr, aAlignType);
|
||||
rv = htmlEditor->SetAttribute(&aElement, nsGkAtoms::align, aAlignType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2596,7 +2596,7 @@ HTMLEditor::CreateElementWithDefaults(const nsAString& aTagName)
|
|||
|
||||
// New call to use instead to get proper HTML element, bug 39919
|
||||
nsCOMPtr<nsIAtom> realTagAtom = NS_Atomize(realTagName);
|
||||
nsCOMPtr<Element> newElement = CreateHTMLContent(realTagAtom);
|
||||
RefPtr<Element> newElement = CreateHTMLContent(realTagAtom);
|
||||
if (!newElement) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -2628,8 +2628,7 @@ HTMLEditor::CreateElementWithDefaults(const nsAString& aTagName)
|
|||
} else if (tagName.EqualsLiteral("td")) {
|
||||
nsresult rv =
|
||||
SetAttributeOrEquivalent(
|
||||
static_cast<nsIDOMElement*>(newElement->AsDOMNode()),
|
||||
NS_LITERAL_STRING("valign"), NS_LITERAL_STRING("top"), true);
|
||||
newElement, nsGkAtoms::valign, NS_LITERAL_STRING("top"), true);
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
}
|
||||
// ADD OTHER TAGS HERE
|
||||
|
@ -4447,93 +4446,83 @@ HTMLEditor::IsEmptyNodeImpl(nsINode* aNode,
|
|||
// add to aElement the CSS inline styles corresponding to the HTML attribute
|
||||
// aAttribute with its value aValue
|
||||
nsresult
|
||||
HTMLEditor::SetAttributeOrEquivalent(nsIDOMElement* aElement,
|
||||
const nsAString& aAttribute,
|
||||
HTMLEditor::SetAttributeOrEquivalent(Element* aElement,
|
||||
nsIAtom* aAttribute,
|
||||
const nsAString& aValue,
|
||||
bool aSuppressTransaction)
|
||||
{
|
||||
MOZ_ASSERT(aElement);
|
||||
MOZ_ASSERT(aAttribute);
|
||||
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
|
||||
if (IsCSSEnabled() && mCSSEditUtils) {
|
||||
nsCOMPtr<dom::Element> element = do_QueryInterface(aElement);
|
||||
MOZ_ASSERT(element);
|
||||
|
||||
nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
|
||||
MOZ_ASSERT(attribute);
|
||||
|
||||
int32_t count =
|
||||
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(element, nullptr,
|
||||
attribute, &aValue,
|
||||
aSuppressTransaction);
|
||||
if (count) {
|
||||
// we found an equivalence ; let's remove the HTML attribute itself if it is set
|
||||
nsAutoString existingValue;
|
||||
bool wasSet = false;
|
||||
nsresult rv =
|
||||
GetAttributeValue(aElement, aAttribute, existingValue, &wasSet);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!wasSet) {
|
||||
return NS_OK;
|
||||
}
|
||||
return aSuppressTransaction ?
|
||||
element->UnsetAttr(kNameSpaceID_None, attribute, true) :
|
||||
RemoveAttribute(aElement, aAttribute);
|
||||
}
|
||||
|
||||
// count is an integer that represents the number of CSS declarations applied to the
|
||||
// element. If it is zero, we found no equivalence in this implementation for the
|
||||
// attribute
|
||||
if (attribute == nsGkAtoms::style) {
|
||||
// if it is the style attribute, just add the new value to the existing style
|
||||
// attribute's value
|
||||
nsAutoString existingValue;
|
||||
bool wasSet = false;
|
||||
nsresult rv = GetAttributeValue(aElement, NS_LITERAL_STRING("style"),
|
||||
existingValue, &wasSet);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
existingValue.Append(' ');
|
||||
existingValue.Append(aValue);
|
||||
return aSuppressTransaction ?
|
||||
element->SetAttr(kNameSpaceID_None, attribute, existingValue, true) :
|
||||
SetAttribute(aElement, aAttribute, existingValue);
|
||||
}
|
||||
|
||||
// we have no CSS equivalence for this attribute and it is not the style
|
||||
// attribute; let's set it the good'n'old HTML way
|
||||
if (!IsCSSEnabled() || !mCSSEditUtils) {
|
||||
// we are not in an HTML+CSS editor; let's set the attribute the HTML way
|
||||
return aSuppressTransaction ?
|
||||
element->SetAttr(kNameSpaceID_None, attribute, aValue, true) :
|
||||
aElement->SetAttr(kNameSpaceID_None, aAttribute, aValue, true) :
|
||||
SetAttribute(aElement, aAttribute, aValue);
|
||||
}
|
||||
|
||||
// we are not in an HTML+CSS editor; let's set the attribute the HTML way
|
||||
return aSuppressTransaction ? aElement->SetAttribute(aAttribute, aValue) :
|
||||
SetAttribute(aElement, aAttribute, aValue);
|
||||
int32_t count =
|
||||
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(aElement, nullptr,
|
||||
aAttribute, &aValue,
|
||||
aSuppressTransaction);
|
||||
if (count) {
|
||||
// we found an equivalence ; let's remove the HTML attribute itself if it
|
||||
// is set
|
||||
nsAutoString existingValue;
|
||||
if (!aElement->GetAttr(kNameSpaceID_None, aAttribute, existingValue)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return aSuppressTransaction ?
|
||||
aElement->UnsetAttr(kNameSpaceID_None, aAttribute, true) :
|
||||
RemoveAttribute(aElement, aAttribute);
|
||||
}
|
||||
|
||||
// count is an integer that represents the number of CSS declarations applied
|
||||
// to the element. If it is zero, we found no equivalence in this
|
||||
// implementation for the attribute
|
||||
if (aAttribute == nsGkAtoms::style) {
|
||||
// if it is the style attribute, just add the new value to the existing
|
||||
// style attribute's value
|
||||
nsAutoString existingValue;
|
||||
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::style, existingValue);
|
||||
existingValue.Append(' ');
|
||||
existingValue.Append(aValue);
|
||||
return aSuppressTransaction ?
|
||||
aElement->SetAttr(kNameSpaceID_None, aAttribute, existingValue, true) :
|
||||
SetAttribute(aElement, aAttribute, existingValue);
|
||||
}
|
||||
|
||||
// we have no CSS equivalence for this attribute and it is not the style
|
||||
// attribute; let's set it the good'n'old HTML way
|
||||
return aSuppressTransaction ?
|
||||
aElement->SetAttr(kNameSpaceID_None, aAttribute, aValue, true) :
|
||||
SetAttribute(aElement, aAttribute, aValue);
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLEditor::RemoveAttributeOrEquivalent(nsIDOMElement* aElement,
|
||||
const nsAString& aAttribute,
|
||||
HTMLEditor::RemoveAttributeOrEquivalent(Element* aElement,
|
||||
nsIAtom* aAttribute,
|
||||
bool aSuppressTransaction)
|
||||
{
|
||||
nsCOMPtr<dom::Element> element = do_QueryInterface(aElement);
|
||||
NS_ENSURE_TRUE(element, NS_OK);
|
||||
|
||||
nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
|
||||
MOZ_ASSERT(attribute);
|
||||
MOZ_ASSERT(aElement);
|
||||
MOZ_ASSERT(aAttribute);
|
||||
|
||||
if (IsCSSEnabled() && mCSSEditUtils) {
|
||||
nsresult rv =
|
||||
mCSSEditUtils->RemoveCSSEquivalentToHTMLStyle(
|
||||
element, nullptr, attribute, nullptr, aSuppressTransaction);
|
||||
aElement, nullptr, aAttribute, nullptr, aSuppressTransaction);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (!element->HasAttr(kNameSpaceID_None, attribute)) {
|
||||
if (!aElement->HasAttr(kNameSpaceID_None, aAttribute)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return aSuppressTransaction ?
|
||||
element->UnsetAttr(kNameSpaceID_None, attribute, /* aNotify = */ true) :
|
||||
aElement->UnsetAttr(kNameSpaceID_None, aAttribute, /* aNotify = */ true) :
|
||||
RemoveAttribute(aElement, aAttribute);
|
||||
}
|
||||
|
||||
|
|
|
@ -121,6 +121,16 @@ public:
|
|||
virtual already_AddRefed<nsIContent> GetInputEventTargetContent() override;
|
||||
virtual bool IsEditable(nsINode* aNode) override;
|
||||
using EditorBase::IsEditable;
|
||||
virtual nsresult RemoveAttributeOrEquivalent(
|
||||
Element* aElement,
|
||||
nsIAtom* aAttribute,
|
||||
bool aSuppressTransaction) override;
|
||||
virtual nsresult SetAttributeOrEquivalent(Element* aElement,
|
||||
nsIAtom* aAttribute,
|
||||
const nsAString& aValue,
|
||||
bool aSuppressTransaction) override;
|
||||
using EditorBase::RemoveAttributeOrEquivalent;
|
||||
using EditorBase::SetAttributeOrEquivalent;
|
||||
|
||||
// nsStubMutationObserver overrides
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
|
||||
|
@ -329,14 +339,6 @@ public:
|
|||
*/
|
||||
virtual nsresult SelectEntireDocument(Selection* aSelection) override;
|
||||
|
||||
NS_IMETHOD SetAttributeOrEquivalent(nsIDOMElement* aElement,
|
||||
const nsAString& aAttribute,
|
||||
const nsAString& aValue,
|
||||
bool aSuppressTransaction) override;
|
||||
NS_IMETHOD RemoveAttributeOrEquivalent(nsIDOMElement* aElement,
|
||||
const nsAString& aAttribute,
|
||||
bool aSuppressTransaction) override;
|
||||
|
||||
/**
|
||||
* Join together any adjacent editable text nodes in the range.
|
||||
*/
|
||||
|
|
|
@ -910,35 +910,30 @@ HTMLEditor::SetFinalSize(int32_t aX,
|
|||
// we want one transaction only from a user's point of view
|
||||
AutoEditBatch batchIt(this);
|
||||
|
||||
NS_NAMED_LITERAL_STRING(widthStr, "width");
|
||||
NS_NAMED_LITERAL_STRING(heightStr, "height");
|
||||
|
||||
nsCOMPtr<Element> resizedObject = do_QueryInterface(mResizedObject);
|
||||
NS_ENSURE_TRUE(resizedObject, );
|
||||
if (mResizedObjectIsAbsolutelyPositioned) {
|
||||
if (setHeight) {
|
||||
mCSSEditUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::top, y);
|
||||
mCSSEditUtils->SetCSSPropertyPixels(*mResizedObject, *nsGkAtoms::top, y);
|
||||
}
|
||||
if (setWidth) {
|
||||
mCSSEditUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::left, x);
|
||||
mCSSEditUtils->SetCSSPropertyPixels(*mResizedObject, *nsGkAtoms::left, x);
|
||||
}
|
||||
}
|
||||
if (IsCSSEnabled() || mResizedObjectIsAbsolutelyPositioned) {
|
||||
if (setWidth && mResizedObject->HasAttr(kNameSpaceID_None, nsGkAtoms::width)) {
|
||||
RemoveAttribute(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)), widthStr);
|
||||
RemoveAttribute(mResizedObject, nsGkAtoms::width);
|
||||
}
|
||||
|
||||
if (setHeight && mResizedObject->HasAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::height)) {
|
||||
RemoveAttribute(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)), heightStr);
|
||||
RemoveAttribute(mResizedObject, nsGkAtoms::height);
|
||||
}
|
||||
|
||||
if (setWidth) {
|
||||
mCSSEditUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::width,
|
||||
mCSSEditUtils->SetCSSPropertyPixels(*mResizedObject, *nsGkAtoms::width,
|
||||
width);
|
||||
}
|
||||
if (setHeight) {
|
||||
mCSSEditUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::height,
|
||||
mCSSEditUtils->SetCSSPropertyPixels(*mResizedObject, *nsGkAtoms::height,
|
||||
height);
|
||||
}
|
||||
} else {
|
||||
|
@ -948,30 +943,30 @@ HTMLEditor::SetFinalSize(int32_t aX,
|
|||
// triggering an immediate reflow; otherwise, we have problems
|
||||
// with asynchronous reflow
|
||||
if (setWidth) {
|
||||
mCSSEditUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::width,
|
||||
mCSSEditUtils->SetCSSPropertyPixels(*mResizedObject, *nsGkAtoms::width,
|
||||
width);
|
||||
}
|
||||
if (setHeight) {
|
||||
mCSSEditUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::height,
|
||||
mCSSEditUtils->SetCSSPropertyPixels(*mResizedObject, *nsGkAtoms::height,
|
||||
height);
|
||||
}
|
||||
if (setWidth) {
|
||||
nsAutoString w;
|
||||
w.AppendInt(width);
|
||||
SetAttribute(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)), widthStr, w);
|
||||
SetAttribute(mResizedObject, nsGkAtoms::width, w);
|
||||
}
|
||||
if (setHeight) {
|
||||
nsAutoString h;
|
||||
h.AppendInt(height);
|
||||
SetAttribute(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)), heightStr, h);
|
||||
SetAttribute(mResizedObject, nsGkAtoms::height, h);
|
||||
}
|
||||
|
||||
if (setWidth) {
|
||||
mCSSEditUtils->RemoveCSSProperty(*resizedObject, *nsGkAtoms::width,
|
||||
mCSSEditUtils->RemoveCSSProperty(*mResizedObject, *nsGkAtoms::width,
|
||||
EmptyString());
|
||||
}
|
||||
if (setHeight) {
|
||||
mCSSEditUtils->RemoveCSSProperty(*resizedObject, *nsGkAtoms::height,
|
||||
mCSSEditUtils->RemoveCSSProperty(*mResizedObject, *nsGkAtoms::height,
|
||||
EmptyString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -731,9 +731,6 @@ HTMLEditor::RemoveStyleInside(nsIContent& aNode,
|
|||
// if we weren't passed an attribute, then we want to
|
||||
// remove any matching inlinestyles entirely
|
||||
if (!aAttribute || aAttribute->IsEmpty()) {
|
||||
NS_NAMED_LITERAL_STRING(styleAttr, "style");
|
||||
NS_NAMED_LITERAL_STRING(classAttr, "class");
|
||||
|
||||
bool hasStyleAttr = aNode.HasAttr(kNameSpaceID_None, nsGkAtoms::style);
|
||||
bool hasClassAttr = aNode.HasAttr(kNameSpaceID_None, nsGkAtoms::_class);
|
||||
if (aProperty && (hasStyleAttr || hasClassAttr)) {
|
||||
|
@ -741,14 +738,14 @@ HTMLEditor::RemoveStyleInside(nsIContent& aNode,
|
|||
// just remove the element... We need to create above the element
|
||||
// a span that will carry those styles or class, then we can delete
|
||||
// the node.
|
||||
nsCOMPtr<Element> spanNode =
|
||||
RefPtr<Element> spanNode =
|
||||
InsertContainerAbove(&aNode, nsGkAtoms::span);
|
||||
NS_ENSURE_STATE(spanNode);
|
||||
nsresult rv =
|
||||
CloneAttribute(styleAttr, spanNode->AsDOMNode(), aNode.AsDOMNode());
|
||||
CloneAttribute(nsGkAtoms::style, spanNode, aNode.AsElement());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv =
|
||||
CloneAttribute(classAttr, spanNode->AsDOMNode(), aNode.AsDOMNode());
|
||||
CloneAttribute(nsGkAtoms::_class, spanNode, aNode.AsElement());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
nsresult rv = RemoveContainer(&aNode);
|
||||
|
|
|
@ -1425,9 +1425,9 @@ TextEditRules::CreateMozBR(nsIDOMNode* inParent,
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// give it special moz attr
|
||||
nsCOMPtr<nsIDOMElement> brElem = do_QueryInterface(brNode);
|
||||
nsCOMPtr<Element> brElem = do_QueryInterface(brNode);
|
||||
if (brElem) {
|
||||
rv = mTextEditor->SetAttribute(brElem, NS_LITERAL_STRING("type"),
|
||||
rv = mTextEditor->SetAttribute(brElem, nsGkAtoms::type,
|
||||
NS_LITERAL_STRING("_moz"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
|
|
@ -309,9 +309,9 @@ TextEditor::UpdateMetaCharset(nsIDOMDocument* aDocument,
|
|||
}
|
||||
|
||||
// set attribute to <original prefix> charset=text/html
|
||||
nsCOMPtr<nsIDOMElement> metaElement = do_QueryInterface(metaNode);
|
||||
RefPtr<Element> metaElement = metaNode->AsElement();
|
||||
MOZ_ASSERT(metaElement);
|
||||
rv = EditorBase::SetAttribute(metaElement, NS_LITERAL_STRING("content"),
|
||||
rv = EditorBase::SetAttribute(metaElement, nsGkAtoms::content,
|
||||
Substring(originalStart, start) +
|
||||
charsetEquals +
|
||||
NS_ConvertASCIItoUTF16(aCharacterSet));
|
||||
|
@ -1618,8 +1618,8 @@ TextEditor::GetDOMEventTarget()
|
|||
|
||||
|
||||
nsresult
|
||||
TextEditor::SetAttributeOrEquivalent(nsIDOMElement* aElement,
|
||||
const nsAString& aAttribute,
|
||||
TextEditor::SetAttributeOrEquivalent(Element* aElement,
|
||||
nsIAtom* aAttribute,
|
||||
const nsAString& aValue,
|
||||
bool aSuppressTransaction)
|
||||
{
|
||||
|
@ -1627,8 +1627,8 @@ TextEditor::SetAttributeOrEquivalent(nsIDOMElement* aElement,
|
|||
}
|
||||
|
||||
nsresult
|
||||
TextEditor::RemoveAttributeOrEquivalent(nsIDOMElement* aElement,
|
||||
const nsAString& aAttribute,
|
||||
TextEditor::RemoveAttributeOrEquivalent(Element* aElement,
|
||||
nsIAtom* aAttribute,
|
||||
bool aSuppressTransaction)
|
||||
{
|
||||
return EditorBase::RemoveAttribute(aElement, aAttribute);
|
||||
|
|
|
@ -63,14 +63,17 @@ public:
|
|||
// nsIEditorMailSupport overrides
|
||||
NS_DECL_NSIEDITORMAILSUPPORT
|
||||
|
||||
// Overrides of EditorBase interface methods
|
||||
NS_IMETHOD SetAttributeOrEquivalent(nsIDOMElement* aElement,
|
||||
const nsAString& aAttribute,
|
||||
const nsAString& aValue,
|
||||
bool aSuppressTransaction) override;
|
||||
NS_IMETHOD RemoveAttributeOrEquivalent(nsIDOMElement* aElement,
|
||||
const nsAString& aAttribute,
|
||||
bool aSuppressTransaction) override;
|
||||
// Overrides of EditorBase
|
||||
virtual nsresult RemoveAttributeOrEquivalent(
|
||||
Element* aElement,
|
||||
nsIAtom* aAttribute,
|
||||
bool aSuppressTransaction) override;
|
||||
virtual nsresult SetAttributeOrEquivalent(Element* aElement,
|
||||
nsIAtom* aAttribute,
|
||||
const nsAString& aValue,
|
||||
bool aSuppressTransaction) override;
|
||||
using EditorBase::RemoveAttributeOrEquivalent;
|
||||
using EditorBase::SetAttributeOrEquivalent;
|
||||
|
||||
NS_IMETHOD Init(nsIDOMDocument* aDoc, nsIContent* aRoot,
|
||||
nsISelectionController* aSelCon, uint32_t aFlags,
|
||||
|
|
|
@ -155,7 +155,7 @@ nsContentDLF::CreateInstance(const char* aCommand,
|
|||
// type of the data. If it's known, use it; otherwise use
|
||||
// text/plain.
|
||||
nsAutoCString type;
|
||||
viewSourceChannel->GetOriginalContentType(type);
|
||||
mozilla::Unused << viewSourceChannel->GetOriginalContentType(type);
|
||||
bool knownType =
|
||||
(!type.EqualsLiteral(VIEWSOURCE_CONTENT_TYPE) &&
|
||||
IsTypeInList(type, gHTMLTypes)) ||
|
||||
|
|
|
@ -7353,12 +7353,9 @@ bool nsDisplayMask::ShouldPaintOnMaskLayer(LayerManager* aManager)
|
|||
nsSVGUtils::MaskUsage maskUsage;
|
||||
nsSVGUtils::DetermineMaskUsage(mFrame, mHandleOpacity, maskUsage);
|
||||
|
||||
if (!maskUsage.shouldGenerateMaskLayer && !maskUsage.shouldApplyClipPath &&
|
||||
!maskUsage.shouldGenerateClipMaskLayer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (maskUsage.opacity != 1.0 || maskUsage.shouldApplyBasicShape) {
|
||||
// XXX Bug 1323912. nsSVGIntegrationUtils::PaintMask can not handle opacity
|
||||
// correctly. Turn it off before bug fixed.
|
||||
if (maskUsage.opacity != 1.0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<title>Paint clip-path onto mask layer</title>
|
||||
<style type="text/css">
|
||||
#inner {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
box-sizing: border-box;
|
||||
background: blue;
|
||||
/* make clip-path pained on mask layer */
|
||||
border: 1px solid transparent;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
#outer {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
clip-path: inset(0px 100px 100px 0px);
|
||||
/* make it fixed so that inner div has different AGR with outter div */
|
||||
position: fixed;
|
||||
}
|
||||
</style>
|
||||
<div id="outer">
|
||||
<div id="inner"></div>
|
||||
</div>
|
||||
|
||||
</html>
|
|
@ -464,3 +464,4 @@ default-preferences
|
|||
|
||||
== paint-on-maskLayer-1a.html paint-on-maskLayer-1-ref.html
|
||||
== paint-on-maskLayer-1b.html paint-on-maskLayer-1-ref.html
|
||||
== paint-on-maskLayer-1c.html paint-on-maskLayer-1-ref.html
|
||||
|
|
|
@ -744,9 +744,6 @@ nsSVGIntegrationUtils::PaintMask(const PaintFramesParams& aParams)
|
|||
nsSVGUtils::MaskUsage maskUsage;
|
||||
nsSVGUtils::DetermineMaskUsage(aParams.frame, aParams.handleOpacity,
|
||||
maskUsage);
|
||||
MOZ_ASSERT(maskUsage.shouldGenerateMaskLayer ||
|
||||
maskUsage.shouldApplyClipPath ||
|
||||
maskUsage.shouldGenerateClipMaskLayer);
|
||||
|
||||
nsIFrame* frame = aParams.frame;
|
||||
if (!ValidateSVGFrame(frame)) {
|
||||
|
@ -781,23 +778,52 @@ nsSVGIntegrationUtils::PaintMask(const PaintFramesParams& aParams)
|
|||
SurfaceFormat::A8);
|
||||
}
|
||||
|
||||
if (maskUsage.shouldApplyBasicShape) {
|
||||
matSR.SetContext(&ctx);
|
||||
|
||||
SetupContextMatrix(firstFrame, aParams, offsetToBoundingBox,
|
||||
offsetToUserSpace);
|
||||
|
||||
nsCSSClipPathInstance::ApplyBasicShapeClip(ctx, frame);
|
||||
if (!maskUsage.shouldGenerateMaskLayer) {
|
||||
// Only have basic-shape clip-path effect. Fill clipped region by
|
||||
// opaque white.
|
||||
ctx.SetColor(Color(0.0, 0.0, 0.0, 1.0));
|
||||
ctx.Fill();
|
||||
ctx.PopClip();
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Paint mask onto ctx.
|
||||
if (maskUsage.shouldGenerateMaskLayer) {
|
||||
matSR.Restore();
|
||||
matSR.SetContext(&ctx);
|
||||
|
||||
SetupContextMatrix(frame, aParams, offsetToBoundingBox,
|
||||
offsetToUserSpace);
|
||||
nsTArray<nsSVGMaskFrame *> maskFrames = effectProperties.GetMaskFrames();
|
||||
bool opacityApplied = !HasNonSVGMask(maskFrames);
|
||||
result = PaintMaskSurface(aParams, maskTarget,
|
||||
opacityApplied ? maskUsage.opacity : 1.0,
|
||||
// XXX Bug 1323912.
|
||||
MOZ_ASSERT(maskUsage.opacity == 1.0,
|
||||
"nsSVGIntegrationUtils::PaintMask can not handle opacity now.");
|
||||
result = PaintMaskSurface(aParams, maskTarget, 1.0,
|
||||
firstFrame->StyleContext(), maskFrames,
|
||||
ctx.CurrentMatrix(), offsetToUserSpace);
|
||||
if (result != DrawResult::SUCCESS) {
|
||||
if (maskUsage.shouldApplyBasicShape) {
|
||||
ctx.PopClip();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (maskUsage.shouldApplyBasicShape) {
|
||||
ctx.PopClip();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Paint clip-path onto ctx.
|
||||
if (maskUsage.shouldGenerateClipMaskLayer || maskUsage.shouldApplyClipPath) {
|
||||
matSR.Restore();
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#include <media/stagefright/foundation/hexdump.h>
|
||||
#include <media/stagefright/MetaData.h>
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
|
||||
namespace stagefright {
|
||||
|
||||
MetaData::MetaData() {
|
||||
|
@ -192,7 +194,10 @@ bool MetaData::setData(
|
|||
ssize_t i = mItems.indexOfKey(key);
|
||||
if (i < 0) {
|
||||
typed_data item;
|
||||
// TODO: "i" will be negative value when OOM,
|
||||
// we should consider handling this case instead of asserting.
|
||||
i = mItems.add(key, item);
|
||||
MOZ_RELEASE_ASSERT(i >= 0, "Item cannot be added due to OOM.");
|
||||
|
||||
overwrote_existing = false;
|
||||
}
|
||||
|
|
|
@ -8,10 +8,14 @@ package org.mozilla.gecko.activitystream;
|
|||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.keepsafe.switchboard.SwitchBoard;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.AppConstants;
|
||||
import org.mozilla.gecko.Experiments;
|
||||
import org.mozilla.gecko.GeckoSharedPrefs;
|
||||
|
@ -20,6 +24,7 @@ import org.mozilla.gecko.util.StringUtils;
|
|||
import org.mozilla.gecko.util.publicsuffix.PublicSuffix;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class ActivityStream {
|
||||
|
|
|
@ -0,0 +1,170 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
* 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/. */
|
||||
|
||||
package org.mozilla.gecko.activitystream;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.db.BrowserContract;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Telemetry constants and an 'extras' builder specific to Activity Stream.
|
||||
*/
|
||||
public class ActivityStreamTelemetry {
|
||||
public static class Contract {
|
||||
// Keys
|
||||
public final static String FX_ACCOUNT_PRESENT = "fx_account_present";
|
||||
public final static String ITEM = "item";
|
||||
public final static String SOURCE_TYPE = "source_type";
|
||||
public final static String SOURCE_SUBTYPE = "source_subtype";
|
||||
public final static String ACTION_POSITION = "action_position";
|
||||
public final static String COUNT = "count";
|
||||
|
||||
// Values
|
||||
public final static String TYPE_TOPSITES = "topsites";
|
||||
public final static String TYPE_HIGHLIGHTS = "highlights";
|
||||
public final static String SUBTYPE_PINNED = "pinned";
|
||||
public final static String SUBTYPE_SUGGESTED = "suggested";
|
||||
public final static String SUBTYPE_TOP = "top";
|
||||
public final static String SUBTYPE_VISITED = "visited";
|
||||
public final static String SUBTYPE_BOOKMARKED = "bookmarked";
|
||||
public final static String ITEM_SHARE = "share";
|
||||
public final static String ITEM_ADD_BOOKMARK = "add_bookmark";
|
||||
public final static String ITEM_REMOVE_BOOKMARK = "remove_bookmark";
|
||||
public final static String ITEM_PIN = "pin";
|
||||
public final static String ITEM_UNPIN = "unpin";
|
||||
public final static String ITEM_COPY = "copy";
|
||||
public final static String ITEM_ADD_TO_HOMESCREEN = "homescreen";
|
||||
public final static String ITEM_NEW_TAB = "newtab";
|
||||
public final static String ITEM_DISMISS = "dismiss";
|
||||
public final static String ITEM_DELETE_HISTORY = "delete";
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper class used for composing an 'extras' field. It encapsulates a holder of "global"
|
||||
* key/value pairs which will be present in every 'extras' constructed by this class, and a
|
||||
* static builder which is aware of Activity Stream telemetry needs.
|
||||
*/
|
||||
public final static class Extras {
|
||||
private static final HashMap<String, Object> globals = new HashMap<>();
|
||||
|
||||
public static void setGlobal(String key, Object value) {
|
||||
globals.put(key, value);
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows composing a JSON extras blob, which is then "built" into a string representation.
|
||||
*/
|
||||
public final static class Builder {
|
||||
private final JSONObject data;
|
||||
|
||||
private Builder() {
|
||||
data = new JSONObject(globals);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
|
||||
* Integer, Long, Double, {@link JSONObject#NULL}, or {@code null}. May not be
|
||||
* {@link Double#isNaN() NaNs} or {@link Double#isInfinite()
|
||||
* infinities}.
|
||||
* @return this object.
|
||||
*/
|
||||
public Builder set(@NonNull String key, Object value) {
|
||||
try {
|
||||
data.put(key, value);
|
||||
} catch (JSONException e) {
|
||||
throw new IllegalArgumentException("Key can't be null");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets extras values describing a context menu interaction based on the menu item ID.
|
||||
*
|
||||
* @param itemId ID of a menu item, which is transformed into a corresponding item
|
||||
* key/value pair and passed off to {@link this#set(String, Object)}.
|
||||
* @return this object.
|
||||
*/
|
||||
public Builder fromMenuItemId(int itemId) {
|
||||
switch (itemId) {
|
||||
case R.id.share:
|
||||
this.set(Contract.ITEM, Contract.ITEM_SHARE);
|
||||
break;
|
||||
|
||||
case R.id.copy_url:
|
||||
this.set(Contract.ITEM, Contract.ITEM_COPY);
|
||||
break;
|
||||
|
||||
case R.id.add_homescreen:
|
||||
this.set(Contract.ITEM, Contract.ITEM_ADD_TO_HOMESCREEN);
|
||||
break;
|
||||
|
||||
// Our current privacy guidelines do not allow us to write to disk
|
||||
// Private Browsing-only telemetry that could indicate that PB mode is used.
|
||||
// See Bug 1325323 for context.
|
||||
case R.id.open_new_private_tab:
|
||||
case R.id.open_new_tab:
|
||||
this.set(Contract.ITEM, Contract.ITEM_NEW_TAB);
|
||||
break;
|
||||
|
||||
case R.id.dismiss:
|
||||
this.set(Contract.ITEM, Contract.ITEM_DISMISS);
|
||||
break;
|
||||
|
||||
case R.id.delete:
|
||||
this.set(Contract.ITEM, Contract.ITEM_DELETE_HISTORY);
|
||||
break;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder forHighlightSource(Utils.HighlightSource source) {
|
||||
switch (source) {
|
||||
case VISITED:
|
||||
this.set(Contract.SOURCE_SUBTYPE, Contract.SUBTYPE_VISITED);
|
||||
break;
|
||||
case BOOKMARKED:
|
||||
this.set(Contract.SOURCE_SUBTYPE, Contract.SUBTYPE_BOOKMARKED);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unknown highlight source: " + source);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder forTopSiteType(int type) {
|
||||
switch (type) {
|
||||
case BrowserContract.TopSites.TYPE_PINNED:
|
||||
this.set(Contract.SOURCE_SUBTYPE, Contract.SUBTYPE_PINNED);
|
||||
break;
|
||||
case BrowserContract.TopSites.TYPE_SUGGESTED:
|
||||
this.set(Contract.SOURCE_SUBTYPE, Contract.SUBTYPE_SUGGESTED);
|
||||
break;
|
||||
case BrowserContract.TopSites.TYPE_TOP:
|
||||
this.set(Contract.SOURCE_SUBTYPE, Contract.SUBTYPE_TOP);
|
||||
break;
|
||||
// While we also have a "blank" type, it is not used by Activity Stream.
|
||||
default:
|
||||
throw new IllegalStateException("Unknown top site type: " + type);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public String build() {
|
||||
return data.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
* 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/. */
|
||||
|
||||
package org.mozilla.gecko.activitystream;
|
||||
|
||||
import android.database.Cursor;
|
||||
|
||||
import org.mozilla.gecko.db.BrowserContract;
|
||||
|
||||
/**
|
||||
* Various util methods and constants that are shared by different parts of Activity Stream.
|
||||
*/
|
||||
public class Utils {
|
||||
public enum HighlightSource {
|
||||
VISITED,
|
||||
BOOKMARKED
|
||||
}
|
||||
|
||||
public static HighlightSource highlightSource(final Cursor cursor) {
|
||||
if (-1 != cursor.getLong(cursor.getColumnIndexOrThrow(BrowserContract.Combined.BOOKMARK_ID))) {
|
||||
return HighlightSource.BOOKMARKED;
|
||||
}
|
||||
|
||||
if (-1 != cursor.getLong(cursor.getColumnIndexOrThrow(BrowserContract.Combined.HISTORY_ID))) {
|
||||
return HighlightSource.VISITED;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Unknown highlight source.");
|
||||
}
|
||||
}
|
|
@ -606,6 +606,7 @@ public class BrowserContract {
|
|||
public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "highlights");
|
||||
|
||||
public static final String DATE = "date";
|
||||
public static final String METADATA = "metadata";
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
|
|
|
@ -1192,11 +1192,16 @@ public class BrowserProvider extends SharedBrowserDatabaseProvider {
|
|||
DBUtils.qualifyColumn(Bookmarks.TABLE_NAME, Bookmarks.POSITION) + " AS " + Bookmarks.POSITION + ", " +
|
||||
DBUtils.qualifyColumn(Bookmarks.TABLE_NAME, Bookmarks.URL) + ", " +
|
||||
DBUtils.qualifyColumn(Bookmarks.TABLE_NAME, Bookmarks.TITLE) + ", " +
|
||||
DBUtils.qualifyColumn(Bookmarks.TABLE_NAME, Bookmarks.DATE_CREATED) + " AS " + Highlights.DATE + " " +
|
||||
DBUtils.qualifyColumn(Bookmarks.TABLE_NAME, Bookmarks.DATE_CREATED) + " AS " + Highlights.DATE + ", " +
|
||||
DBUtils.qualifyColumn(PageMetadata.TABLE_NAME, PageMetadata.JSON) + " AS " + Highlights.METADATA + " " +
|
||||
"FROM " + Bookmarks.TABLE_NAME + " " +
|
||||
"LEFT JOIN " + History.TABLE_NAME + " ON " +
|
||||
DBUtils.qualifyColumn(Bookmarks.TABLE_NAME, Bookmarks.URL) + " = " +
|
||||
DBUtils.qualifyColumn(History.TABLE_NAME, History.URL) + " " +
|
||||
// 1:1 relationship (Metadata is added via INSERT OR REPLACE)
|
||||
"LEFT JOIN " + PageMetadata.TABLE_NAME + " ON " +
|
||||
DBUtils.qualifyColumn(History.TABLE_NAME, History.GUID) + " = " +
|
||||
DBUtils.qualifyColumn(PageMetadata.TABLE_NAME, PageMetadata.HISTORY_GUID) + " " +
|
||||
"WHERE " + DBUtils.qualifyColumn(Bookmarks.TABLE_NAME, Bookmarks.DATE_CREATED) + " > " + threeDaysAgo + " " +
|
||||
"AND (" + DBUtils.qualifyColumn(History.TABLE_NAME, History.VISITS) + " <= 3 " +
|
||||
"OR " + DBUtils.qualifyColumn(History.TABLE_NAME, History.VISITS) + " IS NULL) " +
|
||||
|
@ -1218,11 +1223,16 @@ public class BrowserProvider extends SharedBrowserDatabaseProvider {
|
|||
DBUtils.qualifyColumn(Bookmarks.TABLE_NAME, Bookmarks.POSITION) + " AS " + Bookmarks.POSITION + ", " +
|
||||
DBUtils.qualifyColumn(History.TABLE_NAME, History.URL) + ", " +
|
||||
DBUtils.qualifyColumn(History.TABLE_NAME, History.TITLE) + ", " +
|
||||
DBUtils.qualifyColumn(History.TABLE_NAME, History.DATE_LAST_VISITED) + " AS " + Highlights.DATE + " " +
|
||||
DBUtils.qualifyColumn(History.TABLE_NAME, History.DATE_LAST_VISITED) + " AS " + Highlights.DATE + ", " +
|
||||
DBUtils.qualifyColumn(PageMetadata.TABLE_NAME, PageMetadata.JSON) + " AS " + Highlights.METADATA + " " +
|
||||
"FROM " + History.TABLE_NAME + " " +
|
||||
"LEFT JOIN " + Bookmarks.TABLE_NAME + " ON " +
|
||||
DBUtils.qualifyColumn(History.TABLE_NAME, History.URL) + " = " +
|
||||
DBUtils.qualifyColumn(Bookmarks.TABLE_NAME, Bookmarks.URL) + " " +
|
||||
// 1:1 relationship (Metadata is added via INSERT OR REPLACE)
|
||||
"LEFT JOIN " + PageMetadata.TABLE_NAME + " ON " +
|
||||
DBUtils.qualifyColumn(History.TABLE_NAME, History.GUID) + " = " +
|
||||
DBUtils.qualifyColumn(PageMetadata.TABLE_NAME, PageMetadata.HISTORY_GUID) + " " +
|
||||
"WHERE " + DBUtils.qualifyColumn(History.TABLE_NAME, History.DATE_LAST_VISITED) + " < " + last30Minutes + " " +
|
||||
"AND " + DBUtils.qualifyColumn(History.TABLE_NAME, History.VISITS) + " <= 3 " +
|
||||
"AND " + DBUtils.qualifyColumn(History.TABLE_NAME, History.TITLE) + " NOT NULL AND " + DBUtils.qualifyColumn(History.TABLE_NAME, History.TITLE) + " != '' " +
|
||||
|
|
|
@ -11,20 +11,17 @@ import android.os.Bundle;
|
|||
import android.support.v4.app.LoaderManager;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.support.v4.graphics.ColorUtils;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.activitystream.ActivityStreamTelemetry;
|
||||
import org.mozilla.gecko.db.BrowserDB;
|
||||
import org.mozilla.gecko.fxa.FirefoxAccounts;
|
||||
import org.mozilla.gecko.home.HomePager;
|
||||
import org.mozilla.gecko.home.activitystream.topsites.TopSitesPagerAdapter;
|
||||
import org.mozilla.gecko.util.ContextUtils;
|
||||
import org.mozilla.gecko.widget.RecyclerViewClickSupport;
|
||||
|
||||
public class ActivityStream extends FrameLayout {
|
||||
|
@ -62,6 +59,11 @@ public class ActivityStream extends FrameLayout {
|
|||
desiredTileWidth = resources.getDimensionPixelSize(R.dimen.activity_stream_desired_tile_width);
|
||||
desiredTilesHeight = resources.getDimensionPixelSize(R.dimen.activity_stream_desired_tile_height);
|
||||
tileMargin = resources.getDimensionPixelSize(R.dimen.activity_stream_base_margin);
|
||||
|
||||
ActivityStreamTelemetry.Extras.setGlobal(
|
||||
ActivityStreamTelemetry.Contract.FX_ACCOUNT_PRESENT,
|
||||
FirefoxAccounts.firefoxAccountsExist(context)
|
||||
);
|
||||
}
|
||||
|
||||
void setOnUrlOpenListeners(HomePager.OnUrlOpenListener onUrlOpenListener, HomePager.OnUrlOpenInBackgroundListener onUrlOpenInBackgroundListener) {
|
||||
|
|
|
@ -14,6 +14,7 @@ import android.support.v4.view.ViewPager;
|
|||
import android.support.v7.widget.RecyclerView;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewStub;
|
||||
|
@ -21,9 +22,15 @@ import android.widget.Button;
|
|||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.GeckoSharedPrefs;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.Telemetry;
|
||||
import org.mozilla.gecko.TelemetryContract;
|
||||
import org.mozilla.gecko.activitystream.Utils;
|
||||
import org.mozilla.gecko.activitystream.ActivityStream.LabelCallback;
|
||||
import org.mozilla.gecko.activitystream.ActivityStreamTelemetry;
|
||||
import org.mozilla.gecko.db.BrowserContract;
|
||||
import org.mozilla.gecko.home.HomePager;
|
||||
import org.mozilla.gecko.home.activitystream.menu.ActivityStreamContextMenu;
|
||||
|
@ -42,6 +49,8 @@ import java.util.concurrent.Future;
|
|||
import static org.mozilla.gecko.activitystream.ActivityStream.extractLabel;
|
||||
|
||||
public abstract class StreamItem extends RecyclerView.ViewHolder {
|
||||
private static final String LOGTAG = "GeckoStreamItem";
|
||||
|
||||
public StreamItem(View itemView) {
|
||||
super(itemView);
|
||||
}
|
||||
|
@ -135,17 +144,15 @@ public abstract class StreamItem extends RecyclerView.ViewHolder {
|
|||
public static class HighlightItem extends StreamItem implements IconCallback {
|
||||
public static final int LAYOUT_ID = R.layout.activity_stream_card_history_item;
|
||||
|
||||
enum HighlightSource {
|
||||
VISITED,
|
||||
BOOKMARKED
|
||||
}
|
||||
|
||||
String title;
|
||||
String url;
|
||||
JSONObject metadata;
|
||||
|
||||
@Nullable Boolean isPinned;
|
||||
@Nullable Boolean isBookmarked;
|
||||
|
||||
Utils.HighlightSource source;
|
||||
|
||||
final FaviconView vIconView;
|
||||
final TextView vLabel;
|
||||
final TextView vTimeSince;
|
||||
|
@ -180,12 +187,23 @@ public abstract class StreamItem extends RecyclerView.ViewHolder {
|
|||
menuButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
ActivityStreamTelemetry.Extras.Builder extras = ActivityStreamTelemetry.Extras.builder()
|
||||
.set(ActivityStreamTelemetry.Contract.SOURCE_TYPE, ActivityStreamTelemetry.Contract.TYPE_HIGHLIGHTS)
|
||||
.forHighlightSource(source);
|
||||
|
||||
ActivityStreamContextMenu.show(v.getContext(),
|
||||
menuButton,
|
||||
extras,
|
||||
ActivityStreamContextMenu.MenuMode.HIGHLIGHT,
|
||||
title, url, isBookmarked, isPinned,
|
||||
onUrlOpenListener, onUrlOpenInBackgroundListener,
|
||||
vIconView.getWidth(), vIconView.getHeight());
|
||||
|
||||
Telemetry.sendUIEvent(
|
||||
TelemetryContract.Event.SHOW,
|
||||
TelemetryContract.Method.CONTEXT_MENU,
|
||||
extras.build()
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -193,12 +211,21 @@ public abstract class StreamItem extends RecyclerView.ViewHolder {
|
|||
}
|
||||
|
||||
public void bind(Cursor cursor, int tilesWidth, int tilesHeight) {
|
||||
|
||||
final long time = cursor.getLong(cursor.getColumnIndexOrThrow(BrowserContract.Highlights.DATE));
|
||||
final String ago = DateUtils.getRelativeTimeSpanString(time, System.currentTimeMillis(), DateUtils.MINUTE_IN_MILLIS, 0).toString();
|
||||
|
||||
title = cursor.getString(cursor.getColumnIndexOrThrow(BrowserContract.History.TITLE));
|
||||
url = cursor.getString(cursor.getColumnIndexOrThrow(BrowserContract.Combined.URL));
|
||||
source = Utils.highlightSource(cursor);
|
||||
|
||||
try {
|
||||
final String rawMetadata = cursor.getString(cursor.getColumnIndexOrThrow(BrowserContract.Highlights.METADATA));
|
||||
if (rawMetadata != null) {
|
||||
metadata = new JSONObject(rawMetadata);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
Log.w(LOGTAG, "JSONException while parsing page metadata", e);
|
||||
}
|
||||
|
||||
vLabel.setText(title);
|
||||
vTimeSince.setText(ago);
|
||||
|
@ -208,11 +235,9 @@ public abstract class StreamItem extends RecyclerView.ViewHolder {
|
|||
layoutParams.height = tilesHeight;
|
||||
vIconView.setLayoutParams(layoutParams);
|
||||
|
||||
final HighlightSource source = highlightSource(cursor);
|
||||
|
||||
updateStateForSource(source, cursor);
|
||||
updateStateForSource(source);
|
||||
updateUiForSource(source);
|
||||
updatePage(url);
|
||||
updatePage(metadata, url);
|
||||
|
||||
if (ongoingIconLoad != null) {
|
||||
ongoingIconLoad.cancel(true);
|
||||
|
@ -225,7 +250,7 @@ public abstract class StreamItem extends RecyclerView.ViewHolder {
|
|||
.execute(this);
|
||||
}
|
||||
|
||||
private void updateStateForSource(HighlightSource source, Cursor cursor) {
|
||||
private void updateStateForSource(Utils.HighlightSource source) {
|
||||
// We can only be certain of bookmark state if an item is a bookmark item.
|
||||
// Otherwise, due to the underlying highlights query, we have to look up states when
|
||||
// menus are displayed.
|
||||
|
@ -243,7 +268,7 @@ public abstract class StreamItem extends RecyclerView.ViewHolder {
|
|||
}
|
||||
}
|
||||
|
||||
private void updateUiForSource(HighlightSource source) {
|
||||
private void updateUiForSource(Utils.HighlightSource source) {
|
||||
switch (source) {
|
||||
case BOOKMARKED:
|
||||
vSourceView.setText(R.string.activity_stream_highlight_label_bookmarked);
|
||||
|
@ -260,12 +285,22 @@ public abstract class StreamItem extends RecyclerView.ViewHolder {
|
|||
vSourceIconView.setImageResource(0);
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO Why?
|
||||
// vSourceView.setText(vSourceView.getText());
|
||||
}
|
||||
|
||||
private void updatePage(final String url) {
|
||||
private void updatePage(final JSONObject metadata, final String url) {
|
||||
// First try to set the provider name from the page's metadata.
|
||||
|
||||
try {
|
||||
if (metadata != null && metadata.has("provider")) {
|
||||
vPageView.setText(metadata.getString("provider"));
|
||||
return;
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
// Broken JSON? Continue with fallback.
|
||||
}
|
||||
|
||||
// If there's no provider name available then let's try to extract one from the URL.
|
||||
|
||||
extractLabel(itemView.getContext(), url, false, new LabelCallback() {
|
||||
@Override
|
||||
public void onLabelExtracted(String label) {
|
||||
|
@ -279,16 +314,4 @@ public abstract class StreamItem extends RecyclerView.ViewHolder {
|
|||
vIconView.updateImage(response);
|
||||
}
|
||||
}
|
||||
|
||||
private static HighlightItem.HighlightSource highlightSource(final Cursor cursor) {
|
||||
if (-1 != cursor.getLong(cursor.getColumnIndexOrThrow(BrowserContract.Combined.BOOKMARK_ID))) {
|
||||
return HighlightItem.HighlightSource.BOOKMARKED;
|
||||
}
|
||||
|
||||
if (-1 != cursor.getLong(cursor.getColumnIndexOrThrow(BrowserContract.Combined.HISTORY_ID))) {
|
||||
return HighlightItem.HighlightSource.VISITED;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Unknown highlight source.");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@ import android.view.ViewGroup;
|
|||
|
||||
import org.mozilla.gecko.Telemetry;
|
||||
import org.mozilla.gecko.TelemetryContract;
|
||||
import org.mozilla.gecko.activitystream.ActivityStreamTelemetry;
|
||||
import org.mozilla.gecko.activitystream.Utils;
|
||||
import org.mozilla.gecko.db.BrowserContract;
|
||||
import org.mozilla.gecko.home.HomePager;
|
||||
import org.mozilla.gecko.home.activitystream.StreamItem.HighlightItem;
|
||||
|
@ -113,15 +115,25 @@ public class StreamRecyclerAdapter extends RecyclerView.Adapter<StreamItem> impl
|
|||
return;
|
||||
}
|
||||
|
||||
highlightsCursor.moveToPosition(
|
||||
translatePositionToCursor(position));
|
||||
int actualPosition = translatePositionToCursor(position);
|
||||
highlightsCursor.moveToPosition(actualPosition);
|
||||
|
||||
final String url = highlightsCursor.getString(
|
||||
highlightsCursor.getColumnIndexOrThrow(BrowserContract.Combined.URL));
|
||||
|
||||
onUrlOpenListener.onUrlOpen(url, EnumSet.of(HomePager.OnUrlOpenListener.Flags.ALLOW_SWITCH_TO_TAB));
|
||||
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.LIST_ITEM, "as_highlights");
|
||||
ActivityStreamTelemetry.Extras.Builder extras = ActivityStreamTelemetry.Extras.builder()
|
||||
.forHighlightSource(Utils.highlightSource(highlightsCursor))
|
||||
.set(ActivityStreamTelemetry.Contract.SOURCE_TYPE, ActivityStreamTelemetry.Contract.TYPE_HIGHLIGHTS)
|
||||
.set(ActivityStreamTelemetry.Contract.ACTION_POSITION, actualPosition)
|
||||
.set(ActivityStreamTelemetry.Contract.COUNT, highlightsCursor.getCount());
|
||||
|
||||
Telemetry.sendUIEvent(
|
||||
TelemetryContract.Event.LOAD_URL,
|
||||
TelemetryContract.Method.LIST_ITEM,
|
||||
extras.build()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.mozilla.gecko.IntentHelper;
|
|||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.Telemetry;
|
||||
import org.mozilla.gecko.TelemetryContract;
|
||||
import org.mozilla.gecko.activitystream.ActivityStreamTelemetry;
|
||||
import org.mozilla.gecko.annotation.RobocopTarget;
|
||||
import org.mozilla.gecko.db.BrowserDB;
|
||||
import org.mozilla.gecko.home.HomePager;
|
||||
|
@ -38,18 +39,20 @@ public abstract class ActivityStreamContextMenu
|
|||
TOPSITE
|
||||
}
|
||||
|
||||
final Context context;
|
||||
private final Context context;
|
||||
|
||||
final String title;
|
||||
final String url;
|
||||
private final String title;
|
||||
private final String url;
|
||||
|
||||
private final ActivityStreamTelemetry.Extras.Builder telemetryExtraBuilder;
|
||||
|
||||
// We might not know bookmarked/pinned states, so we allow for null values.
|
||||
// If we aren't told what these are in the constructor, we look them up in postInit.
|
||||
private @Nullable Boolean isBookmarked;
|
||||
private @Nullable Boolean isPinned;
|
||||
|
||||
final HomePager.OnUrlOpenListener onUrlOpenListener;
|
||||
final HomePager.OnUrlOpenInBackgroundListener onUrlOpenInBackgroundListener;
|
||||
|
||||
private final HomePager.OnUrlOpenListener onUrlOpenListener;
|
||||
private final HomePager.OnUrlOpenInBackgroundListener onUrlOpenInBackgroundListener;
|
||||
|
||||
public abstract MenuItem getItemByID(int id);
|
||||
|
||||
|
@ -57,15 +60,17 @@ public abstract class ActivityStreamContextMenu
|
|||
|
||||
public abstract void dismiss();
|
||||
|
||||
final MenuMode mode;
|
||||
private final MenuMode mode;
|
||||
|
||||
/* package-private */ ActivityStreamContextMenu(final Context context,
|
||||
final ActivityStreamTelemetry.Extras.Builder telemetryExtraBuilder,
|
||||
final MenuMode mode,
|
||||
final String title, @NonNull final String url,
|
||||
@Nullable final Boolean isBookmarked, @Nullable final Boolean isPinned,
|
||||
HomePager.OnUrlOpenListener onUrlOpenListener,
|
||||
HomePager.OnUrlOpenInBackgroundListener onUrlOpenInBackgroundListener) {
|
||||
this.context = context;
|
||||
this.telemetryExtraBuilder = telemetryExtraBuilder;
|
||||
|
||||
this.mode = mode;
|
||||
|
||||
|
@ -83,7 +88,7 @@ public abstract class ActivityStreamContextMenu
|
|||
* Your implementation must be ready to return items from getItemByID() before postInit() is
|
||||
* called, i.e. you should probably inflate your menu items before this call.
|
||||
*/
|
||||
protected void postInit() {
|
||||
/* package-local */ void postInit() {
|
||||
final MenuItem bookmarkItem = getItemByID(R.id.bookmark);
|
||||
if (Boolean.TRUE.equals(this.isBookmarked)) {
|
||||
bookmarkItem.setTitle(R.string.bookmark_remove);
|
||||
|
@ -106,19 +111,19 @@ public abstract class ActivityStreamContextMenu
|
|||
// Disable the bookmark item until we know its bookmark state
|
||||
bookmarkItem.setEnabled(false);
|
||||
|
||||
(new UIAsyncTask.WithoutParams<Void>(ThreadUtils.getBackgroundHandler()) {
|
||||
(new UIAsyncTask.WithoutParams<Boolean>(ThreadUtils.getBackgroundHandler()) {
|
||||
@Override
|
||||
protected Void doInBackground() {
|
||||
isBookmarked = BrowserDB.from(context).isBookmark(context.getContentResolver(), url);
|
||||
return null;
|
||||
protected Boolean doInBackground() {
|
||||
return BrowserDB.from(context).isBookmark(context.getContentResolver(), url);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void aVoid) {
|
||||
if (isBookmarked) {
|
||||
protected void onPostExecute(Boolean hasBookmark) {
|
||||
if (hasBookmark) {
|
||||
bookmarkItem.setTitle(R.string.bookmark_remove);
|
||||
}
|
||||
|
||||
isBookmarked = hasBookmark;
|
||||
bookmarkItem.setEnabled(true);
|
||||
}
|
||||
}).execute();
|
||||
|
@ -128,19 +133,19 @@ public abstract class ActivityStreamContextMenu
|
|||
// Disable the pin item until we know its pinned state
|
||||
pinItem.setEnabled(false);
|
||||
|
||||
(new UIAsyncTask.WithoutParams<Void>(ThreadUtils.getBackgroundHandler()) {
|
||||
(new UIAsyncTask.WithoutParams<Boolean>(ThreadUtils.getBackgroundHandler()) {
|
||||
@Override
|
||||
protected Void doInBackground() {
|
||||
isPinned = BrowserDB.from(context).isPinnedForAS(context.getContentResolver(), url);
|
||||
return null;
|
||||
protected Boolean doInBackground() {
|
||||
return BrowserDB.from(context).isPinnedForAS(context.getContentResolver(), url);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void aVoid) {
|
||||
if (isPinned) {
|
||||
protected void onPostExecute(Boolean hasPin) {
|
||||
if (hasPin) {
|
||||
pinItem.setTitle(R.string.contextmenu_top_sites_unpin);
|
||||
}
|
||||
|
||||
isPinned = hasPin;
|
||||
pinItem.setEnabled(true);
|
||||
}
|
||||
}).execute();
|
||||
|
@ -150,30 +155,25 @@ public abstract class ActivityStreamContextMenu
|
|||
final MenuItem deleteHistoryItem = getItemByID(R.id.delete);
|
||||
deleteHistoryItem.setVisible(false);
|
||||
|
||||
(new UIAsyncTask.WithoutParams<Void>(ThreadUtils.getBackgroundHandler()) {
|
||||
boolean hasHistory;
|
||||
|
||||
(new UIAsyncTask.WithoutParams<Boolean>(ThreadUtils.getBackgroundHandler()) {
|
||||
@Override
|
||||
protected Void doInBackground() {
|
||||
protected Boolean doInBackground() {
|
||||
final Cursor cursor = BrowserDB.from(context).getHistoryForURL(context.getContentResolver(), url);
|
||||
// It's tempting to throw here, but crashing because of a (hopefully) inconsequential
|
||||
// oddity is somewhat questionable.
|
||||
if (cursor == null) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
if (cursor != null &&
|
||||
cursor.getCount() == 1) {
|
||||
hasHistory = true;
|
||||
} else {
|
||||
hasHistory = false;
|
||||
}
|
||||
return cursor.getCount() == 1;
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void aVoid) {
|
||||
if (hasHistory) {
|
||||
deleteHistoryItem.setVisible(true);
|
||||
}
|
||||
protected void onPostExecute(Boolean hasHistory) {
|
||||
deleteHistoryItem.setVisible(hasHistory);
|
||||
}
|
||||
}).execute();
|
||||
}
|
||||
|
@ -181,49 +181,76 @@ public abstract class ActivityStreamContextMenu
|
|||
|
||||
@Override
|
||||
public boolean onNavigationItemSelected(MenuItem item) {
|
||||
final int menuItemId = item.getItemId();
|
||||
|
||||
// Sets extra telemetry which doesn't require additional state information.
|
||||
// Pin and bookmark items are handled separately below, since they do require state
|
||||
// information to handle correctly.
|
||||
telemetryExtraBuilder.fromMenuItemId(menuItemId);
|
||||
|
||||
switch (item.getItemId()) {
|
||||
case R.id.share:
|
||||
// NB: Generic menu item action event will be sent at the end of this function.
|
||||
// We have a seemingly duplicate telemetry event here because we want to emit
|
||||
// a concrete event in case it is used by other queries to estimate feature usage.
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.SHARE, TelemetryContract.Method.LIST, "as_contextmenu");
|
||||
|
||||
IntentHelper.openUriExternal(url, "text/plain", "", "", Intent.ACTION_SEND, title, false);
|
||||
break;
|
||||
|
||||
case R.id.bookmark:
|
||||
final TelemetryContract.Event telemetryEvent;
|
||||
final String telemetryExtra;
|
||||
SavedReaderViewHelper rch = SavedReaderViewHelper.getSavedReaderViewHelper(context);
|
||||
final boolean isReaderViewPage = rch.isURLCached(url);
|
||||
|
||||
// While isBookmarked is nullable, behaviour of postInit - disabling 'bookmark' item
|
||||
// until we know value of isBookmarked - guarantees that it will be set when we get here.
|
||||
if (isBookmarked) {
|
||||
telemetryEvent = TelemetryContract.Event.UNSAVE;
|
||||
|
||||
if (isReaderViewPage) {
|
||||
telemetryExtra = "as_bookmark_reader";
|
||||
} else {
|
||||
telemetryExtra = "as_bookmark";
|
||||
}
|
||||
telemetryExtraBuilder.set(ActivityStreamTelemetry.Contract.ITEM, ActivityStreamTelemetry.Contract.ITEM_REMOVE_BOOKMARK);
|
||||
} else {
|
||||
telemetryEvent = TelemetryContract.Event.SAVE;
|
||||
telemetryExtra = "as_bookmark";
|
||||
telemetryExtraBuilder.set(ActivityStreamTelemetry.Contract.ITEM, ActivityStreamTelemetry.Contract.ITEM_ADD_BOOKMARK);
|
||||
}
|
||||
// NB: Generic menu item action event will be sent at the end of this function.
|
||||
// We have a seemingly duplicate telemetry event here because we want to emit
|
||||
// a concrete event in case it is used by other queries to estimate feature usage.
|
||||
Telemetry.sendUIEvent(telemetryEvent, TelemetryContract.Method.CONTEXT_MENU, telemetryExtra);
|
||||
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final BrowserDB db = BrowserDB.from(context);
|
||||
|
||||
final TelemetryContract.Event telemetryEvent;
|
||||
final String telemetryExtra;
|
||||
if (isBookmarked) {
|
||||
db.removeBookmarksWithURL(context.getContentResolver(), url);
|
||||
|
||||
SavedReaderViewHelper rch = SavedReaderViewHelper.getSavedReaderViewHelper(context);
|
||||
final boolean isReaderViewPage = rch.isURLCached(url);
|
||||
|
||||
telemetryEvent = TelemetryContract.Event.UNSAVE;
|
||||
|
||||
if (isReaderViewPage) {
|
||||
telemetryExtra = "as_bookmark_reader";
|
||||
} else {
|
||||
telemetryExtra = "as_bookmark";
|
||||
}
|
||||
} else {
|
||||
// We only store raw URLs in history (and bookmarks), hence we won't ever show about:reader
|
||||
// URLs in AS topsites or highlights. Therefore we don't need to do any special about:reader handling here.
|
||||
db.addBookmark(context.getContentResolver(), title, url);
|
||||
|
||||
telemetryEvent = TelemetryContract.Event.SAVE;
|
||||
telemetryExtra = "as_bookmark";
|
||||
}
|
||||
|
||||
Telemetry.sendUIEvent(telemetryEvent, TelemetryContract.Method.CONTEXT_MENU, telemetryExtra);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case R.id.pin:
|
||||
// While isPinned is nullable, behaviour of postInit - disabling 'pin' item
|
||||
// until we know value of isPinned - guarantees that it will be set when we get here.
|
||||
if (isPinned) {
|
||||
telemetryExtraBuilder.set(ActivityStreamTelemetry.Contract.ITEM, ActivityStreamTelemetry.Contract.ITEM_UNPIN);
|
||||
} else {
|
||||
telemetryExtraBuilder.set(ActivityStreamTelemetry.Contract.ITEM, ActivityStreamTelemetry.Contract.ITEM_PIN);
|
||||
}
|
||||
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -236,6 +263,7 @@ public abstract class ActivityStreamContextMenu
|
|||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case R.id.copy_url:
|
||||
Clipboard.setText(url);
|
||||
|
@ -243,20 +271,14 @@ public abstract class ActivityStreamContextMenu
|
|||
|
||||
case R.id.add_homescreen:
|
||||
GeckoAppShell.createShortcut(title, url);
|
||||
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.ACTION, TelemetryContract.Method.CONTEXT_MENU, "as_add_to_launcher");
|
||||
break;
|
||||
|
||||
case R.id.open_new_tab:
|
||||
onUrlOpenInBackgroundListener.onUrlOpenInBackground(url, EnumSet.noneOf(HomePager.OnUrlOpenInBackgroundListener.Flags.class));
|
||||
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.CONTEXT_MENU, "as_new_tab");
|
||||
break;
|
||||
|
||||
case R.id.open_new_private_tab:
|
||||
onUrlOpenInBackgroundListener.onUrlOpenInBackground(url, EnumSet.of(HomePager.OnUrlOpenInBackgroundListener.Flags.PRIVATE));
|
||||
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.CONTEXT_MENU, "as_private_tab");
|
||||
break;
|
||||
|
||||
case R.id.dismiss:
|
||||
|
@ -285,6 +307,12 @@ public abstract class ActivityStreamContextMenu
|
|||
throw new IllegalArgumentException("Menu item with ID=" + item.getItemId() + " not handled");
|
||||
}
|
||||
|
||||
Telemetry.sendUIEvent(
|
||||
TelemetryContract.Event.ACTION,
|
||||
TelemetryContract.Method.CONTEXT_MENU,
|
||||
telemetryExtraBuilder.build()
|
||||
);
|
||||
|
||||
dismiss();
|
||||
return true;
|
||||
}
|
||||
|
@ -292,7 +320,7 @@ public abstract class ActivityStreamContextMenu
|
|||
|
||||
@RobocopTarget
|
||||
public static ActivityStreamContextMenu show(Context context,
|
||||
View anchor,
|
||||
View anchor, ActivityStreamTelemetry.Extras.Builder telemetryExtraBuilder,
|
||||
final MenuMode menuMode,
|
||||
final String title, @NonNull final String url,
|
||||
@Nullable final Boolean isBookmarked, @Nullable final Boolean isPinned,
|
||||
|
@ -303,14 +331,14 @@ public abstract class ActivityStreamContextMenu
|
|||
|
||||
if (!HardwareUtils.isTablet()) {
|
||||
menu = new BottomSheetContextMenu(context,
|
||||
menuMode,
|
||||
telemetryExtraBuilder, menuMode,
|
||||
title, url, isBookmarked, isPinned,
|
||||
onUrlOpenListener, onUrlOpenInBackgroundListener,
|
||||
tilesWidth, tilesHeight);
|
||||
} else {
|
||||
menu = new PopupContextMenu(context,
|
||||
anchor,
|
||||
menuMode,
|
||||
telemetryExtraBuilder, menuMode,
|
||||
title, url, isBookmarked, isPinned,
|
||||
onUrlOpenListener, onUrlOpenInBackgroundListener);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ package org.mozilla.gecko.home.activitystream.menu;
|
|||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.BottomSheetBehavior;
|
||||
import android.support.design.widget.BottomSheetDialog;
|
||||
import android.support.design.widget.NavigationView;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -18,6 +17,7 @@ import android.widget.TextView;
|
|||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.activitystream.ActivityStream;
|
||||
import org.mozilla.gecko.activitystream.ActivityStreamTelemetry;
|
||||
import org.mozilla.gecko.home.HomePager;
|
||||
import org.mozilla.gecko.icons.IconCallback;
|
||||
import org.mozilla.gecko.icons.IconResponse;
|
||||
|
@ -35,6 +35,7 @@ import static org.mozilla.gecko.activitystream.ActivityStream.extractLabel;
|
|||
private final NavigationView navigationView;
|
||||
|
||||
public BottomSheetContextMenu(final Context context,
|
||||
final ActivityStreamTelemetry.Extras.Builder telemetryExtraBuilder,
|
||||
final MenuMode mode,
|
||||
final String title, @NonNull final String url,
|
||||
@Nullable final Boolean isBookmarked, @Nullable final Boolean isPinned,
|
||||
|
@ -43,6 +44,7 @@ import static org.mozilla.gecko.activitystream.ActivityStream.extractLabel;
|
|||
final int tilesWidth, final int tilesHeight) {
|
||||
|
||||
super(context,
|
||||
telemetryExtraBuilder,
|
||||
mode,
|
||||
title,
|
||||
url,
|
||||
|
|
|
@ -16,6 +16,8 @@ import android.view.View;
|
|||
import android.widget.PopupWindow;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.activitystream.ActivityStream;
|
||||
import org.mozilla.gecko.activitystream.ActivityStreamTelemetry;
|
||||
import org.mozilla.gecko.home.HomePager;
|
||||
|
||||
/* package-private */ class PopupContextMenu
|
||||
|
@ -28,6 +30,7 @@ import org.mozilla.gecko.home.HomePager;
|
|||
|
||||
public PopupContextMenu(final Context context,
|
||||
View anchor,
|
||||
final ActivityStreamTelemetry.Extras.Builder telemetryExtraBuilder,
|
||||
final MenuMode mode,
|
||||
final String title,
|
||||
@NonNull final String url,
|
||||
|
@ -36,6 +39,7 @@ import org.mozilla.gecko.home.HomePager;
|
|||
HomePager.OnUrlOpenListener onUrlOpenListener,
|
||||
HomePager.OnUrlOpenInBackgroundListener onUrlOpenInBackgroundListener) {
|
||||
super(context,
|
||||
telemetryExtraBuilder,
|
||||
mode,
|
||||
title,
|
||||
url,
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.mozilla.gecko.R;
|
|||
import org.mozilla.gecko.Telemetry;
|
||||
import org.mozilla.gecko.TelemetryContract;
|
||||
import org.mozilla.gecko.activitystream.ActivityStream;
|
||||
import org.mozilla.gecko.activitystream.ActivityStreamTelemetry;
|
||||
import org.mozilla.gecko.db.BrowserContract;
|
||||
import org.mozilla.gecko.home.HomePager;
|
||||
import org.mozilla.gecko.home.activitystream.menu.ActivityStreamContextMenu;
|
||||
|
@ -103,13 +104,22 @@ class TopSitesCard extends RecyclerView.ViewHolder
|
|||
|
||||
@Override
|
||||
public void onClick(View clickedView) {
|
||||
ActivityStreamTelemetry.Extras.Builder extras = ActivityStreamTelemetry.Extras.builder()
|
||||
.set(ActivityStreamTelemetry.Contract.SOURCE_TYPE, ActivityStreamTelemetry.Contract.TYPE_TOPSITES)
|
||||
.forTopSiteType(type);
|
||||
|
||||
if (clickedView == itemView) {
|
||||
onUrlOpenListener.onUrlOpen(url, EnumSet.noneOf(HomePager.OnUrlOpenListener.Flags.class));
|
||||
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.LIST_ITEM, "as_top_sites");
|
||||
Telemetry.sendUIEvent(
|
||||
TelemetryContract.Event.LOAD_URL,
|
||||
TelemetryContract.Method.LIST_ITEM,
|
||||
extras.build()
|
||||
);
|
||||
} else if (clickedView == menuButton) {
|
||||
ActivityStreamContextMenu.show(clickedView.getContext(),
|
||||
menuButton,
|
||||
extras,
|
||||
ActivityStreamContextMenu.MenuMode.TOPSITE,
|
||||
title.getText().toString(), url,
|
||||
|
||||
|
@ -118,11 +128,15 @@ class TopSitesCard extends RecyclerView.ViewHolder
|
|||
onUrlOpenListener, onUrlOpenInBackgroundListener,
|
||||
faviconView.getWidth(), faviconView.getHeight());
|
||||
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.SHOW, TelemetryContract.Method.CONTEXT_MENU, "as_top_sites");
|
||||
Telemetry.sendUIEvent(
|
||||
TelemetryContract.Event.SHOW,
|
||||
TelemetryContract.Method.CONTEXT_MENU,
|
||||
extras.build()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isPinned(int type) {
|
||||
private boolean isPinned(int type) {
|
||||
return type == BrowserContract.TopSites.TYPE_PINNED;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -335,6 +335,8 @@ gbjar.sources += ['java/org/mozilla/gecko/' + x for x in [
|
|||
'ActionModeCompatView.java',
|
||||
'ActivityHandlerHelper.java',
|
||||
'activitystream/ActivityStream.java',
|
||||
'activitystream/ActivityStreamTelemetry.java',
|
||||
'activitystream/Utils.java',
|
||||
'adjust/AdjustBrowserAppDelegate.java',
|
||||
'animation/AnimationUtils.java',
|
||||
'animation/HeightChangeAnimation.java',
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
.. -*- Mode: rst; fill-column: 80; -*-
|
||||
|
||||
==============
|
||||
Activity Stream UI Telemetry
|
||||
==============
|
||||
Building on top of UI Telemetry, Activity Stream records additional information about events and user context in which they occur.
|
||||
The ``extras`` field is used for that purpose; additional information is structured as JSON blobs.
|
||||
|
||||
Session
|
||||
=======
|
||||
Activity Stream events are recorded as part of the "activitystream.1" session.
|
||||
|
||||
Global extras
|
||||
=============
|
||||
A concept of a "global" extra is meant to support recording certain context information with every event that is being sent, regardless of its type.
|
||||
|
||||
``fx_account_present``, values: true, false
|
||||
Indicates if Firefox Account is currently enabled.
|
||||
|
||||
Extra information available for various event types
|
||||
===================================================
|
||||
Top Site interactions
|
||||
---------------------
|
||||
Two event types are recorded:
|
||||
|
||||
1) User clicked on a Top Site: event="loadurl.1", method="listitem"
|
||||
2) User clicked on the menu button: event="show.1", method="contextmenu"
|
||||
|
||||
For each event, in addition to global extras, the following information is recorded:
|
||||
|
||||
extras: {
|
||||
...
|
||||
"source_type": "topsites",
|
||||
"source_subtype": "pinned"/"suggested"/"top"
|
||||
}
|
||||
|
||||
Subtype indicates a reason an item which is being interacted with appeared in the Top Sites:
|
||||
- "pinned": a pinned top site, specifically a non-positioned "Activity Stream pinned" site
|
||||
- "suggested": a suggested top site, one of the default ones displayed when there's not enough browsing history available
|
||||
- "top": a frecency-based top site, based on browsing history. Neither "pinned" nor "suggested".
|
||||
|
||||
Highlight interactions
|
||||
----------------------
|
||||
Two event types are recorded:
|
||||
|
||||
1) User clicked on a Highlight: event="loadurl.1", method="listitem"
|
||||
2) User clicked on the menu button: event="show.1", method="contextmenu"
|
||||
|
||||
For both event types, in addition to global extras, the following information is recorded:
|
||||
|
||||
extras: {
|
||||
...
|
||||
"source_type": "highlights",
|
||||
"source_subtype": "visited"/"bookmarked"
|
||||
}
|
||||
|
||||
Subtype indicates reason an item being which is being interacted with appeared in the Highlights:
|
||||
- "visited": a website has been visited recently
|
||||
- "bookmarked": a website has been bookmarked recently
|
||||
|
||||
For "loadurl.1" event, the following extra information is also recorded:
|
||||
|
||||
extras: {
|
||||
...
|
||||
"action_position": number, /* 0-based index of a highlight being interacted with */
|
||||
"count": number, /* total number of highlights displayed */
|
||||
}
|
||||
|
||||
Context Menu interactions
|
||||
-------------------------
|
||||
Every interaction with a context menu item is recorded using: event="action.1", method="contextmenu"
|
||||
|
||||
For all interactions, in addition to global extras, the following information is recorded:
|
||||
|
||||
extras: {
|
||||
...
|
||||
"item": string, /* name of a menu item */
|
||||
"source_type": "topsites"/"highlights",
|
||||
"source_subtype": string, /* depending on type, one of: "pinned", "suggested", "top", "visited", "bookmarked" */
|
||||
}
|
||||
|
||||
Possible values for "item" key (names of menu items), in no particular order:
|
||||
- "share"
|
||||
- "add_bookmark"
|
||||
- "remove_bookmark"
|
||||
- "pin"
|
||||
- "unpin"
|
||||
- "copy"
|
||||
- "homescreen"
|
||||
- "newtab" (private tab actions are collapsed into "newtab" telemetry due to our privacy guidelines)
|
||||
- "dismiss"
|
||||
- "delete"
|
||||
|
||||
Full Examples
|
||||
=============
|
||||
Following examples of events are here to provide a better feel for the overall shape of telemetry data being recorded.
|
||||
|
||||
1) User with an active Firefox Account clicked on a menu item for a "visited highlight":
|
||||
``
|
||||
session="activitystream.1"
|
||||
event="show.1"
|
||||
method="contextmenu"
|
||||
extras="{
|
||||
'fx_account_present': true,
|
||||
'source_type': 'highlights',
|
||||
'source_subtype': 'visited'
|
||||
}"
|
||||
``
|
||||
|
||||
2) User with no active Firefox Account clicked on a second highlight (recent bookmark), with total of 7 highlights being displayed:
|
||||
``
|
||||
session="activitystream.1"
|
||||
event="loadurl.1"
|
||||
method="listitem"
|
||||
extras="{
|
||||
'fx_account_present': false,
|
||||
'source_type': 'highlights',
|
||||
'source_subtype': 'bookmarked'
|
||||
'action_position': 1,
|
||||
'count': 7
|
||||
}"
|
||||
``
|
||||
|
||||
3) User with an active Firefox Account clicked on a pinned top site:
|
||||
``
|
||||
session="activitystream.1"
|
||||
event="loadurl.1"
|
||||
method="listitem"
|
||||
extras="{
|
||||
'fx_account_present': true,
|
||||
'source_type': 'topsites',
|
||||
'source_subtype': 'pinned'
|
||||
}"
|
||||
``
|
||||
|
||||
4) User with an active Firefox Account clicked on a "share" context menu item, which was displayed for a regular top site:
|
||||
``
|
||||
session="activitystream.1"
|
||||
event="action.1"
|
||||
method="contextmenu"
|
||||
extras="{
|
||||
'fx_account_present': true,
|
||||
'source_type': 'topsites',
|
||||
'source_subtype': 'top',
|
||||
'item': 'share'
|
||||
}"
|
||||
``
|
|
@ -10,6 +10,8 @@ import android.view.View;
|
|||
import com.robotium.solo.Condition;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.activitystream.ActivityStream;
|
||||
import org.mozilla.gecko.activitystream.ActivityStreamTelemetry;
|
||||
import org.mozilla.gecko.db.BrowserDB;
|
||||
import org.mozilla.gecko.home.activitystream.menu.ActivityStreamContextMenu;
|
||||
|
||||
|
@ -61,7 +63,8 @@ public class testActivityStreamContextMenu extends BaseTest {
|
|||
private void testMenuForUrl(final String url, final Boolean isBookmarkedKnownState, final boolean isBookmarked, final Boolean isPinnedKnownState, final boolean isPinned, final boolean isVisited) {
|
||||
final View anchor = new View(getActivity());
|
||||
|
||||
final ActivityStreamContextMenu menu = ActivityStreamContextMenu.show(getActivity(), anchor, ActivityStreamContextMenu.MenuMode.HIGHLIGHT, "foobar", url, isBookmarkedKnownState, isPinnedKnownState, null, null, 100, 100);
|
||||
final ActivityStreamContextMenu menu = ActivityStreamContextMenu.show(
|
||||
getActivity(), anchor, ActivityStreamTelemetry.Extras.builder(), ActivityStreamContextMenu.MenuMode.HIGHLIGHT, "foobar", url, isBookmarkedKnownState, isPinnedKnownState, null, null, 100, 100);
|
||||
|
||||
final int expectedBookmarkString;
|
||||
if (isBookmarked) {
|
||||
|
|
|
@ -2161,8 +2161,10 @@ NS_IsSrcdocChannel(nsIChannel *aChannel)
|
|||
}
|
||||
nsCOMPtr<nsIViewSourceChannel> vsc = do_QueryInterface(aChannel);
|
||||
if (vsc) {
|
||||
vsc->GetIsSrcdocChannel(&isSrcdoc);
|
||||
return isSrcdoc;
|
||||
nsresult rv = vsc->GetIsSrcdocChannel(&isSrcdoc);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
return isSrcdoc;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -18,12 +18,12 @@ interface nsIViewSourceChannel : nsIChannel
|
|||
* However, callers interested in finding out or setting the
|
||||
* actual content type can utilize this attribute.
|
||||
*/
|
||||
attribute ACString originalContentType;
|
||||
[must_use] attribute ACString originalContentType;
|
||||
|
||||
/**
|
||||
* Whether the channel was created to view the source of a srcdoc document.
|
||||
*/
|
||||
readonly attribute boolean isSrcdocChannel;
|
||||
[must_use] readonly attribute boolean isSrcdocChannel;
|
||||
|
||||
/**
|
||||
* Set to indicate the base URI. If this channel is a srcdoc channel, it
|
||||
|
@ -32,7 +32,7 @@ interface nsIViewSourceChannel : nsIChannel
|
|||
* otherwise recoverable. Returns null when it isn't set and isn't a
|
||||
* srcdoc channel.
|
||||
*/
|
||||
attribute nsIURI baseURI;
|
||||
[must_use] attribute nsIURI baseURI;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -48,12 +48,12 @@ public:
|
|||
: mIsDocument(false)
|
||||
, mOpened(false) {}
|
||||
|
||||
nsresult Init(nsIURI* uri);
|
||||
MOZ_MUST_USE nsresult Init(nsIURI* uri);
|
||||
|
||||
nsresult InitSrcdoc(nsIURI* aURI,
|
||||
nsIURI* aBaseURI,
|
||||
const nsAString &aSrcdoc,
|
||||
nsILoadInfo* aLoadInfo);
|
||||
MOZ_MUST_USE nsresult InitSrcdoc(nsIURI* aURI,
|
||||
nsIURI* aBaseURI,
|
||||
const nsAString &aSrcdoc,
|
||||
nsILoadInfo* aLoadInfo);
|
||||
|
||||
protected:
|
||||
~nsViewSourceChannel() {}
|
||||
|
|
|
@ -25,11 +25,11 @@ public:
|
|||
|
||||
// Creates a new nsViewSourceChannel to view the source of an about:srcdoc
|
||||
// URI with contents specified by srcdoc.
|
||||
nsresult NewSrcdocChannel(nsIURI *aURI,
|
||||
nsIURI *aBaseURI,
|
||||
const nsAString &aSrcdoc,
|
||||
nsILoadInfo *aLoadInfo,
|
||||
nsIChannel** outChannel);
|
||||
MOZ_MUST_USE nsresult NewSrcdocChannel(nsIURI *aURI,
|
||||
nsIURI *aBaseURI,
|
||||
const nsAString &aSrcdoc,
|
||||
nsILoadInfo *aLoadInfo,
|
||||
nsIChannel** outChannel);
|
||||
|
||||
static nsViewSourceHandler* GetInstance();
|
||||
|
||||
|
|
|
@ -2077,9 +2077,8 @@ if test -n "$MOZ_SYSTEM_NSS"; then
|
|||
else
|
||||
NSS_CFLAGS="-I${DIST}/include/nss"
|
||||
case "${OS_ARCH}" in
|
||||
# This is to match the conditions in security/generate_mapfile.py,
|
||||
# plus Windows which doesn't run that script.
|
||||
WINNT|Darwin|Linux)
|
||||
# Only few platforms have been tested with GYP
|
||||
WINNT|Darwin|Linux|DragonFly|FreeBSD|NetBSD|OpenBSD)
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR([building in-tree NSS is not supported on this platform. Use --with-system-nss])
|
||||
|
|
|
@ -20,18 +20,18 @@ RUSTUP_URL_BASE = 'https://static-rust-lang-org.s3.amazonaws.com/rustup'
|
|||
RUSTUP_MANIFEST = os.path.join(RUSTUP_URL_BASE, 'release-stable.toml')
|
||||
|
||||
# We bake in a known version number so we can verify a checksum.
|
||||
RUSTUP_VERSION = '0.6.5'
|
||||
RUSTUP_VERSION = '1.0.0'
|
||||
|
||||
# SHA-256 checksums of the installers, per platform.
|
||||
RUSTUP_HASHES = {
|
||||
'x86_64-apple-darwin':
|
||||
'6404ab0a92c1559bac279a20d31be9166c91434f8e7ff8d1a97bcbe4dbd3cadc',
|
||||
'x86_64-pc-windows-msvc':
|
||||
'772579edcbc9a480a61fb19ace49527839e7f919e1041bcc2dee2a4ff82d3ca2',
|
||||
'x86_64-unknown-linux-gnu':
|
||||
'e901e23ee48c3a24470d997c4376d8835cecca51bf2636dcd419821d4056d823',
|
||||
'x86_64-unknown-freebsd':
|
||||
'63b7c0f35a811993c94af85b96abdd3dcca847d260af284f888e91c2ffdb374e',
|
||||
'706c2c8a49498b722baad5e8dadaa16a3505e2a9f46b7ee3f41d4dce56163155',
|
||||
'x86_64-apple-darwin':
|
||||
'2da68a13feb9a691ef3b59d0d6d53af617962ab5ba4673eaf3818778ccd00bec',
|
||||
'x86_64-unknown-linux-gnu':
|
||||
'4cda09438c08eab55cfe4a98325a5722c4ec66865d07da07d38ddc6c36893692',
|
||||
'x86_64-pc-windows-msvc':
|
||||
'e3bba8fbb24aed412757d1ea07d6ed1e952ca3f6293b3551e44649601dbe830f',
|
||||
}
|
||||
|
||||
NO_PLATFORM = '''
|
||||
|
|
|
@ -1044,7 +1044,8 @@ class Artifacts(object):
|
|||
'revision': revision},
|
||||
'Will only accept artifacts from a pushhead at {revision} '
|
||||
'(matched revset "{revset}").')
|
||||
pushheads = [(list(CANDIDATE_TREES), revision)]
|
||||
# Include try in our search to allow pulling from a specific push.
|
||||
pushheads = [(list(CANDIDATE_TREES) + ['try'], revision)]
|
||||
return self._install_from_hg_pushheads(pushheads, distdir)
|
||||
|
||||
def install_from(self, source, distdir):
|
||||
|
|
|
@ -17,12 +17,7 @@ import buildconfig
|
|||
|
||||
|
||||
def main(output, input):
|
||||
# There's a check in old-configure.in under the system-nss handling
|
||||
# that should match this.
|
||||
if buildconfig.substs['OS_ARCH'] not in ('Linux', 'Darwin'):
|
||||
print "Error: unhandled OS_ARCH %s" % buildconfig.substs['OS_ARCH']
|
||||
return 1
|
||||
is_linux = buildconfig.substs['OS_ARCH'] == 'Linux'
|
||||
is_darwin = buildconfig.substs['OS_ARCH'] == 'Darwin'
|
||||
|
||||
with open(input, 'rb') as f:
|
||||
for line in f:
|
||||
|
@ -30,8 +25,8 @@ def main(output, input):
|
|||
# Remove all lines containing ';-'
|
||||
if ';-' in line:
|
||||
continue
|
||||
# On non-Linux, remove all lines containing ';+'
|
||||
if not is_linux and ';+' in line:
|
||||
# On OS X, remove all lines containing ';+'
|
||||
if is_darwin and ';+' in line:
|
||||
continue
|
||||
# Remove the string ' DATA '.
|
||||
line = line.replace(' DATA ', '')
|
||||
|
@ -40,15 +35,15 @@ def main(output, input):
|
|||
# Remove the string ';;'
|
||||
line = line.replace(';;', '')
|
||||
# If a ';' is present, remove everything after it,
|
||||
# and on non-Linux, remove it as well.
|
||||
# and on OS X, remove it as well.
|
||||
i = line.find(';')
|
||||
if i != -1:
|
||||
if is_linux:
|
||||
line = line[:i+1]
|
||||
else:
|
||||
if is_darwin:
|
||||
line = line[:i]
|
||||
# On non-Linux, symbols get an underscore in front.
|
||||
if line and not is_linux:
|
||||
else:
|
||||
line = line[:i+1]
|
||||
# On OS X, symbols get an underscore in front.
|
||||
if line and is_darwin:
|
||||
output.write('_')
|
||||
output.write(line)
|
||||
output.write('\n')
|
||||
|
|
|
@ -1149,4 +1149,4 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
|
|||
|
||||
static const int32_t kUnknownId = -1;
|
||||
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1490884654448000);
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1490970376665000);
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
7kovrikov.ru: did not receive HSTS header
|
||||
808.lv: could not connect to host
|
||||
83i.net: could not connect to host
|
||||
88.to: could not connect to host
|
||||
8ack.de: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
911911.pw: could not connect to host
|
||||
922.be: could not connect to host
|
||||
|
@ -59,6 +60,7 @@ abecodes.net: could not connect to host
|
|||
abeestrada.com: did not receive HSTS header
|
||||
abilitylist.org: did not receive HSTS header
|
||||
abioniere.de: could not connect to host
|
||||
abnarnro.com: could not connect to host
|
||||
about.ge: could not connect to host
|
||||
aboutmyip.info: did not receive HSTS header
|
||||
aboutmyproperty.ca: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
|
@ -167,7 +169,6 @@ altfire.ca: could not connect to host
|
|||
altmv.com: max-age too low: 7776000
|
||||
alwaysmine.fi: did not receive HSTS header
|
||||
amaforums.org: could not connect to host
|
||||
amdouglas.com: could not connect to host
|
||||
american-truck-simulator.de: could not connect to host
|
||||
american-truck-simulator.net: could not connect to host
|
||||
americanworkwear.nl: did not receive HSTS header
|
||||
|
@ -214,13 +215,13 @@ ant.land: could not connect to host
|
|||
anthenor.co.uk: could not connect to host
|
||||
antimine.kr: could not connect to host
|
||||
antocom.com: did not receive HSTS header
|
||||
antoinedeschenes.com: could not connect to host
|
||||
antoniomarques.eu: did not receive HSTS header
|
||||
antoniorequena.com.ve: could not connect to host
|
||||
antscript.com: did not receive HSTS header
|
||||
any.pm: could not connect to host
|
||||
anycoin.me: could not connect to host
|
||||
aojiao.org: did not receive HSTS header
|
||||
aosc.io: did not receive HSTS header
|
||||
apachelounge.com: did not receive HSTS header
|
||||
apeasternpower.com: max-age too low: 0
|
||||
api.mega.co.nz: could not connect to host
|
||||
|
@ -250,6 +251,7 @@ arbu.eu: max-age too low: 2419200
|
|||
argh.io: could not connect to host
|
||||
arlen.se: could not connect to host
|
||||
armingrodon.de: did not receive HSTS header
|
||||
arminpech.de: could not connect to host
|
||||
armory.consulting: could not connect to host
|
||||
armory.supplies: could not connect to host
|
||||
armytricka.cz: did not receive HSTS header
|
||||
|
@ -284,6 +286,7 @@ atavio.at: could not connect to host
|
|||
atavio.ch: could not connect to host
|
||||
atavio.de: did not receive HSTS header
|
||||
atbeckett.com: did not receive HSTS header
|
||||
atelierdesflammesnoires.fr: could not connect to host
|
||||
athaliasoft.com: did not receive HSTS header
|
||||
athenelive.com: could not connect to host
|
||||
athul.xyz: did not receive HSTS header
|
||||
|
@ -321,7 +324,6 @@ axado.com.br: did not receive HSTS header
|
|||
axeny.com: did not receive HSTS header
|
||||
az.search.yahoo.com: did not receive HSTS header
|
||||
azprep.us: could not connect to host
|
||||
azuxul.fr: could not connect to host
|
||||
b3orion.com: max-age too low: 0
|
||||
baby-click.de: did not receive HSTS header
|
||||
babybic.hu: did not receive HSTS header
|
||||
|
@ -347,6 +349,7 @@ basicsolutionsus.com: did not receive HSTS header
|
|||
basilisk.io: could not connect to host
|
||||
basnieuwenhuizen.nl: could not connect to host
|
||||
bassh.net: did not receive HSTS header
|
||||
baud.ninja: could not connect to host
|
||||
baumstark.ca: did not receive HSTS header
|
||||
bazarstupava.sk: could not connect to host
|
||||
bcbsmagentprofile.com: could not connect to host
|
||||
|
@ -378,6 +381,7 @@ beneffy.com: did not receive HSTS header
|
|||
benk.press: could not connect to host
|
||||
benny003.de: did not receive HSTS header
|
||||
benzkosmetik.de: could not connect to host
|
||||
berasavocate.com: could not connect to host
|
||||
bergenhave.nl: did not receive HSTS header
|
||||
bermytraq.bm: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
berr.yt: could not connect to host
|
||||
|
@ -416,7 +420,6 @@ binderapp.net: could not connect to host
|
|||
biofam.ru: did not receive HSTS header
|
||||
bionicspirit.com: could not connect to host
|
||||
biophysik-ssl.de: did not receive HSTS header
|
||||
bioshome.de: could not connect to host
|
||||
birkman.com: did not receive HSTS header
|
||||
bismarck.moe: did not receive HSTS header
|
||||
bitchan.it: could not connect to host
|
||||
|
@ -430,8 +433,6 @@ bitheus.com: could not connect to host
|
|||
bithosting.io: did not receive HSTS header
|
||||
bitnet.io: did not receive HSTS header
|
||||
bitsafe.systems: could not connect to host
|
||||
bitstorm.nl: could not connect to host
|
||||
bitstorm.org: could not connect to host
|
||||
bitvigor.com: could not connect to host
|
||||
bivsi.com: could not connect to host
|
||||
bizcms.com: did not receive HSTS header
|
||||
|
@ -444,14 +445,12 @@ bl4ckb0x.net: did not receive HSTS header
|
|||
bl4ckb0x.org: did not receive HSTS header
|
||||
black-armada.com.pl: could not connect to host
|
||||
black-armada.pl: could not connect to host
|
||||
black-khat.com: could not connect to host
|
||||
blackburn.link: did not receive HSTS header
|
||||
blacklane.com: did not receive HSTS header
|
||||
blackly.uk: could not connect to host
|
||||
blackpayment.ru: could not connect to host
|
||||
blackunicorn.wtf: could not connect to host
|
||||
blantik.net: could not connect to host
|
||||
blaudev.es: could not connect to host
|
||||
blenheimchalcot.com: did not receive HSTS header
|
||||
blha303.com.au: could not connect to host
|
||||
blindsexdate.nl: could not connect to host
|
||||
|
@ -508,6 +507,7 @@ brandspray.com: did not receive HSTS header
|
|||
brianmwaters.net: could not connect to host
|
||||
brickoo.com: could not connect to host
|
||||
brideandgroomdirect.ie: did not receive HSTS header
|
||||
brivadois.ovh: could not connect to host
|
||||
brks.xyz: could not connect to host
|
||||
broken-oak.com: could not connect to host
|
||||
brokenhands.io: did not receive HSTS header
|
||||
|
@ -551,6 +551,7 @@ bypro.xyz: could not connect to host
|
|||
bysymphony.com: max-age too low: 0
|
||||
byte.wtf: did not receive HSTS header
|
||||
bytepark.de: did not receive HSTS header
|
||||
bytesunlimited.com: could not connect to host
|
||||
c1yd3i.me: could not connect to host
|
||||
c3b.info: could not connect to host
|
||||
cabarave.com: could not connect to host
|
||||
|
@ -564,6 +565,7 @@ cajapopcorn.com: did not receive HSTS header
|
|||
cake.care: could not connect to host
|
||||
calgaryconstructionjobs.com: could not connect to host
|
||||
calix.com: max-age too low: 0
|
||||
callsigns.ca: could not connect to host
|
||||
calltrackingreports.com: could not connect to host
|
||||
calvin.me: max-age too low: 2592000
|
||||
calvinallen.net: did not receive HSTS header
|
||||
|
@ -632,7 +634,6 @@ championsofregnum.com: did not receive HSTS header
|
|||
chandlerredding.com: did not receive HSTS header
|
||||
changelab.cc: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
chaos.fail: did not receive HSTS header
|
||||
chaoslab.org: could not connect to host
|
||||
chargejuice.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
charnleyhouse.co.uk: max-age too low: 604800
|
||||
chartpen.com: did not receive HSTS header
|
||||
|
@ -715,6 +716,7 @@ cmscafe.ru: did not receive HSTS header
|
|||
cn.search.yahoo.com: did not receive HSTS header
|
||||
cni-certing.it: max-age too low: 0
|
||||
co50.com: did not receive HSTS header
|
||||
coam.co: did not receive HSTS header
|
||||
cocaine-import.agency: could not connect to host
|
||||
codabix.com: did not receive HSTS header
|
||||
codabix.de: could not connect to host
|
||||
|
@ -731,7 +733,6 @@ coiffeurschnittstelle.ch: did not receive HSTS header
|
|||
coindam.com: could not connect to host
|
||||
coldfff.com: could not connect to host
|
||||
coldlostsick.net: could not connect to host
|
||||
colinwolff.com: could not connect to host
|
||||
colisfrais.com: did not receive HSTS header
|
||||
collies.eu: did not receive HSTS header
|
||||
collins.kg: did not receive HSTS header
|
||||
|
@ -767,6 +768,7 @@ core4system.de: could not connect to host
|
|||
corenetworking.de: could not connect to host
|
||||
cormilu.com.br: did not receive HSTS header
|
||||
cornodo.com: could not connect to host
|
||||
coronelpicanha.com.br: could not connect to host
|
||||
correctpaardbatterijnietje.nl: did not receive HSTS header
|
||||
corruption-mc.net: could not connect to host
|
||||
corruption-rsps.net: could not connect to host
|
||||
|
@ -780,7 +782,7 @@ coverduck.ru: could not connect to host
|
|||
cr.search.yahoo.com: did not receive HSTS header
|
||||
cracking.org: did not receive HSTS header
|
||||
craftbeerbarn.co.uk: could not connect to host
|
||||
craftedge.xyz: could not connect to host
|
||||
craftedge.xyz: did not receive HSTS header
|
||||
craftmine.cz: did not receive HSTS header
|
||||
crate.io: did not receive HSTS header
|
||||
cravelyrics.com: did not receive HSTS header
|
||||
|
@ -830,6 +832,7 @@ cupidmentor.com: did not receive HSTS header
|
|||
curroapp.com: could not connect to host
|
||||
custe.rs: could not connect to host
|
||||
cuvva.insure: did not receive HSTS header
|
||||
cvjm-memmingen.de: could not connect to host
|
||||
cyanogenmod.xxx: could not connect to host
|
||||
cyberpunk.ca: could not connect to host
|
||||
cybershambles.com: could not connect to host
|
||||
|
@ -867,6 +870,7 @@ databutlr.net: could not connect to host
|
|||
datahove.no: did not receive HSTS header
|
||||
datarank.com: max-age too low: 0
|
||||
dataretention.solutions: could not connect to host
|
||||
datasnitch.co.uk: could not connect to host
|
||||
datatekniikka.com: could not connect to host
|
||||
datenkeks.de: did not receive HSTS header
|
||||
dateno1.com: max-age too low: 2592000
|
||||
|
@ -918,6 +922,7 @@ depijl-mz.nl: did not receive HSTS header
|
|||
depixion.agency: could not connect to host
|
||||
dequehablamos.es: could not connect to host
|
||||
derevtsov.com: did not receive HSTS header
|
||||
dergeilstestammderwelt.de: could not connect to host
|
||||
derhil.de: did not receive HSTS header
|
||||
derwolfe.net: did not receive HSTS header
|
||||
desiccantpackets.com: did not receive HSTS header
|
||||
|
@ -981,7 +986,6 @@ doridian.net: did not receive HSTS header
|
|||
doridian.org: could not connect to host
|
||||
dossplumbing.co.za: did not receive HSTS header
|
||||
dotadata.me: could not connect to host
|
||||
dougferris.id.au: could not connect to host
|
||||
dovetailnow.com: could not connect to host
|
||||
download.jitsi.org: did not receive HSTS header
|
||||
downsouthweddings.com.au: did not receive HSTS header
|
||||
|
@ -1000,7 +1004,6 @@ dreaming.solutions: did not receive HSTS header
|
|||
drishti.guru: could not connect to host
|
||||
drive.google.com: did not receive HSTS header (error ignored - included regardless)
|
||||
driving-lessons.co.uk: did not receive HSTS header
|
||||
drjuanitacollier.com: could not connect to host
|
||||
droidboss.com: could not connect to host
|
||||
dropcam.com: did not receive HSTS header
|
||||
drtroyhendrickson.com: could not connect to host
|
||||
|
@ -1012,6 +1015,7 @@ duch.cloud: could not connect to host
|
|||
duesee.org: could not connect to host
|
||||
dullsir.com: did not receive HSTS header
|
||||
duria.de: max-age too low: 3600
|
||||
dutchrank.com: could not connect to host
|
||||
dwhd.org: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
dxa.io: could not connect to host
|
||||
dycontrol.de: could not connect to host
|
||||
|
@ -1050,6 +1054,7 @@ edk.com.tr: did not receive HSTS header
|
|||
edmodo.com: did not receive HSTS header
|
||||
edp-collaborative.com: max-age too low: 2500
|
||||
eduvance.in: did not receive HSTS header
|
||||
edwards.me.uk: could not connect to host
|
||||
eenhoorn.ga: did not receive HSTS header
|
||||
eeqj.com: could not connect to host
|
||||
efficienthealth.com: did not receive HSTS header
|
||||
|
@ -1089,7 +1094,6 @@ email.lookout.com: could not connect to host
|
|||
emanatepixels.com: could not connect to host
|
||||
emeldi-commerce.com: max-age too low: 0
|
||||
emjainteractive.com: did not receive HSTS header
|
||||
emjimadhu.com: could not connect to host
|
||||
emmable.com: could not connect to host
|
||||
emnitech.com: could not connect to host
|
||||
empleosentorreon.mx: could not connect to host
|
||||
|
@ -1124,7 +1128,7 @@ equatetechnologies.com.au: max-age too low: 3600
|
|||
equilibre-yoga-jennifer-will.com: could not connect to host
|
||||
erawanarifnugroho.com: did not receive HSTS header
|
||||
eressea.xyz: could not connect to host
|
||||
ericyl.com: did not receive HSTS header
|
||||
ericyl.com: could not connect to host
|
||||
ernesto.at: could not connect to host
|
||||
eromixx.com: did not receive HSTS header
|
||||
erotalia.es: could not connect to host
|
||||
|
@ -1261,6 +1265,7 @@ flamingkeys.com.au: could not connect to host
|
|||
flawcheck.com: did not receive HSTS header
|
||||
fliexer.com: did not receive HSTS header
|
||||
floless.co.uk: did not receive HSTS header
|
||||
florent-tatard.fr: could not connect to host
|
||||
florian-lillpopp.de: max-age too low: 10
|
||||
florianlillpopp.de: max-age too low: 10
|
||||
floridaescapes.co.uk: did not receive HSTS header
|
||||
|
@ -1270,7 +1275,6 @@ flowersandclouds.com: could not connect to host
|
|||
flukethoughts.com: could not connect to host
|
||||
flushstudios.com: did not receive HSTS header
|
||||
flyaces.com: did not receive HSTS header
|
||||
flyss.net: did not receive HSTS header
|
||||
fm83.nl: could not connect to host
|
||||
fndout.com: did not receive HSTS header
|
||||
fnvsecurity.com: could not connect to host
|
||||
|
@ -1324,7 +1328,6 @@ fuckgfw233.org: could not connect to host
|
|||
fugle.de: could not connect to host
|
||||
fukushima-web.com: did not receive HSTS header
|
||||
funkyweddingideas.com.au: could not connect to host
|
||||
funnyang.com: could not connect to host
|
||||
funrun.com: did not receive HSTS header
|
||||
furiffic.com: did not receive HSTS header
|
||||
furry.be: max-age too low: 86400
|
||||
|
@ -1375,6 +1378,7 @@ genuu.com: could not connect to host
|
|||
genuxation.com: could not connect to host
|
||||
genyaa.com: could not connect to host
|
||||
gerencianet.com.br: did not receive HSTS header
|
||||
gersting.net: could not connect to host
|
||||
get.zenpayroll.com: did not receive HSTS header
|
||||
getable.com: did not receive HSTS header
|
||||
getblys.com.au: did not receive HSTS header
|
||||
|
@ -1463,6 +1467,7 @@ gparent.org: did not receive HSTS header
|
|||
gpsfix.cz: could not connect to host
|
||||
gpstuner.com: did not receive HSTS header
|
||||
gracesofgrief.com: max-age too low: 86400
|
||||
graffen.dk: did not receive HSTS header
|
||||
grandmascookieblog.com: did not receive HSTS header
|
||||
graph.no: did not receive HSTS header
|
||||
gravity-net.de: could not connect to host
|
||||
|
@ -1472,7 +1477,6 @@ greenvines.com.tw: did not receive HSTS header
|
|||
gregorytlee.me: could not connect to host
|
||||
gremots.com: did not receive HSTS header
|
||||
greplin.com: could not connect to host
|
||||
gribani.com: could not connect to host
|
||||
grigalanzsoftware.com: could not connect to host
|
||||
grossmann.gr: could not connect to host
|
||||
groups.google.com: did not receive HSTS header (error ignored - included regardless)
|
||||
|
@ -1486,7 +1490,6 @@ gtlfsonlinepay.com: did not receive HSTS header
|
|||
gtraxapp.com: could not connect to host
|
||||
guava.studio: did not receive HSTS header
|
||||
guilde-vindicta.fr: did not receive HSTS header
|
||||
gulenet.com: did not receive HSTS header
|
||||
gurusupe.com: could not connect to host
|
||||
gussi.is: could not connect to host
|
||||
gvt2.com: could not connect to host (error ignored - included regardless)
|
||||
|
@ -1604,7 +1607,6 @@ horosho.in: could not connect to host
|
|||
horseboners.xxx: did not receive HSTS header
|
||||
hortifarm.ro: did not receive HSTS header
|
||||
hosted-service.com: did not receive HSTS header
|
||||
hosted4u.de: could not connect to host
|
||||
hostedtalkgadget.google.com: did not receive HSTS header (error ignored - included regardless)
|
||||
hostgarou.com: did not receive HSTS header
|
||||
hostinaus.com.au: could not connect to host
|
||||
|
@ -1624,6 +1626,7 @@ http418.xyz: could not connect to host
|
|||
httpstatuscode418.xyz: could not connect to host
|
||||
hu.search.yahoo.com: did not receive HSTS header
|
||||
huarongdao.com: did not receive HSTS header
|
||||
huffduffer.com: could not connect to host
|
||||
hugosleep.com.au: did not receive HSTS header
|
||||
humblefinances.com: could not connect to host
|
||||
humeurs.net: could not connect to host
|
||||
|
@ -1689,6 +1692,7 @@ immunicity.press: could not connect to host
|
|||
immunicity.top: could not connect to host
|
||||
imolug.org: did not receive HSTS header
|
||||
imouto.my: max-age too low: 5184000
|
||||
imouyang.com: could not connect to host
|
||||
imperialwebsolutions.com: did not receive HSTS header
|
||||
imu.li: did not receive HSTS header
|
||||
imusic.dk: did not receive HSTS header
|
||||
|
@ -1697,7 +1701,6 @@ inbox.li: did not receive HSTS header
|
|||
incendiary-arts.com: could not connect to host
|
||||
inchomatic.com: did not receive HSTS header
|
||||
indoorskiassen.nl: did not receive HSTS header
|
||||
indredouglas.me: could not connect to host
|
||||
indust.me: did not receive HSTS header
|
||||
infcof.com: max-age too low: 0
|
||||
infinitude.xyz: could not connect to host
|
||||
|
@ -1713,6 +1716,7 @@ inkstory.gr: did not receive HSTS header
|
|||
inksupply.com: did not receive HSTS header
|
||||
inleaked.com: could not connect to host
|
||||
inmyarea.com: max-age too low: 0
|
||||
innophate-security.com: could not connect to host
|
||||
innophate-security.nl: could not connect to host
|
||||
ins1gn1a.com: did not receive HSTS header
|
||||
insane.zone: could not connect to host
|
||||
|
@ -1726,7 +1730,6 @@ intel.li: could not connect to host
|
|||
intelldynamics.com: could not connect to host
|
||||
interference.io: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
interlun.com: could not connect to host
|
||||
internect.co.za: did not receive HSTS header
|
||||
internetcasinos.de: did not receive HSTS header
|
||||
internetcensus.org: could not connect to host
|
||||
interserved.com: did not receive HSTS header
|
||||
|
@ -1803,6 +1806,7 @@ jannyrijneveld.nl: did not receive HSTS header
|
|||
janus-engineering.de: did not receive HSTS header
|
||||
japlex.com: could not connect to host
|
||||
jaqen.ch: could not connect to host
|
||||
jardins-utopie.net: could not connect to host
|
||||
jaredeberle.org: did not receive HSTS header
|
||||
jaroslavtrsek.cz: did not receive HSTS header
|
||||
jartza.org: could not connect to host
|
||||
|
@ -1815,7 +1819,6 @@ jayblock.com: did not receive HSTS header
|
|||
jayschulman.com: could not connect to host
|
||||
jayscoaching.com: could not connect to host
|
||||
jayshao.com: did not receive HSTS header
|
||||
jayxon.com: could not connect to host
|
||||
jazzinutrecht.info: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
jazzncheese.com: could not connect to host
|
||||
jbbd.fr: could not connect to host
|
||||
|
@ -1893,6 +1896,7 @@ juwairen.cn: could not connect to host
|
|||
jvoice.net: could not connect to host
|
||||
jwilsson.me: could not connect to host
|
||||
jxm.in: could not connect to host
|
||||
jym.fit: did not receive HSTS header
|
||||
k-dev.de: could not connect to host
|
||||
ka-clan.com: could not connect to host
|
||||
kabuabc.com: did not receive HSTS header
|
||||
|
@ -1902,6 +1906,7 @@ kahopoon.net: could not connect to host
|
|||
kaisers.de: did not receive HSTS header
|
||||
kalami.nl: did not receive HSTS header
|
||||
kamikano.com: could not connect to host
|
||||
kaniklani.co.za: could not connect to host
|
||||
kaplatz.is: could not connect to host
|
||||
kapucini.si: max-age too low: 0
|
||||
karaoketonight.com: could not connect to host
|
||||
|
@ -1923,6 +1928,7 @@ keeley.ml: could not connect to host
|
|||
keeleysam.me: could not connect to host
|
||||
keepclean.me: could not connect to host
|
||||
ken.fm: did not receive HSTS header
|
||||
kennethlim.me: could not connect to host
|
||||
kentacademiestrust.org.uk: could not connect to host
|
||||
kerangalam.com: could not connect to host
|
||||
kerksanders.nl: did not receive HSTS header
|
||||
|
@ -1953,6 +1959,7 @@ kisa.io: could not connect to host
|
|||
kisalt.im: did not receive HSTS header
|
||||
kissart.net: could not connect to host
|
||||
kissflow.com: did not receive HSTS header
|
||||
kisstyle.ru: could not connect to host
|
||||
kisun.co.jp: could not connect to host
|
||||
kitakemon.com: could not connect to host
|
||||
kitchenpunx.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
|
@ -1989,7 +1996,6 @@ kotovstyle.ru: could not connect to host
|
|||
kr.search.yahoo.com: did not receive HSTS header
|
||||
kredite.sale: could not connect to host
|
||||
kriegt.es: could not connect to host
|
||||
kristikala.nl: could not connect to host
|
||||
krmela.com: could not connect to host
|
||||
kroetenfuchs.de: could not connect to host
|
||||
kropkait.pl: could not connect to host
|
||||
|
@ -2022,6 +2028,7 @@ labs.moscow: did not receive HSTS header
|
|||
lachlankidson.net: did not receive HSTS header
|
||||
lacledeslan.ninja: could not connect to host
|
||||
ladbroke.net: did not receive HSTS header
|
||||
laextra.mx: could not connect to host
|
||||
laf.in.net: did not receive HSTS header
|
||||
lagalerievirtuelle.fr: did not receive HSTS header
|
||||
lagoza.name: could not connect to host
|
||||
|
@ -2037,7 +2044,7 @@ lask.in: did not receive HSTS header
|
|||
latus.xyz: could not connect to host
|
||||
lavabit.no: could not connect to host
|
||||
lavval.com: could not connect to host
|
||||
lawformt.com: did not receive HSTS header
|
||||
lawformt.com: could not connect to host
|
||||
laxatus.com: did not receive HSTS header
|
||||
laxiongames.es: could not connect to host
|
||||
lbrt.xyz: could not connect to host
|
||||
|
@ -2119,7 +2126,6 @@ livedemo.io: could not connect to host
|
|||
livej.am: could not connect to host
|
||||
livi.co: did not receive HSTS header
|
||||
lnoldan.com: could not connect to host
|
||||
lntu.org: could not connect to host
|
||||
loadingdeck.com: did not receive HSTS header
|
||||
loafbox.com: could not connect to host
|
||||
lobosdomain.no-ip.info: could not connect to host
|
||||
|
@ -2260,7 +2266,6 @@ mca2017.org: did not receive HSTS header
|
|||
mcc.re: could not connect to host
|
||||
mcdonalds.ru: did not receive HSTS header
|
||||
mclab.su: could not connect to host
|
||||
md5hashing.net: did not receive HSTS header
|
||||
mdewendt.de: could not connect to host
|
||||
mdfnet.se: did not receive HSTS header
|
||||
mdscomp.net: did not receive HSTS header
|
||||
|
@ -2346,7 +2351,7 @@ mironized.com: did not receive HSTS header
|
|||
mirrorx.com: did not receive HSTS header
|
||||
missrain.tw: could not connect to host
|
||||
mister.hosting: could not connect to host
|
||||
misterl.net: did not receive HSTS header
|
||||
misterl.net: could not connect to host
|
||||
mitchellrenouf.ca: could not connect to host
|
||||
mittenhacks.com: could not connect to host
|
||||
mivcon.net: could not connect to host
|
||||
|
@ -2371,7 +2376,7 @@ modemagazines.co.uk: could not connect to host
|
|||
moebel-nagel.de: did not receive HSTS header
|
||||
moelord.org: could not connect to host
|
||||
moen.io: did not receive HSTS header
|
||||
mogry.net: did not receive HSTS header
|
||||
mogry.net: could not connect to host
|
||||
mona.lu: did not receive HSTS header
|
||||
monarca.systems: could not connect to host
|
||||
monasterialis.eu: could not connect to host
|
||||
|
@ -2402,6 +2407,7 @@ moula.com.au: did not receive HSTS header
|
|||
mountainmusicpromotions.com: did not receive HSTS header
|
||||
moviesabout.net: could not connect to host
|
||||
moy.cat: could not connect to host
|
||||
mozoa.net: did not receive HSTS header
|
||||
mp3juices.is: could not connect to host
|
||||
mqas.net: could not connect to host
|
||||
mrettich.org: could not connect to host
|
||||
|
@ -2434,6 +2440,7 @@ my.alfresco.com: did not receive HSTS header
|
|||
my.swedbank.se: did not receive HSTS header
|
||||
my.usa.gov: did not receive HSTS header
|
||||
myairshop.gr: could not connect to host
|
||||
myartsjournal.com: did not receive HSTS header
|
||||
mybon.at: could not connect to host
|
||||
mybudget.xyz: could not connect to host
|
||||
mycollab.net: could not connect to host
|
||||
|
@ -2468,7 +2475,7 @@ nanogeneinc.com: could not connect to host
|
|||
nanto.eu: could not connect to host
|
||||
narada.com.ua: could not connect to host
|
||||
nargileh.nl: could not connect to host
|
||||
nascher.org: could not connect to host
|
||||
nascher.org: max-age too low: 7884000
|
||||
natalia.io: could not connect to host
|
||||
natalt.org: did not receive HSTS header
|
||||
nathanmfarrugia.com: did not receive HSTS header
|
||||
|
@ -2487,6 +2494,7 @@ nct.org.uk: max-age too low: 1
|
|||
nctx.co.uk: did not receive HSTS header
|
||||
near.st: did not receive HSTS header
|
||||
neftaly.com: did not receive HSTS header
|
||||
negai.moe: could not connect to host
|
||||
negativecurvature.net: could not connect to host
|
||||
neko-life.com: did not receive HSTS header
|
||||
neko-system.com: did not receive HSTS header
|
||||
|
@ -2540,6 +2548,7 @@ nikksno.io: did not receive HSTS header
|
|||
nikomo.fi: could not connect to host
|
||||
ninchisho-online.com: did not receive HSTS header
|
||||
ninhs.org: could not connect to host
|
||||
ninux.ch: did not receive HSTS header
|
||||
nippler.org: did not receive HSTS header
|
||||
nippombashi.net: did not receive HSTS header
|
||||
nipponcareers.com: did not receive HSTS header
|
||||
|
@ -2628,7 +2637,7 @@ okok-rent.com: could not connect to host
|
|||
okok.rent: could not connect to host
|
||||
okutama.in.th: could not connect to host
|
||||
olafnorge.de: could not connect to host
|
||||
oliver-pietsch.de: did not receive HSTS header
|
||||
oliveraiedelabastideblanche.fr: could not connect to host
|
||||
oliverdunk.com: did not receive HSTS header
|
||||
ollehbizev.co.kr: could not connect to host
|
||||
ollie.io: did not receive HSTS header
|
||||
|
@ -2637,7 +2646,6 @@ ominto.com: max-age too low: 0
|
|||
omniasl.com: could not connect to host
|
||||
omniti.com: max-age too low: 1
|
||||
omquote.gq: could not connect to host
|
||||
omskit.ru: could not connect to host
|
||||
oneb4nk.com: could not connect to host
|
||||
onefour.co: could not connect to host
|
||||
oneminute.io: did not receive HSTS header
|
||||
|
@ -2719,7 +2727,6 @@ owncloud.help: could not connect to host
|
|||
ownmovies.fr: could not connect to host
|
||||
oxygenabsorbers.com: did not receive HSTS header
|
||||
oxynux.fr: could not connect to host
|
||||
p-s-b.com: could not connect to host
|
||||
p.linode.com: could not connect to host
|
||||
p8r.de: did not receive HSTS header
|
||||
pa.search.yahoo.com: did not receive HSTS header
|
||||
|
@ -2737,6 +2744,7 @@ panaceallc.net: could not connect to host
|
|||
pantsu.cat: did not receive HSTS header
|
||||
papeda.net: did not receive HSTS header
|
||||
papercard.co.uk: did not receive HSTS header
|
||||
paperwork.co.za: could not connect to host
|
||||
papierniak.net: could not connect to host
|
||||
papygeek.com: could not connect to host
|
||||
parent5446.us: could not connect to host
|
||||
|
@ -2809,6 +2817,7 @@ pharmgkb.org: could not connect to host
|
|||
philpropertygroup.com: could not connect to host
|
||||
phonenumberinfo.co.uk: could not connect to host
|
||||
phongmay24h.com: could not connect to host
|
||||
photoancestry.com: did not receive HSTS header
|
||||
phpfashion.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
phurl.de: could not connect to host
|
||||
picallo.es: could not connect to host
|
||||
|
@ -2823,7 +2832,7 @@ pinesandneedles.com: did not receive HSTS header
|
|||
pippen.io: could not connect to host
|
||||
piratedb.com: could not connect to host
|
||||
piratedot.com: could not connect to host
|
||||
piratelist.online: could not connect to host
|
||||
piratelist.online: did not receive HSTS header
|
||||
piratenlogin.de: could not connect to host
|
||||
pirati.cz: max-age too low: 604800
|
||||
pirlitu.com: did not receive HSTS header
|
||||
|
@ -2849,7 +2858,7 @@ playnation.io: did not receive HSTS header
|
|||
pleier-it.de: did not receive HSTS header
|
||||
pleier.it: did not receive HSTS header
|
||||
plhdb.org: did not receive HSTS header
|
||||
plixer.com: could not connect to host
|
||||
plixer.com: did not receive HSTS header
|
||||
plogable.co: could not connect to host
|
||||
plothost.com: did not receive HSTS header
|
||||
ploup.net: could not connect to host
|
||||
|
@ -2874,7 +2883,6 @@ postcodewise.co.uk: did not receive HSTS header
|
|||
posterspy.com: did not receive HSTS header
|
||||
postscheduler.org: could not connect to host
|
||||
posylka.de: did not receive HSTS header
|
||||
potatofrom.space: could not connect to host
|
||||
poussinooz.fr: could not connect to host
|
||||
povitria.net: could not connect to host
|
||||
power-of-interest.com: did not receive HSTS header
|
||||
|
@ -2890,9 +2898,11 @@ prego-shop.de: did not receive HSTS header
|
|||
preissler.co.uk: could not connect to host
|
||||
prelist.org: did not receive HSTS header
|
||||
pressfreedomfoundation.org: did not receive HSTS header
|
||||
pretzlaff.info: could not connect to host
|
||||
preworkout.me: could not connect to host
|
||||
prezola.com: did not receive HSTS header
|
||||
princesparktouch.com: could not connect to host
|
||||
printexpress.cloud: did not receive HSTS header
|
||||
printfn.com: could not connect to host
|
||||
priolkar.com: did not receive HSTS header
|
||||
priva.si: could not connect to host
|
||||
|
@ -2919,7 +2929,8 @@ proximato.com: could not connect to host
|
|||
proxybay.al: could not connect to host
|
||||
proxybay.club: could not connect to host
|
||||
proxybay.info: did not receive HSTS header
|
||||
prxio.site: could not connect to host
|
||||
prxio.date: could not connect to host
|
||||
prxio.site: did not receive HSTS header
|
||||
prytkov.com: did not receive HSTS header
|
||||
psw.academy: did not receive HSTS header
|
||||
psw.consulting: did not receive HSTS header
|
||||
|
@ -2929,7 +2940,6 @@ puhe.se: could not connect to host
|
|||
puiterwijk.org: could not connect to host
|
||||
pumpgames.net: could not connect to host
|
||||
punchr-kamikazee.rhcloud.com: did not receive HSTS header
|
||||
pupboss.com: could not connect to host
|
||||
purewebmasters.com: could not connect to host
|
||||
purplemoon.mobi: did not receive HSTS header
|
||||
purplestar.mobi: did not receive HSTS header
|
||||
|
@ -2994,7 +3004,7 @@ realmic.net: could not connect to host
|
|||
realmofespionage.com: could not connect to host
|
||||
reardenporn.com: could not connect to host
|
||||
recommended.reviews: could not connect to host
|
||||
redar.xyz: could not connect to host
|
||||
redar.xyz: did not receive HSTS header
|
||||
reddiseals.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
reddit.com: did not receive HSTS header
|
||||
rede.ca: did not receive HSTS header
|
||||
|
@ -3010,7 +3020,6 @@ reggae-cdmx.com: did not receive HSTS header
|
|||
reic.me: could not connect to host
|
||||
rejo.in: could not connect to host
|
||||
rejuvemedspa.com: did not receive HSTS header
|
||||
relayawards.com: did not receive HSTS header
|
||||
relisten.nl: did not receive HSTS header
|
||||
rem.pe: could not connect to host
|
||||
remitatm.com: could not connect to host
|
||||
|
@ -3046,6 +3055,7 @@ richiemail.net: did not receive HSTS header
|
|||
richmondsunlight.com: did not receive HSTS header
|
||||
rid-wan.com: could not connect to host
|
||||
rideworks.com: did not receive HSTS header
|
||||
riesenweber.id.au: did not receive HSTS header
|
||||
right2.org: could not connect to host
|
||||
righttoknow.ie: did not receive HSTS header
|
||||
rijndael.xyz: could not connect to host
|
||||
|
@ -3061,7 +3071,6 @@ rme.li: did not receive HSTS header
|
|||
roan24.pl: did not receive HSTS header
|
||||
robertglastra.com: could not connect to host
|
||||
robigalia.org: did not receive HSTS header
|
||||
robohash.org: could not connect to host
|
||||
robtex.com: did not receive HSTS header
|
||||
robtex.net: did not receive HSTS header
|
||||
robtex.org: did not receive HSTS header
|
||||
|
@ -3072,6 +3081,7 @@ rodney.id.au: did not receive HSTS header
|
|||
rodosto.com: did not receive HSTS header
|
||||
roeper.party: could not connect to host
|
||||
roesemann.email: could not connect to host
|
||||
roessner-network-solutions.com: could not connect to host
|
||||
rohlik.cz: could not connect to host
|
||||
rolemaster.net: could not connect to host
|
||||
romans-place.me.uk: did not receive HSTS header
|
||||
|
@ -3185,7 +3195,6 @@ search-one.de: did not receive HSTS header
|
|||
sebastian-lutsch.de: could not connect to host
|
||||
sebster.com: did not receive HSTS header
|
||||
secandtech.com: could not connect to host
|
||||
secondpay.nl: did not receive HSTS header
|
||||
secpatrol.de: could not connect to host
|
||||
sectia22.ro: could not connect to host
|
||||
sectun.com: did not receive HSTS header
|
||||
|
@ -3200,6 +3209,7 @@ securityinet.net: did not receive HSTS header
|
|||
securityinet.org.il: did not receive HSTS header
|
||||
securitysoapbox.com: could not connect to host
|
||||
securiviera.ch: did not receive HSTS header
|
||||
sedrubal.de: could not connect to host
|
||||
seedbox.fr: did not receive HSTS header
|
||||
seele.ca: could not connect to host
|
||||
segulink.com: could not connect to host
|
||||
|
@ -3273,7 +3283,6 @@ sifls.com: could not connect to host
|
|||
silentcircle.org: could not connect to host
|
||||
silicagelpackets.ca: did not receive HSTS header
|
||||
silver-drachenkrieger.de: did not receive HSTS header
|
||||
silverhome.ninja: could not connect to host
|
||||
silverpvp.com: could not connect to host
|
||||
silverwind.io: did not receive HSTS header
|
||||
simbast.com: could not connect to host
|
||||
|
@ -3289,6 +3298,7 @@ simply-premium.com: max-age too low: 0
|
|||
sincron.org: could not connect to host
|
||||
siriad.com: did not receive HSTS header
|
||||
sirius-lee.net: could not connect to host
|
||||
sitennisclub.com: did not receive HSTS header
|
||||
sites.google.com: did not receive HSTS header (error ignored - included regardless)
|
||||
sitesten.com: did not receive HSTS header
|
||||
sitsy.ru: did not receive HSTS header
|
||||
|
@ -3340,7 +3350,7 @@ sobotkama.eu: did not receive HSTS header
|
|||
soccergif.com: could not connect to host
|
||||
soci.ml: did not receive HSTS header
|
||||
socialbillboard.com: could not connect to host
|
||||
socialdevelop.biz: could not connect to host
|
||||
socialdevelop.biz: did not receive HSTS header
|
||||
socialhams.net: did not receive HSTS header
|
||||
socialhead.io: could not connect to host
|
||||
socialspirit.com.br: did not receive HSTS header
|
||||
|
@ -3466,6 +3476,7 @@ stugb.de: did not receive HSTS header
|
|||
stw-group.at: could not connect to host
|
||||
subbing.work: could not connect to host
|
||||
subdimension.org: could not connect to host
|
||||
subeesu.com: could not connect to host
|
||||
subrosa.io: could not connect to host
|
||||
subtitle.rip: could not connect to host
|
||||
sudo.li: did not receive HSTS header
|
||||
|
@ -3475,9 +3486,9 @@ suksit.com: could not connect to host
|
|||
sumoatm.com: did not receive HSTS header
|
||||
sumoscout.de: did not receive HSTS header
|
||||
suncountrymarine.com: did not receive HSTS header
|
||||
sunflyer.cn: did not receive HSTS header
|
||||
sunnyfruit.ru: did not receive HSTS header
|
||||
sunshinepress.org: could not connect to host
|
||||
sunyanzi.tk: could not connect to host
|
||||
superbabysitting.ch: could not connect to host
|
||||
superbike.tw: could not connect to host
|
||||
supereight.net: did not receive HSTS header
|
||||
|
@ -3508,7 +3519,6 @@ synackr.com: could not connect to host
|
|||
syncer.jp: did not receive HSTS header
|
||||
syncserve.net: did not receive HSTS header
|
||||
syneic.com: did not receive HSTS header
|
||||
synfin.org: could not connect to host
|
||||
syno.gq: could not connect to host
|
||||
syntheticmotoroil.org: did not receive HSTS header
|
||||
syso.name: could not connect to host
|
||||
|
@ -3556,7 +3566,6 @@ tcp.expert: did not receive HSTS header
|
|||
teachforcanada.ca: did not receive HSTS header
|
||||
team-pancake.eu: could not connect to host
|
||||
teamsocial.co: did not receive HSTS header
|
||||
teamx-gaming.de: could not connect to host
|
||||
teamzeus.cz: could not connect to host
|
||||
techassist.io: did not receive HSTS header
|
||||
techhipster.net: could not connect to host
|
||||
|
@ -3567,6 +3576,7 @@ techmatehq.com: could not connect to host
|
|||
technosavvyport.com: did not receive HSTS header
|
||||
techpointed.com: could not connect to host
|
||||
techvalue.gr: did not receive HSTS header
|
||||
tedovo.com: could not connect to host
|
||||
tegelsensanitaironline.nl: did not receive HSTS header
|
||||
tekshrek.com: did not receive HSTS header
|
||||
telefonnummer.online: could not connect to host
|
||||
|
@ -3592,6 +3602,7 @@ tfl.lu: did not receive HSTS header
|
|||
tgr.re: could not connect to host
|
||||
th-bl.de: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
thai.land: could not connect to host
|
||||
thaianthro.com: did not receive HSTS header
|
||||
the-construct.com: could not connect to host
|
||||
the-sky-of-valkyries.com: could not connect to host
|
||||
theamateurs.net: did not receive HSTS header
|
||||
|
@ -3681,6 +3692,7 @@ tokyopopline.com: did not receive HSTS header
|
|||
tollmanz.com: did not receive HSTS header
|
||||
tom.horse: did not receive HSTS header
|
||||
tomberek.info: could not connect to host
|
||||
tomcort.com: could not connect to host
|
||||
tomeara.net: could not connect to host
|
||||
tomharling.co.uk: max-age too low: 86400
|
||||
tomharling.uk: max-age too low: 86400
|
||||
|
@ -3713,7 +3725,6 @@ translate.googleapis.com: did not receive HSTS header (error ignored - included
|
|||
transportal.sk: did not receive HSTS header
|
||||
treeby.net: could not connect to host
|
||||
trendberry.ru: could not connect to host
|
||||
trik.es: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
trinityaffirmations.com: max-age too low: 0
|
||||
trinitycore.org: max-age too low: 2592000
|
||||
tripdelta.com: did not receive HSTS header
|
||||
|
@ -3766,6 +3777,7 @@ ubuntuhot.com: did not receive HSTS header
|
|||
uega.net: did not receive HSTS header
|
||||
ufgaming.com: did not receive HSTS header
|
||||
ufotable.uk: max-age too low: 0
|
||||
uhm.io: did not receive HSTS header
|
||||
ui8.net: max-age too low: 86400
|
||||
ukas.com: did not receive HSTS header
|
||||
ukdropshipment.co.uk: did not receive HSTS header
|
||||
|
@ -3880,7 +3892,6 @@ vlora.city: could not connect to host
|
|||
vm0.eu: did not receive HSTS header
|
||||
vmrdev.com: could not connect to host
|
||||
voceinveste.com: did not receive HSTS header
|
||||
vogler.name: could not connect to host
|
||||
voicesuk.co.uk: did not receive HSTS header
|
||||
volcrado.com: could not connect to host
|
||||
voliere-info.nl: did not receive HSTS header
|
||||
|
@ -3922,7 +3933,6 @@ wealthfactory.com: [Exception... "Component returned failure code: 0x80004005 (N
|
|||
wear2work.nl: did not receive HSTS header
|
||||
wearandcare.net: could not connect to host
|
||||
weaverhairextensions.nl: could not connect to host
|
||||
web-vision.de: could not connect to host
|
||||
web4all.fr: max-age too low: 0
|
||||
web4pro.fr: max-age too low: 0
|
||||
webandwords.com.au: could not connect to host
|
||||
|
@ -4105,6 +4115,7 @@ yabrt.cn: could not connect to host
|
|||
yamaken.jp: did not receive HSTS header
|
||||
yamamo10.com: could not connect to host
|
||||
yanaduday.com: could not connect to host
|
||||
yanwh.xyz: could not connect to host
|
||||
yaporn.tv: did not receive HSTS header
|
||||
yard-fu.com: could not connect to host
|
||||
yasinaydin.net: max-age too low: 2592000
|
||||
|
@ -4133,7 +4144,6 @@ youcontrol.ru: could not connect to host
|
|||
youngandunited.nl: did not receive HSTS header
|
||||
yourstrongbox.com: could not connect to host
|
||||
yout.com: max-age too low: 60000
|
||||
ypid.de: could not connect to host
|
||||
ytec.ca: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no]
|
||||
yu.gg: did not receive HSTS header
|
||||
yuan.ga: did not receive HSTS header
|
||||
|
@ -4154,7 +4164,6 @@ zadieheimlich.com: did not receive HSTS header
|
|||
zamorano.edu: could not connect to host
|
||||
zap.yt: could not connect to host
|
||||
zarooba.com: did not receive HSTS header
|
||||
zberger.com: could not connect to host
|
||||
zbigniewgalucki.eu: did not receive HSTS header
|
||||
zbp.at: did not receive HSTS header
|
||||
zebrababy.cn: did not receive HSTS header
|
||||
|
@ -4171,6 +4180,7 @@ zera.com.au: could not connect to host
|
|||
zett4.me: could not connect to host
|
||||
zeytin.pro: could not connect to host
|
||||
zh.search.yahoo.com: did not receive HSTS header
|
||||
zhaochen.xyz: could not connect to host
|
||||
zhaojin97.cn: did not receive HSTS header
|
||||
zhendingresources.com: max-age too low: 0
|
||||
zicklam.com: could not connect to host
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -325,10 +325,9 @@ static const char contentSandboxRules[] =
|
|||
"\n"
|
||||
" (allow-shared-list \"org.mozilla.plugincontainer\")\n"
|
||||
"\n"
|
||||
"; the following 2 rules should be removed when microphone and camera access\n"
|
||||
"; are brokered through the content process\n"
|
||||
"; the following rule should be removed when microphone access\n"
|
||||
"; is brokered through the content process\n"
|
||||
" (allow device-microphone)\n"
|
||||
" (allow device-camera)\n"
|
||||
"\n"
|
||||
" (allow file* (var-folders2-regex \"/com\\.apple\\.IntlDataCache\\.le$\"))\n"
|
||||
" (allow file-read*\n"
|
||||
|
|
|
@ -19,7 +19,7 @@ scopes:
|
|||
# Bug 1269443: cache scopes, etc. must be listed explicitly
|
||||
- "docker-worker:cache:tooltool-cache"
|
||||
- "secrets:get:project/taskcluster/gecko/hgfingerprint"
|
||||
- "assume:repo:hg.mozilla.org/{{project}}:*"
|
||||
- {{repo_scope}}
|
||||
|
||||
routes:
|
||||
- "tc-treeherder.v2.{{project}}.{{head_rev}}.{{pushlog_id}}"
|
||||
|
|
|
@ -8,6 +8,7 @@ from __future__ import absolute_import, print_function, unicode_literals
|
|||
import os
|
||||
import json
|
||||
import logging
|
||||
import re
|
||||
|
||||
import time
|
||||
import yaml
|
||||
|
@ -178,10 +179,17 @@ def write_artifact(filename, data):
|
|||
def get_action_yml(parameters):
|
||||
templates = Templates(os.path.join(GECKO, "taskcluster/taskgraph"))
|
||||
action_parameters = parameters.copy()
|
||||
|
||||
match = re.match(r'https://(hg.mozilla.org)/(.*?)/?$', action_parameters['head_repository'])
|
||||
if not match:
|
||||
raise Exception('Unrecognized head_repository')
|
||||
repo_scope = 'assume:repo:{}/{}:*'.format(
|
||||
match.group(1), match.group(2))
|
||||
|
||||
action_parameters.update({
|
||||
"action": "{{action}}",
|
||||
"action_args": "{{action_args}}",
|
||||
"project": parameters["project"],
|
||||
"repo_scope": repo_scope,
|
||||
"from_now": json_time_from_now,
|
||||
"now": current_json_time()
|
||||
})
|
||||
|
|
|
@ -75,6 +75,24 @@ def validate_schema(schema, obj, msg_prefix):
|
|||
raise Exception('\n'.join(msg) + '\n' + pprint.pformat(obj))
|
||||
|
||||
|
||||
def optionally_keyed_by(*arguments):
|
||||
"""
|
||||
Mark a schema value as optionally keyed by any of a number of fields. The
|
||||
schema is the last argument, and the remaining fields are taken to be the
|
||||
field names. For example:
|
||||
|
||||
'some-value': optionally_keyed_by(
|
||||
'test-platform', 'build-platform',
|
||||
Any('a', 'b', 'c'))
|
||||
"""
|
||||
subschema = arguments[-1]
|
||||
fields = arguments[:-1]
|
||||
options = [subschema]
|
||||
for field in fields:
|
||||
options.append({'by-' + field: {basestring: subschema}})
|
||||
return voluptuous.Any(*options)
|
||||
|
||||
|
||||
def get_keyed_by(item, field, item_name, subfield=None):
|
||||
"""
|
||||
For values which can either accept a literal value, or be keyed by some
|
||||
|
|
|
@ -40,3 +40,11 @@ def set_treeherder_machine_platform(config, tests):
|
|||
build_platform = test['build-platform']
|
||||
test['treeherder-machine-platform'] = translation.get(build_platform, build_platform)
|
||||
yield test
|
||||
|
||||
|
||||
@transforms.add
|
||||
def set_e10s_attr(config, tests):
|
||||
"""Set the e10s attribute to false"""
|
||||
for test in tests:
|
||||
test.setdefault('attributes', {})['e10s'] = False
|
||||
yield test
|
||||
|
|
|
@ -95,9 +95,9 @@ def split_e10s(config, tests):
|
|||
def allow_software_gl_layers(config, tests):
|
||||
for test in tests:
|
||||
|
||||
# since this value defaults to true, but is not applicable on windows,
|
||||
# since this value defaults to true, but is not applicable on non-linux,
|
||||
# it's overriden for that platform here.
|
||||
allow = not test['test-platform'].startswith('win') \
|
||||
allow = test['test-platform'].startswith('linux') \
|
||||
and get_keyed_by(item=test, field='allow-software-gl-layers',
|
||||
item_name=test['test-name'])
|
||||
if allow:
|
||||
|
|
|
@ -9,7 +9,7 @@ transforms do not generate invalid tests.
|
|||
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
|
||||
from taskgraph.transforms.base import validate_schema
|
||||
from taskgraph.transforms.base import validate_schema, optionally_keyed_by
|
||||
from voluptuous import (
|
||||
Any,
|
||||
Optional,
|
||||
|
@ -32,10 +32,7 @@ test_description_schema = Schema({
|
|||
'description': basestring,
|
||||
|
||||
# test suite name, or <suite>/<flavor>
|
||||
Required('suite'): Any(
|
||||
basestring,
|
||||
{'by-test-platform': {basestring: basestring}},
|
||||
),
|
||||
Required('suite'): optionally_keyed_by('test-platform', basestring),
|
||||
|
||||
# the name by which this test suite is addressed in try syntax; defaults to
|
||||
# the test-name
|
||||
|
@ -60,10 +57,9 @@ test_description_schema = Schema({
|
|||
# The `run_on_projects` attribute, defaulting to "all". This dictates the
|
||||
# projects on which this task should be included in the target task set.
|
||||
# See the attributes documentation for details.
|
||||
Optional('run-on-projects', default=['all']): Any(
|
||||
[basestring],
|
||||
{'by-test-platform': {basestring: [basestring]}},
|
||||
),
|
||||
Optional('run-on-projects', default=['all']): optionally_keyed_by(
|
||||
'test-platform',
|
||||
[basestring]),
|
||||
|
||||
# the sheriffing tier for this task (default: set based on test platform)
|
||||
Optional('tier'): Any(
|
||||
|
@ -74,10 +70,7 @@ test_description_schema = Schema({
|
|||
# number of chunks to create for this task. This can be keyed by test
|
||||
# platform by passing a dictionary in the `by-test-platform` key. If the
|
||||
# test platform is not found, the key 'default' will be tried.
|
||||
Required('chunks', default=1): Any(
|
||||
int,
|
||||
{'by-test-platform': {basestring: int}},
|
||||
),
|
||||
Required('chunks', default=1): optionally_keyed_by('test-platform', int),
|
||||
|
||||
# the time (with unit) after which this task is deleted; default depends on
|
||||
# the branch (see below)
|
||||
|
@ -87,16 +80,14 @@ test_description_schema = Schema({
|
|||
# without e10s; if true, run with e10s; if 'both', run one task with and
|
||||
# one task without e10s. E10s tasks have "-e10s" appended to the test name
|
||||
# and treeherder group.
|
||||
Required('e10s', default='both'): Any(
|
||||
bool, 'both',
|
||||
{'by-test-platform': {basestring: Any(bool, 'both')}},
|
||||
),
|
||||
Required('e10s', default='both'): optionally_keyed_by(
|
||||
'test-platform',
|
||||
Any(bool, 'both')),
|
||||
|
||||
# The EC2 instance size to run these tests on.
|
||||
Required('instance-size', default='default'): Any(
|
||||
Any('default', 'large', 'xlarge', 'legacy'),
|
||||
{'by-test-platform': {basestring: Any('default', 'large', 'xlarge', 'legacy')}},
|
||||
),
|
||||
Required('instance-size', default='default'): optionally_keyed_by(
|
||||
'test-platform',
|
||||
Any('default', 'large', 'xlarge', 'legacy')),
|
||||
|
||||
# Whether the task requires loopback audio or video (whatever that may mean
|
||||
# on the platform)
|
||||
|
@ -132,10 +123,7 @@ test_description_schema = Schema({
|
|||
|
||||
# seconds of runtime after which the task will be killed. Like 'chunks',
|
||||
# this can be keyed by test pltaform.
|
||||
Required('max-run-time', default=3600): Any(
|
||||
int,
|
||||
{'by-test-platform': {basestring: int}},
|
||||
),
|
||||
Required('max-run-time', default=3600): optionally_keyed_by('test-platform', int),
|
||||
|
||||
# the exit status code that indicates the task should be retried
|
||||
Optional('retry-exit-status'): int,
|
||||
|
@ -149,20 +137,16 @@ test_description_schema = Schema({
|
|||
Required('script'): basestring,
|
||||
|
||||
# the config files required for the task
|
||||
Required('config'): Any(
|
||||
[basestring],
|
||||
{'by-test-platform': {basestring: [basestring]}},
|
||||
),
|
||||
Required('config'): optionally_keyed_by('test-platform', [basestring]),
|
||||
|
||||
# any additional actions to pass to the mozharness command
|
||||
Optional('actions'): [basestring],
|
||||
|
||||
# additional command-line options for mozharness, beyond those
|
||||
# automatically added
|
||||
Required('extra-options', default=[]): Any(
|
||||
[basestring],
|
||||
{'by-test-platform': {basestring: [basestring]}},
|
||||
),
|
||||
Required('extra-options', default=[]): optionally_keyed_by(
|
||||
'test-platform',
|
||||
[basestring]),
|
||||
|
||||
# the artifact name (including path) to test on the build task; this is
|
||||
# generally set in a per-kind transformation
|
||||
|
@ -211,11 +195,9 @@ test_description_schema = Schema({
|
|||
|
||||
# os user groups for test task workers; required scopes, will be
|
||||
# added automatically
|
||||
Optional('os-groups', default=[]): Any(
|
||||
[basestring],
|
||||
# todo: create a dedicated elevated worker group and name here
|
||||
{'by-test-platform': {basestring: [basestring]}},
|
||||
),
|
||||
Optional('os-groups', default=[]): optionally_keyed_by(
|
||||
'test-platform',
|
||||
[basestring]),
|
||||
|
||||
# -- values supplied by the task-generation infrastructure
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
|
||||
#include <shlwapi.h>
|
||||
|
||||
PRLogModuleInfo* gWindowsLog = nullptr;
|
||||
mozilla::LazyLogModule gWindowsLog("Widget");
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
|
@ -462,9 +462,6 @@ static NtTestAlertPtr sNtTestAlert = nullptr;
|
|||
void
|
||||
WinUtils::Initialize()
|
||||
{
|
||||
if (!gWindowsLog) {
|
||||
gWindowsLog = PR_NewLogModule("Widget");
|
||||
}
|
||||
if (!sDwmDll && IsVistaOrLater()) {
|
||||
sDwmDll = ::LoadLibraryW(kDwmLibraryName);
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/gfx/PrintTargetPDF.h"
|
||||
#include "mozilla/gfx/PrintTargetWindows.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
|
||||
#include "nsDeviceContextSpecWin.h"
|
||||
|
@ -34,7 +35,7 @@
|
|||
#include "mozilla/gfx/Logging.h"
|
||||
|
||||
#include "mozilla/Logging.h"
|
||||
PRLogModuleInfo * kWidgetPrintingLogMod = PR_NewLogModule("printing-widget");
|
||||
static mozilla::LazyLogModule kWidgetPrintingLogMod("printing-widget");
|
||||
#define PR_PL(_p1) MOZ_LOG(kWidgetPrintingLogMod, mozilla::LogLevel::Debug, _p1)
|
||||
|
||||
using namespace mozilla;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "nsNativeThemeWin.h"
|
||||
|
||||
#include "mozilla/EventStates.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/WindowsVersion.h"
|
||||
#include "nsDeviceContext.h"
|
||||
#include "nsRenderingContext.h"
|
||||
|
@ -42,7 +43,7 @@ using mozilla::IsVistaOrLater;
|
|||
using namespace mozilla;
|
||||
using namespace mozilla::widget;
|
||||
|
||||
extern PRLogModuleInfo* gWindowsLog;
|
||||
extern mozilla::LazyLogModule gWindowsLog;
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED(nsNativeThemeWin, nsNativeTheme, nsITheme)
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "nsUXThemeData.h"
|
||||
#include "nsIDOMSimpleGestureEvent.h"
|
||||
#include "nsIDOMWheelEvent.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/MouseEvents.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/TouchEvents.h"
|
||||
|
@ -21,7 +22,7 @@
|
|||
using namespace mozilla;
|
||||
using namespace mozilla::widget;
|
||||
|
||||
extern PRLogModuleInfo* gWindowsLog;
|
||||
extern mozilla::LazyLogModule gWindowsLog;
|
||||
|
||||
const wchar_t nsWinGesture::kGestureLibraryName[] = L"user32.dll";
|
||||
HMODULE nsWinGesture::sLibraryHandle = nullptr;
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
#include "gfxEnv.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "gfxPrefs.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
#include "mozilla/MiscEvents.h"
|
||||
#include "mozilla/MouseEvents.h"
|
||||
|
@ -453,7 +454,7 @@ StaticAutoPtr<TIPMessageHandler> TIPMessageHandler::sInstance;
|
|||
|
||||
static const char *sScreenManagerContractID = "@mozilla.org/gfx/screenmanager;1";
|
||||
|
||||
extern PRLogModuleInfo* gWindowsLog;
|
||||
extern mozilla::LazyLogModule gWindowsLog;
|
||||
|
||||
// Global used in Show window enumerations.
|
||||
static bool gWindowsVisible = false;
|
||||
|
|
|
@ -7,12 +7,13 @@
|
|||
* nsWindowDbg - Debug related utilities for nsWindow.
|
||||
*/
|
||||
|
||||
#include "mozilla/Logging.h"
|
||||
#include "nsWindowDbg.h"
|
||||
#include "WinUtils.h"
|
||||
|
||||
using namespace mozilla::widget;
|
||||
|
||||
extern PRLogModuleInfo* gWindowsLog;
|
||||
extern mozilla::LazyLogModule gWindowsLog;
|
||||
|
||||
#if defined(POPUP_ROLLUP_DEBUG_OUTPUT)
|
||||
MSGFEventMsgInfo gMSGFEvents[] = {
|
||||
|
|
Загрузка…
Ссылка в новой задаче