зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to autoland. a=merge CLOSED TREE
This commit is contained in:
Коммит
f63d10362d
|
@ -161,8 +161,8 @@ name = "baldrdash"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bindgen 0.43.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-codegen 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-wasm 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -352,6 +352,11 @@ dependencies = [
|
|||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cast"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.23"
|
||||
|
@ -480,20 +485,20 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cranelift-bforest"
|
||||
version = "0.25.0"
|
||||
version = "0.26.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cranelift-entity 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen"
|
||||
version = "0.25.0"
|
||||
version = "0.26.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cranelift-bforest 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-codegen-meta 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-entity 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-bforest 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-codegen-meta 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -502,35 +507,36 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-meta"
|
||||
version = "0.25.0"
|
||||
version = "0.26.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cranelift-entity 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-entity"
|
||||
version = "0.25.0"
|
||||
version = "0.26.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-frontend"
|
||||
version = "0.25.0"
|
||||
version = "0.26.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cranelift-codegen 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-wasm"
|
||||
version = "0.25.0"
|
||||
version = "0.26.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cranelift-codegen 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-entity 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-frontend 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-frontend 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -3199,6 +3205,7 @@ dependencies = [
|
|||
"checksum bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e178b8e0e239e844b083d5a0d4a156b2654e67f9f80144d48398fcd736a24fb8"
|
||||
"checksum bzip2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3eafc42c44e0d827de6b1c131175098fe7fb53b8ce8a47e65cb3ea94688be24"
|
||||
"checksum bzip2-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2c5162604199bbb17690ede847eaa6120a3f33d5ab4dcc8e7c25b16d849ae79b"
|
||||
"checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427"
|
||||
"checksum cc 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)" = "c37f0efaa4b9b001fa6f02d4b644dee4af97d3414df07c51e3e4f015f3a3e131"
|
||||
"checksum cexpr 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8fc0086be9ca82f7fc89fc873435531cb898b86e850005850de1f820e2db6e9b"
|
||||
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
|
||||
|
@ -3214,12 +3221,12 @@ dependencies = [
|
|||
"checksum core-text 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f3f46450d6f2397261af420b4ccce23807add2e45fa206410a03d66fb7f050ae"
|
||||
"checksum cose 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "72fa26cb151d3ae4b70f63d67d0fed57ce04220feafafbae7f503bef7aae590d"
|
||||
"checksum cose-c 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "49726015ab0ca765144fcca61e4a7a543a16b795a777fa53f554da2fffff9a94"
|
||||
"checksum cranelift-bforest 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b2d527b241af388ff017d72f2b0b323929a70cf97342c6ec1534e3b0f4dfaa0"
|
||||
"checksum cranelift-codegen 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e92fa0fa287cf00a6739c46aba114957e0a8eeeb4f0d1aa65d6ed0699c34ca6b"
|
||||
"checksum cranelift-codegen-meta 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "963262697a05d9aa63ca40f4670a7243e4525f4a098e10d654c3f5143fcef686"
|
||||
"checksum cranelift-entity 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc9a0329208e5e0d7d4d6e64cd50985d4c4cbfdbeeb594ae2157a094b98e8dcc"
|
||||
"checksum cranelift-frontend 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98d9eb4a2343435d520499236c805725c88d6d55eefb9a6ad0819b7970c76bdd"
|
||||
"checksum cranelift-wasm 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5022a3a3d1044fdc8c97909b5e8d701884982dcfb43885034d004cfdd9b7d577"
|
||||
"checksum cranelift-bforest 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "40f8ff24e9a6c89b8a846b14df9a34d2cac17cea7bdb5c81ed6b4744ee0e38bf"
|
||||
"checksum cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "42f5b809bd885c368e01aeec8fe04f21dcb07569834b907d75b4a7bed8d067eb"
|
||||
"checksum cranelift-codegen-meta 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "014c23ed3ebdc8377d41540af638245207dd169f421df042dfccc867465734ed"
|
||||
"checksum cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4df40e26c0cf7b4d86919cb995bb412ee3001cc18e4f3c83a903f30b7007d8b"
|
||||
"checksum cranelift-frontend 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "789907218eeebebcea8122c2053d71affac91c96ce72cea35ebfdbbf547e82af"
|
||||
"checksum cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49723365dab9a48b354bdc24cb6d9d5719bc1d3b858ffd2ea179d0d7d885804a"
|
||||
"checksum crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd5d02c0aac6bd68393ed69e00bbc2457f3e89075c6349db7189618dc4ddc1d7"
|
||||
"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
|
||||
"checksum crossbeam-deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fe8153ef04a7594ded05b427ffad46ddeaf22e63fd48d42b3e1e3bb4db07cae7"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
This is the PDF.js project output, https://github.com/mozilla/pdf.js
|
||||
|
||||
Current extension version is: 2.1.145
|
||||
Current extension version is: 2.1.153
|
||||
|
||||
Taken from upstream commit: d8f201ea
|
||||
Taken from upstream commit: 5a2bd9fc
|
||||
|
|
|
@ -123,8 +123,8 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
"use strict";
|
||||
|
||||
|
||||
var pdfjsVersion = '2.1.145';
|
||||
var pdfjsBuild = 'd8f201ea';
|
||||
var pdfjsVersion = '2.1.153';
|
||||
var pdfjsBuild = '5a2bd9fc';
|
||||
|
||||
var pdfjsSharedUtil = __w_pdfjs_require__(1);
|
||||
|
||||
|
@ -5154,7 +5154,7 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) {
|
|||
|
||||
return worker.messageHandler.sendWithPromise('GetDocRequest', {
|
||||
docId,
|
||||
apiVersion: '2.1.145',
|
||||
apiVersion: '2.1.153',
|
||||
source: {
|
||||
data: source.data,
|
||||
url: source.url,
|
||||
|
@ -6885,9 +6885,9 @@ const InternalRenderTask = function InternalRenderTaskClosure() {
|
|||
return InternalRenderTask;
|
||||
}();
|
||||
|
||||
const version = '2.1.145';
|
||||
const version = '2.1.153';
|
||||
exports.version = version;
|
||||
const build = 'd8f201ea';
|
||||
const build = '5a2bd9fc';
|
||||
exports.build = build;
|
||||
|
||||
/***/ }),
|
||||
|
@ -10978,12 +10978,18 @@ class SimpleDOMNode {
|
|||
}
|
||||
|
||||
get firstChild() {
|
||||
return this.childNodes[0];
|
||||
return this.childNodes && this.childNodes[0];
|
||||
}
|
||||
|
||||
get nextSibling() {
|
||||
let index = this.parentNode.childNodes.indexOf(this);
|
||||
return this.parentNode.childNodes[index + 1];
|
||||
const childNodes = this.parentNode.childNodes;
|
||||
|
||||
if (!childNodes) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const index = childNodes.indexOf(this);
|
||||
return childNodes[index + 1];
|
||||
}
|
||||
|
||||
get textContent() {
|
||||
|
|
|
@ -123,8 +123,8 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
"use strict";
|
||||
|
||||
|
||||
var pdfjsVersion = '2.1.145';
|
||||
var pdfjsBuild = 'd8f201ea';
|
||||
var pdfjsVersion = '2.1.153';
|
||||
var pdfjsBuild = '5a2bd9fc';
|
||||
|
||||
var pdfjsCoreWorker = __w_pdfjs_require__(1);
|
||||
|
||||
|
@ -375,7 +375,7 @@ var WorkerMessageHandler = {
|
|||
var cancelXHRs = null;
|
||||
var WorkerTasks = [];
|
||||
let apiVersion = docParams.apiVersion;
|
||||
let workerVersion = '2.1.145';
|
||||
let workerVersion = '2.1.153';
|
||||
|
||||
if (apiVersion !== workerVersion) {
|
||||
throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`);
|
||||
|
@ -6947,8 +6947,8 @@ class PDFDocument {
|
|||
|
||||
let fingerprint = '';
|
||||
|
||||
for (const hashPart of hash) {
|
||||
const hex = hashPart.toString(16);
|
||||
for (let i = 0, ii = hash.length; i < ii; i++) {
|
||||
const hex = hash[i].toString(16);
|
||||
fingerprint += hex.length === 1 ? '0' + hex : hex;
|
||||
}
|
||||
|
||||
|
@ -31088,6 +31088,13 @@ var CFFParser = function CFFParserClosure() {
|
|||
if (validationCommand) {
|
||||
if (validationCommand.stem) {
|
||||
state.hints += stackSize >> 1;
|
||||
|
||||
if (value === 3 || value === 23) {
|
||||
state.hasVStems = true;
|
||||
} else if (state.hasVStems && (value === 1 || value === 18)) {
|
||||
(0, _util.warn)('CFF stem hints are in wrong order');
|
||||
data[j - 1] = value === 1 ? 3 : 23;
|
||||
}
|
||||
}
|
||||
|
||||
if ('min' in validationCommand) {
|
||||
|
@ -31157,7 +31164,8 @@ var CFFParser = function CFFParserClosure() {
|
|||
hints: 0,
|
||||
firstStackClearing: true,
|
||||
seac: null,
|
||||
width: null
|
||||
width: null,
|
||||
hasVStems: false
|
||||
};
|
||||
var valid = true;
|
||||
var localSubrToUse = null;
|
||||
|
|
|
@ -20,7 +20,7 @@ origin:
|
|||
|
||||
# Human-readable identifier for this version/release
|
||||
# Generally "version NNN", "tag SSS", "bookmark SSS"
|
||||
release: version 2.1.145
|
||||
release: version 2.1.153
|
||||
|
||||
# The package's license, where possible using the mnemonic from
|
||||
# https://spdx.org/licenses/
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
This is the debugger.html project output.
|
||||
See https://github.com/devtools-html/debugger.html
|
||||
|
||||
Version 116
|
||||
Version 117
|
||||
|
||||
Comparison: https://github.com/devtools-html/debugger.html/compare/release-115...release-116
|
||||
Comparison: https://github.com/devtools-html/debugger.html/compare/release-116...release-117
|
||||
|
||||
Packages:
|
||||
- babel-plugin-transform-es2015-modules-commonjs @6.26.2
|
||||
|
|
|
@ -40,7 +40,7 @@ function createOriginalSource(
|
|||
url: originalUrl,
|
||||
relativeUrl: originalUrl,
|
||||
id: generatedToOriginalId(generatedSource.id, originalUrl),
|
||||
thread: "",
|
||||
thread: generatedSource.thread,
|
||||
isPrettyPrinted: false,
|
||||
isWasm: false,
|
||||
isBlackBoxed: false,
|
||||
|
|
|
@ -9752,7 +9752,24 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
|
|||
nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA,
|
||||
&doesNotReturnData);
|
||||
if (doesNotReturnData) {
|
||||
return NS_ERROR_UNKNOWN_PROTOCOL;
|
||||
bool popupBlocked = true;
|
||||
|
||||
// Let's consider external protocols as popups and let's check if the page
|
||||
// is allowed to open them without abuse regardless of allowed events
|
||||
if (PopupBlocker::GetPopupControlState() <= PopupBlocker::openBlocked) {
|
||||
popupBlocked = !PopupBlocker::TryUsePopupOpeningToken();
|
||||
} else {
|
||||
nsCOMPtr<nsINode> loadingNode =
|
||||
mScriptGlobal->AsOuter()->GetFrameElementInternal();
|
||||
if (loadingNode) {
|
||||
popupBlocked = !PopupBlocker::CanShowPopupByPermission(
|
||||
loadingNode->NodePrincipal());
|
||||
}
|
||||
}
|
||||
|
||||
if (popupBlocked) {
|
||||
return NS_ERROR_UNKNOWN_PROTOCOL;
|
||||
}
|
||||
}
|
||||
|
||||
// Only allow view-source scheme in top-level docshells. view-source is
|
||||
|
|
|
@ -771,6 +771,35 @@ constexpr auto kSkipSelfHosted = JS::SavedFrameSelfHosted::Exclude;
|
|||
NS_ConvertUTF16toUTF8(aOrigin));
|
||||
}
|
||||
|
||||
/* static */ PopupBlockerState ChromeUtils::GetPopupControlState(
|
||||
GlobalObject& aGlobal) {
|
||||
switch (PopupBlocker::GetPopupControlState()) {
|
||||
case PopupBlocker::PopupControlState::openAllowed:
|
||||
return PopupBlockerState::OpenAllowed;
|
||||
|
||||
case PopupBlocker::PopupControlState::openControlled:
|
||||
return PopupBlockerState::OpenControlled;
|
||||
|
||||
case PopupBlocker::PopupControlState::openBlocked:
|
||||
return PopupBlockerState::OpenBlocked;
|
||||
|
||||
case PopupBlocker::PopupControlState::openAbused:
|
||||
return PopupBlockerState::OpenAbused;
|
||||
|
||||
case PopupBlocker::PopupControlState::openOverridden:
|
||||
return PopupBlockerState::OpenOverridden;
|
||||
|
||||
default:
|
||||
MOZ_CRASH(
|
||||
"PopupBlocker::PopupControlState and PopupBlockerState are out of "
|
||||
"sync");
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ bool ChromeUtils::IsPopupTokenUnused(GlobalObject& aGlobal) {
|
||||
return PopupBlocker::IsPopupOpeningTokenUnused();
|
||||
}
|
||||
|
||||
/* static */ void ChromeUtils::RegisterWindowActor(
|
||||
const GlobalObject& aGlobal, const nsAString& aName,
|
||||
const WindowActorOptions& aOptions, ErrorResult& aRv) {
|
||||
|
|
|
@ -174,6 +174,10 @@ class ChromeUtils {
|
|||
const nsAString& aOrigin,
|
||||
ErrorResult& aRv);
|
||||
|
||||
static PopupBlockerState GetPopupControlState(GlobalObject& aGlobal);
|
||||
|
||||
static bool IsPopupTokenUnused(GlobalObject& aGlobal);
|
||||
|
||||
static void RegisterWindowActor(const GlobalObject& aGlobal,
|
||||
const nsAString& aName,
|
||||
const WindowActorOptions& aOptions,
|
||||
|
|
|
@ -282,7 +282,6 @@
|
|||
|
||||
#include "mozilla/MediaManager.h"
|
||||
|
||||
#include "nsIURIClassifier.h"
|
||||
#include "nsIURIMutator.h"
|
||||
#include "mozilla/DocumentStyleRootIterator.h"
|
||||
#include "mozilla/PendingFullscreenEvent.h"
|
||||
|
@ -336,65 +335,6 @@ static nsresult GetHttpChannelHelper(nsIChannel* aChannel,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// PrincipalFlashClassifier
|
||||
|
||||
// Classify the flash based on the document principal.
|
||||
// The usage of this class is as follows:
|
||||
//
|
||||
// 1) Call AsyncClassify() as early as possible to asynchronously do
|
||||
// classification against all the flash blocking related tables
|
||||
// via nsIURIClassifier.asyncClassifyLocalWithTables.
|
||||
//
|
||||
// 2) At any time you need the classification result, call Result()
|
||||
// and it is guaranteed to give you the result. Note that you have
|
||||
// to specify "aIsThirdParty" to the function so please make sure
|
||||
// you can already correctly decide if the document is third-party.
|
||||
//
|
||||
// Behind the scenes, the sync classification API
|
||||
// (nsIURIClassifier.classifyLocalWithTable) may be called as a fallback to
|
||||
// synchronously get the result if the asyncClassifyLocalWithTables hasn't
|
||||
// been done yet.
|
||||
//
|
||||
// 3) You can call Result() as many times as you want and only the first time
|
||||
// it may unfortunately call the blocking sync API. The subsequent call
|
||||
// will just return the result that came out at the first time.
|
||||
//
|
||||
class PrincipalFlashClassifier final : public nsIURIClassifierCallback {
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIURICLASSIFIERCALLBACK
|
||||
|
||||
PrincipalFlashClassifier();
|
||||
|
||||
// Fire async classification based on the given principal.
|
||||
void AsyncClassify(nsIPrincipal* aPrincipal);
|
||||
|
||||
// Would block if the result hasn't come out.
|
||||
mozilla::dom::FlashClassification ClassifyMaybeSync(nsIPrincipal* aPrincipal,
|
||||
bool aIsThirdParty);
|
||||
|
||||
private:
|
||||
~PrincipalFlashClassifier() = default;
|
||||
|
||||
void Reset();
|
||||
bool EnsureUriClassifier();
|
||||
mozilla::dom::FlashClassification CheckIfClassifyNeeded(
|
||||
nsIPrincipal* aPrincipal);
|
||||
mozilla::dom::FlashClassification Resolve(bool aIsThirdParty);
|
||||
mozilla::dom::FlashClassification AsyncClassifyInternal(
|
||||
nsIPrincipal* aPrincipal);
|
||||
void GetClassificationTables(bool aIsThirdParty, nsACString& aTables);
|
||||
|
||||
// For the fallback sync classification.
|
||||
nsCOMPtr<nsIURI> mClassificationURI;
|
||||
|
||||
nsCOMPtr<nsIURIClassifier> mUriClassifier;
|
||||
bool mAsyncClassified;
|
||||
nsTArray<nsCString> mMatchedTables;
|
||||
mozilla::dom::FlashClassification mResult;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -1395,8 +1335,7 @@ Document::Document(const char* aContentType)
|
|||
mViewportOverflowType(ViewportOverflowType::NoOverflow),
|
||||
mSubDocuments(nullptr),
|
||||
mHeaderData(nullptr),
|
||||
mPrincipalFlashClassifier(new PrincipalFlashClassifier()),
|
||||
mFlashClassification(FlashClassification::Unclassified),
|
||||
mFlashClassification(FlashClassification::Unknown),
|
||||
mBoxObjectTable(nullptr),
|
||||
mCurrentOrientationAngle(0),
|
||||
mCurrentOrientationType(OrientationType::Portrait_primary),
|
||||
|
@ -2628,11 +2567,6 @@ nsresult Document::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
|
|||
aChannel->Cancel(NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION);
|
||||
}
|
||||
|
||||
// Perform a async flash classification based on the doc principal
|
||||
// in an early stage to reduce the blocking time.
|
||||
mFlashClassification = FlashClassification::Unclassified;
|
||||
mPrincipalFlashClassifier->AsyncClassify(GetPrincipal());
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -12036,317 +11970,27 @@ Document* Document::GetSameTypeParentDocument() {
|
|||
|
||||
/**
|
||||
* Retrieves the classification of the Flash plugins in the document based on
|
||||
* the classification lists. We perform AsyncInitFlashClassification on
|
||||
* StartDocumentLoad() and the result may not be initialized when this function
|
||||
* gets called. In that case, We can only unfortunately have a blocking wait.
|
||||
*
|
||||
* For more information, see
|
||||
* the classification lists. For more information, see
|
||||
* toolkit/components/url-classifier/flash-block-lists.rst
|
||||
*/
|
||||
FlashClassification Document::PrincipalFlashClassification() {
|
||||
MOZ_ASSERT(mPrincipalFlashClassifier);
|
||||
return mPrincipalFlashClassifier->ClassifyMaybeSync(NodePrincipal(),
|
||||
IsThirdParty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for |Document::PrincipalFlashClassification|
|
||||
*
|
||||
* Adds a table name string to a table list (a comma separated string). The
|
||||
* table will not be added if the name is an empty string.
|
||||
*/
|
||||
static void MaybeAddTableToTableList(const nsACString& aTableNames,
|
||||
nsACString& aTableList) {
|
||||
if (aTableNames.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (!aTableList.IsEmpty()) {
|
||||
aTableList.AppendLiteral(",");
|
||||
}
|
||||
aTableList.Append(aTableNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for |Document::PrincipalFlashClassification|
|
||||
*
|
||||
* Takes an array of table names and a comma separated list of table names
|
||||
* Returns |true| if any table name in the array matches a table name in the
|
||||
* comma separated list.
|
||||
*/
|
||||
static bool ArrayContainsTable(const nsTArray<nsCString>& aTableArray,
|
||||
const nsACString& aTableNames) {
|
||||
for (const nsCString& table : aTableArray) {
|
||||
// This check is sufficient because table names cannot contain commas and
|
||||
// cannot contain another existing table name.
|
||||
if (FindInReadable(table, aTableNames)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
static const char* gCallbackPrefs[] = {
|
||||
// We only need to register string-typed preferences.
|
||||
"urlclassifier.flashAllowTable",
|
||||
"urlclassifier.flashAllowExceptTable",
|
||||
"urlclassifier.flashTable",
|
||||
"urlclassifier.flashExceptTable",
|
||||
"urlclassifier.flashSubDocTable",
|
||||
"urlclassifier.flashSubDocExceptTable",
|
||||
nullptr,
|
||||
};
|
||||
|
||||
// An object to store all preferences we need for flash blocking feature.
|
||||
struct PrefStore {
|
||||
PrefStore() : mFlashBlockEnabled(false), mPluginsHttpOnly(false) {
|
||||
Preferences::AddBoolVarCache(&mFlashBlockEnabled,
|
||||
"plugins.flashBlock.enabled");
|
||||
Preferences::AddBoolVarCache(&mPluginsHttpOnly, "plugins.http_https_only");
|
||||
|
||||
Preferences::RegisterCallbacks(
|
||||
PREF_CHANGE_METHOD(PrefStore::UpdateStringPrefs), gCallbackPrefs, this);
|
||||
|
||||
UpdateStringPrefs();
|
||||
}
|
||||
|
||||
~PrefStore() {
|
||||
Preferences::UnregisterCallbacks(
|
||||
PREF_CHANGE_METHOD(PrefStore::UpdateStringPrefs), gCallbackPrefs, this);
|
||||
}
|
||||
|
||||
void UpdateStringPrefs(const char* aPref = nullptr) {
|
||||
Preferences::GetCString("urlclassifier.flashAllowTable", mAllowTables);
|
||||
Preferences::GetCString("urlclassifier.flashAllowExceptTable",
|
||||
mAllowExceptionsTables);
|
||||
Preferences::GetCString("urlclassifier.flashTable", mDenyTables);
|
||||
Preferences::GetCString("urlclassifier.flashExceptTable",
|
||||
mDenyExceptionsTables);
|
||||
Preferences::GetCString("urlclassifier.flashSubDocTable",
|
||||
mSubDocDenyTables);
|
||||
Preferences::GetCString("urlclassifier.flashSubDocExceptTable",
|
||||
mSubDocDenyExceptionsTables);
|
||||
}
|
||||
|
||||
bool mFlashBlockEnabled;
|
||||
bool mPluginsHttpOnly;
|
||||
|
||||
nsCString mAllowTables;
|
||||
nsCString mAllowExceptionsTables;
|
||||
nsCString mDenyTables;
|
||||
nsCString mDenyExceptionsTables;
|
||||
nsCString mSubDocDenyTables;
|
||||
nsCString mSubDocDenyExceptionsTables;
|
||||
};
|
||||
|
||||
static const PrefStore& GetPrefStore() {
|
||||
static UniquePtr<PrefStore> sPrefStore;
|
||||
if (!sPrefStore) {
|
||||
sPrefStore.reset(new PrefStore());
|
||||
ClearOnShutdown(&sPrefStore);
|
||||
}
|
||||
return *sPrefStore;
|
||||
}
|
||||
|
||||
} // end of unnamed namespace.
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// PrincipalFlashClassifier implementation.
|
||||
|
||||
NS_IMPL_ISUPPORTS(PrincipalFlashClassifier, nsIURIClassifierCallback)
|
||||
|
||||
PrincipalFlashClassifier::PrincipalFlashClassifier() { Reset(); }
|
||||
|
||||
void PrincipalFlashClassifier::Reset() {
|
||||
mAsyncClassified = false;
|
||||
mMatchedTables.Clear();
|
||||
mResult = FlashClassification::Unclassified;
|
||||
}
|
||||
|
||||
void PrincipalFlashClassifier::GetClassificationTables(bool aIsThirdParty,
|
||||
nsACString& aTables) {
|
||||
aTables.Truncate();
|
||||
auto& prefs = GetPrefStore();
|
||||
|
||||
MaybeAddTableToTableList(prefs.mAllowTables, aTables);
|
||||
MaybeAddTableToTableList(prefs.mAllowExceptionsTables, aTables);
|
||||
MaybeAddTableToTableList(prefs.mDenyTables, aTables);
|
||||
MaybeAddTableToTableList(prefs.mDenyExceptionsTables, aTables);
|
||||
|
||||
if (aIsThirdParty) {
|
||||
MaybeAddTableToTableList(prefs.mSubDocDenyTables, aTables);
|
||||
MaybeAddTableToTableList(prefs.mSubDocDenyExceptionsTables, aTables);
|
||||
}
|
||||
}
|
||||
|
||||
bool PrincipalFlashClassifier::EnsureUriClassifier() {
|
||||
if (!mUriClassifier) {
|
||||
mUriClassifier = do_GetService(NS_URICLASSIFIERSERVICE_CONTRACTID);
|
||||
}
|
||||
|
||||
return !!mUriClassifier;
|
||||
}
|
||||
|
||||
FlashClassification PrincipalFlashClassifier::ClassifyMaybeSync(
|
||||
nsIPrincipal* aPrincipal, bool aIsThirdParty) {
|
||||
if (FlashClassification::Unclassified != mResult) {
|
||||
// We already have the result. Just return it.
|
||||
return mResult;
|
||||
}
|
||||
|
||||
// TODO: Bug 1342333 - Entirely remove the use of the sync API
|
||||
// (ClassifyLocalWithTables).
|
||||
if (!mAsyncClassified) {
|
||||
//
|
||||
// We may
|
||||
// 1) have called AsyncClassifyLocalWithTables but OnClassifyComplete
|
||||
// hasn't been called.
|
||||
// 2) haven't even called AsyncClassifyLocalWithTables.
|
||||
//
|
||||
// In both cases we need to do the synchronous classification as the
|
||||
// fallback.
|
||||
//
|
||||
|
||||
if (!EnsureUriClassifier()) {
|
||||
return FlashClassification::Denied;
|
||||
}
|
||||
mResult = CheckIfClassifyNeeded(aPrincipal);
|
||||
if (FlashClassification::Unclassified != mResult) {
|
||||
return mResult;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
nsAutoCString classificationTables;
|
||||
GetClassificationTables(aIsThirdParty, classificationTables);
|
||||
|
||||
if (!mClassificationURI) {
|
||||
rv = aPrincipal->GetURI(getter_AddRefs(mClassificationURI));
|
||||
if (NS_FAILED(rv) || !mClassificationURI) {
|
||||
mResult = FlashClassification::Denied;
|
||||
return mResult;
|
||||
}
|
||||
}
|
||||
|
||||
rv = mUriClassifier->ClassifyLocalWithTables(
|
||||
mClassificationURI, classificationTables, mMatchedTables);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
if (rv == NS_ERROR_MALFORMED_URI) {
|
||||
// This means that the URI had no hostname (ex: file://doc.html). In
|
||||
// this case, we allow the default (Unknown plugin) behavior.
|
||||
mResult = FlashClassification::Unknown;
|
||||
} else {
|
||||
mResult = FlashClassification::Denied;
|
||||
}
|
||||
return mResult;
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve the result based on mMatchedTables and aIsThirdParty.
|
||||
mResult = Resolve(aIsThirdParty);
|
||||
MOZ_ASSERT(FlashClassification::Unclassified != mResult);
|
||||
|
||||
// The subsequent call of Result() will return the resolved result
|
||||
// and never reach here until Reset() is called.
|
||||
return mResult;
|
||||
}
|
||||
|
||||
/*virtual*/ nsresult PrincipalFlashClassifier::OnClassifyComplete(
|
||||
nsresult /*aErrorCode*/,
|
||||
const nsACString& aLists, // Only this matters.
|
||||
const nsACString& /*aProvider*/, const nsACString& /*aPrefix*/) {
|
||||
mAsyncClassified = true;
|
||||
|
||||
if (FlashClassification::Unclassified != mResult) {
|
||||
// Result() has been called prior to this callback.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// TODO: Bug 1364804 - We should use a callback type which notifies
|
||||
// the result as a string array rather than a formatted string.
|
||||
|
||||
// We only populate the matched list without resolving the classification
|
||||
// result because we are not sure if the parent doc has been properly set.
|
||||
// We also parse the comma-separated tables to array. (the code is copied
|
||||
// from Classifier::SplitTables.)
|
||||
nsACString::const_iterator begin, iter, end;
|
||||
aLists.BeginReading(begin);
|
||||
aLists.EndReading(end);
|
||||
while (begin != end) {
|
||||
iter = begin;
|
||||
FindCharInReadable(',', iter, end);
|
||||
nsDependentCSubstring table = Substring(begin, iter);
|
||||
if (!table.IsEmpty()) {
|
||||
mMatchedTables.AppendElement(Substring(begin, iter));
|
||||
}
|
||||
begin = iter;
|
||||
if (begin != end) {
|
||||
begin++;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// We resolve the classification result based on aIsThirdParty
|
||||
// and the matched tables we got ealier on (via either sync or async API).
|
||||
FlashClassification PrincipalFlashClassifier::Resolve(bool aIsThirdParty) {
|
||||
MOZ_ASSERT(FlashClassification::Unclassified == mResult,
|
||||
"We already have resolved classification result.");
|
||||
|
||||
if (mMatchedTables.IsEmpty()) {
|
||||
return FlashClassification::Unknown;
|
||||
}
|
||||
|
||||
auto& prefs = GetPrefStore();
|
||||
if (ArrayContainsTable(mMatchedTables, prefs.mDenyTables) &&
|
||||
!ArrayContainsTable(mMatchedTables, prefs.mDenyExceptionsTables)) {
|
||||
return FlashClassification::Denied;
|
||||
} else if (ArrayContainsTable(mMatchedTables, prefs.mAllowTables) &&
|
||||
!ArrayContainsTable(mMatchedTables,
|
||||
prefs.mAllowExceptionsTables)) {
|
||||
return FlashClassification::Allowed;
|
||||
}
|
||||
|
||||
if (aIsThirdParty &&
|
||||
ArrayContainsTable(mMatchedTables, prefs.mSubDocDenyTables) &&
|
||||
!ArrayContainsTable(mMatchedTables, prefs.mSubDocDenyExceptionsTables)) {
|
||||
return FlashClassification::Denied;
|
||||
}
|
||||
|
||||
return FlashClassification::Unknown;
|
||||
}
|
||||
|
||||
void PrincipalFlashClassifier::AsyncClassify(nsIPrincipal* aPrincipal) {
|
||||
MOZ_ASSERT(FlashClassification::Unclassified == mResult,
|
||||
"The old classification result should be reset first.");
|
||||
Reset();
|
||||
mResult = AsyncClassifyInternal(aPrincipal);
|
||||
}
|
||||
|
||||
FlashClassification PrincipalFlashClassifier::CheckIfClassifyNeeded(
|
||||
nsIPrincipal* aPrincipal) {
|
||||
nsresult rv;
|
||||
|
||||
auto& prefs = GetPrefStore();
|
||||
|
||||
FlashClassification Document::DocumentFlashClassification() {
|
||||
// If neither pref is on, skip the null-principal and principal URI checks.
|
||||
if (prefs.mPluginsHttpOnly && !prefs.mFlashBlockEnabled) {
|
||||
if (!StaticPrefs::plugins_http_https_only() &&
|
||||
!StaticPrefs::plugins_flashBlock_enabled()) {
|
||||
return FlashClassification::Unknown;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal = aPrincipal;
|
||||
if (principal->GetIsNullPrincipal()) {
|
||||
if (NodePrincipal()->GetIsNullPrincipal()) {
|
||||
return FlashClassification::Denied;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> classificationURI;
|
||||
rv = principal->GetURI(getter_AddRefs(classificationURI));
|
||||
nsresult rv = NodePrincipal()->GetURI(getter_AddRefs(classificationURI));
|
||||
if (NS_FAILED(rv) || !classificationURI) {
|
||||
return FlashClassification::Denied;
|
||||
}
|
||||
|
||||
if (prefs.mPluginsHttpOnly) {
|
||||
if (StaticPrefs::plugins_http_https_only()) {
|
||||
// Only allow plugins for documents from an HTTP/HTTPS origin. This should
|
||||
// allow dependent data: URIs to load plugins, but not:
|
||||
// * chrome documents
|
||||
|
@ -12362,125 +12006,21 @@ FlashClassification PrincipalFlashClassifier::CheckIfClassifyNeeded(
|
|||
|
||||
// If flash blocking is disabled, it is equivalent to all sites being
|
||||
// on neither list.
|
||||
if (!prefs.mFlashBlockEnabled) {
|
||||
if (!StaticPrefs::plugins_flashBlock_enabled()) {
|
||||
return FlashClassification::Unknown;
|
||||
}
|
||||
|
||||
return FlashClassification::Unclassified;
|
||||
}
|
||||
|
||||
// Using nsIURIClassifier.asyncClassifyLocalWithTables to do classification
|
||||
// against the flash related tables based on the given principal.
|
||||
FlashClassification PrincipalFlashClassifier::AsyncClassifyInternal(
|
||||
nsIPrincipal* aPrincipal) {
|
||||
auto result = CheckIfClassifyNeeded(aPrincipal);
|
||||
if (FlashClassification::Unclassified != result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// We haven't been able to decide if it's a third party document
|
||||
// since determining if a document is third-party may depend on its
|
||||
// parent document. At the time we call AsyncClassifyInternal
|
||||
// (i.e. StartDocumentLoad) the parent document may not have been
|
||||
// set. As a result, we wait until Resolve() to be called to
|
||||
// take "is third party" into account. At this point, we just assume
|
||||
// it's third-party to include every list.
|
||||
nsAutoCString tables;
|
||||
GetClassificationTables(true, tables);
|
||||
|
||||
if (tables.IsEmpty()) {
|
||||
return FlashClassification::Unknown;
|
||||
}
|
||||
|
||||
if (!EnsureUriClassifier()) {
|
||||
return FlashClassification::Denied;
|
||||
}
|
||||
|
||||
nsresult rv = aPrincipal->GetURI(getter_AddRefs(mClassificationURI));
|
||||
if (NS_FAILED(rv) || !mClassificationURI) {
|
||||
return FlashClassification::Denied;
|
||||
}
|
||||
|
||||
// We don't support extra entries by pref for this classifier.
|
||||
rv = mUriClassifier->AsyncClassifyLocalWithTables(
|
||||
mClassificationURI, tables, nsTArray<nsCString>(), nsTArray<nsCString>(),
|
||||
this);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
if (rv == NS_ERROR_MALFORMED_URI) {
|
||||
// This means that the URI had no hostname (ex: file://doc.html). In this
|
||||
// case, we allow the default (Unknown plugin) behavior.
|
||||
return FlashClassification::Unknown;
|
||||
} else {
|
||||
return FlashClassification::Denied;
|
||||
}
|
||||
}
|
||||
|
||||
return FlashClassification::Unclassified;
|
||||
}
|
||||
|
||||
FlashClassification Document::ComputeFlashClassification() {
|
||||
nsCOMPtr<nsIDocShellTreeItem> current = this->GetDocShell();
|
||||
if (!current) {
|
||||
return FlashClassification::Denied;
|
||||
}
|
||||
nsCOMPtr<nsIDocShellTreeItem> parent;
|
||||
DebugOnly<nsresult> rv = current->GetSameTypeParent(getter_AddRefs(parent));
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv),
|
||||
"nsIDocShellTreeItem::GetSameTypeParent should never fail");
|
||||
|
||||
bool isTopLevel = !parent;
|
||||
FlashClassification classification;
|
||||
if (isTopLevel) {
|
||||
classification = PrincipalFlashClassification();
|
||||
} else {
|
||||
nsCOMPtr<Document> parentDocument = GetParentDocument();
|
||||
if (!parentDocument) {
|
||||
return FlashClassification::Denied;
|
||||
}
|
||||
FlashClassification parentClassification =
|
||||
parentDocument->DocumentFlashClassification();
|
||||
|
||||
if (parentClassification == FlashClassification::Denied) {
|
||||
classification = FlashClassification::Denied;
|
||||
} else {
|
||||
classification = PrincipalFlashClassification();
|
||||
|
||||
// Allow unknown children to inherit allowed status from parent, but
|
||||
// do not allow denied children to do so.
|
||||
if (classification == FlashClassification::Unknown &&
|
||||
parentClassification == FlashClassification::Allowed) {
|
||||
classification = FlashClassification::Allowed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return classification;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the classification of plugins in this document. This is dependent
|
||||
* on the classification of this document and all parent documents.
|
||||
* This function is infallible - It must return some classification that
|
||||
* callers can act on.
|
||||
*
|
||||
* This function will NOT return FlashClassification::Unclassified
|
||||
*/
|
||||
FlashClassification Document::DocumentFlashClassification() {
|
||||
if (mFlashClassification == FlashClassification::Unclassified) {
|
||||
FlashClassification result = ComputeFlashClassification();
|
||||
mFlashClassification = result;
|
||||
MOZ_ASSERT(
|
||||
result != FlashClassification::Unclassified,
|
||||
"Document::GetPluginClassification should never return Unclassified");
|
||||
if (mFlashClassification == FlashClassification::Unknown) {
|
||||
mFlashClassification = DocumentFlashClassificationInternal();
|
||||
}
|
||||
|
||||
return mFlashClassification;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes |mIsThirdParty| if necessary and returns its value. The value
|
||||
* returned represents whether this document should be considered Third-Party.
|
||||
* Initializes |mIsThirdPartyForFlashClassifier| if necessary and returns its
|
||||
* value. The value returned represents whether this document should be
|
||||
* considered Third-Party.
|
||||
*
|
||||
* A top-level document cannot be a considered Third-Party; only subdocuments
|
||||
* may. For a subdocument to be considered Third-Party, it must meet ANY ONE
|
||||
|
@ -12493,15 +12033,15 @@ FlashClassification Document::DocumentFlashClassification() {
|
|||
* If there is an error in determining whether the document is Third-Party,
|
||||
* it will be assumed to be Third-Party for security reasons.
|
||||
*/
|
||||
bool Document::IsThirdParty() {
|
||||
if (mIsThirdParty.isSome()) {
|
||||
return mIsThirdParty.value();
|
||||
bool Document::IsThirdPartyForFlashClassifier() {
|
||||
if (mIsThirdPartyForFlashClassifier.isSome()) {
|
||||
return mIsThirdPartyForFlashClassifier.value();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> docshell = this->GetDocShell();
|
||||
if (!docshell) {
|
||||
mIsThirdParty.emplace(true);
|
||||
return mIsThirdParty.value();
|
||||
mIsThirdPartyForFlashClassifier.emplace(true);
|
||||
return mIsThirdPartyForFlashClassifier.value();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> parent;
|
||||
|
@ -12511,20 +12051,20 @@ bool Document::IsThirdParty() {
|
|||
bool isTopLevel = !parent;
|
||||
|
||||
if (isTopLevel) {
|
||||
mIsThirdParty.emplace(false);
|
||||
return mIsThirdParty.value();
|
||||
mIsThirdPartyForFlashClassifier.emplace(false);
|
||||
return mIsThirdPartyForFlashClassifier.value();
|
||||
}
|
||||
|
||||
nsCOMPtr<Document> parentDocument = GetParentDocument();
|
||||
if (!parentDocument) {
|
||||
// Failure
|
||||
mIsThirdParty.emplace(true);
|
||||
return mIsThirdParty.value();
|
||||
mIsThirdPartyForFlashClassifier.emplace(true);
|
||||
return mIsThirdPartyForFlashClassifier.value();
|
||||
}
|
||||
|
||||
if (parentDocument->IsThirdParty()) {
|
||||
mIsThirdParty.emplace(true);
|
||||
return mIsThirdParty.value();
|
||||
if (parentDocument->IsThirdPartyForFlashClassifier()) {
|
||||
mIsThirdPartyForFlashClassifier.emplace(true);
|
||||
return mIsThirdPartyForFlashClassifier.value();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal = NodePrincipal();
|
||||
|
@ -12535,18 +12075,69 @@ bool Document::IsThirdParty() {
|
|||
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
// Failure
|
||||
mIsThirdParty.emplace(true);
|
||||
return mIsThirdParty.value();
|
||||
mIsThirdPartyForFlashClassifier.emplace(true);
|
||||
return mIsThirdPartyForFlashClassifier.value();
|
||||
}
|
||||
|
||||
if (!principalsMatch) {
|
||||
mIsThirdParty.emplace(true);
|
||||
return mIsThirdParty.value();
|
||||
mIsThirdPartyForFlashClassifier.emplace(true);
|
||||
return mIsThirdPartyForFlashClassifier.value();
|
||||
}
|
||||
|
||||
// Fall-through. Document is not a Third-Party Document.
|
||||
mIsThirdParty.emplace(false);
|
||||
return mIsThirdParty.value();
|
||||
mIsThirdPartyForFlashClassifier.emplace(false);
|
||||
return mIsThirdPartyForFlashClassifier.value();
|
||||
}
|
||||
|
||||
FlashClassification Document::DocumentFlashClassificationInternal() {
|
||||
FlashClassification classification = FlashClassification::Unknown;
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(GetChannel());
|
||||
if (httpChannel) {
|
||||
nsIHttpChannel::FlashPluginState state = nsIHttpChannel::FlashPluginUnknown;
|
||||
httpChannel->GetFlashPluginState(&state);
|
||||
|
||||
// Allow unknown children to inherit allowed status from parent, but do not
|
||||
// allow denied children to do so.
|
||||
|
||||
if (state == nsIHttpChannel::FlashPluginDeniedInSubdocuments &&
|
||||
IsThirdPartyForFlashClassifier()) {
|
||||
return FlashClassification::Denied;
|
||||
}
|
||||
|
||||
if (state == nsIHttpChannel::FlashPluginDenied) {
|
||||
return FlashClassification::Denied;
|
||||
}
|
||||
|
||||
if (state == nsIHttpChannel::FlashPluginAllowed) {
|
||||
classification = FlashClassification::Allowed;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsTopLevelContentDocument()) {
|
||||
return classification;
|
||||
}
|
||||
|
||||
Document* parentDocument = GetParentDocument();
|
||||
if (!parentDocument) {
|
||||
return FlashClassification::Denied;
|
||||
}
|
||||
|
||||
FlashClassification parentClassification =
|
||||
parentDocument->DocumentFlashClassification();
|
||||
|
||||
if (parentClassification == FlashClassification::Denied) {
|
||||
return FlashClassification::Denied;
|
||||
}
|
||||
|
||||
// Allow unknown children to inherit allowed status from parent, but
|
||||
// do not allow denied children to do so.
|
||||
if (classification == FlashClassification::Unknown &&
|
||||
parentClassification == FlashClassification::Allowed) {
|
||||
return FlashClassification::Allowed;
|
||||
}
|
||||
|
||||
return classification;
|
||||
}
|
||||
|
||||
void Document::ClearStaleServoData() {
|
||||
|
|
|
@ -427,9 +427,6 @@ class ExternalResourceMap {
|
|||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// For classifying a flash document based on its principal.
|
||||
class PrincipalFlashClassifier;
|
||||
|
||||
// Document interface. This is implemented by all document objects in
|
||||
// Gecko.
|
||||
class Document : public nsINode,
|
||||
|
@ -3412,6 +3409,8 @@ class Document : public nsINode,
|
|||
const nsAString& aHeightString,
|
||||
const nsAString& aScaleString);
|
||||
|
||||
mozilla::dom::FlashClassification DocumentFlashClassificationInternal();
|
||||
|
||||
nsTArray<nsString> mL10nResources;
|
||||
|
||||
// The application cache that this document is associated with, if
|
||||
|
@ -3419,7 +3418,7 @@ class Document : public nsINode,
|
|||
nsCOMPtr<nsIApplicationCache> mApplicationCache;
|
||||
|
||||
public:
|
||||
bool IsThirdParty();
|
||||
bool IsThirdPartyForFlashClassifier();
|
||||
|
||||
bool IsScopedStyleEnabled();
|
||||
|
||||
|
@ -3520,14 +3519,6 @@ class Document : public nsINode,
|
|||
*/
|
||||
Element* GetTitleElement();
|
||||
|
||||
// Retrieves the classification of the Flash plugins in the document based on
|
||||
// the classification lists.
|
||||
mozilla::dom::FlashClassification PrincipalFlashClassification();
|
||||
|
||||
// Attempts to determine the Flash classification of this page based on the
|
||||
// the classification lists and the classification of parent documents.
|
||||
mozilla::dom::FlashClassification ComputeFlashClassification();
|
||||
|
||||
void RecordNavigationTiming(ReadyState aReadyState);
|
||||
|
||||
// This method may fire a DOM event; if it does so it will happen
|
||||
|
@ -4294,11 +4285,11 @@ class Document : public nsINode,
|
|||
|
||||
// For determining if this is a flash document which should be
|
||||
// blocked based on its principal.
|
||||
RefPtr<PrincipalFlashClassifier> mPrincipalFlashClassifier;
|
||||
mozilla::dom::FlashClassification mFlashClassification;
|
||||
// Do not use this value directly. Call the |IsThirdParty()| method, which
|
||||
// caches its result here.
|
||||
mozilla::Maybe<bool> mIsThirdParty;
|
||||
|
||||
// Do not use this value directly. Call the |IsThirdPartyForFlashClassifier()|
|
||||
// method, which caches its result here.
|
||||
mozilla::Maybe<bool> mIsThirdPartyForFlashClassifier;
|
||||
|
||||
nsRevocableEventPtr<nsRunnableMethod<Document, void, false>>
|
||||
mPendingTitleChangeEvent;
|
||||
|
|
|
@ -141,6 +141,10 @@ PopupBlocker::GetPopupControlState() {
|
|||
return false;
|
||||
}
|
||||
|
||||
/* static */ bool PopupBlocker::IsPopupOpeningTokenUnused() {
|
||||
return sUnusedPopupToken;
|
||||
}
|
||||
|
||||
/* static */ void PopupBlocker::PopupStatePusherCreated() {
|
||||
++sPopupStatePusherCount;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ class PopupBlocker final {
|
|||
// permissive to least permissive so that it's safe to push state in
|
||||
// all situations. Pushing popup state onto the stack never makes the
|
||||
// current popup state less permissive.
|
||||
// Keep this in sync with PopupBlockerState webidl dictionary!
|
||||
enum PopupControlState {
|
||||
openAllowed = 0, // open that window without worries
|
||||
openControlled, // it's a popup, but allow it
|
||||
|
@ -47,6 +48,8 @@ class PopupBlocker final {
|
|||
// allowed per event.
|
||||
static bool TryUsePopupOpeningToken();
|
||||
|
||||
static bool IsPopupOpeningTokenUnused();
|
||||
|
||||
static PopupBlocker::PopupControlState GetEventPopupControlState(
|
||||
WidgetEvent* aEvent, Event* aDOMEvent = nullptr);
|
||||
|
||||
|
|
|
@ -380,6 +380,12 @@ partial namespace ChromeUtils {
|
|||
[ChromeOnly, Throws]
|
||||
boolean hasReportingHeaderForOrigin(DOMString aOrigin);
|
||||
|
||||
[ChromeOnly]
|
||||
PopupBlockerState getPopupControlState();
|
||||
|
||||
[ChromeOnly]
|
||||
boolean isPopupTokenUnused();
|
||||
|
||||
[ChromeOnly, Throws]
|
||||
void registerWindowActor(DOMString aName, WindowActorOptions aOptions);
|
||||
};
|
||||
|
@ -551,3 +557,12 @@ dictionary Base64URLDecodeOptions {
|
|||
/** Specifies the padding mode for decoding the input. */
|
||||
required Base64URLDecodePadding padding;
|
||||
};
|
||||
|
||||
// Keep this in sync with PopupBlocker::PopupControlState!
|
||||
enum PopupBlockerState {
|
||||
"openAllowed",
|
||||
"openControlled",
|
||||
"openBlocked",
|
||||
"openAbused",
|
||||
"openOverridden",
|
||||
};
|
||||
|
|
|
@ -7,3 +7,4 @@ support-files =
|
|||
skip-if = os == 'android'
|
||||
[test_bug1414077.html]
|
||||
[test_multipleFilePicker.html]
|
||||
[test_external_protocol_iframe.html]
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for external protocol URLs blocked for iframes</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div id='foo'><a href='#'>Click here to test this issue</a></div>
|
||||
<script>
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
let foo = document.getElementById('foo');
|
||||
foo.addEventListener('click', _ => {
|
||||
is(ChromeUtils.getPopupControlState(), "openAllowed", "Click events allow popups");
|
||||
ok(!ChromeUtils.isPopupTokenUnused(), "Popup token has not been used yet");
|
||||
|
||||
for (let i = 0; i < 10; ++i) {
|
||||
let ifr = document.createElement('iframe');
|
||||
ifr.src = "foo+bar:all_good";
|
||||
document.body.appendChild(ifr);
|
||||
|
||||
is(ChromeUtils.getPopupControlState(), "openAllowed", "Click events allow popups");
|
||||
ok(ChromeUtils.isPopupTokenUnused(), "Popup token has been used!");
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
|
||||
}, {once: true});
|
||||
|
||||
setTimeout(_ => {
|
||||
sendMouseEvent({type:'click'}, 'foo');
|
||||
}, 0);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -5454,23 +5454,6 @@ bool ContentParent::DeallocPLoginReputationParent(
|
|||
return true;
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentParent::RecvClassifyLocal(
|
||||
const URIParams& aURI, const nsCString& aTables, nsresult* aRv,
|
||||
nsTArray<nsCString>* aResults) {
|
||||
MOZ_ASSERT(aResults);
|
||||
nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
|
||||
if (!uri) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
nsCOMPtr<nsIURIClassifier> uriClassifier =
|
||||
do_GetService(NS_URICLASSIFIERSERVICE_CONTRACTID);
|
||||
if (!uriClassifier) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
*aRv = uriClassifier->ClassifyLocalWithTables(uri, aTables, *aResults);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentParent::RecvFileCreationRequest(
|
||||
const nsID& aID, const nsString& aFullPath, const nsString& aType,
|
||||
const nsString& aName, const bool& aLastModifiedPassed,
|
||||
|
|
|
@ -593,10 +593,6 @@ class ContentParent final : public PContentParent,
|
|||
virtual bool DeallocPURLClassifierParent(
|
||||
PURLClassifierParent* aActor) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvClassifyLocal(
|
||||
const URIParams& aURI, const nsCString& aTables, nsresult* aRv,
|
||||
nsTArray<nsCString>* aResults) override;
|
||||
|
||||
// Use the PHangMonitor channel to ask the child to repaint a tab.
|
||||
void PaintTabWhileInterruptingJS(TabParent* aTabParent, bool aForceRepaint,
|
||||
const layers::LayersObserverEpoch& aEpoch);
|
||||
|
|
|
@ -841,10 +841,6 @@ parent:
|
|||
sync PURLClassifier(Principal principal, bool useTrackingProtection)
|
||||
returns (bool success);
|
||||
|
||||
sync ClassifyLocal(URIParams uri, nsCString tables)
|
||||
returns (nsresult rv, nsCString[] results);
|
||||
|
||||
// The async version of ClassifyLocal.
|
||||
async PURLClassifierLocal(URIParams uri, IPCURLClassifierFeature[] features);
|
||||
|
||||
async PLoginReputation(URIParams formURI);
|
||||
|
|
|
@ -6,13 +6,17 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
include protocol PContent;
|
||||
|
||||
include PURLClassifierInfo;
|
||||
|
||||
using refcounted class nsIURI from "mozilla/ipc/URIUtils.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
struct URLClassifierLocalResult
|
||||
{
|
||||
nsIURI uri;
|
||||
nsCString featureName;
|
||||
nsCString matchingList;
|
||||
};
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "mozilla/dom/PURLClassifierChild.h"
|
||||
#include "mozilla/dom/PURLClassifierLocalChild.h"
|
||||
#include "mozilla/ipc/URIUtils.h"
|
||||
#include "mozilla/net/UrlClassifierFeatureResult.h"
|
||||
#include "nsIURIClassifier.h"
|
||||
#include "nsIUrlClassifierFeature.h"
|
||||
|
@ -63,8 +64,14 @@ class URLClassifierLocalChild : public PURLClassifierLocalChild {
|
|||
continue;
|
||||
}
|
||||
|
||||
RefPtr<nsIURI> uri = result.uri();
|
||||
if (NS_WARN_IF(!uri)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RefPtr<net::UrlClassifierFeatureResult> r =
|
||||
new net::UrlClassifierFeatureResult(feature, result.matchingList());
|
||||
new net::UrlClassifierFeatureResult(uri, feature,
|
||||
result.matchingList());
|
||||
finalResults.AppendElement(r);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -53,8 +53,8 @@ class IPCFeature final : public nsIUrlClassifierFeature {
|
|||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
explicit IPCFeature(const IPCURLClassifierFeature& aFeature)
|
||||
: mIPCFeature(aFeature) {}
|
||||
IPCFeature(nsIURI* aURI, const IPCURLClassifierFeature& aFeature)
|
||||
: mURI(aURI), mIPCFeature(aFeature) {}
|
||||
|
||||
NS_IMETHOD
|
||||
GetName(nsACString& aName) override {
|
||||
|
@ -102,9 +102,22 @@ class IPCFeature final : public nsIUrlClassifierFeature {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
GetURIByListType(nsIChannel* aChannel,
|
||||
nsIUrlClassifierFeature::listType aListType,
|
||||
nsIURI** aURI) override {
|
||||
NS_ENSURE_ARG_POINTER(aURI);
|
||||
|
||||
// This method should not be called, but we have a URI, let's return it.
|
||||
nsCOMPtr<nsIURI> uri = mURI;
|
||||
uri.forget(aURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
~IPCFeature() = default;
|
||||
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
IPCURLClassifierFeature mIPCFeature;
|
||||
};
|
||||
|
||||
|
@ -130,7 +143,7 @@ mozilla::ipc::IPCResult URLClassifierLocalParent::StartClassify(
|
|||
|
||||
nsTArray<RefPtr<nsIUrlClassifierFeature>> features;
|
||||
for (const IPCURLClassifierFeature& feature : aFeatures) {
|
||||
features.AppendElement(new IPCFeature(feature));
|
||||
features.AppendElement(new IPCFeature(aURI, feature));
|
||||
}
|
||||
|
||||
// Doesn't matter if we pass blacklist, whitelist or any other list.
|
||||
|
@ -154,6 +167,8 @@ URLClassifierLocalParent::OnClassifyComplete(
|
|||
|
||||
net::UrlClassifierFeatureResult* r =
|
||||
static_cast<net::UrlClassifierFeatureResult*>(result);
|
||||
|
||||
ipcResult->uri() = r->URI();
|
||||
r->Feature()->GetName(ipcResult->featureName());
|
||||
ipcResult->matchingList() = r->List();
|
||||
}
|
||||
|
|
|
@ -516,8 +516,6 @@ partial interface Document {
|
|||
// For more information on Flash classification, see
|
||||
// toolkit/components/url-classifier/flash-block-lists.rst
|
||||
enum FlashClassification {
|
||||
"unclassified", // Denotes a classification that has not yet been computed.
|
||||
// Allows for lazy classification.
|
||||
"unknown", // Site is not on the whitelist or blacklist
|
||||
"allowed", // Site is on the Flash whitelist
|
||||
"denied" // Site is on the Flash blacklist
|
||||
|
|
|
@ -920,13 +920,13 @@ void Grouper::PaintContainerItem(DIGroup* aGroup, nsDisplayItem* aItem,
|
|||
case DisplayItemType::TYPE_TRANSFORM: {
|
||||
DisplayItemClip currentClip = aItem->GetClip();
|
||||
|
||||
gfx::Matrix matrix;
|
||||
gfxContextMatrixAutoSaveRestore saveMatrix;
|
||||
if (currentClip.HasClip()) {
|
||||
aContext->Save();
|
||||
currentClip.ApplyTo(aContext, this->mAppUnitsPerDevPixel);
|
||||
aContext->GetDrawTarget()->FlushItem(aItemBounds);
|
||||
} else {
|
||||
matrix = aContext->CurrentMatrix();
|
||||
saveMatrix.SetContext(aContext);
|
||||
}
|
||||
|
||||
auto transformItem = static_cast<nsDisplayTransform*>(aItem);
|
||||
|
@ -946,13 +946,11 @@ void Grouper::PaintContainerItem(DIGroup* aGroup, nsDisplayItem* aItem,
|
|||
aContext->Multiply(ThebesMatrix(trans2d));
|
||||
aGroup->PaintItemRange(this, aChildren->GetBottom(), nullptr, aContext,
|
||||
aRecorder);
|
||||
}
|
||||
|
||||
if (currentClip.HasClip()) {
|
||||
aContext->Restore();
|
||||
aContext->GetDrawTarget()->FlushItem(aItemBounds);
|
||||
} else {
|
||||
aContext->SetMatrix(matrix);
|
||||
}
|
||||
if (currentClip.HasClip()) {
|
||||
aContext->Restore();
|
||||
aContext->GetDrawTarget()->FlushItem(aItemBounds);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -28,12 +28,6 @@
|
|||
|
||||
#include "base/basictypes.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// For FILETIME in FromFileTime, until it moves to a new converter class.
|
||||
// See TODO(iyengar) below.
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
namespace base {
|
||||
|
||||
class Time;
|
||||
|
@ -199,11 +193,6 @@ class Time {
|
|||
static Time FromDoubleT(double dt);
|
||||
double ToDoubleT() const;
|
||||
|
||||
#if defined(OS_WIN)
|
||||
static Time FromFileTime(FILETIME ft);
|
||||
FILETIME ToFileTime() const;
|
||||
#endif
|
||||
|
||||
// Converts an exploded structure representing either the local time or UTC
|
||||
// into a Time class.
|
||||
static Time FromUTCExploded(const Exploded& exploded) {
|
||||
|
@ -391,11 +380,6 @@ class TimeTicks {
|
|||
|
||||
// Tick count in microseconds.
|
||||
int64_t ticks_;
|
||||
|
||||
#if defined(OS_WIN)
|
||||
typedef DWORD (*TickFunctionType)(void);
|
||||
static TickFunctionType SetMockTickFunction(TickFunctionType ticker);
|
||||
#endif
|
||||
};
|
||||
|
||||
inline TimeTicks TimeDelta::operator+(TimeTicks t) const {
|
||||
|
|
|
@ -138,17 +138,6 @@ Time Time::NowFromSystemTime() {
|
|||
return Time(initial_time);
|
||||
}
|
||||
|
||||
// static
|
||||
Time Time::FromFileTime(FILETIME ft) {
|
||||
return Time(FileTimeToMicroseconds(ft));
|
||||
}
|
||||
|
||||
FILETIME Time::ToFileTime() const {
|
||||
FILETIME utc_ft;
|
||||
MicrosecondsToFileTime(us_, &utc_ft);
|
||||
return utc_ft;
|
||||
}
|
||||
|
||||
// static
|
||||
Time Time::FromExploded(bool is_local, const Exploded& exploded) {
|
||||
// Create the system struct representing our exploded time. It will either be
|
||||
|
@ -256,14 +245,6 @@ class NowSingleton {
|
|||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
TimeTicks::TickFunctionType TimeTicks::SetMockTickFunction(
|
||||
TickFunctionType ticker) {
|
||||
TickFunctionType old = tick_function;
|
||||
tick_function = ticker;
|
||||
return old;
|
||||
}
|
||||
|
||||
// static
|
||||
TimeTicks TimeTicks::Now() {
|
||||
return TimeTicks() + NowSingleton::instance().Now();
|
||||
|
|
|
@ -862,8 +862,6 @@ description =
|
|||
description =
|
||||
[PContent::PURLClassifier]
|
||||
description =
|
||||
[PContent::ClassifyLocal]
|
||||
description =
|
||||
[PContent::GetGfxVars]
|
||||
description =
|
||||
[PContent::ReadFontList]
|
||||
|
|
|
@ -8,10 +8,10 @@ crate-type = ["rlib"]
|
|||
name = "baldrdash"
|
||||
|
||||
[dependencies]
|
||||
cranelift-codegen = "0.25.0"
|
||||
cranelift-wasm = "0.25.0"
|
||||
cranelift-codegen = "0.26.0"
|
||||
cranelift-wasm = "0.26.0"
|
||||
target-lexicon = "0.2.0"
|
||||
log = { version = "0.4.4", default-features = false, features = ["release_max_level_info"] }
|
||||
log = { version = "0.4.5", default-features = false, features = ["release_max_level_info"] }
|
||||
env_logger = "0.5.6"
|
||||
|
||||
[build-dependencies]
|
||||
|
|
|
@ -48,7 +48,8 @@ fn main() {
|
|||
"-std=gnu++14",
|
||||
"-fno-sized-deallocation",
|
||||
"-DRUST_BINDGEN",
|
||||
]).clang_arg("-I../..");
|
||||
])
|
||||
.clang_arg("-I../..");
|
||||
|
||||
match env::var_os("MOZ_TOPOBJDIR") {
|
||||
Some(path) => {
|
||||
|
|
|
@ -21,11 +21,11 @@ extern crate target_lexicon;
|
|||
extern crate log;
|
||||
extern crate env_logger;
|
||||
|
||||
mod baldrapi; // Low-level C API, ignore this.
|
||||
mod baldrapi; // Low-level C API, ignore this.
|
||||
mod baldrdash; // High-level Rust API, use this.
|
||||
mod compile; // Cranelift function compiler.
|
||||
mod cpu; // CPU detection and `TargetISA` configuration.
|
||||
mod utils; // Helpers for other source files.
|
||||
mod compile; // Cranelift function compiler.
|
||||
mod cpu; // CPU detection and `TargetISA` configuration.
|
||||
mod utils; // Helpers for other source files.
|
||||
mod wasm2clif; // WebAssembly to Cranelift translation callbacks.
|
||||
|
||||
use baldrdash::{CompiledFunc, FuncCompileInput, ModuleEnvironment, StaticEnvironment};
|
||||
|
|
|
@ -62,6 +62,11 @@ fn imm64(offset: usize) -> ir::immediates::Imm64 {
|
|||
(offset as i64).into()
|
||||
}
|
||||
|
||||
/// Convert a usize offset into a `Uimm64`.
|
||||
fn uimm64(offset: usize) -> ir::immediates::Uimm64 {
|
||||
(offset as u64).into()
|
||||
}
|
||||
|
||||
/// Initialize a `Signature` from a wasm signature.
|
||||
fn init_sig_from_wsig(sig: &mut ir::Signature, wsig: bd::FuncTypeWithId) {
|
||||
sig.clear(CallConv::Baldrdash);
|
||||
|
@ -301,7 +306,8 @@ impl<'a, 'b, 'c> TransEnv<'a, 'b, 'c> {
|
|||
base: vmctx,
|
||||
offset: imm64(self.static_env.cxTlsOffset),
|
||||
global_type: native_pointer_type(),
|
||||
}).into();
|
||||
})
|
||||
.into();
|
||||
}
|
||||
if self.realm_addr.is_none() {
|
||||
let vmctx = self.get_vmctx_gv(&mut pos.func);
|
||||
|
@ -311,7 +317,8 @@ impl<'a, 'b, 'c> TransEnv<'a, 'b, 'c> {
|
|||
base: vmctx,
|
||||
offset: imm64(self.static_env.realmTlsOffset),
|
||||
global_type: native_pointer_type(),
|
||||
}).into();
|
||||
})
|
||||
.into();
|
||||
}
|
||||
|
||||
let ptr = native_pointer_type();
|
||||
|
@ -389,35 +396,31 @@ impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
|
|||
let mut pos = FuncCursor::new(func);
|
||||
pos.next_ebb().expect("empty function");
|
||||
pos.next_inst();
|
||||
GlobalVariable::Const(global.emit_constant(&mut pos))
|
||||
return GlobalVariable::Const(global.emit_constant(&mut pos));
|
||||
}
|
||||
|
||||
// This is a global variable. Here we don't care if it is mutable or not.
|
||||
let vmctx_gv = self.get_vmctx_gv(func);
|
||||
let offset = global.tls_offset();
|
||||
|
||||
// Some globals are represented as a pointer to the actual data, in which case we
|
||||
// must do an extra dereference to get to them.
|
||||
let (base_gv, offset) = if global.is_indirect() {
|
||||
let gv = func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: vmctx_gv,
|
||||
offset: offset32(offset),
|
||||
global_type: native_pointer_type(),
|
||||
readonly: false,
|
||||
});
|
||||
(gv, 0.into())
|
||||
} else {
|
||||
// This is a global variable. Here we don't care if it is mutable or not.
|
||||
let offset = global.tls_offset();
|
||||
let mut gv = self.get_vmctx_gv(func);
|
||||
(vmctx_gv, offset32(offset))
|
||||
};
|
||||
|
||||
// Some globals are represented as a pointer to the actual data, in which case we
|
||||
// must do an extra dereference to get to them.
|
||||
if global.is_indirect() {
|
||||
gv = func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: gv,
|
||||
offset: offset32(offset),
|
||||
global_type: native_pointer_type(),
|
||||
readonly: false,
|
||||
});
|
||||
} else {
|
||||
gv = func.create_global_value(ir::GlobalValueData::IAddImm {
|
||||
base: gv,
|
||||
offset: imm64(offset),
|
||||
global_type: native_pointer_type(),
|
||||
});
|
||||
}
|
||||
|
||||
// Create a Cranelift global variable. We don't need to remember the reference, the
|
||||
// function translator does that for us.
|
||||
GlobalVariable::Memory {
|
||||
gv,
|
||||
ty: global.value_type().into(),
|
||||
}
|
||||
GlobalVariable::Memory {
|
||||
gv: base_gv,
|
||||
ty: global.value_type().into(),
|
||||
offset,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -433,13 +436,13 @@ impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
|
|||
global_type: native_pointer_type(),
|
||||
readonly: true,
|
||||
});
|
||||
let min_size = ir::immediates::Imm64::new(self.env.min_memory_length());
|
||||
let guard_size = imm64(self.static_env.memoryGuardSize);
|
||||
let min_size = ir::immediates::Uimm64::new(self.env.min_memory_length() as u64);
|
||||
let guard_size = uimm64(self.static_env.memoryGuardSize);
|
||||
|
||||
let bound = self.static_env.staticMemoryBound;
|
||||
let style = if bound > 0 {
|
||||
// We have a static heap.
|
||||
let bound = (bound as i64).into();
|
||||
let bound = (bound as u64).into();
|
||||
ir::HeapStyle::Static { bound }
|
||||
} else {
|
||||
// Get the `TlsData::boundsCheckLimit` field.
|
||||
|
@ -455,7 +458,7 @@ impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
|
|||
func.create_heap(ir::HeapData {
|
||||
base,
|
||||
min_size,
|
||||
guard_size,
|
||||
offset_guard_size: guard_size,
|
||||
style,
|
||||
index_type: ir::types::I32,
|
||||
})
|
||||
|
@ -498,9 +501,9 @@ impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
|
|||
|
||||
func.create_table(ir::TableData {
|
||||
base_gv,
|
||||
min_size: ir::immediates::Imm64::new(0),
|
||||
min_size: ir::immediates::Uimm64::new(0),
|
||||
bound_gv,
|
||||
element_size: ir::immediates::Imm64::new(i64::from(self.pointer_bytes()) * 2),
|
||||
element_size: ir::immediates::Uimm64::new(u64::from(self.pointer_bytes()) * 2),
|
||||
index_type: ir::types::I32,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1940,6 +1940,22 @@ VARCACHE_PREF(
|
|||
)
|
||||
#undef PREF_VALUE
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Plugins prefs
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
VARCACHE_PREF(
|
||||
"plugins.flashBlock.enabled",
|
||||
plugins_flashBlock_enabled,
|
||||
bool, false
|
||||
)
|
||||
|
||||
VARCACHE_PREF(
|
||||
"plugins.http_https_only",
|
||||
plugins_http_https_only,
|
||||
bool, true
|
||||
)
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Reporting API
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -5638,9 +5638,6 @@ pref("urlclassifier.flashSubDocTable", "block-flashsubdoc-digest256");
|
|||
pref("urlclassifier.flashSubDocExceptTable", "except-flashsubdoc-digest256");
|
||||
pref("urlclassifier.flashInfobarTable", "except-flashinfobar-digest256");
|
||||
|
||||
pref("plugins.http_https_only", true);
|
||||
pref("plugins.flashBlock.enabled", false);
|
||||
|
||||
// Turn off Spatial navigation by default.
|
||||
pref("snav.enabled", false);
|
||||
|
||||
|
|
|
@ -52,6 +52,13 @@ SimpleChannelParent::NotifyTrackingResource(bool aIsThirdParty) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SimpleChannelParent::NotifyFlashPluginStateChanged(
|
||||
nsIHttpChannel::FlashPluginState aState) {
|
||||
// Nothing to do.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SimpleChannelParent::SetClassifierMatchedInfo(const nsACString& aList,
|
||||
const nsACString& aProvider,
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsIStreamListener.idl"
|
||||
#include "nsIHttpChannel.idl"
|
||||
|
||||
interface nsITabParent;
|
||||
|
||||
|
@ -46,6 +47,11 @@ interface nsIParentChannel : nsIStreamListener
|
|||
*/
|
||||
[noscript] void notifyTrackingCookieBlocked(in uint32_t aRejectedReason);
|
||||
|
||||
/**
|
||||
* Called to notify the HttpChannelChild that flash plugin state has changed.
|
||||
*/
|
||||
[noscript] void notifyFlashPluginStateChanged(in nsIHttpChannel_FlashPluginState aState);
|
||||
|
||||
/**
|
||||
* Called to set matched information when URL matches SafeBrowsing list.
|
||||
* @param aList
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "ipc/IPCMessageUtils.h"
|
||||
#include "nsExceptionHandler.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsString.h"
|
||||
#include "prio.h"
|
||||
|
@ -179,6 +180,12 @@ struct ParamTraits<mozilla::net::ResourceTimingStruct> {
|
|||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<nsIHttpChannel::FlashPluginState>
|
||||
: public ContiguousEnumSerializerInclusive<
|
||||
nsIHttpChannel::FlashPluginState, nsIHttpChannel::FlashPluginUnknown,
|
||||
nsIHttpChannel::FlashPluginLastValue> {};
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
#endif // mozilla_net_NeckoMessageUtils_h
|
||||
|
|
|
@ -52,6 +52,13 @@ DataChannelParent::NotifyTrackingResource(bool aIsThirdParty) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DataChannelParent::NotifyFlashPluginStateChanged(
|
||||
nsIHttpChannel::FlashPluginState aState) {
|
||||
// Nothing to do.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DataChannelParent::SetClassifierMatchedInfo(const nsACString &aList,
|
||||
const nsACString &aProvider,
|
||||
|
|
|
@ -52,6 +52,13 @@ FileChannelParent::NotifyTrackingResource(bool aIsThirdParty) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FileChannelParent::NotifyFlashPluginStateChanged(
|
||||
nsIHttpChannel::FlashPluginState aState) {
|
||||
// Nothing to do.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FileChannelParent::SetClassifierMatchedInfo(const nsACString &aList,
|
||||
const nsACString &aProvider,
|
||||
|
|
|
@ -523,6 +523,13 @@ FTPChannelParent::NotifyTrackingResource(bool aIsThirdParty) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FTPChannelParent::NotifyFlashPluginStateChanged(
|
||||
nsIHttpChannel::FlashPluginState aState) {
|
||||
// One day, this should probably be filled in.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FTPChannelParent::SetClassifierMatchedInfo(const nsACString& aList,
|
||||
const nsACString& aProvider,
|
||||
|
|
|
@ -358,6 +358,25 @@ IPCResult HttpBackgroundChannelChild::RecvNotifyTrackingResource(
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
IPCResult HttpBackgroundChannelChild::RecvNotifyFlashPluginStateChanged(
|
||||
const nsIHttpChannel::FlashPluginState& aState) {
|
||||
LOG(
|
||||
("HttpBackgroundChannelChild::RecvNotifyFlashPluginStateChanged "
|
||||
"[this=%p]\n",
|
||||
this));
|
||||
MOZ_ASSERT(OnSocketThread());
|
||||
|
||||
if (NS_WARN_IF(!mChannelChild)) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
// NotifyFlashPluginStateChanged has no order dependency to OnStartRequest.
|
||||
// It this be handled as soon as possible
|
||||
mChannelChild->ProcessNotifyFlashPluginStateChanged(aState);
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
IPCResult HttpBackgroundChannelChild::RecvSetClassifierMatchedInfo(
|
||||
const ClassifierInfo& info) {
|
||||
LOG(("HttpBackgroundChannelChild::RecvSetClassifierMatchedInfo [this=%p]\n",
|
||||
|
|
|
@ -72,6 +72,9 @@ class HttpBackgroundChannelChild final : public PHttpBackgroundChannelChild {
|
|||
|
||||
IPCResult RecvNotifyTrackingResource(const bool& aIsThirdParty) override;
|
||||
|
||||
IPCResult RecvNotifyFlashPluginStateChanged(
|
||||
const nsIHttpChannel::FlashPluginState& aState) override;
|
||||
|
||||
IPCResult RecvSetClassifierMatchedInfo(const ClassifierInfo& info) override;
|
||||
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
|
|
@ -426,6 +426,37 @@ bool HttpBackgroundChannelParent::OnNotifyTrackingResource(bool aIsThirdParty) {
|
|||
return SendNotifyTrackingResource(aIsThirdParty);
|
||||
}
|
||||
|
||||
bool HttpBackgroundChannelParent::OnNotifyFlashPluginStateChanged(
|
||||
nsIHttpChannel::FlashPluginState aState) {
|
||||
LOG(
|
||||
("HttpBackgroundChannelParent::OnNotifyFlashPluginStateChanged "
|
||||
"[this=%p]\n",
|
||||
this));
|
||||
AssertIsInMainProcess();
|
||||
|
||||
if (NS_WARN_IF(!mIPCOpened)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsOnBackgroundThread()) {
|
||||
MutexAutoLock lock(mBgThreadMutex);
|
||||
RefPtr<HttpBackgroundChannelParent> self = this;
|
||||
nsresult rv = mBackgroundThread->Dispatch(
|
||||
NS_NewRunnableFunction(
|
||||
"net::HttpBackgroundChannelParent::OnNotifyFlashPluginStateChanged",
|
||||
[self, aState]() {
|
||||
self->OnNotifyFlashPluginStateChanged(aState);
|
||||
}),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
return SendNotifyFlashPluginStateChanged(aState);
|
||||
}
|
||||
|
||||
bool HttpBackgroundChannelParent::OnSetClassifierMatchedInfo(
|
||||
const nsACString& aList, const nsACString& aProvider,
|
||||
const nsACString& aFullHash) {
|
||||
|
|
|
@ -75,6 +75,9 @@ class HttpBackgroundChannelParent final : public PHttpBackgroundChannelParent {
|
|||
// To send NotifyTrackingResource message over background channel.
|
||||
bool OnNotifyTrackingResource(bool aIsThirdParty);
|
||||
|
||||
// To send NotifyFlashPluginStateChanged message over background channel.
|
||||
bool OnNotifyFlashPluginStateChanged(nsIHttpChannel::FlashPluginState aState);
|
||||
|
||||
// To send SetClassifierMatchedInfo message over background channel.
|
||||
bool OnSetClassifierMatchedInfo(const nsACString& aList,
|
||||
const nsACString& aProvider,
|
||||
|
|
|
@ -168,6 +168,7 @@ HttpBaseChannel::HttpBaseChannel()
|
|||
mCanceled(false),
|
||||
mIsFirstPartyTrackingResource(false),
|
||||
mIsThirdPartyTrackingResource(false),
|
||||
mFlashPluginState(nsIHttpChannel::FlashPluginUnknown),
|
||||
mLoadFlags(LOAD_NORMAL),
|
||||
mCaps(0),
|
||||
mClassOfService(0),
|
||||
|
@ -319,6 +320,12 @@ void HttpBaseChannel::SetIsTrackingResource(bool aIsThirdParty) {
|
|||
}
|
||||
}
|
||||
|
||||
void HttpBaseChannel::SetFlashPluginState(
|
||||
nsIHttpChannel::FlashPluginState aState) {
|
||||
LOG(("HttpBaseChannel::SetFlashPluginState %p", this));
|
||||
mFlashPluginState = aState;
|
||||
}
|
||||
|
||||
nsresult HttpBaseChannel::Init(nsIURI* aURI, uint32_t aCaps,
|
||||
nsProxyInfo* aProxyInfo,
|
||||
uint32_t aProxyResolveFlags, nsIURI* aProxyURI,
|
||||
|
@ -1485,6 +1492,13 @@ HttpBaseChannel::GetIsThirdPartyTrackingResource(bool* aIsTrackingResource) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpBaseChannel::GetFlashPluginState(nsIHttpChannel::FlashPluginState* aState) {
|
||||
uint32_t flashPluginState = mFlashPluginState;
|
||||
*aState = (nsIHttpChannel::FlashPluginState)flashPluginState;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpBaseChannel::OverrideTrackingFlagsForDocumentCookieAccessor(
|
||||
nsIHttpChannel* aDocumentChannel) {
|
||||
|
|
|
@ -238,6 +238,8 @@ class HttpBaseChannel : public nsHashPropertyBag,
|
|||
bool *aIsTrackingResource) override;
|
||||
NS_IMETHOD OverrideTrackingFlagsForDocumentCookieAccessor(
|
||||
nsIHttpChannel *aDocumentChannel) override;
|
||||
NS_IMETHOD GetFlashPluginState(
|
||||
nsIHttpChannel::FlashPluginState *aState) override;
|
||||
|
||||
// nsIHttpChannelInternal
|
||||
NS_IMETHOD GetDocumentURI(nsIURI **aDocumentURI) override;
|
||||
|
@ -413,6 +415,8 @@ class HttpBaseChannel : public nsHashPropertyBag,
|
|||
|
||||
void SetIsTrackingResource(bool aIsThirdParty);
|
||||
|
||||
void SetFlashPluginState(nsIHttpChannel::FlashPluginState aState);
|
||||
|
||||
const uint64_t &ChannelId() const { return mChannelId; }
|
||||
|
||||
void InternalSetUploadStream(nsIInputStream *uploadStream) {
|
||||
|
@ -647,6 +651,7 @@ class HttpBaseChannel : public nsHashPropertyBag,
|
|||
Atomic<bool, ReleaseAcquire> mCanceled;
|
||||
Atomic<bool, ReleaseAcquire> mIsFirstPartyTrackingResource;
|
||||
Atomic<bool, ReleaseAcquire> mIsThirdPartyTrackingResource;
|
||||
Atomic<uint32_t, ReleaseAcquire> mFlashPluginState;
|
||||
|
||||
uint32_t mLoadFlags;
|
||||
uint32_t mCaps;
|
||||
|
|
|
@ -1862,6 +1862,15 @@ void HttpChannelChild::ProcessNotifyTrackingResource(bool aIsThirdParty) {
|
|||
SetIsTrackingResource(aIsThirdParty);
|
||||
}
|
||||
|
||||
void HttpChannelChild::ProcessNotifyFlashPluginStateChanged(
|
||||
nsIHttpChannel::FlashPluginState aState) {
|
||||
LOG(("HttpChannelChild::ProcessNotifyFlashPluginStateChanged [this=%p]\n",
|
||||
this));
|
||||
MOZ_ASSERT(OnSocketThread());
|
||||
|
||||
SetFlashPluginState(aState);
|
||||
}
|
||||
|
||||
void HttpChannelChild::FlushedForDiversion() {
|
||||
LOG(("HttpChannelChild::FlushedForDiversion [this=%p]\n", this));
|
||||
MOZ_RELEASE_ASSERT(mDivertingToParent);
|
||||
|
|
|
@ -265,6 +265,8 @@ class HttpChannelChild final : public PHttpChannelChild,
|
|||
void ProcessNotifyCookieAllowed();
|
||||
void ProcessNotifyTrackingCookieBlocked(uint32_t aRejectedReason);
|
||||
void ProcessNotifyTrackingResource(bool aIsThirdParty);
|
||||
void ProcessNotifyFlashPluginStateChanged(
|
||||
nsIHttpChannel::FlashPluginState aState);
|
||||
void ProcessSetClassifierMatchedInfo(const nsCString& aList,
|
||||
const nsCString& aProvider,
|
||||
const nsCString& aFullHash);
|
||||
|
|
|
@ -1826,6 +1826,17 @@ HttpChannelParent::NotifyTrackingResource(bool aIsThirdParty) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpChannelParent::NotifyFlashPluginStateChanged(
|
||||
nsIHttpChannel::FlashPluginState aState) {
|
||||
LOG(("HttpChannelParent::NotifyFlashPluginStateChanged [this=%p]\n", this));
|
||||
if (!mIPCClosed) {
|
||||
MOZ_ASSERT(mBgParent);
|
||||
Unused << mBgParent->OnNotifyFlashPluginStateChanged(aState);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpChannelParent::Delete() {
|
||||
if (!mIPCClosed) Unused << DoSendDeleteSelf();
|
||||
|
|
|
@ -88,6 +88,12 @@ NullHttpChannel::GetIsTrackingResource(bool *aIsTrackingResource) {
|
|||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
NullHttpChannel::GetFlashPluginState(
|
||||
nsIHttpChannel::FlashPluginState *aResult) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
NullHttpChannel::GetIsThirdPartyTrackingResource(bool *aIsTrackingResource) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
|
|
|
@ -13,6 +13,7 @@ include "mozilla/net/NeckoMessageUtils.h";
|
|||
|
||||
using class nsHttpHeaderArray from "nsHttpHeaderArray.h";
|
||||
using struct mozilla::net::ResourceTimingStruct from "mozilla/net/TimingStruct.h";
|
||||
using nsIHttpChannel::FlashPluginState from "mozilla/net/NeckoMessageUtils.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
@ -66,6 +67,10 @@ child:
|
|||
// protection list.
|
||||
async NotifyTrackingResource(bool aIsThirdParty);
|
||||
|
||||
// Tell the child that the current channel's document is not allowed to load
|
||||
// flash content.
|
||||
async NotifyFlashPluginStateChanged(FlashPluginState aState);
|
||||
|
||||
// Tell the child information of matched URL againts SafeBrowsing list
|
||||
async SetClassifierMatchedInfo(ClassifierInfo info);
|
||||
|
||||
|
|
|
@ -495,6 +495,20 @@ interface nsIHttpChannel : nsIChannel
|
|||
*/
|
||||
[infallible] readonly attribute boolean isThirdPartyTrackingResource;
|
||||
|
||||
/**
|
||||
* Returns the allowing status for flash plugin for this channel.
|
||||
*/
|
||||
cenum FlashPluginState : 8 {
|
||||
FlashPluginUnknown = 0,
|
||||
FlashPluginAllowed = 1,
|
||||
FlashPluginDenied = 2,
|
||||
FlashPluginDeniedInSubdocuments = 3,
|
||||
|
||||
// Keep this equal to the last value.
|
||||
FlashPluginLastValue = 3,
|
||||
};
|
||||
[infallible] readonly attribute nsIHttpChannel_FlashPluginState flashPluginState;
|
||||
|
||||
/**
|
||||
* This method is used by the document.cookie call site in order
|
||||
* to override the tracking status of an HTTP channel. This should
|
||||
|
|
|
@ -765,6 +765,13 @@ nsViewSourceChannel::GetIsTrackingResource(bool *aIsTrackingResource) {
|
|||
: mHttpChannel->GetIsTrackingResource(aIsTrackingResource);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsViewSourceChannel::GetFlashPluginState(
|
||||
nsIHttpChannel::FlashPluginState *aResult) {
|
||||
return !mHttpChannel ? NS_ERROR_NULL_POINTER
|
||||
: mHttpChannel->GetFlashPluginState(aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsViewSourceChannel::GetIsThirdPartyTrackingResource(
|
||||
bool *aIsTrackingResource) {
|
||||
|
|
|
@ -24,6 +24,74 @@ namespace net {
|
|||
|
||||
namespace {
|
||||
|
||||
// When we do blacklist/whitelist classification, from a list of features, we
|
||||
// need to aggregate them per URI, because not all the features work with the
|
||||
// same channel's URI.
|
||||
// This struct contains only the features able to deal with a particular URI.
|
||||
// See more in GetFeatureTasks().
|
||||
struct FeatureTask {
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
// Let's use RefPtr<> here, because this needs to be used with methods which
|
||||
// require it.
|
||||
nsTArray<RefPtr<nsIUrlClassifierFeature>> mFeatures;
|
||||
};
|
||||
|
||||
// Features are able to classify particular URIs from a channel. For instance,
|
||||
// tracking-annotation feature uses the top-level URI to whitelist the current
|
||||
// channel's URI; flash feature always uses the channel's URI. Because of
|
||||
// this, this function aggregates feature per URI in an array of FeatureTask
|
||||
// object.
|
||||
nsresult GetFeatureTasks(
|
||||
nsIChannel* aChannel,
|
||||
const nsTArray<nsCOMPtr<nsIUrlClassifierFeature>>& aFeatures,
|
||||
nsIUrlClassifierFeature::listType aListType,
|
||||
nsTArray<FeatureTask>& aTasks) {
|
||||
MOZ_ASSERT(!aFeatures.IsEmpty());
|
||||
|
||||
// Let's unify features per nsIURI.
|
||||
for (nsIUrlClassifierFeature* feature : aFeatures) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv =
|
||||
feature->GetURIByListType(aChannel, aListType, getter_AddRefs(uri));
|
||||
if (NS_WARN_IF(NS_FAILED(rv)) || !uri) {
|
||||
if (UC_LOG_ENABLED()) {
|
||||
nsAutoCString errorName;
|
||||
GetErrorName(rv, errorName);
|
||||
UC_LOG(
|
||||
("GetFeatureTasks got an unexpected error (rv=%s) while trying to "
|
||||
"create a whitelist URI. Allowing tracker.",
|
||||
errorName.get()));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(uri);
|
||||
|
||||
bool found = false;
|
||||
for (FeatureTask& task : aTasks) {
|
||||
bool equal = false;
|
||||
rv = task.mURI->Equals(uri, &equal);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (equal) {
|
||||
task.mFeatures.AppendElement(feature);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
FeatureTask* task = aTasks.AppendElement();
|
||||
task->mURI = uri;
|
||||
task->mFeatures.AppendElement(feature);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult TrackerFound(
|
||||
const nsTArray<RefPtr<nsIUrlClassifierFeatureResult>>& aResults,
|
||||
nsIChannel* aChannel, const std::function<void()>& aCallback) {
|
||||
|
@ -48,81 +116,6 @@ nsresult TrackerFound(
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult CreateWhiteListURI(nsIChannel* aChannel, nsIURI** aURI) {
|
||||
MOZ_ASSERT(aChannel);
|
||||
MOZ_ASSERT(aURI);
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIHttpChannelInternal> chan = do_QueryInterface(aChannel, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!chan) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> topWinURI;
|
||||
rv = chan->GetTopWindowURI(getter_AddRefs(topWinURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!topWinURI) {
|
||||
if (UC_LOG_ENABLED()) {
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIHttpChannel> httpChan = do_QueryInterface(aChannel, &rv);
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = httpChan->GetURI(getter_AddRefs(uri));
|
||||
nsAutoCString spec;
|
||||
uri->GetAsciiSpec(spec);
|
||||
spec.Truncate(
|
||||
std::min(spec.Length(), UrlClassifierCommon::sMaxSpecLength));
|
||||
UC_LOG(
|
||||
("CreateWhiteListURI: No window URI associated with %s", spec.get()));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIScriptSecurityManager> securityManager =
|
||||
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIPrincipal> chanPrincipal;
|
||||
rv = securityManager->GetChannelURIPrincipal(aChannel,
|
||||
getter_AddRefs(chanPrincipal));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Craft a whitelist URL like "toplevel.page/?resource=third.party.domain"
|
||||
nsAutoCString pageHostname, resourceDomain;
|
||||
rv = topWinURI->GetHost(pageHostname);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = chanPrincipal->GetBaseDomain(resourceDomain);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsAutoCString whitelistEntry = NS_LITERAL_CSTRING("http://") + pageHostname +
|
||||
NS_LITERAL_CSTRING("/?resource=") +
|
||||
resourceDomain;
|
||||
UC_LOG(("CreateWhiteListURI: Looking for %s in the whitelist (channel=%p)",
|
||||
whitelistEntry.get(), aChannel));
|
||||
|
||||
nsCOMPtr<nsIURI> whitelistURI;
|
||||
rv = NS_NewURI(getter_AddRefs(whitelistURI), whitelistEntry);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
whitelistURI.forget(aURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult IsTrackerWhitelisted(
|
||||
nsIURI* aWhiteListURI,
|
||||
const nsTArray<RefPtr<nsIUrlClassifierFeature>>& aFeatures,
|
||||
nsIUrlClassifierFeatureCallback* aCallback) {
|
||||
MOZ_ASSERT(aWhiteListURI);
|
||||
MOZ_ASSERT(!aFeatures.IsEmpty());
|
||||
MOZ_ASSERT(aCallback);
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIURIClassifier> uriClassifier =
|
||||
do_GetService(NS_URICLASSIFIERSERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return uriClassifier->AsyncClassifyLocalWithFeatures(
|
||||
aWhiteListURI, aFeatures, nsIUrlClassifierFeature::whitelist, aCallback);
|
||||
}
|
||||
|
||||
// This class is designed to get the results of checking whitelist.
|
||||
class WhitelistClassifierCallback final
|
||||
: public nsIUrlClassifierFeatureCallback {
|
||||
|
@ -131,25 +124,34 @@ class WhitelistClassifierCallback final
|
|||
NS_DECL_NSIURLCLASSIFIERFEATURECALLBACK
|
||||
|
||||
WhitelistClassifierCallback(
|
||||
nsIChannel* aChannel, nsIURI* aURI,
|
||||
nsIChannel* aChannel,
|
||||
const nsTArray<RefPtr<nsIUrlClassifierFeatureResult>>& aBlacklistResults,
|
||||
std::function<void()>& aCallback)
|
||||
: mChannel(aChannel),
|
||||
mURI(aURI),
|
||||
mTaskCount(0),
|
||||
mBlacklistResults(aBlacklistResults),
|
||||
mChannelCallback(aCallback) {
|
||||
MOZ_ASSERT(mChannel);
|
||||
MOZ_ASSERT(mURI);
|
||||
MOZ_ASSERT(!mBlacklistResults.IsEmpty());
|
||||
}
|
||||
|
||||
void SetTaskCount(uint32_t aTaskCount) {
|
||||
MOZ_ASSERT(aTaskCount > 0);
|
||||
mTaskCount = aTaskCount;
|
||||
}
|
||||
|
||||
private:
|
||||
~WhitelistClassifierCallback() = default;
|
||||
|
||||
nsresult OnClassifyCompleteInternal();
|
||||
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
uint32_t mTaskCount;
|
||||
nsTArray<RefPtr<nsIUrlClassifierFeatureResult>> mBlacklistResults;
|
||||
std::function<void()> mChannelCallback;
|
||||
|
||||
nsTArray<RefPtr<nsIUrlClassifierFeatureResult>> mWhitelistResults;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(WhitelistClassifierCallback, nsIUrlClassifierFeatureCallback)
|
||||
|
@ -157,18 +159,33 @@ NS_IMPL_ISUPPORTS(WhitelistClassifierCallback, nsIUrlClassifierFeatureCallback)
|
|||
NS_IMETHODIMP
|
||||
WhitelistClassifierCallback::OnClassifyComplete(
|
||||
const nsTArray<RefPtr<nsIUrlClassifierFeatureResult>>& aWhitelistResults) {
|
||||
MOZ_ASSERT(mTaskCount > 0);
|
||||
|
||||
UC_LOG(("WhitelistClassifierCallback[%p]:OnClassifyComplete channel=%p", this,
|
||||
mChannel.get()));
|
||||
|
||||
mWhitelistResults.AppendElements(aWhitelistResults);
|
||||
|
||||
if (--mTaskCount) {
|
||||
// More callbacks will come.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return OnClassifyCompleteInternal();
|
||||
}
|
||||
|
||||
nsresult WhitelistClassifierCallback::OnClassifyCompleteInternal() {
|
||||
nsTArray<RefPtr<nsIUrlClassifierFeatureResult>> remainingResults;
|
||||
|
||||
for (nsIUrlClassifierFeatureResult* blacklistResult : mBlacklistResults) {
|
||||
nsIUrlClassifierFeature* blacklistFeature =
|
||||
static_cast<UrlClassifierFeatureResult*>(blacklistResult)->Feature();
|
||||
UrlClassifierFeatureResult* result =
|
||||
static_cast<UrlClassifierFeatureResult*>(blacklistResult);
|
||||
|
||||
nsIUrlClassifierFeature* blacklistFeature = result->Feature();
|
||||
MOZ_ASSERT(blacklistFeature);
|
||||
|
||||
bool found = false;
|
||||
for (nsIUrlClassifierFeatureResult* whitelistResult : aWhitelistResults) {
|
||||
for (nsIUrlClassifierFeatureResult* whitelistResult : mWhitelistResults) {
|
||||
// We can do pointer comparison because Features are singletons.
|
||||
if (static_cast<UrlClassifierFeatureResult*>(whitelistResult)
|
||||
->Feature() == blacklistFeature) {
|
||||
|
@ -188,13 +205,12 @@ WhitelistClassifierCallback::OnClassifyComplete(
|
|||
continue;
|
||||
}
|
||||
|
||||
if (nsContentUtils::IsURIInList(mURI, skipList)) {
|
||||
if (nsContentUtils::IsURIInList(result->URI(), skipList)) {
|
||||
if (UC_LOG_ENABLED()) {
|
||||
nsCString spec = mURI->GetSpecOrDefault();
|
||||
UC_LOG(
|
||||
("WhitelistClassifierCallback[%p]::OnClassifyComplete uri %s found "
|
||||
"in skiplist",
|
||||
this, spec.get()));
|
||||
("WhitelistClassifierCallback[%p]::OnClassifyComplete uri found in "
|
||||
"skiplist",
|
||||
this));
|
||||
}
|
||||
|
||||
continue;
|
||||
|
@ -207,13 +223,10 @@ WhitelistClassifierCallback::OnClassifyComplete(
|
|||
|
||||
if (remainingResults.IsEmpty()) {
|
||||
if (UC_LOG_ENABLED()) {
|
||||
nsCString spec = mURI->GetSpecOrDefault();
|
||||
spec.Truncate(
|
||||
std::min(spec.Length(), UrlClassifierCommon::sMaxSpecLength));
|
||||
UC_LOG(
|
||||
("WhitelistClassifierCallback[%p]::OnClassifyComplete uri %s fully "
|
||||
("WhitelistClassifierCallback[%p]::OnClassifyComplete uri fully "
|
||||
"whitelisted",
|
||||
this, spec.get()));
|
||||
this));
|
||||
}
|
||||
|
||||
mChannelCallback();
|
||||
|
@ -221,12 +234,10 @@ WhitelistClassifierCallback::OnClassifyComplete(
|
|||
}
|
||||
|
||||
if (UC_LOG_ENABLED()) {
|
||||
nsCString spec = mURI->GetSpecOrDefault();
|
||||
spec.Truncate(std::min(spec.Length(), UrlClassifierCommon::sMaxSpecLength));
|
||||
UC_LOG(
|
||||
("WhitelistClassifierCallback[%p]::OnClassifyComplete "
|
||||
"channel[%p] uri=%s, should not be whitelisted",
|
||||
this, mChannel.get(), spec.get()));
|
||||
("WhitelistClassifierCallback[%p]::OnClassifyComplete channel[%p] "
|
||||
"should not be whitelisted",
|
||||
this, mChannel.get()));
|
||||
}
|
||||
|
||||
return TrackerFound(remainingResults, mChannel, mChannelCallback);
|
||||
|
@ -239,19 +250,29 @@ class BlacklistClassifierCallback final
|
|||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIURLCLASSIFIERFEATURECALLBACK
|
||||
|
||||
BlacklistClassifierCallback(nsIChannel* aChannel, nsIURI* aURI,
|
||||
BlacklistClassifierCallback(nsIChannel* aChannel,
|
||||
std::function<void()>&& aCallback)
|
||||
: mChannel(aChannel), mURI(aURI), mChannelCallback(std::move(aCallback)) {
|
||||
: mChannel(aChannel),
|
||||
mTaskCount(0),
|
||||
mChannelCallback(std::move(aCallback)) {
|
||||
MOZ_ASSERT(mChannel);
|
||||
MOZ_ASSERT(mURI);
|
||||
}
|
||||
|
||||
void SetTaskCount(uint32_t aTaskCount) {
|
||||
MOZ_ASSERT(aTaskCount > 0);
|
||||
mTaskCount = aTaskCount;
|
||||
}
|
||||
|
||||
private:
|
||||
~BlacklistClassifierCallback() = default;
|
||||
|
||||
nsresult OnClassifyCompleteInternal();
|
||||
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
uint32_t mTaskCount;
|
||||
std::function<void()> mChannelCallback;
|
||||
|
||||
nsTArray<RefPtr<nsIUrlClassifierFeatureResult>> mResults;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(BlacklistClassifierCallback, nsIUrlClassifierFeatureCallback)
|
||||
|
@ -259,18 +280,29 @@ NS_IMPL_ISUPPORTS(BlacklistClassifierCallback, nsIUrlClassifierFeatureCallback)
|
|||
NS_IMETHODIMP
|
||||
BlacklistClassifierCallback::OnClassifyComplete(
|
||||
const nsTArray<RefPtr<nsIUrlClassifierFeatureResult>>& aResults) {
|
||||
UC_LOG(("BlacklistClassifierCallback[%p]:OnClassifyComplete", this));
|
||||
MOZ_ASSERT(mTaskCount > 0);
|
||||
|
||||
UC_LOG(("BlacklistClassifierCallback[%p]:OnClassifyComplete - remaining %d",
|
||||
this, mTaskCount));
|
||||
|
||||
mResults.AppendElements(aResults);
|
||||
|
||||
if (--mTaskCount) {
|
||||
// More callbacks will come.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return OnClassifyCompleteInternal();
|
||||
}
|
||||
|
||||
nsresult BlacklistClassifierCallback::OnClassifyCompleteInternal() {
|
||||
// All good! The URL has not been classified.
|
||||
if (aResults.IsEmpty()) {
|
||||
if (mResults.IsEmpty()) {
|
||||
if (UC_LOG_ENABLED()) {
|
||||
nsCString spec = mURI->GetSpecOrDefault();
|
||||
spec.Truncate(
|
||||
std::min(spec.Length(), UrlClassifierCommon::sMaxSpecLength));
|
||||
UC_LOG(
|
||||
("BlacklistClassifierCallback[%p]::OnClassifyComplete uri %s not "
|
||||
"found in blacklist",
|
||||
this, spec.get()));
|
||||
("BlacklistClassifierCallback[%p]::OnClassifyComplete uri not found "
|
||||
"in blacklist",
|
||||
this));
|
||||
}
|
||||
|
||||
mChannelCallback();
|
||||
|
@ -278,63 +310,79 @@ BlacklistClassifierCallback::OnClassifyComplete(
|
|||
}
|
||||
|
||||
if (UC_LOG_ENABLED()) {
|
||||
nsCString spec = mURI->GetSpecOrDefault();
|
||||
spec.Truncate(std::min(spec.Length(), UrlClassifierCommon::sMaxSpecLength));
|
||||
UC_LOG(
|
||||
("BlacklistClassifierCallback[%p]::OnClassifyComplete uri %s is in "
|
||||
("BlacklistClassifierCallback[%p]::OnClassifyComplete uri is in "
|
||||
"blacklist. Start checking whitelist.",
|
||||
this, spec.get()));
|
||||
this));
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> whitelistURI;
|
||||
nsresult rv = CreateWhiteListURI(mChannel, getter_AddRefs(whitelistURI));
|
||||
if (NS_FAILED(rv)) {
|
||||
nsAutoCString errorName;
|
||||
GetErrorName(rv, errorName);
|
||||
NS_WARNING(
|
||||
nsPrintfCString("BlacklistClassifierCallback[%p]:OnClassifyComplete "
|
||||
"got an unexpected error (rv=%s) while trying to "
|
||||
"create a whitelist URI. Allowing tracker.",
|
||||
this, errorName.get())
|
||||
.get());
|
||||
return TrackerFound(aResults, mChannel, mChannelCallback);
|
||||
nsTArray<nsCOMPtr<nsIUrlClassifierFeature>> features;
|
||||
for (nsIUrlClassifierFeatureResult* result : mResults) {
|
||||
features.AppendElement(
|
||||
static_cast<UrlClassifierFeatureResult*>(result)->Feature());
|
||||
}
|
||||
|
||||
if (!whitelistURI) {
|
||||
nsTArray<FeatureTask> tasks;
|
||||
nsresult rv = GetFeatureTasks(mChannel, features,
|
||||
nsIUrlClassifierFeature::whitelist, tasks);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return TrackerFound(mResults, mChannel, mChannelCallback);
|
||||
}
|
||||
|
||||
if (tasks.IsEmpty()) {
|
||||
UC_LOG(
|
||||
("BlacklistClassifierCallback[%p]:OnClassifyComplete could not create "
|
||||
"a whitelist URI. Ignoring whitelist.",
|
||||
this));
|
||||
|
||||
return TrackerFound(aResults, mChannel, mChannelCallback);
|
||||
return TrackerFound(mResults, mChannel, mChannelCallback);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIUrlClassifierFeatureCallback> callback =
|
||||
new WhitelistClassifierCallback(mChannel, mURI, aResults,
|
||||
mChannelCallback);
|
||||
RefPtr<WhitelistClassifierCallback> callback =
|
||||
new WhitelistClassifierCallback(mChannel, mResults, mChannelCallback);
|
||||
|
||||
// xpcom parser creates array of interfaces using RefPtr<>.
|
||||
nsTArray<RefPtr<nsIUrlClassifierFeature>> refPtrFeatures;
|
||||
for (nsIUrlClassifierFeatureResult* result : aResults) {
|
||||
refPtrFeatures.AppendElement(
|
||||
static_cast<UrlClassifierFeatureResult*>(result)->Feature());
|
||||
}
|
||||
nsCOMPtr<nsIURIClassifier> uriClassifier =
|
||||
do_GetService(NS_URICLASSIFIERSERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = IsTrackerWhitelisted(whitelistURI, refPtrFeatures, callback);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
if (UC_LOG_ENABLED()) {
|
||||
nsAutoCString errorName;
|
||||
GetErrorName(rv, errorName);
|
||||
UC_LOG(
|
||||
("BlacklistClassifierCallback[%p]:OnClassifyComplete "
|
||||
"IsTrackerWhitelisted has failed with rv=%s.",
|
||||
this, errorName.get()));
|
||||
uint32_t pendingCallbacks = 0;
|
||||
for (FeatureTask& task : tasks) {
|
||||
rv = uriClassifier->AsyncClassifyLocalWithFeatures(
|
||||
task.mURI, task.mFeatures, nsIUrlClassifierFeature::whitelist,
|
||||
callback);
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
if (UC_LOG_ENABLED()) {
|
||||
nsAutoCString errorName;
|
||||
GetErrorName(rv, errorName);
|
||||
UC_LOG((
|
||||
"BlacklistClassifierCallback[%p]:OnClassifyComplete Failed "
|
||||
"calling AsyncClassifyLocalWithFeatures with rv=%s. Let's move on.",
|
||||
this, errorName.get()));
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
return TrackerFound(aResults, mChannel, mChannelCallback);
|
||||
++pendingCallbacks;
|
||||
}
|
||||
|
||||
// All the AsyncClassifyLocalWithFeatures() calls return error. We do not
|
||||
// expect callbacks.
|
||||
if (pendingCallbacks == 0) {
|
||||
if (UC_LOG_ENABLED()) {
|
||||
UC_LOG(
|
||||
("BlacklistClassifierCallback[%p]:OnClassifyComplete All "
|
||||
"AsyncClassifyLocalWithFeatures() calls return errors. We cannot "
|
||||
"continue.",
|
||||
this));
|
||||
}
|
||||
|
||||
return TrackerFound(mResults, mChannel, mChannelCallback);
|
||||
}
|
||||
|
||||
// Nothing else do here. Let's wait for the WhitelistClassifierCallback.
|
||||
callback->SetTaskCount(pendingCallbacks);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -349,44 +397,62 @@ BlacklistClassifierCallback::OnClassifyComplete(
|
|||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = aChannel->GetURI(getter_AddRefs(uri));
|
||||
if (NS_FAILED(rv) || !uri) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// We need to obtain the list of nsIUrlClassifierFeature objects able to
|
||||
// classify this channel. If the list is empty, we do an early return.
|
||||
nsTArray<nsCOMPtr<nsIUrlClassifierFeature>> features;
|
||||
UrlClassifierFeatureFactory::GetFeaturesFromChannel(aChannel, features);
|
||||
if (features.IsEmpty()) {
|
||||
UC_LOG(("AsyncUrlChannelClassifier: Feature list is empty for channel %p",
|
||||
aChannel));
|
||||
UC_LOG(
|
||||
("AsyncUrlChannelClassifier: Nothing to do for channel %p", aChannel));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsTArray<FeatureTask> tasks;
|
||||
nsresult rv = GetFeatureTasks(aChannel, features,
|
||||
nsIUrlClassifierFeature::blacklist, tasks);
|
||||
if (NS_WARN_IF(NS_FAILED(rv)) || tasks.IsEmpty()) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!tasks.IsEmpty());
|
||||
|
||||
nsCOMPtr<nsIURIClassifier> uriClassifier =
|
||||
do_GetService(NS_URICLASSIFIERSERVICE_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIUrlClassifierFeatureCallback> callback =
|
||||
new BlacklistClassifierCallback(aChannel, uri, std::move(aCallback));
|
||||
RefPtr<BlacklistClassifierCallback> callback =
|
||||
new BlacklistClassifierCallback(aChannel, std::move(aCallback));
|
||||
|
||||
if (UC_LOG_ENABLED()) {
|
||||
nsCString spec = uri->GetSpecOrDefault();
|
||||
spec.Truncate(std::min(spec.Length(), UrlClassifierCommon::sMaxSpecLength));
|
||||
UC_LOG(("AsyncUrlChannelClassifier: Checking blacklist for uri=%s\n",
|
||||
spec.get()));
|
||||
uint32_t pendingCallbacks = 0;
|
||||
for (FeatureTask& task : tasks) {
|
||||
if (UC_LOG_ENABLED()) {
|
||||
nsCString spec = task.mURI->GetSpecOrDefault();
|
||||
spec.Truncate(
|
||||
std::min(spec.Length(), UrlClassifierCommon::sMaxSpecLength));
|
||||
UC_LOG(("AsyncUrlChannelClassifier: Checking blacklist for uri=%s\n",
|
||||
spec.get()));
|
||||
}
|
||||
|
||||
rv = uriClassifier->AsyncClassifyLocalWithFeatures(
|
||||
task.mURI, task.mFeatures, nsIUrlClassifierFeature::blacklist,
|
||||
callback);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
++pendingCallbacks;
|
||||
}
|
||||
|
||||
// xpcom parser creates array of interfaces using RefPtr<>.
|
||||
nsTArray<RefPtr<nsIUrlClassifierFeature>> refPtrFeatures;
|
||||
for (nsIUrlClassifierFeature* feature : features) {
|
||||
refPtrFeatures.AppendElement(feature);
|
||||
// All the AsyncClassifyLocalWithFeatures() calls return error. We do not
|
||||
// expect callbacks.
|
||||
if (pendingCallbacks == 0) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return uriClassifier->AsyncClassifyLocalWithFeatures(
|
||||
uri, refPtrFeatures, nsIUrlClassifierFeature::blacklist, callback);
|
||||
callback->SetTaskCount(pendingCallbacks);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
|
|
|
@ -244,5 +244,66 @@ UrlClassifierCommon::ShouldEnableTrackingProtectionOrAnnotation(
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */ nsresult UrlClassifierCommon::CreatePairwiseWhiteListURI(
|
||||
nsIChannel* aChannel, nsIURI** aURI) {
|
||||
MOZ_ASSERT(aChannel);
|
||||
MOZ_ASSERT(aURI);
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIHttpChannelInternal> chan = do_QueryInterface(aChannel, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!chan) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> topWinURI;
|
||||
rv = chan->GetTopWindowURI(getter_AddRefs(topWinURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!topWinURI) {
|
||||
if (UC_LOG_ENABLED()) {
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIHttpChannel> httpChan = do_QueryInterface(aChannel, &rv);
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = httpChan->GetURI(getter_AddRefs(uri));
|
||||
nsAutoCString spec;
|
||||
uri->GetAsciiSpec(spec);
|
||||
spec.Truncate(
|
||||
std::min(spec.Length(), UrlClassifierCommon::sMaxSpecLength));
|
||||
UC_LOG(("CreatePairwiseWhiteListURI: No window URI associated with %s",
|
||||
spec.get()));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIScriptSecurityManager> securityManager =
|
||||
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIPrincipal> chanPrincipal;
|
||||
rv = securityManager->GetChannelURIPrincipal(aChannel,
|
||||
getter_AddRefs(chanPrincipal));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Craft a whitelist URL like "toplevel.page/?resource=third.party.domain"
|
||||
nsAutoCString pageHostname, resourceDomain;
|
||||
rv = topWinURI->GetHost(pageHostname);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = chanPrincipal->GetBaseDomain(resourceDomain);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsAutoCString whitelistEntry = NS_LITERAL_CSTRING("http://") + pageHostname +
|
||||
NS_LITERAL_CSTRING("/?resource=") +
|
||||
resourceDomain;
|
||||
UC_LOG(
|
||||
("CreatePairwiseWhiteListURI: Looking for %s in the whitelist "
|
||||
"(channel=%p)",
|
||||
whitelistEntry.get(), aChannel));
|
||||
|
||||
nsCOMPtr<nsIURI> whitelistURI;
|
||||
rv = NS_NewURI(getter_AddRefs(whitelistURI), whitelistEntry);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
whitelistURI.forget(aURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -41,6 +41,11 @@ class UrlClassifierCommon final {
|
|||
const nsACString& aList,
|
||||
const nsACString& aProvider,
|
||||
const nsACString& aFullHash);
|
||||
|
||||
// Use this function only when you are looking for a pairwise whitelist uri
|
||||
// with the format: http://toplevel.page/?resource=channel.uri.domain
|
||||
static nsresult CreatePairwiseWhiteListURI(nsIChannel* aChannel,
|
||||
nsIURI** aURI);
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "mozilla/net/UrlClassifierFeatureFactory.h"
|
||||
|
||||
// List of Features
|
||||
#include "UrlClassifierFeatureFlash.h"
|
||||
#include "UrlClassifierFeatureLoginReputation.h"
|
||||
#include "UrlClassifierFeatureTrackingProtection.h"
|
||||
#include "UrlClassifierFeatureTrackingAnnotation.h"
|
||||
|
@ -22,6 +23,7 @@ namespace net {
|
|||
return;
|
||||
}
|
||||
|
||||
UrlClassifierFeatureFlash::Initialize();
|
||||
UrlClassifierFeatureTrackingAnnotation::Initialize();
|
||||
UrlClassifierFeatureTrackingProtection::Initialize();
|
||||
}
|
||||
|
@ -32,6 +34,7 @@ namespace net {
|
|||
return;
|
||||
}
|
||||
|
||||
UrlClassifierFeatureFlash::Shutdown();
|
||||
UrlClassifierFeatureLoginReputation::MaybeShutdown();
|
||||
UrlClassifierFeatureTrackingAnnotation::Shutdown();
|
||||
UrlClassifierFeatureTrackingProtection::Shutdown();
|
||||
|
@ -61,6 +64,11 @@ namespace net {
|
|||
if (feature) {
|
||||
aFeatures.AppendElement(feature);
|
||||
}
|
||||
|
||||
// Flash
|
||||
nsTArray<nsCOMPtr<nsIUrlClassifierFeature>> flashFeatures;
|
||||
UrlClassifierFeatureFlash::MaybeCreate(aChannel, flashFeatures);
|
||||
aFeatures.AppendElements(flashFeatures);
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "UrlClassifierFeatureFlash.h"
|
||||
#include "mozilla/net/HttpBaseChannel.h"
|
||||
#include "nsScriptSecurityManager.h"
|
||||
#include "nsQueryObject.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
namespace {
|
||||
|
||||
struct FlashFeatures {
|
||||
const char* mName;
|
||||
const char* mBlacklistPrefTables;
|
||||
const char* mWhitelistPrefTables;
|
||||
bool mSubdocumentOnly;
|
||||
nsIHttpChannel::FlashPluginState mFlashPluginState;
|
||||
RefPtr<UrlClassifierFeatureFlash> mFeature;
|
||||
};
|
||||
|
||||
static FlashFeatures sFlashFeaturesMap[] = {
|
||||
{"flash-deny", "urlclassifier.flashTable", "urlclassifier.flashExceptTable",
|
||||
false, nsIHttpChannel::FlashPluginDenied},
|
||||
{"flash-allow", "urlclassifier.flashAllowTable",
|
||||
"urlclassifier.flashAllowExceptTable", false,
|
||||
nsIHttpChannel::FlashPluginAllowed},
|
||||
{"flash-deny-subdoc", "urlclassifier.flashSubDocTable",
|
||||
"urlclassifier.flashSubDocExceptTable", true,
|
||||
nsIHttpChannel::FlashPluginDeniedInSubdocuments},
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
UrlClassifierFeatureFlash::UrlClassifierFeatureFlash(uint32_t aId)
|
||||
: UrlClassifierFeatureBase(
|
||||
nsDependentCString(sFlashFeaturesMap[aId].mName),
|
||||
nsDependentCString(sFlashFeaturesMap[aId].mBlacklistPrefTables),
|
||||
nsDependentCString(sFlashFeaturesMap[aId].mWhitelistPrefTables),
|
||||
EmptyCString(), // aPrefBlacklistHosts
|
||||
EmptyCString(), // aPrefWhitelistHosts
|
||||
EmptyCString(), // aPrefBlacklistTableName
|
||||
EmptyCString(), // aPrefWhitelistTableName
|
||||
EmptyCString()) // aPrefSkipHosts
|
||||
,
|
||||
mFlashPluginState(sFlashFeaturesMap[aId].mFlashPluginState) {
|
||||
static_assert(nsIHttpChannel::FlashPluginDeniedInSubdocuments ==
|
||||
nsIHttpChannel::FlashPluginLastValue,
|
||||
"nsIHttpChannel::FlashPluginLastValue is out-of-sync!");
|
||||
}
|
||||
|
||||
/* static */ void UrlClassifierFeatureFlash::Initialize() {
|
||||
uint32_t numFeatures =
|
||||
(sizeof(sFlashFeaturesMap) / sizeof(sFlashFeaturesMap[0]));
|
||||
for (uint32_t i = 0; i < numFeatures; ++i) {
|
||||
MOZ_ASSERT(!sFlashFeaturesMap[i].mFeature);
|
||||
sFlashFeaturesMap[i].mFeature = new UrlClassifierFeatureFlash(i);
|
||||
sFlashFeaturesMap[i].mFeature->InitializePreferences();
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void UrlClassifierFeatureFlash::Shutdown() {
|
||||
uint32_t numFeatures =
|
||||
(sizeof(sFlashFeaturesMap) / sizeof(sFlashFeaturesMap[0]));
|
||||
for (uint32_t i = 0; i < numFeatures; ++i) {
|
||||
MOZ_ASSERT(sFlashFeaturesMap[i].mFeature);
|
||||
sFlashFeaturesMap[i].mFeature->ShutdownPreferences();
|
||||
sFlashFeaturesMap[i].mFeature = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void UrlClassifierFeatureFlash::MaybeCreate(
|
||||
nsIChannel* aChannel,
|
||||
nsTArray<nsCOMPtr<nsIUrlClassifierFeature>>& aFeatures) {
|
||||
// All disabled.
|
||||
if (!StaticPrefs::plugins_flashBlock_enabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We use Flash feature just for document loading.
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
|
||||
nsContentPolicyType contentPolicyType =
|
||||
loadInfo ? loadInfo->GetExternalContentPolicyType()
|
||||
: nsIContentPolicy::TYPE_INVALID;
|
||||
|
||||
if (contentPolicyType != nsIContentPolicy::TYPE_DOCUMENT &&
|
||||
contentPolicyType != nsIContentPolicy::TYPE_SUBDOCUMENT) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only allow plugins for documents from an HTTP/HTTPS origin.
|
||||
if (StaticPrefs::plugins_http_https_only()) {
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
|
||||
if (!httpChannel) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t numFeatures =
|
||||
(sizeof(sFlashFeaturesMap) / sizeof(sFlashFeaturesMap[0]));
|
||||
for (uint32_t i = 0; i < numFeatures; ++i) {
|
||||
MOZ_ASSERT(sFlashFeaturesMap[i].mFeature);
|
||||
if (!sFlashFeaturesMap[i].mSubdocumentOnly ||
|
||||
contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT) {
|
||||
aFeatures.AppendElement(sFlashFeaturesMap[i].mFeature);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
UrlClassifierFeatureFlash::ProcessChannel(nsIChannel* aChannel,
|
||||
const nsACString& aList,
|
||||
bool* aShouldContinue) {
|
||||
NS_ENSURE_ARG_POINTER(aChannel);
|
||||
NS_ENSURE_ARG_POINTER(aShouldContinue);
|
||||
|
||||
// This is not a blocking feature.
|
||||
*aShouldContinue = true;
|
||||
|
||||
UC_LOG(("UrlClassifierFeatureFlash::ProcessChannel, annotating channel[%p]",
|
||||
aChannel));
|
||||
|
||||
nsCOMPtr<nsIParentChannel> parentChannel;
|
||||
NS_QueryNotificationCallbacks(aChannel, parentChannel);
|
||||
if (parentChannel) {
|
||||
// This channel is a parent-process proxy for a child process
|
||||
// request. We should notify the child process as well.
|
||||
parentChannel->NotifyFlashPluginStateChanged(mFlashPluginState);
|
||||
}
|
||||
|
||||
RefPtr<HttpBaseChannel> httpChannel = do_QueryObject(aChannel);
|
||||
if (httpChannel) {
|
||||
httpChannel->SetFlashPluginState(mFlashPluginState);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
UrlClassifierFeatureFlash::GetURIByListType(
|
||||
nsIChannel* aChannel, nsIUrlClassifierFeature::listType aListType,
|
||||
nsIURI** aURI) {
|
||||
NS_ENSURE_ARG_POINTER(aChannel);
|
||||
NS_ENSURE_ARG_POINTER(aURI);
|
||||
|
||||
// Here we return the channel's URI always.
|
||||
return aChannel->GetURI(aURI);
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,41 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_UrlClassifierFeatureFlash_h
|
||||
#define mozilla_UrlClassifierFeatureFlash_h
|
||||
|
||||
#include "UrlClassifierFeatureBase.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class UrlClassifierFeatureFlash final : public UrlClassifierFeatureBase {
|
||||
public:
|
||||
static void Initialize();
|
||||
static void Shutdown();
|
||||
|
||||
static void MaybeCreate(
|
||||
nsIChannel* aChannel,
|
||||
nsTArray<nsCOMPtr<nsIUrlClassifierFeature>>& aFeatures);
|
||||
|
||||
NS_IMETHOD
|
||||
ProcessChannel(nsIChannel* aChannel, const nsACString& aList,
|
||||
bool* aShouldContinue) override;
|
||||
|
||||
NS_IMETHOD GetURIByListType(nsIChannel* aChannel,
|
||||
nsIUrlClassifierFeature::listType aListType,
|
||||
nsIURI** aURI) override;
|
||||
|
||||
private:
|
||||
explicit UrlClassifierFeatureFlash(uint32_t aId);
|
||||
|
||||
nsIHttpChannel::FlashPluginState mFlashPluginState;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_UrlClassifierFeatureFlash_h
|
|
@ -93,5 +93,18 @@ UrlClassifierFeatureLoginReputation::HasHostInPreferences(
|
|||
aHost, aListType, aPrefTableName, aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
UrlClassifierFeatureLoginReputation::GetURIByListType(
|
||||
nsIChannel* aChannel, nsIUrlClassifierFeature::listType aListType,
|
||||
nsIURI** aURI) {
|
||||
NS_ENSURE_ARG_POINTER(aChannel);
|
||||
NS_ENSURE_ARG_POINTER(aURI);
|
||||
MOZ_ASSERT(aListType == nsIUrlClassifierFeature::whitelist,
|
||||
"UrlClassifierFeatureLoginReputation is meant to be used just to "
|
||||
"whitelist URLs");
|
||||
|
||||
return aChannel->GetURI(aURI);
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -37,6 +37,10 @@ class UrlClassifierFeatureLoginReputation final
|
|||
NS_IMETHOD ProcessChannel(nsIChannel* aChannel, const nsACString& aList,
|
||||
bool* aShouldContinue) override;
|
||||
|
||||
NS_IMETHOD GetURIByListType(nsIChannel* aChannel,
|
||||
nsIUrlClassifierFeature::listType aListType,
|
||||
nsIURI** aURI) override;
|
||||
|
||||
private:
|
||||
UrlClassifierFeatureLoginReputation();
|
||||
};
|
||||
|
|
|
@ -10,11 +10,19 @@ namespace mozilla {
|
|||
namespace net {
|
||||
|
||||
UrlClassifierFeatureResult::UrlClassifierFeatureResult(
|
||||
nsIUrlClassifierFeature* aFeature, const nsACString& aList)
|
||||
: mFeature(aFeature), mList(aList) {}
|
||||
nsIURI* aURI, nsIUrlClassifierFeature* aFeature, const nsACString& aList)
|
||||
: mURI(aURI), mFeature(aFeature), mList(aList) {}
|
||||
|
||||
UrlClassifierFeatureResult::~UrlClassifierFeatureResult() = default;
|
||||
|
||||
NS_IMETHODIMP
|
||||
UrlClassifierFeatureResult::GetUri(nsIURI** aURI) {
|
||||
NS_ENSURE_ARG_POINTER(aURI);
|
||||
nsCOMPtr<nsIURI> uri = mURI;
|
||||
uri.forget(aURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
UrlClassifierFeatureResult::GetFeature(nsIUrlClassifierFeature** aFeature) {
|
||||
NS_ENSURE_ARG_POINTER(aFeature);
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include "nsIUrlClassifierFeature.h"
|
||||
#include "nsString.h"
|
||||
|
||||
class nsIURI;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
|
@ -18,9 +20,11 @@ class UrlClassifierFeatureResult final : public nsIUrlClassifierFeatureResult {
|
|||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIURLCLASSIFIERFEATURERESULT
|
||||
|
||||
UrlClassifierFeatureResult(nsIUrlClassifierFeature* aFeature,
|
||||
UrlClassifierFeatureResult(nsIURI* aURI, nsIUrlClassifierFeature* aFeature,
|
||||
const nsACString& aList);
|
||||
|
||||
nsIURI* URI() const { return mURI; }
|
||||
|
||||
nsIUrlClassifierFeature* Feature() const { return mFeature; }
|
||||
|
||||
// Comma separated list of tables.
|
||||
|
@ -30,6 +34,7 @@ class UrlClassifierFeatureResult final : public nsIUrlClassifierFeatureResult {
|
|||
~UrlClassifierFeatureResult();
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
nsCOMPtr<nsIUrlClassifierFeature> mFeature;
|
||||
const nsCString mList;
|
||||
};
|
||||
|
|
|
@ -201,5 +201,20 @@ UrlClassifierFeatureTrackingAnnotation::ProcessChannel(nsIChannel* aChannel,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
UrlClassifierFeatureTrackingAnnotation::GetURIByListType(
|
||||
nsIChannel* aChannel, nsIUrlClassifierFeature::listType aListType,
|
||||
nsIURI** aURI) {
|
||||
NS_ENSURE_ARG_POINTER(aChannel);
|
||||
NS_ENSURE_ARG_POINTER(aURI);
|
||||
|
||||
if (aListType == nsIUrlClassifierFeature::blacklist) {
|
||||
return aChannel->GetURI(aURI);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aListType == nsIUrlClassifierFeature::whitelist);
|
||||
return UrlClassifierCommon::CreatePairwiseWhiteListURI(aChannel, aURI);
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -27,6 +27,10 @@ class UrlClassifierFeatureTrackingAnnotation final
|
|||
NS_IMETHOD ProcessChannel(nsIChannel* aChannel, const nsACString& aList,
|
||||
bool* aShouldContinue) override;
|
||||
|
||||
NS_IMETHOD GetURIByListType(nsIChannel* aChannel,
|
||||
nsIUrlClassifierFeature::listType aListType,
|
||||
nsIURI** aURI) override;
|
||||
|
||||
private:
|
||||
UrlClassifierFeatureTrackingAnnotation();
|
||||
};
|
||||
|
|
|
@ -130,5 +130,20 @@ UrlClassifierFeatureTrackingProtection::ProcessChannel(nsIChannel* aChannel,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
UrlClassifierFeatureTrackingProtection::GetURIByListType(
|
||||
nsIChannel* aChannel, nsIUrlClassifierFeature::listType aListType,
|
||||
nsIURI** aURI) {
|
||||
NS_ENSURE_ARG_POINTER(aChannel);
|
||||
NS_ENSURE_ARG_POINTER(aURI);
|
||||
|
||||
if (aListType == nsIUrlClassifierFeature::blacklist) {
|
||||
return aChannel->GetURI(aURI);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aListType == nsIUrlClassifierFeature::whitelist);
|
||||
return UrlClassifierCommon::CreatePairwiseWhiteListURI(aChannel, aURI);
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -27,6 +27,10 @@ class UrlClassifierFeatureTrackingProtection final
|
|||
NS_IMETHOD ProcessChannel(nsIChannel* aChannel, const nsACString& aList,
|
||||
bool* aShouldContinue) override;
|
||||
|
||||
NS_IMETHOD GetURIByListType(nsIChannel* aChannel,
|
||||
nsIUrlClassifierFeature::listType aListType,
|
||||
nsIURI** aURI) override;
|
||||
|
||||
private:
|
||||
UrlClassifierFeatureTrackingProtection();
|
||||
};
|
||||
|
|
|
@ -23,6 +23,7 @@ UNIFIED_SOURCES += [
|
|||
'UrlClassifierCommon.cpp',
|
||||
'UrlClassifierFeatureBase.cpp',
|
||||
'UrlClassifierFeatureFactory.cpp',
|
||||
'UrlClassifierFeatureFlash.cpp',
|
||||
'UrlClassifierFeatureLoginReputation.cpp',
|
||||
'UrlClassifierFeatureResult.cpp',
|
||||
'UrlClassifierFeatureTrackingAnnotation.cpp',
|
||||
|
|
|
@ -81,13 +81,6 @@ interface nsIURIClassifier : nsISupports
|
|||
in boolean aTrackingProtectionEnabled,
|
||||
in nsIURIClassifierCallback aCallback);
|
||||
|
||||
/**
|
||||
* Synchronously classify a URI with a comma-separated string
|
||||
* containing the given tables. This does not make network requests.
|
||||
* The result is an array of table names that match.
|
||||
*/
|
||||
[noscript] StringArrayRef classifyLocalWithTables(in nsIURI aURI, in ACString aTables);
|
||||
|
||||
/**
|
||||
* Asynchronously classify a URI with a comma-separated string
|
||||
* containing the given tables. This does not make network requests.
|
||||
|
@ -111,12 +104,6 @@ interface nsIURIClassifier : nsISupports
|
|||
in nsIUrlClassifierFeature_listType aListType,
|
||||
in nsIUrlClassifierFeatureCallback aCallback);
|
||||
|
||||
/**
|
||||
* Same as above, but returns a comma separated list of table names.
|
||||
* This is an internal interface used only for testing purposes.
|
||||
*/
|
||||
ACString classifyLocal(in nsIURI aURI, in ACString aTables);
|
||||
|
||||
/**
|
||||
* Report to the provider that a Safe Browsing warning was shown.
|
||||
*
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
[ref] native StringArrayRef(nsTArray<nsCString>);
|
||||
|
||||
interface nsIChannel;
|
||||
interface nsIURI;
|
||||
|
||||
/**
|
||||
* A single URLClassifier feature.
|
||||
|
@ -62,6 +63,14 @@ interface nsIUrlClassifierFeature : nsISupports
|
|||
* processing other features.
|
||||
*/
|
||||
[noscript] boolean processChannel(in nsIChannel aChannel, in ACString aList);
|
||||
|
||||
/**
|
||||
* Features can work with different URLs from a channel (channel url, or
|
||||
* top-level, or something else). This method returns what we need to use for
|
||||
* the current list.
|
||||
*/
|
||||
[noscript] nsIURI getURIByListType(in nsIChannel channel,
|
||||
in nsIUrlClassifierFeature_listType listType);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -71,6 +80,8 @@ interface nsIUrlClassifierFeature : nsISupports
|
|||
[builtinclass, scriptable, uuid(ccb88140-5d66-4873-9815-a1b98d6cdc92)]
|
||||
interface nsIUrlClassifierFeatureResult : nsISupports
|
||||
{
|
||||
readonly attribute nsIURI uri;
|
||||
|
||||
readonly attribute nsIUrlClassifierFeature feature;
|
||||
|
||||
// Comma separate tables or preferences.
|
||||
|
|
|
@ -9,7 +9,7 @@ geckoview-junit:
|
|||
max-run-time: 3600
|
||||
tier:
|
||||
by-test-platform:
|
||||
android-em-7.0-x86/opt: 3
|
||||
android-em-7.0-x86/.*: 3
|
||||
default: default
|
||||
chunks:
|
||||
by-test-platform:
|
||||
|
@ -21,10 +21,10 @@ geckoview-junit:
|
|||
script: android_emulator_unittest.py
|
||||
config:
|
||||
by-test-platform:
|
||||
android-em-7.0-x86/opt:
|
||||
android-em-7.0-x86/.*:
|
||||
- android/android_common.py
|
||||
- android/androidx86_7_0.py
|
||||
android-em.*:
|
||||
android-em-4.*:
|
||||
- android/android_common.py
|
||||
- android/androidarm_4_3_junit.py
|
||||
extra-options:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
job-defaults:
|
||||
target:
|
||||
by-test-platform:
|
||||
android-em-7.0-x86/opt: geckoview-androidTest.apk
|
||||
android-em-7.*: geckoview-androidTest.apk
|
||||
default: null
|
||||
serviceworker-e10s:
|
||||
by-test-platform:
|
||||
|
@ -15,10 +15,10 @@ job-defaults:
|
|||
default: desktop_unittest.py
|
||||
config:
|
||||
by-test-platform:
|
||||
android-em-7.0-x86/opt:
|
||||
android-em-7.*:
|
||||
- android/android_common.py
|
||||
- android/androidx86_7_0.py
|
||||
android-em.*:
|
||||
android-em-4.*:
|
||||
- android/android_common.py
|
||||
- android/androidarm_4_3.py
|
||||
android-hw.*:
|
||||
|
@ -50,8 +50,8 @@ mochitest:
|
|||
chunks:
|
||||
by-test-platform:
|
||||
android-em-4.3-arm7-api-16/debug: 60
|
||||
android-em-7.0-x86/opt: 4
|
||||
android-em.*: 24
|
||||
android-em-4.*: 24
|
||||
android-em-7.*: 4
|
||||
linux.*/debug: 16
|
||||
linux64-asan/opt: 10
|
||||
linux64-.*cov/opt: 10
|
||||
|
@ -277,7 +277,7 @@ mochitest-media:
|
|||
default: large
|
||||
chunks:
|
||||
by-test-platform:
|
||||
android-em-7.0-x86/opt: 1
|
||||
android-em-7.*: 1
|
||||
macosx64.*: 1
|
||||
windows10-64.*: 1
|
||||
default: 3
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
job-defaults:
|
||||
target:
|
||||
by-test-platform:
|
||||
android-em-7.0-x86/opt: geckoview-androidTest.apk
|
||||
android-em-7.*: geckoview-androidTest.apk
|
||||
default: null
|
||||
serviceworker-e10s:
|
||||
by-test-platform:
|
||||
|
@ -14,10 +14,10 @@ job-defaults:
|
|||
default: desktop_unittest.py
|
||||
config:
|
||||
by-test-platform:
|
||||
android-em-7.0-x86/opt:
|
||||
android-em-7.*:
|
||||
- android/android_common.py
|
||||
- android/androidx86_7_0.py
|
||||
android-em.*:
|
||||
android-em-4.*:
|
||||
- android/android_common.py
|
||||
- android/androidarm_4_3.py
|
||||
linux.*:
|
||||
|
@ -44,8 +44,8 @@ crashtest:
|
|||
chunks:
|
||||
by-test-platform:
|
||||
android-em-4.3-arm7-api-16/debug: 10
|
||||
android-em-7.0-x86/opt: 1
|
||||
android-em.*: 4
|
||||
android-em-4.3-arm7-api-16/opt: 4
|
||||
android-em-7.*: 1
|
||||
default: 1
|
||||
e10s:
|
||||
by-test-platform:
|
||||
|
@ -70,6 +70,7 @@ jsreftest:
|
|||
by-test-platform:
|
||||
android-em-4.3-arm7-api-16/debug: 100
|
||||
android-em-7.0-x86/opt: 4
|
||||
android-em-7.0-x86/debug: 8
|
||||
android-em.*: 40
|
||||
windows.*: 2
|
||||
windows10-64-ccov/debug: 5
|
||||
|
@ -98,8 +99,8 @@ reftest:
|
|||
chunks:
|
||||
by-test-platform:
|
||||
android-em-4.3-arm7-api-16/debug: 56
|
||||
android-em-7.0-x86/opt: 5
|
||||
android-em.*: 28
|
||||
android-em-4.*: 28
|
||||
android-em-7.*: 5
|
||||
macosx64.*/opt: 2
|
||||
macosx64.*/debug: 3
|
||||
macosx64-ccov/debug: 6
|
||||
|
|
|
@ -601,7 +601,8 @@ def set_treeherder_machine_platform(config, tests):
|
|||
elif 'android-hw' in test['test-platform']:
|
||||
test['treeherder-machine-platform'] = test['test-platform']
|
||||
elif 'android-em-7.0-x86' in test['test-platform']:
|
||||
test['treeherder-machine-platform'] = 'android-em-7-0-x86/opt'
|
||||
opt = test['test-platform'].split('/')[1]
|
||||
test['treeherder-machine-platform'] = 'android-em-7-0-x86/'+opt
|
||||
else:
|
||||
test['treeherder-machine-platform'] = translation.get(
|
||||
test['build-platform'], test['test-platform'])
|
||||
|
|
|
@ -67,8 +67,7 @@ class JUnitTestRunner(MochitestDesktop):
|
|||
self.build_profile()
|
||||
self.startServers(
|
||||
self.options,
|
||||
debuggerInfo=None,
|
||||
ignoreSSLTunnelExts=True)
|
||||
debuggerInfo=None)
|
||||
self.log.debug("Servers started")
|
||||
|
||||
def server_init(self):
|
||||
|
|
|
@ -123,11 +123,9 @@ class RobocopTestRunner(MochitestDesktop):
|
|||
self.printDeviceInfo()
|
||||
self.setupLocalPaths()
|
||||
self.buildProfile()
|
||||
# ignoreSSLTunnelExts is a workaround for bug 1109310
|
||||
self.startServers(
|
||||
self.options,
|
||||
debuggerInfo=None,
|
||||
ignoreSSLTunnelExts=True)
|
||||
debuggerInfo=None)
|
||||
self.log.debug("Servers started")
|
||||
|
||||
def cleanup(self):
|
||||
|
|
|
@ -568,7 +568,7 @@ class WebSocketServer(object):
|
|||
|
||||
class SSLTunnel:
|
||||
|
||||
def __init__(self, options, logger, ignoreSSLTunnelExts=False):
|
||||
def __init__(self, options, logger):
|
||||
self.log = logger
|
||||
self.process = None
|
||||
self.utilityPath = options.utilityPath
|
||||
|
@ -578,7 +578,6 @@ class SSLTunnel:
|
|||
self.httpPort = options.httpPort
|
||||
self.webServer = options.webServer
|
||||
self.webSocketPort = options.webSocketPort
|
||||
self.useSSLTunnelExts = not ignoreSSLTunnelExts
|
||||
|
||||
self.customCertRE = re.compile("^cert=(?P<nickname>[0-9a-zA-Z_ ]+)")
|
||||
self.clientAuthRE = re.compile("^clientauth=(?P<clientauth>[a-z]+)")
|
||||
|
@ -604,7 +603,7 @@ class SSLTunnel:
|
|||
config.write("redirhost:%s:%s:%s:%s\n" %
|
||||
(loc.host, loc.port, self.sslPort, redirhost))
|
||||
|
||||
if self.useSSLTunnelExts and option in (
|
||||
if option in (
|
||||
'tls1',
|
||||
'ssl3',
|
||||
'rc4',
|
||||
|
@ -1145,7 +1144,7 @@ class MochitestDesktop(object):
|
|||
self.log.error("runtests.py | Timed out while waiting for "
|
||||
"websocket/process bridge startup.")
|
||||
|
||||
def startServers(self, options, debuggerInfo, ignoreSSLTunnelExts=False):
|
||||
def startServers(self, options, debuggerInfo):
|
||||
# start servers and set ports
|
||||
# TODO: pass these values, don't set on `self`
|
||||
self.webServer = options.webServer
|
||||
|
@ -1169,8 +1168,7 @@ class MochitestDesktop(object):
|
|||
# start SSL pipe
|
||||
self.sslTunnel = SSLTunnel(
|
||||
options,
|
||||
logger=self.log,
|
||||
ignoreSSLTunnelExts=ignoreSSLTunnelExts)
|
||||
logger=self.log)
|
||||
self.sslTunnel.buildConfig(self.locations)
|
||||
self.sslTunnel.start()
|
||||
|
||||
|
|
|
@ -216,12 +216,10 @@ class MochiRemote(MochitestDesktop):
|
|||
def startServers(self, options, debuggerInfo):
|
||||
""" Create the servers on the host and start them up """
|
||||
restoreRemotePaths = self.switchToLocalPaths(options)
|
||||
# ignoreSSLTunnelExts is a workaround for bug 1109310
|
||||
MochitestDesktop.startServers(
|
||||
self,
|
||||
options,
|
||||
debuggerInfo,
|
||||
ignoreSSLTunnelExts=True)
|
||||
debuggerInfo)
|
||||
restoreRemotePaths()
|
||||
|
||||
def buildProfile(self, options):
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
{"files":{"CHANGELOG.md":"b24b688b552ea12f4ef03b2c76e17ecfb8c05104d4f494c47b698fd7d94d3e3a","Cargo.toml":"3908d7c2421a4071d3fdd4a7c7a44c1c8779cf9d229cec307fd1a2b96398aa60","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"005b3f9b4687364514bbaea2a25e96d54ce6a59277d157386e8259cbcae8e095","README.md":"006ae145ee89fa14a9d755b206ec2011a3687408e9d5fe3943f2448767b01d62","ci/install.sh":"f3965bda34345579d0799ca2e581efd7ae51f3191aa9203b018f4ade8b986b15","ci/script.sh":"0f8329c7345731c12f35a392e8deeb2e265b75f107c5aca6eed584096896737f","src/lib.rs":"52418274bc4ec5c59dba1885de7324157e677739a2c9624b5d462d5d4c77b5e3","src/test.rs":"58ea38d755d5eae72b1df29fc602483fef888a111bb2e9c3a219e2b2a1ed222f"},"package":"926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427"}
|
|
@ -0,0 +1,42 @@
|
|||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [v0.2.2] - 2017-05-07
|
||||
|
||||
### Fixed
|
||||
|
||||
- UB in the checked cast from `f32` to `u128`.
|
||||
|
||||
## [v0.2.1] - 2017-05-06
|
||||
|
||||
### Added
|
||||
|
||||
- Support for 128-bit integers, behind the `x128` Cargo feature (nightly
|
||||
needed).
|
||||
|
||||
## [v0.2.0] - 2017-02-08
|
||||
|
||||
### Added
|
||||
|
||||
- Now `cast::Error` implements the `std::error::Error` trait among other traits
|
||||
like `Display`, `Clone`, etc.
|
||||
|
||||
### Changed
|
||||
|
||||
- [breaking-change] This crate now depends on the `std` crate by default but you
|
||||
can make it `no_std` by opting out of the `std` Cargo feature.
|
||||
|
||||
## v0.1.0 - 2016-02-07
|
||||
|
||||
Initial release
|
||||
|
||||
[Unreleased]: https://github.com/japaric/cast.rs/compare/v0.2.2...HEAD
|
||||
[v0.2.2]: https://github.com/japaric/cast.rs/compare/v0.2.1...v0.2.2
|
||||
[v0.2.1]: https://github.com/japaric/cast.rs/compare/v0.2.0...v0.2.1
|
||||
[v0.2.0]: https://github.com/japaric/cast.rs/compare/v0.1.0...v0.2.0
|
|
@ -0,0 +1,21 @@
|
|||
[package]
|
||||
authors = ["Jorge Aparicio <jorge@japaric.io>"]
|
||||
description = "Ergonomic, checked cast functions for primitive types"
|
||||
documentation = "https://docs.rs/cast"
|
||||
keywords = ["checked", "cast", "primitive", "integer", "float"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
name = "cast"
|
||||
repository = "https://github.com/japaric/cast.rs"
|
||||
version = "0.2.2"
|
||||
|
||||
[features]
|
||||
# Assume we should use `std` unless asked to do otherwise.
|
||||
default = ["std"]
|
||||
# Enable this to get a std::error::Error impl for convenient use with other
|
||||
# libraries.
|
||||
std = []
|
||||
# Enable this for i128/u128 support
|
||||
x128 = []
|
||||
|
||||
[dev-dependencies]
|
||||
quickcheck = "0.4.1"
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,25 @@
|
|||
Copyright (c) 2014-2017 Jorge Aparicio
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,44 @@
|
|||
[![crates.io](https://img.shields.io/crates/d/cast.svg)](https://crates.io/crates/cast)
|
||||
[![crates.io](https://img.shields.io/crates/v/cast.svg)](https://crates.io/crates/cast)
|
||||
|
||||
# `cast`
|
||||
|
||||
> Ergonomic, checked cast functions for primitive types
|
||||
|
||||
``` rust
|
||||
extern crate cast;
|
||||
|
||||
// `u8` and `u16` are checked cast functions, use them to cast from any numeric
|
||||
// primitive to `u8`/`u16` respectively
|
||||
use cast::{u8, u16, Error};
|
||||
|
||||
// Infallible operations, like integer promotion, are equivalent to a normal
|
||||
// cast with `as`
|
||||
assert_eq!(u16(0u8), 0u16);
|
||||
|
||||
// Everything else will return a `Result` depending on the success of the
|
||||
// operation
|
||||
assert_eq!(u8(0u16), Ok(0u8));
|
||||
assert_eq!(u8(256u16), Err(Error::Overflow));
|
||||
assert_eq!(u8(-1i8), Err(Error::Underflow));
|
||||
assert_eq!(u8(1. / 0.), Err(Error::Infinite));
|
||||
assert_eq!(u8(0. / 0.), Err(Error::NaN));
|
||||
```
|
||||
|
||||
## [API docs](https://docs.rs/cast)
|
||||
|
||||
## License
|
||||
|
||||
Licensed under either of
|
||||
|
||||
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||
http://www.apache.org/licenses/LICENSE-2.0)
|
||||
- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
||||
|
||||
at your option.
|
||||
|
||||
### Contribution
|
||||
|
||||
Unless you explicitly state otherwise, any contribution intentionally submitted
|
||||
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
|
||||
dual licensed as above, without any additional terms or conditions.
|
|
@ -0,0 +1,21 @@
|
|||
set -ex
|
||||
|
||||
main() {
|
||||
curl https://sh.rustup.rs -sSf | \
|
||||
sh -s -- -y --default-toolchain $TRAVIS_RUST_VERSION
|
||||
|
||||
local latest=$(git ls-remote --tags --refs --exit-code https://github.com/japaric/cross \
|
||||
| cut -d/ -f3 \
|
||||
| grep -E '^v[0-9.]+$' \
|
||||
| sort --version-sort \
|
||||
| tail -n1)
|
||||
|
||||
curl -LSfs https://japaric.github.io/trust/install.sh | \
|
||||
sh -s -- \
|
||||
--force \
|
||||
--git japaric/cross \
|
||||
--tag $latest \
|
||||
--target x86_64-unknown-linux-gnu
|
||||
}
|
||||
|
||||
main
|
|
@ -0,0 +1,14 @@
|
|||
set -ex
|
||||
|
||||
main() {
|
||||
cross test --target $TARGET
|
||||
cross test --target $TARGET --release
|
||||
|
||||
[ "$TRAVIS_RUST_VERSION" -eq "nightly" ] && cross test --feature x128 --target $TARGET
|
||||
[ "$TRAVIS_RUST_VERSION" -eq "nightly" ] && cross test --feature x128 --target $TARGET --release
|
||||
|
||||
cross test --no-default-features --target $TARGET
|
||||
cross test --no-default-features --target $TARGET --release
|
||||
}
|
||||
|
||||
main
|
|
@ -0,0 +1,523 @@
|
|||
//! Ergonomic, checked cast functions for primitive types
|
||||
//!
|
||||
//! This crate provides one checked cast function for each numeric primitive.
|
||||
//! Use these functions to perform a cast from any other numeric primitive:
|
||||
//!
|
||||
//! ```
|
||||
//! extern crate cast;
|
||||
//!
|
||||
//! use cast::{u8, u16, Error};
|
||||
//!
|
||||
//! # fn main() {
|
||||
//! // Infallible operations, like integer promotion, are equivalent to a normal
|
||||
//! // cast with `as`
|
||||
//! assert_eq!(u16(0u8), 0u16);
|
||||
//!
|
||||
//! // Everything else will return a `Result` depending on the success of the
|
||||
//! // operation
|
||||
//! assert_eq!(u8(0u16), Ok(0u8));
|
||||
//! assert_eq!(u8(256u16), Err(Error::Overflow));
|
||||
//! assert_eq!(u8(-1i8), Err(Error::Underflow));
|
||||
//! assert_eq!(u8(1. / 0.), Err(Error::Infinite));
|
||||
//! assert_eq!(u8(0. / 0.), Err(Error::NaN));
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! There are no namespace problems between these functions, the "primitive
|
||||
//! modules" in `core`/`std` and the built-in primitive types, so all them can
|
||||
//! be in the same scope:
|
||||
//!
|
||||
//! ```
|
||||
//! extern crate cast;
|
||||
//!
|
||||
//! use std::u8;
|
||||
//! use cast::{u8, u16};
|
||||
//!
|
||||
//! # fn main() {
|
||||
//! // `u8` as a type
|
||||
//! let x: u8 = 0;
|
||||
//! // `u8` as a module
|
||||
//! let y = u16(u8::MAX);
|
||||
//! // `u8` as a function
|
||||
//! let z = u8(y).unwrap();
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! The checked cast functionality is also usable with type aliases via the
|
||||
//! `cast` static method:
|
||||
//!
|
||||
//! ```
|
||||
//! extern crate cast;
|
||||
//!
|
||||
//! use std::os::raw::c_ulonglong;
|
||||
//! // NOTE avoid shadowing `std::convert::From` - cf. rust-lang/rfcs#1311
|
||||
//! use cast::From as _0;
|
||||
//!
|
||||
//! # fn main() {
|
||||
//! assert_eq!(c_ulonglong::cast(0u8), 0u64);
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! This crate also provides a `From` trait that can be used, for example,
|
||||
//! to create a generic function that accepts any type that can be infallibly
|
||||
//! casted to `u32`.
|
||||
//!
|
||||
//! ```
|
||||
//! extern crate cast;
|
||||
//!
|
||||
//! fn to_u32<T>(x: T) -> u32
|
||||
//! // reads as: "where u32 can be casted from T with output u32"
|
||||
//! where u32: cast::From<T, Output=u32>,
|
||||
//! {
|
||||
//! cast::u32(x)
|
||||
//! }
|
||||
//!
|
||||
//! # fn main() {
|
||||
//! assert_eq!(to_u32(0u8), 0u32);
|
||||
//! assert_eq!(to_u32(1u16), 1u32);
|
||||
//! assert_eq!(to_u32(2u32), 2u32);
|
||||
//!
|
||||
//! // to_u32(-1i32); // Compile error
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! ## Building without `std`
|
||||
//!
|
||||
//! This crate can be used without Rust's `std` crate by declaring it as
|
||||
//! follows in your `Cargo.toml`:
|
||||
//!
|
||||
//! ``` toml
|
||||
//! cast = { version = "*", default-features = false }
|
||||
//! ```
|
||||
|
||||
#![deny(missing_docs)]
|
||||
#![deny(warnings)]
|
||||
#![allow(const_err)]
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
#![cfg_attr(feature = "x128", feature(i128_type, i128))]
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
extern crate core;
|
||||
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
extern crate quickcheck;
|
||||
|
||||
use core::fmt;
|
||||
#[cfg(feature="std")]
|
||||
use std::error;
|
||||
|
||||
#[cfg(test)]
|
||||
mod test;
|
||||
|
||||
/// Cast errors
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum Error {
|
||||
/// Infinite value casted to a type that can only represent finite values
|
||||
Infinite,
|
||||
/// NaN value casted to a type that can't represent a NaN value
|
||||
NaN,
|
||||
/// Source value is greater than the maximum value that the destination type
|
||||
/// can hold
|
||||
Overflow,
|
||||
/// Source value is smaller than the minimum value that the destination type
|
||||
/// can hold
|
||||
Underflow,
|
||||
}
|
||||
|
||||
impl Error {
|
||||
/// A private helper function that implements `description`, because
|
||||
/// `description` is only available when we have `std` enabled.
|
||||
fn description_helper(&self) -> &str {
|
||||
match *self {
|
||||
Error::Infinite => "Cannot store infinite value in finite type",
|
||||
Error::NaN => "Cannot store NaN in type which does not support it",
|
||||
Error::Overflow => "Overflow during numeric conversion",
|
||||
Error::Underflow => "Underflow during numeric conversion",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.description_helper())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="std")]
|
||||
impl error::Error for Error {
|
||||
fn description(&self) -> &str {
|
||||
self.description_helper()
|
||||
}
|
||||
}
|
||||
|
||||
/// The "cast from" operation
|
||||
pub trait From<Src> {
|
||||
/// The result of the cast operation: either `Self` or `Result<Self, Error>`
|
||||
type Output;
|
||||
|
||||
/// Checked cast from `Src` to `Self`
|
||||
fn cast(Src) -> Self::Output;
|
||||
}
|
||||
|
||||
macro_rules! fns {
|
||||
($($ty:ident),+) => {
|
||||
$(
|
||||
/// Checked cast function
|
||||
#[inline]
|
||||
pub fn $ty<T>(x: T) -> <$ty as From<T>>::Output
|
||||
where $ty: From<T>
|
||||
{
|
||||
<$ty as From<T>>::cast(x)
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
fns!(f32, f64, i8, i16, i32, i64, isize, u8, u16, u32, u64, usize);
|
||||
|
||||
#[cfg(feature = "x128")]
|
||||
fns!(i128, u128);
|
||||
|
||||
/// `$dst` can hold any value of `$src`
|
||||
macro_rules! promotion {
|
||||
($($src:ty => $($dst: ty),+);+;) => {
|
||||
$(
|
||||
$(
|
||||
impl From<$src> for $dst {
|
||||
type Output = $dst;
|
||||
|
||||
#[inline]
|
||||
fn cast(src: $src) -> $dst {
|
||||
src as $dst
|
||||
}
|
||||
}
|
||||
)+
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
/// `$dst` can hold any positive value of `$src`
|
||||
macro_rules! half_promotion {
|
||||
($($src:ty => $($dst:ty),+);+;) => {
|
||||
$(
|
||||
$(
|
||||
impl From<$src> for $dst {
|
||||
type Output = Result<$dst, Error>;
|
||||
|
||||
#[inline]
|
||||
fn cast(src: $src) -> Self::Output {
|
||||
if src < 0 {
|
||||
Err(Error::Underflow)
|
||||
} else {
|
||||
Ok(src as $dst)
|
||||
}
|
||||
}
|
||||
}
|
||||
)+
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
/// From an unsigned `$src` to a smaller `$dst`
|
||||
macro_rules! from_unsigned {
|
||||
($($src:ident => $($dst:ident),+);+;) => {
|
||||
$(
|
||||
$(
|
||||
impl From<$src> for $dst {
|
||||
type Output = Result<$dst, Error>;
|
||||
|
||||
#[inline]
|
||||
fn cast(src: $src) -> Self::Output {
|
||||
use core::$dst;
|
||||
|
||||
if src > $dst::MAX as $src {
|
||||
Err(Error::Overflow)
|
||||
} else {
|
||||
Ok(src as $dst)
|
||||
}
|
||||
}
|
||||
}
|
||||
)+
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
/// From a signed `$src` to a smaller `$dst`
|
||||
macro_rules! from_signed {
|
||||
($($src:ident => $($dst:ident),+);+;) => {
|
||||
$(
|
||||
$(
|
||||
impl From<$src> for $dst {
|
||||
type Output = Result<$dst, Error>;
|
||||
|
||||
#[inline]
|
||||
fn cast(src: $src) -> Self::Output {
|
||||
use core::$dst;
|
||||
|
||||
Err(if src < $dst::MIN as $src {
|
||||
Error::Underflow
|
||||
} else if src > $dst::MAX as $src {
|
||||
Error::Overflow
|
||||
} else {
|
||||
return Ok(src as $dst);
|
||||
})
|
||||
}
|
||||
}
|
||||
)+
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
/// From a float `$src` to an integer `$dst`
|
||||
macro_rules! from_float {
|
||||
($($src:ident => $($dst:ident),+);+;) => {
|
||||
$(
|
||||
$(
|
||||
impl From<$src> for $dst {
|
||||
type Output = Result<$dst, Error>;
|
||||
|
||||
#[inline]
|
||||
fn cast(src: $src) -> Self::Output {
|
||||
use core::{$dst, $src};
|
||||
|
||||
Err(if src != src {
|
||||
Error::NaN
|
||||
} else if src == $src::INFINITY ||
|
||||
src == $src::NEG_INFINITY {
|
||||
Error::Infinite
|
||||
} else if src < $dst::MIN as $src {
|
||||
Error::Underflow
|
||||
} else if src > $dst::MAX as $src {
|
||||
Error::Overflow
|
||||
} else {
|
||||
return Ok(src as $dst);
|
||||
})
|
||||
}
|
||||
}
|
||||
)+
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
/// From a float `$src` to an integer `$dst`, where $dst is large enough to contain
|
||||
/// all values of `$src`. We can't ever overflow here
|
||||
macro_rules! from_float_dst {
|
||||
($($src:ident => $($dst:ident),+);+;) => {
|
||||
$(
|
||||
$(
|
||||
impl From<$src> for $dst {
|
||||
type Output = Result<$dst, Error>;
|
||||
|
||||
#[inline]
|
||||
#[allow(unused_comparisons)]
|
||||
fn cast(src: $src) -> Self::Output {
|
||||
use core::{$dst, $src};
|
||||
|
||||
Err(if src != src {
|
||||
Error::NaN
|
||||
} else if src == $src::INFINITY ||
|
||||
src == $src::NEG_INFINITY {
|
||||
Error::Infinite
|
||||
} else if ($dst::MIN == 0) && src < 0.0 {
|
||||
Error::Underflow
|
||||
} else {
|
||||
return Ok(src as $dst);
|
||||
})
|
||||
}
|
||||
}
|
||||
)+
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
// PLAY TETRIS! ;-)
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
mod _32 {
|
||||
use {Error, From};
|
||||
|
||||
// Signed
|
||||
promotion! {
|
||||
i8 => f32, f64, i8, i16, i32, isize, i64;
|
||||
i16 => f32, f64, i16, i32, isize, i64;
|
||||
i32 => f32, f64, i32, isize, i64;
|
||||
isize => f32, f64, i32, isize, i64;
|
||||
i64 => f32, f64, i64;
|
||||
}
|
||||
|
||||
half_promotion! {
|
||||
i8 => u8, u16, u32, usize, u64;
|
||||
i16 => u16, u32, usize, u64;
|
||||
i32 => u32, usize, u64;
|
||||
isize => u32, usize, u64;
|
||||
i64 => u64;
|
||||
}
|
||||
|
||||
from_signed! {
|
||||
|
||||
i16 => i8, u8;
|
||||
i32 => i8, i16, u8, u16;
|
||||
isize => i8, i16, u8, u16;
|
||||
i64 => i8, i16, i32, isize, u8, u16, u32, usize;
|
||||
}
|
||||
|
||||
// Unsigned
|
||||
promotion! {
|
||||
u8 => f32, f64, i16, i32, isize, i64, u8, u16, u32, usize, u64;
|
||||
u16 => f32, f64, i32, isize, i64, u16, u32, usize, u64;
|
||||
u32 => f32, f64, i64, u32, usize, u64;
|
||||
usize => f32, f64, i64, u32, usize, u64;
|
||||
u64 => f32, f64, u64;
|
||||
}
|
||||
|
||||
from_unsigned! {
|
||||
u8 => i8;
|
||||
u16 => i8, i16, u8;
|
||||
u32 => i8, i16, i32, isize, u8, u16;
|
||||
usize => i8, i16, i32, isize, u8, u16;
|
||||
u64 => i8, i16, i32, isize, i64, u8, u16, u32, usize;
|
||||
}
|
||||
|
||||
// Float
|
||||
promotion! {
|
||||
f32 => f32, f64;
|
||||
f64 => f64;
|
||||
}
|
||||
|
||||
from_float! {
|
||||
f32 => i8, i16, i32, isize, i64, u8, u16, u32, usize, u64;
|
||||
f64 => i8, i16, i32, isize, i64, u8, u16, u32, usize, u64;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
mod _64 {
|
||||
use {Error, From};
|
||||
|
||||
// Signed
|
||||
promotion! {
|
||||
i8 => f32, f64, i8, i16, i32, i64, isize;
|
||||
i16 => f32, f64, i16, i32, i64, isize;
|
||||
i32 => f32, f64, i32, i64, isize;
|
||||
i64 => f32, f64, i64, isize;
|
||||
isize => f32, f64, i64, isize;
|
||||
}
|
||||
|
||||
half_promotion! {
|
||||
i8 => u8, u16, u32, u64, usize;
|
||||
i16 => u16, u32, u64, usize;
|
||||
i32 => u32, u64, usize;
|
||||
i64 => u64, usize;
|
||||
isize => u64, usize;
|
||||
}
|
||||
|
||||
from_signed! {
|
||||
|
||||
i16 => i8, u8;
|
||||
i32 => i8, i16, u8, u16;
|
||||
i64 => i8, i16, i32, u8, u16, u32;
|
||||
isize => i8, i16, i32, u8, u16, u32;
|
||||
}
|
||||
|
||||
// Unsigned
|
||||
promotion! {
|
||||
u8 => f32, f64, i16, i32, i64, isize, u8, u16, u32, u64, usize;
|
||||
u16 => f32, f64, i32, i64, isize, u16, u32, u64, usize;
|
||||
u32 => f32, f64, i64, isize, u32, u64, usize;
|
||||
u64 => f32, f64, u64, usize;
|
||||
usize => f32, f64, u64, usize;
|
||||
}
|
||||
|
||||
from_unsigned! {
|
||||
u8 => i8;
|
||||
u16 => i8, i16, u8;
|
||||
u32 => i8, i16, i32, u8, u16;
|
||||
u64 => i8, i16, i32, i64, isize, u8, u16, u32;
|
||||
usize => i8, i16, i32, i64, isize, u8, u16, u32;
|
||||
}
|
||||
|
||||
// Float
|
||||
promotion! {
|
||||
f32 => f32, f64;
|
||||
f64 => f64;
|
||||
}
|
||||
|
||||
from_float! {
|
||||
f32 => i8, i16, i32, i64, isize, u8, u16, u32, u64, usize;
|
||||
f64 => i8, i16, i32, i64, isize, u8, u16, u32, u64, usize;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "x128")]
|
||||
mod _x128 {
|
||||
use {Error, From};
|
||||
|
||||
// Signed
|
||||
promotion! {
|
||||
i8 => i128;
|
||||
i16 => i128;
|
||||
i32 => i128;
|
||||
i64 => i128;
|
||||
isize => i128;
|
||||
i128 => f32, f64, i128;
|
||||
}
|
||||
|
||||
half_promotion! {
|
||||
i8 => u128;
|
||||
i16 => u128;
|
||||
i32 => u128;
|
||||
i64 => u128;
|
||||
isize => u128;
|
||||
i128 => u128;
|
||||
}
|
||||
|
||||
from_signed! {
|
||||
i128 => i8, i16, i32, i64, isize, u8, u16, u32, u64, usize;
|
||||
}
|
||||
|
||||
// Unsigned
|
||||
promotion! {
|
||||
u8 => i128, u128;
|
||||
u16 => i128, u128;
|
||||
u32 => i128, u128;
|
||||
u64 => i128, u128;
|
||||
usize => i128, u128;
|
||||
u128 => f64, u128;
|
||||
}
|
||||
|
||||
from_unsigned! {
|
||||
u128 => f32, i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, usize;
|
||||
}
|
||||
|
||||
// Float
|
||||
from_float! {
|
||||
f32 => i128;
|
||||
f64 => i128, u128;
|
||||
}
|
||||
from_float_dst! {
|
||||
f32 => u128;
|
||||
}
|
||||
}
|
||||
|
||||
// The missing piece
|
||||
impl From<f64> for f32 {
|
||||
type Output = Result<f32, Error>;
|
||||
|
||||
#[inline]
|
||||
fn cast(src: f64) -> Self::Output {
|
||||
use core::{f32, f64};
|
||||
|
||||
if src != src || src == f64::INFINITY || src == f64::NEG_INFINITY {
|
||||
Ok(src as f32)
|
||||
} else if src < f32::MIN as f64 {
|
||||
Err(Error::Underflow)
|
||||
} else if src > f32::MAX as f64 {
|
||||
Err(Error::Overflow)
|
||||
} else {
|
||||
Ok(src as f32)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,191 @@
|
|||
// If `src` can be promoted to `$dst`, then it must be Ok to cast `dst` back to
|
||||
// `$src`
|
||||
macro_rules! promote_and_back {
|
||||
($($src:ident => $($dst:ident),+);+;) => {
|
||||
mod demoting_to {
|
||||
$(
|
||||
mod $src {
|
||||
mod from {
|
||||
use From;
|
||||
|
||||
$(
|
||||
quickcheck! {
|
||||
fn $dst(src: $src) -> bool {
|
||||
$src::cast($dst::cast(src)).is_ok()
|
||||
}
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
promote_and_back! {
|
||||
i8 => f32, f64, i16, i32, isize, i64 ;
|
||||
i16 => f32, f64, i32, isize, i64 ;
|
||||
i32 => f32, f64, i64 ;
|
||||
isize => f32, f64, i64 ;
|
||||
i64 => f32, f64 ;
|
||||
u8 => f32, f64, i16, i32, isize, i64, u16, u32, usize, u64;
|
||||
u16 => f32, f64, i32, isize, i64, u32, usize, u64;
|
||||
u32 => f32, f64, i64, u64;
|
||||
usize => f32, f64, i64, u64;
|
||||
u64 => f32, f64 ;
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
promote_and_back! {
|
||||
i8 => f32, f64, i16, i32, i64, isize ;
|
||||
i16 => f32, f64, i32, i64, isize ;
|
||||
i32 => f32, f64, i64, isize ;
|
||||
i64 => f32, f64 ;
|
||||
isize => f32, f64 ;
|
||||
u8 => f32, f64, i16, i32, i64, isize, u16, u32, u64, usize;
|
||||
u16 => f32, f64, i32, i64, isize, u32, u64, usize;
|
||||
u32 => f32, f64, i64, isize, u64, usize;
|
||||
u64 => f32, f64 ;
|
||||
usize => f32, f64 ;
|
||||
}
|
||||
|
||||
// TODO uncomment this once quickcheck supports Arbitrary for i128/u128
|
||||
// https://github.com/BurntSushi/quickcheck/issues/162
|
||||
/*#[cfg(feature = "x128")]
|
||||
promote_and_back! {
|
||||
i8 => i128 ;
|
||||
i16 => i128 ;
|
||||
i32 => i128 ;
|
||||
isize => i128 ;
|
||||
i64 => i128 ;
|
||||
i128 => f32, f64 ;
|
||||
u8 => i128, u128;
|
||||
u16 => i128, u128;
|
||||
u32 => i128, u128;
|
||||
usize => i128, u128;
|
||||
u64 => i128, u128;
|
||||
u128 => f32, f64 ;
|
||||
}*/
|
||||
|
||||
// If it's Ok to cast `src` to `$dst`, it must also be Ok to cast `dst` back to
|
||||
// `$src`
|
||||
macro_rules! symmetric_cast_between {
|
||||
($($src:ident => $($dst:ident),+);+;) => {
|
||||
mod symmetric_cast_between {
|
||||
$(
|
||||
mod $src {
|
||||
mod and {
|
||||
use quickcheck::TestResult;
|
||||
|
||||
use From;
|
||||
|
||||
$(
|
||||
quickcheck! {
|
||||
fn $dst(src: $src) -> TestResult {
|
||||
if let Ok(dst) = $dst::cast(src) {
|
||||
TestResult::from_bool(
|
||||
$src::cast(dst).is_ok())
|
||||
} else {
|
||||
TestResult::discard()
|
||||
}
|
||||
}
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
symmetric_cast_between! {
|
||||
u8 => i8 ;
|
||||
u16 => i8, i16 ;
|
||||
u32 => i8, i16, i32 ;
|
||||
usize => i8, i16, i32 ;
|
||||
u64 => i8, i16, i32, i64, isize;
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
symmetric_cast_between! {
|
||||
u8 => i8 ;
|
||||
u16 => i8, i16 ;
|
||||
u32 => i8, i16, i32 ;
|
||||
u64 => i8, i16, i32, i64, isize;
|
||||
usize => i8, i16, i32, i64, isize;
|
||||
}
|
||||
|
||||
// TODO uncomment this once quickcheck supports Arbitrary for i128/u128
|
||||
// https://github.com/BurntSushi/quickcheck/issues/162
|
||||
/*#[cfg(feature = "x128")]
|
||||
symmetric_cast_between! {
|
||||
u128 => i8, i16, i32, isize, i64, i128;
|
||||
}*/
|
||||
|
||||
macro_rules! from_float {
|
||||
($($src:ident => $($dst:ident),+);+;) => {
|
||||
$(
|
||||
mod $src {
|
||||
mod inf {
|
||||
mod to {
|
||||
use {Error, From};
|
||||
|
||||
$(
|
||||
#[test]
|
||||
fn $dst() {
|
||||
let _0: $src = 0.;
|
||||
let _1: $src = 1.;
|
||||
let inf = _1 / _0;
|
||||
let neg_inf = -_1 / _0;
|
||||
|
||||
assert_eq!($dst::cast(inf),
|
||||
Err(Error::Infinite));
|
||||
assert_eq!($dst::cast(neg_inf),
|
||||
Err(Error::Infinite));
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
mod nan {
|
||||
mod to {
|
||||
use {Error, From};
|
||||
|
||||
$(
|
||||
#[test]
|
||||
fn $dst() {
|
||||
let _0: $src = 0.;
|
||||
let nan = _0 / _0;
|
||||
|
||||
assert_eq!($dst::cast(nan),
|
||||
Err(Error::NaN));
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
from_float! {
|
||||
f32 => i8, i16, i32, i64, isize, u8, u16, u32, u64, usize;
|
||||
f64 => i8, i16, i32, i64, isize, u8, u16, u32, u64, usize;
|
||||
}
|
||||
|
||||
// TODO uncomment this once quickcheck supports Arbitrary for i128/u128
|
||||
// https://github.com/BurntSushi/quickcheck/issues/162
|
||||
/*#[cfg(feature = "x128")]
|
||||
from_float! {
|
||||
f32 => i128, u128;
|
||||
f64 => i128, u128;
|
||||
}*/
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "x128")]
|
||||
fn test_fl_conversion() {
|
||||
use u128;
|
||||
assert_eq!(u128(42.0f32), Ok(42));
|
||||
}
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"8c219cb955621bfeb89eb1175dc9d810dc98323ccb54360e623425308c970e72","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"af367c67340fa7f6fb9a35b0aa637dcf303957f7ae7427a5f4f6356801c8bb04","src/lib.rs":"01f8c9b8a077975c8f0803f793b8c20b583aaef2dc1f4400b9d90ba132ff4133","src/map.rs":"77eb9fd2ffdaafaf4daea609602a0c775c5012efae21c03547f63653271da163","src/node.rs":"309609acc70f1ce6be2f3c964430d23c0680bd7a647afab837a2aedc06235531","src/path.rs":"25326bacbb99189e873cb70e770f21c13fdef0fb2cd20f484830386fc4c75c6a","src/pool.rs":"196216124922dc42708a3aa944e98b6a57ef9bb770dab7e01f154b6382cab021","src/set.rs":"d4ff99fe51de9eefb4c774e919259d952ab5dde4dd3b99bd9974e4eedbb28938"},"package":"7b2d527b241af388ff017d72f2b0b323929a70cf97342c6ec1534e3b0f4dfaa0"}
|
||||
{"files":{"Cargo.toml":"591c2da0dad7eafa9aff626400b38e0b08927df674292ca6774f60e2bc02ac32","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"af367c67340fa7f6fb9a35b0aa637dcf303957f7ae7427a5f4f6356801c8bb04","src/lib.rs":"eb691a3bc63c3ed8a64d564cf656fdc56c62ade8b7882efd7b987353acc627bd","src/map.rs":"77eb9fd2ffdaafaf4daea609602a0c775c5012efae21c03547f63653271da163","src/node.rs":"309609acc70f1ce6be2f3c964430d23c0680bd7a647afab837a2aedc06235531","src/path.rs":"25326bacbb99189e873cb70e770f21c13fdef0fb2cd20f484830386fc4c75c6a","src/pool.rs":"196216124922dc42708a3aa944e98b6a57ef9bb770dab7e01f154b6382cab021","src/set.rs":"d4ff99fe51de9eefb4c774e919259d952ab5dde4dd3b99bd9974e4eedbb28938"},"package":"40f8ff24e9a6c89b8a846b14df9a34d2cac17cea7bdb5c81ed6b4744ee0e38bf"}
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
[package]
|
||||
name = "cranelift-bforest"
|
||||
version = "0.25.0"
|
||||
version = "0.26.0"
|
||||
authors = ["The Cranelift Project Developers"]
|
||||
description = "A forest of B+-trees"
|
||||
documentation = "https://cranelift.readthedocs.io/"
|
||||
|
@ -22,7 +22,7 @@ categories = ["no-std"]
|
|||
license = "Apache-2.0 WITH LLVM-exception"
|
||||
repository = "https://github.com/CraneStation/cranelift"
|
||||
[dependencies.cranelift-entity]
|
||||
version = "0.25.0"
|
||||
version = "0.26.0"
|
||||
default-features = false
|
||||
|
||||
[features]
|
||||
|
|
|
@ -16,10 +16,7 @@
|
|||
#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)]
|
||||
#![warn(unused_import_braces)]
|
||||
#![cfg_attr(feature = "std", warn(unstable_features))]
|
||||
#![cfg_attr(
|
||||
feature = "clippy",
|
||||
plugin(clippy(conf_file = "../../clippy.toml"))
|
||||
)]
|
||||
#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))]
|
||||
#![cfg_attr(
|
||||
feature = "cargo-clippy",
|
||||
allow(new_without_default, new_without_default_derive)
|
||||
|
@ -27,14 +24,14 @@
|
|||
#![cfg_attr(
|
||||
feature = "cargo-clippy",
|
||||
warn(
|
||||
float_arithmetic,
|
||||
mut_mut,
|
||||
nonminimal_bool,
|
||||
option_map_unwrap_or,
|
||||
option_map_unwrap_or_else,
|
||||
print_stdout,
|
||||
unicode_not_nfc,
|
||||
use_self
|
||||
clippy::float_arithmetic,
|
||||
clippy::mut_mut,
|
||||
clippy::nonminimal_bool,
|
||||
clippy::option_map_unwrap_or,
|
||||
clippy::option_map_unwrap_or_else,
|
||||
clippy::print_stdout,
|
||||
clippy::unicode_not_nfc,
|
||||
clippy::use_self
|
||||
)
|
||||
)]
|
||||
// Turns on no_std and alloc features if std is not available.
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"0e4050095c283d025e30ccba0e3d9753b63340604b6373e4ea06d221eb3a97e1","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"b123f056d0d458396679c5f7f2a16d2762af0258fcda4ac14b6655a95e5a0022","src/base/mod.rs":"9320dfed2250bdb0347e01862b2ff7bf7db78920dae1719834b374de11131e87","src/base/types.rs":"a3e449db1f515d268f3ad21301740ba415444d399f8433dbc48979f78557f66a","src/cdsl/isa.rs":"b34150e2658dd7ab30e9846dece89f56a0acbfff0341927cec06bf0de1d9b419","src/cdsl/mod.rs":"311726d7e4ad9278eab301fd4f6e31e697b7d4260733c6a00fe39cd61db977d3","src/cdsl/regs.rs":"41cca844b390bba3ceefa147e7b0dec170aba2b5759a41ecb5b9cd7f2cc59f60","src/cdsl/types.rs":"f9756e483329f00a1d8a15e30bc05e8d4c8fa71ff1f649b808528ddeb5fbdfea","src/error.rs":"5110a4e3c1e97396ba02d9f5abbb8af4b586f0cc4d33a5c2473f1718cc4bef05","src/gen_registers.rs":"3d38ff5b0c6183209d4ba84bd1f14b1d84bea697c0589471aa5ce4abc209f20b","src/gen_types.rs":"5eb4e9bd0fda7f7644bb2428045f0bf16f2b698ff32cadcbbf7f2c7669f18de3","src/isa/arm32/mod.rs":"ceb8290344a245f11eb541d60c2678ddfe7beaf60cde491c22fd48090fa210ba","src/isa/arm64/mod.rs":"db7f828940372a21c62cf6f5aefca7cc05c974ba731b8db602da0a336e29ea1e","src/isa/mod.rs":"36c001f8ecdea4aaf8cadcad4f91fe79a82806e4f43182e216c2fa99cecf55dc","src/isa/riscv/mod.rs":"aecb127f8c06970a00dde8ad772fdebe5497b6e7f342fa2a0e859355ae027055","src/isa/x86/mod.rs":"2b3a181a226d66a8faf855d517fb4a13554a31020f6b8875ba75a2fe650f378a","src/lib.rs":"dd97d73d41ffee2d2cc62705f9f6f7ed6b9af982aff8d1fafb72590e097c513c","src/srcgen.rs":"abe118fb41a643ffc63577cc4b62de9a2286e1eeb34b95bff79648d0ea582886"},"package":"963262697a05d9aa63ca40f4670a7243e4525f4a098e10d654c3f5143fcef686"}
|
||||
{"files":{"Cargo.toml":"cdd4cff2d17ca34e3305e9fcf1e8277b0e9987e7369ce70da597e3957e56e408","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"b123f056d0d458396679c5f7f2a16d2762af0258fcda4ac14b6655a95e5a0022","src/base/mod.rs":"559075f0b76a744dd36224e06ff1c2e28ee70aaca9442fc724b116e37028ac52","src/base/settings.rs":"9cbe9bdd5141b9175074370a9b1d28f371249d586e999a31f76631739bf09c13","src/base/types.rs":"a3e449db1f515d268f3ad21301740ba415444d399f8433dbc48979f78557f66a","src/cdsl/isa.rs":"5c9a8173466e69d105245396abd342251eb00e704ab13f179ba1567b339f47e1","src/cdsl/mod.rs":"66ac1b5d095e431bcab88c4b9c5b1492a5d1ca87bcb9c9c3e544ede05b2ba925","src/cdsl/regs.rs":"41cca844b390bba3ceefa147e7b0dec170aba2b5759a41ecb5b9cd7f2cc59f60","src/cdsl/settings.rs":"724a4bd7cfd0608cfc8751ee7c38dbed90b91cfafd34585ed7df953807932794","src/cdsl/types.rs":"78f476f5f700697b94f2d2f00049af8684d3b27afc5684b2c87ea517aeb77e85","src/constant_hash.rs":"6522f86ebfd44efe9b47256d822d0e49d641ccdbb4fcc61d57bb94e6d52702c1","src/error.rs":"5110a4e3c1e97396ba02d9f5abbb8af4b586f0cc4d33a5c2473f1718cc4bef05","src/gen_registers.rs":"9bd381da256c19724964c6445db4fbac80d91174266dccfc5d3b72497a5332c9","src/gen_settings.rs":"a827a90cc1db7345e8081635169b77be497494e558c6e985eaa654386d5e8e48","src/gen_types.rs":"5eb4e9bd0fda7f7644bb2428045f0bf16f2b698ff32cadcbbf7f2c7669f18de3","src/isa/arm32/mod.rs":"b4049ff95164bbf244b6727e16974383e4d58c5be750f7ded3ef8cfe113e5373","src/isa/arm64/mod.rs":"759adfd4dd5c885644de26386797211efc82c5b47f2e147a58d57d24608b9cfb","src/isa/mod.rs":"d3a87bc45173f3743f25d3a004a9b40966c12feb7d95d794b5918bb9ccb988ac","src/isa/riscv/mod.rs":"6e3d96c48e9c289a13912d7f777bde805be327e4a56677d3f3bccf440ae4a09b","src/isa/x86/mod.rs":"e38c60a9d1aba3e5a48052c6185bab3f2b039e9cce639826becfe9f853c41499","src/lib.rs":"c4bfd9d2973e4a382f7a1ce8389cc1604aeba8478432a542ff3f1c24412c5b41","src/srcgen.rs":"e358b6232f0820e6e4525cdbe216206996ae5eb16a1df7a5fe41e3ce2e25b633","src/unique_table.rs":"f6041df1fa85f2a1ee914b84791e80165a0858a6253c212eaa99ff67cb56af26"},"package":"014c23ed3ebdc8377d41540af638245207dd169f421df042dfccc867465734ed"}
|
|
@ -12,14 +12,14 @@
|
|||
|
||||
[package]
|
||||
name = "cranelift-codegen-meta"
|
||||
version = "0.25.0"
|
||||
version = "0.26.0"
|
||||
authors = ["The Cranelift Project Developers"]
|
||||
description = "Metaprogram for cranelift-codegen code generator library"
|
||||
readme = "README.md"
|
||||
license = "Apache-2.0 WITH LLVM-exception"
|
||||
repository = "https://github.com/CraneStation/cranelift"
|
||||
[dependencies.cranelift-entity]
|
||||
version = "0.25.0"
|
||||
version = "0.26.0"
|
||||
[badges.maintenance]
|
||||
status = "experimental"
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//! Definitions for the base Cranelift language.
|
||||
|
||||
pub mod settings;
|
||||
pub mod types;
|
||||
|
|
|
@ -0,0 +1,164 @@
|
|||
use cdsl::settings::{SettingGroup, SettingGroupBuilder};
|
||||
|
||||
pub fn generate() -> SettingGroup {
|
||||
let mut settings = SettingGroupBuilder::new("shared");
|
||||
|
||||
settings.add_enum(
|
||||
"opt_level",
|
||||
r#"
|
||||
Optimization level:
|
||||
|
||||
- default: Very profitable optimizations enabled, none slow.
|
||||
- best: Enable all optimizations
|
||||
- fastest: Optimize for compile time by disabling most optimizations.
|
||||
"#,
|
||||
vec!["default", "best", "fastest"],
|
||||
);
|
||||
|
||||
settings.add_bool(
|
||||
"enable_verifier",
|
||||
r#"
|
||||
Run the Cranelift IR verifier at strategic times during compilation.
|
||||
|
||||
This makes compilation slower but catches many bugs. The verifier is
|
||||
disabled by default, except when reading Cranelift IR from a text file.
|
||||
"#,
|
||||
true,
|
||||
);
|
||||
|
||||
// Note that Cranelift doesn't currently need an is_pie flag, because PIE is
|
||||
// just PIC where symbols can't be pre-empted, which can be expressed with the
|
||||
// `colocated` flag on external functions and global values.
|
||||
settings.add_bool(
|
||||
"is_pic",
|
||||
"Enable Position-Independent Code generation",
|
||||
false,
|
||||
);
|
||||
|
||||
settings.add_bool(
|
||||
"colocated_libcalls",
|
||||
r#"
|
||||
Use colocated libcalls.
|
||||
|
||||
Generate code that assumes that libcalls can be declared "colocated",
|
||||
meaning they will be defined along with the current function, such that
|
||||
they can use more efficient addressing.
|
||||
"#,
|
||||
false,
|
||||
);
|
||||
|
||||
settings.add_bool(
|
||||
"avoid_div_traps",
|
||||
r#"
|
||||
Generate explicit checks around native division instructions to avoid
|
||||
their trapping.
|
||||
|
||||
This is primarily used by SpiderMonkey which doesn't install a signal
|
||||
handler for SIGFPE, but expects a SIGILL trap for division by zero.
|
||||
|
||||
On ISAs like ARM where the native division instructions don't trap,
|
||||
this setting has no effect - explicit checks are always inserted.
|
||||
"#,
|
||||
false,
|
||||
);
|
||||
|
||||
settings.add_bool(
|
||||
"enable_float",
|
||||
r#"
|
||||
Enable the use of floating-point instructions
|
||||
|
||||
Disabling use of floating-point instructions is not yet implemented.
|
||||
"#,
|
||||
true,
|
||||
);
|
||||
|
||||
settings.add_bool(
|
||||
"enable_nan_canonicalization",
|
||||
r#"
|
||||
Enable NaN canonicalization
|
||||
|
||||
This replaces NaNs with a single canonical value, for users requiring
|
||||
entirely deterministic WebAssembly computation. This is not required
|
||||
by the WebAssembly spec, so it is not enabled by default.
|
||||
"#,
|
||||
false,
|
||||
);
|
||||
|
||||
settings.add_bool("enable_simd", "Enable the use of SIMD instructions.", true);
|
||||
|
||||
settings.add_bool(
|
||||
"enable_atomics",
|
||||
"Enable the use of atomic instructions",
|
||||
true,
|
||||
);
|
||||
|
||||
// Settings specific to the `baldrdash` calling convention.
|
||||
|
||||
settings.add_num(
|
||||
"baldrdash_prologue_words",
|
||||
r#"
|
||||
Number of pointer-sized words pushed by the baldrdash prologue.
|
||||
|
||||
Functions with the `baldrdash` calling convention don't generate their
|
||||
own prologue and epilogue. They depend on externally generated code
|
||||
that pushes a fixed number of words in the prologue and restores them
|
||||
in the epilogue.
|
||||
|
||||
This setting configures the number of pointer-sized words pushed on the
|
||||
stack when the Cranelift-generated code is entered. This includes the
|
||||
pushed return address on x86.
|
||||
"#,
|
||||
0,
|
||||
);
|
||||
|
||||
// BaldrMonkey requires that not-yet-relocated function addresses be encoded
|
||||
// as all-ones bitpatterns.
|
||||
settings.add_bool(
|
||||
"allones_funcaddrs",
|
||||
"Emit not-yet-relocated function addresses as all-ones bit patterns.",
|
||||
false,
|
||||
);
|
||||
|
||||
// Stack probing options.
|
||||
|
||||
settings.add_bool(
|
||||
"probestack_enabled",
|
||||
r#"
|
||||
Enable the use of stack probes, for calling conventions which support this
|
||||
functionality.
|
||||
"#,
|
||||
true,
|
||||
);
|
||||
|
||||
settings.add_bool(
|
||||
"probestack_func_adjusts_sp",
|
||||
r#"
|
||||
Set this to true of the stack probe function modifies the stack pointer
|
||||
itself.
|
||||
"#,
|
||||
false,
|
||||
);
|
||||
|
||||
settings.add_num(
|
||||
"probestack_size_log2",
|
||||
r#"
|
||||
The log2 of the size of the stack guard region.
|
||||
|
||||
Stack frames larger than this size will have stack overflow checked
|
||||
by calling the probestack function.
|
||||
|
||||
The default is 12, which translates to a size of 4096.
|
||||
"#,
|
||||
12,
|
||||
);
|
||||
|
||||
// Jump table options.
|
||||
|
||||
settings.add_bool(
|
||||
"jump_tables_enabled",
|
||||
"Enable the use of jump tables in generated machine code.",
|
||||
true,
|
||||
);
|
||||
|
||||
settings.finish()
|
||||
}
|
|
@ -3,19 +3,22 @@ use cranelift_entity::PrimaryMap;
|
|||
use super::regs::{
|
||||
RegBank, RegBankBuilder, RegBankIndex, RegClass, RegClassBuilder, RegClassIndex, RegClassProto,
|
||||
};
|
||||
use super::settings::SettingGroup;
|
||||
|
||||
pub struct TargetIsa {
|
||||
pub name: &'static str,
|
||||
pub reg_banks: PrimaryMap<RegBankIndex, RegBank>,
|
||||
pub reg_classes: PrimaryMap<RegClassIndex, RegClass>,
|
||||
pub settings: SettingGroup,
|
||||
}
|
||||
|
||||
impl TargetIsa {
|
||||
pub fn new(name: &'static str) -> Self {
|
||||
pub fn new(name: &'static str, settings: SettingGroup) -> Self {
|
||||
Self {
|
||||
name,
|
||||
reg_banks: PrimaryMap::new(),
|
||||
reg_classes: PrimaryMap::new(),
|
||||
settings,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,9 +28,9 @@ pub struct TargetIsaBuilder {
|
|||
}
|
||||
|
||||
impl TargetIsaBuilder {
|
||||
pub fn new(name: &'static str) -> Self {
|
||||
pub fn new(name: &'static str, settings: SettingGroup) -> Self {
|
||||
Self {
|
||||
isa: TargetIsa::new(name),
|
||||
isa: TargetIsa::new(name, settings),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,16 +153,15 @@ impl TargetIsaBuilder {
|
|||
|
||||
// If the intersection is the second one, then it must be a subclass.
|
||||
if intersect == rc2_mask {
|
||||
assert!(
|
||||
self.isa
|
||||
.reg_classes
|
||||
.get(*i1)
|
||||
.unwrap()
|
||||
.subclasses
|
||||
.iter()
|
||||
.find(|x| **x == *i2)
|
||||
.is_some()
|
||||
);
|
||||
assert!(self
|
||||
.isa
|
||||
.reg_classes
|
||||
.get(*i1)
|
||||
.unwrap()
|
||||
.subclasses
|
||||
.iter()
|
||||
.find(|x| **x == *i2)
|
||||
.is_some());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -181,7 +183,8 @@ impl TargetIsaBuilder {
|
|||
.values()
|
||||
.filter(|x| {
|
||||
x.toprc == x.index && self.isa.reg_banks.get(x.bank).unwrap().pressure_tracking
|
||||
}).count();
|
||||
})
|
||||
.count();
|
||||
assert!(num_toplevel <= 4, "Too many top-level register classes");
|
||||
|
||||
self.isa
|
||||
|
|
|
@ -5,10 +5,38 @@
|
|||
|
||||
pub mod isa;
|
||||
pub mod regs;
|
||||
pub mod settings;
|
||||
pub mod types;
|
||||
|
||||
/// A macro that converts boolean settings into predicates to look more natural.
|
||||
#[macro_export]
|
||||
macro_rules! predicate {
|
||||
($a:ident && $($b:tt)*) => {
|
||||
PredicateNode::And(Box::new($a.into()), Box::new(predicate!($($b)*)))
|
||||
};
|
||||
($a:ident) => {
|
||||
$a.into()
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! preset {
|
||||
() => {
|
||||
vec![]
|
||||
};
|
||||
($($x:ident)&&*) => {
|
||||
{
|
||||
let mut v = Vec::new();
|
||||
$(
|
||||
v.push($x.into());
|
||||
)*
|
||||
v
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Convert the string `s` to CamelCase.
|
||||
fn _camel_case(s: &str) -> String {
|
||||
pub fn camel_case(s: &str) -> String {
|
||||
let mut output_chars = String::with_capacity(s.len());
|
||||
|
||||
let mut capitalize = true;
|
||||
|
@ -30,7 +58,7 @@ fn _camel_case(s: &str) -> String {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::_camel_case as camel_case;
|
||||
use super::camel_case;
|
||||
|
||||
#[test]
|
||||
fn camel_case_works() {
|
||||
|
|
|
@ -0,0 +1,386 @@
|
|||
use std::iter;
|
||||
|
||||
#[derive(Clone, Copy, Hash, PartialEq, Eq)]
|
||||
pub struct BoolSettingIndex(usize);
|
||||
|
||||
#[derive(Hash, PartialEq, Eq)]
|
||||
pub struct BoolSetting {
|
||||
pub default: bool,
|
||||
pub bit_offset: u8,
|
||||
pub predicate_number: u8,
|
||||
}
|
||||
|
||||
#[derive(Hash, PartialEq, Eq)]
|
||||
pub enum SpecificSetting {
|
||||
Bool(BoolSetting),
|
||||
Enum(Vec<&'static str>),
|
||||
Num(u8),
|
||||
}
|
||||
|
||||
#[derive(Hash, PartialEq, Eq)]
|
||||
pub struct Setting {
|
||||
pub name: &'static str,
|
||||
pub comment: &'static str,
|
||||
pub specific: SpecificSetting,
|
||||
pub byte_offset: u8,
|
||||
}
|
||||
|
||||
impl Setting {
|
||||
pub fn default_byte(&self) -> u8 {
|
||||
match self.specific {
|
||||
SpecificSetting::Bool(BoolSetting {
|
||||
default,
|
||||
bit_offset,
|
||||
..
|
||||
}) => {
|
||||
if default {
|
||||
1 << bit_offset
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
SpecificSetting::Enum(_) => 0,
|
||||
SpecificSetting::Num(default) => default,
|
||||
}
|
||||
}
|
||||
|
||||
fn byte_for_value(&self, v: bool) -> u8 {
|
||||
match self.specific {
|
||||
SpecificSetting::Bool(BoolSetting { bit_offset, .. }) => {
|
||||
if v {
|
||||
1 << bit_offset
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
_ => panic!("byte_for_value shouldn't be used for non-boolean settings."),
|
||||
}
|
||||
}
|
||||
|
||||
fn byte_mask(&self) -> u8 {
|
||||
match self.specific {
|
||||
SpecificSetting::Bool(BoolSetting { bit_offset, .. }) => 1 << bit_offset,
|
||||
_ => panic!("byte_for_value shouldn't be used for non-boolean settings."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Hash, PartialEq, Eq)]
|
||||
pub struct PresetIndex(usize);
|
||||
|
||||
#[derive(Hash, PartialEq, Eq)]
|
||||
pub enum PresetType {
|
||||
BoolSetting(BoolSettingIndex),
|
||||
OtherPreset(PresetIndex),
|
||||
}
|
||||
|
||||
impl Into<PresetType> for BoolSettingIndex {
|
||||
fn into(self) -> PresetType {
|
||||
PresetType::BoolSetting(self)
|
||||
}
|
||||
}
|
||||
impl Into<PresetType> for PresetIndex {
|
||||
fn into(self) -> PresetType {
|
||||
PresetType::OtherPreset(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Hash, PartialEq, Eq)]
|
||||
pub struct Preset {
|
||||
pub name: &'static str,
|
||||
values: Vec<BoolSettingIndex>,
|
||||
}
|
||||
|
||||
impl Preset {
|
||||
pub fn layout(&self, group: &SettingGroup) -> Vec<(u8, u8)> {
|
||||
let mut layout: Vec<(u8, u8)> = iter::repeat((0, 0))
|
||||
.take(group.settings_size as usize)
|
||||
.collect();
|
||||
for bool_index in &self.values {
|
||||
let setting = &group.settings[bool_index.0];
|
||||
let mask = setting.byte_mask();
|
||||
let val = setting.byte_for_value(true);
|
||||
assert!((val & !mask) == 0);
|
||||
let (l_mask, l_val) = layout.get_mut(setting.byte_offset as usize).unwrap();
|
||||
*l_mask |= mask;
|
||||
*l_val = (*l_val & !mask) | val;
|
||||
}
|
||||
layout
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SettingGroup {
|
||||
pub name: &'static str,
|
||||
pub settings: Vec<Setting>,
|
||||
pub bool_start_byte_offset: u8,
|
||||
pub settings_size: u8,
|
||||
pub presets: Vec<Preset>,
|
||||
pub predicates: Vec<Predicate>,
|
||||
}
|
||||
|
||||
impl SettingGroup {
|
||||
fn num_bool_settings(&self) -> u8 {
|
||||
self.settings
|
||||
.iter()
|
||||
.filter(|s| {
|
||||
if let SpecificSetting::Bool(_) = s.specific {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
.count() as u8
|
||||
}
|
||||
|
||||
pub fn byte_size(&self) -> u8 {
|
||||
let num_predicates = self.num_bool_settings() + (self.predicates.len() as u8);
|
||||
self.bool_start_byte_offset + (num_predicates + 7) / 8
|
||||
}
|
||||
|
||||
pub fn get_bool(&self, name: &'static str) -> (BoolSettingIndex, &Self) {
|
||||
for (i, s) in self.settings.iter().enumerate() {
|
||||
if let SpecificSetting::Bool(_) = s.specific {
|
||||
if s.name == name {
|
||||
return (BoolSettingIndex(i), self);
|
||||
}
|
||||
}
|
||||
}
|
||||
panic!("Should have found bool setting by name.");
|
||||
}
|
||||
}
|
||||
|
||||
/// This is the basic information needed to track the specific parts of a setting when building
|
||||
/// them.
|
||||
pub enum ProtoSpecificSetting {
|
||||
Bool(bool, u8),
|
||||
Enum(Vec<&'static str>),
|
||||
Num(u8),
|
||||
}
|
||||
|
||||
/// This is the information provided during building for a setting.
|
||||
struct ProtoSetting {
|
||||
name: &'static str,
|
||||
comment: &'static str,
|
||||
specific: ProtoSpecificSetting,
|
||||
}
|
||||
|
||||
#[derive(Hash, PartialEq, Eq)]
|
||||
pub enum PredicateNode {
|
||||
OwnedBool(BoolSettingIndex),
|
||||
SharedBool(&'static str, &'static str),
|
||||
And(Box<PredicateNode>, Box<PredicateNode>),
|
||||
}
|
||||
|
||||
impl Into<PredicateNode> for BoolSettingIndex {
|
||||
fn into(self) -> PredicateNode {
|
||||
PredicateNode::OwnedBool(self)
|
||||
}
|
||||
}
|
||||
impl<'a> Into<PredicateNode> for (BoolSettingIndex, &'a SettingGroup) {
|
||||
fn into(self) -> PredicateNode {
|
||||
let (index, group) = (self.0, self.1);
|
||||
let setting = &group.settings[index.0];
|
||||
PredicateNode::SharedBool(group.name, setting.name)
|
||||
}
|
||||
}
|
||||
|
||||
impl PredicateNode {
|
||||
fn render(&self, group: &SettingGroup) -> String {
|
||||
match self {
|
||||
PredicateNode::OwnedBool(bool_setting_index) => format!(
|
||||
"{}.{}()",
|
||||
group.name, group.settings[bool_setting_index.0].name
|
||||
),
|
||||
PredicateNode::SharedBool(group_name, bool_name) => {
|
||||
format!("{}.{}()", group_name, bool_name)
|
||||
}
|
||||
PredicateNode::And(lhs, rhs) => {
|
||||
format!("{} && {}", lhs.render(group), rhs.render(group))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Predicate {
|
||||
pub name: &'static str,
|
||||
node: PredicateNode,
|
||||
pub number: u8,
|
||||
}
|
||||
|
||||
impl Predicate {
|
||||
pub fn render(&self, group: &SettingGroup) -> String {
|
||||
self.node.render(group)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SettingGroupBuilder {
|
||||
name: &'static str,
|
||||
settings: Vec<ProtoSetting>,
|
||||
presets: Vec<Preset>,
|
||||
predicates: Vec<Predicate>,
|
||||
predicate_number: u8,
|
||||
}
|
||||
|
||||
impl SettingGroupBuilder {
|
||||
pub fn new(name: &'static str) -> Self {
|
||||
Self {
|
||||
name,
|
||||
settings: Vec::new(),
|
||||
presets: Vec::new(),
|
||||
predicates: Vec::new(),
|
||||
predicate_number: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn add_setting(
|
||||
&mut self,
|
||||
name: &'static str,
|
||||
comment: &'static str,
|
||||
specific: ProtoSpecificSetting,
|
||||
) {
|
||||
self.settings.push(ProtoSetting {
|
||||
name,
|
||||
comment,
|
||||
specific,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn add_bool(
|
||||
&mut self,
|
||||
name: &'static str,
|
||||
comment: &'static str,
|
||||
default: bool,
|
||||
) -> BoolSettingIndex {
|
||||
assert!(
|
||||
self.predicates.len() == 0,
|
||||
"predicates must be added after the boolean settings"
|
||||
);
|
||||
let predicate_number = self.predicate_number;
|
||||
self.predicate_number += 1;
|
||||
self.add_setting(
|
||||
name,
|
||||
comment,
|
||||
ProtoSpecificSetting::Bool(default, predicate_number),
|
||||
);
|
||||
BoolSettingIndex(self.settings.len() - 1)
|
||||
}
|
||||
|
||||
pub fn add_enum(
|
||||
&mut self,
|
||||
name: &'static str,
|
||||
comment: &'static str,
|
||||
values: Vec<&'static str>,
|
||||
) {
|
||||
self.add_setting(name, comment, ProtoSpecificSetting::Enum(values));
|
||||
}
|
||||
|
||||
pub fn add_num(&mut self, name: &'static str, comment: &'static str, default: u8) {
|
||||
self.add_setting(name, comment, ProtoSpecificSetting::Num(default));
|
||||
}
|
||||
|
||||
pub fn add_predicate(&mut self, name: &'static str, node: PredicateNode) {
|
||||
let number = self.predicate_number;
|
||||
self.predicate_number += 1;
|
||||
self.predicates.push(Predicate { name, node, number });
|
||||
}
|
||||
|
||||
pub fn add_preset(&mut self, name: &'static str, args: Vec<PresetType>) -> PresetIndex {
|
||||
let mut values = Vec::new();
|
||||
for arg in args {
|
||||
match arg {
|
||||
PresetType::OtherPreset(index) => {
|
||||
values.extend(self.presets[index.0].values.iter());
|
||||
}
|
||||
PresetType::BoolSetting(index) => values.push(index),
|
||||
}
|
||||
}
|
||||
self.presets.push(Preset { name, values });
|
||||
PresetIndex(self.presets.len() - 1)
|
||||
}
|
||||
|
||||
/// Compute the layout of the byte vector used to represent this settings
|
||||
/// group.
|
||||
///
|
||||
/// The byte vector contains the following entries in order:
|
||||
///
|
||||
/// 1. Byte-sized settings like `NumSetting` and `EnumSetting`.
|
||||
/// 2. `BoolSetting` settings.
|
||||
/// 3. Precomputed named predicates.
|
||||
/// 4. Other numbered predicates, including anonymous predicates and parent
|
||||
/// predicates that need to be accessible by number.
|
||||
///
|
||||
/// Set `self.settings_size` to the length of the byte vector prefix that
|
||||
/// contains the settings. All bytes after that are computed, not
|
||||
/// configured.
|
||||
///
|
||||
/// Set `self.boolean_offset` to the beginning of the numbered predicates,
|
||||
/// 2. in the list above.
|
||||
///
|
||||
/// Assign `byte_offset` and `bit_offset` fields in all settings.
|
||||
///
|
||||
/// After calling this method, no more settings can be added, but
|
||||
/// additional predicates can be made accessible with `number_predicate()`.
|
||||
pub fn finish(self) -> SettingGroup {
|
||||
let mut group = SettingGroup {
|
||||
name: self.name,
|
||||
settings: Vec::new(),
|
||||
bool_start_byte_offset: 0,
|
||||
settings_size: 0,
|
||||
presets: Vec::new(),
|
||||
predicates: Vec::new(),
|
||||
};
|
||||
|
||||
let mut byte_offset = 0;
|
||||
|
||||
// Assign the non-boolean settings first.
|
||||
for s in &self.settings {
|
||||
let specific = match s.specific {
|
||||
ProtoSpecificSetting::Bool(..) => continue,
|
||||
ProtoSpecificSetting::Enum(ref values) => SpecificSetting::Enum(values.clone()),
|
||||
ProtoSpecificSetting::Num(default) => SpecificSetting::Num(default),
|
||||
};
|
||||
|
||||
group.settings.push(Setting {
|
||||
name: s.name,
|
||||
comment: s.comment,
|
||||
byte_offset,
|
||||
specific,
|
||||
});
|
||||
|
||||
byte_offset += 1;
|
||||
}
|
||||
|
||||
group.bool_start_byte_offset = byte_offset;
|
||||
|
||||
// Then the boolean settings.
|
||||
for s in &self.settings {
|
||||
let (default, predicate_number) = match s.specific {
|
||||
ProtoSpecificSetting::Bool(default, predicate_number) => {
|
||||
(default, predicate_number)
|
||||
}
|
||||
ProtoSpecificSetting::Enum(_) | ProtoSpecificSetting::Num(_) => continue,
|
||||
};
|
||||
group.settings.push(Setting {
|
||||
name: s.name,
|
||||
comment: s.comment,
|
||||
byte_offset: byte_offset + predicate_number / 8,
|
||||
specific: SpecificSetting::Bool(BoolSetting {
|
||||
default,
|
||||
bit_offset: predicate_number % 8,
|
||||
predicate_number,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
assert!(
|
||||
group.predicates.len() == 0,
|
||||
"settings_size is the byte size before adding predicates"
|
||||
);
|
||||
group.settings_size = group.byte_size();
|
||||
|
||||
group.predicates.extend(self.predicates);
|
||||
group.presets.extend(self.presets);
|
||||
|
||||
group
|
||||
}
|
||||
}
|
|
@ -190,19 +190,20 @@ impl LaneType {
|
|||
|
||||
/// Find the unique number associated with this lane type.
|
||||
pub fn number(self) -> u8 {
|
||||
LANE_BASE + match self {
|
||||
LaneType::BoolType(base_types::Bool::B1) => 0,
|
||||
LaneType::BoolType(base_types::Bool::B8) => 1,
|
||||
LaneType::BoolType(base_types::Bool::B16) => 2,
|
||||
LaneType::BoolType(base_types::Bool::B32) => 3,
|
||||
LaneType::BoolType(base_types::Bool::B64) => 4,
|
||||
LaneType::IntType(base_types::Int::I8) => 5,
|
||||
LaneType::IntType(base_types::Int::I16) => 6,
|
||||
LaneType::IntType(base_types::Int::I32) => 7,
|
||||
LaneType::IntType(base_types::Int::I64) => 8,
|
||||
LaneType::FloatType(base_types::Float::F32) => 9,
|
||||
LaneType::FloatType(base_types::Float::F64) => 10,
|
||||
}
|
||||
LANE_BASE
|
||||
+ match self {
|
||||
LaneType::BoolType(base_types::Bool::B1) => 0,
|
||||
LaneType::BoolType(base_types::Bool::B8) => 1,
|
||||
LaneType::BoolType(base_types::Bool::B16) => 2,
|
||||
LaneType::BoolType(base_types::Bool::B32) => 3,
|
||||
LaneType::BoolType(base_types::Bool::B64) => 4,
|
||||
LaneType::IntType(base_types::Int::I8) => 5,
|
||||
LaneType::IntType(base_types::Int::I16) => 6,
|
||||
LaneType::IntType(base_types::Int::I32) => 7,
|
||||
LaneType::IntType(base_types::Int::I64) => 8,
|
||||
LaneType::FloatType(base_types::Float::F32) => 9,
|
||||
LaneType::FloatType(base_types::Float::F64) => 10,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
pub fn simple_hash(s: &str) -> usize {
|
||||
let mut h: u32 = 5381;
|
||||
for c in s.chars() {
|
||||
h = (h ^ c as u32).wrapping_add(h.rotate_right(6));
|
||||
}
|
||||
h as usize
|
||||
}
|
||||
|
||||
/// Compute an open addressed, quadratically probed hash table containing
|
||||
/// `items`. The returned table is a list containing the elements of the
|
||||
/// iterable `items` and `None` in unused slots.
|
||||
pub fn generate_table<T, H: Fn(&T) -> usize>(items: &Vec<T>, hash_function: H) -> Vec<Option<&T>> {
|
||||
let size = (1.20 * items.len() as f64) as usize;
|
||||
// TODO do we really need the multiply by two here?
|
||||
let size = if size.is_power_of_two() {
|
||||
size * 2
|
||||
} else {
|
||||
size.next_power_of_two()
|
||||
};
|
||||
|
||||
let mut table: Vec<Option<&T>> = Vec::new();
|
||||
table.resize(size, None);
|
||||
|
||||
for i in items {
|
||||
let mut h = hash_function(i) % size;
|
||||
let mut s = 0;
|
||||
while table[h].is_some() {
|
||||
s += 1;
|
||||
h = (h + s) % size;
|
||||
}
|
||||
table[h] = Some(i);
|
||||
}
|
||||
|
||||
table
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generate_table() {
|
||||
let v = vec!["Hello".to_string(), "world".to_string()];
|
||||
let table = generate_table(&v, |s| simple_hash(&s));
|
||||
assert_eq!(
|
||||
table,
|
||||
vec![
|
||||
None,
|
||||
Some(&"Hello".to_string()),
|
||||
Some(&"world".to_string()),
|
||||
None
|
||||
]
|
||||
);
|
||||
}
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче