Merge mozilla-central to mozilla-inbound. a=merge CLOSED TREE

This commit is contained in:
Bogdan Tara 2019-02-12 00:01:16 +02:00
Родитель 7cb17defee 12bbbc3d51
Коммит dee73f16c3
114 изменённых файлов: 2474 добавлений и 2472 удалений

Просмотреть файл

@ -190,3 +190,6 @@ tps_result\.json
# Ignore file generated by lalrpop at build time.
^third_party/rust/lalrpop/src/parser/lrgrammar.rs
# Ignore the build directories of WebRender standalone builds.
gfx/wr/target/

9
Cargo.lock сгенерированный
Просмотреть файл

@ -1123,6 +1123,7 @@ dependencies = [
"encoding_glue 0.1.0",
"env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"geckoservo 0.0.1",
"gkrust_utils 0.1.0",
"jsrust_shared 0.1.0",
"kvstore 0.1.0",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1140,6 +1141,14 @@ dependencies = [
"xpcom 0.1.0",
]
[[package]]
name = "gkrust_utils"
version = "0.1.0"
dependencies = [
"nsstring 0.1.0",
"uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "gl_generator"
version = "0.10.0"

Просмотреть файл

@ -36,6 +36,7 @@ exclude = [
"media/mp4parse-rust/mp4parse",
"media/mp4parse-rust/mp4parse_capi",
"media/mp4parse-rust/mp4parse_fallible",
"xpcom/rust/gkrust_utils",
]
# Explicitly specify what our profiles use. The opt-level setting here is

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -253,19 +253,13 @@ panelview[mainview] > .panel-header {
z-index: 2;
}
/* The next 3 rules allow dragging tabs slightly outside of the tabstrip
* to make it easier to drag tabs. */
#navigator-toolbox[movingtab] > #titlebar > #TabsToolbar {
padding-bottom: 15px;
}
#navigator-toolbox[movingtab] #tabbrowser-tabs {
/* Make it easier to drag tabs by expanding the drag area downwards. */
#tabbrowser-tabs[movingtab] {
padding-bottom: 15px;
margin-bottom: -15px;
}
#navigator-toolbox[movingtab] > #nav-bar {
margin-top: -15px;
pointer-events: none;
}

Просмотреть файл

