Merge inbound to central, a=merge

This commit is contained in:
Wes Kocher 2015-10-28 17:00:22 -07:00
commit c43e982124
110 changed files with 2118 additions and 1150 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

@ -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

@ -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

@ -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");
}

View File

@ -144,19 +144,25 @@ function run_test() {
} catch(e) {
result = ".com";
}
if (punycodeURL.substr(0, 4) == "xn--") {
// test convertToDisplayIDN with a Unicode URL and with a
// Punycode URL if we have one
do_check_eq(escape(result), escape(punycodeURL));
// If the punycode URL is equivalent to \ufffd.com (i.e. the
// blacklisted character has been replaced by a unicode
// REPLACEMENT CHARACTER, skip the test
if (result != "xn--zn7c.com") {
result = idnService.convertToDisplayIDN(punycodeURL, isASCII);
do_check_eq(escape(result), escape(punycodeURL));
} else {
// The "punycode" URL isn't punycode. This happens in testcases
// where the Unicode URL has become normalized to an ASCII URL,
// so, even though expectedUnicode is true, the expected result
// is equal to punycodeURL
do_check_eq(escape(result), escape(punycodeURL));
if (punycodeURL.substr(0, 4) == "xn--") {
// test convertToDisplayIDN with a Unicode URL and with a
// Punycode URL if we have one
equal(escape(result), escape(punycodeURL));
result = idnService.convertToDisplayIDN(punycodeURL, isASCII);
equal(escape(result), escape(punycodeURL));
} else {
// The "punycode" URL isn't punycode. This happens in testcases
// where the Unicode URL has become normalized to an ASCII URL,
// so, even though expectedUnicode is true, the expected result
// is equal to punycodeURL
equal(escape(result), escape(punycodeURL));
}
}
}
pbi.setBoolPref("network.IDN.whitelist.com", oldWhitelistCom);

View File

@ -12,8 +12,15 @@ const testcases = [
// non-XID character
["I♥NY", "xn--iny-zx5a", false, false, false],
/*
Behaviour of this test changed in IDNA2008, replacing the non-XID
character with U+FFFD replacement character - when all platforms use
IDNA2008 it can be uncommented and the punycode URL changed to
"xn--mgbl3eb85703a"
// new non-XID character in Unicode 6.3
["حلا\u061cل", "xn--bgbvr6gc", false, false, false],
*/
// U+30FB KATAKANA MIDDLE DOT is excluded from non-XID characters (bug 857490)
["乾燥肌・石けん", "xn--08j4gylj12hz80b0uhfup", false, true, true],

View File

@ -0,0 +1,60 @@
const kTransitionalProcessing = true;
// Four characters map differently under non-transitional processing:
const labels = [
// U+00DF LATIN SMALL LETTER SHARP S to "ss"
"stra\u00dfe",
// U+03C2 GREEK SMALL LETTER FINAL SIGMA to U+03C3 GREEK SMALL LETTER SIGMA
"\u03b5\u03bb\u03bb\u03ac\u03c2",
// U+200C ZERO WIDTH NON-JOINER in Indic script
"\u0646\u0627\u0645\u0647\u200c\u0627\u06cc",
// U+200D ZERO WIDTH JOINER in Arabic script
"\u0dc1\u0dca\u200d\u0dbb\u0dd3",
// But CONTEXTJ rules prohibit ZWJ and ZWNJ in non-Arabic or Indic scripts
// U+200C ZERO WIDTH NON-JOINER in Latin script
"m\200cn",
// U+200D ZERO WIDTH JOINER in Latin script
"p\200dq",
];
const transitionalExpected = [
"strasse",
"xn--hxarsa5b",
"xn--mgba3gch31f",
"xn--10cl1a0b",
"",
""
];
const nonTransitionalExpected = [
"xn--strae-oqa",
"xn--hxarsa0b",
"xn--mgba3gch31f060k",
"xn--10cl1a0b660p",
"",
""
];
// Test options for converting IDN URLs under IDNA2008
function run_test()
{
var idnService = Components.classes["@mozilla.org/network/idn-service;1"]
.getService(Components.interfaces.nsIIDNService);
for (var i = 0; i < labels.length; ++i) {
var result;
try {
result = idnService.convertUTF8toACE(labels[i]);
} catch(e) {
result = "";
}
if (kTransitionalProcessing) {
equal(result, transitionalExpected[i]);
} else {
equal(result, nonTransitionalExpected[i]);
}
}
}

View File

@ -215,6 +215,7 @@ skip-if = bits != 32
[test_idnservice.js]
[test_idn_blacklist.js]
[test_idn_urls.js]
[test_idna2008.js]
[test_invalidport.js]
[test_localstreams.js]
[test_mismatch_last-modified.js]

View File

@ -333,7 +333,7 @@ FileSystemDataSource::GetTarget(nsIRDFResource *source,
url->GetValueConst(&uni);
if (!uni) return(NS_RDF_NO_VALUE);
nsAutoString urlStr;
urlStr.Assign(NS_LITERAL_STRING(NS_MOZICON_SCHEME).get());
urlStr.AssignLiteral(NS_MOZICON_SCHEME);
urlStr.Append(uni);
rv = mRDFService->GetLiteral(urlStr.get(), getter_AddRefs(url));

View File

@ -40,8 +40,9 @@
"facebook"
],
"production_domains": [
// Chrome's test domain.
// Chrome's test domains.
"pinningtest.appspot.com",
"pinning-test.badssl.com",
// Dropbox
"dropbox.com",
"www.dropbox.com",

View File

@ -170,30 +170,38 @@ Device Shell methods
Informational methods
+++++++++++++++++++++
.. automethod:: ADBDevice.clear_logcat
.. automethod:: ADBDevice.get_battery_percentage
.. automethod:: ADBDevice.get_info
.. automethod:: ADBDevice.get_logcat
.. automethod:: ADBDevice.get_prop(self, prop, timeout=None)
.. automethod:: ADBDevice.get_state(self, timeout=None)
.. automethod:: ADBDevice.get_prop
.. automethod:: ADBDevice.get_state
System control methods
++++++++++++++++++++++
.. automethod:: ADBDevice.is_device_ready
.. automethod:: ADBDevice.reboot
File management methods
+++++++++++++++++++++++
.. automethod:: ADBDevice.chmod(self, path, recursive=False, mask="777", timeout=None, root=False)
.. automethod:: ADBDevice.exists(self, path, timeout=None, root=False)
.. automethod:: ADBDevice.is_dir(self, path, timeout=None, root=False)
.. automethod:: ADBDevice.is_file(self, path, timeout=None, root=False)
.. automethod:: ADBDevice.list_files(self, path, timeout=None, root=False)
.. automethod:: ADBDevice.mkdir(self, path, parents=False, timeout=None, root=False)
.. automethod:: ADBDevice.push(self, local, remote, timeout=None)
.. automethod:: ADBDevice.rm(self, path, recursive=False, force=False, timeout=None, root=False)
.. automethod:: ADBDevice.rmdir(self, path, timeout=None, root=False)
.. automethod:: ADBDevice.chmod
.. automethod:: ADBDevice.cp
.. automethod:: ADBDevice.exists
.. automethod:: ADBDevice.is_dir
.. automethod:: ADBDevice.is_file
.. automethod:: ADBDevice.list_files
.. automethod:: ADBDevice.mkdir
.. automethod:: ADBDevice.mv
.. automethod:: ADBDevice.push
.. automethod:: ADBDevice.rm
.. automethod:: ADBDevice.rmdir
.. autoattribute:: ADBDevice.test_root
Process management methods
++++++++++++++++++++++++++
.. automethod:: ADBDevice.get_process_list(self, timeout=None)
.. automethod:: ADBDevice.kill(self, pids, sig=None, attempts=3, wait=5, timeout=None, root=False)
.. automethod:: ADBDevice.pkill(self, appname, sig=None, attempts=3, wait=5, timeout=None, root=False)
.. automethod:: ADBDevice.process_exist(self, process_name, timeout=None)
.. automethod:: ADBDevice.get_process_list
.. automethod:: ADBDevice.kill
.. automethod:: ADBDevice.pkill
.. automethod:: ADBDevice.process_exist
ADBAndroid
``````````
@ -201,24 +209,32 @@ ADBAndroid
Informational methods
+++++++++++++++++++++
.. automethod:: ADBAndroid.get_battery_percentage(self, timeout=None)
.. automethod:: ADBAndroid.get_battery_percentage
System control methods
++++++++++++++++++++++
.. automethod:: ADBAndroid.is_device_ready(self, timeout=None)
.. automethod:: ADBAndroid.power_on(self, timeout=None)
.. automethod:: ADBAndroid.reboot(self, timeout=None)
.. automethod:: ADBAndroid.is_device_ready
.. automethod:: ADBAndroid.power_on
Application management methods
++++++++++++++++++++++++++++++
.. automethod:: ADBAndroid.install_app(self, apk_path, timeout=None)
.. automethod:: ADBAndroid.is_app_installed(self, app_name, timeout=None)
.. automethod:: ADBAndroid.launch_application(self, app_name, activity_name, intent, url=None, extras=None, wait=True, fail_if_running=True, timeout=None)
.. automethod:: ADBAndroid.launch_fennec(self, app_name, intent="android.intent.action.VIEW", moz_env=None, extra_args=None, url=None, wait=True, fail_if_running=True, timeout=None)
.. automethod:: ADBAndroid.stop_application(self, app_name, timeout=None, root=False)
.. automethod:: ADBAndroid.uninstall_app(self, app_name, reboot=False, timeout=None)
.. automethod:: ADBAndroid.update_app(self, apk_path, timeout=None)
.. automethod:: ADBAndroid.install_app
.. automethod:: ADBAndroid.is_app_installed
.. automethod:: ADBAndroid.launch_application
.. automethod:: ADBAndroid.launch_fennec
.. automethod:: ADBAndroid.stop_application
.. automethod:: ADBAndroid.uninstall_app
.. automethod:: ADBAndroid.update_app
ADBB2G
``````
.. autoclass:: ADBB2G
Informational methods
+++++++++++++++++++++
.. automethod:: ADBB2G.get_battery_percentage
.. automethod:: ADBB2G.get_info
.. automethod:: ADBB2G.get_memory_total
ADBProcess
``````````

View File

@ -4,6 +4,7 @@
from adb import ADBError, ADBRootError, ADBTimeoutError, ADBProcess, ADBCommand, ADBHost, ADBDevice
from adb_android import ADBAndroid
from adb_b2g import ADBB2G
from devicemanager import DeviceManager, DMError, ZeroconfListener
from devicemanagerADB import DeviceManagerADB
from devicemanagerSUT import DeviceManagerSUT

View File

@ -2,6 +2,7 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
from abc import ABCMeta, abstractmethod
import os
import posixpath
import re
@ -12,9 +13,7 @@ import traceback
class ADBProcess(object):
"""ADBProcess encapsulates the data related to executing the adb process.
"""
"""ADBProcess encapsulates the data related to executing the adb process."""
def __init__(self, args):
#: command argument argument list.
self.args = args
@ -64,7 +63,6 @@ class ADBError(Exception):
device either exited with a non-zero exitcode or when an
unexpected error condition has occurred. Generally, ADBErrors can
be handled and the device can continue to be used.
"""
pass
@ -73,7 +71,6 @@ class ADBRootError(Exception):
root but the device does not support it. This error is fatal since
there is no recovery possible by the script. You must either root
your device or change your scripts to not require running as root.
"""
pass
@ -94,7 +91,6 @@ class ADBTimeoutError(Exception):
* Rebooting the device manually.
* Rebooting the host.
"""
pass
@ -117,7 +113,6 @@ class ADBCommand(object):
adbcommand = ADBCommand()
except NotImplementedError:
print "ADBCommand can not be instantiated."
"""
def __init__(self,
@ -138,7 +133,6 @@ class ADBCommand(object):
:raises: * ADBError
* ADBTimeoutError
"""
if self.__class__ == ADBCommand:
raise NotImplementedError
@ -211,7 +205,6 @@ class ADBCommand(object):
It is the caller's responsibilty to clean up by closing
the stdout and stderr temporary files.
"""
args = [self._adb_path]
if self._adb_host:
@ -263,7 +256,6 @@ class ADBCommand(object):
:raises: * ADBTimeoutError
* ADBError
"""
adb_process = None
try:
@ -306,7 +298,6 @@ class ADBHost(ADBCommand):
adbhost = ADBHost()
adbhost.start_server()
"""
def __init__(self,
adb='adb',
@ -326,7 +317,6 @@ class ADBHost(ADBCommand):
:raises: * ADBError
* ADBTimeoutError
"""
ADBCommand.__init__(self, adb=adb, adb_host=adb_host,
adb_port=adb_port, logger_name=logger_name,
@ -362,7 +352,6 @@ class ADBHost(ADBCommand):
It is the caller's responsibilty to clean up by closing
the stdout and stderr temporary files.
"""
return ADBCommand.command(self, cmds, timeout=timeout)
@ -382,7 +371,6 @@ class ADBHost(ADBCommand):
:raises: * ADBTimeoutError
* ADBError
"""
return ADBCommand.command_output(self, cmds, timeout=timeout)
@ -415,7 +403,6 @@ class ADBHost(ADBCommand):
while true; do
adb -a fork-server server
done
"""
self.command_output(["start-server"], timeout=timeout)
@ -430,7 +417,6 @@ class ADBHost(ADBCommand):
:type timeout: integer or None
:raises: * ADBTimeoutError
* ADBError
"""
self.command_output(["kill-server"], timeout=timeout)
@ -457,7 +443,6 @@ class ADBHost(ADBCommand):
[{'device_serial': 'b313b945', 'state': 'device', 'product': 'd2vzw',
'usb': '1-7', 'device': 'd2vzw', 'model': 'SCH_I535' }]
"""
# b313b945 device usb:1-7 product:d2vzw model:SCH_I535 device:d2vzw
# from Android system/core/adb/transport.c statename()
@ -486,22 +471,12 @@ class ADBHost(ADBCommand):
class ADBDevice(ADBCommand):
"""ADBDevice provides methods which can be used to interact with
the associated Android-based device.
Android specific features such as Application management are not
included but are provided via the ADBAndroid interface.
::
from mozdevice import ADBDevice
adbdevice = ADBDevice()
print adbdevice.list_files("/mnt/sdcard")
if adbdevice.process_exist("org.mozilla.fennec"):
print "Fennec is running"
"""ADBDevice is an abstract base class which provides methods which
can be used to interact with the associated Android or B2G based
device. It must be used via one of the concrete implementations in
:class:`ADBAndroid` or :class:`ADBB2G`.
"""
__metaclass__ = ABCMeta
def __init__(self,
device=None,
@ -547,8 +522,6 @@ class ADBDevice(ADBCommand):
:raises: * ADBError
* ADBTimeoutError
* ValueError
"""
ADBCommand.__init__(self, adb=adb, adb_host=adb_host,
adb_port=adb_port, logger_name=logger_name,
@ -604,6 +577,9 @@ class ADBDevice(ADBCommand):
except ADBError:
self._ls += " -a"
# Do we have cp?
self._have_cp = self.shell_bool("type cp")
self._logger.debug("ADBDevice: %s" % self.__dict__)
def _get_device_serial(self, device):
@ -644,7 +620,6 @@ class ADBDevice(ADBCommand):
def _escape_command_line(cmd):
"""Utility function to return escaped and quoted version of command
line.
"""
quoted_cmd = []
@ -667,7 +642,6 @@ class ADBDevice(ADBCommand):
def _get_exitcode(file_obj):
"""Get the exitcode from the last line of the file_obj for shell
commands.
"""
file_obj.seek(0, os.SEEK_END)
@ -806,7 +780,6 @@ class ADBDevice(ADBCommand):
It is the caller's responsibilty to clean up by closing
the stdout and stderr temporary files.
"""
return ADBCommand.command(self, cmds,
@ -829,7 +802,6 @@ class ADBDevice(ADBCommand):
:raises: * ADBTimeoutError
* ADBError
"""
return ADBCommand.command_output(self, cmds,
device_serial=self._device_serial,
@ -980,7 +952,6 @@ class ADBDevice(ADBCommand):
It is the caller's responsibilty to clean up by closing
the stdout and stderr temporary files.
"""
if root:
ld_library_path='LD_LIBRARY_PATH=/vendor/lib:/system/lib'
@ -1058,7 +1029,6 @@ class ADBDevice(ADBCommand):
:raises: * ADBTimeoutError
* ADBRootError
"""
adb_process = None
try:
@ -1093,7 +1063,6 @@ class ADBDevice(ADBCommand):
:raises: * ADBTimeoutError
* ADBRootError
* ADBError
"""
adb_process = None
try:
@ -1151,7 +1120,6 @@ class ADBDevice(ADBCommand):
"radio", "events", and "main". Defaults to "main".
:raises: * ADBTimeoutError
* ADBError
"""
buffers = self._get_logcat_buffer_args(buffers)
cmds = ["logcat", "-c"] + buffers
@ -1188,7 +1156,6 @@ class ADBDevice(ADBCommand):
:returns: list of lines logcat output.
:raises: * ADBTimeoutError
* ADBError
"""
buffers = self._get_logcat_buffer_args(buffers)
cmds = ["logcat", "-v", format, "-d"] + buffers + filter_specs
@ -1213,7 +1180,6 @@ class ADBDevice(ADBCommand):
:returns: string value of property.
:raises: * ADBTimeoutError
* ADBError
"""
output = self.shell_output('getprop %s' % prop, timeout=timeout)
return output
@ -1231,7 +1197,6 @@ class ADBDevice(ADBCommand):
:returns: string value of adb get-state.
:raises: * ADBTimeoutError
* ADBError
"""
output = self.command_output(["get-state"], timeout=timeout).strip()
return output
@ -1253,7 +1218,6 @@ class ADBDevice(ADBCommand):
be found.
:raises: * ADBTimeoutError
* ADBError
"""
ip_regexp = re.compile(r'(\w+)\s+UP\s+([1-9]\d{0,2}\.\d{1,3}\.\d{1,3}\.\d{1,3})')
data = self.shell_output('netcfg')
@ -1309,7 +1273,6 @@ class ADBDevice(ADBCommand):
:raises: * ADBTimeoutError
* ADBRootError
* ADBError
"""
path = posixpath.normpath(path.strip())
self._logger.debug('chmod: path=%s, recursive=%s, mask=%s, root=%s' %
@ -1356,7 +1319,6 @@ class ADBDevice(ADBCommand):
:returns: boolean - True if path exists.
:raises: * ADBTimeoutError
* ADBRootError
"""
path = posixpath.normpath(path)
return self.shell_bool('ls -a %s' % path, timeout=timeout, root=root)
@ -1378,7 +1340,6 @@ class ADBDevice(ADBCommand):
directory.
:raises: * ADBTimeoutError
* ADBRootError
"""
path = posixpath.normpath(path)
return self.shell_bool('ls -a %s/' % path, timeout=timeout, root=root)
@ -1400,7 +1361,6 @@ class ADBDevice(ADBCommand):
file.
:raises: * ADBTimeoutError
* ADBRootError
"""
path = posixpath.normpath(path)
return (
@ -1424,7 +1384,6 @@ class ADBDevice(ADBCommand):
:returns: list of files/directories contained in the directory.
:raises: * ADBTimeoutError
* ADBRootError
"""
path = posixpath.normpath(path.strip())
data = []
@ -1461,7 +1420,6 @@ class ADBDevice(ADBCommand):
:raises: * ADBTimeoutError
* ADBRootError
* ADBError
"""
path = posixpath.normpath(path)
if parents:
@ -1504,7 +1462,6 @@ class ADBDevice(ADBCommand):
:type timeout: integer or None
:raises: * ADBTimeoutError
* ADBError
"""
self.command_output(["push", os.path.realpath(local), remote],
timeout=timeout)
@ -1525,7 +1482,6 @@ class ADBDevice(ADBCommand):
:type timeout: integer or None
:raises: * ADBTimeoutError
* ADBError
"""
self.command_output(["pull", remote, os.path.realpath(local)],
timeout=timeout)
@ -1551,7 +1507,6 @@ class ADBDevice(ADBCommand):
:raises: * ADBTimeoutError
* ADBRootError
* ADBError
"""
cmd = "rm"
if recursive:
@ -1580,7 +1535,6 @@ class ADBDevice(ADBCommand):
:raises: * ADBTimeoutError
* ADBRootError
* ADBError
"""
self.shell_output("rmdir %s" % path, timeout=timeout, root=root)
if self.is_dir(path, timeout=timeout, root=root):
@ -1603,7 +1557,6 @@ class ADBDevice(ADBCommand):
on the device.
:raises: * ADBTimeoutError
* ADBError
"""
adb_process = None
try:
@ -1668,7 +1621,6 @@ class ADBDevice(ADBCommand):
:raises: * ADBTimeoutError
* ADBRootError
* ADBError
"""
pid_list = [str(pid) for pid in pids]
for attempt in range(attempts):
@ -1719,7 +1671,6 @@ class ADBDevice(ADBCommand):
:raises: * ADBTimeoutError
* ADBRootError
* ADBError
"""
procs = self.get_process_list(timeout=timeout)
# limit the comparion to the first 75 characters due to a
@ -1753,7 +1704,6 @@ class ADBDevice(ADBCommand):
:raises: * ADBTimeoutError
* ADBError
"""
if not isinstance(process_name, basestring):
raise ADBError("Process name %s is not a string" % process_name)
@ -1783,3 +1733,204 @@ class ADBDevice(ADBCommand):
if proc_name == app[:75]:
return True
return False
def cp(self, source, destination, recursive=False, timeout=None,
root=False):
"""Copies a file or directory on the device.
:param source: string containing the path of the source file or
directory.
:param destination: string containing the path of the destination file
or directory.
:param recursive: optional boolean indicating if a recursive copy is to
be performed. Required if the source is a directory. Defaults to
False. Think cp -R source destination.
:param timeout: optional integer specifying the maximum time in
seconds for any spawned adb process to complete before
throwing an ADBTimeoutError.
This timeout is per adb call. The total time spent
may exceed this value. If it is not specified, the value
set in the ADBDevice constructor is used.
:raises: * ADBTimeoutError
* ADBRootError
* ADBError
"""
source = posixpath.normpath(source)
destination = posixpath.normpath(destination)
if self._have_cp:
r = '-R' if recursive else ''
self.shell_output('cp %s %s %s' % (r, source, destination),
timeout=timeout, root=root)
return
# Emulate cp behavior depending on if source and destination
# already exists and whether they are a directory or file.
if not self.exists(source, timeout=timeout, root=root):
raise ADBError("cp: can't stat '%s': No such file or directory" %
source)
if self.is_file(source, timeout=timeout, root=root):
if self.is_dir(destination, timeout=timeout, root=root):
# Copy the source file into the destination directory
destination = posixpath.join(destination,
posixpath.basename(source))
self.shell_output('dd if=%s of=%s' % (source, destination),
timeout=timeout, root=root)
return
if self.is_file(destination, timeout=timeout, root=root):
raise ADBError('cp: %s: Not a directory' % destination)
if not recursive:
raise ADBError("cp: omitting directory '%s'" % source)
if self.is_dir(destination, timeout=timeout, root=root):
# Copy the source directory into the destination directory.
destination_dir = posixpath.join(destination,
posixpath.basename(source))
else:
# Copy the contents of the source directory into the
# destination directory.
destination_dir = destination
try:
# Do not create parent directories since cp does not.
self.mkdir(destination_dir, timeout=timeout, root=root)
except ADBError as e:
if 'File exists' not in e.message:
raise
for i in self.list_files(source, timeout=timeout, root=root):
self.cp(posixpath.join(source, i),
posixpath.join(destination_dir, i),
recursive=recursive,
timeout=timeout, root=root)
def mv(self, source, destination, timeout=None, root=False):
"""Moves a file or directory on the device.
:param source: string containing the path of the source file or
directory.
:param destination: string containing the path of the destination file
or directory.
:param timeout: optional integer specifying the maximum time in
seconds for any spawned adb process to complete before
throwing an ADBTimeoutError.
This timeout is per adb call. The total time spent
may exceed this value. If it is not specified, the value
set in the ADBDevice constructor is used.
:raises: * ADBTimeoutError
* ADBRootError
* ADBError
"""
source = posixpath.normpath(source)
destination = posixpath.normpath(destination)
self.shell_output('mv %s %s' % (source, destination), timeout=timeout,
root=root)
def reboot(self, timeout=None):
"""Reboots the device.
:param timeout: optional integer specifying the maximum time in
seconds for any spawned adb process to complete before
throwing an ADBTimeoutError.
This timeout is per adb call. The total time spent
may exceed this value. If it is not specified, the value
set in the ADB constructor is used.
:raises: * ADBTimeoutError
* ADBError
reboot() reboots the device, issues an adb wait-for-device in order to
wait for the device to complete rebooting, then calls is_device_ready()
to determine if the device has completed booting.
"""
self.command_output(["reboot"], timeout=timeout)
self.command_output(["wait-for-device"], timeout=timeout)
return self.is_device_ready(timeout=timeout)
@abstractmethod
def is_device_ready(self, timeout=None):
"""Abstract class that returns True if the device is ready.
:param timeout: optional integer specifying the maximum time in
seconds for any spawned adb process to complete before
throwing an ADBTimeoutError.
This timeout is per adb call. The total time spent
may exceed this value. If it is not specified, the value
set in the ADB constructor is used.
:raises: * ADBTimeoutError
* ADBError
"""
return
@abstractmethod
def get_battery_percentage(self, timeout=None):
"""Abstract class that returns the battery charge as a percentage.
:param timeout: optional integer specifying the maximum time in
seconds for any spawned adb process to complete before
throwing an ADBTimeoutError.
This timeout is per adb call. The total time spent
may exceed this value. If it is not specified, the value
set in the ADBDevice constructor is used.
:returns: battery charge as a percentage.
:raises: * ADBTimeoutError
* ADBError
"""
return
def get_info(self, directive=None, timeout=None):
"""
Returns a dictionary of information strings about the device.
:param directive: information you want to get. Options are:
- `battery` - battery charge as a percentage
- `disk` - total, free, available bytes on disk
- `id` - unique id of the device
- `os` - name of the os
- `process` - list of running processes (same as ps)
- `systime` - system time of the device
- `uptime` - uptime of the device
If `directive` is `None`, will return all available information
:param timeout: optional integer specifying the maximum time in
seconds for any spawned adb process to complete before
throwing an ADBTimeoutError.
This timeout is per adb call. The total time spent
may exceed this value. If it is not specified, the value
set in the ADB constructor is used.
:raises: * ADBTimeoutError
* ADBError
"""
directives = ['battery', 'disk', 'id', 'os', 'process', 'systime',
'uptime']
if (directive in directives):
directives = [directive]
info = {}
if 'battery' in directives:
info['battery'] = self.get_battery_percentage(timeout=timeout)
if 'disk' in directives:
info['disk'] = self.shell_output('df /data /system /sdcard',
timeout=timeout).splitlines()
if 'id' in directives:
info['id'] = self.command_output(['get-serialno'], timeout=timeout)
if 'os' in directives:
info['os'] = self.shell_output('getprop ro.build.display.id',
timeout=timeout)
if 'process' in directives:
ps = self.shell_output('ps', timeout=timeout)
info['process'] = ps.splitlines()
if 'systime' in directives:
info['systime'] = self.shell_output('date', timeout=timeout)
if 'uptime' in directives:
uptime = self.shell_output('uptime', timeout=timeout)
if uptime:
m = re.match('up time: ((\d+) days, )*(\d{2}):(\d{2}):(\d{2})',
uptime)
if m:
uptime = '%d days %d hours %d minutes %d seconds' % tuple(
[int(g or 0) for g in m.groups()[1:]])
info['uptime'] = uptime
return info

View File

@ -10,8 +10,19 @@ from adb import ADBDevice, ADBError
from distutils.version import StrictVersion
class ADBAndroidMixin(object):
"""Mixin to extend ADB with Android-specific functionality"""
class ADBAndroid(ADBDevice):
"""ADBAndroid implements :class:`ADBDevice` providing Android-specific
functionality.
::
from mozdevice import ADBAndroid
adbdevice = ADBAndroid()
print adbdevice.list_files("/mnt/sdcard")
if adbdevice.process_exist("org.mozilla.fennec"):
print "Fennec is running"
"""
# Informational methods
@ -28,7 +39,6 @@ class ADBAndroidMixin(object):
:returns: battery charge as a percentage.
:raises: * ADBTimeoutError
* ADBError
"""
level = None
scale = None
@ -67,7 +77,6 @@ class ADBAndroidMixin(object):
:type timeout: integer or None
:raises: * ADBTimeoutError
* ADBError
"""
self.command_output(["wait-for-device"], timeout=timeout)
pm_error_string = "Error: Could not access the Package Manager"
@ -120,7 +129,6 @@ class ADBAndroidMixin(object):
:type timeout: integer or None
:raises: * ADBTimeoutError
* ADBError
"""
try:
self.shell_output('svc power stayon true', timeout=timeout)
@ -131,31 +139,6 @@ class ADBAndroidMixin(object):
raise
self._logger.warning('Unable to set power stayon true: %s' % e)
def reboot(self, timeout=None):
"""Reboots the device.
This method uses the Android only package manager to determine
if the device is ready after the reboot.
:param timeout: The maximum time in
seconds for any spawned adb process to complete before
throwing an ADBTimeoutError.
This timeout is per adb call. The total time spent
may exceed this value. If it is not specified, the value
set in the ADB constructor is used.
:type timeout: integer or None
:raises: * ADBTimeoutError
* ADBError
reboot() reboots the device, issues an adb wait-for-device in order to
wait for the device to complete rebooting, then calls is_device_ready()
to determine if the device has completed booting.
"""
self.command_output(["reboot"], timeout=timeout)
self.command_output(["wait-for-device"], timeout=timeout)
return self.is_device_ready(timeout=timeout)
# Application management methods
def install_app(self, apk_path, timeout=None):
@ -171,7 +154,6 @@ class ADBAndroidMixin(object):
:type timeout: integer or None
:raises: * ADBTimeoutError
* ADBError
"""
data = self.command_output(["install", apk_path], timeout=timeout)
if data.find('Success') == -1:
@ -191,7 +173,6 @@ class ADBAndroidMixin(object):
:type timeout: integer or None
:raises: * ADBTimeoutError
* ADBError
"""
pm_error_string = 'Error: Could not access the Package Manager'
data = self.shell_output("pm list package %s" % app_name, timeout=timeout)
@ -226,7 +207,6 @@ class ADBAndroidMixin(object):
:type timeout: integer or None
:raises: * ADBTimeoutError
* ADBError
"""
# If fail_if_running is True, we throw an exception here. Only one
# instance of an application can be running at once on Android,
@ -287,7 +267,6 @@ class ADBAndroidMixin(object):
:type timeout: integer or None
:raises: * ADBTimeoutError
* ADBError
"""
extras = {}
@ -327,7 +306,6 @@ class ADBAndroidMixin(object):
executed as root.
:raises: * ADBTimeoutError
* ADBError
"""
version = self.shell_output("getprop ro.build.version.release",
timeout=timeout, root=root)
@ -367,7 +345,6 @@ class ADBAndroidMixin(object):
:type timeout: integer or None
:raises: * ADBTimeoutError
* ADBError
"""
if self.is_app_installed(app_name, timeout=timeout):
data = self.command_output(["uninstall", app_name], timeout=timeout)
@ -391,27 +368,8 @@ class ADBAndroidMixin(object):
:type timeout: integer or None
:raises: * ADBTimeoutError
* ADBError
"""
output = self.command_output(["install", "-r", apk_path],
timeout=timeout)
self.reboot(timeout=timeout)
return output
class ADBAndroid(ADBDevice, ADBAndroidMixin):
"""ADBAndroid provides all of the methods of :class:`mozdevice.ADB` with
Android specific extensions useful for that platform.
::
from mozdevice import ADBAndroid as ADBDevice
adb = ADBDevice(...)
if adb.is_device_ready():
adb.install_app("/tmp/build.apk")
adb.launch_fennec("org.mozilla.fennec")
"""
pass

View File

@ -0,0 +1,122 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
import traceback
import mozfile
from adb import ADBDevice, ADBError
class ADBB2G(ADBDevice):
"""ADBB2G implements :class:`ADBDevice` providing B2G-specific
functionality.
::
from mozdevice import ADBB2G
adbdevice = ADBB2G()
print adbdevice.list_files("/mnt/sdcard")
if adbdevice.process_exist("b2g"):
print "B2G is running"
"""
def get_battery_percentage(self, timeout=None):
"""Returns the battery charge as a percentage.
:param timeout: optional integer specifying the maximum time in
seconds for any spawned adb process to complete before
throwing an ADBTimeoutError.
This timeout is per adb call. The total time spent
may exceed this value. If it is not specified, the value
set in the ADBDevice constructor is used.
:returns: battery charge as a percentage.
:raises: * ADBTimeoutError
* ADBError
"""
with mozfile.NamedTemporaryFile() as tf:
self.pull('/sys/class/power_supply/battery/capacity', tf.name,
timeout=timeout)
try:
with open(tf.name) as tf2:
return tf2.read().splitlines()[0]
except Exception as e:
raise ADBError(traceback.format_exception_only(
type(e), e)[0].strip())
def get_memory_total(self, timeout=None):
"""Returns the total memory available with units.
:param timeout: optional integer specifying the maximum time in
seconds for any spawned adb process to complete before
throwing an ADBTimeoutError.
This timeout is per adb call. The total time spent
may exceed this value. If it is not specified, the value
set in the ADBDevice constructor is used.
:returns: memory total with units.
:raises: * ADBTimeoutError
* ADBError
"""
meminfo = {}
with mozfile.NamedTemporaryFile() as tf:
self.pull('/proc/meminfo', tf.name, timeout=timeout)
try:
with open(tf.name) as tf2:
for line in tf2.read().splitlines():
key, value = line.split(':')
meminfo[key] = value.strip()
except Exception as e:
raise ADBError(traceback.format_exception_only(
type(e), e)[0].strip())
return meminfo['MemTotal']
def get_info(self, directive=None, timeout=None):
"""
Returns a dictionary of information strings about the device.
:param directive: information you want to get. Options are:
- `battery` - battery charge as a percentage
- `disk` - total, free, available bytes on disk
- `id` - unique id of the device
- `memtotal` - total memory available on the device
- `os` - name of the os
- `process` - list of running processes (same as ps)
- `systime` - system time of the device
- `uptime` - uptime of the device
If `directive` is `None`, will return all available information
:param timeout: optional integer specifying the maximum time in
seconds for any spawned adb process to complete before
throwing an ADBTimeoutError.
This timeout is per adb call. The total time spent
may exceed this value. If it is not specified, the value
set in the ADB constructor is used.
:raises: * ADBTimeoutError
* ADBError
"""
info = super(ADBB2G, self).get_info(directive=directive,
timeout=timeout)
directives = ['memtotal']
if (directive in directives):
directives = [directive]
if 'memtotal' in directives:
info['memtotal'] = self.get_memory_total(timeout=timeout)
return info
def is_device_ready(self, timeout=None):
"""Returns True if the device is ready.
:param timeout: optional integer specifying the maximum time in
seconds for any spawned adb process to complete before
throwing an ADBTimeoutError.
This timeout is per adb call. The total time spent
may exceed this value. If it is not specified, the value
set in the ADB constructor is used.
:raises: * ADBTimeoutError
* ADBError
"""
return self.shell_bool('ls /sbin', timeout=timeout)

View File

@ -23,6 +23,10 @@ config = {
"path": "/firefox/releases/%(version)s/win32/:lang/Firefox%%20Setup%%20%(version)s.exe",
"bouncer-platform": "win",
},
"win64": {
"path": "/firefox/releases/%(version)s/win64/:lang/Firefox%%20Setup%%20%(version)s.exe",
"bouncer-platform": "win64",
},
"opensolaris-i386": {
"path": "/firefox/releases/%(version)s/contrib/solaris_tarball/firefox-%(version)s.en-US.opensolaris-i386.tar.bz2",
"bouncer-platform": "opensolaris-i386",
@ -62,6 +66,10 @@ config = {
"path": "/firefox/releases/%(version)s/win32/:lang/Firefox%%20Setup%%20%(version)s.exe",
"bouncer-platform": "win",
},
"win64": {
"path": "/firefox/releases/%(version)s/win64/:lang/Firefox%%20Setup%%20%(version)s.exe",
"bouncer-platform": "win64",
},
"opensolaris-i386": {
"path": "/firefox/releases/%(version)s/contrib/solaris_tarball/firefox-%(version)s.en-US.opensolaris-i386.tar.bz2",
"bouncer-platform": "opensolaris-i386",
@ -89,6 +97,10 @@ config = {
"path": "/firefox/releases/%(version)s/win32/:lang/Firefox%%20Setup%%20Stub%%20%(version)s.exe",
"bouncer-platform": "win",
},
"win64": {
"path": "/firefox/releases/%(version)s/win64/:lang/Firefox%%20Setup%%20Stub%%20%(version)s.exe",
"bouncer-platform": "win64",
},
},
},
"complete-mar": {
@ -112,6 +124,10 @@ config = {
"path": "/firefox/releases/%(version)s/update/win32/:lang/firefox-%(version)s.complete.mar",
"bouncer-platform": "win",
},
"win64": {
"path": "/firefox/releases/%(version)s/update/win64/:lang/firefox-%(version)s.complete.mar",
"bouncer-platform": "win64",
},
"opensolaris-i386": {
"path": "/firefox/releases/%(version)s/contrib/solaris_tarball/firefox-%(version)s.en-US.opensolaris-i386.complete.mar",
"bouncer-platform": "opensolaris-i386",
@ -151,6 +167,10 @@ config = {
"path": "/firefox/candidates/%(version)s-candidates/build%(build_number)s/update/win32/:lang/firefox-%(version)s.complete.mar",
"bouncer-platform": "win",
},
"win64": {
"path": "/firefox/candidates/%(version)s-candidates/build%(build_number)s/update/win64/:lang/firefox-%(version)s.complete.mar",
"bouncer-platform": "win64",
},
},
},
},
@ -176,6 +196,10 @@ config = {
"path": "/firefox/releases/%(version)s/update/win32/:lang/firefox-%(prev_version)s-%(version)s.partial.mar",
"bouncer-platform": "win",
},
"win64": {
"path": "/firefox/releases/%(version)s/update/win64/:lang/firefox-%(prev_version)s-%(version)s.partial.mar",
"bouncer-platform": "win64",
},
"opensolaris-i386": {
"path": "/firefox/releases/%(version)s/contrib/solaris_tarball/firefox-%(prev_version)s-%(version)s.en-US.opensolaris-i386.partial.mar",
"bouncer-platform": "opensolaris-i386",
@ -215,6 +239,10 @@ config = {
"path": "/firefox/candidates/%(version)s-candidates/build%(build_number)s/update/win32/:lang/firefox-%(prev_version)s-%(version)s.partial.mar",
"bouncer-platform": "win",
},
"win64": {
"path": "/firefox/candidates/%(version)s-candidates/build%(build_number)s/update/win64/:lang/firefox-%(prev_version)s-%(version)s.partial.mar",
"bouncer-platform": "win64",
},
},
},
},

View File

@ -858,6 +858,10 @@ or run without that action (ie: --no-{action})"
# to activate the right behaviour in mozonfigs while we transition
if c.get('enable_release_promotion'):
env['ENABLE_RELEASE_PROMOTION'] = "1"
update_channel = c.get('update_channel', self.branch)
self.info("Release promotion update channel: %s"
% (update_channel,))
env["MOZ_UPDATE_CHANNEL"] = update_channel
# we can't make env an attribute of self because env can change on
# every call for reasons like MOZ_SIGN_CMD

View File

@ -155,7 +155,8 @@ class AntivirusScan(BaseScript, VirtualenvMixin):
return retry(key.get_contents_to_filename,
args=(destination, ),
sleeptime=5, max_sleeptime=60,
retry_exceptions=(S3CopyError, S3ResponseError))
retry_exceptions=(S3CopyError, S3ResponseError,
IOError))
def find_release_files():
candidates_prefix = self._get_candidates_prefix()

View File

@ -192,7 +192,7 @@ class B2GExecutorBrowser(ExecutorBrowser):
import sys, subprocess
self.device = mozdevice.ADBDevice()
self.device = mozdevice.ADBB2G()
self.device.forward("tcp:%s" % self.marionette_port,
"tcp:2828")
self.executor = None

View File

@ -113,7 +113,7 @@ public:
bool mWantReplyFromContentProcess : 1;
// The event's action will be handled by APZ. The main thread should not
// perform its associated action. This is currently only relevant for
// wheel events.
// wheel and touch events.
bool mHandledByAPZ : 1;
// If the event is being handled in target phase, returns true.

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