Merge m-c to fx-team, a=merge

This commit is contained in:
Wes Kocher 2015-10-28 17:09:14 -07:00
commit 81dcce0528
157 changed files with 2468 additions and 1449 deletions

View File

@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
Bug 1217261 - Update mp4parse to v0.1.2
Bug 479520 - Implement IDNA2008 standard for International Domain Names

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="2e89362de40a6c9c36525d36317fa1ae8e67e143"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="75f2236d36cc9f9c02d3596fae3de014007cfd82"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="2e89362de40a6c9c36525d36317fa1ae8e67e143"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="75f2236d36cc9f9c02d3596fae3de014007cfd82"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2e89362de40a6c9c36525d36317fa1ae8e67e143"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="75f2236d36cc9f9c02d3596fae3de014007cfd82"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="4ace9aaee0e048dfda11bb787646c59982a3dc80"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="2e89362de40a6c9c36525d36317fa1ae8e67e143"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="75f2236d36cc9f9c02d3596fae3de014007cfd82"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="3b9a47b517d345b8d98bc7f787b9a6c2f51ca75d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="1837d370a964a9719160c79155a07980f2ea4bdf"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="2e89362de40a6c9c36525d36317fa1ae8e67e143"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="75f2236d36cc9f9c02d3596fae3de014007cfd82"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -129,7 +129,7 @@
<!-- Emulator specific things -->
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="72ffdf71c68a96309212eb13d63560d66db14c9e"/>
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="8d4018ebd33ac3f1a043b2d54bc578028656a659"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="b1f6e6797468ecce33acdb780a84cd0bbb751dd9"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="5a50f96a1d7c788817abb7c57acbb75172c1f48d"/>
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="f37bd545063039e30a92f2550ae78c0e6e4e2d08"/>
<project name="platform_external_wpa_supplicant_8" path="external/wpa_supplicant_8" remote="b2g" revision="0c6a6547cd1fd302fa2b0f6e375654df36bf0ec4"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="aa763fa9180a222547824ae6b6064e4851c15a86"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="2e89362de40a6c9c36525d36317fa1ae8e67e143"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="75f2236d36cc9f9c02d3596fae3de014007cfd82"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2e89362de40a6c9c36525d36317fa1ae8e67e143"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="75f2236d36cc9f9c02d3596fae3de014007cfd82"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="4ace9aaee0e048dfda11bb787646c59982a3dc80"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="2e89362de40a6c9c36525d36317fa1ae8e67e143"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="75f2236d36cc9f9c02d3596fae3de014007cfd82"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>

View File

@ -1,9 +1,9 @@
{
"git": {
"git_revision": "2e89362de40a6c9c36525d36317fa1ae8e67e143",
"git_revision": "75f2236d36cc9f9c02d3596fae3de014007cfd82",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
"revision": "4a596a387a18b019fc2763b3509940d52154d72c",
"revision": "62309a2099d3eb104b4f0fac2d3970ba3403f0e6",
"repo_path": "integration/gaia-central"
}

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="2e89362de40a6c9c36525d36317fa1ae8e67e143"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="75f2236d36cc9f9c02d3596fae3de014007cfd82"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>

View File

@ -18,7 +18,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="2e89362de40a6c9c36525d36317fa1ae8e67e143"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="75f2236d36cc9f9c02d3596fae3de014007cfd82"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="3b9a47b517d345b8d98bc7f787b9a6c2f51ca75d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="1837d370a964a9719160c79155a07980f2ea4bdf"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="2e89362de40a6c9c36525d36317fa1ae8e67e143"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="75f2236d36cc9f9c02d3596fae3de014007cfd82"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>

View File

@ -101,7 +101,7 @@ nsEdgeReadingListExtractor::Extract(const nsAString& aDBPath, nsIArray** aItems)
if (urlColumnInfo.cbMax > MAX_URL_LENGTH) {
nsCOMPtr<nsIConsoleService> consoleService = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
if (consoleService) {
consoleService->LogStringMessage(NS_LITERAL_STRING("Edge migration: URL column size increased").get());
consoleService->LogStringMessage(MOZ_UTF16("Edge migration: URL column size increased"));
}
}
err = JetGetColumnInfo(sesid, dbid, "ReadingList", "Title", &titleColumnInfo,
@ -110,7 +110,7 @@ nsEdgeReadingListExtractor::Extract(const nsAString& aDBPath, nsIArray** aItems)
if (titleColumnInfo.cbMax > MAX_TITLE_LENGTH) {
nsCOMPtr<nsIConsoleService> consoleService = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
if (consoleService) {
consoleService->LogStringMessage(NS_LITERAL_STRING("Edge migration: Title column size increased").get());
consoleService->LogStringMessage(MOZ_UTF16("Edge migration: Title column size increased"));
}
}
err = JetGetColumnInfo(sesid, dbid, "ReadingList", "AddedDate", &addedDateColumnInfo,

View File

@ -142,7 +142,6 @@ if test -z "$BUILDING_JS" -o -n "$JS_STANDALONE"; then
ICU_CPPFLAGS="$ICU_CPPFLAGS -DUCONFIG_NO_TRANSLITERATION"
ICU_CPPFLAGS="$ICU_CPPFLAGS -DUCONFIG_NO_REGULAR_EXPRESSIONS"
ICU_CPPFLAGS="$ICU_CPPFLAGS -DUCONFIG_NO_BREAK_ITERATION"
ICU_CPPFLAGS="$ICU_CPPFLAGS -DUCONFIG_NO_IDNA"
# we don't need to pass data to and from legacy char* APIs
ICU_CPPFLAGS="$ICU_CPPFLAGS -DU_CHARSET_IS_UTF8"
# make sure to not accidentally pick up system-icu headers

View File

@ -812,7 +812,18 @@ exports.openFileStream = function (filePath) {
}
exports.isGenerator = function (fn) {
return typeof fn === "function" && fn.isGenerator();
if (typeof fn !== "function") {
return false;
}
let proto = Object.getPrototypeOf(fn);
if (!proto) {
return false;
}
let ctor = proto.constructor;
if (!ctor) {
return false;
}
return ctor.name == "GeneratorFunction";
};
exports.isPromise = function (p) {

View File

@ -4654,6 +4654,10 @@ this.DOMApplicationRegistry = {
}
return this.getManifestFor(aManifestURL).then((aManifest) => {
if (!aManifest) {
return Promise.reject("NoManifest");
}
let manifest = aEntryPoint && aManifest.entry_points &&
aManifest.entry_points[aEntryPoint]
? aManifest.entry_points[aEntryPoint]

View File

@ -131,8 +131,8 @@ public:
observerService->NotifyObservers(
ToSupports(mWindow),
"audio-playback",
mActive ? NS_LITERAL_STRING("active").get()
: NS_LITERAL_STRING("inactive").get());
mActive ? MOZ_UTF16("active")
: MOZ_UTF16("inactive"));
}
return NS_OK;

View File

@ -138,7 +138,7 @@ public:
EncodingRunnable(const nsAString& aType,
const nsAString& aOptions,
uint8_t* aImageBuffer,
UniquePtr<uint8_t[]> aImageBuffer,
layers::Image* aImage,
imgIEncoder* aEncoder,
EncodingCompleteEvent* aEncodingCompleteEvent,
@ -147,7 +147,7 @@ public:
bool aUsingCustomOptions)
: mType(aType)
, mOptions(aOptions)
, mImageBuffer(aImageBuffer)
, mImageBuffer(Move(aImageBuffer))
, mImage(aImage)
, mEncoder(aEncoder)
, mEncodingCompleteEvent(aEncodingCompleteEvent)
@ -161,7 +161,7 @@ public:
nsCOMPtr<nsIInputStream> stream;
nsresult rv = ImageEncoder::ExtractDataInternal(mType,
mOptions,
mImageBuffer,
mImageBuffer.get(),
mFormat,
mSize,
mImage,
@ -175,7 +175,7 @@ public:
if (rv == NS_ERROR_INVALID_ARG && mUsingCustomOptions) {
rv = ImageEncoder::ExtractDataInternal(mType,
EmptyString(),
mImageBuffer,
mImageBuffer.get(),
mFormat,
mSize,
mImage,
@ -220,7 +220,7 @@ public:
private:
nsAutoString mType;
nsAutoString mOptions;
nsAutoArrayPtr<uint8_t> mImageBuffer;
UniquePtr<uint8_t[]> mImageBuffer;
RefPtr<layers::Image> mImage;
nsCOMPtr<imgIEncoder> mEncoder;
RefPtr<EncodingCompleteEvent> mEncodingCompleteEvent;
@ -287,7 +287,7 @@ nsresult
ImageEncoder::ExtractDataAsync(nsAString& aType,
const nsAString& aOptions,
bool aUsingCustomOptions,
uint8_t* aImageBuffer,
UniquePtr<uint8_t[]> aImageBuffer,
int32_t aFormat,
const nsIntSize aSize,
EncodeCompleteCallback* aEncodeCallback)
@ -306,7 +306,7 @@ ImageEncoder::ExtractDataAsync(nsAString& aType,
nsCOMPtr<nsIRunnable> event = new EncodingRunnable(aType,
aOptions,
aImageBuffer,
Move(aImageBuffer),
nullptr,
encoder,
completeEvent,

View File

@ -11,6 +11,7 @@
#include "nsError.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/HTMLCanvasElementBinding.h"
#include "mozilla/UniquePtr.h"
#include "nsLayoutUtils.h"
#include "nsSize.h"
@ -58,7 +59,7 @@ public:
static nsresult ExtractDataAsync(nsAString& aType,
const nsAString& aOptions,
bool aUsingCustomOptions,
uint8_t* aImageBuffer,
UniquePtr<uint8_t[]> aImageBuffer,
int32_t aFormat,
const nsIntSize aSize,
EncodeCompleteCallback* aEncodeCallback);

View File

@ -1563,8 +1563,8 @@ WebSocketImpl::Init(JSContext* aCx,
}
mSecure = true;
const char16_t* params[] = { reportSpec.get(), NS_LITERAL_STRING("wss").get() };
CSP_LogLocalizedStr(NS_LITERAL_STRING("upgradeInsecureRequest").get(),
const char16_t* params[] = { reportSpec.get(), MOZ_UTF16("wss") };
CSP_LogLocalizedStr(MOZ_UTF16("upgradeInsecureRequest"),
params, ArrayLength(params),
EmptyString(), // aSourceFile
EmptyString(), // aScriptSample

View File

@ -15,7 +15,6 @@ support-files =
skip-if = e10s # Bug ?????? - test directly touches content (contentWindow.iframe.addEventListener)
[browser_bug902350.js]
tags = mcb
skip-if = e10s # Bug ?????? - test e10s utils don't support load events from iframe etc, which this test relies on.
[browser_messagemanager_loadprocessscript.js]
[browser_messagemanager_targetframeloader.js]
[browser_pagehide_on_tab_close.js]

View File

@ -1303,7 +1303,7 @@ nsGonkCameraControl::StopRecordingImpl()
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
obs->NotifyObservers(mFile, "file-watcher-notify", NS_LITERAL_STRING("modified").get());
obs->NotifyObservers(mFile, "file-watcher-notify", MOZ_UTF16("modified"));
return NS_OK;
}

View File

@ -1646,26 +1646,24 @@ CanvasRenderingContext2D::SetContextOptions(JSContext* aCx,
return NS_OK;
}
void
CanvasRenderingContext2D::GetImageBuffer(uint8_t** aImageBuffer,
int32_t* aFormat)
UniquePtr<uint8_t[]>
CanvasRenderingContext2D::GetImageBuffer(int32_t* aFormat)
{
*aImageBuffer = nullptr;
*aFormat = 0;
EnsureTarget();
RefPtr<SourceSurface> snapshot = mTarget->Snapshot();
if (!snapshot) {
return;
return nullptr;
}
RefPtr<DataSourceSurface> data = snapshot->GetDataSurface();
if (!data || data->GetSize() != IntSize(mWidth, mHeight)) {
return;
return nullptr;
}
*aImageBuffer = SurfaceToPackedBGRA(data);
*aFormat = imgIEncoder::INPUT_FORMAT_HOSTARGB;
return SurfaceToPackedBGRA(data);
}
nsString CanvasRenderingContext2D::GetHitRegion(const mozilla::gfx::Point& aPoint)
@ -1691,15 +1689,15 @@ CanvasRenderingContext2D::GetInputStream(const char *aMimeType,
return NS_ERROR_FAILURE;
}
nsAutoArrayPtr<uint8_t> imageBuffer;
int32_t format = 0;
GetImageBuffer(getter_Transfers(imageBuffer), &format);
UniquePtr<uint8_t[]> imageBuffer = GetImageBuffer(&format);
if (!imageBuffer) {
return NS_ERROR_FAILURE;
}
return ImageEncoder::GetInputStream(mWidth, mHeight, imageBuffer, format,
encoder, aEncoderOptions, aStream);
return ImageEncoder::GetInputStream(mWidth, mHeight, imageBuffer.get(),
format, encoder, aEncoderOptions,
aStream);
}
SurfaceFormat

View File

@ -20,6 +20,7 @@
#include "mozilla/dom/CanvasPattern.h"
#include "mozilla/gfx/Rect.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/UniquePtr.h"
#include "gfx2DGlue.h"
#include "imgIEncoder.h"
#include "nsLayoutUtils.h"
@ -526,7 +527,7 @@ public:
friend class CanvasRenderingContext2DUserData;
virtual void GetImageBuffer(uint8_t** aImageBuffer, int32_t* aFormat) override;
virtual UniquePtr<uint8_t[]> GetImageBuffer(int32_t* aFormat) override;
// Given a point, return hit region ID if it exists

View File

@ -7,6 +7,7 @@
#include "ImageEncoder.h"
#include "mozilla/dom/CanvasRenderingContext2D.h"
#include "mozilla/Telemetry.h"
#include "mozilla/UniquePtr.h"
#include "nsContentUtils.h"
#include "nsDOMJSUtils.h"
#include "nsIScriptContext.h"
@ -49,10 +50,10 @@ CanvasRenderingContextHelper::ToBlob(JSContext* aCx,
}
}
uint8_t* imageBuffer = nullptr;
UniquePtr<uint8_t[]> imageBuffer;
int32_t format = 0;
if (mCurrentContext) {
mCurrentContext->GetImageBuffer(&imageBuffer, &format);
imageBuffer = mCurrentContext->GetImageBuffer(&format);
}
// Encoder callback when encoding is complete.
@ -99,7 +100,7 @@ CanvasRenderingContextHelper::ToBlob(JSContext* aCx,
aRv = ImageEncoder::ExtractDataAsync(type,
params,
usingCustomParseOptions,
imageBuffer,
Move(imageBuffer),
format,
GetWidthHeight(),
callback);

View File

@ -1052,25 +1052,25 @@ WebGLContext::LoseOldestWebGLContextIfLimitExceeded()
}
}
void
WebGLContext::GetImageBuffer(uint8_t** out_imageBuffer, int32_t* out_format)
UniquePtr<uint8_t[]>
WebGLContext::GetImageBuffer(int32_t* out_format)
{
*out_imageBuffer = nullptr;
*out_format = 0;
// Use GetSurfaceSnapshot() to make sure that appropriate y-flip gets applied
bool premult;
RefPtr<SourceSurface> snapshot =
GetSurfaceSnapshot(mOptions.premultipliedAlpha ? nullptr : &premult);
if (!snapshot)
return;
if (!snapshot) {
return nullptr;
}
MOZ_ASSERT(mOptions.premultipliedAlpha || !premult, "We must get unpremult when we ask for it!");
RefPtr<DataSourceSurface> dataSurface = snapshot->GetDataSurface();
return gfxUtils::GetImageBuffer(dataSurface, mOptions.premultipliedAlpha,
out_imageBuffer, out_format);
out_format);
}
NS_IMETHODIMP

View File

@ -237,8 +237,7 @@ public:
return NS_ERROR_NOT_IMPLEMENTED;
}
virtual void GetImageBuffer(uint8_t** out_imageBuffer,
int32_t* out_format) override;
virtual UniquePtr<uint8_t[]> GetImageBuffer(int32_t* out_format) override;
NS_IMETHOD GetInputStream(const char* mimeType,
const char16_t* encoderOptions,
nsIInputStream** out_stream) override;

View File

@ -14,6 +14,7 @@
#include "mozilla/dom/HTMLCanvasElement.h"
#include "mozilla/dom/OffscreenCanvas.h"
#include "mozilla/RefPtr.h"
#include "mozilla/UniquePtr.h"
#define NS_ICANVASRENDERINGCONTEXTINTERNAL_IID \
{ 0xb84f2fed, 0x9d4b, 0x430b, \
@ -96,7 +97,7 @@ public:
NS_IMETHOD InitializeWithSurface(nsIDocShell *docShell, gfxASurface *surface, int32_t width, int32_t height) = 0;
// Creates an image buffer. Returns null on failure.
virtual void GetImageBuffer(uint8_t** imageBuffer, int32_t* format) = 0;
virtual mozilla::UniquePtr<uint8_t[]> GetImageBuffer(int32_t* format) = 0;
// Gives you a stream containing the image represented by this context.
// The format is given in mimeTime, for example "image/png".

View File

@ -1764,7 +1764,7 @@ HTMLFormElement::GetActionURL(nsIURI** aActionURL,
NS_ConvertUTF8toUTF16 reportScheme(scheme);
const char16_t* params[] = { reportSpec.get(), reportScheme.get() };
CSP_LogLocalizedStr(NS_LITERAL_STRING("upgradeInsecureRequest").get(),
CSP_LogLocalizedStr(MOZ_UTF16("upgradeInsecureRequest"),
params, ArrayLength(params),
EmptyString(), // aSourceFile
EmptyString(), // aScriptSample

View File

@ -106,43 +106,22 @@ MediaCodecProxy::~MediaCodecProxy()
}
bool
MediaCodecProxy::AskMediaCodecAndWait()
MediaCodecProxy::AllocateAudioMediaCodec()
{
if (mResourceClient || mCodec.get()) {
return false;
}
if (strncasecmp(mCodecMime.get(), "video/", 6) == 0) {
mozilla::MediaSystemResourceType type =
mCodecEncoder ? mozilla::MediaSystemResourceType::VIDEO_ENCODER :
mozilla::MediaSystemResourceType::VIDEO_DECODER;
mResourceClient = new mozilla::MediaSystemResourceClient(type);
mResourceClient->SetListener(this);
} else if (strncasecmp(mCodecMime.get(), "audio/", 6) == 0) {
if (strncasecmp(mCodecMime.get(), "audio/", 6) == 0) {
if (allocateCodec()) {
return true;
}
}
if (!mResourceClient) {
return false;
}
mozilla::MonitorAutoLock mon(mMediaCodecLock);
mPendingRequestMediaResource = true;
// request video codec
mResourceClient->Acquire();
while (mPendingRequestMediaResource) {
mMediaCodecLock.Wait();
}
MCP_LOG("AskMediaCodecAndWait complete");
return true;
return false;
}
bool
MediaCodecProxy::AsyncAskMediaCodec()
MediaCodecProxy::AsyncAllocateVideoMediaCodec()
{
if (mResourceClient || mCodec.get()) {
return false;

View File

@ -138,14 +138,11 @@ public:
void ReleaseMediaBuffer(MediaBuffer* abuffer);
// It asks for the OMX codec and blocked until the resource is grant to be
// allocated.
// Audio codec allocation should use this.
bool AskMediaCodecAndWait();
// It allocates audio MediaCodec synchronously.
bool AllocateAudioMediaCodec();
// It asks for the OMX codec asynchronously.
// Only video codec is supported.
bool AsyncAskMediaCodec();
// It allocates video MediaCodec asynchronously.
bool AsyncAllocateVideoMediaCodec();
// Free the OMX codec so others can allocate it.
void ReleaseMediaCodec();

View File

@ -1303,12 +1303,12 @@ MediaCodecReader::CreateMediaCodecs()
bool isWaiting = false;
RefPtr<MediaResourcePromise> p = mMediaResourcePromise.Ensure(__func__);
if (!CreateMediaCodec(mLooper, mAudioTrack, false, isWaiting, nullptr)) {
if (!CreateMediaCodec(mLooper, mAudioTrack, isWaiting, nullptr)) {
mMediaResourcePromise.Reject(true, __func__);
return p;
}
if (!CreateMediaCodec(mLooper, mVideoTrack, true, isWaiting, mVideoListener)) {
if (!CreateMediaCodec(mLooper, mVideoTrack, isWaiting, mVideoListener)) {
mMediaResourcePromise.Reject(true, __func__);
return p;
}
@ -1324,7 +1324,6 @@ MediaCodecReader::CreateMediaCodecs()
bool
MediaCodecReader::CreateMediaCodec(sp<ALooper>& aLooper,
Track& aTrack,
bool aAsync,
bool& aIsWaiting,
wp<MediaCodecProxy::CodecResourceListener> aListener)
{
@ -1362,7 +1361,7 @@ MediaCodecReader::CreateMediaCodec(sp<ALooper>& aLooper,
#endif
}
if (!aAsync && aTrack.mCodec->AskMediaCodecAndWait()) {
if (aTrack.mType == Track::kAudio && aTrack.mCodec->AllocateAudioMediaCodec()) {
// Pending configure() and start() to codecReserved() if the creation
// should be asynchronous.
if (!aTrack.mCodec->allocated() || !ConfigureMediaCodec(aTrack)){
@ -1370,8 +1369,8 @@ MediaCodecReader::CreateMediaCodec(sp<ALooper>& aLooper,
DestroyMediaCodec(aTrack);
return false;
}
} else if (aAsync) {
if (aTrack.mCodec->AsyncAskMediaCodec()) {
} else if (aTrack.mType == Track::kVideo) {
if (aTrack.mCodec->AsyncAllocateVideoMediaCodec()) {
aIsWaiting = true;
} else {
NS_WARNING("Couldn't request MediaCodec asynchronously");

View File

@ -340,7 +340,6 @@ private:
RefPtr<MediaResourcePromise> CreateMediaCodecs();
static bool CreateMediaCodec(android::sp<android::ALooper>& aLooper,
Track& aTrack,
bool aAsync,
bool& aIsWaiting,
android::wp<android::MediaCodecProxy::CodecResourceListener> aListener);
static bool ConfigureMediaCodec(Track& aTrack);

View File

@ -74,7 +74,7 @@ GonkAudioDecoderManager::InitMediaCodecProxy()
if (!mDecoder.get()) {
return false;
}
if (!mDecoder->AskMediaCodecAndWait())
if (!mDecoder->AllocateAudioMediaCodec())
{
mDecoder = nullptr;
return false;

View File

@ -124,7 +124,7 @@ GonkVideoDecoderManager::Init()
self->codecCanceled();
}));
mDecoder = MediaCodecProxy::CreateByType(mDecodeLooper, mMimeType.get(), false, mVideoListener);
mDecoder->AsyncAskMediaCodec();
mDecoder->AsyncAllocateVideoMediaCodec();
uint32_t capability = MediaCodecProxy::kEmptyCapability;
if (mDecoder->getCapability(&capability) == OK && (capability &

View File

@ -161,6 +161,12 @@ CamerasParent::Observe(nsISupports *aSubject,
nsresult
CamerasParent::DispatchToVideoCaptureThread(nsRunnable *event)
{
// Don't try to dispatch if we're already on the right thread.
// There's a potential deadlock because the mThreadMonitor is likely
// to be taken already.
MOZ_ASSERT(!mVideoCaptureThread ||
mVideoCaptureThread->thread_id() != PlatformThread::CurrentId());
MonitorAutoLock lock(mThreadMonitor);
while(mChildIsAlive && mWebRTCAlive &&
@ -184,12 +190,17 @@ CamerasParent::StopVideoCapture()
RefPtr<CamerasParent> self(this);
RefPtr<nsRunnable> webrtc_runnable =
media::NewRunnableFrom([self]() -> nsresult {
MonitorAutoLock lock(self->mThreadMonitor);
self->CloseEngines();
self->mThreadMonitor.NotifyAll();
return NS_OK;
});
DispatchToVideoCaptureThread(webrtc_runnable);
MonitorAutoLock lock(self->mThreadMonitor);
self->CloseEngines();
self->mThreadMonitor.NotifyAll();
return NS_OK;
});
DebugOnly<nsresult> rv = DispatchToVideoCaptureThread(webrtc_runnable);
#ifdef DEBUG
// It's ok for the dispatch to fail if the cleanup it has to do
// has been done already.
MOZ_ASSERT(NS_SUCCEEDED(rv) || !mWebRTCAlive);
#endif
// Hold here until the WebRTC thread is gone. We need to dispatch
// the thread deletion *now*, or there will be no more possibility
// to get to the main thread.
@ -393,8 +404,8 @@ CamerasParent::CloseEngines()
auto capEngine = mCallbacks[0]->mCapEngine;
auto capNum = mCallbacks[0]->mCapturerId;
LOG(("Forcing shutdown of engine %d, capturer %d", capEngine, capNum));
RecvStopCapture(capEngine, capNum);
RecvReleaseCaptureDevice(capEngine, capNum);
StopCapture(capEngine, capNum);
unused << ReleaseCaptureDevice(capEngine, capNum);
}
for (int i = 0; i < CaptureEngine::MaxEngine; i++) {
@ -651,6 +662,17 @@ CamerasParent::RecvAllocateCaptureDevice(const int& aCapEngine,
return true;
}
int
CamerasParent::ReleaseCaptureDevice(const int& aCapEngine,
const int& capnum)
{
int error = -1;
if (EnsureInitialized(aCapEngine)) {
error = mEngines[aCapEngine].mPtrViECapture->ReleaseCaptureDevice(capnum);
}
return error;
}
bool
CamerasParent::RecvReleaseCaptureDevice(const int& aCapEngine,
const int& numdev)
@ -661,10 +683,7 @@ CamerasParent::RecvReleaseCaptureDevice(const int& aCapEngine,
RefPtr<CamerasParent> self(this);
RefPtr<nsRunnable> webrtc_runnable =
media::NewRunnableFrom([self, aCapEngine, numdev]() -> nsresult {
int error = -1;
if (self->EnsureInitialized(aCapEngine)) {
error = self->mEngines[aCapEngine].mPtrViECapture->ReleaseCaptureDevice(numdev);
}
int error = self->ReleaseCaptureDevice(aCapEngine, numdev);
RefPtr<nsIRunnable> ipc_runnable =
media::NewRunnableFrom([self, error, numdev]() -> nsresult {
if (self->IsShuttingDown()) {
@ -748,6 +767,27 @@ CamerasParent::RecvStartCapture(const int& aCapEngine,
return true;
}
void
CamerasParent::StopCapture(const int& aCapEngine,
const int& capnum)
{
if (EnsureInitialized(aCapEngine)) {
mEngines[aCapEngine].mPtrViECapture->StopCapture(capnum);
mEngines[aCapEngine].mPtrViERender->StopRender(capnum);
mEngines[aCapEngine].mPtrViERender->RemoveRenderer(capnum);
mEngines[aCapEngine].mEngineIsRunning = false;
for (size_t i = 0; i < mCallbacks.Length(); i++) {
if (mCallbacks[i]->mCapEngine == aCapEngine
&& mCallbacks[i]->mCapturerId == capnum) {
delete mCallbacks[i];
mCallbacks.RemoveElementAt(i);
break;
}
}
}
}
bool
CamerasParent::RecvStopCapture(const int& aCapEngine,
const int& capnum)
@ -757,27 +797,18 @@ CamerasParent::RecvStopCapture(const int& aCapEngine,
RefPtr<CamerasParent> self(this);
RefPtr<nsRunnable> webrtc_runnable =
media::NewRunnableFrom([self, aCapEngine, capnum]() -> nsresult {
if (self->EnsureInitialized(aCapEngine)) {
self->mEngines[aCapEngine].mPtrViECapture->StopCapture(capnum);
self->mEngines[aCapEngine].mPtrViERender->StopRender(capnum);
self->mEngines[aCapEngine].mPtrViERender->RemoveRenderer(capnum);
self->mEngines[aCapEngine].mEngineIsRunning = false;
for (size_t i = 0; i < self->mCallbacks.Length(); i++) {
if (self->mCallbacks[i]->mCapEngine == aCapEngine
&& self->mCallbacks[i]->mCapturerId == capnum) {
delete self->mCallbacks[i];
self->mCallbacks.RemoveElementAt(i);
break;
}
}
}
self->StopCapture(aCapEngine, capnum);
return NS_OK;
});
if (NS_SUCCEEDED(DispatchToVideoCaptureThread(webrtc_runnable))) {
return SendReplySuccess();
nsresult rv = DispatchToVideoCaptureThread(webrtc_runnable);
if (self->IsShuttingDown()) {
return NS_SUCCEEDED(rv);
} else {
return SendReplyFailure();
if (NS_SUCCEEDED(rv)) {
return SendReplySuccess();
} else {
return SendReplyFailure();
}
}
}

View File

@ -119,9 +119,13 @@ public:
protected:
virtual ~CamerasParent();
// We use these helpers for shutdown and for the respective IPC commands.
void StopCapture(const int& aCapEngine, const int& capnum);
int ReleaseCaptureDevice(const int& aCapEngine, const int& capnum);
bool SetupEngine(CaptureEngine aCapEngine);
void CloseEngines();
bool EnsureInitialized(int aEngine);
void CloseEngines();
void StopIPC();
void StopVideoCapture();
nsresult DispatchToVideoCaptureThread(nsRunnable *event);

View File

@ -79,8 +79,8 @@ MediaEngineGonkVideoSource::NotifyPull(MediaStreamGraph* aGraph,
// Note: we're not giving up mImage here
RefPtr<layers::Image> image = mImage;
StreamTime delta = aDesiredTime - aSource->GetEndOfAppendedData(aID);
LOGFRAME(("NotifyPull, desired = %ld, delta = %ld %s", (int64_t) aDesiredTime,
(int64_t) delta, image ? "" : "<null>"));
LOGFRAME(("NotifyPull, desired = %" PRIi64 ", delta = %" PRIi64 " %s",
(int64_t) aDesiredTime, (int64_t) delta, image ? "" : "<null>"));
// Bug 846188 We may want to limit incoming frames to the requested frame rate
// mFps - if you want 30FPS, and the camera gives you 60FPS, this could

View File

@ -319,8 +319,8 @@ MediaEngineRemoteVideoSource::DeliverFrame(unsigned char* buffer,
#ifdef DEBUG
static uint32_t frame_num = 0;
LOGFRAME(("frame %d (%dx%d); timestamp %u, ntp_time %lu, render_time %lu", frame_num++,
mWidth, mHeight, time_stamp, ntp_time, render_time));
LOGFRAME(("frame %d (%dx%d); timestamp %u, ntp_time %" PRIu64 ", render_time %" PRIu64,
frame_num++, mWidth, mHeight, time_stamp, ntp_time, render_time));
#endif
// we don't touch anything in 'this' until here (except for snapshot,

View File

@ -925,6 +925,9 @@ this.PushService = {
if (this._state == PUSH_SERVICE_CONNECTION_DISABLE) {
return Promise.reject({state: 0, error: "Service not active"});
} else if (this._state == PUSH_SERVICE_ACTIVE_OFFLINE) {
if (this._service.serviceType() == "WebSocket" && action == "unregister") {
return Promise.resolve();
}
return Promise.reject({state: 0, error: "NetworkError"});
}
return this._service.request(action, aRecord);

View File

@ -441,6 +441,10 @@ this.PushServiceHttp2 = {
PushRecordHttp2);
},
serviceType: function() {
return "http2";
},
hasmainPushService: function() {
return this._mainPushService !== null;
},

View File

@ -157,6 +157,10 @@ this.PushServiceWebSocket = {
PushRecordWebSocket);
},
serviceType: function() {
return "WebSocket";
},
disconnect: function() {
this._shutdownWS();
},

View File

@ -776,7 +776,7 @@ nsCSPContext::SendReports(nsISupports* aBlockedContentSource,
const char16_t* params[] = { reportURIs[r].get() };
CSPCONTEXTLOG(("Could not create nsIURI for report URI %s",
reportURICstring.get()));
CSP_LogLocalizedStr(NS_LITERAL_STRING("triedToSendReport").get(),
CSP_LogLocalizedStr(MOZ_UTF16("triedToSendReport"),
params, ArrayLength(params),
aSourceFile, aScriptSample, aLineNum, 0,
nsIScriptError::errorFlag, "CSP", mInnerWindowID);
@ -820,7 +820,7 @@ nsCSPContext::SendReports(nsISupports* aBlockedContentSource,
if (!isHttpScheme) {
const char16_t* params[] = { reportURIs[r].get() };
CSP_LogLocalizedStr(NS_LITERAL_STRING("reportURInotHttpsOrHttp2").get(),
CSP_LogLocalizedStr(MOZ_UTF16("reportURInotHttpsOrHttp2"),
params, ArrayLength(params),
aSourceFile, aScriptSample, aLineNum, 0,
nsIScriptError::errorFlag, "CSP", mInnerWindowID);
@ -904,7 +904,7 @@ nsCSPContext::SendReports(nsISupports* aBlockedContentSource,
if (NS_FAILED(rv)) {
const char16_t* params[] = { reportURIs[r].get() };
CSPCONTEXTLOG(("AsyncOpen failed for report URI %s", params[0]));
CSP_LogLocalizedStr(NS_LITERAL_STRING("triedToSendReport").get(),
CSP_LogLocalizedStr(MOZ_UTF16("triedToSendReport"),
params, ArrayLength(params),
aSourceFile, aScriptSample, aLineNum, 0,
nsIScriptError::errorFlag, "CSP", mInnerWindowID);
@ -994,8 +994,8 @@ class CSPReportSenderRunnable final : public nsRunnable
const char16_t* params[] = { mViolatedDirective.get(),
blockedDataChar16.get() };
CSP_LogLocalizedStr(mReportOnlyFlag ? NS_LITERAL_STRING("CSPROViolationWithURI").get() :
NS_LITERAL_STRING("CSPViolationWithURI").get(),
CSP_LogLocalizedStr(mReportOnlyFlag ? MOZ_UTF16("CSPROViolationWithURI") :
MOZ_UTF16("CSPViolationWithURI"),
params, ArrayLength(params),
mSourceFile, mScriptSample, mLineNum, 0,
nsIScriptError::errorFlag, "CSP", mInnerWindowID);
@ -1313,7 +1313,7 @@ CSPReportRedirectSink::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
NS_ASSERTION(observerService, "Observer service required to log CSP violations");
observerService->NotifyObservers(uri,
CSP_VIOLATION_TOPIC,
NS_LITERAL_STRING("denied redirect while sending violation report").get());
MOZ_UTF16("denied redirect while sending violation report"));
return NS_BINDING_REDIRECTED;
}

View File

@ -1012,7 +1012,7 @@ nsCSPParser::directive()
// Make sure that the directive-srcs-array contains at least
// one directive and one src.
if (mCurDir.Length() < 1) {
const char16_t* params[] = { NS_LITERAL_STRING("directive missing").get() };
const char16_t* params[] = { MOZ_UTF16("directive missing") };
logWarningErrorToConsole(nsIScriptError::warningFlag, "failedToParseUnrecognizedSource",
params, ArrayLength(params));
return;
@ -1029,7 +1029,7 @@ nsCSPParser::directive()
// by a directive name but does not include any srcs.
if (cspDir->equals(nsIContentSecurityPolicy::UPGRADE_IF_INSECURE_DIRECTIVE)) {
if (mCurDir.Length() > 1) {
const char16_t* params[] = { NS_LITERAL_STRING("upgrade-insecure-requests").get() };
const char16_t* params[] = { MOZ_UTF16("upgrade-insecure-requests") };
logWarningErrorToConsole(nsIScriptError::warningFlag,
"ignoreSrcForDirective",
params, ArrayLength(params));
@ -1062,7 +1062,7 @@ nsCSPParser::directive()
mHasHashOrNonce && mUnsafeInlineKeywordSrc) {
mUnsafeInlineKeywordSrc->invalidate();
// log to the console that unsafe-inline will be ignored
const char16_t* params[] = { NS_LITERAL_STRING("'unsafe-inline'").get() };
const char16_t* params[] = { MOZ_UTF16("'unsafe-inline'") };
logWarningErrorToConsole(nsIScriptError::warningFlag, "ignoringSrcWithinScriptSrc",
params, ArrayLength(params));
}

File diff suppressed because it is too large Load Diff

View File

@ -18,7 +18,9 @@
#include "mozilla/HalTypes.h"
#include "mozilla/Observer.h"
#include "mozilla/UniquePtr.h"
#include "nsAutoPtr.h"
#include "nsDataHashtable.h"
#include "nsIAudioManager.h"
#include "nsIObserver.h"
#include "android_audio/AudioSystem.h"
@ -53,32 +55,7 @@ enum AudioOutputProfiles {
DEVICE_TOTAL_NUMBER = 3,
};
/**
* We have five sound volume settings from UX spec,
* You can see more informations in Bug1068219.
* (1) Media : music, video, FM ...
* (2) Notification : ringer, notification ...
* (3) Alarm : alarm
* (4) Telephony : GSM call, WebRTC call
* (5) Bluetooth SCO : SCO call
**/
enum AudioVolumeCategories {
VOLUME_MEDIA = 0,
VOLUME_NOTIFICATION = 1,
VOLUME_ALARM = 2,
VOLUME_TELEPHONY = 3,
VOLUME_BLUETOOTH_SCO = 4,
VOLUME_TOTAL_NUMBER = 5,
};
struct VolumeData {
const char* mChannelName;
uint32_t mCategory;
};
class RecoverTask;
class VolumeInitCallback;
class AudioProfileData;
class AudioManager final : public nsIAudioManager
, public nsIObserver
@ -90,27 +67,63 @@ public:
NS_DECL_NSIAUDIOMANAGER
NS_DECL_NSIOBSERVER
// When audio backend is dead, recovery task needs to read all volume
// settings then set back into audio backend.
friend class RecoverTask;
friend class VolumeInitCallback;
// Open or close the specific profile
void SwitchProfileData(AudioOutputProfiles aProfile, bool aActive);
// Validate whether the volume index is within the range
nsresult ValidateVolumeIndex(uint32_t aCategory, uint32_t aIndex) const;
nsresult ValidateVolumeIndex(int32_t aStream, uint32_t aIndex) const;
// Called when android AudioFlinger in mediaserver is died
void HandleAudioFlingerDied();
void HandleHeadphoneSwitchEvent(const hal::SwitchEvent& aEvent);
class VolumeStreamState {
public:
explicit VolumeStreamState(AudioManager& aManager, int32_t aStreamType);
int32_t GetStreamType()
{
return mStreamType;
}
bool IsDevicesChanged(bool aFromCache = true);
void ClearDevicesChanged();
uint32_t GetLastDevices()
{
return mLastDevices;
}
void InitStreamVolume();
uint32_t GetMaxIndex();
uint32_t GetDefaultIndex();
uint32_t GetVolumeIndex();
uint32_t GetVolumeIndex(uint32_t aDevice);
void ClearCurrentVolumeUpdated();
// Set volume index to all active devices.
// Active devices are chosen by android AudioPolicyManager.
nsresult SetVolumeIndexToActiveDevices(uint32_t aIndex);
// Set volume index to all alias streams. Alias streams have same volume.
// It is used to update volume based on audio output profile data.
nsresult SetVolumeIndexToAliasStreams(uint32_t aIndex, uint32_t aDevice);
// Set volume index to all alias devices in audio output profile.
// Alias devices have same volume.
nsresult SetVolumeIndexToAliasDevices(uint32_t aIndex, uint32_t aDevice);
nsresult SetVolumeIndex(uint32_t aIndex, uint32_t aDevice, bool aUpdateCache = true);
// Restore volume index to all devices. Called when AudioFlinger is restarted.
void RestoreVolumeIndexToAllDevices();
private:
AudioManager& mManager;
const int32_t mStreamType;
uint32_t mLastDevices;
bool mIsDevicesChanged;
nsDataHashtable<nsUint32HashKey, uint32_t> mVolumeIndexes;
};
protected:
int32_t mPhoneState;
// A bitwise variable for recording what kind of headset/headphone is attached.
int32_t mHeadsetState;
bool mIsVolumeInited;
// A bitwise variable for volume update of audio output profiles
uint32_t mAudioOutProfileUpdated;
// Connected devices that are controlled by setDeviceConnectionState()
nsDataHashtable<nsUint32HashKey, nsCString> mConnectedDevices;
bool mSwitchDone;
@ -120,11 +133,23 @@ protected:
#ifdef MOZ_B2G_BT
bool mA2dpSwitchDone;
#endif
uint32_t mCurrentStreamVolumeTbl[AUDIO_STREAM_CNT];
nsTArray<UniquePtr<VolumeStreamState> > mStreamStates;
uint32_t mLastChannelVolume[AUDIO_STREAM_CNT];
bool IsFmOutConnected();
nsresult SetStreamVolumeForProfile(AudioOutputProfiles aProfile,
int32_t aStream,
uint32_t aIndex);
nsresult SetStreamVolumeIndex(int32_t aStream, uint32_t aIndex);
nsresult GetStreamVolumeIndex(int32_t aStream, uint32_t *aIndex);
void UpdateCachedActiveDevicesForStreams();
uint32_t GetDevicesForStream(int32_t aStream, bool aFromCache = true);
uint32_t GetDeviceForStream(int32_t aStream);
// Choose one device as representative of active devices.
static uint32_t SelectDeviceFromDevices(uint32_t aOutDevices);
private:
nsAutoPtr<mozilla::hal::SwitchObserver> mObserver;
#ifdef MOZ_B2G_RIL
@ -132,57 +157,41 @@ private:
// mIsMicMuted is only used for toggling mute call to RIL.
bool mIsMicMuted;
#endif
nsTArray<nsAutoPtr<AudioProfileData>> mAudioProfiles;
AudioOutputProfiles mPresentProfile;
void HandleBluetoothStatusChanged(nsISupports* aSubject,
const char* aTopic,
const nsCString aAddress);
void HandleAudioChannelProcessChanged();
void CreateAudioProfilesData();
// Initialize volume index for audio output profile
void InitVolumeForProfile(AudioOutputProfiles aProfile,
int32_t aStreamType,
uint32_t aIndex);
// Init the volume setting from the init setting callback
void InitProfileVolume(AudioOutputProfiles aProfile,
uint32_t aCatogory, uint32_t aIndex);
// Update volume data of profiles
void UpdateVolumeToProfile(AudioProfileData* aProfileData);
// Apply the volume data to device
void UpdateVolumeFromProfile(AudioProfileData* aProfileData);
// Send the volume changing event to Gaia
void SendVolumeChangeNotification(AudioProfileData* aProfileData);
// Update the mPresentProfile and profiles active status
void UpdateProfileState(AudioOutputProfiles aProfile, bool aActive);
// Volume control functions
nsresult SetVolumeByCategory(uint32_t aCategory, uint32_t aIndex);
uint32_t GetVolumeByCategory(uint32_t aCategory) const;
uint32_t GetMaxVolumeByCategory(uint32_t aCategory) const;
AudioProfileData* FindAudioProfileData(AudioOutputProfiles aProfile);
// Append the profile to the volume setting string.
// Append the audio output profile to the volume setting string.
nsAutoCString AppendProfileToVolumeSetting(const char* aName,
AudioOutputProfiles aProfile);
// We store the volume setting in the database, these are related functions.
void InitVolumeFromDatabase();
void UpdateVolumeSettingToDatabase(nsISettingsServiceLock* aLock,
const char* aTopic,
uint32_t aVolIndex);
void MaybeUpdateVolumeSettingToDatabase(bool aForce = false);
// Promise functions.
void InitProfileVolumeSucceeded();
void InitProfileVolumeFailed(const char* aError);
void AudioOutProfileUpdated(AudioOutputProfiles aProfile);
void UpdateHeadsetConnectionState(hal::SwitchState aState);
void UpdateDeviceConnectionState(bool aIsConnected, uint32_t aDevice, const nsCString& aDeviceName);
void SetAllDeviceConnectionStates();
AudioManager();
~AudioManager();
friend class VolumeInitCallback;
friend class VolumeStreamState;
friend class GonkAudioPortCallback;
};
} /* namespace gonk */

View File

@ -969,6 +969,9 @@ public:
static status_t getStreamVolumeIndex(audio_stream_type_t stream, int *index);
static uint32_t getStrategyForStream(stream_type stream);
#if ANDROID_VERSION >= 17
static audio_devices_t getDevicesForStream(audio_stream_type_t stream);
#endif
static audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc);
static status_t registerEffect(effect_descriptor_t *desc,
@ -995,6 +998,23 @@ public:
static bool isLinearPCM(uint32_t format);
static bool isModeInCall();
#if ANDROID_VERSION >= 21
class AudioPortCallback : public RefBase
{
public:
AudioPortCallback() {}
virtual ~AudioPortCallback() {}
virtual void onAudioPortListUpdate() = 0;
virtual void onAudioPatchListUpdate() = 0;
virtual void onServiceDied() = 0;
};
static void setAudioPortCallback(sp<AudioPortCallback> callBack);
#endif
private:
class AudioFlingerClient: public IBinder::DeathRecipient, public BnAudioFlingerClient

View File

@ -41,6 +41,7 @@ var radioInterface = ril.getRadioInterface(0);
ok(radioInterface, "radioInterface.constructor is " + radioInterface.constrctor);
var _pendingEmulatorShellCmdCount = 0;
var _pendingEmulatorCmdCount = 0;
/**
* Send emulator shell command with safe guard.
@ -69,6 +70,41 @@ function runEmulatorShellCmdSafe(aCommands) {
});
}
/**
* Send emulator command with safe guard.
*
* We should only call |finish()| after all emulator command transactions
* end, so here comes with the pending counter. Resolve when the emulator
* gives positive response, and reject otherwise.
*
* Fulfill params:
* result -- an array of emulator response lines.
* Reject params:
* result -- an array of emulator response lines.
*
* @param aCommand
* A string command to be passed to emulator through its telnet console.
*
* @return A deferred promise.
*/
function runEmulatorCmdSafe(aCommand) {
log(aCommand);
return new Promise(function(aResolve, aReject) {
++_pendingEmulatorCmdCount;
runEmulatorCmd(aCommand, function(aResult) {
--_pendingEmulatorCmdCount;
log("Emulator console response: " + JSON.stringify(aResult));
if (Array.isArray(aResult) &&
aResult[aResult.length - 1] === "OK") {
aResolve(aResult);
} else {
aReject(aResult);
}
});
});
}
/**
* Get mozSettings value specified by @aKey.
*
@ -286,11 +322,11 @@ function cleanUp() {
ok(true, ":: CLEANING UP ::");
waitFor(finish, function() {
return _pendingEmulatorShellCmdCount === 0;
return _pendingEmulatorShellCmdCount === 0 &&
_pendingEmulatorCmdCount === 0;
});
}
/**
* Basic test routine helper.
*

View File

@ -17,3 +17,5 @@ disabled = Bug 808783
[test_all_network_info.js]
[test_network_interface_mtu.js]
skip-if = android_version < '19'
[test_timezone_changes.js]
skip-if = android_version < '19'

View File

@ -0,0 +1,135 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
MARIONETTE_TIMEOUT = 60000;
MARIONETTE_HEAD_JS = 'head.js';
function init() {
let promises = [];
/*
* The initial timezone of the emulator could be anywhere, depends the host
* machine. Ensure resetting it to UTC before testing.
*/
promises.push(runEmulatorCmdSafe('gsm timezone 0'));
promises.push(new Promise((aResolve, aReject) => {
waitFor(aResolve, () => {
return new Date().getTimezoneOffset() === 0;
});
}));
return Promise.all(promises);
}
function paddingZeros(aNumber, aLength) {
let str = '' + aNumber;
while (str.length < aLength) {
str = '0' + str;
}
return str;
}
function verifyDate(aTestDate, aUTCOffsetDate) {
// Verify basic properties.
is(aUTCOffsetDate.getUTCFullYear(), aTestDate.getFullYear(), 'year');
is(aUTCOffsetDate.getUTCMonth(), aTestDate.getMonth(), 'month');
is(aUTCOffsetDate.getUTCDate(), aTestDate.getDate(), 'date');
is(aUTCOffsetDate.getUTCHours(), aTestDate.getHours(), 'hours');
is(aUTCOffsetDate.getUTCMinutes(), aTestDate.getMinutes(), 'minutes');
is(aUTCOffsetDate.getUTCMilliseconds(), aTestDate.getMilliseconds(), 'milliseconds');
// Ensure toLocaleString also uses correct timezone.
// It uses ICU's timezone instead of the offset calculated from gecko prtime.
let expectedDateString =
paddingZeros(aUTCOffsetDate.getUTCMonth() + 1, 2) + '/' +
paddingZeros(aUTCOffsetDate.getUTCDate(), 2);
let dateString = aTestDate.toLocaleString('en-US', {
month: '2-digit',
day: '2-digit',
});
let expectedTimeString =
paddingZeros(aUTCOffsetDate.getUTCHours(), 2) + ':' +
paddingZeros(aUTCOffsetDate.getUTCMinutes(), 2);
let timeString = aTestDate.toLocaleString('en-US', {
hour12: false,
hour: '2-digit',
minute: '2-digit'
});
is(expectedDateString, dateString, 'dateString');
is(expectedTimeString, timeString, 'timeString');
}
function waitForTimezoneUpdate(aTzOffset,
aTestDateInMillis = 86400000, // Use 'UTC 00:00:00, 2nd of Jan, 1970' by default.
aTransTzOffset, aTransTestDateInMillis) {
return new Promise(function(aResolve, aReject) {
window.addEventListener('moztimechange', function onevent(aEvent) {
// Since there could be multiple duplicate moztimechange event, wait until
// timezone is actually changed to expected value before removing the
// listener.
let testDate = new Date(aTestDateInMillis);
if (testDate.getTimezoneOffset() === aTzOffset) {
window.removeEventListener('moztimechange', onevent);
// The UTC time of offsetDate is the same as the expected local time of
// testDate. We'll use it to verify the values.
let offsetDate = new Date(aTestDateInMillis - aTzOffset * 60 * 1000);
verifyDate(testDate, offsetDate);
// Verify transition time if given.
if (aTransTzOffset !== undefined) {
testDate = new Date(aTransTestDateInMillis);
is(testDate.getTimezoneOffset(), aTransTzOffset);
// Verify transition date.
offsetDate = new Date(aTransTestDateInMillis - aTransTzOffset * 60 * 1000);
verifyDate(testDate, offsetDate);
}
aResolve(aEvent);
}
});
});
}
function testChangeNitzTimezone(aTzDiff) {
let promises = [];
// aTzOffset should be the expected value for getTimezoneOffset().
// Note that getTimezoneOffset() is not so straightforward,
// it values (UTC - localtime), so UTC+08:00 returns -480.
promises.push(waitForTimezoneUpdate(-aTzDiff * 15));
promises.push(runEmulatorCmdSafe('gsm timezone ' + aTzDiff));
return Promise.all(promises);
}
function testChangeOlsonTimezone(aOlsonTz, aTzOffset, aTestDateInMillis,
aTransTzOffset, aTransTestDateInMillis) {
let promises = [];
promises.push(waitForTimezoneUpdate(aTzOffset, aTestDateInMillis,
aTransTzOffset, aTransTestDateInMillis));
promises.push(setSettings('time.timezone', aOlsonTz));
return Promise.all(promises);
}
// Start test
startTestBase(function() {
return init()
.then(() => testChangeNitzTimezone(36)) // UTC+09:00
.then(() => testChangeOlsonTimezone('America/New_York',
300, 1446357600000, // 2015/11/01 02:00 UTC-04:00 => 01:00 UTC-05:00 (EST)
240, 1425798000000)) // 2015/03/08 02:00 UTC-05:00 => 03:00 UTC-04:00 (EDT)
.then(() => testChangeNitzTimezone(-22)) // UTC-05:30
.then(() => testChangeNitzTimezone(51)) // UTC+12:45
.then(() => testChangeOlsonTimezone('Australia/Adelaide',
-570, 1428165000000, // 2015/04/05 03:00 UTC+10:30 => 02:00 UTC+09:30 (ACST)
-630, 1443889800000)) // 2015/10/04 02:00 UTC+09:30 => 03:00 UTC+10:30 (ACDT)
.then(() => testChangeNitzTimezone(-38)) // UTC-09:30
.then(() => testChangeNitzTimezone(0)) // UTC
.then(() => runEmulatorCmdSafe('gsm timezone auto'));
});

View File

@ -95,7 +95,7 @@ nsXULContentUtils::Init()
#define XUL_LITERAL(ident, val) \
PR_BEGIN_MACRO \
rv = gRDF->GetLiteral(NS_LITERAL_STRING(val).get(), &(ident)); \
rv = gRDF->GetLiteral(MOZ_UTF16(val), &(ident)); \
if (NS_FAILED(rv)) return rv; \
PR_END_MACRO

View File

@ -110,7 +110,7 @@ CopyBGRXSurfaceDataToPackedBGRArray(uint8_t* aSrc, uint8_t* aDst,
}
}
uint8_t*
UniquePtr<uint8_t[]>
SurfaceToPackedBGRA(DataSourceSurface *aSurface)
{
SurfaceFormat format = aSurface->GetFormat();
@ -120,25 +120,25 @@ SurfaceToPackedBGRA(DataSourceSurface *aSurface)
IntSize size = aSurface->GetSize();
uint8_t* imageBuffer = new (std::nothrow) uint8_t[size.width * size.height * sizeof(uint32_t)];
UniquePtr<uint8_t[]> imageBuffer(
new (std::nothrow) uint8_t[size.width * size.height * sizeof(uint32_t)]);
if (!imageBuffer) {
return nullptr;
}
DataSourceSurface::MappedSurface map;
if (!aSurface->Map(DataSourceSurface::MapType::READ, &map)) {
delete [] imageBuffer;
return nullptr;
}
CopySurfaceDataToPackedArray(map.mData, imageBuffer, size,
CopySurfaceDataToPackedArray(map.mData, imageBuffer.get(), size,
map.mStride, 4 * sizeof(uint8_t));
aSurface->Unmap();
if (format == SurfaceFormat::B8G8R8X8) {
// Convert BGRX to BGRA by setting a to 255.
ConvertBGRXToBGRA(reinterpret_cast<uint8_t *>(imageBuffer), size, size.width * sizeof(uint32_t));
ConvertBGRXToBGRA(imageBuffer.get(), size, size.width * sizeof(uint32_t));
}
return imageBuffer;

View File

@ -8,6 +8,8 @@
#include "2D.h"
#include "mozilla/UniquePtr.h"
namespace mozilla {
namespace gfx {
@ -25,11 +27,9 @@ CopySurfaceDataToPackedArray(uint8_t* aSrc, uint8_t* aDst, IntSize aSrcSize,
int32_t aSrcStride, int32_t aBytesPerPixel);
/**
* Convert aSurface to a packed buffer in BGRA format. The pixel data is
* returned in a buffer allocated with new uint8_t[]. The caller then has
* ownership of the buffer and is responsible for delete[]'ing it.
* Convert aSurface to a packed buffer in BGRA format.
*/
uint8_t*
UniquePtr<uint8_t[]>
SurfaceToPackedBGRA(DataSourceSurface *aSurface);
/**

View File

@ -110,7 +110,7 @@ struct LayerPropertiesBase : public LayerProperties
, mPostXScale(aLayer->GetPostXScale())
, mPostYScale(aLayer->GetPostYScale())
, mOpacity(aLayer->GetLocalOpacity())
, mUseClipRect(!!aLayer->GetClipRect())
, mUseClipRect(!!aLayer->GetEffectiveClipRect())
{
MOZ_COUNT_CTOR(LayerPropertiesBase);
if (aLayer->GetMaskLayer()) {
@ -121,7 +121,7 @@ struct LayerPropertiesBase : public LayerProperties
mAncestorMaskLayers.AppendElement(CloneLayerTreePropertiesInternal(maskLayer, true));
}
if (mUseClipRect) {
mClipRect = *aLayer->GetClipRect();
mClipRect = *aLayer->GetEffectiveClipRect();
}
mTransform = aLayer->GetLocalTransform();
}
@ -148,7 +148,7 @@ struct LayerPropertiesBase : public LayerProperties
bool transformChanged = !mTransform.FuzzyEqualsMultiplicative(mLayer->GetLocalTransform()) ||
mLayer->GetPostXScale() != mPostXScale ||
mLayer->GetPostYScale() != mPostYScale;
const Maybe<ParentLayerIntRect>& otherClip = mLayer->GetClipRect();
const Maybe<ParentLayerIntRect>& otherClip = mLayer->GetEffectiveClipRect();
nsIntRegion result;
bool ancestorMaskChanged = mAncestorMaskLayers.Length() != mLayer->GetAncestorMaskLayerCount();

View File

@ -688,6 +688,7 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
switch (aEvent.mInputType) {
case MULTITOUCH_INPUT: {
MultiTouchInput& touchInput = aEvent.AsMultiTouchInput();
touchInput.mHandledByAPZ = true;
result = ProcessTouchInput(touchInput, aOutTargetGuid, aOutInputBlockId);
break;
} case MOUSE_INPUT: {

View File

@ -97,7 +97,8 @@ InputQueue::ReceiveTouchInput(const RefPtr<AsyncPanZoomController>& aTarget,
}
block = StartNewTouchBlock(aTarget, aTargetConfirmed, false);
INPQ_LOG("started new touch block %p for target %p\n", block, aTarget.get());
INPQ_LOG("started new touch block %p id %" PRIu64 " for target %p\n",
block, block->GetBlockId(), aTarget.get());
// XXX using the chain from |block| here may be wrong in cases where the
// target isn't confirmed and the real target turns out to be something

View File

@ -262,21 +262,27 @@ APZEventState::ProcessTouchEvent(const WidgetTouchEvent& aEvent,
bool isTouchPrevented = TouchManager::gPreventMouseEvents ||
aEvent.mFlags.mMultipleActionsPrevented;
bool sentContentResponse = false;
APZES_LOG("Handling event type %d\n", aEvent.mMessage);
switch (aEvent.mMessage) {
case eTouchStart: {
mTouchEndCancelled = false;
if (mPendingTouchPreventedResponse) {
// We can enter here if we get two TOUCH_STARTs in a row and didn't
// respond to the first one. Respond to it now.
mContentReceivedInputBlockCallback(mPendingTouchPreventedGuid,
mPendingTouchPreventedBlockId, false);
sentContentResponse = true;
mPendingTouchPreventedResponse = false;
sentContentResponse = SendPendingTouchPreventedResponse(false);
// sentContentResponse can be true here if we get two TOUCH_STARTs in a row
// and just responded to the first one.
if (!aEvent.mFlags.mHandledByAPZ) {
// This condition being true means this touchstart is synthetic and is
// coming from TabParent.injectTouchEvent.
// Since APZ doesn't know about it we don't want to send a response for
// this block; we want to just skip over it from the point of view of
// prevent-default notifications.
break;
}
if (isTouchPrevented) {
mContentReceivedInputBlockCallback(aGuid, aInputBlockId, isTouchPrevented);
sentContentResponse = true;
} else {
APZES_LOG("Event not prevented; pending response for %" PRIu64 " %s\n",
aInputBlockId, Stringify(aGuid).c_str());
mPendingTouchPreventedResponse = true;
mPendingTouchPreventedGuid = aGuid;
mPendingTouchPreventedBlockId = aInputBlockId;
@ -410,6 +416,8 @@ bool
APZEventState::SendPendingTouchPreventedResponse(bool aPreventDefault)
{
if (mPendingTouchPreventedResponse) {
APZES_LOG("Sending response %d for pending guid: %s\n", aPreventDefault,
Stringify(mPendingTouchPreventedGuid).c_str());
mContentReceivedInputBlockCallback(mPendingTouchPreventedGuid,
mPendingTouchPreventedBlockId, aPreventDefault);
mPendingTouchPreventedResponse = false;

View File

@ -69,6 +69,7 @@ public:
BasicCompositor::BasicCompositor(nsIWidget *aWidget)
: mWidget(aWidget)
, mDidExternalComposition(false)
{
MOZ_COUNT_CTOR(BasicCompositor);
@ -509,9 +510,16 @@ BasicCompositor::BeginFrame(const nsIntRegion& aInvalidRegion,
IntRect intRect = gfx::IntRect(IntPoint(), mWidgetSize);
Rect rect = Rect(0, 0, intRect.width, intRect.height);
// Sometimes the invalid region is larger than we want to draw.
nsIntRegion invalidRegionSafe;
invalidRegionSafe.And(aInvalidRegion, intRect);
if (mDidExternalComposition) {
// We do not know rendered region during external composition, just redraw
// whole widget.
invalidRegionSafe = intRect;
mDidExternalComposition = false;
} else {
// Sometimes the invalid region is larger than we want to draw.
invalidRegionSafe.And(aInvalidRegion, intRect);
}
IntRect invalidRect = invalidRegionSafe.GetBounds();
mInvalidRect = IntRect(invalidRect.x, invalidRect.y, invalidRect.width, invalidRect.height);
@ -610,5 +618,16 @@ BasicCompositor::EndFrame()
mRenderTarget = nullptr;
}
void
BasicCompositor::EndFrameForExternalComposition(const gfx::Matrix& aTransform)
{
MOZ_ASSERT(!mTarget);
MOZ_ASSERT(!mDrawTarget);
MOZ_ASSERT(!mRenderTarget);
mDidExternalComposition = true;
}
} // namespace layers
} // namespace mozilla

View File

@ -90,12 +90,7 @@ public:
gfx::Rect *aClipRectOut = nullptr,
gfx::Rect *aRenderBoundsOut = nullptr) override;
virtual void EndFrame() override;
virtual void EndFrameForExternalComposition(const gfx::Matrix& aTransform) override
{
MOZ_ASSERT(!mTarget);
MOZ_ASSERT(!mDrawTarget);
MOZ_ASSERT(!mRenderTarget);
}
virtual void EndFrameForExternalComposition(const gfx::Matrix& aTransform) override;
virtual bool SupportsPartialTextureUpdate() override { return true; }
virtual bool CanUseCanvasLayerForSize(const gfx::IntSize &aSize) override { return true; }
@ -134,6 +129,7 @@ private:
gfx::IntRect mInvalidRect;
nsIntRegion mInvalidRegion;
bool mDidExternalComposition;
uint32_t mMaxTextureSize;
};

View File

@ -431,23 +431,21 @@ ShadowLayerForwarder::RemoveTextureFromCompositableAsync(AsyncTransactionTracker
CompositableClient* aCompositable,
TextureClient* aTexture)
{
#ifdef MOZ_WIDGET_GONK
mPendingAsyncMessages.push_back(OpRemoveTextureAsync(CompositableClient::GetTrackersHolderId(aCompositable->GetIPDLActor()),
aAsyncTransactionTracker->GetId(),
nullptr, aCompositable->GetIPDLActor(),
nullptr, aTexture->GetIPDLActor()));
#else
if (mTxn->Opened() && !aCompositable->IsDestroyed()) {
mTxn->AddEdit(OpRemoveTextureAsync(CompositableClient::GetTrackersHolderId(aCompositable->GetIPDLActor()),
aAsyncTransactionTracker->GetId(),
nullptr, aCompositable->GetIPDLActor(),
nullptr, aTexture->GetIPDLActor()));
} else {
// If the function is called outside of transaction,
// OpRemoveTextureAsync message is stored as pending message.
#ifdef MOZ_WIDGET_GONK
mPendingAsyncMessages.push_back(OpRemoveTextureAsync(CompositableClient::GetTrackersHolderId(aCompositable->GetIPDLActor()),
aAsyncTransactionTracker->GetId(),
nullptr, aCompositable->GetIPDLActor(),
nullptr, aTexture->GetIPDLActor()));
#else
NS_RUNTIMEABORT("not reached");
#endif
}
#endif
CompositableClient::HoldUntilComplete(aCompositable->GetIPDLActor(),
aAsyncTransactionTracker);
}

View File

@ -1547,26 +1547,24 @@ gfxUtils::CopyAsDataURI(DrawTarget* aDT)
}
}
/* static */ void
/* static */ UniquePtr<uint8_t[]>
gfxUtils::GetImageBuffer(gfx::DataSourceSurface* aSurface,
bool aIsAlphaPremultiplied,
uint8_t** outImageBuffer,
int32_t* outFormat)
{
*outImageBuffer = nullptr;
*outFormat = 0;
DataSourceSurface::MappedSurface map;
if (!aSurface->Map(DataSourceSurface::MapType::READ, &map))
return;
return nullptr;
uint32_t bufferSize = aSurface->GetSize().width * aSurface->GetSize().height * 4;
uint8_t* imageBuffer = new (fallible) uint8_t[bufferSize];
UniquePtr<uint8_t[]> imageBuffer(new (fallible) uint8_t[bufferSize]);
if (!imageBuffer) {
aSurface->Unmap();
return;
return nullptr;
}
memcpy(imageBuffer, map.mData, bufferSize);
memcpy(imageBuffer.get(), map.mData, bufferSize);
aSurface->Unmap();
@ -1577,12 +1575,12 @@ gfxUtils::GetImageBuffer(gfx::DataSourceSurface* aSurface,
// Yes, it is THAT silly.
// Except for different lossy conversions by color,
// we could probably just change the label, and not change the data.
gfxUtils::ConvertBGRAtoRGBA(imageBuffer, bufferSize);
gfxUtils::ConvertBGRAtoRGBA(imageBuffer.get(), bufferSize);
format = imgIEncoder::INPUT_FORMAT_RGBA;
}
*outImageBuffer = imageBuffer;
*outFormat = format;
return imageBuffer;
}
/* static */ nsresult
@ -1598,15 +1596,14 @@ gfxUtils::GetInputStream(gfx::DataSourceSurface* aSurface,
if (!encoder)
return NS_ERROR_FAILURE;
nsAutoArrayPtr<uint8_t> imageBuffer;
int32_t format = 0;
GetImageBuffer(aSurface, aIsAlphaPremultiplied, getter_Transfers(imageBuffer), &format);
UniquePtr<uint8_t[]> imageBuffer = GetImageBuffer(aSurface, aIsAlphaPremultiplied, &format);
if (!imageBuffer)
return NS_ERROR_FAILURE;
return dom::ImageEncoder::GetInputStream(aSurface->GetSize().width,
aSurface->GetSize().height,
imageBuffer, format,
imageBuffer.get(), format,
encoder, aEncoderOptions, outStream);
}

View File

@ -10,6 +10,7 @@
#include "imgIContainer.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/RefPtr.h"
#include "mozilla/UniquePtr.h"
#include "nsColor.h"
#include "nsPrintfCString.h"
#include "mozilla/gfx/Rect.h"
@ -282,10 +283,9 @@ public:
static nsCString GetAsDataURI(DrawTarget* aDT);
static nsCString GetAsLZ4Base64Str(DataSourceSurface* aSourceSurface);
static void GetImageBuffer(DataSourceSurface* aSurface,
bool aIsAlphaPremultiplied,
uint8_t** outImageBuffer,
int32_t* outFormat);
static mozilla::UniquePtr<uint8_t[]> GetImageBuffer(DataSourceSurface* aSurface,
bool aIsAlphaPremultiplied,
int32_t* outFormat);
static nsresult GetInputStream(DataSourceSurface* aSurface,
bool aIsAlphaPremultiplied,

View File

@ -219,12 +219,17 @@ elif [[ "$VARIANT" = arm64* ]]; then
fi
$COMMAND_PREFIX $MAKE check || exit 1
RESULT=0
if $RUN_JITTEST; then
$COMMAND_PREFIX $MAKE check-jit-test || exit 1
$COMMAND_PREFIX $MAKE check-jit-test || RESULT=$?
fi
if $RUN_JSAPITESTS; then
$COMMAND_PREFIX $OBJDIR/dist/bin/jsapi-tests || exit 1
$COMMAND_PREFIX $OBJDIR/dist/bin/jsapi-tests || RESULT=$?
fi
if $RUN_JSTESTS; then
$COMMAND_PREFIX $MAKE check-jstests || exit 1
$COMMAND_PREFIX $MAKE check-jstests || RESULT=$?
fi
exit $RESULT

View File

@ -3145,16 +3145,15 @@ Parser<ParseHandler>::maybeParseDirective(Node list, Node pn, bool* cont)
// Request that this function be reparsed as strict.
pc->newDirectives->setStrict();
return false;
} else {
// We don't reparse global scopes, so we keep track of the
// one possible strict violation that could occur in the
// directive prologue -- octal escapes -- and complain now.
if (tokenStream.sawOctalEscape()) {
report(ParseError, false, null(), JSMSG_DEPRECATED_OCTAL);
return false;
}
pc->sc->strictScript = true;
}
// We don't reparse global scopes, so we keep track of the one
// possible strict violation that could occur in the directive
// prologue -- octal escapes -- and complain now.
if (tokenStream.sawOctalEscape()) {
report(ParseError, false, null(), JSMSG_DEPRECATED_OCTAL);
return false;
}
pc->sc->strictScript = true;
}
} else if (directive == context->names().useAsm) {
if (pc->sc->isFunctionBox())

View File

@ -0,0 +1,24 @@
function O() {
this.x = 1;
this.y = 2;
}
function testUnboxed() {
var arr = [];
for (var i=0; i<100; i++)
arr.push(new O);
var o = arr[arr.length-1];
o[0] = 0;
o[2] = 2;
var sym = Symbol();
o[sym] = 1;
o.z = 3;
Object.defineProperty(o, '3', {value:1,enumerable:false,configurable:false,writable:false});
o[4] = 4;
var props = Reflect.ownKeys(o);
assertEq(props[props.length-1], sym);
assertEq(Object.getOwnPropertyNames(o).join(""), "0234xyz");
}
testUnboxed();

View File

@ -0,0 +1,10 @@
// |jit-test| error: ReferenceError
if (!('oomTest' in this))
a;
enableShellObjectMetadataCallback()
oomTest(() => {
newGlobal()
})
gczeal(9, 1);
a;

View File

@ -0,0 +1,12 @@
if (!('oomAfterAllocations' in this))
quit();
gcslice(0); // Start IGC, but don't mark anything.
function f(str) {
for (var i = 0; i < 10; i++) {
arr = /foo(ba(r))?/.exec(str);
var x = arr[oomAfterAllocations(100)] + " " + arr[1] + " " + 1899;
}
}
try {
f("foo");
} catch(e) {}

View File

@ -0,0 +1,25 @@
function f() {
const b = 0;
switch (1) {
case b = 0:
}
}
var err;
try {
f();
} catch(e) {
err = e;
}
assertEq(err.name, "TypeError");
function g() {
const z = 0;
while (z = 1) {}
}
err = null;
try {
g();
} catch(e) {
err = e;
}
assertEq(err.name, "TypeError");

View File

@ -1441,6 +1441,8 @@ JitCompartment::generateRegExpExecStub(JSContext* cx)
Linker linker(masm);
AutoFlushICache afc("RegExpExecStub");
JitCode* code = linker.newCode<CanGC>(cx, OTHER_CODE);
if (!code)
return nullptr;
#ifdef JS_ION_PERF
writePerfSpewerJitCodeProfile(code, "RegExpExecStub");
@ -1572,6 +1574,8 @@ JitCompartment::generateRegExpTestStub(JSContext* cx)
Linker linker(masm);
AutoFlushICache afc("RegExpTestStub");
JitCode* code = linker.newCode<CanGC>(cx, OTHER_CODE);
if (!code)
return nullptr;
#ifdef JS_ION_PERF
writePerfSpewerJitCodeProfile(code, "RegExpTestStub");

View File

@ -1586,10 +1586,6 @@ IonBuilder::snoopControlFlow(JSOp op)
case JSOP_THROW:
return processThrow();
case JSOP_THROWSETCONST:
case JSOP_THROWSETALIASEDCONST:
return processThrowSetConst();
case JSOP_GOTO:
{
jssrcnote* sn = info().getNote(gsn, pc);
@ -1778,6 +1774,10 @@ IonBuilder::inspectOpcode(JSOp op)
current->setLocal(GET_LOCALNO(pc));
return true;
case JSOP_THROWSETCONST:
case JSOP_THROWSETALIASEDCONST:
return jsop_throwsetconst();
case JSOP_CHECKLEXICAL:
return jsop_checklexical();
@ -12740,20 +12740,13 @@ IonBuilder::jsop_deffun(uint32_t index)
return resumeAfter(deffun);
}
IonBuilder::ControlStatus
IonBuilder::processThrowSetConst()
bool
IonBuilder::jsop_throwsetconst()
{
current->peek(-1)->setImplicitlyUsedUnchecked();
MInstruction* lexicalError = MThrowRuntimeLexicalError::New(alloc(), JSMSG_BAD_CONST_ASSIGN);
current->add(lexicalError);
if (!resumeAfter(lexicalError))
return ControlStatus_Error;
current->end(MUnreachable::New(alloc()));
// Make sure no one tries to use this block now.
setCurrent(nullptr);
return processControlEnd();
return resumeAfter(lexicalError);
}
bool

View File

@ -263,7 +263,6 @@ class IonBuilder
ControlStatus processTryEnd(CFGState& state);
ControlStatus processReturn(JSOp op);
ControlStatus processThrow();
ControlStatus processThrowSetConst();
ControlStatus processContinue(JSOp op);
ControlStatus processBreak(JSOp op, jssrcnote* sn);
ControlStatus maybeLoop(JSOp op, jssrcnote* sn);
@ -659,6 +658,7 @@ class IonBuilder
bool jsop_deflexical(uint32_t index);
bool jsop_deffun(uint32_t index);
bool jsop_notearg();
bool jsop_throwsetconst();
bool jsop_checklexical();
bool jsop_checkaliasedlet(ScopeCoordinate sc);
bool jsop_funcall(uint32_t argc);

View File

@ -420,12 +420,14 @@ class MacroAssembler : public MacroAssemblerSpecific
// ===============================================================
// Stack manipulation functions.
void PushRegsInMask(LiveRegisterSet set) PER_SHARED_ARCH;
void PushRegsInMask(LiveRegisterSet set)
DEFINED_ON(arm, arm64, mips32, x86_shared);
void PushRegsInMask(LiveGeneralRegisterSet set);
void PopRegsInMask(LiveRegisterSet set);
void PopRegsInMask(LiveGeneralRegisterSet set);
void PopRegsInMaskIgnore(LiveRegisterSet set, LiveRegisterSet ignore) PER_SHARED_ARCH;
void PopRegsInMaskIgnore(LiveRegisterSet set, LiveRegisterSet ignore)
DEFINED_ON(arm, arm64, mips32, x86_shared);
void Push(const Operand op) DEFINED_ON(x86_shared);
void Push(Register reg) PER_SHARED_ARCH;

View File

@ -793,63 +793,6 @@ MacroAssemblerMIPSShared::asMasm() const
// ===============================================================
// Stack manipulation functions.
void
MacroAssembler::PushRegsInMask(LiveRegisterSet set)
{
int32_t diffF = set.fpus().getPushSizeInBytes();
int32_t diffG = set.gprs().size() * sizeof(intptr_t);
reserveStack(diffG);
for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) {
diffG -= sizeof(intptr_t);
storePtr(*iter, Address(StackPointer, diffG));
}
MOZ_ASSERT(diffG == 0);
// Double values have to be aligned. We reserve extra space so that we can
// start writing from the first aligned location.
// We reserve a whole extra double so that the buffer has even size.
ma_and(SecondScratchReg, sp, Imm32(~(ABIStackAlignment - 1)));
reserveStack(diffF + sizeof(double));
for (FloatRegisterForwardIterator iter(set.fpus().reduceSetForPush()); iter.more(); iter++) {
if ((*iter).code() % 2 == 0)
as_sd(*iter, SecondScratchReg, -diffF);
diffF -= sizeof(double);
}
MOZ_ASSERT(diffF == 0);
}
void
MacroAssembler::PopRegsInMaskIgnore(LiveRegisterSet set, LiveRegisterSet ignore)
{
int32_t diffG = set.gprs().size() * sizeof(intptr_t);
int32_t diffF = set.fpus().getPushSizeInBytes();
const int32_t reservedG = diffG;
const int32_t reservedF = diffF;
// Read the buffer form the first aligned location.
ma_addu(SecondScratchReg, sp, Imm32(reservedF + sizeof(double)));
ma_and(SecondScratchReg, SecondScratchReg, Imm32(~(ABIStackAlignment - 1)));
for (FloatRegisterForwardIterator iter(set.fpus().reduceSetForPush()); iter.more(); iter++) {
if (!ignore.has(*iter) && ((*iter).code() % 2 == 0))
// Use assembly l.d because we have alligned the stack.
as_ld(*iter, SecondScratchReg, -diffF);
diffF -= sizeof(double);
}
freeStack(reservedF + sizeof(double));
MOZ_ASSERT(diffF == 0);
for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) {
diffG -= sizeof(intptr_t);
if (!ignore.has(*iter))
loadPtr(Address(StackPointer, diffG), *iter);
}
freeStack(reservedG);
MOZ_ASSERT(diffG == 0);
}
void
MacroAssembler::Push(Register reg)
{

View File

@ -2497,6 +2497,63 @@ MacroAssemblerMIPSCompat::profilerExitFrame()
// ===============================================================
// Stack manipulation functions.
void
MacroAssembler::PushRegsInMask(LiveRegisterSet set)
{
int32_t diffF = set.fpus().getPushSizeInBytes();
int32_t diffG = set.gprs().size() * sizeof(intptr_t);
reserveStack(diffG);
for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) {
diffG -= sizeof(intptr_t);
storePtr(*iter, Address(StackPointer, diffG));
}
MOZ_ASSERT(diffG == 0);
// Double values have to be aligned. We reserve extra space so that we can
// start writing from the first aligned location.
// We reserve a whole extra double so that the buffer has even size.
ma_and(SecondScratchReg, sp, Imm32(~(ABIStackAlignment - 1)));
reserveStack(diffF + sizeof(double));
for (FloatRegisterForwardIterator iter(set.fpus().reduceSetForPush()); iter.more(); iter++) {
if ((*iter).code() % 2 == 0)
as_sd(*iter, SecondScratchReg, -diffF);
diffF -= sizeof(double);
}
MOZ_ASSERT(diffF == 0);
}
void
MacroAssembler::PopRegsInMaskIgnore(LiveRegisterSet set, LiveRegisterSet ignore)
{
int32_t diffG = set.gprs().size() * sizeof(intptr_t);
int32_t diffF = set.fpus().getPushSizeInBytes();
const int32_t reservedG = diffG;
const int32_t reservedF = diffF;
// Read the buffer form the first aligned location.
ma_addu(SecondScratchReg, sp, Imm32(reservedF + sizeof(double)));
ma_and(SecondScratchReg, SecondScratchReg, Imm32(~(ABIStackAlignment - 1)));
for (FloatRegisterForwardIterator iter(set.fpus().reduceSetForPush()); iter.more(); iter++) {
if (!ignore.has(*iter) && ((*iter).code() % 2 == 0))
// Use assembly l.d because we have alligned the stack.
as_ld(*iter, SecondScratchReg, -diffF);
diffF -= sizeof(double);
}
freeStack(reservedF + sizeof(double));
MOZ_ASSERT(diffF == 0);
for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) {
diffG -= sizeof(intptr_t);
if (!ignore.has(*iter))
loadPtr(Address(StackPointer, diffG), *iter);
}
freeStack(reservedG);
MOZ_ASSERT(diffG == 0);
}
void
MacroAssembler::reserveStack(uint32_t amount)
{

View File

@ -554,10 +554,8 @@ JitRuntime::generateArgumentsRectifier(JSContext* cx, void** returnAddrOut)
AutoFlushICache afc("ArgumentsRectifier");
JitCode* code = linker.newCode<NoGC>(cx, OTHER_CODE);
CodeOffsetLabel returnLabel(returnOffset);
returnLabel.fixup(&masm);
if (returnAddrOut)
*returnAddrOut = (void*) (code->raw() + returnLabel.offset());
*returnAddrOut = (void*) (code->raw() + returnOffset);
#ifdef JS_ION_PERF
writePerfSpewerJitCodeProfile(code, "ArgumentsRectifier");
@ -1197,7 +1195,7 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
{
// scratch2 := StackPointer + Descriptor.size*1 + JitFrameLayout::Size();
masm.as_daddu(scratch2, StackPointer, scratch1);
masm.add32(Imm32(JitFrameLayout::Size()), scratch2);
masm.addPtr(Imm32(JitFrameLayout::Size()), scratch2);
masm.loadPtr(Address(scratch2, RectifierFrameLayout::offsetOfDescriptor()), scratch3);
masm.ma_dsrl(scratch1, scratch3, Imm32(FRAMESIZE_SHIFT));
masm.and32(Imm32((1 << FRAMETYPE_BITS) - 1), scratch3);
@ -1218,7 +1216,7 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
// scratch3 := RectFrame + Rect-Descriptor.Size + RectifierFrameLayout::Size()
masm.as_daddu(scratch3, scratch2, scratch1);
masm.add32(Imm32(RectifierFrameLayout::Size()), scratch3);
masm.addPtr(Imm32(RectifierFrameLayout::Size()), scratch3);
masm.storePtr(scratch3, lastProfilingFrame);
masm.ret();

View File

@ -447,7 +447,6 @@ JSCompartment::wrap(JSContext* cx, MutableHandleObject obj, HandleObject existin
if (obj->compartment() == this)
return true;
// If we already have a wrapper for this value, use it.
RootedValue key(cx, ObjectValue(*obj));
if (WrapperMap::Ptr p = crossCompartmentWrappers.lookup(CrossCompartmentKey(key))) {
@ -468,15 +467,27 @@ JSCompartment::wrap(JSContext* cx, MutableHandleObject obj, HandleObject existin
}
}
obj.set(cb->wrap(cx, existing, obj));
if (!obj)
RootedObject wrapper(cx, cb->wrap(cx, existing, obj));
if (!wrapper)
return false;
// We maintain the invariant that the key in the cross-compartment wrapper
// map is always directly wrapped by the value.
MOZ_ASSERT(Wrapper::wrappedObject(obj) == &key.get().toObject());
MOZ_ASSERT(Wrapper::wrappedObject(wrapper) == &key.get().toObject());
return putWrapper(cx, CrossCompartmentKey(key), ObjectValue(*obj));
if (!putWrapper(cx, CrossCompartmentKey(key), ObjectValue(*wrapper))) {
// Enforce the invariant that all cross-compartment wrapper object are
// in the map by nuking the wrapper if we couldn't add it.
// Unfortunately it's possible for the wrapper to still be marked if we
// took this path, for example if the object metadata callback stashes a
// reference to it.
if (wrapper->is<CrossCompartmentWrapperObject>())
NukeCrossCompartmentWrapper(cx, wrapper);
return false;
}
obj.set(wrapper);
return true;
}
bool

View File

@ -135,6 +135,33 @@ Enumerate(JSContext* cx, HandleObject pobj, jsid id,
return props->append(id);
}
static bool
EnumerateExtraProperties(JSContext* cx, HandleObject obj, unsigned flags, Maybe<IdSet>& ht,
AutoIdVector* props)
{
MOZ_ASSERT(obj->getOps()->enumerate);
AutoIdVector properties(cx);
bool enumerableOnly = !(flags & JSITER_HIDDEN);
if (!obj->getOps()->enumerate(cx, obj, properties, enumerableOnly))
return false;
RootedId id(cx);
for (size_t n = 0; n < properties.length(); n++) {
id = properties[n];
// The enumerate hook does not indicate whether the properties
// it returns are enumerable or not. Since we already passed
// `enumerableOnly` to the hook to filter out non-enumerable
// properties, it doesn't really matter what we pass here.
bool enumerable = true;
if (!Enumerate(cx, obj, id, enumerable, flags, ht, props))
return false;
}
return true;
}
static bool
SortComparatorIntegerIds(jsid a, jsid b, bool* lessOrEqualp)
{
@ -147,7 +174,7 @@ SortComparatorIntegerIds(jsid a, jsid b, bool* lessOrEqualp)
static bool
EnumerateNativeProperties(JSContext* cx, HandleNativeObject pobj, unsigned flags, Maybe<IdSet>& ht,
AutoIdVector* props)
AutoIdVector* props, Handle<UnboxedPlainObject*> unboxed = nullptr)
{
bool enumerateSymbols;
if (flags & JSITER_SYMBOLSONLY) {
@ -207,6 +234,16 @@ EnumerateNativeProperties(JSContext* cx, HandleNativeObject pobj, unsigned flags
return false;
}
if (unboxed) {
// If |unboxed| is set then |pobj| is the expando for an unboxed
// plain object we are enumerating. Add the unboxed properties
// themselves here since they are all property names that were
// given to the object before any of the expando's properties.
MOZ_ASSERT(pobj->is<UnboxedExpandoObject>());
if (!EnumerateExtraProperties(cx, unboxed, flags, ht, props))
return false;
}
size_t initialLength = props->length();
/* Collect all unique property names from this object's shape. */
@ -331,28 +368,23 @@ Snapshot(JSContext* cx, HandleObject pobj_, unsigned flags, AutoIdVector* props)
RootedObject pobj(cx, pobj_);
do {
if (JSNewEnumerateOp enumerate = pobj->getOps()->enumerate) {
AutoIdVector properties(cx);
bool enumerableOnly = !(flags & JSITER_HIDDEN);
if (!enumerate(cx, pobj, properties, enumerableOnly))
return false;
RootedId id(cx);
for (size_t n = 0; n < properties.length(); n++) {
id = properties[n];
// The enumerate hook does not indicate whether the properties
// it returns are enumerable or not. Since we already passed
// `enumerableOnly` to the hook to filter out non-enumerable
// properties, it doesn't really matter what we pass here.
bool enumerable = true;
if (!Enumerate(cx, pobj, id, enumerable, flags, ht, props))
if (pobj->getOps()->enumerate) {
if (pobj->is<UnboxedPlainObject>() && pobj->as<UnboxedPlainObject>().maybeExpando()) {
// Special case unboxed objects with an expando object.
RootedNativeObject expando(cx, pobj->as<UnboxedPlainObject>().maybeExpando());
if (!EnumerateNativeProperties(cx, expando, flags, ht, props,
pobj.as<UnboxedPlainObject>()))
{
return false;
}
if (pobj->isNative()) {
if (!EnumerateNativeProperties(cx, pobj.as<NativeObject>(), flags, ht, props))
}
} else {
if (!EnumerateExtraProperties(cx, pobj, flags, ht, props))
return false;
if (pobj->isNative()) {
if (!EnumerateNativeProperties(cx, pobj.as<NativeObject>(), flags, ht, props))
return false;
}
}
} else if (pobj->isNative()) {
// Give the object a chance to resolve all lazy properties

View File

@ -422,8 +422,6 @@ BytecodeFallsThrough(JSOp op)
case JSOP_RETRVAL:
case JSOP_FINALYIELDRVAL:
case JSOP_THROW:
case JSOP_THROWSETCONST:
case JSOP_THROWSETALIASEDCONST:
case JSOP_TABLESWITCH:
return false;
case JSOP_GOSUB:

View File

@ -637,7 +637,7 @@ ProxyObject::trace(JSTracer* trc, JSObject* obj)
#ifdef DEBUG
if (trc->runtime()->gc.isStrictProxyCheckingEnabled() && proxy->is<WrapperObject>()) {
JSObject* referent = MaybeForwarded(&proxy->private_().toObject());
JSObject* referent = MaybeForwarded(proxy->target());
if (referent->compartment() != proxy->compartment()) {
/*
* Assert that this proxy is tracked in the wrapper map. We maintain

View File

@ -8022,7 +8022,7 @@ DebuggerEnv_getCallee(JSContext* cx, unsigned argc, Value* vp)
return true;
JSObject& scope = env->as<DebugScopeObject>().scope();
if (!scope.is<CallObject>() || scope.is<ModuleEnvironmentObject>())
if (!scope.is<CallObject>())
return true;
CallObject& callobj = scope.as<CallObject>();

View File

@ -27,7 +27,7 @@ NearestEnclosingExtensibleLexicalScope(JSObject* scope)
inline void
ScopeObject::setAliasedVar(JSContext* cx, ScopeCoordinate sc, PropertyName* name, const Value& v)
{
MOZ_ASSERT(is<CallObject>() || is<ClonedBlockObject>());
MOZ_ASSERT(is<LexicalScopeBase>() || is<ClonedBlockObject>());
JS_STATIC_ASSERT(CallObject::RESERVED_SLOTS == BlockObject::RESERVED_SLOTS);
// name may be null if we don't need to track side effects on the object.
@ -48,7 +48,8 @@ ScopeObject::setAliasedVar(JSContext* cx, ScopeCoordinate sc, PropertyName* name
}
inline void
CallObject::setAliasedVar(JSContext* cx, AliasedFormalIter fi, PropertyName* name, const Value& v)
LexicalScopeBase::setAliasedVar(JSContext* cx, AliasedFormalIter fi, PropertyName* name,
const Value& v)
{
MOZ_ASSERT(name == fi->name());
setSlot(fi.scopeSlot(), v);
@ -57,7 +58,8 @@ CallObject::setAliasedVar(JSContext* cx, AliasedFormalIter fi, PropertyName* nam
}
inline void
CallObject::setAliasedVarFromArguments(JSContext* cx, const Value& argsValue, jsid id, const Value& v)
LexicalScopeBase::setAliasedVarFromArguments(JSContext* cx, const Value& argsValue, jsid id,
const Value& v)
{
setSlot(ArgumentsObject::SlotFromMagicScopeSlotValue(argsValue), v);
if (isSingleton())
@ -65,7 +67,7 @@ CallObject::setAliasedVarFromArguments(JSContext* cx, const Value& argsValue, js
}
inline void
CallObject::initRemainingSlotsToUninitializedLexicals(uint32_t begin)
LexicalScopeBase::initRemainingSlotsToUninitializedLexicals(uint32_t begin)
{
uint32_t end = slotSpan();
for (uint32_t slot = begin; slot < end; slot++)
@ -73,7 +75,7 @@ CallObject::initRemainingSlotsToUninitializedLexicals(uint32_t begin)
}
inline void
CallObject::initAliasedLexicalsToThrowOnTouch(JSScript* script)
LexicalScopeBase::initAliasedLexicalsToThrowOnTouch(JSScript* script)
{
initRemainingSlotsToUninitializedLexicals(script->bindings.aliasedBodyLevelLexicalBegin());
}

View File

@ -125,7 +125,7 @@ js::ScopeCoordinateFunctionScript(JSScript* script, jsbytecode* pc)
void
ScopeObject::setEnclosingScope(HandleObject obj)
{
MOZ_ASSERT_IF(obj->is<CallObject>() || obj->is<DeclEnvObject>() || obj->is<BlockObject>(),
MOZ_ASSERT_IF(obj->is<LexicalScopeBase>() || obj->is<DeclEnvObject>() || obj->is<BlockObject>(),
obj->isDelegate());
setFixedSlot(SCOPE_CHAIN_SLOT, ObjectValue(*obj));
}
@ -1755,9 +1755,7 @@ class DebugScopeProxy : public BaseProxyHandler
static bool isFunctionScope(const JSObject& scope)
{
return scope.is<CallObject>() &&
!scope.is<ModuleEnvironmentObject>() &&
!scope.as<CallObject>().isForEval();
return scope.is<CallObject>() && !scope.as<CallObject>().isForEval();
}
/*
@ -2169,7 +2167,7 @@ bool
DebugScopeObject::isForDeclarative() const
{
ScopeObject& s = scope();
return s.is<CallObject>() || s.is<BlockObject>() || s.is<DeclEnvObject>();
return s.is<LexicalScopeBase>() || s.is<BlockObject>() || s.is<DeclEnvObject>();
}
bool
@ -2190,7 +2188,7 @@ DebugScopeObject::isOptimizedOut() const
if (s.is<ClonedBlockObject>())
return !s.as<ClonedBlockObject>().staticBlock().needsClone();
if (s.is<CallObject>() && !s.is<ModuleEnvironmentObject>()) {
if (s.is<CallObject>()) {
return !s.as<CallObject>().isForEval() &&
!s.as<CallObject>().callee().needsCallObject() &&
!maybeSnapshot();

View File

@ -221,7 +221,9 @@ ScopeCoordinateFunctionScript(JSScript* script, jsbytecode* pc);
* | | |
* | | DeclEnvObject Holds name of recursive/needsCallObject named lambda
* | |
* | CallObject Scope of entire function or strict eval
* | LexicalScopeBase Shared base for function and modules scopes
* | | |
* | | CallObject Scope of entire function or strict eval
* | |
* | ModuleEnvironmentObject Module top-level scope on run-time scope chain
* |
@ -287,7 +289,36 @@ class ScopeObject : public NativeObject
}
};
class CallObject : public ScopeObject
class LexicalScopeBase : public ScopeObject
{
protected:
inline void initRemainingSlotsToUninitializedLexicals(uint32_t begin);
inline void initAliasedLexicalsToThrowOnTouch(JSScript* script);
public:
/* Get/set the aliased variable referred to by 'fi'. */
const Value& aliasedVar(AliasedFormalIter fi) {
return getSlot(fi.scopeSlot());
}
inline void setAliasedVar(JSContext* cx, AliasedFormalIter fi, PropertyName* name,
const Value& v);
/*
* When an aliased var (var accessed by nested closures) is also aliased by
* the arguments object, it must of course exist in one canonical location
* and that location is always the CallObject. For this to work, the
* ArgumentsObject stores special MagicValue in its array for forwarded-to-
* CallObject variables. This MagicValue's payload is the slot of the
* CallObject to access.
*/
const Value& aliasedVarFromArguments(const Value& argsValue) {
return getSlot(ArgumentsObject::SlotFromMagicScopeSlotValue(argsValue));
}
inline void setAliasedVarFromArguments(JSContext* cx, const Value& argsValue, jsid id,
const Value& v);
};
class CallObject : public LexicalScopeBase
{
protected:
static const uint32_t CALLEE_SLOT = 1;
@ -295,9 +326,6 @@ class CallObject : public ScopeObject
static CallObject*
create(JSContext* cx, HandleScript script, HandleObject enclosing, HandleFunction callee);
inline void initRemainingSlotsToUninitializedLexicals(uint32_t begin);
inline void initAliasedLexicalsToThrowOnTouch(JSScript* script);
public:
static const Class class_;
@ -347,27 +375,6 @@ class CallObject : public ScopeObject
return getFixedSlot(CALLEE_SLOT).toObject().as<JSFunction>();
}
/* Get/set the aliased variable referred to by 'bi'. */
const Value& aliasedVar(AliasedFormalIter fi) {
return getSlot(fi.scopeSlot());
}
inline void setAliasedVar(JSContext* cx, AliasedFormalIter fi, PropertyName* name,
const Value& v);
/*
* When an aliased var (var accessed by nested closures) is also aliased by
* the arguments object, it must of course exist in one canonical location
* and that location is always the CallObject. For this to work, the
* ArgumentsObject stores special MagicValue in its array for forwarded-to-
* CallObject variables. This MagicValue's payload is the slot of the
* CallObject to access.
*/
const Value& aliasedVarFromArguments(const Value& argsValue) {
return getSlot(ArgumentsObject::SlotFromMagicScopeSlotValue(argsValue));
}
inline void setAliasedVarFromArguments(JSContext* cx, const Value& argsValue, jsid id,
const Value& v);
/* For jit access. */
static size_t offsetOfCallee() {
return getFixedSlotOffset(CALLEE_SLOT);
@ -378,13 +385,15 @@ class CallObject : public ScopeObject
}
};
class ModuleEnvironmentObject : public CallObject
class ModuleEnvironmentObject : public LexicalScopeBase
{
static const uint32_t MODULE_SLOT = CallObject::CALLEE_SLOT;
static const uint32_t MODULE_SLOT = 1;
public:
static const Class class_;
static const uint32_t RESERVED_SLOTS = 2;
static ModuleEnvironmentObject* create(ExclusiveContext* cx, HandleModuleObject module);
ModuleObject& module();
IndirectBindingMap& importBindings();
@ -1262,9 +1271,9 @@ JSObject::is<js::NestedScopeObject>() const
template<>
inline bool
JSObject::is<js::CallObject>() const
JSObject::is<js::LexicalScopeBase>() const
{
return getClass() == &js::CallObject::class_ ||
return is<js::CallObject>() ||
is<js::ModuleEnvironmentObject>();
}
@ -1272,7 +1281,7 @@ template<>
inline bool
JSObject::is<js::ScopeObject>() const
{
return is<js::CallObject>() ||
return is<js::LexicalScopeBase>() ||
is<js::DeclEnvObject>() ||
is<js::NestedScopeObject>() ||
is<js::RuntimeLexicalErrorObject>() ||
@ -1343,7 +1352,7 @@ IsStaticGlobalLexicalScope(JSObject* scope)
inline const Value&
ScopeObject::aliasedVar(ScopeCoordinate sc)
{
MOZ_ASSERT(is<CallObject>() || is<ClonedBlockObject>());
MOZ_ASSERT(is<LexicalScopeBase>() || is<ClonedBlockObject>());
return getSlot(sc.slot());
}

View File

@ -35,10 +35,7 @@ namespace js {
static inline bool
IsCacheableNonGlobalScope(JSObject* obj)
{
bool cacheable =
(obj->is<CallObject>() && !obj->is<ModuleEnvironmentObject>()) ||
obj->is<BlockObject>() ||
obj->is<DeclEnvObject>();
bool cacheable = obj->is<CallObject>() || obj->is<BlockObject>() || obj->is<DeclEnvObject>();
MOZ_ASSERT_IF(cacheable, !obj->getOps()->lookupProperty);
return cacheable;

View File

@ -893,17 +893,8 @@ UnboxedPlainObject::obj_watch(JSContext* cx, HandleObject obj, HandleId id, Hand
UnboxedPlainObject::obj_enumerate(JSContext* cx, HandleObject obj, AutoIdVector& properties,
bool enumerableOnly)
{
UnboxedExpandoObject* expando = obj->as<UnboxedPlainObject>().maybeExpando();
// Add dense elements in the expando first, for consistency with plain objects.
if (expando) {
for (size_t i = 0; i < expando->getDenseInitializedLength(); i++) {
if (!expando->getDenseElement(i).isMagic(JS_ELEMENTS_HOLE)) {
if (!properties.append(INT_TO_JSID(i)))
return false;
}
}
}
// Ignore expando properties here, they are special-cased by the property
// enumeration code.
const UnboxedLayout::PropertyVector& unboxed = obj->as<UnboxedPlainObject>().layout().properties();
for (size_t i = 0; i < unboxed.length(); i++) {
@ -911,19 +902,6 @@ UnboxedPlainObject::obj_enumerate(JSContext* cx, HandleObject obj, AutoIdVector&
return false;
}
if (expando) {
Vector<jsid> ids(cx);
for (Shape::Range<NoGC> r(expando->lastProperty()); !r.empty(); r.popFront()) {
if (enumerableOnly && !r.front().enumerable())
continue;
if (!ids.append(r.front().propid()))
return false;
}
::Reverse(ids.begin(), ids.end());
if (!properties.append(ids.begin(), ids.length()))
return false;
}
return true;
}

View File

@ -63,3 +63,11 @@ skip-if((B2G&&browserIsRemote)||Mulet) == object-fit-scale-down-svg-005.xul obje
skip-if((B2G&&browserIsRemote)||Mulet) == object-fit-scale-down-svg-006.xul object-fit-scale-down-svg-006-ref.html
skip-if((B2G&&browserIsRemote)||Mulet) == object-position-png-001.xul object-position-png-001-ref.html
skip-if((B2G&&browserIsRemote)||Mulet) == object-position-png-002.xul object-position-png-002-ref.html
# Tests for rendering SVG images in a XUL <treecell>:
# XXXdholbert: These are marked as "random" right now, since they might not
# render the images they trying to test in time for the reftest snapshot, per
# bug 1218954. Once that bug is fixed, we should replace the "random"
# annotation with "skip-if((B2G&&browserIsRemote)||Mulet)", like above tests.
skip == treecell-image-svg-1a.xul treecell-image-svg-1-ref.xul # bug 1218954
skip == treecell-image-svg-1b.xul treecell-image-svg-1-ref.xul # bug 1218954

View File

@ -0,0 +1,17 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<tree seltype="single" flex="1">
<treecols>
<treecol flex="1"/>
</treecols>
<treechildren>
<treeitem>
<treerow>
<treecell src="colors-16x8.png"/>
</treerow>
</treeitem>
</treechildren>
</tree>
</window>

View File

@ -0,0 +1,17 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<tree seltype="single" flex="1">
<treecols>
<treecol flex="1"/>
</treecols>
<treechildren>
<treeitem>
<treerow>
<treecell src="colors-16x8.svg"/>
</treerow>
</treeitem>
</treechildren>
</tree>
</window>

View File

@ -0,0 +1,17 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<tree seltype="single" flex="1">
<treecols>
<treecol flex="1"/>
</treecols>
<treechildren>
<treeitem>
<treerow>
<treecell src="colors-16x8-noSize.svg"/>
</treerow>
</treeitem>
</treechildren>
</tree>
</window>

View File

@ -3607,26 +3607,35 @@ nsTreeBodyFrame::PaintImage(int32_t aRowIndex,
// Deflate destRect for the border and padding.
destRect.Deflate(bp);
// Get the image source rectangle - the rectangle containing the part of
// the image that we are going to display.
// sourceRect will be passed as the aSrcRect argument in the DrawImage method.
nsRect sourceRect = GetImageSourceRect(imageContext, useImageRegion, image);
// Let's say that the image is 100 pixels tall and
// that the CSS has specified that the destination height should be 50
// pixels tall. Let's say that the cell height is only 20 pixels. So, in
// those 20 visible pixels, we want to see the top 20/50ths of the image.
// So, the sourceRect.height should be 100 * 20 / 50, which is 40 pixels.
// Essentially, we are scaling the image as dictated by the CSS destination
// height and width, and we are then clipping the scaled image by the cell
// width and height.
// Compute the area where our whole image would be mapped, to get the
// desired subregion onto our actual destRect:
nsRect wholeImageDest;
CSSIntSize rawImageCSSIntSize;
image->GetWidth(&rawImageCSSIntSize.width);
image->GetHeight(&rawImageCSSIntSize.height);
nsSize rawImageSize(CSSPixel::ToAppUnits(rawImageCSSIntSize));
nsRect wholeImageDest =
nsLayoutUtils::GetWholeImageDestination(rawImageSize, sourceRect,
nsRect(destRect.TopLeft(), imageDestSize));
if (NS_SUCCEEDED(image->GetWidth(&rawImageCSSIntSize.width)) &&
NS_SUCCEEDED(image->GetHeight(&rawImageCSSIntSize.height))) {
// Get the image source rectangle - the rectangle containing the part of
// the image that we are going to display. sourceRect will be passed as
// the aSrcRect argument in the DrawImage method.
nsRect sourceRect = GetImageSourceRect(imageContext, useImageRegion, image);
// Let's say that the image is 100 pixels tall and that the CSS has
// specified that the destination height should be 50 pixels tall. Let's
// say that the cell height is only 20 pixels. So, in those 20 visible
// pixels, we want to see the top 20/50ths of the image. So, the
// sourceRect.height should be 100 * 20 / 50, which is 40 pixels.
// Essentially, we are scaling the image as dictated by the CSS
// destination height and width, and we are then clipping the scaled
// image by the cell width and height.
nsSize rawImageSize(CSSPixel::ToAppUnits(rawImageCSSIntSize));
wholeImageDest =
nsLayoutUtils::GetWholeImageDestination(rawImageSize, sourceRect,
nsRect(destRect.TopLeft(),
imageDestSize));
} else {
// GetWidth/GetHeight failed, so we can't easily map a subregion of the
// source image onto the destination area. So, just draw the whole image.
wholeImageDest = destRect;
}
gfxContext* ctx = aRenderingContext.ThebesContext();
if (opacity != 1.0f) {

View File

@ -5102,7 +5102,7 @@ var BrowserEventHandler = {
* - It's a select element showing multiple rows
*/
if (checkElem) {
if ((elem.scrollTopMin != elem.scrollTopMin ||
if ((elem.scrollTopMin != elem.scrollTopMax ||
elem.scrollLeftMin != elem.scrollLeftMax) &&
(this._hasScrollableOverflow(elem) ||
elem.matches("textarea")) ||

View File

@ -69,7 +69,7 @@ CaptivePortalService::PerformCheck()
LOG(("CaptivePortalService::PerformCheck - Calling CheckCaptivePortal\n"));
mRequestInProgress = true;
mCaptivePortalDetector->CheckCaptivePortal(
NS_LITERAL_STRING(kInterfaceName).get(), this);
MOZ_UTF16(kInterfaceName), this);
return NS_OK;
}
@ -164,7 +164,7 @@ CaptivePortalService::Stop()
mRequestInProgress = false;
mStarted = false;
if (mCaptivePortalDetector) {
mCaptivePortalDetector->Abort(NS_LITERAL_STRING(kInterfaceName).get());
mCaptivePortalDetector->Abort(MOZ_UTF16(kInterfaceName));
}
mCaptivePortalDetector = nullptr;
return NS_OK;
@ -281,7 +281,7 @@ CaptivePortalService::Prepare()
LOG(("CaptivePortalService::Prepare\n"));
// XXX: Finish preparation shouldn't be called until dns and routing is available.
if (mCaptivePortalDetector) {
mCaptivePortalDetector->FinishPreparation(NS_LITERAL_STRING(kInterfaceName).get());
mCaptivePortalDetector->FinishPreparation(MOZ_UTF16(kInterfaceName));
}
return NS_OK;
}

View File

@ -1050,7 +1050,7 @@ nsIOService::SetOffline(bool offline)
if (observerService && mConnectivity) {
observerService->NotifyObservers(subject,
NS_IOSERVICE_OFFLINE_STATUS_TOPIC,
NS_LITERAL_STRING(NS_IOSERVICE_ONLINE).get());
MOZ_UTF16(NS_IOSERVICE_ONLINE));
}
}
}
@ -1133,7 +1133,7 @@ nsIOService::SetConnectivityInternal(bool aConnectivity)
observerService->NotifyObservers(
static_cast<nsIIOService *>(this),
NS_IOSERVICE_OFFLINE_STATUS_TOPIC,
NS_LITERAL_STRING(NS_IOSERVICE_ONLINE).get());
MOZ_UTF16(NS_IOSERVICE_ONLINE));
} else {
// If we were previously online and lost connectivity
// send the OFFLINE notification

View File

@ -40,7 +40,6 @@ UNIFIED_SOURCES += [
'DNSRequestChild.cpp',
'DNSRequestParent.cpp',
'GetAddrInfo.cpp',
'nameprep.c',
'nsDNSService2.cpp',
'nsIDNService.cpp',
'punycode.c',
@ -69,3 +68,13 @@ LOCAL_INCLUDES += [
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['ANDROID_VERSION'] > '19':
CXXFLAGS += ['-I%s/bionic/libc/dns/include' % CONFIG['ANDROID_SOURCE']]
if CONFIG['ENABLE_INTL_API']:
DEFINES['IDNA2008'] = True
CXXFLAGS += CONFIG['MOZ_ICU_CFLAGS']
CFLAGS += CONFIG['MOZ_ICU_CFLAGS']
USE_LIBS += ['icu']
else:
UNIFIED_SOURCES += [
'nameprep.c',
]

View File

@ -17,6 +17,16 @@
#include "nsISupportsPrimitives.h"
#include "punycode.h"
#ifdef IDNA2008
// Currently we use the transitional processing option -- see
// http://unicode.org/reports/tr46/
// To switch to non-transitional processing, change the value of this flag
// and kTransitionalProcessing in netwerk/test/unit/test_idna2008.js to false
// (patch in bug 1218179).
const bool kIDNA2008_TransitionalProcessing = true;
#include "ICUUtils.h"
#endif
using namespace mozilla::unicode;
@ -123,18 +133,91 @@ void nsIDNService::prefsChanged(nsIPrefBranch *prefBranch, const char16_t *pref)
nsIDNService::nsIDNService()
{
#ifdef IDNA2008
uint32_t IDNAOptions = UIDNA_CHECK_BIDI | UIDNA_CHECK_CONTEXTJ;
if (!kIDNA2008_TransitionalProcessing) {
IDNAOptions |= UIDNA_NONTRANSITIONAL_TO_UNICODE;
}
UErrorCode errorCode = U_ZERO_ERROR;
mIDNA = uidna_openUTS46(IDNAOptions, &errorCode);
#else
if (idn_success != idn_nameprep_create(nullptr, &mNamePrepHandle))
mNamePrepHandle = nullptr;
mNormalizer = do_GetService(NS_UNICODE_NORMALIZER_CONTRACTID);
/* member initializers and constructor code */
#endif
}
nsIDNService::~nsIDNService()
{
#ifdef IDNA2008
uidna_close(mIDNA);
#else
idn_nameprep_destroy(mNamePrepHandle);
#endif
}
#ifdef IDNA2008
nsresult
nsIDNService::IDNA2008ToUnicode(const nsACString& input, nsAString& output)
{
NS_ConvertUTF8toUTF16 inputStr(input);
UIDNAInfo info = UIDNA_INFO_INITIALIZER;
UErrorCode errorCode = U_ZERO_ERROR;
int32_t inLen = inputStr.Length();
int32_t outMaxLen = inLen - kACEPrefixLen + 1;
UChar outputBuffer[kMaxDNSNodeLen + 1];
int32_t outLen = uidna_labelToUnicode(mIDNA, (const UChar*)inputStr.get(),
inLen, outputBuffer, outMaxLen,
&info, &errorCode);
if (info.errors != 0) {
return NS_ERROR_FAILURE;
}
if (U_SUCCESS(errorCode)) {
ICUUtils::AssignUCharArrayToString(outputBuffer, outLen, output);
}
return ICUUtils::UErrorToNsResult(errorCode);
}
nsresult
nsIDNService::IDNA2008StringPrep(const nsAString& input,
nsAString& output,
stringPrepFlag flag)
{
UIDNAInfo info = UIDNA_INFO_INITIALIZER;
UErrorCode errorCode = U_ZERO_ERROR;
int32_t inLen = input.Length();
int32_t outMaxLen = kMaxDNSNodeLen + 1;
UChar outputBuffer[kMaxDNSNodeLen + 1];
int32_t outLen =
uidna_labelToUnicode(mIDNA, (const UChar*)PromiseFlatString(input).get(),
inLen, outputBuffer, outMaxLen, &info, &errorCode);
nsresult rv = ICUUtils::UErrorToNsResult(errorCode);
NS_ENSURE_SUCCESS(rv, rv);
// Output the result of nameToUnicode even if there were errors
ICUUtils::AssignUCharArrayToString(outputBuffer, outLen, output);
if (flag == eStringPrepIgnoreErrors) {
return NS_OK;
}
if (info.errors != 0) {
if (flag == eStringPrepForDNS) {
output.Truncate();
}
rv = NS_ERROR_FAILURE;
}
return rv;
}
#endif
NS_IMETHODIMP nsIDNService::ConvertUTF8toACE(const nsACString & input, nsACString & ace)
{
return UTF8toACE(input, ace, eStringPrepForDNS);
@ -396,6 +479,7 @@ static nsresult utf16ToUcs4(const nsAString& in,
return NS_OK;
}
#ifndef IDNA2008
static void ucs4toUtf16(const uint32_t *in, nsAString& out)
{
while (*in) {
@ -408,6 +492,7 @@ static void ucs4toUtf16(const uint32_t *in, nsAString& out)
in++;
}
}
#endif
static nsresult punycode(const nsAString& in, nsACString& out)
{
@ -462,6 +547,9 @@ static nsresult punycode(const nsAString& in, nsACString& out)
nsresult nsIDNService::stringPrep(const nsAString& in, nsAString& out,
stringPrepFlag flag)
{
#ifdef IDNA2008
return IDNA2008StringPrep(in, out, flag);
#else
if (!mNamePrepHandle || !mNormalizer)
return NS_ERROR_FAILURE;
@ -523,6 +611,7 @@ nsresult nsIDNService::stringPrep(const nsAString& in, nsAString& out,
}
return rv;
#endif
}
nsresult nsIDNService::stringPrepAndACE(const nsAString& in, nsACString& out,
@ -612,6 +701,11 @@ nsresult nsIDNService::decodeACE(const nsACString& in, nsACString& out,
return NS_OK;
}
nsAutoString utf16;
#ifdef IDNA2008
nsresult result = IDNA2008ToUnicode(in, utf16);
NS_ENSURE_SUCCESS(result, result);
#else
// RFC 3490 - 4.2 ToUnicode
// The ToUnicode output never contains more code points than its input.
punycode_uint output_length = in.Length() - kACEPrefixLen + 1;
@ -630,9 +724,9 @@ nsresult nsIDNService::decodeACE(const nsACString& in, nsACString& out,
// UCS4 -> UTF8
output[output_length] = 0;
nsAutoString utf16;
ucs4toUtf16(output, utf16);
delete [] output;
#endif
if (flag != eStringPrepForUI || isLabelSafe(utf16)) {
CopyUTF16toUTF8(utf16, out);
} else {

View File

@ -10,8 +10,14 @@
#include "nsCOMPtr.h"
#include "nsIObserver.h"
#include "nsWeakReference.h"
#ifdef IDNA2008
#include "unicode/uidna.h"
#else
#include "nsIUnicodeNormalizer.h"
#include "nsIDNKitInterface.h"
#endif
#include "nsString.h"
class nsIPrefBranch;
@ -143,8 +149,23 @@ private:
*/
bool illegalScriptCombo(int32_t script, int32_t& savedScript);
#ifdef IDNA2008
/**
* Convert a DNS label from ASCII to Unicode using IDNA2008
*/
nsresult IDNA2008ToUnicode(const nsACString& input, nsAString& output);
/**
* Convert a DNS label to a normalized form conforming to IDNA2008
*/
nsresult IDNA2008StringPrep(const nsAString& input, nsAString& output,
stringPrepFlag flag);
UIDNA* mIDNA;
#else
idn_nameprep_t mNamePrepHandle;
nsCOMPtr<nsIUnicodeNormalizer> mNormalizer;
#endif
nsXPIDLString mIDNBlacklist;
/**

View File

@ -358,7 +358,7 @@ nsHttpChannel::Connect()
const char16_t* params[] = { reportSpec.get(), reportScheme.get() };
uint32_t innerWindowId = mLoadInfo ? mLoadInfo->GetInnerWindowID() : 0;
CSP_LogLocalizedStr(NS_LITERAL_STRING("upgradeInsecureRequest").get(),
CSP_LogLocalizedStr(MOZ_UTF16("upgradeInsecureRequest"),
params, ArrayLength(params),
EmptyString(), // aSourceFile
EmptyString(), // aScriptSample

View File

@ -43,6 +43,7 @@ LOCAL_INCLUDES = [
'../dns',
]
DEFINES['IDNA2008'] = False
DEFINES['MOZILLA_INTERNAL_API'] = True
DEFINES['MOZILLA_XPCOMRT_API'] = True
DEFINES['MOZILLA_EXTERNAL_LINKAGE'] = True

View File

@ -92,8 +92,14 @@ function run_test() {
// www.1מיץ.com is invalid
expected_fail("www.1\u05DE\u05D9\u05E5.com");
// www.מיץ1.com is invalid
expected_fail("www.\u05DE\u05D9\u05E51.com");
// www.!מיץ.com is invalid
expected_fail("www.!\u05DE\u05D9\u05E5.com");
// www.מיץ!.com is invalid
expected_fail("www.\u05DE\u05D9\u05E5!.com");
// XXX TODO: add a test for an RTL label ending with a digit. This was
// invalid in IDNA2003 but became valid in IDNA2008
// But www.מיץ1פטל.com is fine
expected_pass("www.\u05DE\u05D9\u05E51\u05E4\u05D8\u05DC.com");
}

Some files were not shown because too many files have changed in this diff Show More