@ -833,10 +833,14 @@ var gPrivacyPane = {
* Initialize the starting state for the auto-start private browsing mode pref reverter.
*/
initAutoStartPrivateBrowsingReverter() {
// We determine the mode in initializeHistoryMode, which is guaranteed to have been
// called before now, so this is up-to-date.
let mode = document.getElementById("historyMode");
let autoStart = document.getElementById("privateBrowsingAutoStart");
this._lastMode = mode.selectedIndex;
this._lastCheckState = autoStart.hasAttribute("checked");
// The value of the autostart pref, on the other hand, is gotten from Preferences,
// which updates the DOM asynchronously, so we can't rely on the DOM. Get it directly
// from the prefs.
this._lastCheckState = Preferences.get("browser.privatebrowsing.autostart").value;
},
_lastMode: null,

Просмотреть файл

@ -92,6 +92,7 @@ skip-if = os == 'win' && processor == "x86_64" && bits == 64 # bug 1522821
[browser_telemetry.js]
# Skip this test on Android as FHR and Telemetry are separate systems there.
skip-if = !healthreport || !telemetry || (os == 'linux' && debug) || (os == 'android')
[browser_warning_permanent_private_browsing.js]
[browser_containers_name_input.js]
run-if = nightly_build # Containers is enabled only on Nightly
[browser_fluent.js]

Просмотреть файл

@ -0,0 +1,45 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
function checkForPrompt(prefVal) {
return async function() {
await SpecialPowers.pushPrefEnv({set: [
["privacy.history.custom", true],
["browser.privatebrowsing.autostart", !prefVal],
]});
await openPreferencesViaOpenPreferencesAPI("panePrivacy", { leaveOpen: true });
let doc = gBrowser.contentDocument;
is(doc.getElementById("historyMode").value, "custom", "Expect custom history mode");
// Stub out the prompt method as an easy way to check it was shown. We throw away
// the tab straight after so don't need to bother restoring it.
let promptFired = false;
doc.defaultView.confirmRestartPrompt = () => {
promptFired = true;
return doc.defaultView.CONFIRM_RESTART_PROMPT_RESTART_NOW;
};
// Tick the checkbox and pretend the user did it:
let checkbox = doc.getElementById("privateBrowsingAutoStart");
checkbox.checked = prefVal;
checkbox.doCommand();
// Now the prompt should have shown.
ok(promptFired,
`Expect a prompt when turning permanent private browsing ${prefVal ? "on" : "off"}!`);
BrowserTestUtils.removeTab(gBrowser.selectedTab);
};
}
/**
* Check we show the prompt if the permanent private browsing pref is false
* and we flip the checkbox to true.
*/
add_task(checkForPrompt(true));
/**
* Check it works in the other direction:
*/
add_task(checkForPrompt(false));

Просмотреть файл

@ -69,7 +69,7 @@ class UrlbarView {
* The currently selected result.
*/
get selectedResult() {
if (!this.isOpen) {
if (!this.isOpen || !this._selected) {
return null;
}

Просмотреть файл

@ -279,13 +279,11 @@ inline bool BasePrincipal::FastEquals(nsIPrincipal* aOther) {
// Two principals are considered to be equal if their origins are the same.
// If the two principals are codebase principals, their origin attributes
// (aka the origin suffix) must also match.
// If the two principals are null principals, they're only equal if they're
// the same object.
if (Kind() == eNullPrincipal || Kind() == eSystemPrincipal) {
if (Kind() == eSystemPrincipal) {
return this == other;
}
if (Kind() == eCodebasePrincipal) {
if (Kind() == eCodebasePrincipal || Kind() == eNullPrincipal) {
return mOriginNoSuffix == other->mOriginNoSuffix &&
mOriginSuffix == other->mOriginSuffix;
}
@ -308,13 +306,6 @@ inline bool BasePrincipal::FastEqualsConsideringDomain(nsIPrincipal* aOther) {
inline bool BasePrincipal::FastSubsumes(nsIPrincipal* aOther) {
// If two principals are equal, then they both subsume each other.
// We deal with two special cases first:
// Null principals only subsume each other if they are equal, and are only
// equal if they're the same object.
auto other = Cast(aOther);
if (Kind() == eNullPrincipal && other->Kind() == eNullPrincipal) {
return this == other;
}
if (FastEquals(aOther)) {
return true;
}

Просмотреть файл

@ -171,7 +171,9 @@ bool NullPrincipal::MayLoadInternal(nsIURI* aURI) {
nsCOMPtr<nsIPrincipal> blobPrincipal;
if (dom::BlobURLProtocolHandler::GetBlobURLPrincipal(
aURI, getter_AddRefs(blobPrincipal))) {
return blobPrincipal == this;
MOZ_ASSERT(blobPrincipal);
return SubsumesInternal(blobPrincipal,
BasePrincipal::ConsiderDocumentDomain);
}
return false;

Просмотреть файл

@ -87,7 +87,8 @@ class NullPrincipal final : public BasePrincipal {
bool SubsumesInternal(nsIPrincipal* aOther,
DocumentDomainConsideration aConsideration) override {
return aOther == this;
MOZ_ASSERT(aOther);
return FastEquals(aOther);
}
bool MayLoadInternal(nsIURI* aURI) override;

Просмотреть файл

@ -15,6 +15,8 @@
#include "nsCRT.h"
#include "nsIUUIDGenerator.h"
#include "mozilla/GkRustUtils.h"
using namespace mozilla;
////////////////////////////////////////////////////////////////////////////////
@ -27,18 +29,7 @@ NullPrincipalURI::NullPrincipalURI(const NullPrincipalURI& aOther) {
}
nsresult NullPrincipalURI::Init() {
// FIXME: bug 327161 -- make sure the uuid generator is reseeding-resistant.
nsCOMPtr<nsIUUIDGenerator> uuidgen = services::GetUUIDGenerator();
NS_ENSURE_TRUE(uuidgen, NS_ERROR_NOT_AVAILABLE);
nsID id;
nsresult rv = uuidgen->GenerateUUIDInPlace(&id);
NS_ENSURE_SUCCESS(rv, rv);
mPath.SetLength(NSID_LENGTH - 1); // -1 because NSID_LENGTH counts the '\0'
id.ToProvidedString(
*reinterpret_cast<char(*)[NSID_LENGTH]>(mPath.BeginWriting()));
GkRustUtils::GenerateUUID(mPath);
MOZ_ASSERT(mPath.Length() == NSID_LENGTH - 1);
MOZ_ASSERT(strlen(mPath.get()) == NSID_LENGTH - 1);

Просмотреть файл

@ -395,7 +395,7 @@ function addXULBrowserDecorations(browser) {
if (browser.remoteType == undefined) {
Object.defineProperty(browser, "remoteType", {
get() {
return this.getAttribute("remoteType");
return this.messageManager.remoteType;
},
configurable: true,
enumerable: true,

Просмотреть файл

@ -318,6 +318,10 @@ function tunnelToInnerBrowser(outer, inner) {
// Reset @remote since this is now back to a regular, non-remote browser
outer.setAttribute("remote", "false");
outer.removeAttribute("remoteType");
// Stop forwarding remoteType to the inner browser
delete outer.remoteType;
outer.construct();
// Delete browser window properties exposed on content's owner global
@ -607,6 +611,10 @@ MessageManagerTunnel.prototype = {
return this.innerParentMM.processMessageManager;
},
get remoteType() {
return this.innerParentMM.remoteType;
},
loadFrameScript(url, ...args) {
debug(`Calling loadFrameScript for ${url}`);

Просмотреть файл

@ -158,7 +158,7 @@ class Browser extends PureComponent {
mozbrowser: "true",
noisolation: "true",
remote: "true",
remotetype: "web",
remoteType: "web",
src: "about:blank",
usercontextid: userContextId,
width: "100%",

Просмотреть файл

@ -1,26 +0,0 @@
{
"title": "Console",
"environment": "development",
"baseWorkerURL": "http://localhost:8000/public/build/",
"defaultURL": "https://nchevobbe.github.io/demo/console-test-app.html",
"host": "",
"theme": "light",
"dir": "ltr",
"features": {
},
"logging": {
"client": false,
"firefoxProxy": false,
"actions": false
},
"firefox": {
"webSocketConnection": false,
"host": "localhost",
"webSocketPort": 8116,
"tcpPort": 6080
},
"development": {
"serverPort": 8000,
"examplesPort": 7999
}
}

Просмотреть файл

@ -14,7 +14,7 @@ add_task(async function() {
const jstermHistory = [
`document`,
`document
.querySelectorAll("*")
.querySelectorAll("span")
.forEach(console.log)`,
`Dog = "Snoopy"`,
];

Просмотреть файл

@ -571,7 +571,7 @@ class ReactEventCollector extends MainEventCollector {
if (props) {
for (const [name, prop] of Object.entries(props)) {
if (REACT_EVENT_NAMES.includes(name)) {
const listener = prop.__reactBoundMethod || prop;
const listener = prop && prop.__reactBoundMethod || prop;
if (typeof listener !== "function") {
continue;
@ -614,7 +614,7 @@ class ReactEventCollector extends MainEventCollector {
if (value.memoizedProps) {
return value.memoizedProps; // React 16
}
return value._currentElement.props; // React 15
return value && value._currentElement && value._currentElement.props; // React 15
}
}
return null;

Просмотреть файл

@ -228,24 +228,6 @@ WebConsoleClient.prototype = {
return this._client.request(packet);
},
/**
* Inspect the properties of an object.
*
* @param string actor
* The WebConsoleObjectActor ID to send the request to.
* @param function onResponse
* The function invoked when the response is received.
* @return request
* Request object that implements both Promise and EventEmitter interfaces
*/
inspectObjectProperties: function(actor, onResponse) {
const packet = {
to: actor,
type: "inspectProperties",
};
return this._client.request(packet, onResponse);
},
/**
* Evaluate a JavaScript expression.
*

Просмотреть файл

@ -1079,22 +1079,6 @@ nsresult nsFrameLoader::SwapWithOtherRemoteLoader(
return rv;
}
// Swap the remoteType property as the frameloaders are being swapped
nsAutoString ourRemoteType;
if (!ourContent->GetAttr(kNameSpaceID_None, nsGkAtoms::RemoteType,
ourRemoteType)) {
ourRemoteType.AssignLiteral(DEFAULT_REMOTE_TYPE);
}
nsAutoString otherRemoteType;
if (!otherContent->GetAttr(kNameSpaceID_None, nsGkAtoms::RemoteType,
otherRemoteType)) {
otherRemoteType.AssignLiteral(DEFAULT_REMOTE_TYPE);
}
ourContent->SetAttr(kNameSpaceID_None, nsGkAtoms::RemoteType, otherRemoteType,
false);
otherContent->SetAttr(kNameSpaceID_None, nsGkAtoms::RemoteType, ourRemoteType,
false);
Unused << mRemoteBrowser->SendSwappedWithOtherRemoteLoader(
ourContext.AsIPCTabContext());
Unused << aOther->mRemoteBrowser->SendSwappedWithOtherRemoteLoader(

Просмотреть файл

@ -1171,8 +1171,14 @@ inline bool WrapNewBindingNonWrapperCachedObject(
if (!JS_WrapObject(cx, &proto)) {
return false;
}
} else {
// cx and scope are same-compartment, but they might still be
// different-Realm. Enter the Realm of scope, since that's
// where we want to create our object.
ar.emplace(cx, scope);
}
MOZ_ASSERT_IF(proto, js::IsObjectInContextCompartment(proto, cx));
MOZ_ASSERT(js::IsObjectInContextCompartment(scope, cx));
if (!value->WrapObject(cx, proto, &obj)) {
return false;
@ -1223,8 +1229,14 @@ inline bool WrapNewBindingNonWrapperCachedObject(
if (!JS_WrapObject(cx, &proto)) {
return false;
}
} else {
// cx and scope are same-compartment, but they might still be
// different-Realm. Enter the Realm of scope, since that's
// where we want to create our object.
ar.emplace(cx, scope);
}
MOZ_ASSERT_IF(proto, js::IsObjectInContextCompartment(proto, cx));
MOZ_ASSERT(js::IsObjectInContextCompartment(scope, cx));
if (!value->WrapObject(cx, proto, &obj)) {
return false;

Просмотреть файл

@ -60,6 +60,10 @@ void ImageBitmapRenderingContext::TransferFromImageBitmap(
return;
}
if (aImageBitmap.IsWriteOnly() && mCanvasElement) {
mCanvasElement->SetWriteOnly();
}
Redraw(gfxRect(0, 0, mWidth, mHeight));
}

Просмотреть файл

@ -30,7 +30,7 @@ struct VideoFrameProperties
{
// Size of image data within the ShMem,
// the ShMem is at least this large
size_t bufferSize;
uint32_t bufferSize;
// From webrtc::VideoFrame
uint32_t timeStamp;
int64_t ntpTimeMs;

Просмотреть файл

@ -10,12 +10,14 @@
namespace mozilla {
size_t VideoFrameUtils::TotalRequiredBufferSize(
uint32_t VideoFrameUtils::TotalRequiredBufferSize(
const webrtc::VideoFrame& aVideoFrame) {
auto i420 = aVideoFrame.video_frame_buffer()->ToI420();
auto height = i420->height();
return height * i420->StrideY() + ((height + 1) / 2) * i420->StrideU() +
size_t size = height * i420->StrideY() + ((height + 1) / 2) * i420->StrideU() +
((height + 1) / 2) * i420->StrideV();
MOZ_RELEASE_ASSERT(size < std::numeric_limits<uint32_t>::max());
return static_cast<uint32_t>(size);
}
void VideoFrameUtils::InitFrameBufferProperties(

Просмотреть файл

@ -24,7 +24,7 @@ class VideoFrameUtils {
public:
// Returns the total number of bytes necessary to copy a VideoFrame's buffer
// across all planes.
static size_t TotalRequiredBufferSize(const webrtc::VideoFrame& frame);
static uint32_t TotalRequiredBufferSize(const webrtc::VideoFrame& frame);
// Initializes a camera::VideoFrameProperties from a VideoFrameBuffer
static void InitFrameBufferProperties(

Просмотреть файл

@ -443,7 +443,7 @@ nsresult MediaEngineWebRTCMicrophoneSource::Deallocate(
const RefPtr<const AllocationHandle>&) {
AssertIsOnOwningThread();
MOZ_ASSERT(mState == kStopped);
MOZ_ASSERT(mState == kStopped || mState == kAllocated);
class EndTrackMessage : public ControlMessage {
public:

Просмотреть файл

@ -98,7 +98,7 @@ union GfxVarValue
struct GfxVarUpdate
{
size_t index;
uint32_t index;
GfxVarValue value;
};

Просмотреть файл

@ -350,7 +350,7 @@ struct OpWindowOverlayChanged { };
struct ShmemSection {
Shmem shmem;
uint32_t offset;
size_t size;
uint32_t size;
};
struct CrossProcessSemaphoreDescriptor {

Просмотреть файл

@ -71,7 +71,7 @@ VertexInfo write_text_vertex(RectWithSize local_clip_rect,
vec2 snap_bias) {
// The offset to snap the glyph rect to a device pixel
vec2 snap_offset = vec2(0.0);
mat2 local_transform;
mat2 local_transform = mat2(1.0);
#ifdef WR_FEATURE_GLYPH_TRANSFORM
bool remove_subpx_offset = true;

Просмотреть файл

@ -214,4 +214,4 @@ To learn more about Fluent, follow the `Fluent for Firefox Developers`_ guide.
.. _Pontoon: https://pontoon.mozilla.org/
.. _hg.mozilla.org/l10n-central: https://hg.mozilla.org/l10n-central/
.. _L10n Drivers Team: https://wiki.mozilla.org/L10n:Mozilla_Team
.. _Fluent For Firefox Developers: ./l10n/docs/l10n/index.html
.. _Fluent For Firefox Developers: ./l10n/l10n/fluent_tutorial.html

Просмотреть файл

@ -166,13 +166,23 @@ class L10nRegistryService {
}
}
/**
* Check whether a source with the given known is already registered.
*
* @param {String} sourceName
* @returns {boolean} whether or not a source by that name is known.
*/
hasSource(sourceName) {
return this.sources.has(sourceName);
}
/**
* Adds a new resource source to the L10nRegistry.
*
* @param {FileSource} source
*/
registerSource(source) {
if (this.sources.has(source.name)) {
if (this.hasSource(source.name)) {
throw new Error(`Source with name "${source.name}" already registered.`);
}
this.sources.set(source.name, source);
@ -192,7 +202,7 @@ class L10nRegistryService {
* @param {FileSource} source
*/
updateSource(source) {
if (!this.sources.has(source.name)) {
if (!this.hasSource(source.name)) {
throw new Error(`Source with name "${source.name}" is not registered.`);
}
this.sources.set(source.name, source);
@ -233,7 +243,7 @@ class L10nRegistryService {
_setSourcesFromSharedData() {
let sources = Services.cpmm.sharedData.get("L10nRegistry:Sources");
for (let [name, data] of sources.entries()) {
if (!this.sources.has(name)) {
if (!this.hasSource(name)) {
const source = new FileSource(name, data.locales, data.prePath);
this.registerSource(source);
}

Просмотреть файл

@ -446,12 +446,12 @@ and the developer is not affected.
__ https://unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html
__ https://unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html#bs
Partial Arguments
-----------------
Partially-formatted variables
-----------------------------
When it comes to formatting data, Fluent allows the developer to provide
a set of parameters for the formatter, and the localizer can fine tune some of them.
This technique is called `partial arguments`__.
This technique is called `partially-formatted variables`__.
For example, when formatting a date, the developer can just pass a JS :js:`Date` object,
but its default formatting will be pretty expressive. In most cases, the developer
@ -492,7 +492,7 @@ At the moment Fluent supports two formatters that match JS Intl API counterparts
With time more formatters will be added.
__ https://projectfluent.org/fluent/guide/functions.html#partial-arguments
__ https://projectfluent.org/fluent/guide/functions.html#partially-formatted-variables
__ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat
__ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat

Просмотреть файл

@ -450,3 +450,12 @@ add_task(async function test_parallel_io() {
L10nRegistry.sources.clear();
L10nRegistry.load = originalLoad;
});
add_task(async function test_hasSource() {
equal(L10nRegistry.hasSource("gobbledygook"), false, "Non-existing source doesn't exist");
equal(L10nRegistry.hasSource("app"), false, "hasSource returns true before registering a source");
let oneSource = new FileSource("app", ["en-US"], "/{locale}/");
L10nRegistry.registerSource(oneSource);
equal(L10nRegistry.hasSource("app"), true, "hasSource returns true after registering a source");
L10nRegistry.sources.clear();
});

Просмотреть файл

@ -270,26 +270,6 @@ bool Pickle::ReadLength(PickleIterator* iter, int* result) const {
return ((*result) >= 0);
}
// Always written as a 64-bit value since the size for this type can
// differ between architectures.
bool Pickle::ReadSize(PickleIterator* iter, size_t* result) const {
DCHECK(iter);
uint64_t big_result = 0;
if (IteratorHasRoomFor(*iter, sizeof(big_result))) {
iter->CopyInto(&big_result);
UpdateIter(iter, sizeof(big_result));
} else {
if (!ReadBytesInto(iter, &big_result, sizeof(big_result))) {
return false;
}
}
DCHECK(big_result <= std::numeric_limits<size_t>::max());
*result = static_cast<size_t>(big_result);
return true;
}
bool Pickle::ReadInt32(PickleIterator* iter, int32_t* result) const {
DCHECK(iter);
@ -581,15 +561,6 @@ bool Pickle::WriteULong(unsigned long value) {
return WriteUInt64(uint64_t(value));
}
bool Pickle::WriteSize(size_t value) {
// Always written as a 64-bit value since the size for this type can
// differ between architectures.
#ifdef FUZZING
mozilla::ipc::Faulty::instance().FuzzSize(&value);
#endif
return WriteUInt64(uint64_t(value));
}
bool Pickle::WriteInt32(int32_t value) {
#ifdef FUZZING
mozilla::ipc::Faulty::instance().FuzzInt(&value);

Просмотреть файл

@ -100,7 +100,6 @@ class Pickle {
MOZ_MUST_USE bool ReadLong(PickleIterator* iter, long* result) const;
MOZ_MUST_USE bool ReadULong(PickleIterator* iter,
unsigned long* result) const;
MOZ_MUST_USE bool ReadSize(PickleIterator* iter, size_t* result) const;
MOZ_MUST_USE bool ReadInt32(PickleIterator* iter, int32_t* result) const;
MOZ_MUST_USE bool ReadUInt32(PickleIterator* iter, uint32_t* result) const;
MOZ_MUST_USE bool ReadInt64(PickleIterator* iter, int64_t* result) const;
@ -162,7 +161,6 @@ class Pickle {
bool WriteInt(int value);
bool WriteLong(long value);
bool WriteULong(unsigned long value);
bool WriteSize(size_t value);
bool WriteInt32(int32_t value);
bool WriteUInt32(uint32_t value);
bool WriteInt64(int64_t value);

Просмотреть файл

@ -311,27 +311,10 @@ struct ParamTraitsFixed<uint64_t> {
}
};
// Other standard C types.
template <class P>
struct ParamTraitsLibC : ParamTraitsFixed<P> {};
template <>
struct ParamTraitsLibC<size_t> {
typedef size_t param_type;
static void Write(Message* m, const param_type& p) { m->WriteSize(p); }
static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
return m->ReadSize(iter, r);
}
static void Log(const param_type& p, std::wstring* l) {
l->append(StringPrintf(L"%u", p));
}
};
// std::* types.
template <class P>
struct ParamTraitsStd : ParamTraitsLibC<P> {};
struct ParamTraitsStd : ParamTraitsFixed<P> {};
template <>
struct ParamTraitsStd<std::string> {

Просмотреть файл

@ -28,9 +28,7 @@ Types = (
'intptr_t',
'uintptr_t',
# stddef types
'size_t',
'ssize_t',
# You may be tempted to add size_t. Do not! See bug 1525199.
# Mozilla types: "less" standard things we know how serialize/deserialize
'nsresult',

Просмотреть файл

@ -132,7 +132,7 @@ NativeRegExpMacroAssembler::GenerateCode(JSContext* cx, bool match_only)
masm.Str(PseudoStackPointer64, vixl::MemOperand(sp, -16, vixl::PreIndex));
// Initialize the PSP from the SP.
masm.initStackPtr();
masm.initPseudoStackPtr();
#endif
// Push non-volatile registers which might be modified by jitcode.

Просмотреть файл

@ -1500,6 +1500,12 @@ static Value FromSymbolPayload(uintptr_t payload) {
return SymbolValue(reinterpret_cast<JS::Symbol*>(payload));
}
#ifdef ENABLE_BIGINT
static Value FromBigIntPayload(uintptr_t payload) {
return BigIntValue(reinterpret_cast<JS::BigInt*>(payload));
}
#endif
static Value FromTypedPayload(JSValueType type, uintptr_t payload) {
switch (type) {
case JSVAL_TYPE_INT32:
@ -1510,6 +1516,10 @@ static Value FromTypedPayload(JSValueType type, uintptr_t payload) {
return FromStringPayload(payload);
case JSVAL_TYPE_SYMBOL:
return FromSymbolPayload(payload);
#ifdef ENABLE_BIGINT
case JSVAL_TYPE_BIGINT:
return FromBigIntPayload(payload);
#endif
case JSVAL_TYPE_OBJECT:
return FromObjectPayload(payload);
default:
@ -1606,6 +1616,10 @@ Value SnapshotIterator::allocationValue(const RValueAllocation& alloc,
return FromStringPayload(fromStack(alloc.stackOffset2()));
case JSVAL_TYPE_SYMBOL:
return FromSymbolPayload(fromStack(alloc.stackOffset2()));
#ifdef ENABLE_BIGINT
case JSVAL_TYPE_BIGINT:
return FromBigIntPayload(fromStack(alloc.stackOffset2()));
#endif
case JSVAL_TYPE_OBJECT:
return FromObjectPayload(fromStack(alloc.stackOffset2()));
default:
@ -1727,6 +1741,9 @@ void SnapshotIterator::writeAllocationValuePayload(
break;
case JSVAL_TYPE_STRING:
case JSVAL_TYPE_SYMBOL:
#ifdef ENABLE_BIGINT
case JSVAL_TYPE_BIGINT:
#endif
case JSVAL_TYPE_OBJECT:
WriteFrameSlot(fp_, alloc.stackOffset2(), uintptr_t(v.toGCThing()));
break;

Просмотреть файл

@ -256,7 +256,7 @@ class MacroAssemblerCompat : public vixl::MacroAssembler {
Mov(vixl::sp, GetStackPointer64());
}
}
void initStackPtr() {
void initPseudoStackPtr() {
if (!GetStackPointer64().Is(vixl::sp)) {
Mov(GetStackPointer64(), vixl::sp);
}

Просмотреть файл

@ -649,9 +649,7 @@ bool JitRuntime::generateVMWrapper(JSContext* cx, MacroAssembler& masm,
}
// SP is used to transfer stack across call boundaries.
if (!masm.GetStackPointer64().Is(vixl::sp)) {
masm.Mov(masm.GetStackPointer64(), vixl::sp);
}
masm.initPseudoStackPtr();
// Test for failure.
switch (f.failType()) {

Просмотреть файл

@ -68,6 +68,7 @@ BEGIN_TEST(testJitRValueAlloc_TypedReg) {
/* _(JSVAL_TYPE_MAGIC) */ \
_(JSVAL_TYPE_STRING) \
_(JSVAL_TYPE_SYMBOL) \
IF_BIGINT(_(JSVAL_TYPE_BIGINT),) \
/* _(JSVAL_TYPE_NULL) */ \
_(JSVAL_TYPE_OBJECT)
@ -95,6 +96,7 @@ BEGIN_TEST(testJitRValueAlloc_TypedStack) {
/* _(JSVAL_TYPE_MAGIC) */ \
_(JSVAL_TYPE_STRING) \
_(JSVAL_TYPE_SYMBOL) \
IF_BIGINT(_(JSVAL_TYPE_BIGINT),) \
/* _(JSVAL_TYPE_NULL) */ \
_(JSVAL_TYPE_OBJECT)

Просмотреть файл

@ -620,7 +620,7 @@ bool LCovRuntime::fillWithFilename(char* name, size_t length) {
int len = snprintf(name, length, "%s/%" PRId64 "-%" PRIu32 "-%zu.info",
outDir, timestamp, pid_, rid);
if (len < 0 || size_t(len) >= length) {
fprintf(stderr, "Warning: LCovRuntime::init: Cannot serialize file name.");
fprintf(stderr, "Warning: LCovRuntime::init: Cannot serialize file name.\n");
return false;
}
@ -635,7 +635,7 @@ void LCovRuntime::init() {
// If we cannot open the file, report a warning.
if (!out_.init(name)) {
fprintf(stderr, "Warning: LCovRuntime::init: Cannot open file named '%s'.",
fprintf(stderr, "Warning: LCovRuntime::init: Cannot open file named '%s'.\n",
name);
}
isEmpty_ = true;

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -131,11 +131,14 @@ enum JSTryNoteKind {
* Exception handling record.
*/
struct JSTryNote {
uint8_t kind; /* one of JSTryNoteKind */
uint32_t kind; /* one of JSTryNoteKind */
uint32_t stackDepth; /* stack depth upon exception handler entry */
uint32_t start; /* start of the try statement or loop relative
to script->code() */
uint32_t length; /* length of the try statement or loop */
template <js::XDRMode mode>
js::XDRResult XDR(js::XDRState<mode>* xdr);
};
namespace js {
@ -167,6 +170,9 @@ struct ScopeNote {
// relative to script->code().
uint32_t length; // Bytecode length of scope.
uint32_t parent; // Index of parent block scope in notes, or NoScopeNote.
template <js::XDRMode mode>
js::XDRResult XDR(js::XDRState<mode>* xdr);
};
class ScriptCounts {
@ -452,6 +458,8 @@ struct SourceTypeTraits<char16_t> {
}
};
class ScriptSourceHolder;
class ScriptSource {
friend class SourceCompressionTask;
@ -1003,11 +1011,6 @@ class ScriptSource {
void setCompressedSourceFromTask(SharedImmutableString compressed);
public:
// XDR handling
template <XDRMode mode>
MOZ_MUST_USE XDRResult performXDR(XDRState<mode>* xdr);
private:
// It'd be better to make this function take <XDRMode, Unit>, as both
// specializations of this function contain nested Unit-parametrized
@ -1095,6 +1098,11 @@ class ScriptSource {
parseEnded_ = ReallyNow();
}
template <XDRMode mode>
static MOZ_MUST_USE XDRResult
XDR(XDRState<mode>* xdr, const mozilla::Maybe<JS::CompileOptions>& options,
MutableHandle<ScriptSourceHolder> ss);
void trace(JSTracer* trc);
};
@ -1120,6 +1128,8 @@ class ScriptSourceHolder {
ss = newss;
}
ScriptSource* get() const { return ss; }
void trace(JSTracer* trc) { ss->trace(trc); }
};
// [SMDOC] ScriptSourceObject
@ -1409,6 +1419,13 @@ class alignas(JS::Value) PrivateScriptData final {
uint32_t ntrynotes, uint32_t nscopenotes,
uint32_t nresumeoffsets, uint32_t* dataSize);
template <XDRMode mode>
static MOZ_MUST_USE XDRResult XDR(js::XDRState<mode>* xdr,
js::HandleScript script,
js::HandleScriptSourceObject sourceObject,
js::HandleScope scriptEnclosingScope,
js::HandleFunction fun);
void traceChildren(JSTracer* trc);
};
@ -1478,6 +1495,10 @@ class SharedScriptData {
return offsetof(SharedScriptData, natoms_);
}
template <XDRMode mode>
static MOZ_MUST_USE XDRResult XDR(js::XDRState<mode>* xdr,
js::HandleScript script);
private:
SharedScriptData() = delete;
SharedScriptData(const SharedScriptData&) = delete;
@ -1805,6 +1826,16 @@ class JSScript : public js::gc::TenuredCell {
js::HandleFunction fun,
js::MutableHandleScript scriptp);
template <js::XDRMode mode>
friend js::XDRResult js::SharedScriptData::XDR(js::XDRState<mode>* xdr,
js::HandleScript script);
template <js::XDRMode mode>
friend js::XDRResult js::PrivateScriptData::XDR(
js::XDRState<mode>* xdr, js::HandleScript script,
js::HandleScriptSourceObject sourceObject,
js::HandleScope scriptEnclosingScope, js::HandleFunction fun);
friend bool js::detail::CopyScript(
JSContext* cx, js::HandleScript src, js::HandleScript dst,
js::MutableHandle<JS::GCVector<js::Scope*>> scopes);

Просмотреть файл

@ -1020,6 +1020,32 @@ template
return static_cast<WithScope*>(scope);
}
template <XDRMode mode>
/* static */ XDRResult WithScope::XDR(XDRState<mode>* xdr,
HandleScope enclosing,
MutableHandleScope scope) {
JSContext* cx = xdr->cx();
if (mode == XDR_DECODE) {
scope.set(create(cx, enclosing));
if (!scope) {
return xdr->fail(JS::TranscodeResult_Throw);
}
}
return Ok();
}
template
/* static */ XDRResult
WithScope::XDR(XDRState<XDR_ENCODE>* xdr, HandleScope enclosing,
MutableHandleScope scope);
template
/* static */ XDRResult
WithScope::XDR(XDRState<XDR_DECODE>* xdr, HandleScope enclosing,
MutableHandleScope scope);
static const uint32_t EvalScopeEnvShapeFlags =
BaseShape::QUALIFIED_VAROBJ | BaseShape::DELEGATE;

Просмотреть файл

@ -773,6 +773,10 @@ class WithScope : public Scope {
public:
static WithScope* create(JSContext* cx, HandleScope enclosing);
template <XDRMode mode>
static XDRResult XDR(XDRState<mode>* xdr, HandleScope enclosing,
MutableHandleScope scope);
};
//

Просмотреть файл

@ -110,7 +110,7 @@ static const uintptr_t CLEAR_CONSTRUCTOR_CODE_TOKEN = 0x1;
masm.Str(PseudoStackPointer64, vixl::MemOperand(sp, -16, vixl::PreIndex));
// Initialize the PSP from the SP.
masm.initStackPtr();
masm.initPseudoStackPtr();
#endif
MOZ_ASSERT(propertiesReg.volatile_());

Просмотреть файл

@ -464,9 +464,10 @@ class XDRState : public XDRCoderBase {
return fail(JS::TranscodeResult_Throw);
}
memcpy(ptr, *sp, len);
MOZ_ASSERT(ptr[len-1] == '\0');
} else {
const uint8_t* ptr = buf.read(len);
if (!ptr || ptr[len] != '\0') {
if (!ptr || ptr[len-1] != '\0') {
return fail(JS::TranscodeResult_Failure_BadDecode);
}
*sp = reinterpret_cast<const char*>(ptr);

Просмотреть файл

@ -1099,6 +1099,12 @@ void wasm::GenerateDirectCallFromJit(MacroAssembler& masm, const FuncExport& fe,
masm.callJit(ImmPtr(callee));
masm.assertStackAlignment(WasmStackAlignment);
#ifdef JS_CODEGEN_ARM64
// WASM does not use the emulated stack pointer, so reinitialize it as it
// might be clobbered either by WASM or by any C++ calls within.
masm.initPseudoStackPtr();
#endif
masm.branchPtr(Assembler::Equal, FramePointer, Imm32(wasm::FailFP),
masm.exceptionLabel());

Просмотреть файл

@ -10,6 +10,8 @@ import subprocess
CARGO_LOCK = mozpath.join(buildconfig.topsrcdir, "Cargo.lock")
# cbindgen_crate_path needs to match the crate name
# EG: /xpcom/rust/gkrust_utils is the path for the "gkrust_utils" crate
def generate(output, cbindgen_crate_path, *in_tree_dependencies):
env = os.environ.copy()
env['CARGO'] = str(buildconfig.substs['CARGO'])

Просмотреть файл

@ -329,8 +329,9 @@ void nsFontFaceLoader::Cancel() {
mLoadTimer->Cancel();
mLoadTimer = nullptr;
}
nsCOMPtr<nsIChannel> channel = mChannel.forget();
channel->Cancel(NS_BINDING_ABORTED);
if (nsCOMPtr<nsIChannel> channel = mChannel.forget()) {
channel->Cancel(NS_BINDING_ABORTED);
}
}
StyleFontDisplay nsFontFaceLoader::GetFontDisplay() {

Просмотреть файл

@ -2993,9 +2993,10 @@ RefPtr<RTCStatsQueryPromise> PeerConnectionImpl::ExecuteStatsQuery_s(
transportId = query->transportId;
}
auto report = std::move(query->report);
auto now = query->now;
return aTransportHandler
->GetIceStats(transportId, query->now, std::move(report))
->GetIceStats(transportId, now, std::move(report))
->Then(
GetMainThreadSerialEventTarget(), __func__,
[query = std::move(query)](

Просмотреть файл

@ -1458,7 +1458,7 @@ pref("javascript.options.strict", false);
#ifdef DEBUG
pref("javascript.options.strict.debug", false);
#endif
pref("javascript.options.unboxed_objects", true);
pref("javascript.options.unboxed_objects", false);
pref("javascript.options.baselinejit", true);
//Duplicated in JitOptions - ensure both match.
pref("javascript.options.baselinejit.threshold", 10);

Просмотреть файл

@ -728,25 +728,22 @@ inline nsresult NS_GetInnermostURIHost(nsIURI *aURI, nsACString &aHost) {
// This block is optimized in order to avoid the overhead of calling
// NS_GetInnermostURI() which incurs a lot of overhead in terms of
// AddRef/Release calls.
nsINestedURI *nestedURI = nullptr;
nsresult rv = CallQueryInterface(aURI, &nestedURI);
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(aURI);
if (nestedURI) {
// We have a nested URI!
nsCOMPtr<nsIURI> uri;
rv = nestedURI->GetInnermostURI(getter_AddRefs(uri));
nsresult rv = nestedURI->GetInnermostURI(getter_AddRefs(uri));
if (NS_FAILED(rv)) {
return rv;
}
NS_RELEASE(nestedURI);
rv = uri->GetAsciiHost(aHost);
if (NS_FAILED(rv)) {
return rv;
}
} else {
// We have a non-nested URI!
rv = aURI->GetAsciiHost(aHost);
nsresult rv = aURI->GetAsciiHost(aHost);
if (NS_FAILED(rv)) {
return rv;
}

Просмотреть файл

@ -1171,4 +1171,4 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
static const int32_t kUnknownId = -1;
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1558009037934000);
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1558354645894000);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -14,7 +14,7 @@ use crate::media_queries::Device;
use crate::values::computed::basic_shape::ShapeRadius as ComputedShapeRadius;
use crate::values::computed::FlexBasis as ComputedFlexBasis;
use crate::values::computed::{Angle, ExtremumLength, Length, LengthPercentage};
use crate::values::computed::{MaxLength as ComputedMaxLength, MozLength as ComputedMozLength};
use crate::values::computed::{MaxSize as ComputedMaxSize, Size as ComputedSize};
use crate::values::computed::{NonNegativeLengthPercentage, Percentage};
use crate::values::computed::{Number, NumberOrPercentage};
use crate::values::generics::basic_shape::ShapeRadius;
@ -22,7 +22,7 @@ use crate::values::generics::box_::Perspective;
use crate::values::generics::flex::FlexBasis;
use crate::values::generics::gecko::ScrollSnapPoint;
use crate::values::generics::grid::{TrackBreadth, TrackKeyword};
use crate::values::generics::length::{LengthPercentageOrAuto, MaxLength, MozLength};
use crate::values::generics::length::{LengthPercentageOrAuto, MaxSize, Size};
use crate::values::generics::{CounterStyleOrNone, NonNegative};
use crate::values::{Auto, Either, None_, Normal};
use crate::Atom;
@ -91,7 +91,7 @@ impl GeckoStyleCoordConvertible for ComputedFlexBasis {
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
if let Some(width) = ComputedMozLength::from_gecko_style_coord(coord) {
if let Some(width) = ComputedSize::from_gecko_style_coord(coord) {
return Some(FlexBasis::Width(width));
}
@ -350,43 +350,43 @@ impl GeckoStyleCoordConvertible for ExtremumLength {
}
}
impl GeckoStyleCoordConvertible for ComputedMozLength {
impl GeckoStyleCoordConvertible for ComputedSize {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
match *self {
MozLength::LengthPercentage(ref lpoa) => lpoa.to_gecko_style_coord(coord),
MozLength::Auto => coord.set_value(CoordDataValue::Auto),
MozLength::ExtremumLength(ref e) => e.to_gecko_style_coord(coord),
Size::LengthPercentage(ref lpoa) => lpoa.to_gecko_style_coord(coord),
Size::Auto => coord.set_value(CoordDataValue::Auto),
Size::ExtremumLength(ref e) => e.to_gecko_style_coord(coord),
}
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
if let CoordDataValue::Auto = coord.as_value() {
return Some(MozLength::Auto);
return Some(Size::Auto);
}
if let Some(lp) = NonNegativeLengthPercentage::from_gecko_style_coord(coord) {
return Some(MozLength::LengthPercentage(lp));
return Some(Size::LengthPercentage(lp));
}
ExtremumLength::from_gecko_style_coord(coord).map(MozLength::ExtremumLength)
ExtremumLength::from_gecko_style_coord(coord).map(Size::ExtremumLength)
}
}
impl GeckoStyleCoordConvertible for ComputedMaxLength {
impl GeckoStyleCoordConvertible for ComputedMaxSize {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
match *self {
MaxLength::LengthPercentage(ref lpon) => lpon.to_gecko_style_coord(coord),
MaxLength::None => coord.set_value(CoordDataValue::None),
MaxLength::ExtremumLength(ref e) => e.to_gecko_style_coord(coord),
MaxSize::LengthPercentage(ref lpon) => lpon.to_gecko_style_coord(coord),
MaxSize::None => coord.set_value(CoordDataValue::None),
MaxSize::ExtremumLength(ref e) => e.to_gecko_style_coord(coord),
}
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
if let CoordDataValue::None = coord.as_value() {
return Some(MaxLength::None);
return Some(MaxSize::None);
}
if let Some(lp) = NonNegativeLengthPercentage::from_gecko_style_coord(coord) {
return Some(MaxLength::LengthPercentage(lp));
return Some(MaxSize::LengthPercentage(lp));
}
ExtremumLength::from_gecko_style_coord(coord).map(MaxLength::ExtremumLength)
ExtremumLength::from_gecko_style_coord(coord).map(MaxSize::ExtremumLength)
}
}

Просмотреть файл

@ -1390,8 +1390,8 @@ impl Clone for ${style_struct.gecko_struct_name} {
"LengthOrNormal": impl_style_coord,
"LengthPercentage": impl_simple,
"LengthPercentageOrAuto": impl_style_coord,
"MaxLength": impl_style_coord,
"MozLength": impl_style_coord,
"MaxSize": impl_style_coord,
"Size": impl_style_coord,
"MozScriptMinSize": impl_absolute_length,
"MozScriptSizeMultiplier": impl_simple,
"NonNegativeLengthPercentage": impl_simple,

Просмотреть файл

@ -244,65 +244,40 @@ ${helpers.predefined_type(
if logical:
spec = "https://drafts.csswg.org/css-logical-props/#propdef-%s"
%>
% if product == "gecko":
// width, height, block-size, inline-size
${helpers.predefined_type(
size,
"MozLength",
"computed::MozLength::auto()",
logical=logical,
logical_group="size",
allow_quirks=not logical,
spec=spec % size,
animation_value_type="MozLength",
flags="GETCS_NEEDS_LAYOUT_FLUSH",
servo_restyle_damage="reflow",
)}
// min-width, min-height, min-block-size, min-inline-size,
${helpers.predefined_type(
"min-%s" % size,
"MozLength",
"computed::MozLength::auto()",
logical=logical,
logical_group="min-size",
allow_quirks=not logical,
spec=spec % size,
animation_value_type="MozLength",
servo_restyle_damage="reflow",
)}
% else:
// servo versions (no keyword support)
${helpers.predefined_type(
size,
"NonNegativeLengthPercentageOrAuto",
"computed::NonNegativeLengthPercentageOrAuto::auto()",
spec=spec % size,
logical_group="size",
allow_quirks=not logical,
animation_value_type="ComputedValue", logical = logical,
servo_restyle_damage="reflow",
)}
${helpers.predefined_type(
"min-%s" % size,
"NonNegativeLengthPercentage",
"computed::NonNegativeLengthPercentage::zero()",
spec=spec % ("min-%s" % size),
logical_group="min-size",
animation_value_type="ComputedValue",
logical=logical,
allow_quirks=not logical,
servo_restyle_damage="reflow",
)}
% endif
// width, height, block-size, inline-size
${helpers.predefined_type(
size,
"Size",
"computed::Size::auto()",
logical=logical,
logical_group="size",
allow_quirks=not logical,
spec=spec % size,
animation_value_type="Size",
flags="GETCS_NEEDS_LAYOUT_FLUSH",
servo_restyle_damage="reflow",
)}
// min-width, min-height, min-block-size, min-inline-size
${helpers.predefined_type(
"min-%s" % size,
"Size",
"computed::Size::auto()",
logical=logical,
logical_group="min-size",
allow_quirks=not logical,
spec=spec % size,
animation_value_type="Size",
servo_restyle_damage="reflow",
)}
${helpers.predefined_type(
"max-%s" % size,
"MaxLength",
"computed::MaxLength::none()",
"MaxSize",
"computed::MaxSize::none()",
logical=logical,
logical_group="max-size",
allow_quirks=not logical,
spec=spec % size,
animation_value_type="MaxLength",
animation_value_type="MaxSize",
servo_restyle_damage="reflow",
)}
% endfor

Просмотреть файл

@ -3016,7 +3016,7 @@ impl ComputedValuesInner {
/// Get the logical computed inline size.
#[inline]
pub fn content_inline_size(&self) -> computed::NonNegativeLengthPercentageOrAuto {
pub fn content_inline_size(&self) -> computed::Size {
let position_style = self.get_position();
if self.writing_mode.is_vertical() {
position_style.height
@ -3027,35 +3027,35 @@ impl ComputedValuesInner {
/// Get the logical computed block size.
#[inline]
pub fn content_block_size(&self) -> computed::NonNegativeLengthPercentageOrAuto {
pub fn content_block_size(&self) -> computed::Size {
let position_style = self.get_position();
if self.writing_mode.is_vertical() { position_style.width } else { position_style.height }
}
/// Get the logical computed min inline size.
#[inline]
pub fn min_inline_size(&self) -> computed::NonNegativeLengthPercentage {
pub fn min_inline_size(&self) -> computed::Size {
let position_style = self.get_position();
if self.writing_mode.is_vertical() { position_style.min_height } else { position_style.min_width }
}
/// Get the logical computed min block size.
#[inline]
pub fn min_block_size(&self) -> computed::NonNegativeLengthPercentage {
pub fn min_block_size(&self) -> computed::Size {
let position_style = self.get_position();
if self.writing_mode.is_vertical() { position_style.min_width } else { position_style.min_height }
}
/// Get the logical computed max inline size.
#[inline]
pub fn max_inline_size(&self) -> computed::MaxLength {
pub fn max_inline_size(&self) -> computed::MaxSize {
let position_style = self.get_position();
if self.writing_mode.is_vertical() { position_style.max_height } else { position_style.max_width }
}
/// Get the logical computed max block size.
#[inline]
pub fn max_block_size(&self) -> computed::MaxLength {
pub fn max_block_size(&self) -> computed::MaxSize {
let position_style = self.get_position();
if self.writing_mode.is_vertical() { position_style.max_width } else { position_style.max_height }
}

Просмотреть файл

@ -4,23 +4,16 @@
//! Computed types for CSS values related to flexbox.
use crate::values::computed::Size;
use crate::values::generics::flex::FlexBasis as GenericFlexBasis;
/// The `width` value type.
#[cfg(feature = "servo")]
pub type Width = crate::values::computed::NonNegativeLengthPercentageOrAuto;
/// The `width` value type.
#[cfg(feature = "gecko")]
pub type Width = crate::values::computed::MozLength;
/// A computed value for the `flex-basis` property.
pub type FlexBasis = GenericFlexBasis<Width>;
pub type FlexBasis = GenericFlexBasis<Size>;
impl FlexBasis {
/// `auto`
#[inline]
pub fn auto() -> Self {
GenericFlexBasis::Width(Width::auto())
GenericFlexBasis::Width(Size::auto())
}
}

Просмотреть файл

@ -8,9 +8,7 @@ use super::{Context, Number, Percentage, ToComputedValue};
use crate::values::animated::ToAnimatedValue;
use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
use crate::values::generics::length as generics;
use crate::values::generics::length::{
MaxLength as GenericMaxLength, MozLength as GenericMozLength,
};
use crate::values::generics::length::{MaxSize as GenericMaxSize, Size as GenericSize};
use crate::values::generics::transform::IsZeroLength;
use crate::values::generics::NonNegative;
use crate::values::specified::length::ViewportPercentageLength;
@ -580,12 +578,36 @@ impl NonNegativeLengthPercentage {
}
#[cfg(feature = "servo")]
impl MaxLength {
impl MaxSize {
/// Convert the computed value into used value.
#[inline]
pub fn to_used_value(&self, percentage_basis: Au) -> Option<Au> {
match *self {
GenericMaxLength::None => None,
GenericMaxLength::LengthPercentage(ref lp) => Some(lp.to_used_value(percentage_basis)),
GenericMaxSize::None => None,
GenericMaxSize::LengthPercentage(ref lp) => Some(lp.to_used_value(percentage_basis)),
}
}
}
impl Size {
/// Convert the computed value into used value.
#[inline]
#[cfg(feature = "servo")]
pub fn to_used_value(&self, percentage_basis: Au) -> Option<Au> {
match *self {
GenericSize::Auto => None,
GenericSize::LengthPercentage(ref lp) => Some(lp.to_used_value(percentage_basis)),
}
}
/// Returns true if the computed value is absolute 0 or 0%.
#[inline]
pub fn is_definitely_zero(&self) -> bool {
match *self {
GenericSize::Auto => false,
GenericSize::LengthPercentage(ref lp) => lp.is_definitely_zero(),
#[cfg(feature = "gecko")]
GenericSize::ExtremumLength(..) => false,
}
}
}
@ -821,7 +843,7 @@ pub enum ExtremumLength {
}
/// A computed value for `min-width`, `min-height`, `width` or `height` property.
pub type MozLength = GenericMozLength<NonNegativeLengthPercentage>;
pub type Size = GenericSize<NonNegativeLengthPercentage>;
/// A computed value for `max-width` or `min-height` property.
pub type MaxLength = GenericMaxLength<NonNegativeLengthPercentage>;
pub type MaxSize = GenericMaxSize<NonNegativeLengthPercentage>;

Просмотреть файл

@ -62,7 +62,7 @@ pub use self::gecko::ScrollSnapPoint;
pub use self::image::{Gradient, GradientItem, Image, ImageLayer, LineDirection, MozImageRect};
pub use self::length::{CSSPixelLength, ExtremumLength, NonNegativeLength};
pub use self::length::{Length, LengthOrNumber, LengthPercentage};
pub use self::length::{LengthPercentageOrAuto, MaxLength, MozLength};
pub use self::length::{LengthPercentageOrAuto, MaxSize, Size};
pub use self::length::{NonNegativeLengthPercentage, NonNegativeLengthPercentageOrAuto};
#[cfg(feature = "gecko")]
pub use self::list::ListStyleType;

Просмотреть файл

@ -5,6 +5,7 @@
//! Generic types for CSS values related to length.
use crate::parser::{Parse, ParserContext};
#[cfg(feature = "gecko")]
use crate::values::computed::ExtremumLength;
use cssparser::Parser;
use style_traits::ParseError;
@ -76,7 +77,7 @@ impl<LengthPercentage: Parse> Parse for LengthPercentageOrAuto<LengthPercentage>
/// A generic value for the `width`, `height`, `min-width`, or `min-height` property.
///
/// Unlike `max-width` or `max-height` properties, a MozLength can be `auto`,
/// Unlike `max-width` or `max-height` properties, a Size can be `auto`,
/// and cannot be `none`.
///
/// Note that it only accepts non-negative values.
@ -95,18 +96,25 @@ impl<LengthPercentage: Parse> Parse for LengthPercentageOrAuto<LengthPercentage>
ToComputedValue,
ToCss,
)]
pub enum MozLength<LengthPercentage> {
pub enum Size<LengthPercentage> {
LengthPercentage(LengthPercentage),
Auto,
#[cfg(feature = "gecko")]
#[animation(error)]
ExtremumLength(ExtremumLength),
}
impl<LengthPercentage> MozLength<LengthPercentage> {
impl<LengthPercentage> Size<LengthPercentage> {
/// `auto` value.
#[inline]
pub fn auto() -> Self {
MozLength::Auto
Size::Auto
}
/// Returns whether we're the auto value.
#[inline]
pub fn is_auto(&self) -> bool {
matches!(*self, Size::Auto)
}
}
@ -126,7 +134,7 @@ impl<LengthPercentage> MozLength<LengthPercentage> {
ToComputedValue,
ToCss,
)]
pub enum MaxLength<LengthPercentage> {
pub enum MaxSize<LengthPercentage> {
LengthPercentage(LengthPercentage),
None,
#[cfg(feature = "gecko")]
@ -134,10 +142,10 @@ pub enum MaxLength<LengthPercentage> {
ExtremumLength(ExtremumLength),
}
impl<LengthPercentage> MaxLength<LengthPercentage> {
impl<LengthPercentage> MaxSize<LengthPercentage> {
/// `none` value.
#[inline]
pub fn none() -> Self {
MaxLength::None
MaxSize::None
}
}

Просмотреть файл

@ -6,26 +6,19 @@
use crate::parser::{Parse, ParserContext};
use crate::values::generics::flex::FlexBasis as GenericFlexBasis;
use crate::values::specified::Size;
use cssparser::Parser;
use style_traits::ParseError;
/// The `width` value type.
#[cfg(feature = "servo")]
pub type Width = crate::values::specified::NonNegativeLengthPercentageOrAuto;
/// The `width` value type.
#[cfg(feature = "gecko")]
pub type Width = crate::values::specified::MozLength;
/// A specified value for the `flex-basis` property.
pub type FlexBasis = GenericFlexBasis<Width>;
pub type FlexBasis = GenericFlexBasis<Size>;
impl Parse for FlexBasis {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
if let Ok(width) = input.try(|i| Width::parse(context, i)) {
if let Ok(width) = input.try(|i| Size::parse(context, i)) {
return Ok(GenericFlexBasis::Width(width));
}
try_match_ident_ignore_ascii_case! { input,
@ -38,12 +31,12 @@ impl FlexBasis {
/// `auto`
#[inline]
pub fn auto() -> Self {
GenericFlexBasis::Width(Width::auto())
GenericFlexBasis::Width(Size::auto())
}
/// `0%`
#[inline]
pub fn zero_percent() -> Self {
GenericFlexBasis::Width(Width::zero_percent())
GenericFlexBasis::Width(Size::zero_percent())
}
}

Просмотреть файл

@ -9,11 +9,9 @@
use super::{AllowQuirks, Number, Percentage, ToComputedValue};
use crate::font_metrics::FontMetricsQueryResult;
use crate::parser::{Parse, ParserContext};
use crate::values::computed::{self, CSSPixelLength, Context, ExtremumLength};
use crate::values::computed::{self, CSSPixelLength, Context};
use crate::values::generics::length as generics;
use crate::values::generics::length::{
MaxLength as GenericMaxLength, MozLength as GenericMozLength,
};
use crate::values::generics::length::{MaxSize as GenericMaxSize, Size as GenericSize};
use crate::values::generics::transform::IsZeroLength;
use crate::values::generics::NonNegative;
use crate::values::specified::calc::CalcNode;
@ -1051,56 +1049,18 @@ impl LengthOrNumber {
}
/// A specified value for `min-width`, `min-height`, `width` or `height` property.
pub type MozLength = GenericMozLength<NonNegativeLengthPercentage>;
pub type Size = GenericSize<NonNegativeLengthPercentage>;
impl Parse for MozLength {
impl Parse for Size {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
MozLength::parse_quirky(context, input, AllowQuirks::No)
Size::parse_quirky(context, input, AllowQuirks::No)
}
}
impl MozLength {
/// Parses, with quirks.
pub fn parse_quirky<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks,
) -> Result<Self, ParseError<'i>> {
if let Ok(l) = input.try(ExtremumLength::parse) {
return Ok(GenericMozLength::ExtremumLength(l));
}
if input.try(|i| i.expect_ident_matching("auto")).is_ok() {
return Ok(GenericMozLength::Auto);
}
let length = NonNegativeLengthPercentage::parse_quirky(context, input, allow_quirks)?;
Ok(GenericMozLength::LengthPercentage(length))
}
/// Returns `0%`.
#[inline]
pub fn zero_percent() -> Self {
GenericMozLength::LengthPercentage(NonNegativeLengthPercentage::zero_percent())
}
}
/// A specified value for `max-width` or `max-height` property.
pub type MaxLength = GenericMaxLength<NonNegativeLengthPercentage>;
impl Parse for MaxLength {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
MaxLength::parse_quirky(context, input, AllowQuirks::No)
}
}
impl MaxLength {
impl Size {
/// Parses, with quirks.
pub fn parse_quirky<'i, 't>(
context: &ParserContext,
@ -1109,16 +1069,57 @@ impl MaxLength {
) -> Result<Self, ParseError<'i>> {
#[cfg(feature = "gecko")]
{
if let Ok(l) = input.try(ExtremumLength::parse) {
return Ok(GenericMaxLength::ExtremumLength(l));
if let Ok(l) = input.try(computed::ExtremumLength::parse) {
return Ok(GenericSize::ExtremumLength(l));
}
}
if input.try(|i| i.expect_ident_matching("auto")).is_ok() {
return Ok(GenericSize::Auto);
}
let length = NonNegativeLengthPercentage::parse_quirky(context, input, allow_quirks)?;
Ok(GenericSize::LengthPercentage(length))
}
/// Returns `0%`.
#[inline]
pub fn zero_percent() -> Self {
GenericSize::LengthPercentage(NonNegativeLengthPercentage::zero_percent())
}
}
/// A specified value for `max-width` or `max-height` property.
pub type MaxSize = GenericMaxSize<NonNegativeLengthPercentage>;
impl Parse for MaxSize {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
MaxSize::parse_quirky(context, input, AllowQuirks::No)
}
}
impl MaxSize {
/// Parses, with quirks.
pub fn parse_quirky<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks,
) -> Result<Self, ParseError<'i>> {
#[cfg(feature = "gecko")]
{
if let Ok(l) = input.try(computed::ExtremumLength::parse) {
return Ok(GenericMaxSize::ExtremumLength(l));
}
}
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
return Ok(GenericMaxLength::None);
return Ok(GenericMaxSize::None);
}
let length = NonNegativeLengthPercentage::parse_quirky(context, input, allow_quirks)?;
Ok(GenericMaxLength::LengthPercentage(length))
Ok(GenericMaxSize::LengthPercentage(length))
}
}

Просмотреть файл

@ -59,7 +59,7 @@ pub use self::image::{GradientItem, GradientKind, Image, ImageLayer, MozImageRec
pub use self::length::{AbsoluteLength, CalcLengthPercentage, CharacterWidth};
pub use self::length::{FontRelativeLength, Length, LengthOrNumber};
pub use self::length::{LengthPercentage, LengthPercentageOrAuto};
pub use self::length::{MaxLength, MozLength};
pub use self::length::{MaxSize, Size};
pub use self::length::{NoCalcLength, ViewportPercentageLength};
pub use self::length::{NonNegativeLengthPercentage, NonNegativeLengthPercentageOrAuto};
#[cfg(feature = "gecko")]

Просмотреть файл

@ -4434,7 +4434,7 @@ pub extern "C" fn Servo_DeclarationBlock_SetPixelValue(
) {
use style::properties::longhands::border_spacing::SpecifiedValue as BorderSpacing;
use style::properties::{LonghandId, PropertyDeclaration};
use style::values::generics::length::MozLength;
use style::values::generics::length::Size;
use style::values::generics::NonNegative;
use style::values::generics::length::LengthPercentageOrAuto;
use style::values::specified::length::NonNegativeLengthPercentage;
@ -4447,8 +4447,8 @@ pub extern "C" fn Servo_DeclarationBlock_SetPixelValue(
let lp = LengthPercentage::Length(nocalc);
let lp_or_auto = LengthPercentageOrAuto::LengthPercentage(lp.clone());
let prop = match_wrap_declared! { long,
Height => MozLength::LengthPercentage(NonNegative(lp)),
Width => MozLength::LengthPercentage(NonNegative(lp)),
Height => Size::LengthPercentage(NonNegative(lp)),
Width => Size::LengthPercentage(NonNegative(lp)),
BorderTopWidth => BorderSideWidth::Length(nocalc.into()),
BorderRightWidth => BorderSideWidth::Length(nocalc.into()),
BorderBottomWidth => BorderSideWidth::Length(nocalc.into()),
@ -4497,7 +4497,7 @@ pub extern "C" fn Servo_DeclarationBlock_SetLengthValue(
use style::properties::longhands::_moz_script_min_size::SpecifiedValue as MozScriptMinSize;
use style::properties::{LonghandId, PropertyDeclaration};
use style::values::generics::NonNegative;
use style::values::generics::length::MozLength;
use style::values::generics::length::Size;
use style::values::specified::length::NoCalcLength;
use style::values::specified::length::{AbsoluteLength, FontRelativeLength};
use style::values::specified::length::LengthPercentage;
@ -4525,7 +4525,7 @@ pub extern "C" fn Servo_DeclarationBlock_SetLengthValue(
};
let prop = match_wrap_declared! { long,
Width => MozLength::LengthPercentage(NonNegative(LengthPercentage::Length(nocalc))),
Width => Size::LengthPercentage(NonNegative(LengthPercentage::Length(nocalc))),
FontSize => LengthPercentage::from(nocalc).into(),
MozScriptMinSize => MozScriptMinSize(nocalc),
};
@ -4565,7 +4565,7 @@ pub extern "C" fn Servo_DeclarationBlock_SetPercentValue(
use style::properties::{LonghandId, PropertyDeclaration};
use style::values::computed::Percentage;
use style::values::generics::NonNegative;
use style::values::generics::length::{MozLength, LengthPercentageOrAuto};
use style::values::generics::length::{Size, LengthPercentageOrAuto};
use style::values::specified::length::LengthPercentage;
let long = get_longhand_from_id!(property);
@ -4574,8 +4574,8 @@ pub extern "C" fn Servo_DeclarationBlock_SetPercentValue(
let lp_or_auto = LengthPercentageOrAuto::LengthPercentage(lp.clone());
let prop = match_wrap_declared! { long,
Height => MozLength::LengthPercentage(NonNegative(lp)),
Width => MozLength::LengthPercentage(NonNegative(lp)),
Height => Size::LengthPercentage(NonNegative(lp)),
Width => Size::LengthPercentage(NonNegative(lp)),
MarginTop => lp_or_auto,
MarginRight => lp_or_auto,
MarginBottom => lp_or_auto,
@ -4593,14 +4593,14 @@ pub extern "C" fn Servo_DeclarationBlock_SetAutoValue(
property: nsCSSPropertyID,
) {
use style::properties::{LonghandId, PropertyDeclaration};
use style::values::generics::length::{LengthPercentageOrAuto, MozLength};
use style::values::generics::length::{LengthPercentageOrAuto, Size};
let long = get_longhand_from_id!(property);
let auto = LengthPercentageOrAuto::Auto;
let prop = match_wrap_declared! { long,
Height => MozLength::auto(),
Width => MozLength::auto(),
Height => Size::auto(),
Width => Size::auto(),
MarginTop => auto,
MarginRight => auto,
MarginBottom => auto,

Просмотреть файл

@ -9,6 +9,10 @@ job-defaults:
by-test-platform:
android-hw.*: /builds/worker
default: /home/cltbld
run-on-projects:
by-test-platform:
windows10-64-ux: ['try', 'mozilla-central']
default: ['try', 'trunk', 'mozilla-beta']
tier:
by-test-platform:
windows10-64-ccov/.*: 3
@ -40,10 +44,6 @@ raptor-tp6-1-firefox:
description: "Raptor tp6-1 on Firefox"
try-name: raptor-tp6-1-firefox
treeherder-symbol: Rap(tp6-1)
run-on-projects:
by-test-platform:
windows10-64-ux: ['try', 'mozilla-central']
default: built-projects
mozharness:
extra-options:
- --test=raptor-tp6-1
@ -76,7 +76,6 @@ raptor-tp6-2-firefox:
description: "Raptor tp6-2 on Firefox"
try-name: raptor-tp6-2-firefox
treeherder-symbol: Rap(tp6-2)
run-on-projects: built-projects
mozharness:
extra-options:
- --test=raptor-tp6-2
@ -108,7 +107,6 @@ raptor-tp6-3-firefox:
description: "Raptor tp6-3 on Firefox"
try-name: raptor-tp6-3-firefox
treeherder-symbol: Rap(tp6-3)
run-on-projects: built-projects
mozharness:
extra-options:
- --test=raptor-tp6-3
@ -141,7 +139,6 @@ raptor-tp6-4-firefox:
description: "Raptor tp6-4 on Firefox"
try-name: raptor-tp6-4-firefox
treeherder-symbol: Rap(tp6-4)
run-on-projects: built-projects
mozharness:
extra-options:
- --test=raptor-tp6-4
@ -173,7 +170,6 @@ raptor-tp6-5-firefox:
description: "Raptor tp6-5 on Firefox"
try-name: raptor-tp6-5-firefox
treeherder-symbol: Rap(tp6-5)
run-on-projects: built-projects
mozharness:
extra-options:
- --test=raptor-tp6-5
@ -205,7 +201,6 @@ raptor-tp6-6-firefox:
description: "Raptor tp6-6 on Firefox"
try-name: raptor-tp6-6-firefox
treeherder-symbol: Rap(tp6-6)
run-on-projects: built-projects
mozharness:
extra-options:
- --test=raptor-tp6-6
@ -370,7 +365,6 @@ raptor-tp6m-1-geckoview:
try-name: raptor-tp6m-1-geckoview
treeherder-symbol: Rap(tp6m-1)
target: geckoview_example.apk
run-on-projects: built-projects
tier: 2
mozharness:
extra-options:
@ -382,10 +376,6 @@ raptor-speedometer-firefox:
description: "Raptor Speedometer on Firefox"
try-name: raptor-speedometer-firefox
treeherder-symbol: Rap(sp)
run-on-projects:
by-test-platform:
windows10-64-ux: ['try', 'mozilla-central']
default: built-projects
mozharness:
extra-options:
- --test=raptor-speedometer
@ -409,7 +399,7 @@ raptor-speedometer-geckoview:
target: geckoview_example.apk
run-on-projects:
by-test-platform:
android-hw.*: built-projects
android-hw.*: ['try', 'trunk', 'mozilla-beta']
max-run-time: 900
mozharness:
extra-options:
@ -442,7 +432,7 @@ raptor-speedometer-fennec:
target: target.apk
run-on-projects:
by-test-platform:
android-hw.*: built-projects
android-hw.*: ['try', 'trunk', 'mozilla-beta']
tier: 3
max-run-time: 900
mozharness:
@ -467,10 +457,6 @@ raptor-stylebench-firefox:
description: "Raptor StyleBench on Firefox"
try-name: raptor-stylebench-firefox
treeherder-symbol: Rap(sb)
run-on-projects:
by-test-platform:
windows10-64-ux: ['try', 'mozilla-central']
default: built-projects
mozharness:
extra-options:
- --test=raptor-stylebench
@ -502,10 +488,6 @@ raptor-motionmark-htmlsuite-firefox:
description: "Raptor MotionMark HtmlSuite on Firefox"
try-name: raptor-motionmark-htmlsuite-firefox
treeherder-symbol: Rap(mm-h)
run-on-projects:
by-test-platform:
windows10-64-ux: ['try', 'mozilla-central']
default: built-projects
mozharness:
extra-options:
- --test=raptor-motionmark-htmlsuite
@ -537,10 +519,6 @@ raptor-motionmark-animometer-firefox:
description: "Raptor MotionMark Animometer on Firefox"
try-name: raptor-motionmark-animometer-firefox
treeherder-symbol: Rap(mm-a)
run-on-projects:
by-test-platform:
windows10-64-ux: ['try', 'mozilla-central']
default: built-projects
mozharness:
extra-options:
- --test=raptor-motionmark-animometer
@ -572,10 +550,6 @@ raptor-webaudio-firefox:
description: "Raptor WebAudio on Firefox"
try-name: raptor-webaudio-firefox
treeherder-symbol: Rap(wa)
run-on-projects:
by-test-platform:
windows10-64-ux: ['try', 'mozilla-central']
default: built-projects
mozharness:
extra-options:
- --test=raptor-webaudio
@ -601,19 +575,11 @@ raptor-webaudio-chrome:
extra-options:
- --test=raptor-webaudio
- --app=chrome
run-on-projects:
by-test-platform:
windows10-64-ux: ['try', 'mozilla-central']
default: built-projects
raptor-sunspider-firefox:
description: "Raptor SunSpider on Firefox"
try-name: raptor-sunspider-firefox
treeherder-symbol: Rap(ss)
run-on-projects:
by-test-platform:
windows10-64-ux: ['try', 'mozilla-central']
default: built-projects
mozharness:
extra-options:
- --test=raptor-sunspider
@ -645,10 +611,6 @@ raptor-unity-webgl-firefox:
description: "Raptor Unity WebGL on Firefox"
try-name: raptor-unity-webgl-firefox
treeherder-symbol: Rap(ugl)
run-on-projects:
by-test-platform:
windows10-64-ux: ['try', 'mozilla-central']
default: built-projects
mozharness:
extra-options:
- --test=raptor-unity-webgl
@ -678,7 +640,7 @@ raptor-unity-webgl-geckoview:
target: geckoview_example.apk
run-on-projects:
by-test-platform:
android-hw.*: built-projects
android-hw.*: ['try', 'trunk', 'mozilla-beta']
max-run-time: 900
mozharness:
extra-options:
@ -707,10 +669,6 @@ raptor-wasm-misc-firefox:
description: "Raptor WASM Misc on Firefox"
try-name: raptor-wasm-misc-firefox
treeherder-symbol: Rap(wm)
run-on-projects:
by-test-platform:
windows10-64-ux: ['try', 'mozilla-central']
default: built-projects
mozharness:
extra-options:
- --test=raptor-wasm-misc
@ -737,10 +695,6 @@ raptor-wasm-misc-baseline-firefox:
description: "Raptor WASM Misc on Firefox with baseline JIT"
try-name: raptor-wasm-misc-baseline-firefox
treeherder-symbol: Rap(wm-b)
run-on-projects:
by-test-platform:
windows10-64-ux: ['try', 'mozilla-central']
default: built-projects
mozharness:
extra-options:
- --test=raptor-wasm-misc-baseline
@ -767,10 +721,6 @@ raptor-wasm-misc-ion-firefox:
description: "Raptor WASM Misc on Firefox with ION Monkey"
try-name: raptor-wasm-misc-ion-firefox
treeherder-symbol: Rap(wm-i)
run-on-projects:
by-test-platform:
windows10-64-ux: ['try', 'mozilla-central']
default: built-projects
mozharness:
extra-options:
- --test=raptor-wasm-misc-ion
@ -811,10 +761,6 @@ raptor-assorted-dom-firefox:
description: "Raptor Assorted-Dom on Firefox"
try-name: raptor-assorted-dom-firefox
treeherder-symbol: Rap(dom)
run-on-projects:
by-test-platform:
windows10-64-ux: ['try', 'mozilla-central']
default: built-projects
max-run-time:
by-test-platform:
.*-qr/.*: 2100
@ -861,10 +807,6 @@ raptor-wasm-godot-firefox:
description: "Raptor Wasm Godot on Firefox"
try-name: raptor-wasm-godot-firefox
treeherder-symbol: Rap(godot)
run-on-projects:
by-test-platform:
windows10-64-ux: ['try', 'mozilla-central']
default: built-projects
max-run-time:
by-test-platform:
.*-qr/.*: 2100
@ -902,10 +844,6 @@ raptor-wasm-godot-baseline-firefox:
description: "Raptor Wasm Godot on Firefox with baseline JIT"
try-name: raptor-wasm-godot-baseline-firefox
treeherder-symbol: Rap(godot-b)
run-on-projects:
by-test-platform:
windows10-64-ux: ['try', 'mozilla-central']
default: built-projects
max-run-time:
by-test-platform:
.*-qr/.*: 2100
@ -931,10 +869,6 @@ raptor-wasm-godot-ion-firefox:
description: "Raptor WASM godot on Firefox with ION Monkey"
try-name: raptor-wasm-godot-ion-firefox
treeherder-symbol: Rap(godot-i)
run-on-projects:
by-test-platform:
windows10-64-ux: ['try', 'mozilla-central']
default: built-projects
max-run-time:
by-test-platform:
.*-qr/.*: 2100

Просмотреть файл

@ -297,10 +297,10 @@
},
"python-dateutil": {
"hashes": [
"sha256:063df5763652e21de43de7d9e00ccf239f953a832941e37be541614732cdfc93",
"sha256:88f9287c0174266bb0d8cedd395cfba9c58e87e5ad86b2ce58859bc11be3cf02"
"sha256:7e6584c74aeed623791615e26efd690f29817a27c73085b78e4bad02493df2fb",
"sha256:c89805f6f4d64db21ed966fda138f8a5ed7a4fdbc1a8ee329ce1b74e3c74da9e"
],
"version": "==2.7.5"
"version": "==2.8.0"
},
"python-gnupg": {
"hashes": [

Просмотреть файл

@ -12,9 +12,9 @@ import signal
import subprocess
import sys
import tempfile
import urllib2
import zipfile
from collections import namedtuple
from six.moves.urllib.request import urlopen
import mozfile
import mozinfo
@ -110,7 +110,9 @@ def check_for_crashes(dump_directory,
sig=signature,
out="\n".join(stackwalk_output),
err="\n".join(info.stackwalk_errors))
print(output.encode("utf-8"))
if sys.stdout.encoding != 'UTF-8':
output = output.encode('utf-8')
print(output)
return crash_count
@ -179,7 +181,7 @@ class CrashInfo(object):
self.remove_symbols = True
self.logger.info("Downloading symbols from: %s" % self.symbols_path)
# Get the symbols and write them to a temporary zipfile
data = urllib2.urlopen(self.symbols_path)
data = urlopen(self.symbols_path)
with tempfile.TemporaryFile() as symbols_file:
symbols_file.write(data.read())
# extract symbols to a temporary directory (which we'll delete after

Просмотреть файл

@ -1,6 +1,5 @@
[DEFAULT]
subsuite = mozbase
skip-if = python == 3
[test_basic.py]
[test_java_exception.py]
[test_save_path.py]

Просмотреть файл

@ -3,9 +3,9 @@
from __future__ import absolute_import
import urlparse
import zipfile
import StringIO
from six import BytesIO
from six.moves.urllib.parse import urlunsplit
import mozhttpd
import mozunit
@ -34,7 +34,7 @@ def test_symbols_path_url(check_for_crashes, minidump_files):
data = {"retrieved": False}
def make_zipfile():
data = StringIO.StringIO()
data = BytesIO()
z = zipfile.ZipFile(data, 'w')
z.writestr("symbols.txt", "abc/xyz")
z.close()
@ -51,8 +51,8 @@ def test_symbols_path_url(check_for_crashes, minidump_files):
'path': '/symbols',
'function': get_symbols}])
httpd.start()
symbol_url = urlparse.urlunsplit(('http', '%s:%d' % httpd.httpd.server_address,
'/symbols', '', ''))
symbol_url = urlunsplit(('http', '%s:%d' % httpd.httpd.server_address,
'/symbols', '', ''))
assert 1 == check_for_crashes(symbols_path=symbol_url)
assert data["retrieved"]

Просмотреть файл

@ -7,7 +7,7 @@ from __future__ import absolute_import
from setuptools import setup, find_packages
PACKAGE_NAME = 'mozrunner'
PACKAGE_VERSION = '7.2.0'
PACKAGE_VERSION = '7.3.0'
desc = """Reliable start/stop/configuration of Mozilla Applications (Firefox, Thunderbird, etc.)"""

Просмотреть файл

@ -606,11 +606,6 @@ class Output(object):
def output(self, test_names):
"""output to file and perfherder data json """
if self.summarized_results == {}:
LOG.error("error: no summarized raptor results found for %s" %
', '.join(test_names))
return False
if os.environ['MOZ_UPLOAD_DIR']:
# i.e. testing/mozharness/build/raptor.json locally; in production it will
# be at /tasks/task_*/build/ (where it will be picked up by mozharness later
@ -623,9 +618,13 @@ class Output(object):
results_path = os.path.join(os.getcwd(), 'raptor.json')
screenshot_path = os.path.join(os.getcwd(), 'screenshots.html')
with open(results_path, 'w') as f:
for result in self.summarized_results:
f.write("%s\n" % result)
if self.summarized_results == {}:
LOG.error("error: no summarized raptor results found for %s" %
', '.join(test_names))
else:
with open(results_path, 'w') as f:
for result in self.summarized_results:
f.write("%s\n" % result)
if len(self.summarized_screenshots) > 0:
with open(screenshot_path, 'w') as f:
@ -633,6 +632,11 @@ class Output(object):
f.write("%s\n" % result)
LOG.info("screen captures can be found locally at: %s" % screenshot_path)
# now that we've checked for screen captures too, if there were no actual
# test results we can bail out here
if self.summarized_results == {}:
return False
# when gecko_profiling, we don't want results ingested by Perfherder
extra_opts = self.summarized_results['suites'][0].get('extraOptions', [])
if 'gecko_profile' not in extra_opts:

Просмотреть файл

@ -396,9 +396,13 @@ async function nextCycle() {
}
}
function timeoutAlarmListener() {
async function timeoutAlarmListener() {
console.error("raptor-page-timeout on %s" % testURL);
postToControlServer("raptor-page-timeout", [testName, testURL]);
// take a screen capture
if (screenCapture) {
await getScreenCapture();
}
// call clean-up to shutdown gracefully
cleanUp();
}

Просмотреть файл

@ -121,17 +121,36 @@ bool GetParentPrincipalAndTrackingOrigin(
return true;
};
void CreatePermissionKey(const nsCString& aTrackingOrigin,
nsACString& aPermissionKey) {
MOZ_ASSERT(aPermissionKey.IsEmpty());
static const nsLiteralCString prefix =
NS_LITERAL_CSTRING(ANTITRACKING_PERM_KEY "^");
aPermissionKey.SetCapacity(prefix.Length() + aTrackingOrigin.Length());
aPermissionKey.Append(prefix);
aPermissionKey.Append(aTrackingOrigin);
}
void CreatePermissionKey(const nsCString& aTrackingOrigin,
const nsCString& aGrantedOrigin,
nsACString& aPermissionKey) {
MOZ_ASSERT(aPermissionKey.IsEmpty());
if (aTrackingOrigin == aGrantedOrigin) {
aPermissionKey =
nsPrintfCString(ANTITRACKING_PERM_KEY "^%s", aTrackingOrigin.get());
CreatePermissionKey(aTrackingOrigin, aPermissionKey);
return;
}
aPermissionKey = nsPrintfCString(ANTITRACKING_PERM_KEY "^%s^%s",
aTrackingOrigin.get(), aGrantedOrigin.get());
static const nsLiteralCString prefix =
NS_LITERAL_CSTRING(ANTITRACKING_PERM_KEY "^");
aPermissionKey.SetCapacity(prefix.Length() + 1 + aTrackingOrigin.Length());
aPermissionKey.Append(prefix);
aPermissionKey.Append(aTrackingOrigin);
aPermissionKey.AppendLiteral("^");
aPermissionKey.Append(aGrantedOrigin);
}
// This internal method returns ACCESS_DENY if the access is denied,
@ -1021,7 +1040,7 @@ bool AntiTrackingCommon::IsStorageAccessPermission(nsIPermission* aPermission,
// shorter permission key and will then do a prefix match on the type of the
// input permission to see if it is a storage access permission or not.
nsAutoCString permissionKey;
CreatePermissionKey(origin, origin, permissionKey);
CreatePermissionKey(origin, permissionKey);
nsAutoCString type;
rv = aPermission->GetType(type);
@ -1545,7 +1564,7 @@ bool AntiTrackingCommon::IsFirstPartyStorageAccessGrantedFor(
}
nsAutoCString type;
CreatePermissionKey(origin, origin, type);
CreatePermissionKey(origin, type);
nsPermissionManager* permManager = nsPermissionManager::GetInstance();
if (NS_WARN_IF(!permManager)) {

Просмотреть файл

@ -20,12 +20,16 @@ AntiTracking.runTest("IndexedDB in workers",
await new Promise((resolve, reject) => {
worker.onmessage = function(e) {
if (e) {
if (e.data) {
resolve();
} else {
reject();
}
};
worker.onerror = function(e) {
reject();
};
});
},
async _ => {
@ -45,12 +49,16 @@ AntiTracking.runTest("IndexedDB in workers",
await new Promise((resolve, reject) => {
worker.onmessage = function(e) {
if (e) {
if (e.data) {
resolve();
} else {
reject();
}
};
worker.onerror = function(e) {
reject();
};
});
},
async _ => {
@ -88,12 +96,16 @@ AntiTracking.runTest("IndexedDB in workers and Storage Access API",
await new Promise((resolve, reject) => {
worker.onmessage = function(e) {
if (e) {
if (e.data) {
resolve();
} else {
reject();
}
};
worker.onerror = function(e) {
reject();
};
});
/* import-globals-from storageAccessAPIHelpers.js */
@ -114,12 +126,16 @@ AntiTracking.runTest("IndexedDB in workers and Storage Access API",
await new Promise((resolve, reject) => {
worker.onmessage = function(e) {
if (e) {
if (e.data) {
resolve();
} else {
reject();
}
};
worker.onerror = function(e) {
reject();
};
});
},
async _ => {
@ -142,12 +158,16 @@ AntiTracking.runTest("IndexedDB in workers and Storage Access API",
await new Promise((resolve, reject) => {
worker.onmessage = function(e) {
if (e) {
if (e.data) {
resolve();
} else {
reject();
}
};
worker.onerror = function(e) {
reject();
};
});
/* import-globals-from storageAccessAPIHelpers.js */
@ -160,12 +180,16 @@ AntiTracking.runTest("IndexedDB in workers and Storage Access API",
await new Promise((resolve, reject) => {
worker.onmessage = function(e) {
if (e) {
if (e.data) {
resolve();
} else {
reject();
}
};
worker.onerror = function(e) {
reject();
};
});
},
async _ => {

Просмотреть файл

@ -40,12 +40,16 @@ AntiTracking.runTest("BroadcastChannel in workers",
await new Promise((resolve, reject) => {
worker.onmessage = function(e) {
if (e) {
if (e.data) {
resolve();
} else {
reject();
}
};
worker.onerror = function(e) {
reject();
};
});
},
async _ => {
@ -65,12 +69,16 @@ AntiTracking.runTest("BroadcastChannel in workers",
await new Promise((resolve, reject) => {
worker.onmessage = function(e) {
if (e) {
if (e.data) {
resolve();
} else {
reject();
}
};
worker.onerror = function(e) {
reject();
};
});
},
async _ => {
@ -157,12 +165,16 @@ AntiTracking.runTest("BroadcastChannel in workers and Storage Access API",
await new Promise((resolve, reject) => {
worker.onmessage = function(e) {
if (e) {
if (e.data) {
resolve();
} else {
reject();
}
};
worker.onerror = function(e) {
reject();
};
});
/* import-globals-from storageAccessAPIHelpers.js */
@ -184,12 +196,16 @@ AntiTracking.runTest("BroadcastChannel in workers and Storage Access API",
await new Promise((resolve, reject) => {
worker.onmessage = function(e) {
if (e) {
if (e.data) {
resolve();
} else {
reject();
}
};
worker.onerror = function(e) {
reject();
};
});
},
async _ => {
@ -212,12 +228,16 @@ AntiTracking.runTest("BroadcastChannel in workers and Storage Access API",
await new Promise((resolve, reject) => {
worker.onmessage = function(e) {
if (e) {
if (e.data) {
resolve();
} else {
reject();
}
};
worker.onerror = function(e) {
reject();
};
});
/* import-globals-from storageAccessAPIHelpers.js */
@ -230,12 +250,16 @@ AntiTracking.runTest("BroadcastChannel in workers and Storage Access API",
await new Promise((resolve, reject) => {
worker.onmessage = function(e) {
if (e) {
if (e.data) {
resolve();
} else {
reject();
}
};
worker.onerror = function(e) {
reject();
};
});
},
async _ => {

Просмотреть файл

@ -316,899 +316,6 @@ add_task(async function test_userScripts_no_webext_apis() {
await extension.unload();
});
// A small utility function used to test the expected behaviors of the userScripts API method
// wrapper.
async function test_userScript_APIMethod({
apiScript, userScript, userScriptMetadata, testFn,
runtimeMessageListener,
}) {
async function backgroundScript(userScriptFn, scriptMetadata, messageListener) {
await browser.userScripts.register({
js: [{
code: `(${userScriptFn})();`,
}],
runAt: "document_end",
matches: ["http://localhost/*/file_sample.html"],
scriptMetadata,
});
if (messageListener) {
browser.runtime.onMessage.addListener(messageListener);
}
browser.test.sendMessage("background-ready");
}
function notifyFinish(failureReason) {
browser.test.assertEq(undefined, failureReason, "should be completed without errors");
browser.test.sendMessage("test_userScript_APIMethod:done");
}
function assertTrue(val, message) {
browser.test.assertTrue(val, message);
if (!val) {
browser.test.sendMessage("test_userScript_APIMethod:done");
throw message;
}
}
let extension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: [
"http://localhost/*/file_sample.html",
],
user_scripts: {
api_script: "api-script.js",
},
},
// Defines a background script that receives all the needed test parameters.
background: `
const metadata = ${JSON.stringify(userScriptMetadata)};
(${backgroundScript})(${userScript}, metadata, ${runtimeMessageListener})
`,
files: {
"api-script.js": `(${apiScript})({
assertTrue: ${assertTrue},
notifyFinish: ${notifyFinish}
})`,
},
});
// Load a page in a content process, register the user script and then load a
// new page in the existing content process.
let url = `${BASE_URL}/file_sample.html`;
let contentPage = await ExtensionTestUtils.loadContentPage(`about:blank`);
await extension.startup();
await extension.awaitMessage("background-ready");
await contentPage.loadURL(url);
// Run any additional test-specific assertions.
if (testFn) {
await testFn({extension, contentPage, url});
}
await extension.awaitMessage("test_userScript_APIMethod:done");
await extension.unload();
await contentPage.close();
}
add_task(async function test_apiScript_exports_simple_sync_method() {
function apiScript(sharedTestAPIMethods) {
browser.userScripts.onBeforeScript.addListener(script => {
const scriptMetadata = script.metadata;
script.defineGlobals({
...sharedTestAPIMethods,
testAPIMethod(stringParam, numberParam, boolParam, nullParam, undefinedParam, arrayParam) {
browser.test.assertEq("test-user-script-exported-apis", scriptMetadata.name,
"Got the expected value for a string scriptMetadata property");
browser.test.assertEq(null, scriptMetadata.nullProperty,
"Got the expected value for a null scriptMetadata property");
browser.test.assertTrue(scriptMetadata.arrayProperty &&
scriptMetadata.arrayProperty.length === 1 &&
scriptMetadata.arrayProperty[0] === "el1",
"Got the expected value for an array scriptMetadata property");
browser.test.assertTrue(scriptMetadata.objectProperty &&
scriptMetadata.objectProperty.nestedProp === "nestedValue",
"Got the expected value for an object scriptMetadata property");
browser.test.assertEq("param1", stringParam, "Got the expected string parameter value");
browser.test.assertEq(123, numberParam, "Got the expected number parameter value");
browser.test.assertEq(true, boolParam, "Got the expected boolean parameter value");
browser.test.assertEq(null, nullParam, "Got the expected null parameter value");
browser.test.assertEq(undefined, undefinedParam, "Got the expected undefined parameter value");
browser.test.assertEq(3, arrayParam.length, "Got the expected length on the array param");
browser.test.assertTrue(arrayParam.includes(1),
"Got the expected result when calling arrayParam.includes");
return "returned_value";
},
});
});
}
function userScript() {
const {assertTrue, notifyFinish, testAPIMethod} = this;
// Redefine the includes method on the Array prototype, to explicitly verify that the method
// redefined in the userScript is not used when accessing arrayParam.includes from the API script.
Array.prototype.includes = () => { // eslint-disable-line no-extend-native
throw new Error("Unexpected prototype leakage");
};
const arrayParam = new Array(1, 2, 3); // eslint-disable-line no-array-constructor
const result = testAPIMethod("param1", 123, true, null, undefined, arrayParam);
assertTrue(result === "returned_value", `userScript got an unexpected result value: ${result}`);
notifyFinish();
}
const userScriptMetadata = {
name: "test-user-script-exported-apis",
arrayProperty: ["el1"],
objectProperty: {nestedProp: "nestedValue"},
nullProperty: null,
};
await test_userScript_APIMethod({
userScript,
apiScript,
userScriptMetadata,
});
});
add_task(async function test_apiScript_async_method() {
function apiScript(sharedTestAPIMethods) {
browser.userScripts.onBeforeScript.addListener(script => {
script.defineGlobals({
...sharedTestAPIMethods,
testAPIMethod(param, cb, cb2, objWithCb) {
browser.test.assertEq("function", typeof cb, "Got a callback function parameter");
browser.test.assertTrue(cb === cb2, "Got the same cloned function for the same function parameter");
browser.runtime.sendMessage(param).then(bgPageRes => {
const cbResult = cb(script.export(bgPageRes));
browser.test.sendMessage("user-script-callback-return", cbResult);
});
return "resolved_value";
},
});
});
}
async function userScript() {
// Redefine Promise to verify that it doesn't break the WebExtensions internals
// that are going to use them.
const {Promise} = this;
Promise.resolve = function() {
throw new Error("Promise.resolve poisoning");
};
this.Promise = function() {
throw new Error("Promise constructor poisoning");
};
const {assertTrue, notifyFinish, testAPIMethod} = this;
const cb = (cbParam) => {
return `callback param: ${JSON.stringify(cbParam)}`;
};
const cb2 = cb;
const asyncAPIResult = await testAPIMethod("param3", cb, cb2);
assertTrue(asyncAPIResult === "resolved_value",
`userScript got an unexpected resolved value: ${asyncAPIResult}`);
notifyFinish();
}
async function runtimeMessageListener(param) {
if (param !== "param3") {
browser.test.fail(`Got an unexpected message: ${param}`);
}
return {bgPageReply: true};
}
await test_userScript_APIMethod({
userScript,
apiScript,
runtimeMessageListener,
async testFn({extension}) {
const res = await extension.awaitMessage("user-script-callback-return");
equal(res, `callback param: ${JSON.stringify({bgPageReply: true})}`,
"Got the expected userScript callback return value");
},
});
});
add_task(async function test_apiScript_method_with_webpage_objects_params() {
function apiScript(sharedTestAPIMethods) {
browser.userScripts.onBeforeScript.addListener(script => {
script.defineGlobals({
...sharedTestAPIMethods,
testAPIMethod(windowParam, documentParam) {
browser.test.assertEq(window, windowParam, "Got a reference to the native window as first param");
browser.test.assertEq(window.document, documentParam,
"Got a reference to the native document as second param");
// Return an uncloneable webpage object, which checks that if the returned object is from a principal
// that is subsumed by the userScript sandbox principal, it is returned without being cloned.
return windowParam;
},
});
});
}
async function userScript() {
const {assertTrue, notifyFinish, testAPIMethod} = this;
const result = testAPIMethod(window, document);
// We expect the returned value to be the uncloneable window object.
assertTrue(result === window,
`userScript got an unexpected returned value: ${result}`);
notifyFinish();
}
await test_userScript_APIMethod({
userScript,
apiScript,
});
});
add_task(async function test_apiScript_method_got_param_with_methods() {
function apiScript(sharedTestAPIMethods) {
browser.userScripts.onBeforeScript.addListener(script => {
const scriptGlobal = script.global;
const ScriptFunction = scriptGlobal.Function;
script.defineGlobals({
...sharedTestAPIMethods,
testAPIMethod(objWithMethods) {
browser.test.assertEq("objPropertyValue", objWithMethods && objWithMethods.objProperty,
"Got the expected property on the object passed as a parameter");
browser.test.assertEq(undefined, typeof objWithMethods && objWithMethods.objMethod,
"XrayWrapper should deny access to a callable property");
browser.test.assertTrue(
objWithMethods && objWithMethods.wrappedJSObject &&
objWithMethods.wrappedJSObject.objMethod instanceof ScriptFunction.wrappedJSObject,
"The callable property is accessible on the wrappedJSObject");
browser.test.assertEq("objMethodResult: p1", objWithMethods && objWithMethods.wrappedJSObject &&
objWithMethods.wrappedJSObject.objMethod("p1"),
"Got the expected result when calling the method on the wrappedJSObject");
return true;
},
});
});
}
async function userScript() {
const {assertTrue, notifyFinish, testAPIMethod} = this;
let result = testAPIMethod({
objProperty: "objPropertyValue",
objMethod(param) {
return `objMethodResult: ${param}`;
},
});
assertTrue(result === true, `userScript got an unexpected returned value: ${result}`);
notifyFinish();
}
await test_userScript_APIMethod({
userScript,
apiScript,
});
});
add_task(async function test_apiScript_method_throws_errors() {
function apiScript({notifyFinish}) {
let proxyTrapsCount = 0;
browser.userScripts.onBeforeScript.addListener(script => {
const scriptGlobals = {
Error: script.global.Error,
TypeError: script.global.TypeError,
Proxy: script.global.Proxy,
};
script.defineGlobals({
notifyFinish,
testAPIMethod(errorTestName, returnRejectedPromise) {
let err;
switch (errorTestName) {
case "apiScriptError":
err = new Error(`${errorTestName} message`);
break;
case "apiScriptThrowsPlainString":
err = `${errorTestName} message`;
break;
case "apiScriptThrowsNull":
err = null;
break;
case "userScriptError":
err = new scriptGlobals.Error(`${errorTestName} message`);
break;
case "userScriptTypeError":
err = new scriptGlobals.TypeError(`${errorTestName} message`);
break;
case "userScriptProxyObject":
let proxyTarget = script.export({
name: "ProxyObject", message: "ProxyObject message",
});
let proxyHandlers = script.export({
get(target, prop) {
proxyTrapsCount++;
switch (prop) {
case "name":
return "ProxyObjectGetName";
case "message":
return "ProxyObjectGetMessage";
}
return undefined;
},
getPrototypeOf() {
proxyTrapsCount++;
return scriptGlobals.TypeError;
},
});
err = new scriptGlobals.Proxy(proxyTarget, proxyHandlers);
break;
default:
browser.test.fail(`Unknown ${errorTestName} error testname`);
return undefined;
}
if (returnRejectedPromise) {
return Promise.reject(err);
}
throw err;
},
assertNoProxyTrapTriggered() {
browser.test.assertEq(0, proxyTrapsCount, "Proxy traps should not be triggered");
},
resetProxyTrapCounter() {
proxyTrapsCount = 0;
},
sendResults(results) {
browser.test.sendMessage("test-results", results);
},
});
});
}
async function userScript() {
const {
assertNoProxyTrapTriggered,
notifyFinish,
resetProxyTrapCounter,
sendResults,
testAPIMethod,
} = this;
let apiThrowResults = {};
let apiThrowTestCases = [
"apiScriptError",
"apiScriptThrowsPlainString",
"apiScriptThrowsNull",
"userScriptError",
"userScriptTypeError",
"userScriptProxyObject",
];
for (let errorTestName of apiThrowTestCases) {
try {
testAPIMethod(errorTestName);
} catch (err) {
// We expect that no proxy traps have been triggered by the WebExtensions internals.
if (errorTestName === "userScriptProxyObject") {
assertNoProxyTrapTriggered();
}
if (err instanceof Error) {
apiThrowResults[errorTestName] = {name: err.name, message: err.message};
} else {
apiThrowResults[errorTestName] = {
name: err && err.name,
message: err && err.message,
typeOf: typeof err,
value: err,
};
}
}
}
sendResults(apiThrowResults);
resetProxyTrapCounter();
let apiRejectsResults = {};
for (let errorTestName of apiThrowTestCases) {
try {
await testAPIMethod(errorTestName, true);
} catch (err) {
// We expect that no proxy traps have been triggered by the WebExtensions internals.
if (errorTestName === "userScriptProxyObject") {
assertNoProxyTrapTriggered();
}
if (err instanceof Error) {
apiRejectsResults[errorTestName] = {name: err.name, message: err.message};
} else {
apiRejectsResults[errorTestName] = {
name: err && err.name,
message: err && err.message,
typeOf: typeof err,
value: err,
};
}
}
}
sendResults(apiRejectsResults);
notifyFinish();
}
await test_userScript_APIMethod({
userScript,
apiScript,
async testFn({extension}) {
const expectedResults = {
// Any error not explicitly raised as a userScript objects or error instance is
// expected to be turned into a generic error message.
"apiScriptError": {name: "Error", message: "An unexpected apiScript error occurred"},
// When the api script throws a primitive value, we expect to receive it unmodified on
// the userScript side.
"apiScriptThrowsPlainString": {
typeOf: "string", value: "apiScriptThrowsPlainString message",
name: undefined, message: undefined,
},
"apiScriptThrowsNull": {
typeOf: "object", value: null,
name: undefined, message: undefined,
},
// Error messages that the apiScript has explicitly created as userScript's Error
// global instances are expected to be passing through unmodified.
"userScriptError": {name: "Error", message: "userScriptError message"},
"userScriptTypeError": {name: "TypeError", message: "userScriptTypeError message"},
// Error raised from the apiScript as userScript proxy objects are expected to
// be passing through unmodified.
"userScriptProxyObject": {
typeOf: "object", name: "ProxyObjectGetName", message: "ProxyObjectGetMessage",
},
};
info("Checking results from errors raised from an apiScript exported function");
const apiThrowResults = await extension.awaitMessage("test-results");
for (let [key, expected] of Object.entries(expectedResults)) {
Assert.deepEqual(apiThrowResults[key], expected,
`Got the expected error object for test case "${key}"`);
}
Assert.deepEqual(Object.keys(expectedResults).sort(),
Object.keys(apiThrowResults).sort(),
"the expected and actual test case names matches");
info("Checking expected results from errors raised from an apiScript exported function");
// Verify expected results from rejected promises returned from an apiScript exported function.
const apiThrowRejections = await extension.awaitMessage("test-results");
for (let [key, expected] of Object.entries(expectedResults)) {
Assert.deepEqual(apiThrowRejections[key], expected,
`Got the expected rejected object for test case "${key}"`);
}
Assert.deepEqual(Object.keys(expectedResults).sort(),
Object.keys(apiThrowRejections).sort(),
"the expected and actual test case names matches");
},
});
});
add_task(async function test_apiScript_method_ensure_xraywrapped_proxy_in_params() {
function apiScript(sharedTestAPIMethods) {
browser.userScripts.onBeforeScript.addListener(script => {
script.defineGlobals({
...sharedTestAPIMethods,
testAPIMethod(...args) {
// Proxies are opaque when wrapped in Xrays, and the proto of an opaque object
// is supposed to be Object.prototype.
browser.test.assertEq(
script.global.Object.prototype,
Object.getPrototypeOf(args[0]),
"Calling getPrototypeOf on the XrayWrapped proxy object doesn't run the proxy trap");
browser.test.assertTrue(Array.isArray(args[0]),
"Got an array object for the XrayWrapped proxy object param");
browser.test.assertEq(undefined, args[0].length,
"XrayWrappers deny access to the length property");
browser.test.assertEq(undefined, args[0][0],
"Got the expected item in the array object");
return true;
},
});
});
}
async function userScript() {
const {
assertTrue,
notifyFinish,
testAPIMethod,
} = this;
let proxy = new Proxy(["expectedArrayValue"], {
getPrototypeOf() {
throw new Error("Proxy's getPrototypeOf trap");
},
get(target, prop, receiver) {
throw new Error("Proxy's get trap");
},
});
let result = testAPIMethod(proxy);
assertTrue(result, `userScript got an unexpected returned value: ${result}`);
notifyFinish();
}
await test_userScript_APIMethod({
userScript,
apiScript,
});
});
add_task(async function test_apiScript_method_return_proxy_object() {
function apiScript(sharedTestAPIMethods) {
let proxyTrapsCount = 0;
let scriptTrapsCount = 0;
browser.userScripts.onBeforeScript.addListener(script => {
script.defineGlobals({
...sharedTestAPIMethods,
testAPIMethodError() {
return new Proxy(["expectedArrayValue"], {
getPrototypeOf(target) {
proxyTrapsCount++;
return Object.getPrototypeOf(target);
},
});
},
testAPIMethodOk() {
return new script.global.Proxy(
script.export(["expectedArrayValue"]),
script.export({
getPrototypeOf(target) {
scriptTrapsCount++;
return script.global.Object.getPrototypeOf(target);
},
}));
},
assertNoProxyTrapTriggered() {
browser.test.assertEq(0, proxyTrapsCount, "Proxy traps should not be triggered");
},
assertScriptProxyTrapsCount(expected) {
browser.test.assertEq(expected, scriptTrapsCount, "Script Proxy traps should have been triggered");
},
});
});
}
async function userScript() {
const {
assertTrue,
assertNoProxyTrapTriggered,
assertScriptProxyTrapsCount,
notifyFinish,
testAPIMethodError,
testAPIMethodOk,
} = this;
let error;
try {
let result = testAPIMethodError();
notifyFinish(`Unexpected returned value while expecting error: ${result}`);
return;
} catch (err) {
error = err;
}
assertTrue(error && error.message.includes("Return value not accessible to the userScript"),
`Got an unexpected error message: ${error}`);
error = undefined;
try {
let result = testAPIMethodOk();
assertScriptProxyTrapsCount(0);
if (!(result instanceof Array)) {
notifyFinish(`Got an unexpected result: ${result}`);
return;
}
assertScriptProxyTrapsCount(1);
} catch (err) {
error = err;
}
assertTrue(!error, `Got an unexpected error: ${error}`);
assertNoProxyTrapTriggered();
notifyFinish();
}
await test_userScript_APIMethod({
userScript,
apiScript,
});
});
add_task(async function test_apiScript_returns_functions() {
function apiScript(sharedTestAPIMethods) {
browser.userScripts.onBeforeScript.addListener(script => {
script.defineGlobals({
...sharedTestAPIMethods,
testAPIReturnsFunction() {
// Return a function with provides the same kind of behavior
// of the API methods exported as globals.
return script.export(() => window);
},
testAPIReturnsObjWithMethod() {
return script.export({
getWindow() {
return window;
},
});
},
});
});
}
async function userScript() {
const {
assertTrue,
notifyFinish,
testAPIReturnsFunction,
testAPIReturnsObjWithMethod,
} = this;
let resultFn = testAPIReturnsFunction();
assertTrue(typeof resultFn === "function",
`userScript got an unexpected returned value: ${typeof resultFn}`);
let fnRes = resultFn();
assertTrue(fnRes === window,
`Got an unexpected value from the returned function: ${fnRes}`);
let resultObj = testAPIReturnsObjWithMethod();
let actualTypeof = resultObj && typeof resultObj.getWindow;
assertTrue(actualTypeof === "function",
`Returned object does not have the expected getWindow method: ${actualTypeof}`);
let methodRes = resultObj.getWindow();
assertTrue(methodRes === window,
`Got an unexpected value from the returned method: ${methodRes}`);
notifyFinish();
}
await test_userScript_APIMethod({
userScript,
apiScript,
});
});
add_task(async function test_apiScript_method_clone_non_subsumed_returned_values() {
function apiScript(sharedTestAPIMethods) {
browser.userScripts.onBeforeScript.addListener(script => {
script.defineGlobals({
...sharedTestAPIMethods,
testAPIMethodReturnOk() {
return script.export({
objKey1: {
nestedProp: "nestedvalue",
},
window,
});
},
testAPIMethodExplicitlyClonedError() {
let result = script.export({apiScopeObject: undefined});
browser.test.assertThrows(
() => {
result.apiScopeObject = {disallowedProp: "disallowedValue"};
},
/Not allowed to define cross-origin object as property on .* XrayWrapper/,
"Assigning a property to a xRayWrapper is expected to throw");
// Let the exception to be raised, so that we check that the actual underlying
// error message is not leaking in the userScript (replaced by the generic
// "An unexpected apiScript error occurred" error message).
result.apiScopeObject = {disallowedProp: "disallowedValue"};
},
});
});
}
async function userScript() {
const {
assertTrue,
notifyFinish,
testAPIMethodReturnOk,
testAPIMethodExplicitlyClonedError,
} = this;
let result = testAPIMethodReturnOk();
assertTrue(result && ("objKey1" in result) && result.objKey1.nestedProp === "nestedvalue",
`userScript got an unexpected returned value: ${result}`);
assertTrue(result.window === window,
`userScript should have access to the window property: ${result.window}`);
let error;
try {
result = testAPIMethodExplicitlyClonedError();
notifyFinish(`Unexpected returned value while expecting error: ${result}`);
return;
} catch (err) {
error = err;
}
// We expect the generic "unexpected apiScript error occurred" to be raised to the
// userScript code.
assertTrue(error && error.message.includes("An unexpected apiScript error occurred"),
`Got an unexpected error message: ${error}`);
notifyFinish();
}
await test_userScript_APIMethod({
userScript,
apiScript,
});
});
add_task(async function test_apiScript_method_export_primitive_types() {
function apiScript(sharedTestAPIMethods) {
browser.userScripts.onBeforeScript.addListener(script => {
script.defineGlobals({
...sharedTestAPIMethods,
testAPIMethod(typeToExport) {
switch (typeToExport) {
case "boolean": return script.export(true);
case "number": return script.export(123);
case "string": return script.export("a string");
case "symbol": return script.export(Symbol("a symbol"));
}
return undefined;
},
});
});
}
async function userScript() {
const {assertTrue, notifyFinish, testAPIMethod} = this;
let v = testAPIMethod("boolean");
assertTrue(v === true, `Should export a boolean`);
v = testAPIMethod("number");
assertTrue(v === 123, `Should export a number`);
v = testAPIMethod("string");
assertTrue(v === "a string", `Should export a string`);
v = testAPIMethod("symbol");
assertTrue(typeof v === "symbol", `Should export a symbol`);
notifyFinish();
}
await test_userScript_APIMethod({
userScript,
apiScript,
});
});
add_task(async function test_apiScript_method_avoid_unnecessary_params_cloning() {
function apiScript(sharedTestAPIMethods) {
browser.userScripts.onBeforeScript.addListener(script => {
script.defineGlobals({
...sharedTestAPIMethods,
testAPIMethodReturnsParam(param) {
return param;
},
testAPIMethodReturnsUnwrappedParam(param) {
return param.wrappedJSObject;
},
});
});
}
async function userScript() {
const {
assertTrue,
notifyFinish,
testAPIMethodReturnsParam,
testAPIMethodReturnsUnwrappedParam,
} = this;
let obj = {};
let result = testAPIMethodReturnsParam(obj);
assertTrue(result === obj,
`Expect returned value to be strictly equal to the API method parameter`);
result = testAPIMethodReturnsUnwrappedParam(obj);
assertTrue(result === obj,
`Expect returned value to be strictly equal to the unwrapped API method parameter`);
notifyFinish();
}
await test_userScript_APIMethod({
userScript,
apiScript,
});
});
add_task(async function test_apiScript_method_export_sparse_arrays() {
function apiScript(sharedTestAPIMethods) {
browser.userScripts.onBeforeScript.addListener(script => {
script.defineGlobals({
...sharedTestAPIMethods,
testAPIMethod() {
const sparseArray = [];
sparseArray[3] = "third-element";
sparseArray[5] = "fifth-element";
return script.export(sparseArray);
},
});
});
}
async function userScript() {
const {assertTrue, notifyFinish, testAPIMethod} = this;
const result = testAPIMethod(window, document);
// We expect the returned value to be the uncloneable window object.
assertTrue(result && result.length === 6,
`the returned value should be an array of the expected length: ${result}`);
assertTrue(result[3] === "third-element",
`the third array element should have the expected value: ${result[3]}`);
assertTrue(result[5] === "fifth-element",
`the fifth array element should have the expected value: ${result[5]}`);
assertTrue(result[0] === undefined,
`the first array element should have the expected value: ${result[0]}`);
assertTrue(!("0" in result), "Holey array should still be holey");
notifyFinish();
}
await test_userScript_APIMethod({
userScript,
apiScript,
});
});
// This test verify that a cached script is still able to catch the document
// while it is still loading (when we do not block the document parsing as
// we do for a non cached script).

Просмотреть файл

@ -0,0 +1,907 @@
"use strict";
const {
createAppInfo,
} = AddonTestUtils;
AddonTestUtils.init(this);
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "49");
const server = createHttpServer();
server.registerDirectory("/data/", do_get_file("data"));
const BASE_URL = `http://localhost:${server.identity.primaryPort}/data`;
// A small utility function used to test the expected behaviors of the userScripts API method
// wrapper.
async function test_userScript_APIMethod({
apiScript, userScript, userScriptMetadata, testFn,
runtimeMessageListener,
}) {
async function backgroundScript(userScriptFn, scriptMetadata, messageListener) {
await browser.userScripts.register({
js: [{
code: `(${userScriptFn})();`,
}],
runAt: "document_end",
matches: ["http://localhost/*/file_sample.html"],
scriptMetadata,
});
if (messageListener) {
browser.runtime.onMessage.addListener(messageListener);
}
browser.test.sendMessage("background-ready");
}
function notifyFinish(failureReason) {
browser.test.assertEq(undefined, failureReason, "should be completed without errors");
browser.test.sendMessage("test_userScript_APIMethod:done");
}
function assertTrue(val, message) {
browser.test.assertTrue(val, message);
if (!val) {
browser.test.sendMessage("test_userScript_APIMethod:done");
throw message;
}
}
let extension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: [
"http://localhost/*/file_sample.html",
],
user_scripts: {
api_script: "api-script.js",
},
},
// Defines a background script that receives all the needed test parameters.
background: `
const metadata = ${JSON.stringify(userScriptMetadata)};
(${backgroundScript})(${userScript}, metadata, ${runtimeMessageListener})
`,
files: {
"api-script.js": `(${apiScript})({
assertTrue: ${assertTrue},
notifyFinish: ${notifyFinish}
})`,
},
});
// Load a page in a content process, register the user script and then load a
// new page in the existing content process.
let url = `${BASE_URL}/file_sample.html`;
let contentPage = await ExtensionTestUtils.loadContentPage(`about:blank`);
await extension.startup();
await extension.awaitMessage("background-ready");
await contentPage.loadURL(url);
// Run any additional test-specific assertions.
if (testFn) {
await testFn({extension, contentPage, url});
}
await extension.awaitMessage("test_userScript_APIMethod:done");
await extension.unload();
await contentPage.close();
}
add_task(async function test_apiScript_exports_simple_sync_method() {
function apiScript(sharedTestAPIMethods) {
browser.userScripts.onBeforeScript.addListener(script => {
const scriptMetadata = script.metadata;
script.defineGlobals({
...sharedTestAPIMethods,
testAPIMethod(stringParam, numberParam, boolParam, nullParam, undefinedParam, arrayParam) {
browser.test.assertEq("test-user-script-exported-apis", scriptMetadata.name,
"Got the expected value for a string scriptMetadata property");
browser.test.assertEq(null, scriptMetadata.nullProperty,
"Got the expected value for a null scriptMetadata property");
browser.test.assertTrue(scriptMetadata.arrayProperty &&
scriptMetadata.arrayProperty.length === 1 &&
scriptMetadata.arrayProperty[0] === "el1",
"Got the expected value for an array scriptMetadata property");
browser.test.assertTrue(scriptMetadata.objectProperty &&
scriptMetadata.objectProperty.nestedProp === "nestedValue",
"Got the expected value for an object scriptMetadata property");
browser.test.assertEq("param1", stringParam, "Got the expected string parameter value");
browser.test.assertEq(123, numberParam, "Got the expected number parameter value");
browser.test.assertEq(true, boolParam, "Got the expected boolean parameter value");
browser.test.assertEq(null, nullParam, "Got the expected null parameter value");
browser.test.assertEq(undefined, undefinedParam, "Got the expected undefined parameter value");
browser.test.assertEq(3, arrayParam.length, "Got the expected length on the array param");
browser.test.assertTrue(arrayParam.includes(1),
"Got the expected result when calling arrayParam.includes");
return "returned_value";
},
});
});
}
function userScript() {
const {assertTrue, notifyFinish, testAPIMethod} = this;
// Redefine the includes method on the Array prototype, to explicitly verify that the method
// redefined in the userScript is not used when accessing arrayParam.includes from the API script.
Array.prototype.includes = () => { // eslint-disable-line no-extend-native
throw new Error("Unexpected prototype leakage");
};
const arrayParam = new Array(1, 2, 3); // eslint-disable-line no-array-constructor
const result = testAPIMethod("param1", 123, true, null, undefined, arrayParam);
assertTrue(result === "returned_value", `userScript got an unexpected result value: ${result}`);
notifyFinish();
}
const userScriptMetadata = {
name: "test-user-script-exported-apis",
arrayProperty: ["el1"],
objectProperty: {nestedProp: "nestedValue"},
nullProperty: null,
};
await test_userScript_APIMethod({
userScript,
apiScript,
userScriptMetadata,
});
});
add_task(async function test_apiScript_async_method() {
function apiScript(sharedTestAPIMethods) {
browser.userScripts.onBeforeScript.addListener(script => {
script.defineGlobals({
...sharedTestAPIMethods,
testAPIMethod(param, cb, cb2, objWithCb) {
browser.test.assertEq("function", typeof cb, "Got a callback function parameter");
browser.test.assertTrue(cb === cb2, "Got the same cloned function for the same function parameter");
browser.runtime.sendMessage(param).then(bgPageRes => {
const cbResult = cb(script.export(bgPageRes));
browser.test.sendMessage("user-script-callback-return", cbResult);
});
return "resolved_value";
},
});
});
}
async function userScript() {
// Redefine Promise to verify that it doesn't break the WebExtensions internals
// that are going to use them.
const {Promise} = this;
Promise.resolve = function() {
throw new Error("Promise.resolve poisoning");
};
this.Promise = function() {
throw new Error("Promise constructor poisoning");
};
const {assertTrue, notifyFinish, testAPIMethod} = this;
const cb = (cbParam) => {
return `callback param: ${JSON.stringify(cbParam)}`;
};
const cb2 = cb;
const asyncAPIResult = await testAPIMethod("param3", cb, cb2);
assertTrue(asyncAPIResult === "resolved_value",
`userScript got an unexpected resolved value: ${asyncAPIResult}`);
notifyFinish();
}
async function runtimeMessageListener(param) {
if (param !== "param3") {
browser.test.fail(`Got an unexpected message: ${param}`);
}
return {bgPageReply: true};
}
await test_userScript_APIMethod({
userScript,
apiScript,
runtimeMessageListener,
async testFn({extension}) {
const res = await extension.awaitMessage("user-script-callback-return");
equal(res, `callback param: ${JSON.stringify({bgPageReply: true})}`,
"Got the expected userScript callback return value");
},
});
});
add_task(async function test_apiScript_method_with_webpage_objects_params() {
function apiScript(sharedTestAPIMethods) {
browser.userScripts.onBeforeScript.addListener(script => {
script.defineGlobals({
...sharedTestAPIMethods,
testAPIMethod(windowParam, documentParam) {
browser.test.assertEq(window, windowParam, "Got a reference to the native window as first param");
browser.test.assertEq(window.document, documentParam,
"Got a reference to the native document as second param");
// Return an uncloneable webpage object, which checks that if the returned object is from a principal
// that is subsumed by the userScript sandbox principal, it is returned without being cloned.
return windowParam;
},
});
});
}
async function userScript() {
const {assertTrue, notifyFinish, testAPIMethod} = this;
const result = testAPIMethod(window, document);
// We expect the returned value to be the uncloneable window object.
assertTrue(result === window,
`userScript got an unexpected returned value: ${result}`);
notifyFinish();
}
await test_userScript_APIMethod({
userScript,
apiScript,
});
});
add_task(async function test_apiScript_method_got_param_with_methods() {
function apiScript(sharedTestAPIMethods) {
browser.userScripts.onBeforeScript.addListener(script => {
const scriptGlobal = script.global;
const ScriptFunction = scriptGlobal.Function;
script.defineGlobals({
...sharedTestAPIMethods,
testAPIMethod(objWithMethods) {
browser.test.assertEq("objPropertyValue", objWithMethods && objWithMethods.objProperty,
"Got the expected property on the object passed as a parameter");
browser.test.assertEq(undefined, typeof objWithMethods && objWithMethods.objMethod,
"XrayWrapper should deny access to a callable property");
browser.test.assertTrue(
objWithMethods && objWithMethods.wrappedJSObject &&
objWithMethods.wrappedJSObject.objMethod instanceof ScriptFunction.wrappedJSObject,
"The callable property is accessible on the wrappedJSObject");
browser.test.assertEq("objMethodResult: p1", objWithMethods && objWithMethods.wrappedJSObject &&
objWithMethods.wrappedJSObject.objMethod("p1"),
"Got the expected result when calling the method on the wrappedJSObject");
return true;
},
});
});
}
async function userScript() {
const {assertTrue, notifyFinish, testAPIMethod} = this;
let result = testAPIMethod({
objProperty: "objPropertyValue",
objMethod(param) {
return `objMethodResult: ${param}`;
},
});
assertTrue(result === true, `userScript got an unexpected returned value: ${result}`);
notifyFinish();
}
await test_userScript_APIMethod({
userScript,
apiScript,
});
});
add_task(async function test_apiScript_method_throws_errors() {
function apiScript({notifyFinish}) {
let proxyTrapsCount = 0;
browser.userScripts.onBeforeScript.addListener(script => {
const scriptGlobals = {
Error: script.global.Error,
TypeError: script.global.TypeError,
Proxy: script.global.Proxy,
};
script.defineGlobals({
notifyFinish,
testAPIMethod(errorTestName, returnRejectedPromise) {
let err;
switch (errorTestName) {
case "apiScriptError":
err = new Error(`${errorTestName} message`);
break;
case "apiScriptThrowsPlainString":
err = `${errorTestName} message`;
break;
case "apiScriptThrowsNull":
err = null;
break;
case "userScriptError":
err = new scriptGlobals.Error(`${errorTestName} message`);
break;
case "userScriptTypeError":
err = new scriptGlobals.TypeError(`${errorTestName} message`);
break;
case "userScriptProxyObject":
let proxyTarget = script.export({
name: "ProxyObject", message: "ProxyObject message",
});
let proxyHandlers = script.export({
get(target, prop) {
proxyTrapsCount++;
switch (prop) {
case "name":
return "ProxyObjectGetName";
case "message":
return "ProxyObjectGetMessage";
}
return undefined;
},
getPrototypeOf() {
proxyTrapsCount++;
return scriptGlobals.TypeError;
},
});
err = new scriptGlobals.Proxy(proxyTarget, proxyHandlers);
break;
default:
browser.test.fail(`Unknown ${errorTestName} error testname`);
return undefined;
}
if (returnRejectedPromise) {
return Promise.reject(err);
}
throw err;
},
assertNoProxyTrapTriggered() {
browser.test.assertEq(0, proxyTrapsCount, "Proxy traps should not be triggered");
},
resetProxyTrapCounter() {
proxyTrapsCount = 0;
},
sendResults(results) {
browser.test.sendMessage("test-results", results);
},
});
});
}
async function userScript() {
const {
assertNoProxyTrapTriggered,
notifyFinish,
resetProxyTrapCounter,
sendResults,
testAPIMethod,
} = this;
let apiThrowResults = {};
let apiThrowTestCases = [
"apiScriptError",
"apiScriptThrowsPlainString",
"apiScriptThrowsNull",
"userScriptError",
"userScriptTypeError",
"userScriptProxyObject",
];
for (let errorTestName of apiThrowTestCases) {
try {
testAPIMethod(errorTestName);
} catch (err) {
// We expect that no proxy traps have been triggered by the WebExtensions internals.
if (errorTestName === "userScriptProxyObject") {
assertNoProxyTrapTriggered();
}
if (err instanceof Error) {
apiThrowResults[errorTestName] = {name: err.name, message: err.message};
} else {
apiThrowResults[errorTestName] = {
name: err && err.name,
message: err && err.message,
typeOf: typeof err,
value: err,
};
}
}
}
sendResults(apiThrowResults);
resetProxyTrapCounter();
let apiRejectsResults = {};
for (let errorTestName of apiThrowTestCases) {
try {
await testAPIMethod(errorTestName, true);
} catch (err) {
// We expect that no proxy traps have been triggered by the WebExtensions internals.
if (errorTestName === "userScriptProxyObject") {
assertNoProxyTrapTriggered();
}
if (err instanceof Error) {
apiRejectsResults[errorTestName] = {name: err.name, message: err.message};
} else {
apiRejectsResults[errorTestName] = {
name: err && err.name,
message: err && err.message,
typeOf: typeof err,
value: err,
};
}
}
}
sendResults(apiRejectsResults);
notifyFinish();
}
await test_userScript_APIMethod({
userScript,
apiScript,
async testFn({extension}) {
const expectedResults = {
// Any error not explicitly raised as a userScript objects or error instance is
// expected to be turned into a generic error message.
"apiScriptError": {name: "Error", message: "An unexpected apiScript error occurred"},
// When the api script throws a primitive value, we expect to receive it unmodified on
// the userScript side.
"apiScriptThrowsPlainString": {
typeOf: "string", value: "apiScriptThrowsPlainString message",
name: undefined, message: undefined,
},
"apiScriptThrowsNull": {
typeOf: "object", value: null,
name: undefined, message: undefined,
},
// Error messages that the apiScript has explicitly created as userScript's Error
// global instances are expected to be passing through unmodified.
"userScriptError": {name: "Error", message: "userScriptError message"},
"userScriptTypeError": {name: "TypeError", message: "userScriptTypeError message"},
// Error raised from the apiScript as userScript proxy objects are expected to
// be passing through unmodified.
"userScriptProxyObject": {
typeOf: "object", name: "ProxyObjectGetName", message: "ProxyObjectGetMessage",
},
};
info("Checking results from errors raised from an apiScript exported function");
const apiThrowResults = await extension.awaitMessage("test-results");
for (let [key, expected] of Object.entries(expectedResults)) {
Assert.deepEqual(apiThrowResults[key], expected,
`Got the expected error object for test case "${key}"`);
}
Assert.deepEqual(Object.keys(expectedResults).sort(),
Object.keys(apiThrowResults).sort(),
"the expected and actual test case names matches");
info("Checking expected results from errors raised from an apiScript exported function");
// Verify expected results from rejected promises returned from an apiScript exported function.
const apiThrowRejections = await extension.awaitMessage("test-results");
for (let [key, expected] of Object.entries(expectedResults)) {
Assert.deepEqual(apiThrowRejections[key], expected,
`Got the expected rejected object for test case "${key}"`);
}
Assert.deepEqual(Object.keys(expectedResults).sort(),
Object.keys(apiThrowRejections).sort(),
"the expected and actual test case names matches");
},
});
});
add_task(async function test_apiScript_method_ensure_xraywrapped_proxy_in_params() {
function apiScript(sharedTestAPIMethods) {
browser.userScripts.onBeforeScript.addListener(script => {
script.defineGlobals({
...sharedTestAPIMethods,
testAPIMethod(...args) {
// Proxies are opaque when wrapped in Xrays, and the proto of an opaque object
// is supposed to be Object.prototype.
browser.test.assertEq(
script.global.Object.prototype,
Object.getPrototypeOf(args[0]),
"Calling getPrototypeOf on the XrayWrapped proxy object doesn't run the proxy trap");
browser.test.assertTrue(Array.isArray(args[0]),
"Got an array object for the XrayWrapped proxy object param");
browser.test.assertEq(undefined, args[0].length,
"XrayWrappers deny access to the length property");
browser.test.assertEq(undefined, args[0][0],
"Got the expected item in the array object");
return true;
},
});
});
}
async function userScript() {
const {
assertTrue,
notifyFinish,
testAPIMethod,
} = this;
let proxy = new Proxy(["expectedArrayValue"], {
getPrototypeOf() {
throw new Error("Proxy's getPrototypeOf trap");
},
get(target, prop, receiver) {
throw new Error("Proxy's get trap");
},
});
let result = testAPIMethod(proxy);
assertTrue(result, `userScript got an unexpected returned value: ${result}`);
notifyFinish();
}
await test_userScript_APIMethod({
userScript,
apiScript,
});
});
add_task(async function test_apiScript_method_return_proxy_object() {
function apiScript(sharedTestAPIMethods) {
let proxyTrapsCount = 0;
let scriptTrapsCount = 0;
browser.userScripts.onBeforeScript.addListener(script => {
script.defineGlobals({
...sharedTestAPIMethods,
testAPIMethodError() {
return new Proxy(["expectedArrayValue"], {
getPrototypeOf(target) {
proxyTrapsCount++;
return Object.getPrototypeOf(target);
},
});
},
testAPIMethodOk() {
return new script.global.Proxy(
script.export(["expectedArrayValue"]),
script.export({
getPrototypeOf(target) {
scriptTrapsCount++;
return script.global.Object.getPrototypeOf(target);
},
}));
},
assertNoProxyTrapTriggered() {
browser.test.assertEq(0, proxyTrapsCount, "Proxy traps should not be triggered");
},
assertScriptProxyTrapsCount(expected) {
browser.test.assertEq(expected, scriptTrapsCount, "Script Proxy traps should have been triggered");
},
});
});
}
async function userScript() {
const {
assertTrue,
assertNoProxyTrapTriggered,
assertScriptProxyTrapsCount,
notifyFinish,
testAPIMethodError,
testAPIMethodOk,
} = this;
let error;
try {
let result = testAPIMethodError();
notifyFinish(`Unexpected returned value while expecting error: ${result}`);
return;
} catch (err) {
error = err;
}
assertTrue(error && error.message.includes("Return value not accessible to the userScript"),
`Got an unexpected error message: ${error}`);
error = undefined;
try {
let result = testAPIMethodOk();
assertScriptProxyTrapsCount(0);
if (!(result instanceof Array)) {
notifyFinish(`Got an unexpected result: ${result}`);
return;
}
assertScriptProxyTrapsCount(1);
} catch (err) {
error = err;
}
assertTrue(!error, `Got an unexpected error: ${error}`);
assertNoProxyTrapTriggered();
notifyFinish();
}
await test_userScript_APIMethod({
userScript,
apiScript,
});
});
add_task(async function test_apiScript_returns_functions() {
function apiScript(sharedTestAPIMethods) {
browser.userScripts.onBeforeScript.addListener(script => {
script.defineGlobals({
...sharedTestAPIMethods,
testAPIReturnsFunction() {
// Return a function with provides the same kind of behavior
// of the API methods exported as globals.
return script.export(() => window);
},
testAPIReturnsObjWithMethod() {
return script.export({
getWindow() {
return window;
},
});
},
});
});
}
async function userScript() {
const {
assertTrue,
notifyFinish,
testAPIReturnsFunction,
testAPIReturnsObjWithMethod,
} = this;
let resultFn = testAPIReturnsFunction();
assertTrue(typeof resultFn === "function",
`userScript got an unexpected returned value: ${typeof resultFn}`);
let fnRes = resultFn();
assertTrue(fnRes === window,
`Got an unexpected value from the returned function: ${fnRes}`);
let resultObj = testAPIReturnsObjWithMethod();
let actualTypeof = resultObj && typeof resultObj.getWindow;
assertTrue(actualTypeof === "function",
`Returned object does not have the expected getWindow method: ${actualTypeof}`);
let methodRes = resultObj.getWindow();
assertTrue(methodRes === window,
`Got an unexpected value from the returned method: ${methodRes}`);
notifyFinish();
}
await test_userScript_APIMethod({
userScript,
apiScript,
});
});
add_task(async function test_apiScript_method_clone_non_subsumed_returned_values() {
function apiScript(sharedTestAPIMethods) {
browser.userScripts.onBeforeScript.addListener(script => {
script.defineGlobals({
...sharedTestAPIMethods,
testAPIMethodReturnOk() {
return script.export({
objKey1: {
nestedProp: "nestedvalue",
},
window,
});
},
testAPIMethodExplicitlyClonedError() {
let result = script.export({apiScopeObject: undefined});
browser.test.assertThrows(
() => {
result.apiScopeObject = {disallowedProp: "disallowedValue"};
},
/Not allowed to define cross-origin object as property on .* XrayWrapper/,
"Assigning a property to a xRayWrapper is expected to throw");
// Let the exception to be raised, so that we check that the actual underlying
// error message is not leaking in the userScript (replaced by the generic
// "An unexpected apiScript error occurred" error message).
result.apiScopeObject = {disallowedProp: "disallowedValue"};
},
});
});
}
async function userScript() {
const {
assertTrue,
notifyFinish,
testAPIMethodReturnOk,
testAPIMethodExplicitlyClonedError,
} = this;
let result = testAPIMethodReturnOk();
assertTrue(result && ("objKey1" in result) && result.objKey1.nestedProp === "nestedvalue",
`userScript got an unexpected returned value: ${result}`);
assertTrue(result.window === window,
`userScript should have access to the window property: ${result.window}`);
let error;
try {
result = testAPIMethodExplicitlyClonedError();
notifyFinish(`Unexpected returned value while expecting error: ${result}`);
return;
} catch (err) {
error = err;
}
// We expect the generic "unexpected apiScript error occurred" to be raised to the
// userScript code.
assertTrue(error && error.message.includes("An unexpected apiScript error occurred"),
`Got an unexpected error message: ${error}`);
notifyFinish();
}
await test_userScript_APIMethod({
userScript,
apiScript,
});
});
add_task(async function test_apiScript_method_export_primitive_types() {
function apiScript(sharedTestAPIMethods) {
browser.userScripts.onBeforeScript.addListener(script => {
script.defineGlobals({
...sharedTestAPIMethods,
testAPIMethod(typeToExport) {
switch (typeToExport) {
case "boolean": return script.export(true);
case "number": return script.export(123);
case "string": return script.export("a string");
case "symbol": return script.export(Symbol("a symbol"));
}
return undefined;
},
});
});
}
async function userScript() {
const {assertTrue, notifyFinish, testAPIMethod} = this;
let v = testAPIMethod("boolean");
assertTrue(v === true, `Should export a boolean`);
v = testAPIMethod("number");
assertTrue(v === 123, `Should export a number`);
v = testAPIMethod("string");
assertTrue(v === "a string", `Should export a string`);
v = testAPIMethod("symbol");
assertTrue(typeof v === "symbol", `Should export a symbol`);
notifyFinish();
}
await test_userScript_APIMethod({
userScript,
apiScript,
});
});
add_task(async function test_apiScript_method_avoid_unnecessary_params_cloning() {
function apiScript(sharedTestAPIMethods) {
browser.userScripts.onBeforeScript.addListener(script => {
script.defineGlobals({
...sharedTestAPIMethods,
testAPIMethodReturnsParam(param) {
return param;
},
testAPIMethodReturnsUnwrappedParam(param) {
return param.wrappedJSObject;
},
});
});
}
async function userScript() {
const {
assertTrue,
notifyFinish,
testAPIMethodReturnsParam,
testAPIMethodReturnsUnwrappedParam,
} = this;
let obj = {};
let result = testAPIMethodReturnsParam(obj);
assertTrue(result === obj,
`Expect returned value to be strictly equal to the API method parameter`);
result = testAPIMethodReturnsUnwrappedParam(obj);
assertTrue(result === obj,
`Expect returned value to be strictly equal to the unwrapped API method parameter`);
notifyFinish();
}
await test_userScript_APIMethod({
userScript,
apiScript,
});
});
add_task(async function test_apiScript_method_export_sparse_arrays() {
function apiScript(sharedTestAPIMethods) {
browser.userScripts.onBeforeScript.addListener(script => {
script.defineGlobals({
...sharedTestAPIMethods,
testAPIMethod() {
const sparseArray = [];
sparseArray[3] = "third-element";
sparseArray[5] = "fifth-element";
return script.export(sparseArray);
},
});
});
}
async function userScript() {
const {assertTrue, notifyFinish, testAPIMethod} = this;
const result = testAPIMethod(window, document);
// We expect the returned value to be the uncloneable window object.
assertTrue(result && result.length === 6,
`the returned value should be an array of the expected length: ${result}`);
assertTrue(result[3] === "third-element",
`the third array element should have the expected value: ${result[3]}`);
assertTrue(result[5] === "fifth-element",
`the fifth array element should have the expected value: ${result[5]}`);
assertTrue(result[0] === undefined,
`the first array element should have the expected value: ${result[0]}`);
assertTrue(!("0" in result), "Holey array should still be holey");
notifyFinish();
}
await test_userScript_APIMethod({
userScript,
apiScript,
});
});

Просмотреть файл

@ -131,7 +131,7 @@ skip-if = os == "android"
[test_ext_unload_frame.js]
skip-if = true # Too frequent intermittent failures
[test_ext_userScripts.js]
skip-if = os == "android" && debug # Bug 1512741
[test_ext_userScripts_exports.js]
[test_ext_userScripts_telemetry.js]
[test_ext_webRequest_auth.js]
skip-if = os == "android" && debug

Просмотреть файл

@ -31,6 +31,7 @@ support-files =
[test_nocache.js]
[test_big_icon.js]
skip-if = (os == "win" && processor == "x86_64" && !debug) # Bug 1496191
[test_bug930456.js]
[test_bug930456_child.js]
[test_engine_set_alias.js]

Просмотреть файл

@ -313,7 +313,7 @@ const BaseControlMixin = Base => {
};
MozElements.BaseControl = BaseControlMixin(MozXULElement);
const BaseTextMixin = Base => class extends Base {
const BaseTextMixin = Base => class extends BaseControlMixin(Base) {
set label(val) {
this.setAttribute("label", val);
return val;

Просмотреть файл

@ -29,6 +29,7 @@
testMixin();
testBaseControl();
testBaseControlMixin();
testBaseText();
testParseXULToFragment();
testInherits();
await testCustomInterface();
@ -63,6 +64,14 @@
ok("disabled" in HTMLSpanBaseControl.prototype, "Mixed in class prototype contains base control attributes");
}
function testBaseText() {
ok(MozElements.BaseText, "BaseText exists");
ok("label" in MozElements.BaseText.prototype,
"BaseText prototype inherits BaseText attributes");
ok("disabled" in MozElements.BaseText.prototype,
"BaseText prototype inherits BaseControl attributes");
}
function testParseXULToFragment() {
ok(MozXULElement.parseXULToFragment, "parseXULToFragment helper exists");

Просмотреть файл

@ -173,7 +173,7 @@
<content>
<xul:hbox class="menu-iconic-left" align="center" pack="center"
xbl:inherits="selected,_moz-menuactive,disabled,checked">
<xul:image class="menu-iconic-icon" xbl:inherits="src=image,triggeringprincipal=iconloadingprincipal,validate,src"/>
<xul:image class="menu-iconic-icon" xbl:inherits="src=image,triggeringprincipal=iconloadingprincipal,validate"/>
</xul:hbox>
<xul:label class="menu-iconic-text" flex="1" xbl:inherits="value=label,accesskey,crop,highlightable" crop="right"/>
<xul:label class="menu-iconic-highlightable-text" xbl:inherits="xbl:text=label,crop,accesskey,highlightable" crop="right"/>
@ -188,7 +188,7 @@
<content>
<xul:hbox class="menu-iconic-left" align="center" pack="center"
xbl:inherits="selected,disabled,checked">
<xul:image class="menu-iconic-icon" xbl:inherits="src=image,validate,src"/>
<xul:image class="menu-iconic-icon" xbl:inherits="src=image,validate"/>
</xul:hbox>
<xul:label class="menu-iconic-text" flex="1" xbl:inherits="value=label,accesskey,crop,highlightable" crop="right"/>
<xul:label class="menu-iconic-highlightable-text" xbl:inherits="xbl:text=label,crop,accesskey,highlightable" crop="right"/>

Просмотреть файл

@ -24,6 +24,7 @@ encoding_glue = { path = "../../../../intl/encoding_glue" }
audioipc-client = { path = "../../../../media/audioipc/client", optional = true }
audioipc-server = { path = "../../../../media/audioipc/server", optional = true }
u2fhid = { path = "../../../../dom/webauthn/u2f-hid-rs" }
gkrust_utils = { path = "../../../../xpcom/rust/gkrust_utils" }
rsdparsa_capi = { path = "../../../../media/webrtc/signaling/src/sdp/rsdparsa_capi" }
# We have these to enforce common feature sets for said crates.
log = {version = "0.4", features = ["release_max_level_info"]}

Просмотреть файл

@ -29,6 +29,7 @@ extern crate audioipc_client;
extern crate audioipc_server;
extern crate env_logger;
extern crate u2fhid;
extern crate gkrust_utils;
extern crate log;
extern crate cosec;
extern crate rsdparsa_capi;

Просмотреть файл

@ -1901,7 +1901,7 @@ var AddonManagerInternal = {
this.installNotifyObservers("addon-install-disabled", topBrowser,
aInstallingPrincipal.URI, aInstall);
return;
} else if (!aBrowser.contentPrincipal || !aInstallingPrincipal.subsumes(aBrowser.contentPrincipal)) {
} else if (aInstallingPrincipal.isNullPrincipal || !aBrowser.contentPrincipal || !aInstallingPrincipal.subsumes(aBrowser.contentPrincipal)) {
aInstall.cancel();
this.installNotifyObservers("addon-install-origin-blocked", topBrowser,

Просмотреть файл

@ -168,6 +168,7 @@ row[unsupported="true"] {
}
#detail-name, #detail-desc, #detail-fulldesc {
-moz-user-select: text;
word-wrap: break-word;
}
#detail-name-container {

Просмотреть файл

@ -11,14 +11,16 @@ ChromeUtils.defineModuleGetter(this, "UpdateListener",
"resource://gre/modules/UpdateListener.jsm");
const BIN_SUFFIX = (AppConstants.platform == "win" ? ".exe" : "");
const FILE_UPDATER_BIN = "updater" + (AppConstants.platform == "macosx" ? ".app" : BIN_SUFFIX);
const FILE_UPDATER_BIN =
"updater" + (AppConstants.platform == "macosx" ? ".app" : BIN_SUFFIX);
const FILE_UPDATER_BIN_BAK = FILE_UPDATER_BIN + ".bak";
const LOG_FUNCTION = info;
const MAX_UPDATE_COPY_ATTEMPTS = 10;
const DATA_URI_SPEC = "chrome://mochitests/content/browser/toolkit/mozapps/update/tests/browser/";
const DATA_URI_SPEC =
"chrome://mochitests/content/browser/toolkit/mozapps/update/tests/browser/";
/* import-globals-from testConstants.js */
Services.scriptloader.loadSubScript(DATA_URI_SPEC + "testConstants.js", this);
@ -35,14 +37,49 @@ let gOriginalUpdateAutoValue = null;
// the test's onload function.
gDebugTest = true;
/**
* Common tasks to perform for all tests before each one has started.
*/
add_task(async function setupTestCommon() {
await SpecialPowers.pushPrefEnv({
set: [
[PREF_APP_UPDATE_LOG, gDebugTest],
],
});
setUpdateTimerPrefs();
removeUpdateFiles(true);
// Most app update mochitest-browser-chrome tests expect auto update to be
// enabled. Those that don't will explicitly change this.
await setAppUpdateAutoEnabledHelper(true);
});
/**
* Common tasks to perform for all tests after each one has finished.
*/
registerCleanupFunction(async () => {
gEnv.set("MOZ_TEST_SKIP_UPDATE_STAGE", "");
gEnv.set("MOZ_TEST_SLOW_SKIP_UPDATE_STAGE", "");
UpdateListener.reset();
reloadUpdateManagerData(true);
// Pass false when the log files are needed for troubleshooting the tests.
removeUpdateFiles(true);
// Always try to restore the original updater files. If none of the updater
// backup files are present then this is just a no-op.
await finishTestRestoreUpdaterBackup();
});
/**
* Creates the continue file used to signal that update staging or the mock http
* server should continue. The delay this creates allows the tests to verify the
* user interfaces before they auto advance to phases of an update. The continue
* file for staging will be deleted by the test updater and the continue file
* for update check and update download requests will be deleted by the test
* http server handler implemented in app_update.sjs. The test returns a promise
* so the test can wait on the deletion of the continue file when necessary.
* user interfaces before they auto advance to other phases of an update. The
* continue file for staging will be deleted by the test updater and the
* continue file for the update check and update download requests will be
* deleted by the test http server handler implemented in app_update.sjs. The
* test returns a promise so the test can wait on the deletion of the continue
* file when necessary. If the continue file still exists at the end of a test
* it will be removed to prevent it from affecting tests that run after the test
* that created it.
*
* @param leafName
* The leafName of the file to create. This should be one of the
@ -84,6 +121,16 @@ async function continueFileHandler(leafName) {
continueFile.path);
}
continueFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, PERMS_FILE);
// If for whatever reason the continue file hasn't been removed when a test
// has finished remove it during cleanup so it doesn't affect tests that run
// after the test that created it.
registerCleanupFunction(() => {
if (continueFile.exists()) {
logTestInfo("Removing continue file during test cleanup, path: " +
continueFile.path);
continueFile.remove(false);
}
});
return BrowserTestUtils.waitForCondition(() =>
(!continueFile.exists()),
"Waiting for file to be deleted, path: " + continueFile.path,
@ -120,6 +167,13 @@ function lockWriteTestFile() {
});
}
/**
* Closes the update mutex handle in nsUpdateService.js if it exists and then
* creates a new update mutex handle so the update code thinks there is another
* instance of the application handling updates.
*
* @throws If the function is called on a platform other than Windows.
*/
function setOtherInstanceHandlingUpdates() {
if (AppConstants.platform != "win") {
throw new Error("Windows only test function called");
@ -146,14 +200,6 @@ function getVersionParams(aAppVersion) {
return "&appVersion=" + (aAppVersion ? aAppVersion : appInfo.version);
}
/**
* Clean up updates list and the updates directory.
*/
function cleanUpUpdates() {
reloadUpdateManagerData(true);
removeUpdateFiles(true);
}
/**
* Prevent nsIUpdateTimerManager from notifying nsIApplicationUpdateService
* to check for updates by setting the app update last update time to the
@ -167,8 +213,11 @@ function setUpdateTimerPrefs() {
}
/*
* In addition to changing the value of the Auto Update setting, this function
* also takes care of cleaning up after itself.
* Sets the value of the App Auto Update setting and sets it back to the
* original value at the start of the test when the test finishes.
*
* @param enabled
* The value to set App Auto Update to.
*/
async function setAppUpdateAutoEnabledHelper(enabled) {
if (gOriginalUpdateAutoValue == null) {
@ -180,19 +229,6 @@ async function setAppUpdateAutoEnabledHelper(enabled) {
await UpdateUtils.setAppUpdateAutoEnabled(enabled);
}
add_task(async function setDefaults() {
await SpecialPowers.pushPrefEnv({
set: [
[PREF_APP_UPDATE_LOG, gDebugTest],
// See bug 1505790 - uses a very large value to prevent the sync code
// from running since it has nothing to do with these tests.
["services.sync.autoconnectDelay", 600000],
]});
// Most tests in this directory expect auto update to be enabled. Those that
// don't will explicitly change this.
await setAppUpdateAutoEnabledHelper(true);
});
/**
* Runs a typical update test. Will set various common prefs for using the
* updater doorhanger, runs the provided list of steps, and makes sure
@ -211,22 +247,15 @@ add_task(async function setDefaults() {
*/
function runUpdateTest(updateParams, checkAttempts, steps) {
return (async function() {
registerCleanupFunction(() => {
gEnv.set("MOZ_TEST_SKIP_UPDATE_STAGE", "");
UpdateListener.reset();
cleanUpUpdates();
});
gEnv.set("MOZ_TEST_SKIP_UPDATE_STAGE", "1");
setUpdateTimerPrefs();
removeUpdateFiles(true);
await SpecialPowers.pushPrefEnv({
set: [
[PREF_APP_UPDATE_DOWNLOADPROMPTATTEMPTS, 0],
[PREF_APP_UPDATE_DISABLEDFORTESTING, false],
[PREF_APP_UPDATE_IDLETIME, 0],
[PREF_APP_UPDATE_URL_MANUAL, URL_MANUAL_UPDATE],
]});
],
});
await setupTestUpdater();
@ -249,8 +278,6 @@ function runUpdateTest(updateParams, checkAttempts, steps) {
for (let step of steps) {
await processStep(step);
}
await finishTestRestoreUpdaterBackup();
})();
}
@ -267,22 +294,15 @@ function runUpdateTest(updateParams, checkAttempts, steps) {
*/
function runUpdateProcessingTest(updates, steps) {
return (async function() {
registerCleanupFunction(() => {
gEnv.set("MOZ_TEST_SKIP_UPDATE_STAGE", "");
UpdateListener.reset();
cleanUpUpdates();
});
gEnv.set("MOZ_TEST_SKIP_UPDATE_STAGE", "1");
setUpdateTimerPrefs();
removeUpdateFiles(true);
await SpecialPowers.pushPrefEnv({
set: [
[PREF_APP_UPDATE_DOWNLOADPROMPTATTEMPTS, 0],
[PREF_APP_UPDATE_DISABLEDFORTESTING, false],
[PREF_APP_UPDATE_IDLETIME, 0],
[PREF_APP_UPDATE_URL_MANUAL, URL_MANUAL_UPDATE],
]});
],
});
await setupTestUpdater();
@ -297,8 +317,6 @@ function runUpdateProcessingTest(updates, steps) {
for (let step of steps) {
await processStep(step);
}
await finishTestRestoreUpdaterBackup();
})();
}
@ -366,7 +384,8 @@ function waitForEvent(topic, status = null) {
* @return The button element.
*/
function getNotificationButton(win, notificationId, button) {
let notification = win.document.getElementById(`appMenu-${notificationId}-notification`);
let notification =
win.document.getElementById(`appMenu-${notificationId}-notification`);
is(notification.hidden, false, `${notificationId} notification is showing`);
return notification[button];
}
@ -492,9 +511,11 @@ function copyTestUpdater(attempt = 0) {
}
/**
* Restores the updater that was backed up. This is called in setupTestUpdater
* before the backup of the real updater is done in case the previous test
* failed to restore the updater when the test has finished.
* Restores the updater and updater related file that if there a backup exists.
* This is called in setupTestUpdater before the backup of the real updater is
* done in case the previous test failed to restore the file when a test has
* finished. This is also called in finishTestRestoreUpdaterBackup to restore
* the files when a test finishes.
*/
function restoreUpdaterBackup() {
let greBinDir = getGREBinDir();
@ -538,23 +559,21 @@ function restoreUpdaterBackup() {
}
/**
* When a staging test finishes this will repeatedly attempt to restore the real
* updater.
* When a test finishes this will repeatedly attempt to restore the real updater
* and the other files for the updater if a backup of the file exists.
*/
function finishTestRestoreUpdaterBackup() {
return (async function() {
if (Services.prefs.getBoolPref(PREF_APP_UPDATE_STAGING_ENABLED)) {
try {
// Windows debug builds keep the updater file in use for a short period of
// time after the updater process exits.
restoreUpdaterBackup();
} catch (e) {
logTestInfo("Attempt to restore the backed up updater failed... " +
"will try again, Exception: " + e);
try {
// Windows debug builds keep the updater file in use for a short period of
// time after the updater process exits.
restoreUpdaterBackup();
} catch (e) {
logTestInfo("Attempt to restore the backed up updater failed... " +
"will try again, Exception: " + e);
await TestUtils.waitForTick();
await finishTestRestoreUpdaterBackup();
}
await TestUtils.waitForTick();
await finishTestRestoreUpdaterBackup();
}
})();
}
@ -575,7 +594,8 @@ function waitForAboutDialog() {
async function aboutDialogOnLoad() {
domwindow.removeEventListener("load", aboutDialogOnLoad, true);
let chromeURI = "chrome://browser/content/aboutDialog.xul";
is(domwindow.document.location.href, chromeURI, "About dialog appeared");
is(domwindow.document.location.href, chromeURI,
"About dialog appeared");
resolve(domwindow);
}
@ -664,6 +684,7 @@ function runAboutDialogUpdateTest(updateParams, backgroundUpdate, steps) {
}
return (async function() {
gEnv.set("MOZ_TEST_SLOW_SKIP_UPDATE_STAGE", "1");
await SpecialPowers.pushPrefEnv({
set: [
[PREF_APP_UPDATE_SERVICE_ENABLED, false],
@ -671,20 +692,8 @@ function runAboutDialogUpdateTest(updateParams, backgroundUpdate, steps) {
[PREF_APP_UPDATE_URL_MANUAL, detailsURL],
],
});
registerCleanupFunction(() => {
gEnv.set("MOZ_TEST_SLOW_SKIP_UPDATE_STAGE", "");
UpdateListener.reset();
cleanUpUpdates();
});
gEnv.set("MOZ_TEST_SLOW_SKIP_UPDATE_STAGE", "1");
setUpdateTimerPrefs();
removeUpdateFiles(true);
await setupTestUpdater();
registerCleanupFunction(async () => {
await finishTestRestoreUpdaterBackup();
});
let updateURL = URL_HTTP_UPDATE_SJS + "?detailsURL=" + detailsURL +
updateParams + getVersionParams();
@ -694,9 +703,6 @@ function runAboutDialogUpdateTest(updateParams, backgroundUpdate, steps) {
// MOZ_TEST_SLOW_SKIP_UPDATE_STAGE in updater.cpp this removes the need
// for the continue file to continue staging the update.
gEnv.set("MOZ_TEST_SKIP_UPDATE_STAGE", "1");
registerCleanupFunction(() => {
gEnv.set("MOZ_TEST_SKIP_UPDATE_STAGE", "");
});
}
setUpdateURL(updateURL);
gAUS.checkForBackgroundUpdates();
@ -743,7 +749,8 @@ function runAboutPrefsUpdateTest(updateParams, backgroundUpdate, steps) {
const {panelId, checkActiveUpdate, continueFile} = step;
return (async function() {
await ContentTask.spawn(tab.linkedBrowser, {panelId}, async ({panelId}) => {
await ContentTask.spawn(tab.linkedBrowser, {panelId},
async ({panelId}) => {
let updateDeck = content.document.getElementById("updateDeck");
await ContentTaskUtils.waitForCondition(() =>
(updateDeck.selectedPanel && updateDeck.selectedPanel.id == panelId),
@ -766,7 +773,8 @@ function runAboutPrefsUpdateTest(updateParams, backgroundUpdate, steps) {
await continueFileHandler(continueFile);
}
await ContentTask.spawn(tab.linkedBrowser, {panelId, detailsURL}, async ({panelId, detailsURL}) => {
await ContentTask.spawn(tab.linkedBrowser, {panelId, detailsURL},
async ({panelId, detailsURL}) => {
let linkPanels = ["downloadFailed", "manualUpdate", "unsupportedSystem"];
if (linkPanels.includes(panelId)) {
let selectedPanel =
@ -787,13 +795,14 @@ function runAboutPrefsUpdateTest(updateParams, backgroundUpdate, steps) {
let buttonPanels = ["downloadAndInstall", "apply"];
if (buttonPanels.includes(panelId)) {
let selectedPanel = content.document.getElementById("updateDeck").selectedPanel;
let selectedPanel =
content.document.getElementById("updateDeck").selectedPanel;
let buttonEl = selectedPanel.querySelector("button");
// Note: The about:preferences doesn't focus the button like the
// About Dialog does.
ok(!buttonEl.disabled, "The button should be enabled");
// Don't click the button on the apply panel since this will restart the
// application.
// Don't click the button on the apply panel since this will restart
// the application.
if (selectedPanel.id != "apply") {
buttonEl.click();
}
@ -803,6 +812,7 @@ function runAboutPrefsUpdateTest(updateParams, backgroundUpdate, steps) {
}
return (async function() {
gEnv.set("MOZ_TEST_SLOW_SKIP_UPDATE_STAGE", "1");
await SpecialPowers.pushPrefEnv({
set: [
[PREF_APP_UPDATE_SERVICE_ENABLED, false],
@ -810,20 +820,8 @@ function runAboutPrefsUpdateTest(updateParams, backgroundUpdate, steps) {
[PREF_APP_UPDATE_URL_MANUAL, detailsURL],
],
});
registerCleanupFunction(() => {
gEnv.set("MOZ_TEST_SLOW_SKIP_UPDATE_STAGE", "");
UpdateListener.reset();
cleanUpUpdates();
});
gEnv.set("MOZ_TEST_SLOW_SKIP_UPDATE_STAGE", "1");
setUpdateTimerPrefs();
removeUpdateFiles(true);
await setupTestUpdater();
registerCleanupFunction(async () => {
await finishTestRestoreUpdaterBackup();
});
let updateURL = URL_HTTP_UPDATE_SJS + "?detailsURL=" + detailsURL +
updateParams + getVersionParams();
@ -833,9 +831,6 @@ function runAboutPrefsUpdateTest(updateParams, backgroundUpdate, steps) {
// MOZ_TEST_SLOW_SKIP_UPDATE_STAGE in updater.cpp this removes the need
// for the continue file to continue staging the update.
gEnv.set("MOZ_TEST_SKIP_UPDATE_STAGE", "1");
registerCleanupFunction(() => {
gEnv.set("MOZ_TEST_SKIP_UPDATE_STAGE", "");
});
}
setUpdateURL(updateURL);
gAUS.checkForBackgroundUpdates();
@ -845,7 +840,8 @@ function runAboutPrefsUpdateTest(updateParams, backgroundUpdate, steps) {
setUpdateURL(updateURL);
}
tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:preferences");
tab = await BrowserTestUtils.openNewForegroundTab(gBrowser,
"about:preferences");
registerCleanupFunction(async () => {
await BrowserTestUtils.removeTab(tab);
});

Двоичные данные
toolkit/mozapps/update/tests/data/complete.mar

Двоичный файл не отображается.

Двоичный файл не отображается.

Двоичные данные
toolkit/mozapps/update/tests/data/partial.mar

Двоичный файл не отображается.

Двоичный файл не отображается.

Просмотреть файл

@ -16,7 +16,7 @@
/* global Services, UpdateUtils, gURLData */
const FILE_SIMPLE_MAR = "simple.mar";
const SIZE_SIMPLE_MAR = "1404";
const SIZE_SIMPLE_MAR = "1419";
const STATE_NONE = "null";
const STATE_DOWNLOADING = "downloading";

Двоичные данные
toolkit/mozapps/update/tests/data/simple.mar

Двоичный файл не отображается.

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше