From d51649d86ad42e166dae43431ac0e78fdbb4afe2 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Tue, 9 Jun 2015 14:07:08 -0700 Subject: [PATCH 01/95] Bug 1171171: Move nsAppRunner's gfxPrefs #include out of windows-specific section. r=milan a=KWierso --- toolkit/xre/nsAppRunner.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index c568a43d2724..150f76945bff 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -87,6 +87,7 @@ #include "nsAppShellCID.h" #include "mozilla/scache/StartupCache.h" #include "nsIGfxInfo.h" +#include "gfxPrefs.h" #include "base/histogram.h" @@ -100,8 +101,6 @@ #include "cairo/cairo-features.h" #include "mozilla/WindowsVersion.h" -#include "gfxPrefs.h" - #ifndef PROCESS_DEP_ENABLE #define PROCESS_DEP_ENABLE 0x1 #endif From 65e7f383031d0a7fd9fb186947083de83ad6fd05 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Tue, 9 Jun 2015 15:21:13 -0400 Subject: [PATCH 02/95] Bug 1170937 - Set the URL on the Response object created from a fetch() properly if the underlying channel gets redirected; r=baku --- dom/fetch/FetchDriver.cpp | 22 ++++++++++++++++------ dom/fetch/FetchDriver.h | 3 ++- dom/tests/mochitest/fetch/mochitest.ini | 6 ++---- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/dom/fetch/FetchDriver.cpp b/dom/fetch/FetchDriver.cpp index a188fe1d6d8b..7c42a4864c0c 100644 --- a/dom/fetch/FetchDriver.cpp +++ b/dom/fetch/FetchDriver.cpp @@ -548,14 +548,16 @@ FetchDriver::ContinueHttpFetchAfterNetworkFetch() } already_AddRefed -FetchDriver::BeginAndGetFilteredResponse(InternalResponse* aResponse) +FetchDriver::BeginAndGetFilteredResponse(InternalResponse* aResponse, nsIURI* aFinalURI) { MOZ_ASSERT(aResponse); - if (!aResponse->FinalURL()) { - nsAutoCString reqURL; + nsAutoCString reqURL; + if (aFinalURI) { + aFinalURI->GetSpec(reqURL); + } else { mRequest->GetURL(reqURL); - aResponse->SetUrl(reqURL); } + aResponse->SetUrl(reqURL); // FIXME(nsm): Handle mixed content check, step 7 of fetch. @@ -584,7 +586,7 @@ FetchDriver::BeginAndGetFilteredResponse(InternalResponse* aResponse) void FetchDriver::BeginResponse(InternalResponse* aResponse) { - nsRefPtr r = BeginAndGetFilteredResponse(aResponse); + nsRefPtr r = BeginAndGetFilteredResponse(aResponse, nullptr); // Release the ref. } @@ -716,9 +718,17 @@ FetchDriver::OnStartRequest(nsIRequest* aRequest, nsCOMPtr channel = do_QueryInterface(aRequest); response->InitChannelInfo(channel); + nsCOMPtr channelURI; + rv = channel->GetURI(getter_AddRefs(channelURI)); + if (NS_WARN_IF(NS_FAILED(rv))) { + FailWithNetworkError(); + // Cancel request. + return rv; + } + // Resolves fetch() promise which may trigger code running in a worker. Make // sure the Response is fully initialized before calling this. - mResponse = BeginAndGetFilteredResponse(response); + mResponse = BeginAndGetFilteredResponse(response, channelURI); nsCOMPtr sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv); if (NS_WARN_IF(NS_FAILED(rv))) { diff --git a/dom/fetch/FetchDriver.h b/dom/fetch/FetchDriver.h index 6b8861434af3..ed376c999a73 100644 --- a/dom/fetch/FetchDriver.h +++ b/dom/fetch/FetchDriver.h @@ -88,8 +88,9 @@ private: nsresult HttpFetch(bool aCORSFlag = false, bool aCORSPreflightFlag = false, bool aAuthenticationFlag = false); nsresult ContinueHttpFetchAfterNetworkFetch(); // Returns the filtered response sent to the observer. + // Callers who don't have access to a channel can pass null for aFinalURI. already_AddRefed - BeginAndGetFilteredResponse(InternalResponse* aResponse); + BeginAndGetFilteredResponse(InternalResponse* aResponse, nsIURI* aFinalURI); // Utility since not all cases need to do any post processing of the filtered // response. void BeginResponse(InternalResponse* aResponse); diff --git a/dom/tests/mochitest/fetch/mochitest.ini b/dom/tests/mochitest/fetch/mochitest.ini index 9febdd63972b..84e18b479e5b 100644 --- a/dom/tests/mochitest/fetch/mochitest.ini +++ b/dom/tests/mochitest/fetch/mochitest.ini @@ -27,12 +27,10 @@ skip-if = buildapp == 'b2g' # Bug 1137683 skip-if = buildapp == 'b2g' # Bug 1137683 [test_fetch_basic_http.html] [test_fetch_basic_http_sw_reroute.html] -skip-if = true # Bug 1170937, need fully support for redirects -#skip-if = buildapp == 'b2g' # Bug 1137683 +skip-if = buildapp == 'b2g' # Bug 1137683 [test_fetch_cors.html] [test_fetch_cors_sw_reroute.html] -skip-if = true # Bug 1170937, need fully support for redirects -#skip-if = buildapp == 'b2g' # Bug 1137683 +skip-if = buildapp == 'b2g' # Bug 1137683 [test_formdataparsing.html] [test_formdataparsing_sw_reroute.html] skip-if = buildapp == 'b2g' # Bug 1137683 From ed54538c7f1a12c48418e33e3a9cef1ecab05e2a Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Tue, 9 Jun 2015 15:23:13 -0400 Subject: [PATCH 03/95] Bug 1173029 - Remove mFinalURL from InternalResponse; r=baku a=KWierso --- dom/fetch/InternalResponse.cpp | 1 - dom/fetch/InternalResponse.h | 15 --------------- 2 files changed, 16 deletions(-) diff --git a/dom/fetch/InternalResponse.cpp b/dom/fetch/InternalResponse.cpp index 2791a013e2da..ae67917dd807 100644 --- a/dom/fetch/InternalResponse.cpp +++ b/dom/fetch/InternalResponse.cpp @@ -14,7 +14,6 @@ namespace dom { InternalResponse::InternalResponse(uint16_t aStatus, const nsACString& aStatusText) : mType(ResponseType::Default) - , mFinalURL(false) , mStatus(aStatus) , mStatusText(aStatusText) , mHeaders(new InternalHeaders(HeadersGuardEnum::Response)) diff --git a/dom/fetch/InternalResponse.h b/dom/fetch/InternalResponse.h index 9b88de778ccd..694033ad0f78 100644 --- a/dom/fetch/InternalResponse.h +++ b/dom/fetch/InternalResponse.h @@ -48,7 +48,6 @@ public: response->mType = ResponseType::Opaque; response->mTerminationReason = mTerminationReason; response->mURL = mURL; - response->mFinalURL = mFinalURL; response->mChannelInfo = mChannelInfo; response->mWrappedResponse = this; return response.forget(); @@ -90,18 +89,6 @@ public: mURL.Assign(aURL); } - bool - FinalURL() const - { - return mFinalURL; - } - - void - SetFinalURL(bool aFinalURL) - { - mFinalURL = aFinalURL; - } - uint16_t GetStatus() const { @@ -197,7 +184,6 @@ private: copy->mType = mType; copy->mTerminationReason = mTerminationReason; copy->mURL = mURL; - copy->mFinalURL = mFinalURL; copy->mChannelInfo = mChannelInfo; return copy.forget(); } @@ -205,7 +191,6 @@ private: ResponseType mType; nsCString mTerminationReason; nsCString mURL; - bool mFinalURL; const uint16_t mStatus; const nsCString mStatusText; nsRefPtr mHeaders; From eb73e64e7c0ab2c2bca7c4bed17c5fc48c4ebee9 Mon Sep 17 00:00:00 2001 From: David Major Date: Tue, 9 Jun 2015 16:48:59 -0400 Subject: [PATCH 04/95] Bug 1173107: Add hexa() around various hr logging. r=jrmuizel a=KWierso --- gfx/2d/DrawTargetD2D.cpp | 5 +++-- gfx/layers/d3d11/CompositorD3D11.cpp | 7 ++++--- gfx/thebes/gfxWindowsPlatform.cpp | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/gfx/2d/DrawTargetD2D.cpp b/gfx/2d/DrawTargetD2D.cpp index 08d68c3b64dd..57be72b4c3a9 100644 --- a/gfx/2d/DrawTargetD2D.cpp +++ b/gfx/2d/DrawTargetD2D.cpp @@ -1964,7 +1964,7 @@ DrawTargetD2D::CreateRTForTexture(ID3D10Texture2D *aTexture, SurfaceFormat aForm hr = aTexture->QueryInterface((IDXGISurface**)byRef(surface)); if (FAILED(hr)) { - gfxCriticalError() << "Failed to QI texture to surface. Code: " << hr; + gfxCriticalError() << "Failed to QI texture to surface. Code: " << hexa(hr); return nullptr; } @@ -1982,7 +1982,8 @@ DrawTargetD2D::CreateRTForTexture(ID3D10Texture2D *aTexture, SurfaceFormat aForm hr = factory()->CreateDxgiSurfaceRenderTarget(surface, props, byRef(rt)); if (FAILED(hr)) { - gfxCriticalError() << "Failed to create D2D render target for texture. Code:" << hr << " " << mSize << " Format: " << uint32_t(aFormat); + gfxCriticalError() << "Failed to create D2D render target for texture. Code: " + << hexa(hr) << " " << mSize << " Format: " << uint32_t(aFormat); return nullptr; } diff --git a/gfx/layers/d3d11/CompositorD3D11.cpp b/gfx/layers/d3d11/CompositorD3D11.cpp index 2b00e9652f34..292a94baeb18 100644 --- a/gfx/layers/d3d11/CompositorD3D11.cpp +++ b/gfx/layers/d3d11/CompositorD3D11.cpp @@ -413,7 +413,8 @@ CompositorD3D11::GetTextureFactoryIdentifier() if (mAttachments->mSyncTexture) { HRESULT hr = mAttachments->mSyncTexture->GetSharedHandle(&ident.mSyncHandle); if (FAILED(hr) || !ident.mSyncHandle) { - gfxCriticalError() << "Failed to get SharedHandle for sync texture. Result: " << hr; + gfxCriticalError() << "Failed to get SharedHandle for sync texture. Result: " + << hexa(hr); MOZ_CRASH(); } } @@ -1342,7 +1343,7 @@ CompositorD3D11::UpdateConstantBuffers() hr = mContext->Map(mAttachments->mVSConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource); if (Failed(hr) || !resource.pData) { - gfxCriticalError() << "Failed to map VSConstantBuffer. Result: " << hr; + gfxCriticalError() << "Failed to map VSConstantBuffer. Result: " << hexa(hr); return false; } *(VertexShaderConstants*)resource.pData = mVSConstants; @@ -1351,7 +1352,7 @@ CompositorD3D11::UpdateConstantBuffers() hr = mContext->Map(mAttachments->mPSConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource); if (Failed(hr) || !resource.pData) { - gfxCriticalError() << "Failed to map PSConstantBuffer. Result: " << hr; + gfxCriticalError() << "Failed to map PSConstantBuffer. Result: " << hexa(hr); return false; } *(PixelShaderConstants*)resource.pData = mPSConstants; diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp index cfbe821bc38d..dea314dea83a 100644 --- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -1980,7 +1980,7 @@ gfxWindowsPlatform::InitD3D11Devices() if (FAILED(hr)) { // This should always succeed... in theory. - gfxCriticalError() << "Failed to initialize WARP D3D11 device!" << hr; + gfxCriticalError() << "Failed to initialize WARP D3D11 device! " << hexa(hr); return; } From 215b1e0292eb701422c547506787e0210b69ab87 Mon Sep 17 00:00:00 2001 From: Ben Turner Date: Tue, 9 Jun 2015 14:34:00 -0700 Subject: [PATCH 05/95] Bug 1173002 - Set worker system principal flag correctly when created from chrome, r=bz, a=kwierso. --- dom/workers/ScriptLoader.cpp | 8 +++++--- dom/workers/WorkerPrivate.cpp | 9 ++++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/dom/workers/ScriptLoader.cpp b/dom/workers/ScriptLoader.cpp index 4398d4161f26..6eda7de113a1 100644 --- a/dom/workers/ScriptLoader.cpp +++ b/dom/workers/ScriptLoader.cpp @@ -983,9 +983,11 @@ private: // If the load principal is the system principal then the channel // principal must also be the system principal (we do not allow chrome - // code to create workers with non-chrome scripts). Otherwise this channel - // principal must be same origin with the load principal (we check again - // here in case redirects changed the location of the script). + // code to create workers with non-chrome scripts, and if we ever decide + // to change this we need to make sure we don't always set + // mPrincipalIsSystem to true in WorkerPrivate::GetLoadInfo()). Otherwise + // this channel principal must be same origin with the load principal (we + // check again here in case redirects changed the location of the script). if (nsContentUtils::IsSystemPrincipal(loadPrincipal)) { if (!nsContentUtils::IsSystemPrincipal(channelPrincipal)) { // See if this is a resource URI. Since JSMs usually come from diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index 19bda025ab71..8d05961eac32 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -4885,12 +4885,15 @@ WorkerPrivate::GetLoadInfo(JSContext* aCx, nsPIDOMWindow* aWindow, return NS_ERROR_DOM_SECURITY_ERR; } - // Chrome callers (whether ChromeWorker of Worker) always get the system - // principal here as they're allowed to load anything. The script loader may - // change the principal later depending on the script uri. + // Chrome callers (whether creating a ChromeWorker or Worker) always get the + // system principal here as they're allowed to load anything. The script + // loader will refuse to run any script that does not also have the system + // principal. if (isChrome) { rv = ssm->GetSystemPrincipal(getter_AddRefs(loadInfo.mPrincipal)); NS_ENSURE_SUCCESS(rv, rv); + + loadInfo.mPrincipalIsSystem = true; } // See if we're being called from a window. From c9c2607c21612d0b17e9fecb65f08bcdec2875dd Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Mon, 8 Jun 2015 11:38:40 -0400 Subject: [PATCH 06/95] bug 1172538 - make sure a document has an IPC actor before shutting it down r=davidb, lsocks If a document is shutdown before ever being bound to a parent document it doesn't have an associated IPC actor, so we shouldn't try and shut one down. --- accessible/generic/DocAccessible.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/accessible/generic/DocAccessible.cpp b/accessible/generic/DocAccessible.cpp index edf2618a225d..5eade3209ed7 100644 --- a/accessible/generic/DocAccessible.cpp +++ b/accessible/generic/DocAccessible.cpp @@ -455,7 +455,8 @@ DocAccessible::Shutdown() mChildDocuments.Clear(); // XXX thinking about ordering? - if (IPCAccessibilityActive()) { + if (mIPCDoc) { + MOZ_ASSERT(IPCAccessibilityActive()); mIPCDoc->Shutdown(); MOZ_ASSERT(!mIPCDoc); } From 07c93b66f79131262270f8c4329e2e0d76e5e254 Mon Sep 17 00:00:00 2001 From: Steve Fink Date: Mon, 8 Jun 2015 12:32:17 -0700 Subject: [PATCH 07/95] Bug 1166101 - redirect aka os.file.redirect should not be available in fuzzing mode --HG-- extra : rebase_source : a12c59e3816f53c17fe9eb7cb8e607a8ae300696 --- js/src/shell/OSObject.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/js/src/shell/OSObject.cpp b/js/src/shell/OSObject.cpp index 39b20dd3f2e5..341ba88ac968 100644 --- a/js/src/shell/OSObject.cpp +++ b/js/src/shell/OSObject.cpp @@ -267,6 +267,10 @@ static const JSFunctionSpecWithHelp osfile_functions[] = { " Read filename into returned string. Filename is relative to the directory\n" " containing the current script."), + JS_FS_HELP_END +}; + +static const JSFunctionSpecWithHelp osfile_unsafe_functions[] = { JS_FN_HELP("redirect", osfile_redirect, 2, 0, "redirect(stdoutFilename[, stderrFilename])", " Redirect stdout and/or stderr to the named file. Pass undefined to avoid\n" @@ -566,6 +570,11 @@ DefineOS(JSContext* cx, HandleObject global, bool fuzzingSafe) return false; } + if (!fuzzingSafe) { + if (!JS_DefineFunctionsWithHelp(cx, osfile, osfile_unsafe_functions)) + return false; + } + // For backwards compatibility, expose various os.file.* functions as // direct methods on the global. RootedValue val(cx); @@ -583,9 +592,11 @@ DefineOS(JSContext* cx, HandleObject global, bool fuzzingSafe) for (auto pair : osfile_exports) { if (!JS_GetProperty(cx, osfile, pair.src, &val)) return false; - RootedObject function(cx, &val.toObject()); - if (!JS_DefineProperty(cx, global, pair.dst, function, 0)) - return false; + if (val.isObject()) { + RootedObject function(cx, &val.toObject()); + if (!JS_DefineProperty(cx, global, pair.dst, function, 0)) + return false; + } } return true; From e39fdb1b069a9bc99f17b6bc6971ec2156ab19b5 Mon Sep 17 00:00:00 2001 From: Steve Fink Date: Tue, 9 Jun 2015 14:53:17 -0700 Subject: [PATCH 08/95] No bug. Add a --function argument for analyzing a single function by name. --HG-- extra : rebase_source : 5fa23c8bdfe574cd868added7ba067df8a0b4989 --- js/src/devtools/rootAnalysis/analyzeRoots.js | 45 ++++++++++++-------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/js/src/devtools/rootAnalysis/analyzeRoots.js b/js/src/devtools/rootAnalysis/analyzeRoots.js index 9e870a967bf3..624ec9cb9d01 100644 --- a/js/src/devtools/rootAnalysis/analyzeRoots.js +++ b/js/src/devtools/rootAnalysis/analyzeRoots.js @@ -8,10 +8,17 @@ loadRelativeToScript('CFG.js'); var sourceRoot = (os.getenv('SOURCE') || '') + '/' +var functionName; var functionBodies; if (typeof scriptArgs[0] != 'string' || typeof scriptArgs[1] != 'string') - throw "Usage: analyzeRoots.js [start end [tmpfile]]"; + throw "Usage: analyzeRoots.js [-f function_name] [start end [tmpfile]]"; + +var theFunctionNameToFind; +if (scriptArgs[0] == '--function') { + theFunctionNameToFind = scriptArgs[1]; + scriptArgs = scriptArgs.slice(2); +} var gcFunctionsFile = scriptArgs[0]; var gcEdgesFile = scriptArgs[1]; @@ -635,24 +642,10 @@ var end = Math.min(minStream + each * batch - 1, maxStream); var theFunctionNameToFind; // var start = end = 12345; -for (var nameIndex = start; nameIndex <= end; nameIndex++) { - var name = xdb.read_key(nameIndex); - var functionName = name.readString(); - var data = xdb.read_entry(name); - xdb.free_string(name); - var json = data.readString(); - xdb.free_string(data); +function process(name, json) { + functionName = name; functionBodies = JSON.parse(json); - if (theFunctionNameToFind) { - if (functionName == theFunctionNameToFind) { - printErr("nameIndex = " + nameIndex); - quit(1); - } else { - continue; - } - } - for (var body of functionBodies) body.suppressed = []; for (var body of functionBodies) { @@ -661,3 +654,21 @@ for (var nameIndex = start; nameIndex <= end; nameIndex++) { } processBodies(functionName); } + +if (theFunctionNameToFind) { + var data = xdb.read_entry(theFunctionNameToFind); + var json = data.readString(); + process(theFunctionNameToFind, json); + xdb.free_string(data); + quit(0); +} + +for (var nameIndex = start; nameIndex <= end; nameIndex++) { + var name = xdb.read_key(nameIndex); + var functionName = name.readString(); + var data = xdb.read_entry(name); + xdb.free_string(name); + var json = data.readString(); + process(functionName, json); + xdb.free_string(data); +} From 2114f90ea70bddd1f03f16128457625851de4359 Mon Sep 17 00:00:00 2001 From: Steve Fink Date: Tue, 9 Jun 2015 14:53:40 -0700 Subject: [PATCH 09/95] Bug 1172682 - Comment and refactor analysis code, r=terrence The one change this patch makes in functionality is that it properly computes minimumUse in more cases, in anticipation of it being used for hazards (in addition to its current use for unnecessary roots). --HG-- extra : rebase_source : d2a3068933aefd9d16d944361738a9f68685984c --- js/src/devtools/rootAnalysis/analyzeRoots.js | 95 ++++++++++++++------ 1 file changed, 70 insertions(+), 25 deletions(-) diff --git a/js/src/devtools/rootAnalysis/analyzeRoots.js b/js/src/devtools/rootAnalysis/analyzeRoots.js index 624ec9cb9d01..48e94be158e8 100644 --- a/js/src/devtools/rootAnalysis/analyzeRoots.js +++ b/js/src/devtools/rootAnalysis/analyzeRoots.js @@ -216,7 +216,7 @@ function edgeTakesVariableAddress(edge, variable) function edgeKillsVariable(edge, variable) { - // Direct assignments kill their lhs. + // Direct assignments kill their lhs: var = value if (edge.Kind == "Assign") { var lhs = edge.Exp[0]; if (lhs.Kind == "Var" && sameVariable(lhs.Variable, variable)) @@ -303,26 +303,48 @@ function edgeCanGC(edge) return indirectCallCannotGC(functionName, varName) ? null : "*" + varName; } -function variableUsePrecedesGC(suppressed, variable, worklist) +// Search recursively through predecessors from a variable use, returning +// whether a GC call is reachable (in the reverse direction; this means that +// the variable use is reachable from the GC call, and therefore the variable +// is live after the GC call), along with some additional information. What +// info we want depends on whether the variable turns out to be live across any +// GC call. We are looking for both hazards (unrooted variables live across GC +// calls) and unnecessary roots (rooted variables that have no GC calls in +// their live ranges.) +// +// If not: +// +// - 'minimumUse': the earliest point in each body that uses the variable, for +// reporting on unnecessary roots. +// +// If so: +// +// - 'why': a path from the GC call to a use of the variable after the GC +// call, chained through a 'why' field in the returned edge descriptor +// +// - 'gcInfo': a direct pointer to the GC call edge +// +function findGCBeforeVariableUse(suppressed, variable, worklist) { // Scan through all edges preceding an unrooted variable use, using an - // explicit worklist. A worklist contains an incoming edge together with a - // description of where it or one of its successors GC'd (if any). + // explicit worklist, looking for a GC call. A worklist contains an + // incoming edge together with a description of where it or one of its + // successors GC'd (if any). while (worklist.length) { var entry = worklist.pop(); - var body = entry.body, ppoint = entry.ppoint; + var { body, ppoint, gcInfo } = entry; if (body.seen) { if (ppoint in body.seen) { var seenEntry = body.seen[ppoint]; - if (!entry.gcInfo || seenEntry.gcInfo) + if (!gcInfo || seenEntry.gcInfo) continue; } } else { body.seen = []; } - body.seen[ppoint] = {body:body, gcInfo:entry.gcInfo}; + body.seen[ppoint] = {body: body, gcInfo: gcInfo}; if (ppoint == body.Index[0]) { if (body.BlockId.Kind == "Loop") { @@ -334,17 +356,17 @@ function variableUsePrecedesGC(suppressed, variable, worklist) if (sameBlockId(xbody.BlockId, parent.BlockId)) { assert(!found); found = true; - worklist.push({body:xbody, ppoint:parent.Index, - gcInfo:entry.gcInfo, why:entry}); + worklist.push({body: xbody, ppoint: parent.Index, + gcInfo: gcInfo, why: entry}); } } assert(found); } } - } else if (variable.Kind == "Arg" && entry.gcInfo) { + } else if (variable.Kind == "Arg" && gcInfo) { // The scope of arguments starts at the beginning of the // function - return {gcInfo:entry.gcInfo, why:entry}; + return {gcInfo: gcInfo, why: entry}; } } @@ -355,31 +377,45 @@ function variableUsePrecedesGC(suppressed, variable, worklist) for (var edge of predecessors[ppoint]) { var source = edge.Index[0]; - if (edgeKillsVariable(edge, variable)) { - if (entry.gcInfo) - return {gcInfo: entry.gcInfo, why: {body:body, ppoint:source, gcInfo:entry.gcInfo, why:entry } } + var edge_kills = edgeKillsVariable(edge, variable); + var edge_uses = edgeUsesVariable(edge, variable, body); + + if (edge_kills || edge_uses) { if (!body.minimumUse || source < body.minimumUse) body.minimumUse = source; + } + + if (edge_kills) { + // This is a beginning of the variable's live range. If we can + // reach a GC call from here, then we're done -- we have a path + // from the beginning of the live range, through the GC call, + // to a use after the GC call that proves its live range + // extends at least that far. + if (gcInfo) + return {gcInfo: gcInfo, why: {body: body, ppoint: source, gcInfo: gcInfo, why: entry } } + + // Otherwise, we want to continue searching for the true + // minimumUse, for use in reporting unnecessary rooting, but we + // truncate this particular branch of the search at this edge. continue; } - var gcInfo = entry.gcInfo; if (!gcInfo && !(source in body.suppressed) && !suppressed) { var gcName = edgeCanGC(edge, body); if (gcName) gcInfo = {name:gcName, body:body, ppoint:source}; } - if (edgeUsesVariable(edge, variable, body)) { + if (edge_uses) { + // The live range starts at least this far back, so we're done + // for the same reason as with edge_kills. if (gcInfo) return {gcInfo:gcInfo, why:entry}; - if (!body.minimumUse || source < body.minimumUse) - body.minimumUse = source; } if (edge.Kind == "Loop") { - // propagate to exit points of the loop body, in addition to the - // predecessor of the loop edge itself. + // Additionally propagate the search into a loop body, starting + // with the exit point. var found = false; for (var xbody of functionBodies) { if (sameBlockId(xbody.BlockId, edge.BlockId)) { @@ -392,6 +428,8 @@ function variableUsePrecedesGC(suppressed, variable, worklist) assert(found); break; } + + // Propagate the search to the predecessors of this edge. worklist.push({body:body, ppoint:source, gcInfo:gcInfo, why:entry}); } } @@ -414,14 +452,21 @@ function variableLiveAcrossGC(suppressed, variable) continue; for (var edge of body.PEdge) { var usePoint = edgeUsesVariable(edge, variable, body); + // Example for !edgeKillsVariable: + // + // JSObject* obj = NewObject(); + // cangc(); + // obj = NewObject(); <-- uses 'obj', but kills previous value + // if (usePoint && !edgeKillsVariable(edge, variable)) { // Found a use, possibly after a GC. var worklist = [{body:body, ppoint:usePoint, gcInfo:null, why:null}]; - var call = variableUsePrecedesGC(suppressed, variable, worklist); - if (call) { - call.afterGCUse = usePoint; - return call; - } + var call = findGCBeforeVariableUse(suppressed, variable, worklist); + if (!call) + continue; + + call.afterGCUse = usePoint; + return call; } } } From c3704cadb3ad30ea61a351bd2bbd92cbe588878c Mon Sep 17 00:00:00 2001 From: David Keeler Date: Wed, 3 Jun 2015 15:12:00 -0700 Subject: [PATCH 10/95] bug 1171557 - convert test_cert_trust.js to generate certificates at build time r=mgoodwin --- security/manager/ssl/tests/unit/moz.build | 1 + security/manager/ssl/tests/unit/pycert.py | 6 +- .../manager/ssl/tests/unit/test_cert_trust.js | 2 +- .../ssl/tests/unit/test_cert_trust/ca.der | Bin 782 -> 0 bytes .../unit/test_cert_trust/ca.pem.certspec | 5 ++ .../ssl/tests/unit/test_cert_trust/ee.der | Bin 712 -> 0 bytes .../unit/test_cert_trust/ee.pem.certspec | 2 + .../tests/unit/test_cert_trust/generate.py | 72 ------------------ .../ssl/tests/unit/test_cert_trust/int.der | Bin 783 -> 0 bytes .../unit/test_cert_trust/int.pem.certspec | 5 ++ .../ssl/tests/unit/test_cert_trust/moz.build | 19 +++++ 11 files changed, 38 insertions(+), 74 deletions(-) delete mode 100644 security/manager/ssl/tests/unit/test_cert_trust/ca.der create mode 100644 security/manager/ssl/tests/unit/test_cert_trust/ca.pem.certspec delete mode 100644 security/manager/ssl/tests/unit/test_cert_trust/ee.der create mode 100644 security/manager/ssl/tests/unit/test_cert_trust/ee.pem.certspec delete mode 100755 security/manager/ssl/tests/unit/test_cert_trust/generate.py delete mode 100644 security/manager/ssl/tests/unit/test_cert_trust/int.der create mode 100644 security/manager/ssl/tests/unit/test_cert_trust/int.pem.certspec create mode 100644 security/manager/ssl/tests/unit/test_cert_trust/moz.build diff --git a/security/manager/ssl/tests/unit/moz.build b/security/manager/ssl/tests/unit/moz.build index ab01313e2c4d..4f3731d12b45 100644 --- a/security/manager/ssl/tests/unit/moz.build +++ b/security/manager/ssl/tests/unit/moz.build @@ -7,6 +7,7 @@ DIRS += ['tlsserver'] TEST_DIRS += [ 'test_cert_keyUsage', + 'test_cert_trust', 'test_intermediate_basic_usage_constraints', ] diff --git a/security/manager/ssl/tests/unit/pycert.py b/security/manager/ssl/tests/unit/pycert.py index f758f083949d..de114847be4a 100755 --- a/security/manager/ssl/tests/unit/pycert.py +++ b/security/manager/ssl/tests/unit/pycert.py @@ -19,7 +19,7 @@ Known extensions are: basicConstraints:[cA],[pathLenConstraint] keyUsage:[digitalSignature,nonRepudiation,keyEncipherment, dataEncipherment,keyAgreement,keyCertSign,cRLSign] -extKeyUsage:[serverAuth,clientAuth] +extKeyUsage:[serverAuth,clientAuth,codeSigning,emailProtection] In the future it will be possible to specify other properties of the generated certificate (for example, its validity period, signature @@ -279,6 +279,10 @@ class Certificate: return univ.ObjectIdentifier('1.3.6.1.5.5.7.3.1') if keyPurpose == 'clientAuth': return rfc2459.id_kp_clientAuth + if keyPurpose == 'codeSigning': + return rfc2459.id_kp_codeSigning + if keyPurpose == 'emailProtection': + return rfc2459.id_kp_emailProtection raise UnknownKeyPurposeTypeError(keyPurpose) def addExtKeyUsage(self, extKeyUsage): diff --git a/security/manager/ssl/tests/unit/test_cert_trust.js b/security/manager/ssl/tests/unit/test_cert_trust.js index 9a9d51a10fa7..ea40a55c0999 100644 --- a/security/manager/ssl/tests/unit/test_cert_trust.js +++ b/security/manager/ssl/tests/unit/test_cert_trust.js @@ -16,7 +16,7 @@ let certList = [ ]; function load_cert(cert_name, trust_string) { - let cert_filename = cert_name + ".der"; + let cert_filename = cert_name + ".pem"; addCertFromFile(certdb, "test_cert_trust/" + cert_filename, trust_string); } diff --git a/security/manager/ssl/tests/unit/test_cert_trust/ca.der b/security/manager/ssl/tests/unit/test_cert_trust/ca.der deleted file mode 100644 index 1609633660e652df2258974481851be491de43cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 782 zcmXqLV&*bvV*Ip#nTe5!iILHOmyJ`a&7AA-4f18*?ZNGY?a8qJf+^ zuc3*7v4Odvg`ts&QIt5Z5r}I7<)SNZVpKvlkdc*vxrvdV0car?QxhX2!~VK2TmF_a z{@7hy7p1={^S9H*jx()l!M;~neoW=t5qJ1wre1C0N0IgJ3Flk?aXagq3t#K|@Z09$ z6kd%Nsv>KWxcr=iTi5l!4_^HL=;q<~$=LbQ>ij784_W3@`}KQl zS$=o%e|V;NR5EjE`cv&4!HW+~W&U97*v5ZGPo{j`LAM|Oc5Am>e;TfRBGJmsa)S$_ z@Yd6(1^)kHEK2J*HNEDF%u1iF`xscZdT;Q~Em9Ae(RyO$nF9gGG`KGb#CTnv5Ip4@ z=eciO3+rxATqpQ1?n92=3zt&WC#|`v4yz|!-ah@}$N42J6MJ%Q8|0lkHud9?>81~^ zZ+*wg#LURRxVY4y*nl4x#AgN;L*jggg=otY8NVuG_+;4Eh3hylhlFk%=P zJS*2mbI)&Qmh{PcGV`C4f{uo~OLzYtncc6CCQ04ovznN`^;e5Ncbjdf^D9xMlaqRH zEL5C&zoJo9{C<@4#8c_dcgQYYxvJhYbh+%alZd5*Pg>=JN4hpx6|gW@tb#RyM?jN($LnG2Tx7A&*fCLvOC_5?fge^Bk7E^Z7B{7 z{oel@yM3Z65BTt(n8|k6Zu{-Vz^q8l_44jQr{4+1{NQ?2srhNn&(G}7b?0b>aIQbx MvD*Jm&B>$d0diC(Jpcdz diff --git a/security/manager/ssl/tests/unit/test_cert_trust/ca.pem.certspec b/security/manager/ssl/tests/unit/test_cert_trust/ca.pem.certspec new file mode 100644 index 000000000000..f35844946f53 --- /dev/null +++ b/security/manager/ssl/tests/unit/test_cert_trust/ca.pem.certspec @@ -0,0 +1,5 @@ +issuer:ca +subject:ca +extension:basicConstraints:cA, +extension:keyUsage:digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyAgreement,keyCertSign,cRLSign +extension:extKeyUsage:serverAuth,clientAuth,emailProtection,codeSigning diff --git a/security/manager/ssl/tests/unit/test_cert_trust/ee.der b/security/manager/ssl/tests/unit/test_cert_trust/ee.der deleted file mode 100644 index 12a62223c554c920655636c8ae65848e571989e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 712 zcmXqLVme~b#JFYwGZP~d6Jv@2FB_*;n@8JsUPeZ4Rt5t;LmmSzHs(+kW*+9uyb=RB zab80c17iboLkmMA6Qd|`ULz3K1j;qwHRLwngs5jqO$C~)glr-sD+6;ABR>OBoQtW6 zk&$8ZGskFd4yFH>4HmX?yoqGzX?PvJZ_na+mE3d7TND4xWGq~mxl-a1zmpc*tVzty zp8tE!?42#Y(|h9?i@SP?EcvYYL+=`5qi${CMU!!GH1%U|0muzvBAC$o%W!A0Y#lR_BSC&e=g zIsD^XtTbin`ZKCR#YyQWyDV25YWv(@^!W0e2YXZgADZ;>(gb4x;T~b5i?eLbeiuwW z!`GIne&6U6tM#|NX&ZOX`6E!`zQVLg#@>SAfo)gq*5{iimncuT`9W>}i9m*B-5WKz z8}qLOORef{*062YAme k|IM}9m)5Gsx}MK+&0K?uO`q2^&t(>n-DLSrv|qRc0P`s!(*OVf diff --git a/security/manager/ssl/tests/unit/test_cert_trust/ee.pem.certspec b/security/manager/ssl/tests/unit/test_cert_trust/ee.pem.certspec new file mode 100644 index 000000000000..aed266202bc8 --- /dev/null +++ b/security/manager/ssl/tests/unit/test_cert_trust/ee.pem.certspec @@ -0,0 +1,2 @@ +issuer:int +subject:ee diff --git a/security/manager/ssl/tests/unit/test_cert_trust/generate.py b/security/manager/ssl/tests/unit/test_cert_trust/generate.py deleted file mode 100755 index 23a3461ad2fd..000000000000 --- a/security/manager/ssl/tests/unit/test_cert_trust/generate.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/python -# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# -# 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 tempfile, os, sys -import random -import pexpect -import subprocess -import shutil - -libpath = os.path.abspath('../psm_common_py') - -sys.path.append(libpath) - -import CertUtils - -srcdir = os.getcwd() -db = tempfile.mkdtemp() - -CA_basic_constraints = "basicConstraints = critical, CA:TRUE\n" -EE_basic_constraints = "basicConstraints = CA:FALSE\n" - -CA_full_ku = ("keyUsage = digitalSignature, nonRepudiation, keyEncipherment, " + - "dataEncipherment, keyAgreement, keyCertSign, cRLSign\n") - -CA_eku = ("extendedKeyUsage = critical, serverAuth, clientAuth, " + - "emailProtection, codeSigning\n") - -authority_key_ident = "authorityKeyIdentifier = keyid, issuer\n" -subject_key_ident = "subjectKeyIdentifier = hash\n" - - - -def generate_certs(): - key_type = 'rsa' - ca_ext = CA_basic_constraints + CA_full_ku + subject_key_ident + CA_eku; - ee_ext_text = (EE_basic_constraints + authority_key_ident) - [ca_key, ca_cert] = CertUtils.generate_cert_generic(db, - srcdir, - 1, - key_type, - 'ca', - ca_ext) - - [int_key, int_cert] = CertUtils.generate_cert_generic(db, - srcdir, - 103, - key_type, - 'int', - ca_ext, - ca_key, - ca_cert) - - #now the ee - CertUtils.generate_cert_generic(db, - srcdir, - 100, - key_type, - 'ee', - ee_ext_text, - int_key, - int_cert) - - - - - -generate_certs() diff --git a/security/manager/ssl/tests/unit/test_cert_trust/int.der b/security/manager/ssl/tests/unit/test_cert_trust/int.der deleted file mode 100644 index 4f8844c6c956adc8e602180dbca2a3a237b2072f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 783 zcmXqLV&*nzV*I>-nTe5!i80-PmyJ`a&7AA-4f18*?ZNGY?a8qJf+^ zuc3*7v4Odvg`ts&QIt5Z5r}I7kjvLN<|+m4Ug5k)Hu5&c)Qk z$jC4ynf;WmSETvYjlV7xOg`Gc-hV%=|BYYFnO`wHnp0jpULse0_S+uod6yK$jy>0S z7o!n*e!2=vZO@rEQD?4|UoV-IvH$s+9e-5sXXY4^rv5m!9mnvHLd9mbIVGzm$K!>dLmW*A8myJc)T3Tqd#1`H9f!q(yQ+ z6OP?)>0LD6nb~tyhJA#{mwm4-wnmH2&)6^YPVA)k+xxv{k#6k!oE~SdyrR`5SJz>n z;S^o$71QAUac|(lQ=#q;E?ewmyMB{pcin=$Y9G5>BQ!kr3S?Y{J>C?6=r1o&%$cJ45SRWK?3|NEWn8QXCMpW z@Ue)oh^X)gv)MUMZEv+avtZ%oxqfq}bn6+IfTUGHnzalx*f_M=7+G1_nHk|MCOC@) z&SFN67+_QbBZiS-PxD`|Tg={iFH|KI-4ypZO%P0bZ_T4<&BFRFh0i0zYHfP^$!kwb z_IoL3&oF=YncMP*p*NRCF26(8W~Jt=FTGY;3#FblSX-^TpvK9vOzqJHy)!i4@A Date: Wed, 3 Jun 2015 15:37:38 -0700 Subject: [PATCH 11/95] bug 1171557 - make test_cert_trust.js certs a bit more realistic r=mgoodwin According to the Baseline Requirements, root certificates MUST NOT have the extendedKeyUsage extension. The extension is optional for intermediates and required for end-entity certificates. This change modifies the test certificates so they're more in line with the BRs. --- security/manager/ssl/tests/unit/test_cert_trust.js | 12 +++++------- .../ssl/tests/unit/test_cert_trust/ca.pem.certspec | 3 +-- .../ssl/tests/unit/test_cert_trust/ee.pem.certspec | 1 + .../ssl/tests/unit/test_cert_trust/int.pem.certspec | 3 +-- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/security/manager/ssl/tests/unit/test_cert_trust.js b/security/manager/ssl/tests/unit/test_cert_trust.js index ea40a55c0999..7a7518e1023e 100644 --- a/security/manager/ssl/tests/unit/test_cert_trust.js +++ b/security/manager/ssl/tests/unit/test_cert_trust.js @@ -65,9 +65,7 @@ function test_ca_distrust(ee_cert, cert_to_modify_trust, isRootCA) { certificateUsageObjectSigner); checkCertErrorGeneric(certdb, ee_cert, SEC_ERROR_CA_CERT_INVALID, certificateUsageVerifyCA); - checkCertErrorGeneric(certdb, ee_cert, - !isRootCA ? SEC_ERROR_UNTRUSTED_ISSUER - : SEC_ERROR_INADEQUATE_CERT_TYPE, + checkCertErrorGeneric(certdb, ee_cert, SEC_ERROR_UNTRUSTED_ISSUER, certificateUsageStatusResponder); // Trust set to T - trusted CA to issue client certs, where client cert is @@ -96,7 +94,9 @@ function test_ca_distrust(ee_cert, cert_to_modify_trust, isRootCA) { certificateUsageObjectSigner); checkCertErrorGeneric(certdb, ee_cert, SEC_ERROR_CA_CERT_INVALID, certificateUsageVerifyCA); - checkCertErrorGeneric(certdb, ee_cert, SEC_ERROR_INADEQUATE_CERT_TYPE, + checkCertErrorGeneric(certdb, ee_cert, + isRootCA ? SEC_ERROR_UNKNOWN_ISSUER + : SEC_ERROR_INADEQUATE_CERT_TYPE, certificateUsageStatusResponder); @@ -118,9 +118,7 @@ function test_ca_distrust(ee_cert, cert_to_modify_trust, isRootCA) { certificateUsageObjectSigner); checkCertErrorGeneric(certdb, ee_cert, SEC_ERROR_CA_CERT_INVALID, certificateUsageVerifyCA); - checkCertErrorGeneric(certdb, ee_cert, - isRootCA ? SEC_ERROR_INADEQUATE_CERT_TYPE - : SEC_ERROR_UNTRUSTED_ISSUER, + checkCertErrorGeneric(certdb, ee_cert, SEC_ERROR_UNTRUSTED_ISSUER, certificateUsageStatusResponder); // Inherited trust SSL diff --git a/security/manager/ssl/tests/unit/test_cert_trust/ca.pem.certspec b/security/manager/ssl/tests/unit/test_cert_trust/ca.pem.certspec index f35844946f53..d809dbd635d4 100644 --- a/security/manager/ssl/tests/unit/test_cert_trust/ca.pem.certspec +++ b/security/manager/ssl/tests/unit/test_cert_trust/ca.pem.certspec @@ -1,5 +1,4 @@ issuer:ca subject:ca extension:basicConstraints:cA, -extension:keyUsage:digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyAgreement,keyCertSign,cRLSign -extension:extKeyUsage:serverAuth,clientAuth,emailProtection,codeSigning +extension:keyUsage:keyCertSign,cRLSign diff --git a/security/manager/ssl/tests/unit/test_cert_trust/ee.pem.certspec b/security/manager/ssl/tests/unit/test_cert_trust/ee.pem.certspec index aed266202bc8..9666c18062c5 100644 --- a/security/manager/ssl/tests/unit/test_cert_trust/ee.pem.certspec +++ b/security/manager/ssl/tests/unit/test_cert_trust/ee.pem.certspec @@ -1,2 +1,3 @@ issuer:int subject:ee +extension:extKeyUsage:serverAuth,clientAuth,emailProtection,codeSigning diff --git a/security/manager/ssl/tests/unit/test_cert_trust/int.pem.certspec b/security/manager/ssl/tests/unit/test_cert_trust/int.pem.certspec index 2ef31208fe4f..a7f6d81419da 100644 --- a/security/manager/ssl/tests/unit/test_cert_trust/int.pem.certspec +++ b/security/manager/ssl/tests/unit/test_cert_trust/int.pem.certspec @@ -1,5 +1,4 @@ issuer:ca subject:int extension:basicConstraints:cA, -extension:keyUsage:digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyAgreement,keyCertSign,cRLSign -extension:extKeyUsage:serverAuth,clientAuth,emailProtection,codeSigning +extension:keyUsage:keyCertSign,cRLSign From 517b46502344f6cda49f3e39c9cb09a250057909 Mon Sep 17 00:00:00 2001 From: JW Wang Date: Mon, 8 Jun 2015 16:51:39 +0800 Subject: [PATCH 12/95] Bug 1172390 - Align stream blocking of decoded stream with play state of MDSM. r=roc. --- dom/media/AudioSink.cpp | 12 +---- dom/media/AudioSink.h | 3 +- dom/media/DecodedStream.cpp | 37 ++++++++++++-- dom/media/DecodedStream.h | 9 ++-- dom/media/MediaDecoderStateMachine.cpp | 69 +++----------------------- dom/media/MediaDecoderStateMachine.h | 7 --- 6 files changed, 45 insertions(+), 92 deletions(-) diff --git a/dom/media/AudioSink.cpp b/dom/media/AudioSink.cpp index 5fe6b692f56a..cf003e3b45e8 100644 --- a/dom/media/AudioSink.cpp +++ b/dom/media/AudioSink.cpp @@ -165,18 +165,10 @@ AudioSink::SetPreservesPitch(bool aPreservesPitch) } void -AudioSink::StartPlayback() +AudioSink::SetPlaying(bool aPlaying) { AssertCurrentThreadInMonitor(); - mPlaying = true; - GetReentrantMonitor().NotifyAll(); -} - -void -AudioSink::StopPlayback() -{ - AssertCurrentThreadInMonitor(); - mPlaying = false; + mPlaying = aPlaying; GetReentrantMonitor().NotifyAll(); } diff --git a/dom/media/AudioSink.h b/dom/media/AudioSink.h index 3b8877c0a75c..aa8ef8d9b9b9 100644 --- a/dom/media/AudioSink.h +++ b/dom/media/AudioSink.h @@ -42,8 +42,7 @@ public: void SetPlaybackRate(double aPlaybackRate); void SetPreservesPitch(bool aPreservesPitch); - void StartPlayback(); - void StopPlayback(); + void SetPlaying(bool aPlaying); private: ~AudioSink() {} diff --git a/dom/media/DecodedStream.cpp b/dom/media/DecodedStream.cpp index ff728cb0a222..e7c984862186 100644 --- a/dom/media/DecodedStream.cpp +++ b/dom/media/DecodedStream.cpp @@ -69,6 +69,19 @@ private: bool mStreamFinishedOnMainThread; }; +static void +UpdateStreamBlocking(MediaStream* aStream, bool aBlocking) +{ + int32_t delta = aBlocking ? 1 : -1; + if (NS_IsMainThread()) { + aStream->ChangeExplicitBlockerCount(delta); + } else { + nsCOMPtr r = NS_NewRunnableMethodWithArg( + aStream, &MediaStream::ChangeExplicitBlockerCount, delta); + AbstractThread::MainThread()->Dispatch(r.forget()); + } +} + DecodedStreamData::DecodedStreamData(SourceMediaStream* aStream) : mAudioFramesWritten(0) , mNextVideoTime(-1) @@ -78,14 +91,13 @@ DecodedStreamData::DecodedStreamData(SourceMediaStream* aStream) , mHaveSentFinishAudio(false) , mHaveSentFinishVideo(false) , mStream(aStream) - , mHaveBlockedForPlayState(false) - , mHaveBlockedForStateMachineNotPlaying(false) + , mPlaying(false) , mEOSVideoCompensation(false) { mListener = new DecodedStreamGraphListener(mStream); mStream->AddListener(mListener); - // Block the stream until the initialization is done. - mStream->ChangeExplicitBlockerCount(1); + // Block the stream as mPlaying is initially false. + UpdateStreamBlocking(mStream, true); } DecodedStreamData::~DecodedStreamData() @@ -106,6 +118,15 @@ DecodedStreamData::GetPosition() const return mListener->GetLastOutputTime(); } +void +DecodedStreamData::SetPlaying(bool aPlaying) +{ + if (mPlaying != aPlaying) { + mPlaying = aPlaying; + UpdateStreamBlocking(mStream, !mPlaying); + } +} + class OutputStreamListener : public MediaStreamListener { typedef MediaStreamListener::MediaStreamGraphEvent MediaStreamGraphEvent; public: @@ -290,4 +311,12 @@ DecodedStream::Connect(ProcessedMediaStream* aStream, bool aFinishWhenEnded) } } +void +DecodedStream::SetPlaying(bool aPlaying) +{ + GetReentrantMonitor().AssertCurrentThreadIn(); + MOZ_ASSERT(mData); + mData->SetPlaying(aPlaying); +} + } // namespace mozilla diff --git a/dom/media/DecodedStream.h b/dom/media/DecodedStream.h index 9e655cd4b060..748576c9826a 100644 --- a/dom/media/DecodedStream.h +++ b/dom/media/DecodedStream.h @@ -41,6 +41,7 @@ public: ~DecodedStreamData(); bool IsFinished() const; int64_t GetPosition() const; + void SetPlaying(bool aPlaying); /* The following group of fields are protected by the decoder's monitor * and can be read or written on any thread. @@ -66,12 +67,7 @@ public: // The decoder is responsible for calling Destroy() on this stream. const nsRefPtr mStream; nsRefPtr mListener; - // True when we've explicitly blocked this stream because we're - // not in PLAY_STATE_PLAYING. Used on the main thread only. - bool mHaveBlockedForPlayState; - // We also have an explicit blocker on the stream when - // mDecoderStateMachine is non-null and MediaDecoderStateMachine is false. - bool mHaveBlockedForStateMachineNotPlaying; + bool mPlaying; // True if we need to send a compensation video frame to ensure the // StreamTime going forward. bool mEOSVideoCompensation; @@ -96,6 +92,7 @@ public: nsTArray& OutputStreams(); ReentrantMonitor& GetReentrantMonitor() const; void Connect(ProcessedMediaStream* aStream, bool aFinishWhenEnded); + void SetPlaying(bool aPlaying); private: void Connect(OutputStreamData* aStream); diff --git a/dom/media/MediaDecoderStateMachine.cpp b/dom/media/MediaDecoderStateMachine.cpp index 2eb316d0c86a..e4dfbeaa29d4 100644 --- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -314,8 +314,6 @@ MediaDecoderStateMachine::InitializationTask() mWatchManager.Watch(mObservedDuration, &MediaDecoderStateMachine::RecomputeDuration); mWatchManager.Watch(mPlayState, &MediaDecoderStateMachine::PlayStateChanged); mWatchManager.Watch(mLogicallySeeking, &MediaDecoderStateMachine::LogicallySeekingChanged); - mWatchManager.Watch(mPlayState, &MediaDecoderStateMachine::UpdateStreamBlockingForPlayState); - mWatchManager.Watch(mLogicallySeeking, &MediaDecoderStateMachine::UpdateStreamBlockingForPlayState); } bool MediaDecoderStateMachine::HasFutureAudio() @@ -430,19 +428,6 @@ static bool ZeroDurationAtLastChunk(VideoSegment& aInput) return lastVideoStratTime == aInput.GetDuration(); } -static void -UpdateStreamBlocking(MediaStream* aStream, bool aBlocking) -{ - int32_t delta = aBlocking ? 1 : -1; - if (NS_IsMainThread()) { - aStream->ChangeExplicitBlockerCount(delta); - } else { - nsCOMPtr r = NS_NewRunnableMethodWithArg( - aStream, &MediaStream::ChangeExplicitBlockerCount, delta); - AbstractThread::MainThread()->Dispatch(r.forget()); - } -} - void MediaDecoderStateMachine::SendStreamData() { MOZ_ASSERT(OnTaskQueue()); @@ -481,12 +466,6 @@ void MediaDecoderStateMachine::SendStreamData() } mediaStream->FinishAddTracks(); stream->mStreamInitialized = true; - - // Make sure stream blocking is updated before sending stream data so we - // don't 'leak' data when the stream is supposed to be blocked. - UpdateStreamBlockingForPlayState(); - UpdateStreamBlockingForStateMachinePlaying(); - UpdateStreamBlocking(mediaStream, false); } if (mInfo.HasAudio()) { @@ -1295,7 +1274,6 @@ void MediaDecoderStateMachine::StopPlayback() // so it can pause audio playback. mDecoder->GetReentrantMonitor().NotifyAll(); NS_ASSERTION(!IsPlaying(), "Should report not playing at end of StopPlayback()"); - UpdateStreamBlockingForStateMachinePlaying(); DispatchDecodeTasksIfNeeded(); } @@ -1333,7 +1311,6 @@ void MediaDecoderStateMachine::MaybeStartPlayback() NS_ENSURE_SUCCESS_VOID(rv); mDecoder->GetReentrantMonitor().NotifyAll(); - UpdateStreamBlockingForStateMachinePlaying(); DispatchDecodeTasksIfNeeded(); } @@ -3296,13 +3273,11 @@ void MediaDecoderStateMachine::SetPlayStartTime(const TimeStamp& aTimeStamp) { AssertCurrentThreadInMonitor(); mPlayStartTime = aTimeStamp; - if (!mAudioSink) { - return; - } - if (!mPlayStartTime.IsNull()) { - mAudioSink->StartPlayback(); - } else { - mAudioSink->StopPlayback(); + + if (mAudioSink) { + mAudioSink->SetPlaying(!mPlayStartTime.IsNull()); + } else if (mAudioCaptured) { + mDecodedStream.SetPlaying(!mPlayStartTime.IsNull()); } } @@ -3526,44 +3501,12 @@ void MediaDecoderStateMachine::AddOutputStream(ProcessedMediaStream* aStream, DispatchAudioCaptured(); } -void MediaDecoderStateMachine::UpdateStreamBlockingForPlayState() -{ - ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); - - auto stream = GetDecodedStream(); - if (!stream) { - return; - } - - bool blocking = mPlayState != MediaDecoder::PLAY_STATE_PLAYING || - mLogicallySeeking; - if (blocking != stream->mHaveBlockedForPlayState) { - stream->mHaveBlockedForPlayState = blocking; - UpdateStreamBlocking(stream->mStream, blocking); - } -} - -void MediaDecoderStateMachine::UpdateStreamBlockingForStateMachinePlaying() -{ - AssertCurrentThreadInMonitor(); - - auto stream = GetDecodedStream(); - if (!stream) { - return; - } - - bool blocking = !IsPlaying(); - if (blocking != stream->mHaveBlockedForStateMachineNotPlaying) { - stream->mHaveBlockedForStateMachineNotPlaying = blocking; - UpdateStreamBlocking(stream->mStream, blocking); - } -} - void MediaDecoderStateMachine::RecreateDecodedStream(MediaStreamGraph* aGraph) { MOZ_ASSERT(NS_IsMainThread()); ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); mDecodedStream.RecreateData(aGraph); + mDecodedStream.SetPlaying(IsPlaying()); } } // namespace mozilla diff --git a/dom/media/MediaDecoderStateMachine.h b/dom/media/MediaDecoderStateMachine.h index debe82a73d6b..fc37b344c13b 100644 --- a/dom/media/MediaDecoderStateMachine.h +++ b/dom/media/MediaDecoderStateMachine.h @@ -162,13 +162,6 @@ private: void DispatchAudioCaptured(); - // Update blocking state of mDecodedStream when mPlayState or - // mLogicallySeeking change. Decoder monitor must be held. - void UpdateStreamBlockingForPlayState(); - - // Call this IsPlaying() changes. Decoder monitor must be held. - void UpdateStreamBlockingForStateMachinePlaying(); - // Recreates mDecodedStream. Call this to create mDecodedStream at first, // and when seeking, to ensure a new stream is set up with fresh buffers. // Decoder monitor must be held. From d67edd7f93de65a20cd1c2b2922fa23f436db7f8 Mon Sep 17 00:00:00 2001 From: David Keeler Date: Mon, 1 Jun 2015 13:55:23 -0700 Subject: [PATCH 13/95] bug 1170303 - treat malformed name information in certificates as a domain name mismatch r=Cykesiopka --- security/certverifier/CertVerifier.cpp | 7 ++++- .../manager/ssl/SSLServerCertVerification.cpp | 4 ++- .../ssl/tests/unit/test_cert_overrides.js | 24 +++++++++++++++--- .../manager/ssl/tests/unit/tlsserver/cert9.db | Bin 327680 -> 327680 bytes .../unit/tlsserver/cmd/BadCertServer.cpp | 3 +++ .../tests/unit/tlsserver/generate_certs.sh | 9 +++++-- .../manager/ssl/tests/unit/tlsserver/key4.db | Bin 524288 -> 524288 bytes 7 files changed, 40 insertions(+), 7 deletions(-) diff --git a/security/certverifier/CertVerifier.cpp b/security/certverifier/CertVerifier.cpp index 4bae10293b03..96654a210ae4 100644 --- a/security/certverifier/CertVerifier.cpp +++ b/security/certverifier/CertVerifier.cpp @@ -488,7 +488,12 @@ CertVerifier::VerifySSLServerCert(CERTCertificate* peerCert, } result = CheckCertHostname(peerCertInput, hostnameInput); if (result != Success) { - PR_SetError(MapResultToPRErrorCode(result), 0); + // Treat malformed name information as a domain mismatch. + if (result == Result::ERROR_BAD_DER) { + PR_SetError(SSL_ERROR_BAD_CERT_DOMAIN, 0); + } else { + PR_SetError(MapResultToPRErrorCode(result), 0); + } return SECFailure; } diff --git a/security/manager/ssl/SSLServerCertVerification.cpp b/security/manager/ssl/SSLServerCertVerification.cpp index 05072b4c98b9..406f4de254e9 100644 --- a/security/manager/ssl/SSLServerCertVerification.cpp +++ b/security/manager/ssl/SSLServerCertVerification.cpp @@ -433,7 +433,9 @@ DetermineCertOverrideErrors(CERTCertificate* cert, const char* hostName, return SECFailure; } result = CheckCertHostname(certInput, hostnameInput); - if (result == Result::ERROR_BAD_CERT_DOMAIN) { + // Treat malformed name information as a domain mismatch. + if (result == Result::ERROR_BAD_DER || + result == Result::ERROR_BAD_CERT_DOMAIN) { collectedErrors |= nsICertOverrideService::ERROR_MISMATCH; errorCodeMismatch = SSL_ERROR_BAD_CERT_DOMAIN; } else if (result != Success) { diff --git a/security/manager/ssl/tests/unit/test_cert_overrides.js b/security/manager/ssl/tests/unit/test_cert_overrides.js index 2f888635db4f..e60c66819658 100644 --- a/security/manager/ssl/tests/unit/test_cert_overrides.js +++ b/security/manager/ssl/tests/unit/test_cert_overrides.js @@ -47,7 +47,7 @@ function check_telemetry() { "Actual and expected SEC_ERROR_INADEQUATE_KEY_USAGE counts should match"); equal(histogram.counts[ 8], 2, "Actual and expected SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED counts should match"); - equal(histogram.counts[ 9], 6, + equal(histogram.counts[ 9], 10, "Actual and expected SSL_ERROR_BAD_CERT_DOMAIN counts should match"); equal(histogram.counts[10], 5, "Actual and expected SEC_ERROR_EXPIRED_CERTIFICATE counts should match"); @@ -72,7 +72,7 @@ function check_telemetry() { "Actual and expected unchecked key size counts should match"); equal(keySizeHistogram.counts[1], 0, "Actual and expected successful verifications of 2048-bit keys should match"); - equal(keySizeHistogram.counts[2], 4, + equal(keySizeHistogram.counts[2], 12, "Actual and expected successful verifications of 1024-bit keys should match"); equal(keySizeHistogram.counts[3], 48, "Actual and expected key size verification failures should match"); @@ -129,9 +129,16 @@ function add_simple_tests() { add_cert_override_test("md5signature.example.com", Ci.nsICertOverrideService.ERROR_UNTRUSTED, SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED); + // This has name information in the subject alternative names extension, + // but not the subject common name. add_cert_override_test("mismatch.example.com", Ci.nsICertOverrideService.ERROR_MISMATCH, SSL_ERROR_BAD_CERT_DOMAIN); + // This has name information in the subject common name but not the subject + // alternative names extension. + add_cert_override_test("mismatch-CN.example.com", + Ci.nsICertOverrideService.ERROR_MISMATCH, + SSL_ERROR_BAD_CERT_DOMAIN); // A Microsoft IIS utility generates self-signed certificates with // properties similar to the one this "host" will present (see @@ -152,7 +159,8 @@ function add_simple_tests() { setCertTrust(rootCert, ",,"); run_next_test(); }); - add_non_overridable_test("badSubjectAltNames.example.com", SEC_ERROR_BAD_DER); + add_non_overridable_test("nsCertTypeCritical.example.com", + SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION); add_test(function() { let rootCert = constructCertFromFile("tlsserver/test-ca.der"); setCertTrust(rootCert, "CTu,,"); @@ -205,6 +213,16 @@ function add_simple_tests() { // small and terminates the connection. The error is not overridable. add_non_overridable_test("inadequate-key-size-ee.example.com", SSL_ERROR_WEAK_SERVER_CERT_KEY); + + add_cert_override_test("ipAddressAsDNSNameInSAN.example.com", + Ci.nsICertOverrideService.ERROR_MISMATCH, + SSL_ERROR_BAD_CERT_DOMAIN); + add_cert_override_test("noValidNames.example.com", + Ci.nsICertOverrideService.ERROR_MISMATCH, + SSL_ERROR_BAD_CERT_DOMAIN); + add_cert_override_test("badSubjectAltNames.example.com", + Ci.nsICertOverrideService.ERROR_MISMATCH, + SSL_ERROR_BAD_CERT_DOMAIN); } function add_combo_tests() { diff --git a/security/manager/ssl/tests/unit/tlsserver/cert9.db b/security/manager/ssl/tests/unit/tlsserver/cert9.db index 2403e89349b1e557edc6e6fd77035fda820b6fa6..35e3e1e6a7abe5b03c9bc18d81b95a389d32e514 100644 GIT binary patch delta 6737 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 diff --git a/security/manager/ssl/tests/unit/tlsserver/cmd/BadCertServer.cpp b/security/manager/ssl/tests/unit/tlsserver/cmd/BadCertServer.cpp index 6d1fa8224bde..b980e443bb2c 100644 --- a/security/manager/ssl/tests/unit/tlsserver/cmd/BadCertServer.cpp +++ b/security/manager/ssl/tests/unit/tlsserver/cmd/BadCertServer.cpp @@ -33,6 +33,7 @@ const BadCertHost sBadCertHosts[] = { "selfsigned.example.com", "selfsigned" }, { "unknownissuer.example.com", "unknownissuer" }, { "mismatch.example.com", "mismatch" }, + { "mismatch-CN.example.com", "mismatchCN" }, { "expiredissuer.example.com", "expiredissuer" }, { "notyetvalidissuer.example.com", "notYetValidIssuer" }, { "before-epoch-issuer.example.com", "beforeEpochIssuer" }, @@ -71,6 +72,8 @@ const BadCertHost sBadCertHosts[] = { "end-entity-issued-by-non-CA.example.com", "eeIssuedByNonCA" }, { "inadequate-key-size-ee.example.com", "inadequateKeySizeEE" }, { "badSubjectAltNames.example.com", "badSubjectAltNames" }, + { "ipAddressAsDNSNameInSAN.example.com", "ipAddressAsDNSNameInSAN" }, + { "noValidNames.example.com", "noValidNames" }, { nullptr, nullptr } }; diff --git a/security/manager/ssl/tests/unit/tlsserver/generate_certs.sh b/security/manager/ssl/tests/unit/tlsserver/generate_certs.sh index 80efdf102fbd..a26487411959 100755 --- a/security/manager/ssl/tests/unit/tlsserver/generate_certs.sh +++ b/security/manager/ssl/tests/unit/tlsserver/generate_certs.sh @@ -178,6 +178,8 @@ function make_EE { SUBJECT_ALT_NAME="${4}" EXTRA_ARGS="${5} ${6}" + [ -z "$SUBJECT_ALT_NAME" ] && SUBJECT_ALT_NAME_PART="" || SUBJECT_ALT_NAME_PART="-8 $SUBJECT_ALT_NAME" + cert_already_exists $NICKNAME if [ $ALREADY_EXISTS -eq 1 ]; then echo "cert \"$NICKNAME\" already exists - not regenerating it (use --clobber to force regeneration)" @@ -187,7 +189,7 @@ function make_EE { echo -e "$CERT_RESPONSES" | $RUN_MOZILLA $CERTUTIL -d $DB_ARGUMENT -S \ -n $NICKNAME \ -s "$SUBJECT" \ - -8 $SUBJECT_ALT_NAME \ + $SUBJECT_ALT_NAME_PART \ -c $CA \ -t ",," \ -m $SERIALNO \ @@ -276,7 +278,10 @@ make_EE ocspEEWithIntermediate 'CN=Test End-entity with Intermediate' testINT "l make_EE expired 'CN=Expired Test End-entity' testCA "expired.example.com" "-w -400" export_cert expired expired-ee.der make_EE notYetValid 'CN=Not Yet Valid Test End-entity' testCA "notyetvalid.example.com" "-w 400" -make_EE mismatch 'CN=Mismatch Test End-entity' testCA "doesntmatch.example.com" +make_EE mismatch 'CN=Mismatch Test End-entity' testCA "doesntmatch.example.com,*.alsodoesntmatch.example.com" +make_EE mismatchCN 'CN=doesntmatch.example.com' testCA +make_EE ipAddressAsDNSNameInSAN 'CN=127.0.0.1' testCA "127.0.0.1" +make_EE noValidNames 'CN=End-entity with no valid names' testCA make_EE selfsigned 'CN=Self-signed Test End-entity' testCA "selfsigned.example.com" "-x" # If the certificate 'CN=Test Intermediate' isn't loaded into memory, # this certificate will have an unknown issuer. diff --git a/security/manager/ssl/tests/unit/tlsserver/key4.db b/security/manager/ssl/tests/unit/tlsserver/key4.db index 8b4c6c1c0489d80fbc3447359ec78f67ff5def3d..09ed98f8ff8f9b216ee9675cd4540dfba5704c85 100644 GIT binary patch delta 23409 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 LP&y5(LHGXvs`ezF delta 267 zcmZo@P-tjSm>|ulIZ?)$Rg*#Y8OO$y1^+p$Yu_={Mb!mvm13M)J6WN@cl*0qMlmL4 z>$+Rh*&7(kHw!kz)NQ}@k5P*eD5g1;oe3ngx^}x}9n)=WLTuJmb__K}Q-zp=gzC@N z@m4q2x72>AeqI$`eXeHO)*5EvN}x4+x7$@QA8Tdq(myekoke}?8Wt{=?Uz_sQWQ5U zH0W@#$TK@KO}}`PU9$bDJ_``DZhxxJCVxSQ-S;s=wQcdb9Ql+9v5cWbzK?;fIqS>Z v&tpA(V=;T(_7p$%1%}KHVO>Divo``InZj5am0G!`H{4*C+rH)+dx$0ggLq Date: Tue, 9 Jun 2015 15:12:21 -0700 Subject: [PATCH 14/95] Backed out changeset 1be05715932f (bug 1161166) --- ipc/chromium/src/chrome/common/mach_ipc_mac.h | 3 - .../src/chrome/common/mach_ipc_mac.mm | 32 +- ipc/glue/GeckoChildProcessHost.cpp | 33 +- ipc/glue/SharedMemoryBasic.h | 2 - ipc/glue/SharedMemoryBasic_mach.cpp | 692 ------------------ ipc/glue/SharedMemoryBasic_mach.h | 84 --- ipc/glue/moz.build | 5 - toolkit/xre/nsEmbedFunctions.cpp | 32 - 8 files changed, 3 insertions(+), 880 deletions(-) delete mode 100644 ipc/glue/SharedMemoryBasic_mach.cpp delete mode 100644 ipc/glue/SharedMemoryBasic_mach.h diff --git a/ipc/chromium/src/chrome/common/mach_ipc_mac.h b/ipc/chromium/src/chrome/common/mach_ipc_mac.h index 1d4de5f99591..de9d8843c3b0 100644 --- a/ipc/chromium/src/chrome/common/mach_ipc_mac.h +++ b/ipc/chromium/src/chrome/common/mach_ipc_mac.h @@ -274,9 +274,6 @@ class ReceivePort { kern_return_t WaitForMessage(MachReceiveMessage *out_message, mach_msg_timeout_t timeout); - kern_return_t SendMessageToSelf(MachSendMessage& msg, - mach_msg_timeout_t timeout); - // The underlying mach port that we wrap mach_port_t GetPort() const { return port_; } diff --git a/ipc/chromium/src/chrome/common/mach_ipc_mac.mm b/ipc/chromium/src/chrome/common/mach_ipc_mac.mm index aa18130943bf..8f1250b80408 100644 --- a/ipc/chromium/src/chrome/common/mach_ipc_mac.mm +++ b/ipc/chromium/src/chrome/common/mach_ipc_mac.mm @@ -266,7 +266,7 @@ kern_return_t ReceivePort::WaitForMessage(MachReceiveMessage *out_message, out_message->Head()->msgh_id = 0; kern_return_t result = mach_msg(out_message->Head(), - MACH_RCV_MSG | (timeout == MACH_MSG_TIMEOUT_NONE ? 0 : MACH_RCV_TIMEOUT), + MACH_RCV_MSG | MACH_RCV_TIMEOUT, 0, out_message->MaxSize(), port_, @@ -276,34 +276,6 @@ kern_return_t ReceivePort::WaitForMessage(MachReceiveMessage *out_message, return result; } -//============================================================================== -// send a message to this port -kern_return_t ReceivePort::SendMessageToSelf(MachSendMessage& message, mach_msg_timeout_t timeout) { - if (message.Head()->msgh_size == 0) { - NOTREACHED(); - return KERN_INVALID_VALUE; // just for safety -- never should occur - }; - - if (init_result_ != KERN_SUCCESS) - return init_result_; - - message.Head()->msgh_remote_port = port_; - message.Head()->msgh_bits - = MACH_MSGH_BITS (MACH_MSG_TYPE_MAKE_SEND, - MACH_MSG_TYPE_MAKE_SEND_ONCE); - kern_return_t result = mach_msg(message.Head(), - MACH_SEND_MSG | (timeout == MACH_MSG_TIMEOUT_NONE ? 0 : MACH_SEND_TIMEOUT), - message.Head()->msgh_size, - 0, - MACH_PORT_NULL, - timeout, // timeout in ms - MACH_PORT_NULL); - - return result; - -} - - #pragma mark - //============================================================================== @@ -340,7 +312,7 @@ kern_return_t MachPortSender::SendMessage(MachSendMessage &message, message.Head()->msgh_remote_port = send_port_; kern_return_t result = mach_msg(message.Head(), - MACH_SEND_MSG | (timeout == MACH_MSG_TIMEOUT_NONE ? 0 : MACH_SEND_TIMEOUT), + MACH_SEND_MSG | MACH_SEND_TIMEOUT, message.Head()->msgh_size, 0, MACH_PORT_NULL, diff --git a/ipc/glue/GeckoChildProcessHost.cpp b/ipc/glue/GeckoChildProcessHost.cpp index 528b47069089..f37616bbdf9b 100644 --- a/ipc/glue/GeckoChildProcessHost.cpp +++ b/ipc/glue/GeckoChildProcessHost.cpp @@ -14,7 +14,6 @@ #include "chrome/common/mach_ipc_mac.h" #include "base/rand_util.h" #include "nsILocalFileMac.h" -#include "SharedMemoryBasic.h" #endif #include "MainThreadUtils.h" @@ -120,16 +119,12 @@ GeckoChildProcessHost::~GeckoChildProcessHost() MOZ_COUNT_DTOR(GeckoChildProcessHost); - if (mChildProcessHandle > 0) { -#if defined(MOZ_WIDGET_COCOA) - SharedMemoryBasic::CleanupForPid(mChildProcessHandle); -#endif + if (mChildProcessHandle > 0) ProcessWatcher::EnsureProcessTerminated(mChildProcessHandle #if defined(NS_BUILD_REFCNT_LOGGING) , false // don't "force" #endif ); - } #if defined(MOZ_WIDGET_COCOA) if (mChildTask != MACH_PORT_NULL) @@ -788,44 +783,18 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector& aExt } MachPortSender parent_sender(child_message.GetTranslatedPort(1)); - if (child_message.GetTranslatedPort(2) == MACH_PORT_NULL) { - CHROMIUM_LOG(ERROR) << "parent GetTranslatedPort(2) failed."; - } - MachPortSender* parent_recv_port_memory_ack = new MachPortSender(child_message.GetTranslatedPort(2)); - - if (child_message.GetTranslatedPort(3) == MACH_PORT_NULL) { - CHROMIUM_LOG(ERROR) << "parent GetTranslatedPort(3) failed."; - } - MachPortSender* parent_send_port_memory = new MachPortSender(child_message.GetTranslatedPort(3)); - MachSendMessage parent_message(/* id= */0); if (!parent_message.AddDescriptor(MachMsgPortDescriptor(bootstrap_port))) { CHROMIUM_LOG(ERROR) << "parent AddDescriptor(" << bootstrap_port << ") failed."; return false; } - ReceivePort* parent_recv_port_memory = new ReceivePort(); - if (!parent_message.AddDescriptor(MachMsgPortDescriptor(parent_recv_port_memory->GetPort()))) { - CHROMIUM_LOG(ERROR) << "parent AddDescriptor(" << parent_recv_port_memory->GetPort() << ") failed."; - return false; - } - - ReceivePort* parent_send_port_memory_ack = new ReceivePort(); - if (!parent_message.AddDescriptor(MachMsgPortDescriptor(parent_send_port_memory_ack->GetPort()))) { - CHROMIUM_LOG(ERROR) << "parent AddDescriptor(" << parent_send_port_memory_ack->GetPort() << ") failed."; - return false; - } - err = parent_sender.SendMessage(parent_message, kTimeoutMs); if (err != KERN_SUCCESS) { std::string errString = StringPrintf("0x%x %s", err, mach_error_string(err)); CHROMIUM_LOG(ERROR) << "parent SendMessage() failed: " << errString; return false; } - - SharedMemoryBasic::SetupMachMemory(process, parent_recv_port_memory, parent_recv_port_memory_ack, - parent_send_port_memory, parent_send_port_memory_ack, false); - #endif //-------------------------------------------------- diff --git a/ipc/glue/SharedMemoryBasic.h b/ipc/glue/SharedMemoryBasic.h index 223e735b34da..d1697a0bb239 100644 --- a/ipc/glue/SharedMemoryBasic.h +++ b/ipc/glue/SharedMemoryBasic.h @@ -10,8 +10,6 @@ #ifdef ANDROID # include "mozilla/ipc/SharedMemoryBasic_android.h" -#elif defined(XP_MACOSX) -# include "mozilla/ipc/SharedMemoryBasic_mach.h" #else # include "mozilla/ipc/SharedMemoryBasic_chromium.h" #endif diff --git a/ipc/glue/SharedMemoryBasic_mach.cpp b/ipc/glue/SharedMemoryBasic_mach.cpp deleted file mode 100644 index ad382baf3e45..000000000000 --- a/ipc/glue/SharedMemoryBasic_mach.cpp +++ /dev/null @@ -1,692 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: sw=2 ts=8 et : - */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include - -#include -#include -#include -#include "SharedMemoryBasic.h" -#include "chrome/common/mach_ipc_mac.h" - -#include "mozilla/Services.h" -#include "mozilla/StaticMutex.h" -#include "nsCOMPtr.h" -#include "nsIObserver.h" -#include "nsIObserverService.h" -#include "nsThreadUtils.h" -#include "nsXPCOMPrivate.h" - -#ifdef DEBUG -#define LOG_ERROR(str, args...) \ - PR_BEGIN_MACRO \ - char *msg = PR_smprintf(str, ## args); \ - NS_WARNING(msg); \ - PR_smprintf_free(msg); \ - PR_END_MACRO -#else -#define LOG_ERROR(str, args...) do { /* nothing */ } while(0) -#endif - -#define CHECK_MACH_ERROR(kr, msg) \ - PR_BEGIN_MACRO \ - if (kr != KERN_SUCCESS) { \ - LOG_ERROR("%s %s (%x)\n", msg, mach_error_string(kr), kr); \ - return false; \ - } \ - PR_END_MACRO - -/* - * This code is responsible for sharing memory between processes. Memory can be - * shared between parent and child or between two children. Each memory region is - * referenced via a Mach port. Mach ports are also used for messaging when - * sharing a memory region. - * - * When the parent starts a child, it starts a thread whose only purpose is to - * communicate with the child about shared memory. Once the child has started, - * it starts a similar thread for communicating with the parent. Each side can - * communicate with the thread on the other side via Mach ports. When either - * side wants to share memory with the other, it sends a Mach message to the - * other side. Attached to the message is the port that references the shared - * memory region. When the other side receives the message, it automatically - * gets access to the region. It sends a reply (also via a Mach port) so that - * the originating side can continue. - * - * The two sides communicate using four ports. Two ports are used when the - * parent shares memory with the child. The other two are used when the child - * shares memory with the parent. One of these two ports is used for sending the - * "share" message and the other is used for the reply. - * - * If a child wants to share memory with another child, it sends a "GetPorts" - * message to the parent. The parent forwards this GetPorts message to the - * target child. The message includes some ports so that the children can talk - * directly. Both children start up a thread to communicate with the other child, - * similar to the way parent and child communicate. In the future, when these - * two children want to communicate, they re-use the channels that were created. - * - * When a child shuts down, the parent notifies all other children. Those - * children then have the opportunity to shut down any threads they might have - * been using to communicate directly with that child. - */ - -namespace mozilla { -namespace ipc { - -struct MemoryPorts { - MachPortSender* mSender; - ReceivePort* mReceiver; - - MemoryPorts() {} - MemoryPorts(MachPortSender* sender, ReceivePort* receiver) - : mSender(sender), mReceiver(receiver) {} -}; - -// Protects gMemoryCommPorts and gThreads. -static StaticMutex gMutex; - -static std::map gMemoryCommPorts; - -enum { - kGetPortsMsg = 1, - kSharePortsMsg, - kReturnIdMsg, - kReturnPortsMsg, - kShutdownMsg, - kCleanupMsg, -}; - -const int kTimeout = 1000; - -pid_t gParentPid = 0; - -struct PIDPair { - pid_t mRequester; - pid_t mRequested; - - PIDPair(pid_t requester, pid_t requested) - : mRequester(requester), mRequested(requested) {} -}; - -struct ListeningThread { - pthread_t mThread; - MemoryPorts* mPorts; - - ListeningThread() {} - ListeningThread(pthread_t thread, MemoryPorts* ports) - : mThread(thread), mPorts(ports) {} -}; - -std::map gThreads; - -static void * -PortServerThread(void *argument); - -namespace { - -class ShutdownObserver final : public nsIObserver -{ - ~ShutdownObserver() {} - - static bool sInitialized; - -public: - NS_DECL_THREADSAFE_ISUPPORTS - NS_DECL_NSIOBSERVER - - void InitializeOnMainThread() - { - if (sInitialized) { - return; - } - - nsCOMPtr observerService = - mozilla::services::GetObserverService(); - if (!observerService) { - return; - } - nsCOMPtr obs = new ShutdownObserver(); - observerService->AddObserver(obs, "xpcom-shutdown-threads", false); - sInitialized = true; - } - - static void Initialize(bool onMainThread) - { - if (sInitialized) { - return; - } - - nsRefPtr obs = new ShutdownObserver(); - if (onMainThread) { - obs->InitializeOnMainThread(); - } else { - NS_DispatchToMainThread(NS_NewRunnableMethod(obs, &ShutdownObserver::InitializeOnMainThread)); - } - } -}; - -bool ShutdownObserver::sInitialized = false; - -} // namespace - -NS_IMPL_ISUPPORTS(ShutdownObserver, nsIObserver) - -NS_IMETHODIMP -ShutdownObserver::Observe(nsISupports* subject, - const char* topic, - const char16_t* data) -{ - MOZ_ASSERT(strcmp(topic, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID) == 0); - - StaticMutexAutoLock smal(gMutex); - - for (auto it = gThreads.begin(); it != gThreads.end(); ++it) { - MachSendMessage shutdownMsg(kShutdownMsg); - it->second.mPorts->mReceiver->SendMessageToSelf(shutdownMsg, kTimeout); - pthread_join(it->second.mThread, nullptr); - } - gThreads.clear(); - - for (auto it = gMemoryCommPorts.begin(); it != gMemoryCommPorts.end(); ++it) { - delete it->second.mSender; - delete it->second.mReceiver; - } - gMemoryCommPorts.clear(); - - nsCOMPtr observerService = - mozilla::services::GetObserverService(); - if (observerService) { - observerService->RemoveObserver(this, "xpcom-shutdown-threads"); - } - - return NS_OK; -} - -static void -SetupMachMemory(pid_t pid, - ReceivePort* listen_port, - MachPortSender* listen_port_ack, - MachPortSender* send_port, - ReceivePort* send_port_ack, - bool pidIsParent) -{ - if (pidIsParent) { - gParentPid = pid; - } - MemoryPorts* listen_ports = new MemoryPorts(listen_port_ack, listen_port); - pthread_t thread; - int err = pthread_create(&thread, nullptr, PortServerThread, listen_ports); - if (err) { - LOG_ERROR("pthread_create failed with %x\n", err); - return; - } - - gMutex.AssertCurrentThreadOwns(); - gThreads[pid] = ListeningThread(thread, listen_ports); - gMemoryCommPorts[pid] = MemoryPorts(send_port, send_port_ack); -} - -// Send two communication ports to another process along with the pid of the process that is -// listening on them. -bool -SendPortsMessage(MachPortSender* sender, - mach_port_t ports_in_receiver, - mach_port_t ports_out_receiver, - PIDPair pid_pair) -{ - MachSendMessage getPortsMsg(kGetPortsMsg); - if (!getPortsMsg.AddDescriptor(MachMsgPortDescriptor(ports_in_receiver))) { - LOG_ERROR("Adding descriptor to message failed"); - return false; - } - if (!getPortsMsg.AddDescriptor(MachMsgPortDescriptor(ports_out_receiver))) { - LOG_ERROR("Adding descriptor to message failed"); - return false; - } - - getPortsMsg.SetData(&pid_pair, sizeof(PIDPair)); - kern_return_t err = sender->SendMessage(getPortsMsg, kTimeout); - if (KERN_SUCCESS != err) { - LOG_ERROR("Error sending get ports message %s (%x)\n", mach_error_string(err), err); - return false; - } - return true; -} - -// Receive two communication ports from another process -bool -RecvPortsMessage(ReceivePort* receiver, mach_port_t* ports_in_sender, mach_port_t* ports_out_sender) -{ - MachReceiveMessage rcvPortsMsg; - kern_return_t err = receiver->WaitForMessage(&rcvPortsMsg, kTimeout); - if (KERN_SUCCESS != err) { - LOG_ERROR("Error receiving get ports message %s (%x)\n", mach_error_string(err), err); - } - if (rcvPortsMsg.GetTranslatedPort(0) == MACH_PORT_NULL) { - LOG_ERROR("GetTranslatedPort(0) failed"); - return false; - } - *ports_in_sender = rcvPortsMsg.GetTranslatedPort(0); - - if (rcvPortsMsg.GetTranslatedPort(1) == MACH_PORT_NULL) { - LOG_ERROR("GetTranslatedPort(1) failed"); - return false; - } - *ports_out_sender = rcvPortsMsg.GetTranslatedPort(1); - return true; -} - -// Send two communication ports to another process and receive two back -bool -RequestPorts(const MemoryPorts& request_ports, - mach_port_t ports_in_receiver, - mach_port_t* ports_in_sender, - mach_port_t* ports_out_sender, - mach_port_t ports_out_receiver, - PIDPair pid_pair) -{ - if (!SendPortsMessage(request_ports.mSender, ports_in_receiver, ports_out_receiver, pid_pair)) { - return false; - } - return RecvPortsMessage(request_ports.mReceiver, ports_in_sender, ports_out_sender); -} - -MemoryPorts* -GetMemoryPortsForPid(pid_t pid) -{ - gMutex.AssertCurrentThreadOwns(); - - if (gMemoryCommPorts.find(pid) == gMemoryCommPorts.end()) { - // We don't have the ports open to communicate with that pid, so we're going to - // ask our parent process over IPC to set them up for us. - if (gParentPid == 0) { - // If we're the top level parent process, we have no parent to ask. - LOG_ERROR("request for ports for pid %d, but we're the chrome process\n", pid); - return nullptr; - } - const MemoryPorts& parent = gMemoryCommPorts[gParentPid]; - - // Create two receiving ports in this process to send to the parent. One will be used for - // for listening for incoming memory to be shared, the other for getting the Handle of - // memory we share to the other process. - ReceivePort* ports_in_receiver = new ReceivePort(); - ReceivePort* ports_out_receiver = new ReceivePort(); - mach_port_t raw_ports_in_sender, raw_ports_out_sender; - if (!RequestPorts(parent, - ports_in_receiver->GetPort(), - &raw_ports_in_sender, - &raw_ports_out_sender, - ports_out_receiver->GetPort(), - PIDPair(getpid(), pid))) { - LOG_ERROR("failed to request ports\n"); - return nullptr; - } - // Our parent process sent us two ports, one is for sending new memory to, the other - // is for replying with the Handle when we receive new memory. - MachPortSender* ports_in_sender = new MachPortSender(raw_ports_in_sender); - MachPortSender* ports_out_sender = new MachPortSender(raw_ports_out_sender); - SetupMachMemory(pid, - ports_in_receiver, - ports_in_sender, - ports_out_sender, - ports_out_receiver, - false); - MOZ_ASSERT(gMemoryCommPorts.find(pid) != gMemoryCommPorts.end()); - } - return &gMemoryCommPorts.at(pid); -} - -// We just received a port representing a region of shared memory, reply to -// the process that set it with the mach_port_t that represents it in this process. -// That will be the Handle to be shared over normal IPC -void -HandleSharePortsMessage(MachReceiveMessage* rmsg, MemoryPorts* ports) -{ - mach_port_t port = rmsg->GetTranslatedPort(0); - MachSendMessage msg(kReturnIdMsg); - msg.SetData(&port, sizeof(port)); - kern_return_t err = ports->mSender->SendMessage(msg, kTimeout); - if (KERN_SUCCESS != err) { - LOG_ERROR("SendMessage failed 0x%x %s\n", err, mach_error_string(err)); - } -} - -// We were asked by another process to get communications ports to some process. Return -// those ports via an IPC message. -bool -SendReturnPortsMsg(MachPortSender* sender, - mach_port_t raw_ports_in_sender, - mach_port_t raw_ports_out_sender) -{ - MachSendMessage getPortsMsg(kReturnPortsMsg); - if (!getPortsMsg.AddDescriptor(MachMsgPortDescriptor(raw_ports_in_sender))) { - LOG_ERROR("Adding descriptor to message failed"); - return false; - } - - if (!getPortsMsg.AddDescriptor(MachMsgPortDescriptor(raw_ports_out_sender))) { - LOG_ERROR("Adding descriptor to message failed"); - return false; - } - kern_return_t err = sender->SendMessage(getPortsMsg, kTimeout); - if (KERN_SUCCESS != err) { - LOG_ERROR("Error sending get ports message %s (%x)\n", mach_error_string(err), err); - return false; - } - return true; -} - -// We were asked for communcations ports to a process that isn't us. Assuming that process -// is one of our children, forward that request on. -void -ForwardGetPortsMessage(MachReceiveMessage* rmsg, MemoryPorts* ports, PIDPair* pid_pair) -{ - if (rmsg->GetTranslatedPort(0) == MACH_PORT_NULL) { - LOG_ERROR("GetTranslatedPort(0) failed"); - return; - } - if (rmsg->GetTranslatedPort(1) == MACH_PORT_NULL) { - LOG_ERROR("GetTranslatedPort(1) failed"); - return; - } - mach_port_t raw_ports_in_sender, raw_ports_out_sender; - MemoryPorts* requestedPorts = GetMemoryPortsForPid(pid_pair->mRequested); - if (!requestedPorts) { - LOG_ERROR("failed to find port for process\n"); - return; - } - if (!RequestPorts(*requestedPorts, rmsg->GetTranslatedPort(0), &raw_ports_in_sender, - &raw_ports_out_sender, rmsg->GetTranslatedPort(1), *pid_pair)) { - LOG_ERROR("failed to request ports\n"); - return; - } - SendReturnPortsMsg(ports->mSender, raw_ports_in_sender, raw_ports_out_sender); -} - -// We receieved a message asking us to get communications ports for another process -void -HandleGetPortsMessage(MachReceiveMessage* rmsg, MemoryPorts* ports) -{ - PIDPair* pid_pair; - if (rmsg->GetDataLength() != sizeof(PIDPair)) { - LOG_ERROR("Improperly formatted message\n"); - return; - } - pid_pair = reinterpret_cast(rmsg->GetData()); - if (pid_pair->mRequested != getpid()) { - // This request is for ports to a process that isn't us, forward it to that process - ForwardGetPortsMessage(rmsg, ports, pid_pair); - } else { - if (rmsg->GetTranslatedPort(0) == MACH_PORT_NULL) { - LOG_ERROR("GetTranslatedPort(0) failed"); - return; - } - - if (rmsg->GetTranslatedPort(1) == MACH_PORT_NULL) { - LOG_ERROR("GetTranslatedPort(1) failed"); - return; - } - - MachPortSender* ports_in_sender = new MachPortSender(rmsg->GetTranslatedPort(0)); - MachPortSender* ports_out_sender = new MachPortSender(rmsg->GetTranslatedPort(1)); - - ReceivePort* ports_in_receiver = new ReceivePort(); - ReceivePort* ports_out_receiver = new ReceivePort(); - if (SendReturnPortsMsg(ports->mSender, ports_in_receiver->GetPort(), ports_out_receiver->GetPort())) { - SetupMachMemory(pid_pair->mRequester, - ports_out_receiver, - ports_out_sender, - ports_in_sender, - ports_in_receiver, - false); - } - } -} - -static void * -PortServerThread(void *argument) -{ - MemoryPorts* ports = static_cast(argument); - MachReceiveMessage child_message; - while (true) { - MachReceiveMessage rmsg; - kern_return_t err = ports->mReceiver->WaitForMessage(&rmsg, MACH_MSG_TIMEOUT_NONE); - if (err != KERN_SUCCESS) { - LOG_ERROR("Wait for message failed 0x%x %s\n", err, mach_error_string(err)); - continue; - } - - StaticMutexAutoLock smal(gMutex); - - switch (rmsg.GetMessageID()) { - case kSharePortsMsg: - HandleSharePortsMessage(&rmsg, ports); - break; - case kGetPortsMsg: - HandleGetPortsMessage(&rmsg, ports); - break; - case kShutdownMsg: - delete ports->mSender; - delete ports->mReceiver; - delete ports; - return nullptr; - case kCleanupMsg: - if (gParentPid == 0) { - LOG_ERROR("Cleanup message not valid for parent process"); - continue; - } - - pid_t* pid; - if (rmsg.GetDataLength() != sizeof(pid_t)) { - LOG_ERROR("Improperly formatted message\n"); - continue; - } - pid = reinterpret_cast(rmsg.GetData()); - SharedMemoryBasic::CleanupForPid(*pid); - break; - default: - LOG_ERROR("Unknown message\n"); - } - } -} - -void -SharedMemoryBasic::SetupMachMemory(pid_t pid, - ReceivePort* listen_port, - MachPortSender* listen_port_ack, - MachPortSender* send_port, - ReceivePort* send_port_ack, - bool pidIsParent) -{ - StaticMutexAutoLock smal(gMutex); - mozilla::ipc::SetupMachMemory(pid, listen_port, listen_port_ack, send_port, send_port_ack, pidIsParent); - - ShutdownObserver::Initialize(pidIsParent); -} - -void -SharedMemoryBasic::CleanupForPid(pid_t pid) -{ - if (gThreads.find(pid) == gThreads.end()) { - return; - } - const ListeningThread& listeningThread = gThreads[pid]; - MachSendMessage shutdownMsg(kShutdownMsg); - kern_return_t ret = listeningThread.mPorts->mReceiver->SendMessageToSelf(shutdownMsg, kTimeout); - if (ret != KERN_SUCCESS) { - LOG_ERROR("sending shutdown msg failed %s %x\n", mach_error_string(ret), ret); - } - gThreads.erase(pid); - - if (gParentPid == 0) { - // We're the parent. Broadcast the cleanup message to everyone else. - for (auto it = gMemoryCommPorts.begin(); it != gMemoryCommPorts.end(); ++it) { - MachSendMessage msg(kCleanupMsg); - msg.SetData(&pid, sizeof(pid)); - // We don't really care if this fails, we could be trying to send to an already shut down proc - it->second.mSender->SendMessage(msg, kTimeout); - } - } - - MemoryPorts& ports = gMemoryCommPorts[pid]; - delete ports.mSender; - delete ports.mReceiver; - gMemoryCommPorts.erase(pid); -} - -SharedMemoryBasic::SharedMemoryBasic() - : mPort(MACH_PORT_NULL) - , mMemory(nullptr) -{ -} - -SharedMemoryBasic::SharedMemoryBasic(Handle aHandle) - : mPort(MACH_PORT_NULL) - , mMemory(nullptr) -{ - mPort = aHandle; -} - -SharedMemoryBasic::~SharedMemoryBasic() -{ - Unmap(); - Destroy(); -} - -static inline void* -toPointer(mach_vm_address_t address) -{ - return reinterpret_cast(static_cast(address)); -} - -static inline mach_vm_address_t -toVMAddress(void* pointer) -{ - return static_cast(reinterpret_cast(pointer)); -} - -bool -SharedMemoryBasic::Create(size_t size) -{ - mach_vm_address_t address; - - kern_return_t kr = mach_vm_allocate(mach_task_self(), &address, round_page(size), VM_FLAGS_ANYWHERE); - if (kr != KERN_SUCCESS) { - LOG_ERROR("Failed to allocate mach_vm_allocate shared memory (%zu bytes). %s (%x)\n", - size, mach_error_string(kr), kr); - return false; - } - - memory_object_size_t memoryObjectSize = round_page(size); - - kr = mach_make_memory_entry_64(mach_task_self(), - &memoryObjectSize, - address, - VM_PROT_DEFAULT, - &mPort, - MACH_PORT_NULL); - if (kr != KERN_SUCCESS) { - LOG_ERROR("Failed to make memory entry (%zu bytes). %s (%x)\n", - size, mach_error_string(kr), kr); - return false; - } - - mMemory = toPointer(address); - Mapped(size); - return true; -} - -bool -SharedMemoryBasic::Map(size_t size) -{ - if (mMemory) { - return true; - } - - if (MACH_PORT_NULL == mPort) { - return false; - } - - kern_return_t kr; - mach_vm_address_t address = 0; - - vm_prot_t vmProtection = VM_PROT_READ | VM_PROT_WRITE; - - kr = mach_vm_map(mach_task_self(), &address, round_page(size), 0, VM_FLAGS_ANYWHERE, - mPort, 0, false, vmProtection, vmProtection, VM_INHERIT_NONE); - if (kr != KERN_SUCCESS) { - LOG_ERROR("Failed to map shared memory (%zu bytes) into %x, port %x. %s (%x)\n", - size, mach_task_self(), mPort, mach_error_string(kr), kr); - return false; - } - - mMemory = toPointer(address); - Mapped(size); - return true; -} - -bool -SharedMemoryBasic::ShareToProcess(base::ProcessId pid, - Handle* aNewHandle) -{ - StaticMutexAutoLock smal(gMutex); - - MemoryPorts* ports = GetMemoryPortsForPid(pid); - if (!ports) { - LOG_ERROR("Unable to get ports for process.\n"); - return false; - } - MachSendMessage smsg(kSharePortsMsg); - smsg.AddDescriptor(MachMsgPortDescriptor(mPort, MACH_MSG_TYPE_COPY_SEND)); - kern_return_t err = ports->mSender->SendMessage(smsg, kTimeout); - if (err != KERN_SUCCESS) { - LOG_ERROR("sending port failed %s %x\n", mach_error_string(err), err); - return false; - } - MachReceiveMessage msg; - err = ports->mReceiver->WaitForMessage(&msg, kTimeout); - if (err != KERN_SUCCESS) { - LOG_ERROR("didn't get an id %s %x\n", mach_error_string(err), err); - return false; - } - if (msg.GetDataLength() != sizeof(mach_port_t)) { - LOG_ERROR("Improperly formatted reply\n"); - return false; - } - mach_port_t *id = reinterpret_cast(msg.GetData()); - *aNewHandle = *id; - return true; -} - -void -SharedMemoryBasic::Unmap() -{ - if (!mMemory) { - return; - } - vm_address_t address = toVMAddress(mMemory); - kern_return_t kr = vm_deallocate(mach_task_self(), address, vm_page_size); - if (kr != KERN_SUCCESS) { - LOG_ERROR("Failed to deallocate shared memory. %s (%x)\n", mach_error_string(kr), kr); - return; - } - mMemory = nullptr; -} - -void -SharedMemoryBasic::Destroy() -{ - mach_port_deallocate(mach_task_self(), mPort); -} - -bool -SharedMemoryBasic::IsHandleValid(const Handle& aHandle) -{ - return aHandle > 0; -} - -} // namespace ipc -} // namespace mozilla diff --git a/ipc/glue/SharedMemoryBasic_mach.h b/ipc/glue/SharedMemoryBasic_mach.h deleted file mode 100644 index 32733644c2d8..000000000000 --- a/ipc/glue/SharedMemoryBasic_mach.h +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: sw=2 ts=8 et : - */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_ipc_SharedMemoryBasic_mach_h -#define mozilla_ipc_SharedMemoryBasic_mach_h - -#include "base/file_descriptor_posix.h" -#include "base/process.h" - -#include "SharedMemory.h" -#include - -// -// This is a low-level wrapper around platform shared memory. Don't -// use it directly; use Shmem allocated through IPDL interfaces. -// - -class MachPortSender; -class ReceivePort; - -namespace mozilla { -namespace ipc { - -class SharedMemoryBasic final : public SharedMemory -{ -public: - typedef mach_port_t Handle; - - static void SetupMachMemory(pid_t pid, - ReceivePort* listen_port, - MachPortSender* listen_port_ack, - MachPortSender* send_port, - ReceivePort* send_port_ack, - bool pidIsParent); - - static void CleanupForPid(pid_t pid); - - SharedMemoryBasic(); - - explicit SharedMemoryBasic(Handle aHandle); - - virtual bool Create(size_t aNbytes) override; - - virtual bool Map(size_t nBytes) override; - - virtual void* memory() const override - { - return mMemory; - } - - virtual SharedMemoryType Type() const override - { - return TYPE_BASIC; - } - - static Handle NULLHandle() - { - return Handle(); - } - - - static bool IsHandleValid(const Handle &aHandle); - - bool ShareToProcess(base::ProcessId aProcessId, - Handle* aNewHandle); - -private: - ~SharedMemoryBasic(); - - void Unmap(); - void Destroy(); - mach_port_t mPort; - // Pointer to mapped region, null if unmapped. - void *mMemory; -}; - -} // namespace ipc -} // namespace mozilla - -#endif // ifndef mozilla_ipc_SharedMemoryBasic_mach_h diff --git a/ipc/glue/moz.build b/ipc/glue/moz.build index cfce05891000..8f75c1fdb7bb 100644 --- a/ipc/glue/moz.build +++ b/ipc/glue/moz.build @@ -76,11 +76,6 @@ if CONFIG['OS_TARGET'] == 'Android': UNIFIED_SOURCES += [ 'SharedMemoryBasic_android.cpp', ] -elif CONFIG['OS_ARCH'] == 'Darwin': - EXPORTS.mozilla.ipc += ['SharedMemoryBasic_mach.h'] - SOURCES += [ - 'SharedMemoryBasic_mach.cpp', - ] else: EXPORTS.mozilla.ipc += ['SharedMemoryBasic_chromium.h'] diff --git a/toolkit/xre/nsEmbedFunctions.cpp b/toolkit/xre/nsEmbedFunctions.cpp index 3df2542feb5b..366a89f0fd88 100644 --- a/toolkit/xre/nsEmbedFunctions.cpp +++ b/toolkit/xre/nsEmbedFunctions.cpp @@ -375,18 +375,6 @@ XRE_InitChildProcess(int aArgc, return NS_ERROR_FAILURE; } - ReceivePort* ports_out_receiver = new ReceivePort(); - if (!child_message.AddDescriptor(MachMsgPortDescriptor(ports_out_receiver->GetPort()))) { - NS_WARNING("Adding descriptor to message failed"); - return NS_ERROR_FAILURE; - } - - ReceivePort* ports_in_receiver = new ReceivePort(); - if (!child_message.AddDescriptor(MachMsgPortDescriptor(ports_in_receiver->GetPort()))) { - NS_WARNING("Adding descriptor to message failed"); - return NS_ERROR_FAILURE; - } - MachPortSender child_sender(mach_port_name); kern_return_t err = child_sender.SendMessage(child_message, kTimeoutMs); if (err != KERN_SUCCESS) { @@ -405,27 +393,12 @@ XRE_InitChildProcess(int aArgc, NS_WARNING("child GetTranslatedPort(0) failed"); return NS_ERROR_FAILURE; } - err = task_set_bootstrap_port(mach_task_self(), parent_message.GetTranslatedPort(0)); - - if (parent_message.GetTranslatedPort(1) == MACH_PORT_NULL) { - NS_WARNING("child GetTranslatedPort(1) failed"); - return NS_ERROR_FAILURE; - } - MachPortSender* ports_out_sender = new MachPortSender(parent_message.GetTranslatedPort(1)); - - if (parent_message.GetTranslatedPort(2) == MACH_PORT_NULL) { - NS_WARNING("child GetTranslatedPort(2) failed"); - return NS_ERROR_FAILURE; - } - MachPortSender* ports_in_sender = new MachPortSender(parent_message.GetTranslatedPort(2)); - if (err != KERN_SUCCESS) { NS_WARNING("child task_set_bootstrap_port() failed"); return NS_ERROR_FAILURE; } - #endif SetupErrorHandling(aArgv[0]); @@ -494,11 +467,6 @@ XRE_InitChildProcess(int aArgc, base::ProcessId parentPID = strtol(parentPIDString, &end, 10); MOZ_ASSERT(!*end, "invalid parent PID"); -#ifdef XP_MACOSX - mozilla::ipc::SharedMemoryBasic::SetupMachMemory(parentPID, ports_in_receiver, ports_in_sender, - ports_out_sender, ports_out_receiver, true); -#endif - #if defined(XP_WIN) // On Win7+, register the application user model id passed in by // parent. This insures windows created by the container properly From 653dd57e07af7b38ea286bc429b6b635188546e2 Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Tue, 9 Jun 2015 15:12:29 -0700 Subject: [PATCH 15/95] Backed out changeset 8ee308c30146 (bug 1161166) for debug osx mochitest failures --- ipc/chromium/src/chrome/common/mach_ipc_mac.h | 12 +++++++++--- ipc/chromium/src/chrome/common/mach_ipc_mac.mm | 15 --------------- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/ipc/chromium/src/chrome/common/mach_ipc_mac.h b/ipc/chromium/src/chrome/common/mach_ipc_mac.h index de9d8843c3b0..46466245edb7 100644 --- a/ipc/chromium/src/chrome/common/mach_ipc_mac.h +++ b/ipc/chromium/src/chrome/common/mach_ipc_mac.h @@ -10,6 +10,8 @@ #include #include +#include + #include "base/basictypes.h" //============================================================================== @@ -143,12 +145,16 @@ class MachMessage { return GetDataLength() > 0 ? GetDataPacket()->data : NULL; } - u_int32_t GetDataLength(); + u_int32_t GetDataLength() { + return EndianU32_LtoN(GetDataPacket()->data_length); + } // The message ID may be used as a code identifying the type of message - void SetMessageID(int32_t message_id); + void SetMessageID(int32_t message_id) { + GetDataPacket()->id = EndianU32_NtoL(message_id); + } - int32_t GetMessageID(); + int32_t GetMessageID() { return EndianU32_LtoN(GetDataPacket()->id); } // Adds a descriptor (typically a mach port) to be translated // returns true if successful, otherwise not enough space diff --git a/ipc/chromium/src/chrome/common/mach_ipc_mac.mm b/ipc/chromium/src/chrome/common/mach_ipc_mac.mm index 8f1250b80408..3c95ef6dfb2c 100644 --- a/ipc/chromium/src/chrome/common/mach_ipc_mac.mm +++ b/ipc/chromium/src/chrome/common/mach_ipc_mac.mm @@ -59,21 +59,6 @@ MachMessage::~MachMessage() { } } - -u_int32_t MachMessage::GetDataLength() { - return EndianU32_LtoN(GetDataPacket()->data_length); -} - - // The message ID may be used as a code identifying the type of message -void MachMessage::SetMessageID(int32_t message_id) { - GetDataPacket()->id = EndianU32_NtoL(message_id); -} - -int32_t MachMessage::GetMessageID() { - return EndianU32_LtoN(GetDataPacket()->id); -} - - //============================================================================== // returns true if successful bool MachMessage::SetData(const void* data, From 08b17ee9a2a5d11b020d8a7ee87c90d2aaadc834 Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Tue, 9 Jun 2015 15:16:30 -0700 Subject: [PATCH 16/95] Backed out changeset e33db57c3fec (bug 1173029) --- dom/fetch/InternalResponse.cpp | 1 + dom/fetch/InternalResponse.h | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/dom/fetch/InternalResponse.cpp b/dom/fetch/InternalResponse.cpp index ae67917dd807..2791a013e2da 100644 --- a/dom/fetch/InternalResponse.cpp +++ b/dom/fetch/InternalResponse.cpp @@ -14,6 +14,7 @@ namespace dom { InternalResponse::InternalResponse(uint16_t aStatus, const nsACString& aStatusText) : mType(ResponseType::Default) + , mFinalURL(false) , mStatus(aStatus) , mStatusText(aStatusText) , mHeaders(new InternalHeaders(HeadersGuardEnum::Response)) diff --git a/dom/fetch/InternalResponse.h b/dom/fetch/InternalResponse.h index 694033ad0f78..9b88de778ccd 100644 --- a/dom/fetch/InternalResponse.h +++ b/dom/fetch/InternalResponse.h @@ -48,6 +48,7 @@ public: response->mType = ResponseType::Opaque; response->mTerminationReason = mTerminationReason; response->mURL = mURL; + response->mFinalURL = mFinalURL; response->mChannelInfo = mChannelInfo; response->mWrappedResponse = this; return response.forget(); @@ -89,6 +90,18 @@ public: mURL.Assign(aURL); } + bool + FinalURL() const + { + return mFinalURL; + } + + void + SetFinalURL(bool aFinalURL) + { + mFinalURL = aFinalURL; + } + uint16_t GetStatus() const { @@ -184,6 +197,7 @@ private: copy->mType = mType; copy->mTerminationReason = mTerminationReason; copy->mURL = mURL; + copy->mFinalURL = mFinalURL; copy->mChannelInfo = mChannelInfo; return copy.forget(); } @@ -191,6 +205,7 @@ private: ResponseType mType; nsCString mTerminationReason; nsCString mURL; + bool mFinalURL; const uint16_t mStatus; const nsCString mStatusText; nsRefPtr mHeaders; From 4d5ff3adfe433641f25430ca537c1947fcbbb192 Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Tue, 9 Jun 2015 15:16:42 -0700 Subject: [PATCH 17/95] Backed out changeset ec31f39d4df8 (bug 1170937) for mochitest-e10s-4 permafail CLOSED TREE --- dom/fetch/FetchDriver.cpp | 22 ++++++---------------- dom/fetch/FetchDriver.h | 3 +-- dom/tests/mochitest/fetch/mochitest.ini | 6 ++++-- 3 files changed, 11 insertions(+), 20 deletions(-) diff --git a/dom/fetch/FetchDriver.cpp b/dom/fetch/FetchDriver.cpp index 7c42a4864c0c..a188fe1d6d8b 100644 --- a/dom/fetch/FetchDriver.cpp +++ b/dom/fetch/FetchDriver.cpp @@ -548,16 +548,14 @@ FetchDriver::ContinueHttpFetchAfterNetworkFetch() } already_AddRefed -FetchDriver::BeginAndGetFilteredResponse(InternalResponse* aResponse, nsIURI* aFinalURI) +FetchDriver::BeginAndGetFilteredResponse(InternalResponse* aResponse) { MOZ_ASSERT(aResponse); - nsAutoCString reqURL; - if (aFinalURI) { - aFinalURI->GetSpec(reqURL); - } else { + if (!aResponse->FinalURL()) { + nsAutoCString reqURL; mRequest->GetURL(reqURL); + aResponse->SetUrl(reqURL); } - aResponse->SetUrl(reqURL); // FIXME(nsm): Handle mixed content check, step 7 of fetch. @@ -586,7 +584,7 @@ FetchDriver::BeginAndGetFilteredResponse(InternalResponse* aResponse, nsIURI* aF void FetchDriver::BeginResponse(InternalResponse* aResponse) { - nsRefPtr r = BeginAndGetFilteredResponse(aResponse, nullptr); + nsRefPtr r = BeginAndGetFilteredResponse(aResponse); // Release the ref. } @@ -718,17 +716,9 @@ FetchDriver::OnStartRequest(nsIRequest* aRequest, nsCOMPtr channel = do_QueryInterface(aRequest); response->InitChannelInfo(channel); - nsCOMPtr channelURI; - rv = channel->GetURI(getter_AddRefs(channelURI)); - if (NS_WARN_IF(NS_FAILED(rv))) { - FailWithNetworkError(); - // Cancel request. - return rv; - } - // Resolves fetch() promise which may trigger code running in a worker. Make // sure the Response is fully initialized before calling this. - mResponse = BeginAndGetFilteredResponse(response, channelURI); + mResponse = BeginAndGetFilteredResponse(response); nsCOMPtr sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv); if (NS_WARN_IF(NS_FAILED(rv))) { diff --git a/dom/fetch/FetchDriver.h b/dom/fetch/FetchDriver.h index ed376c999a73..6b8861434af3 100644 --- a/dom/fetch/FetchDriver.h +++ b/dom/fetch/FetchDriver.h @@ -88,9 +88,8 @@ private: nsresult HttpFetch(bool aCORSFlag = false, bool aCORSPreflightFlag = false, bool aAuthenticationFlag = false); nsresult ContinueHttpFetchAfterNetworkFetch(); // Returns the filtered response sent to the observer. - // Callers who don't have access to a channel can pass null for aFinalURI. already_AddRefed - BeginAndGetFilteredResponse(InternalResponse* aResponse, nsIURI* aFinalURI); + BeginAndGetFilteredResponse(InternalResponse* aResponse); // Utility since not all cases need to do any post processing of the filtered // response. void BeginResponse(InternalResponse* aResponse); diff --git a/dom/tests/mochitest/fetch/mochitest.ini b/dom/tests/mochitest/fetch/mochitest.ini index 84e18b479e5b..9febdd63972b 100644 --- a/dom/tests/mochitest/fetch/mochitest.ini +++ b/dom/tests/mochitest/fetch/mochitest.ini @@ -27,10 +27,12 @@ skip-if = buildapp == 'b2g' # Bug 1137683 skip-if = buildapp == 'b2g' # Bug 1137683 [test_fetch_basic_http.html] [test_fetch_basic_http_sw_reroute.html] -skip-if = buildapp == 'b2g' # Bug 1137683 +skip-if = true # Bug 1170937, need fully support for redirects +#skip-if = buildapp == 'b2g' # Bug 1137683 [test_fetch_cors.html] [test_fetch_cors_sw_reroute.html] -skip-if = buildapp == 'b2g' # Bug 1137683 +skip-if = true # Bug 1170937, need fully support for redirects +#skip-if = buildapp == 'b2g' # Bug 1137683 [test_formdataparsing.html] [test_formdataparsing_sw_reroute.html] skip-if = buildapp == 'b2g' # Bug 1137683 From b7b9afe1583f8f9a21d94c59f7bf097d2be3f1d7 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Tue, 9 Jun 2015 15:21:13 -0400 Subject: [PATCH 18/95] Bug 1170937 - Set the URL on the Response object created from a fetch() properly if the underlying channel gets redirected; r=baku --- dom/fetch/FetchDriver.cpp | 22 ++++++++++++++++------ dom/fetch/FetchDriver.h | 3 ++- dom/tests/mochitest/fetch/mochitest.ini | 6 ++---- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/dom/fetch/FetchDriver.cpp b/dom/fetch/FetchDriver.cpp index a188fe1d6d8b..7c42a4864c0c 100644 --- a/dom/fetch/FetchDriver.cpp +++ b/dom/fetch/FetchDriver.cpp @@ -548,14 +548,16 @@ FetchDriver::ContinueHttpFetchAfterNetworkFetch() } already_AddRefed -FetchDriver::BeginAndGetFilteredResponse(InternalResponse* aResponse) +FetchDriver::BeginAndGetFilteredResponse(InternalResponse* aResponse, nsIURI* aFinalURI) { MOZ_ASSERT(aResponse); - if (!aResponse->FinalURL()) { - nsAutoCString reqURL; + nsAutoCString reqURL; + if (aFinalURI) { + aFinalURI->GetSpec(reqURL); + } else { mRequest->GetURL(reqURL); - aResponse->SetUrl(reqURL); } + aResponse->SetUrl(reqURL); // FIXME(nsm): Handle mixed content check, step 7 of fetch. @@ -584,7 +586,7 @@ FetchDriver::BeginAndGetFilteredResponse(InternalResponse* aResponse) void FetchDriver::BeginResponse(InternalResponse* aResponse) { - nsRefPtr r = BeginAndGetFilteredResponse(aResponse); + nsRefPtr r = BeginAndGetFilteredResponse(aResponse, nullptr); // Release the ref. } @@ -716,9 +718,17 @@ FetchDriver::OnStartRequest(nsIRequest* aRequest, nsCOMPtr channel = do_QueryInterface(aRequest); response->InitChannelInfo(channel); + nsCOMPtr channelURI; + rv = channel->GetURI(getter_AddRefs(channelURI)); + if (NS_WARN_IF(NS_FAILED(rv))) { + FailWithNetworkError(); + // Cancel request. + return rv; + } + // Resolves fetch() promise which may trigger code running in a worker. Make // sure the Response is fully initialized before calling this. - mResponse = BeginAndGetFilteredResponse(response); + mResponse = BeginAndGetFilteredResponse(response, channelURI); nsCOMPtr sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv); if (NS_WARN_IF(NS_FAILED(rv))) { diff --git a/dom/fetch/FetchDriver.h b/dom/fetch/FetchDriver.h index 6b8861434af3..ed376c999a73 100644 --- a/dom/fetch/FetchDriver.h +++ b/dom/fetch/FetchDriver.h @@ -88,8 +88,9 @@ private: nsresult HttpFetch(bool aCORSFlag = false, bool aCORSPreflightFlag = false, bool aAuthenticationFlag = false); nsresult ContinueHttpFetchAfterNetworkFetch(); // Returns the filtered response sent to the observer. + // Callers who don't have access to a channel can pass null for aFinalURI. already_AddRefed - BeginAndGetFilteredResponse(InternalResponse* aResponse); + BeginAndGetFilteredResponse(InternalResponse* aResponse, nsIURI* aFinalURI); // Utility since not all cases need to do any post processing of the filtered // response. void BeginResponse(InternalResponse* aResponse); diff --git a/dom/tests/mochitest/fetch/mochitest.ini b/dom/tests/mochitest/fetch/mochitest.ini index 9febdd63972b..a5cacd29f467 100644 --- a/dom/tests/mochitest/fetch/mochitest.ini +++ b/dom/tests/mochitest/fetch/mochitest.ini @@ -27,12 +27,10 @@ skip-if = buildapp == 'b2g' # Bug 1137683 skip-if = buildapp == 'b2g' # Bug 1137683 [test_fetch_basic_http.html] [test_fetch_basic_http_sw_reroute.html] -skip-if = true # Bug 1170937, need fully support for redirects -#skip-if = buildapp == 'b2g' # Bug 1137683 +skip-if = e10s || buildapp == 'b2g' # Bug 1173163 for e10s, bug 1137683 for b2g [test_fetch_cors.html] [test_fetch_cors_sw_reroute.html] -skip-if = true # Bug 1170937, need fully support for redirects -#skip-if = buildapp == 'b2g' # Bug 1137683 +skip-if = e10s || buildapp == 'b2g' # Bug 1173163 for e10s, bug 1137683 for b2g [test_formdataparsing.html] [test_formdataparsing_sw_reroute.html] skip-if = buildapp == 'b2g' # Bug 1137683 From 3f5c9c69fda5e948602235b2e95b99a64e543bcb Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Tue, 9 Jun 2015 15:23:13 -0400 Subject: [PATCH 19/95] Bug 1173029 - Remove mFinalURL from InternalResponse; r=baku a=KWierso --- dom/fetch/InternalResponse.cpp | 1 - dom/fetch/InternalResponse.h | 15 --------------- 2 files changed, 16 deletions(-) diff --git a/dom/fetch/InternalResponse.cpp b/dom/fetch/InternalResponse.cpp index 2791a013e2da..ae67917dd807 100644 --- a/dom/fetch/InternalResponse.cpp +++ b/dom/fetch/InternalResponse.cpp @@ -14,7 +14,6 @@ namespace dom { InternalResponse::InternalResponse(uint16_t aStatus, const nsACString& aStatusText) : mType(ResponseType::Default) - , mFinalURL(false) , mStatus(aStatus) , mStatusText(aStatusText) , mHeaders(new InternalHeaders(HeadersGuardEnum::Response)) diff --git a/dom/fetch/InternalResponse.h b/dom/fetch/InternalResponse.h index 9b88de778ccd..694033ad0f78 100644 --- a/dom/fetch/InternalResponse.h +++ b/dom/fetch/InternalResponse.h @@ -48,7 +48,6 @@ public: response->mType = ResponseType::Opaque; response->mTerminationReason = mTerminationReason; response->mURL = mURL; - response->mFinalURL = mFinalURL; response->mChannelInfo = mChannelInfo; response->mWrappedResponse = this; return response.forget(); @@ -90,18 +89,6 @@ public: mURL.Assign(aURL); } - bool - FinalURL() const - { - return mFinalURL; - } - - void - SetFinalURL(bool aFinalURL) - { - mFinalURL = aFinalURL; - } - uint16_t GetStatus() const { @@ -197,7 +184,6 @@ private: copy->mType = mType; copy->mTerminationReason = mTerminationReason; copy->mURL = mURL; - copy->mFinalURL = mFinalURL; copy->mChannelInfo = mChannelInfo; return copy.forget(); } @@ -205,7 +191,6 @@ private: ResponseType mType; nsCString mTerminationReason; nsCString mURL; - bool mFinalURL; const uint16_t mStatus; const nsCString mStatusText; nsRefPtr mHeaders; From d1c7dfa95b73db23fb8e1c2981babdb17ca275da Mon Sep 17 00:00:00 2001 From: Birunthan Mohanathas Date: Tue, 2 Jun 2015 15:10:16 -0700 Subject: [PATCH 20/95] Bug 1170758 - Make non-debug GraphSpewer constructor explicit. r=nbp --- js/src/jit/JitSpewer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/jit/JitSpewer.h b/js/src/jit/JitSpewer.h index 06b718eb793f..261392f06014 100644 --- a/js/src/jit/JitSpewer.h +++ b/js/src/jit/JitSpewer.h @@ -171,7 +171,7 @@ void EnableIonDebugAsyncLogging(); class GraphSpewer { public: - GraphSpewer(TempAllocator *alloc) { } + explicit GraphSpewer(TempAllocator *alloc) { } bool isSpewing() { return false; } void init(MIRGraph* graph, JSScript* function) { } From 53c8a09de0654f5e70c152f9d26f3ae47d177eaf Mon Sep 17 00:00:00 2001 From: Birunthan Mohanathas Date: Mon, 8 Jun 2015 13:39:49 -0700 Subject: [PATCH 21/95] Bug 968520 - Add mozilla::fallible to FallibleArray calls in tests. r=froydnj --- xpcom/glue/tests/gtest/TestGCPostBarriers.cpp | 2 +- xpcom/tests/TestTArray.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/xpcom/glue/tests/gtest/TestGCPostBarriers.cpp b/xpcom/glue/tests/gtest/TestGCPostBarriers.cpp index c44b8c2e27e0..236f895550df 100644 --- a/xpcom/glue/tests/gtest/TestGCPostBarriers.cpp +++ b/xpcom/glue/tests/gtest/TestGCPostBarriers.cpp @@ -58,7 +58,7 @@ RunTest(JSRuntime* rt, JSContext* cx, ArrayT* array) ASSERT_FALSE(JS::ObjectIsTenured(obj)); value = Int32Value(i); ASSERT_TRUE(JS_SetProperty(cx, obj, property, value)); - array->AppendElement(obj); + ASSERT_TRUE(array->AppendElement(obj, fallible)); } /* diff --git a/xpcom/tests/TestTArray.cpp b/xpcom/tests/TestTArray.cpp index 80d359a879c3..df38cc7cd9e3 100644 --- a/xpcom/tests/TestTArray.cpp +++ b/xpcom/tests/TestTArray.cpp @@ -1011,7 +1011,7 @@ static bool test_fallible() const unsigned numArrays = 36; FallibleTArray arrays[numArrays]; for (size_t i = 0; i < numArrays; i++) { - bool success = arrays[i].SetCapacity(128 * 1024 * 1024); + bool success = arrays[i].SetCapacity(128 * 1024 * 1024, fallible); if (!success) { // We got our OOM. Check that it didn't come too early. if (i < 8) { @@ -1112,7 +1112,7 @@ static bool test_SetLengthAndRetainStorage_no_ctor() { } while (0) // Setup test arrays. - FOR_EACH(;, .SetLength(N)); + FOR_EACH(;, .SetLength(N, fallible)); for (int n = 0; n < N; ++n) { FOR_EACH(;, [n] = n); } From c864230df7735a67445949b1ee2b750b3552a9c3 Mon Sep 17 00:00:00 2001 From: Birunthan Mohanathas Date: Mon, 8 Jun 2015 13:39:53 -0700 Subject: [PATCH 22/95] Bug 968520 - Make nsTArray::InsertElementSorted support moves. r=froydnj --- xpcom/glue/nsTArray.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/xpcom/glue/nsTArray.h b/xpcom/glue/nsTArray.h index f45c027e1aab..038e5f092553 100644 --- a/xpcom/glue/nsTArray.h +++ b/xpcom/glue/nsTArray.h @@ -1393,17 +1393,20 @@ public: // was previously sorted, it will remain sorted after this // insertion. template - elem_type* InsertElementSorted(const Item& aItem, const Comparator& aComp) + elem_type* InsertElementSorted(Item&& aItem, const Comparator& aComp) { - index_type index = IndexOfFirstElementGt(aItem, aComp); - return InsertElementAt(index, aItem); + index_type index = IndexOfFirstElementGt(aItem, aComp); + return InsertElementAt( + index, mozilla::Forward(aItem)); } // A variation on the InsertElementSorted method defined above. template - elem_type* InsertElementSorted(const Item& aItem) + elem_type* InsertElementSorted(Item&& aItem) { - return InsertElementSorted(aItem, nsDefaultComparator()); + nsDefaultComparator comp; + return InsertElementSorted( + mozilla::Forward(aItem), comp); } // This method appends elements to the end of this array. From 5cce2e644c9bde328a268604a7312eb8feace32b Mon Sep 17 00:00:00 2001 From: Birunthan Mohanathas Date: Mon, 8 Jun 2015 13:39:57 -0700 Subject: [PATCH 23/95] Bug 968520 - Add fallible variants of nsTArray::InsertElementSorted. r=froydnj --- xpcom/glue/nsTArray.h | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/xpcom/glue/nsTArray.h b/xpcom/glue/nsTArray.h index 038e5f092553..492ed9a24691 100644 --- a/xpcom/glue/nsTArray.h +++ b/xpcom/glue/nsTArray.h @@ -1392,23 +1392,40 @@ public: // Inserts |aItem| at such an index to guarantee that if the array // was previously sorted, it will remain sorted after this // insertion. - template + template elem_type* InsertElementSorted(Item&& aItem, const Comparator& aComp) { index_type index = IndexOfFirstElementGt(aItem, aComp); - return InsertElementAt( + return InsertElementAt( index, mozilla::Forward(aItem)); } + template + /* MOZ_WARN_UNUSED_RESULT */ + elem_type* InsertElementSorted(Item&& aItem, const Comparator& aComp, + const mozilla::fallible_t&) + { + return InsertElementSorted( + mozilla::Forward(aItem), aComp); + } + // A variation on the InsertElementSorted method defined above. - template + template elem_type* InsertElementSorted(Item&& aItem) { nsDefaultComparator comp; - return InsertElementSorted( + return InsertElementSorted( mozilla::Forward(aItem), comp); } + template + /* MOZ_WARN_UNUSED_RESULT */ + elem_type* InsertElementSorted(Item&& aItem, const mozilla::fallible_t&) + { + return InsertElementSorted( + mozilla::Forward(aItem)); + } + // This method appends elements to the end of this array. // @param aArray The elements to append to this array. // @param aArrayLen The number of elements to append to this array. From 8b524164fa2ff28ffd4399cb90468e1edd5cffb0 Mon Sep 17 00:00:00 2001 From: Birunthan Mohanathas Date: Mon, 8 Jun 2015 13:40:00 -0700 Subject: [PATCH 24/95] Bug 968520 - Add mozilla::fallible to FallibleTArray::InsertElementSorted calls. r=froydnj --- dom/indexedDB/ActorsParent.cpp | 15 ++++++++++----- toolkit/components/url-classifier/ChunkSet.cpp | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/dom/indexedDB/ActorsParent.cpp b/dom/indexedDB/ActorsParent.cpp index 9ddf54cc15e0..de183bfe24b9 100644 --- a/dom/indexedDB/ActorsParent.cpp +++ b/dom/indexedDB/ActorsParent.cpp @@ -858,7 +858,8 @@ ReadCompressedIndexDataValuesFromBlob( blobDataIter += keyBufferLength; if (NS_WARN_IF(!aIndexValues.InsertElementSorted( - IndexDataValue(indexId, unique, Key(keyBuffer))))) { + IndexDataValue(indexId, unique, Key(keyBuffer)), + fallible))) { IDB_REPORT_INTERNAL_ERR(); return NS_ERROR_OUT_OF_MEMORY; } @@ -2734,7 +2735,8 @@ InsertIndexDataValuesFunction::OnFunctionCall(mozIStorageValueArray* aValues, } MOZ_ALWAYS_TRUE( - indexValues.InsertElementSorted(IndexDataValue(indexId, !!unique, value))); + indexValues.InsertElementSorted(IndexDataValue(indexId, !!unique, value), + fallible)); // Compress the array. UniqueFreePtr indexValuesBlob; @@ -17856,7 +17858,8 @@ DatabaseOperationBase::IndexDataValuesFromUpdateInfos( MOZ_ALWAYS_TRUE(aUniqueIndexTable.Get(indexId, &unique)); MOZ_ALWAYS_TRUE( - aIndexValues.InsertElementSorted(IndexDataValue(indexId, unique, key))); + aIndexValues.InsertElementSorted(IndexDataValue(indexId, unique, key), + fallible)); } return NS_OK; @@ -22291,7 +22294,8 @@ UpdateIndexDataValuesFunction::OnFunctionCall(mozIStorageValueArray* aValues, MOZ_ALWAYS_TRUE( indexValues.InsertElementSorted(IndexDataValue(metadata.id(), metadata.unique(), - info.value()))); + info.value()), + fallible)); } UniqueFreePtr indexValuesBlob; @@ -22327,7 +22331,8 @@ UpdateIndexDataValuesFunction::OnFunctionCall(mozIStorageValueArray* aValues, MOZ_ALWAYS_TRUE( indexValues.InsertElementSorted(IndexDataValue(metadata.id(), metadata.unique(), - info.value()))); + info.value()), + fallible)); } } diff --git a/toolkit/components/url-classifier/ChunkSet.cpp b/toolkit/components/url-classifier/ChunkSet.cpp index 2549b0e0e697..8e0e20dcb44d 100644 --- a/toolkit/components/url-classifier/ChunkSet.cpp +++ b/toolkit/components/url-classifier/ChunkSet.cpp @@ -41,7 +41,7 @@ ChunkSet::Set(uint32_t aChunk) { size_t idx = mChunks.BinaryIndexOf(aChunk); if (idx == nsTArray::NoIndex) { - if (!mChunks.InsertElementSorted(aChunk)) { + if (!mChunks.InsertElementSorted(aChunk, fallible)) { return NS_ERROR_OUT_OF_MEMORY; } } From 2db38a1d84f567b542ae09c5601864c5515b4d19 Mon Sep 17 00:00:00 2001 From: Birunthan Mohanathas Date: Tue, 9 Jun 2015 17:27:31 -0700 Subject: [PATCH 25/95] Bug 968520 - Add more fallible variants of nsTArray::InsertElementsAt. r=froydnj --- xpcom/glue/nsTArray.h | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/xpcom/glue/nsTArray.h b/xpcom/glue/nsTArray.h index 492ed9a24691..e45bd41ed575 100644 --- a/xpcom/glue/nsTArray.h +++ b/xpcom/glue/nsTArray.h @@ -1292,19 +1292,37 @@ public: } // A variation on the ReplaceElementsAt method defined above. - template + template elem_type* InsertElementsAt(index_type aIndex, const Item* aArray, size_type aArrayLen) { - return ReplaceElementsAt(aIndex, 0, aArray, aArrayLen); + return ReplaceElementsAt(aIndex, 0, aArray, aArrayLen); + } + + template + /* MOZ_WARN_UNUSED_RESULT */ + elem_type* InsertElementsAt(index_type aIndex, const Item* aArray, + size_type aArrayLen, const mozilla::fallible_t&) + { + return InsertElementsAt(aIndex, aArray, aArrayLen); } // A variation on the ReplaceElementsAt method defined above. - template + template elem_type* InsertElementsAt(index_type aIndex, const nsTArray_Impl& aArray) { - return ReplaceElementsAt(aIndex, 0, aArray.Elements(), aArray.Length()); + return ReplaceElementsAt( + aIndex, 0, aArray.Elements(), aArray.Length()); + } + + template + /* MOZ_WARN_UNUSED_RESULT */ + elem_type* InsertElementsAt(index_type aIndex, + const nsTArray_Impl& aArray, + const mozilla::fallible_t&) + { + return InsertElementsAt(aIndex, aArray); } // Insert a new element without copy-constructing. This is useful to avoid From eb5db88588f1231a5a77831c85bc55657ab3fbdd Mon Sep 17 00:00:00 2001 From: Birunthan Mohanathas Date: Tue, 9 Jun 2015 17:27:35 -0700 Subject: [PATCH 26/95] Bug 968520 - Add mozilla::fallible to more FallibleTArray::InsertElementsAt calls. r=froydnj --- dom/media/MediaData.cpp | 3 ++- dom/network/TCPSocketChild.cpp | 3 ++- dom/network/TCPSocketParent.cpp | 2 +- dom/network/UDPSocketChild.cpp | 2 +- dom/network/UDPSocketParent.cpp | 2 +- dom/svg/DOMSVGPathSegList.cpp | 3 ++- netwerk/base/nsUDPSocket.cpp | 4 ++-- 7 files changed, 11 insertions(+), 8 deletions(-) diff --git a/dom/media/MediaData.cpp b/dom/media/MediaData.cpp index 484b56396db6..8b02108c19fe 100644 --- a/dom/media/MediaData.cpp +++ b/dom/media/MediaData.cpp @@ -639,7 +639,8 @@ MediaRawDataWriter::Prepend(const uint8_t* aData, size_t aSize) } // We ensure sufficient capacity above so this shouldn't fail. - MOZ_ALWAYS_TRUE(mBuffer->InsertElementsAt(mTarget->mPadding, aData, aSize)); + MOZ_ALWAYS_TRUE(mBuffer->InsertElementsAt(mTarget->mPadding, aData, aSize, + fallible)); mTarget->mSize += aSize; mSize = mTarget->mSize; return true; diff --git a/dom/network/TCPSocketChild.cpp b/dom/network/TCPSocketChild.cpp index 4668120ccd4e..b4fa4d26d8ed 100644 --- a/dom/network/TCPSocketChild.cpp +++ b/dom/network/TCPSocketChild.cpp @@ -237,7 +237,8 @@ TCPSocketChild::SendSend(JS::Handle aData, if (!data) { return NS_ERROR_OUT_OF_MEMORY; } - if (!fallibleArr.InsertElementsAt(0, data + aByteOffset, nbytes)) { + if (!fallibleArr.InsertElementsAt(0, data + aByteOffset, nbytes, + fallible)) { return NS_ERROR_OUT_OF_MEMORY; } } diff --git a/dom/network/TCPSocketParent.cpp b/dom/network/TCPSocketParent.cpp index 539653b628c7..2f0557c785d4 100644 --- a/dom/network/TCPSocketParent.cpp +++ b/dom/network/TCPSocketParent.cpp @@ -311,7 +311,7 @@ TCPSocketParent::SendEvent(const nsAString& aType, JS::Handle aDataVa errLine = __LINE__; break; } - if (!fallibleArr.InsertElementsAt(0, buffer, nbytes)) { + if (!fallibleArr.InsertElementsAt(0, buffer, nbytes, fallible)) { errLine = __LINE__; break; } diff --git a/dom/network/UDPSocketChild.cpp b/dom/network/UDPSocketChild.cpp index 5b73dbf2b0a4..e53d5cd3c6a3 100644 --- a/dom/network/UDPSocketChild.cpp +++ b/dom/network/UDPSocketChild.cpp @@ -249,7 +249,7 @@ UDPSocketChild::SendDataInternal(const UDPSocketAddr& aAddr, NS_ENSURE_ARG(aData); FallibleTArray fallibleArray; - if (!fallibleArray.InsertElementsAt(0, aData, aByteLength)) { + if (!fallibleArray.InsertElementsAt(0, aData, aByteLength, fallible)) { return NS_ERROR_OUT_OF_MEMORY; } diff --git a/dom/network/UDPSocketParent.cpp b/dom/network/UDPSocketParent.cpp index 51cb792dc09a..9c1aac048cf1 100644 --- a/dom/network/UDPSocketParent.cpp +++ b/dom/network/UDPSocketParent.cpp @@ -451,7 +451,7 @@ UDPSocketParent::OnPacketReceived(nsIUDPSocket* aSocket, nsIUDPMessage* aMessage } FallibleTArray fallibleArray; - if (!fallibleArray.InsertElementsAt(0, buffer, len)) { + if (!fallibleArray.InsertElementsAt(0, buffer, len, fallible)) { FireInternalError(__LINE__); return NS_ERROR_OUT_OF_MEMORY; } diff --git a/dom/svg/DOMSVGPathSegList.cpp b/dom/svg/DOMSVGPathSegList.cpp index 371ca9e4d7aa..0a0c28f730bc 100644 --- a/dom/svg/DOMSVGPathSegList.cpp +++ b/dom/svg/DOMSVGPathSegList.cpp @@ -385,7 +385,8 @@ DOMSVGPathSegList::InsertItemBefore(DOMSVGPathSeg& aNewItem, MOZ_ALWAYS_TRUE(InternalList().mData.InsertElementsAt(internalIndex, segAsRaw, - 1 + argCount)); + 1 + argCount, + fallible)); MOZ_ALWAYS_TRUE(mItems.InsertElementAt(aIndex, ItemProxy(domItem.get(), internalIndex), diff --git a/netwerk/base/nsUDPSocket.cpp b/netwerk/base/nsUDPSocket.cpp index 4bc0b9f3ddfa..7cea95aa75c6 100644 --- a/netwerk/base/nsUDPSocket.cpp +++ b/netwerk/base/nsUDPSocket.cpp @@ -1311,7 +1311,7 @@ nsUDPSocket::Send(const nsACString &aHost, uint16_t aPort, *_retval = 0; FallibleTArray fallibleArray; - if (!fallibleArray.InsertElementsAt(0, aData, aDataLength)) { + if (!fallibleArray.InsertElementsAt(0, aData, aDataLength, fallible)) { return NS_ERROR_OUT_OF_MEMORY; } @@ -1369,7 +1369,7 @@ nsUDPSocket::SendWithAddress(const NetAddr *aAddr, const uint8_t *aData, *_retval = count; } else { FallibleTArray fallibleArray; - if (!fallibleArray.InsertElementsAt(0, aData, aDataLength)) { + if (!fallibleArray.InsertElementsAt(0, aData, aDataLength, fallible)) { return NS_ERROR_OUT_OF_MEMORY; } From ad90bd664ad88f54da3d41f6e0b42a4f21e8ec7c Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Fri, 5 Jun 2015 13:59:05 +0900 Subject: [PATCH 27/95] Bug 985857 - Automatically log mach output and add a command to display it. r=gps --- python/mozbuild/mozbuild/base.py | 14 +++++ python/mozbuild/mozbuild/mach_commands.py | 62 +++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/python/mozbuild/mozbuild/base.py b/python/mozbuild/mozbuild/base.py index 7dde8004aac7..e5f29bf6227b 100644 --- a/python/mozbuild/mozbuild/base.py +++ b/python/mozbuild/mozbuild/base.py @@ -700,6 +700,20 @@ class MachCommandBase(MozbuildObject): sys.exit(1) + # Always keep a log of the last command, but don't do that for mach + # invokations from scripts (especially not the ones done by the build + # system itself). + if (self.log_manager and self.log_manager.terminal and + not getattr(self, 'NO_AUTO_LOG', False)): + self._ensure_state_subdir_exists('.') + logfile = self._get_state_filename('last_log.json') + try: + fd = open(logfile, "wb") + self.log_manager.add_json_handler(fd) + except Exception as e: + self.log(logging.WARNING, 'mach', {'error': e}, + 'Log will not be kept for this command: {error}.') + class MachCommandConditions(object): """A series of commonly used condition functions which can be applied to diff --git a/python/mozbuild/mozbuild/mach_commands.py b/python/mozbuild/mozbuild/mach_commands.py index d2cd24dc5a12..f62374f8ee34 100644 --- a/python/mozbuild/mozbuild/mach_commands.py +++ b/python/mozbuild/mozbuild/mach_commands.py @@ -4,10 +4,13 @@ from __future__ import print_function, unicode_literals +import argparse import itertools +import json import logging import operator import os +import subprocess import sys import mozpack.path as mozpath @@ -566,6 +569,65 @@ class Doctor(MachCommandBase): doctor = Doctor(self.topsrcdir, self.topobjdir, fix) return doctor.check_all() +@CommandProvider +class Logs(MachCommandBase): + """Provide commands to read mach logs.""" + NO_AUTO_LOG = True + + @Command('show-log', category='post-build', + description='Display mach logs') + @CommandArgument('log_file', nargs='?', type=argparse.FileType('rb'), + help='Filename to read log data from. Defaults to the log of the last ' + 'mach command.') + def show_log(self, log_file=None): + if not log_file: + path = self._get_state_filename('last_log.json') + log_file = open(path, 'rb') + + if self.log_manager.terminal: + env = dict(os.environ) + if 'LESS' not in env: + # Sensible default flags if none have been set in the user + # environment. + env['LESS'] = 'FRX' + less = subprocess.Popen(['less'], stdin=subprocess.PIPE, env=env) + # Various objects already have a reference to sys.stdout, so we + # can't just change it, we need to change the file descriptor under + # it to redirect to less's input. + # First keep a copy of the sys.stdout file descriptor. + output_fd = os.dup(sys.stdout.fileno()) + os.dup2(less.stdin.fileno(), sys.stdout.fileno()) + + startTime = 0 + for line in log_file: + created, action, params = json.loads(line) + if not startTime: + startTime = created + self.log_manager.terminal_handler.formatter.start_time = \ + created + if 'line' in params: + record = logging.makeLogRecord({ + 'created': created, + 'name': self._logger.name, + 'levelno': logging.INFO, + 'msg': '{line}', + 'params': params, + 'action': action, + }) + self._logger.handle(record) + + if self.log_manager.terminal: + # Close less's input so that it knows that we're done sending data. + less.stdin.close() + # Since the less's input file descriptor is now also the stdout + # file descriptor, we still actually have a non-closed system file + # descriptor for less's input. Replacing sys.stdout's file + # descriptor with what it was before we replaced it will properly + # close less's input. + os.dup2(output_fd, sys.stdout.fileno()) + less.wait() + + @CommandProvider class Warnings(MachCommandBase): """Provide commands for inspecting warnings.""" From 0d786e205704c9daf1b6e2e6e1c7cc78c9e8b3c0 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Thu, 4 Jun 2015 17:24:13 +0900 Subject: [PATCH 28/95] Bug 1172800 - Fixup after bug 991983. r=gps --- python/mozbuild/mozbuild/frontend/sandbox.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/mozbuild/mozbuild/frontend/sandbox.py b/python/mozbuild/mozbuild/frontend/sandbox.py index 43587acc496b..2803a2c57487 100644 --- a/python/mozbuild/mozbuild/frontend/sandbox.py +++ b/python/mozbuild/mozbuild/frontend/sandbox.py @@ -213,7 +213,7 @@ class Sandbox(dict): raise SandboxExecutionError(source_stack, exc[0], exc[1], exc[2]) finally: self._context._sandbox = old_sandbox - if path: + if path and becomes_current_path: self._context.pop_source() def push_subcontext(self, context): From 17363f4d4e1dd97d7610bc13deecfd1618d23738 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Wed, 6 May 2015 11:45:24 +0900 Subject: [PATCH 29/95] Bug 1172800 - Move moz.build template handling in a separate class. r=gps This will make subsequent refactorings a bit more intelligible. --- python/mozbuild/mozbuild/frontend/reader.py | 195 ++++++++++---------- 1 file changed, 99 insertions(+), 96 deletions(-) diff --git a/python/mozbuild/mozbuild/frontend/reader.py b/python/mozbuild/mozbuild/frontend/reader.py index 712092033ce2..acd4d14f917c 100644 --- a/python/mozbuild/mozbuild/frontend/reader.py +++ b/python/mozbuild/mozbuild/frontend/reader.py @@ -198,7 +198,7 @@ class MozbuildSandbox(Sandbox): if key in self.subcontext_types: return self._create_subcontext(self.subcontext_types[key]) if key in self.templates: - return self._create_template_function(self.templates[key]) + return self._create_template_wrapper(self.templates[key]) return Sandbox.__getitem__(self, key) def __setitem__(self, key, value): @@ -308,14 +308,7 @@ class MozbuildSandbox(Sandbox): raise SandboxCalledError(self._context.source_stack, message) def _template_decorator(self, func): - """Registers template as expected by _create_template_function. - - The template data consists of: - - the function object as it comes from the sandbox evaluation of the - template declaration. - - its code, modified as described in the comments of this method. - - the path of the file containing the template definition. - """ + """Registers a template function.""" if not inspect.isfunction(func): raise Exception('`template` is a function decorator. You must ' @@ -326,11 +319,99 @@ class MozbuildSandbox(Sandbox): if name in self.templates: raise KeyError( 'A template named "%s" was already declared in %s.' % (name, - self.templates[name][2])) + self.templates[name].path)) if name.islower() or name.isupper() or name[0].islower(): raise NameError('Template function names must be CamelCase.') + self.templates[name] = TemplateFunction(func) + + @memoize + def _create_subcontext(self, cls): + """Return a function object that creates SubContext instances.""" + def fn(*args, **kwargs): + return cls(self._context, *args, **kwargs) + + return fn + + @memoize + def _create_function(self, function_def): + """Returns a function object for use within the sandbox for the given + function definition. + + The wrapper function does type coercion on the function arguments + """ + func, args_def, doc = function_def + def function(*args): + def coerce(arg, type): + if not isinstance(arg, type): + if issubclass(type, ContextDerivedValue): + arg = type(self._context, arg) + else: + arg = type(arg) + return arg + args = [coerce(arg, type) for arg, type in zip(args, args_def)] + return func(self)(*args) + + return function + + @memoize + def _create_template_wrapper(self, template): + """Returns a function object for use within the sandbox for the given + TemplateFunction instance.. + + When a moz.build file contains a reference to a template call, the + sandbox needs a function to execute. This is what this method returns. + That function creates a new sandbox for execution of the template. + After the template is executed, the data from its execution is merged + with the context of the calling sandbox. + """ + def template_wrapper(*args, **kwargs): + context = TemplateContext( + template=template.name, + allowed_variables=self._context._allowed_variables, + config=self._context.config) + context.add_source(self._context.current_path) + for p in self._context.all_paths: + context.add_source(p) + + sandbox = MozbuildSandbox(context, metadata={ + # We should arguably set these defaults to something else. + # Templates, for example, should arguably come from the state + # of the sandbox from when the template was declared, not when + # it was instantiated. Bug 1137319. + 'functions': self.metadata.get('functions', {}), + 'special_variables': self.metadata.get('special_variables', {}), + 'subcontexts': self.metadata.get('subcontexts', {}), + 'templates': self.metadata.get('templates', {}) + }) + template.exec_in_sandbox(sandbox, *args, **kwargs) + + # This is gross, but allows the merge to happen. Eventually, the + # merging will go away and template contexts emitted independently. + klass = self._context.__class__ + self._context.__class__ = TemplateContext + # The sandbox will do all the necessary checks for these merges. + for key, value in context.items(): + if isinstance(value, dict): + self[key].update(value) + elif isinstance(value, list): + self[key] += value + else: + self[key] = value + self._context.__class__ = klass + + for p in context.all_paths: + self._context.add_source(p) + + return template_wrapper + + +class TemplateFunction(object): + def __init__(self, func): + self.path = inspect.getfile(func) + self.name = func.func_name + lines, firstlineno = inspect.getsourcelines(func) first_op = None generator = tokenize.generate_tokens(iter(lines).next) @@ -363,95 +444,17 @@ class MozbuildSandbox(Sandbox): # (this is simpler than trying to deindent the function body) # So we need to prepend with n - 1 newlines so that line numbers # are unchanged. - code = '\n' * (firstlineno + begin[0] - 3) + 'if True:\n' - code += ''.join(lines[begin[0] - 1:]) + self._code = '\n' * (firstlineno + begin[0] - 3) + 'if True:\n' + self._code += ''.join(lines[begin[0] - 1:]) + self._func = func - self.templates[name] = func, code, self._context.current_path + def exec_in_sandbox(self, sandbox, *args, **kwargs): + """Executes the template function in the given sandbox.""" - @memoize - def _create_subcontext(self, cls): - """Return a function object that creates SubContext instances.""" - def fn(*args, **kwargs): - return cls(self._context, *args, **kwargs) + for k, v in inspect.getcallargs(self._func, *args, **kwargs).items(): + sandbox[k] = v - return fn - - @memoize - def _create_function(self, function_def): - """Returns a function object for use within the sandbox for the given - function definition. - - The wrapper function does type coercion on the function arguments - """ - func, args_def, doc = function_def - def function(*args): - def coerce(arg, type): - if not isinstance(arg, type): - if issubclass(type, ContextDerivedValue): - arg = type(self._context, arg) - else: - arg = type(arg) - return arg - args = [coerce(arg, type) for arg, type in zip(args, args_def)] - return func(self)(*args) - - return function - - @memoize - def _create_template_function(self, template): - """Returns a function object for use within the sandbox for the given - template. - - When a moz.build file contains a reference to a template call, the - sandbox needs a function to execute. This is what this method returns. - That function creates a new sandbox for execution of the template. - After the template is executed, the data from its execution is merged - with the context of the calling sandbox. - """ - func, code, path = template - - def template_function(*args, **kwargs): - context = TemplateContext( - template=func.func_name, - allowed_variables=self._context._allowed_variables, - config=self._context.config) - context.add_source(self._context.current_path) - for p in self._context.all_paths: - context.add_source(p) - - sandbox = MozbuildSandbox(context, metadata={ - # We should arguably set these defaults to something else. - # Templates, for example, should arguably come from the state - # of the sandbox from when the template was declared, not when - # it was instantiated. Bug 1137319. - 'functions': self.metadata.get('functions', {}), - 'special_variables': self.metadata.get('special_variables', {}), - 'subcontexts': self.metadata.get('subcontexts', {}), - 'templates': self.metadata.get('templates', {}) - }) - for k, v in inspect.getcallargs(func, *args, **kwargs).items(): - sandbox[k] = v - - sandbox.exec_source(code, path, becomes_current_path=False) - - # This is gross, but allows the merge to happen. Eventually, the - # merging will go away and template contexts emitted independently. - klass = self._context.__class__ - self._context.__class__ = TemplateContext - # The sandbox will do all the necessary checks for these merges. - for key, value in context.items(): - if isinstance(value, dict): - self[key].update(value) - elif isinstance(value, list): - self[key] += value - else: - self[key] = value - self._context.__class__ = klass - - for p in context.all_paths: - self._context.add_source(p) - - return template_function + sandbox.exec_source(self._code, self.path, becomes_current_path=False) class SandboxValidationError(Exception): From e7ceb2bd70e9239a86c97d2c81a55e855b091d94 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Tue, 9 Jun 2015 15:18:39 +0900 Subject: [PATCH 30/95] Bug 1172800 - Avoid using inspect.getsourcelines() and inspect.getfile(). r=gps inspect.getsourcelines() and inspect.getfile() involve I/O out of our control. Our use of those functions, however, doesn't require all their smarts. In fact, we only use them on function objects, for which we can just do the work ourselves without involving inspect functions that trigger I/O. --- python/mozbuild/mozbuild/frontend/reader.py | 10 ++++++---- python/mozbuild/mozbuild/frontend/sandbox.py | 6 ++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/python/mozbuild/mozbuild/frontend/reader.py b/python/mozbuild/mozbuild/frontend/reader.py index acd4d14f917c..58572e8e8725 100644 --- a/python/mozbuild/mozbuild/frontend/reader.py +++ b/python/mozbuild/mozbuild/frontend/reader.py @@ -324,7 +324,7 @@ class MozbuildSandbox(Sandbox): if name.islower() or name.isupper() or name[0].islower(): raise NameError('Template function names must be CamelCase.') - self.templates[name] = TemplateFunction(func) + self.templates[name] = TemplateFunction(func, self) @memoize def _create_subcontext(self, cls): @@ -408,11 +408,13 @@ class MozbuildSandbox(Sandbox): class TemplateFunction(object): - def __init__(self, func): - self.path = inspect.getfile(func) + def __init__(self, func, sandbox): + self.path = func.func_code.co_filename self.name = func.func_name - lines, firstlineno = inspect.getsourcelines(func) + firstlineno = func.func_code.co_firstlineno + lines = sandbox._current_source.splitlines(True) + lines = inspect.getblock(lines[firstlineno - 1:]) first_op = None generator = tokenize.generate_tokens(iter(lines).next) # Find the first indent token in the source of this template function, diff --git a/python/mozbuild/mozbuild/frontend/sandbox.py b/python/mozbuild/mozbuild/frontend/sandbox.py index 2803a2c57487..d77a4594c8ac 100644 --- a/python/mozbuild/mozbuild/frontend/sandbox.py +++ b/python/mozbuild/mozbuild/frontend/sandbox.py @@ -129,6 +129,9 @@ class Sandbox(dict): # evaluation. self._last_name_error = None + # Current literal source being executed. + self._current_source = None + @property def _context(self): return self._active_contexts[-1] @@ -171,6 +174,8 @@ class Sandbox(dict): # too low-level for that. However, we could add bytecode generation via # the marshall module if parsing performance were ever an issue. + old_source = self._current_source + self._current_source = source try: # compile() inherits the __future__ from the module by default. We # do want Unicode literals. @@ -212,6 +217,7 @@ class Sandbox(dict): source_stack.append(path) raise SandboxExecutionError(source_stack, exc[0], exc[1], exc[2]) finally: + self._current_source = old_source self._context._sandbox = old_sandbox if path and becomes_current_path: self._context.pop_source() From 0a4831d9453536f7d3030bd761ca837d5b0ac8d0 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Thu, 4 Jun 2015 16:04:34 +0900 Subject: [PATCH 31/95] Bug 1172800 - Create actual functions to execute moz.build templates. r=gps The current mode of execution of templates doesn't allow them to more advanced control flow, like returning early, returning or yielding values, because that mode of execution is equivalent to running the code at the top level of a .py file. Making the templates executed through a function call, although trickier, allows those control flows, which will be useful for template as context managers. --- python/mozbuild/mozbuild/frontend/reader.py | 131 +++++++++++++------ python/mozbuild/mozbuild/frontend/sandbox.py | 40 ++++-- 2 files changed, 122 insertions(+), 49 deletions(-) diff --git a/python/mozbuild/mozbuild/frontend/reader.py b/python/mozbuild/mozbuild/frontend/reader.py index 58572e8e8725..8c281728ec69 100644 --- a/python/mozbuild/mozbuild/frontend/reader.py +++ b/python/mozbuild/mozbuild/frontend/reader.py @@ -201,6 +201,13 @@ class MozbuildSandbox(Sandbox): return self._create_template_wrapper(self.templates[key]) return Sandbox.__getitem__(self, key) + def __contains__(self, key): + if any(key in d for d in (self.special_variables, self.functions, + self.subcontext_types, self.templates)): + return True + + return Sandbox.__contains__(self, key) + def __setitem__(self, key, value): if key in self.special_variables or key in self.functions or key in self.subcontext_types: raise KeyError('Cannot set "%s" because it is a reserved keyword' @@ -412,51 +419,97 @@ class TemplateFunction(object): self.path = func.func_code.co_filename self.name = func.func_name - firstlineno = func.func_code.co_firstlineno + code = func.func_code + firstlineno = code.co_firstlineno lines = sandbox._current_source.splitlines(True) lines = inspect.getblock(lines[firstlineno - 1:]) - first_op = None - generator = tokenize.generate_tokens(iter(lines).next) - # Find the first indent token in the source of this template function, - # which corresponds to the beginning of the function body. - for typ, s, begin, end, line in generator: - if typ == tokenize.OP: - first_op = True - if first_op and typ == tokenize.INDENT: - break - if typ != tokenize.INDENT: - # This should never happen. - raise Exception('Could not find the first line of the template %s' % - func.func_name) - # The code of the template in moz.build looks like this: - # m def Foo(args): - # n FOO = 'bar' - # n+1 (...) - # - # where, - # - m is firstlineno - 1, - # - n is usually m + 1, but in case the function signature takes more - # lines, is really m + begin[0] - 1 - # - # We want that to be replaced with: - # m if True: - # n FOO = 'bar' - # n+1 (...) - # - # (this is simpler than trying to deindent the function body) - # So we need to prepend with n - 1 newlines so that line numbers - # are unchanged. - self._code = '\n' * (firstlineno + begin[0] - 3) + 'if True:\n' - self._code += ''.join(lines[begin[0] - 1:]) - self._func = func + + # The code lines we get out of inspect.getsourcelines look like + # @template + # def Template(*args, **kwargs): + # VAR = 'value' + # ... + func_ast = ast.parse(''.join(lines), self.path) + # Remove decorators + func_ast.body[0].decorator_list = [] + # Adjust line numbers accordingly + ast.increment_lineno(func_ast, firstlineno - 1) + + # When using a custom dictionary for function globals/locals, Cpython + # actually never calls __getitem__ and __setitem__, so we need to + # modify the AST so that accesses to globals are properly directed + # to a dict. + self._global_name = b'_data' # AST wants str for this, not unicode + # In case '_data' is a name used for a variable in the function code, + # prepend more underscores until we find an unused name. + while (self._global_name in code.co_names or + self._global_name in code.co_varnames): + self._global_name += '_' + func_ast = self.RewriteName(sandbox, self._global_name).visit(func_ast) + + # Execute the rewritten code. That code now looks like: + # def Template(*args, **kwargs): + # _data['VAR'] = 'value' + # ... + # The result of executing this code is the creation of a 'Template' + # function object in the global namespace. + glob = {'__builtins__': sandbox._builtins} + func = types.FunctionType( + compile(func_ast, self.path, 'exec'), + glob, + self.name, + func.func_defaults, + func.func_closure, + ) + func() + + self._func = glob[self.name] def exec_in_sandbox(self, sandbox, *args, **kwargs): """Executes the template function in the given sandbox.""" + # Create a new function object associated with the execution sandbox + glob = { + self._global_name: sandbox, + '__builtins__': sandbox._builtins + } + func = types.FunctionType( + self._func.func_code, + glob, + self.name, + self._func.func_defaults, + self._func.func_closure + ) + sandbox.exec_function(func, args, kwargs, self.path, + becomes_current_path=False) - for k, v in inspect.getcallargs(self._func, *args, **kwargs).items(): - sandbox[k] = v + class RewriteName(ast.NodeTransformer): + """AST Node Transformer to rewrite variable accesses to go through + a dict. + """ + def __init__(self, sandbox, global_name): + self._sandbox = sandbox + self._global_name = global_name - sandbox.exec_source(self._code, self.path, becomes_current_path=False) + def visit_Str(self, node): + # String nodes we got from the AST parser are str, but we want + # unicode literals everywhere, so transform them. + node.s = unicode(node.s) + return node + + def visit_Name(self, node): + # Modify uppercase variable references and names known to the + # sandbox as if they were retrieved from a dict instead. + if not node.id.isupper() and node.id not in self._sandbox: + return node + + def c(new_node): + return ast.copy_location(new_node, node) + + return c(ast.Subscript( + value=c(ast.Name(id=self._global_name, ctx=ast.Load())), + slice=c(ast.Index(value=c(ast.Str(s=node.id)))), + ctx=node.ctx + )) class SandboxValidationError(Exception): @@ -594,7 +647,7 @@ class BuildReaderError(Exception): # Reset if we enter a new execution context. This prevents errors # in this module from being attributes to a script. - elif frame[0] == __file__ and frame[2] == 'exec_source': + elif frame[0] == __file__ and frame[2] == 'exec_function': script_frame = None if script_frame is not None: diff --git a/python/mozbuild/mozbuild/frontend/sandbox.py b/python/mozbuild/mozbuild/frontend/sandbox.py index d77a4594c8ac..83f951de0e24 100644 --- a/python/mozbuild/mozbuild/frontend/sandbox.py +++ b/python/mozbuild/mozbuild/frontend/sandbox.py @@ -154,7 +154,7 @@ class Sandbox(dict): self.exec_source(source, path) - def exec_source(self, source, path='', becomes_current_path=True): + def exec_source(self, source, path=''): """Execute Python code within a string. The passed string should contain Python code to be executed. The string @@ -164,6 +164,30 @@ class Sandbox(dict): does not perform extra path normalization. This can cause relative paths to behave weirdly. """ + def execute(): + # compile() inherits the __future__ from the module by default. We + # do want Unicode literals. + code = compile(source, path, 'exec') + # We use ourself as the global namespace for the execution. There + # is no need for a separate local namespace as moz.build execution + # is flat, namespace-wise. + old_source = self._current_source + self._current_source = source + try: + # Ideally, we'd use exec(code, self), but that yield the + # following error: + # SyntaxError: unqualified exec is not allowed in function + # 'execute' it is a nested function. + exec code in self + finally: + self._current_source = old_source + + self.exec_function(execute, path=path) + + def exec_function(self, func, args=(), kwargs={}, path='', + becomes_current_path=True): + """Execute function with the given arguments in the sandbox. + """ if path and becomes_current_path: self._context.push_source(path) @@ -175,15 +199,9 @@ class Sandbox(dict): # the marshall module if parsing performance were ever an issue. old_source = self._current_source - self._current_source = source + self._current_source = None try: - # compile() inherits the __future__ from the module by default. We - # do want Unicode literals. - code = compile(source, path, 'exec') - # We use ourself as the global namespace for the execution. There - # is no need for a separate local namespace as moz.build execution - # is flat, namespace-wise. - exec(code, self) + func(*args, **kwargs) except SandboxError as e: raise e except NameError as e: @@ -282,4 +300,6 @@ class Sandbox(dict): raise NotImplementedError('Not supported') def __contains__(self, key): - raise NotImplementedError('Not supported') + if key.isupper(): + return key in self._context + return dict.__contains__(self, key) From e93602d2bc99951bbb6eae2a2adc7438abc293eb Mon Sep 17 00:00:00 2001 From: Chris Manchester Date: Tue, 9 Jun 2015 17:37:02 -0700 Subject: [PATCH 32/95] Bug 1173026 - Fix typo in path to taskcluster build definition.;r=mrrrgn --HG-- extra : commitid : 8Zt3iECdDiA --- testing/taskcluster/tasks/builds/dbg_linux64.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/taskcluster/tasks/builds/dbg_linux64.yml b/testing/taskcluster/tasks/builds/dbg_linux64.yml index 779df30deb8c..2cdccd84770d 100644 --- a/testing/taskcluster/tasks/builds/dbg_linux64.yml +++ b/testing/taskcluster/tasks/builds/dbg_linux64.yml @@ -1,5 +1,5 @@ $inherits: - from: 'tasks/opt_linux64.yml' + from: 'tasks/builds/opt_linux64.yml' variables: build_name: 'linux64' build_type: 'dbg' From 7c8e569eaf33156dac3f27cddf520bd310cafb84 Mon Sep 17 00:00:00 2001 From: Chris Manchester Date: Thu, 28 May 2015 15:57:21 -0700 Subject: [PATCH 33/95] Bug 1149670 - Add a mach command to find tests in specified directories and prepare a commit to push them to try.;r=ahal --HG-- extra : commitid : EDP1u6cliJy --- build/mach_bootstrap.py | 1 + testing/mach_commands.py | 111 +++++++++++++++++++++++++ testing/tools/autotry/__init__.py | 0 testing/tools/autotry/autotry.py | 134 ++++++++++++++++++++++++++++++ 4 files changed, 246 insertions(+) create mode 100644 testing/tools/autotry/__init__.py create mode 100644 testing/tools/autotry/autotry.py diff --git a/build/mach_bootstrap.py b/build/mach_bootstrap.py index c57530d07138..db61fa02b831 100644 --- a/build/mach_bootstrap.py +++ b/build/mach_bootstrap.py @@ -47,6 +47,7 @@ SEARCH_PATHS = [ 'other-licenses/ply', 'xpcom/idl-parser', 'testing', + 'testing/tools/autotry', 'testing/taskcluster', 'testing/xpcshell', 'testing/web-platform', diff --git a/testing/mach_commands.py b/testing/mach_commands.py index aa4c1a929f06..1a13f1a58430 100644 --- a/testing/mach_commands.py +++ b/testing/mach_commands.py @@ -5,6 +5,7 @@ from __future__ import print_function, unicode_literals import os +import pprint import sys from mach.decorators import ( @@ -13,6 +14,7 @@ from mach.decorators import ( Command, ) +from autotry import AutoTry from mozbuild.base import MachCommandBase @@ -360,3 +362,112 @@ class JsapiTestsCommand(MachCommandBase): jsapi_tests_result = subprocess.call(jsapi_tests_cmd) return jsapi_tests_result + + +AUTOTRY_HELP_MSG = """ +Autotry is in beta, please file bugs blocking 1149670. + +Push test from the specified paths to try. A set of test +jobs will be selected based on the tests present in the tree, however +specifying platforms is still required with the -p argument (a default +is taken from the AUTOTRY_PLATFORM_HINT environment variable if set). + +The -u argument may be used to specify additional unittest suites to run. + +Selected tests will be run in a single chunk of the relevant suite, at this +time in chunk 1. + +The following types of tests are eligible to be selected automatically +by this command at this time: %s +""" % list(AutoTry.test_flavors) + +@CommandProvider +class PushToTry(MachCommandBase): + + def validate_args(self, paths, tests, builds, platforms): + if not len(paths) and not tests: + print("Paths or tests must be specified as an argument to autotry.") + sys.exit(1) + + if platforms is None: + platforms = os.environ['AUTOTRY_PLATFORM_HINT'] + + for p in paths: + p = os.path.normpath(os.path.abspath(p)) + if not p.startswith(self.topsrcdir): + print('Specified path "%s" is outside of the srcdir, unable to' + ' specify tests outside of the srcdir' % p) + sys.exit(1) + if len(p) <= len(self.topsrcdir): + print('Specified path "%s" is at the top of the srcdir and would' + ' select all tests.' % p) + sys.exit(1) + + return builds, platforms + + @Command('try', category='testing', description=AUTOTRY_HELP_MSG) + @CommandArgument('paths', nargs='*', help='Paths to search for tests to run on try.') + @CommandArgument('-v', dest='verbose', action='store_true', default=True, + help='Print detailed information about the resulting test selection ' + 'and commands performed.') + @CommandArgument('-p', dest='platforms', required='AUTOTRY_PLATFORM_HINT' not in os.environ, + help='Platforms to run. (required if not found in the environment)') + @CommandArgument('-u', dest='tests', + help='Test jobs to run. These will be use in place of test jobs ' + 'determined by test paths, if any.') + @CommandArgument('--extra', dest='extra_tests', + help='Additional tests to run. These will be added to test jobs ' + 'determined by test paths, if any.') + @CommandArgument('-b', dest='builds', default='do', + help='Build types to run (d for debug, o for optimized)') + @CommandArgument('--tag', dest='tags', action='append', + help='Restrict tests to the given tag (may be specified multiple times)') + @CommandArgument('--no-push', dest='push', action='store_false', + help='Do not push to try as a result of running this command (if ' + 'specified this command will only print calculated try ' + 'syntax and selection info).') + def autotry(self, builds=None, platforms=None, paths=None, verbose=None, extra_tests=None, + push=None, tags=None, tests=None): + + from mozbuild.testing import TestResolver + from mozbuild.controller.building import BuildDriver + + print("mach try is under development, please file bugs blocking 1149670.") + + builds, platforms = self.validate_args(paths, tests, builds, platforms) + resolver = self._spawn(TestResolver) + + at = AutoTry(self.topsrcdir, resolver, self._mach_context) + if at.find_uncommited_changes(): + print('ERROR please commit changes before continuing') + sys.exit(1) + + driver = self._spawn(BuildDriver) + driver.install_tests(remove=False) + + manifests_by_flavor = at.manifests_by_flavor(paths) + + if not manifests_by_flavor and not tests: + print("No tests were found when attempting to resolve paths:\n\n\t%s" % + paths) + sys.exit(1) + + all_manifests = set() + for m in manifests_by_flavor.values(): + all_manifests |= m + all_manifests = list(all_manifests) + + msg = at.calc_try_syntax(platforms, manifests_by_flavor.keys(), tests, + extra_tests, builds, all_manifests, tags) + + if verbose: + print('Tests from the following manifests will be selected: ') + pprint.pprint(manifests_by_flavor) + + if verbose: + print('The following try message was calculated:\n\n\t%s\n' % msg) + + if push: + at.push_to_try(msg, verbose) + + return diff --git a/testing/tools/autotry/__init__.py b/testing/tools/autotry/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/testing/tools/autotry/autotry.py b/testing/tools/autotry/autotry.py new file mode 100644 index 000000000000..0bf2d0bab283 --- /dev/null +++ b/testing/tools/autotry/autotry.py @@ -0,0 +1,134 @@ +# 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 sys +import os +import itertools +import subprocess +import which + +from collections import defaultdict + + +TRY_SYNTAX_TMPL = """ +try: -b %s -p %s -u %s -t none %s %s +""" + +class AutoTry(object): + + test_flavors = [ + 'browser-chrome', + 'chrome', + 'devtools-chrome', + 'mochitest', + 'xpcshell', + 'reftest', + 'crashtest', + ] + + def __init__(self, topsrcdir, resolver, mach_context): + self.topsrcdir = topsrcdir + self.resolver = resolver + self.mach_context = mach_context + + if os.path.exists(os.path.join(self.topsrcdir, '.hg')): + self._use_git = False + else: + self._use_git = True + + def manifests_by_flavor(self, paths): + manifests_by_flavor = defaultdict(set) + + if not paths: + return dict(manifests_by_flavor) + + tests = list(self.resolver.resolve_tests(paths=paths, + cwd=self.mach_context.cwd)) + for t in tests: + if t['flavor'] in AutoTry.test_flavors: + flavor = t['flavor'] + if 'subsuite' in t and t['subsuite'] == 'devtools': + flavor = 'devtools-chrome' + manifest = os.path.relpath(t['manifest'], self.topsrcdir) + manifests_by_flavor[flavor].add(manifest) + + return dict(manifests_by_flavor) + + def calc_try_syntax(self, platforms, flavors, tests, extra_tests, builds, + manifests, tags): + + # Maps from flavors to the try syntax snippets implied by that flavor. + # TODO: put selected tests under their own builder/label to avoid + # confusion reading results on treeherder. + flavor_suites = { + 'mochitest': ['mochitest-1', 'mochitest-e10s-1'], + 'xpcshell': ['xpcshell'], + 'chrome': ['mochitest-o'], + 'browser-chrome': ['mochitest-browser-chrome-1', + 'mochitest-e10s-browser-chrome-1'], + 'devtools-chrome': ['mochitest-dt', + 'mochitest-e10s-devtools-chrome'], + 'crashtest': ['crashtest', 'crashtest-e10s'], + 'reftest': ['reftest', 'reftest-e10s'], + } + + if tags: + tags = ' '.join('--tag %s' % t for t in tags) + else: + tags = '' + + if not tests: + tests = ','.join(itertools.chain(*(flavor_suites[f] for f in flavors))) + if extra_tests: + tests += ',%s' % (extra_tests) + + manifests = ' '.join(manifests) + if manifests: + manifests = '--try-test-paths %s' % manifests + return TRY_SYNTAX_TMPL % (builds, platforms, tests, manifests, tags) + + def _run_git(self, *args): + args = ['git'] + list(args) + ret = subprocess.call(args) + if ret: + print('ERROR git command %s returned %s' % + (args, ret)) + sys.exit(1) + + def _git_push_to_try(self, msg): + self._run_git('commit', '--allow-empty', '-m', msg) + self._run_git('push', 'hg::ssh://hg.mozilla.org/try', + '+HEAD:refs/heads/branches/default/tip') + self._run_git('reset', 'HEAD~') + + def push_to_try(self, msg, verbose): + if not self._use_git: + try: + hg_args = ['hg', 'push-to-try', '-m', msg] + subprocess.check_call(hg_args, stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as e: + print('ERROR hg command %s returned %s' % (hg_args, e.returncode)) + print('The "push-to-try" hg extension is required to push from ' + 'hg to try with the autotry command.\n\nIt can be installed ' + 'by running ./mach mercurial-setup') + sys.exit(1) + else: + try: + which.which('git-cinnabar') + self._git_push_to_try(msg) + except which.WhichError: + print('ERROR git-cinnabar is required to push from git to try with' + 'the autotry command.\n\nMore information can by found at ' + 'https://github.com/glandium/git-cinnabar') + sys.exit(1) + + def find_uncommited_changes(self): + if self._use_git: + stat = subprocess.check_output(['git', 'status', '-z']) + return any(len(entry.strip()) and entry.strip()[0] in ('A', 'M', 'D') + for entry in stat.split('\0')) + else: + stat = subprocess.check_output(['hg', 'status']) + return any(len(entry.strip()) and entry.strip()[0] in ('A', 'M', 'R') + for entry in stat.splitlines()) From 4d3dc04b596dee807d856e97363714dfb08e38c6 Mon Sep 17 00:00:00 2001 From: Eric Rahm Date: Tue, 9 Jun 2015 17:44:46 -0700 Subject: [PATCH 34/95] Bug 1172138 - Call PR_LogInit before profiler_init. r=froydnj --- toolkit/xre/nsAppRunner.cpp | 4 ++-- toolkit/xre/nsEmbedFunctions.cpp | 5 +++-- xpcom/build/XPCOMInit.cpp | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index 150f76945bff..2d02b02573e1 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -4276,6 +4276,8 @@ XREMain::XRE_mainRun() int XREMain::XRE_main(int argc, char* argv[], const nsXREAppData* aAppData) { + ScopedLogging log; + char aLocal; GeckoProfilerInitRAII profilerGuard(&aLocal); @@ -4302,8 +4304,6 @@ XREMain::XRE_main(int argc, char* argv[], const nsXREAppData* aAppData) // used throughout this file gAppData = mAppData; - ScopedLogging log; - mozilla::IOInterposerInit ioInterposerGuard; #if defined(MOZ_WIDGET_GTK) diff --git a/toolkit/xre/nsEmbedFunctions.cpp b/toolkit/xre/nsEmbedFunctions.cpp index 366a89f0fd88..7abf55960139 100644 --- a/toolkit/xre/nsEmbedFunctions.cpp +++ b/toolkit/xre/nsEmbedFunctions.cpp @@ -347,6 +347,9 @@ XRE_InitChildProcess(int aArgc, } #endif + // NB: This must be called before profiler_init + NS_LogInit(); + char aLocal; profiler_init(&aLocal); @@ -488,8 +491,6 @@ XRE_InitChildProcess(int aArgc, base::AtExitManager exitManager; NotificationService notificationService; - NS_LogInit(); - nsresult rv = XRE_InitCommandLine(aArgc, aArgv); if (NS_FAILED(rv)) { profiler_shutdown(); diff --git a/xpcom/build/XPCOMInit.cpp b/xpcom/build/XPCOMInit.cpp index 72e0a9be1899..c227ecebf29c 100644 --- a/xpcom/build/XPCOMInit.cpp +++ b/xpcom/build/XPCOMInit.cpp @@ -486,6 +486,8 @@ NS_InitXPCOM2(nsIServiceManager** aResult, mozPoisonValueInit(); + NS_LogInit(); + char aLocal; profiler_init(&aLocal); nsresult rv = NS_OK; @@ -508,8 +510,6 @@ NS_InitXPCOM2(nsIServiceManager** aResult, ::umask(nsSystemInfo::gUserUmask); #endif - NS_LogInit(); - // Set up chromium libs NS_ASSERTION(!sExitManager && !sMessageLoop, "Bad logic!"); From 6e3fc0bd96806b4c40b4f1abd74fc53616aa73c6 Mon Sep 17 00:00:00 2001 From: Xidorn Quan Date: Wed, 10 Jun 2015 13:13:49 +1200 Subject: [PATCH 35/95] Bug 1171328 - Convert nsTableFrame::GetChildAreaOffset() and its friends to use LogicalMargin. r=dholbert --HG-- extra : source : 5d48d96995a1b2fd4aefc463d0f2fb2d156e0406 --- layout/generic/nsHTMLReflowState.cpp | 3 +- layout/tables/nsTableFrame.cpp | 174 ++++++++++++++------------- layout/tables/nsTableFrame.h | 25 ++-- layout/tables/nsTableOuterFrame.cpp | 4 +- 4 files changed, 115 insertions(+), 91 deletions(-) diff --git a/layout/generic/nsHTMLReflowState.cpp b/layout/generic/nsHTMLReflowState.cpp index 50bae0a1e98d..edca8648ad71 100644 --- a/layout/generic/nsHTMLReflowState.cpp +++ b/layout/generic/nsHTMLReflowState.cpp @@ -2393,7 +2393,8 @@ nsCSSOffsetState::InitOffsets(const LogicalSize& aPercentBasis, // try to do anything like handling 'auto' widths, // 'box-sizing', or 'auto' margins. ComputedPhysicalPadding().SizeTo(0,0,0,0); - ComputedPhysicalBorderPadding() = tableFrame->GetIncludedOuterBCBorder(); + SetComputedLogicalBorderPadding( + tableFrame->GetIncludedOuterBCBorder(mWritingMode)); } // The margin is inherited to the outer table frame via diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp index 0db84bf3b0df..1b4077cbc103 100644 --- a/layout/tables/nsTableFrame.cpp +++ b/layout/tables/nsTableFrame.cpp @@ -79,25 +79,26 @@ struct nsTableReflowState { "nsTableReflowState should only be created for nsTableFrame"); nsTableFrame* table = static_cast(reflowState.frame->FirstInFlow()); - nsMargin borderPadding = table->GetChildAreaOffset(&reflowState); + WritingMode wm = aReflowState.GetWritingMode(); + LogicalMargin borderPadding = table->GetChildAreaOffset(wm, &reflowState); - x = borderPadding.left + table->GetColSpacing(-1); - y = borderPadding.top; //cellspacing added during reflow + x = borderPadding.IStart(wm) + table->GetColSpacing(-1); + y = borderPadding.BStart(wm); //cellspacing added during reflow availSize.width = aAvailWidth; if (NS_UNCONSTRAINEDSIZE != availSize.width) { int32_t colCount = table->GetColCount(); - availSize.width -= borderPadding.left + borderPadding.right - + table->GetColSpacing(-1) - + table->GetColSpacing(colCount); + availSize.width -= borderPadding.IStartEnd(wm) + + table->GetColSpacing(-1) + + table->GetColSpacing(colCount); availSize.width = std::max(0, availSize.width); } availSize.height = aAvailHeight; if (NS_UNCONSTRAINEDSIZE != availSize.height) { - availSize.height -= borderPadding.top + borderPadding.bottom - + table->GetRowSpacing(-1) - + table->GetRowSpacing(table->GetRowCount()); + availSize.height -= borderPadding.BStartEnd(wm) + + table->GetRowSpacing(-1) + + table->GetRowSpacing(table->GetRowCount()); availSize.height = std::max(0, availSize.height); } } @@ -1350,7 +1351,8 @@ nsTableFrame::GetDeflationForBackground(nsPresContext* aPresContext) const !IsBorderCollapse()) return nsMargin(0,0,0,0); - return GetOuterBCBorder(); + WritingMode wm = GetWritingMode(); + return GetOuterBCBorder(wm).GetPhysicalMargin(wm); } // XXX We don't put the borders and backgrounds in tree order like we should. @@ -1418,10 +1420,10 @@ nsTableFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const } void -nsTableFrame::SetColumnDimensions(nscoord aHeight, - const nsMargin& aBorderPadding) +nsTableFrame::SetColumnDimensions(nscoord aHeight, WritingMode aWM, + const LogicalMargin& aBorderPadding) { - nscoord colHeight = aHeight -= aBorderPadding.top + aBorderPadding.bottom + + nscoord colHeight = aHeight -= aBorderPadding.BStartEnd(aWM) + GetRowSpacing(-1) + GetRowSpacing(GetRowCount()); @@ -1431,8 +1433,8 @@ nsTableFrame::SetColumnDimensions(nscoord aHeight, int32_t colX =tableIsLTR ? 0 : std::max(0, GetColCount() - 1); nscoord cellSpacingX = GetColSpacing(colX); int32_t tableColIncr = tableIsLTR ? 1 : -1; - nsPoint colGroupOrigin(aBorderPadding.left + GetColSpacing(-1), - aBorderPadding.top + GetRowSpacing(-1)); + nsPoint colGroupOrigin(aBorderPadding.IStart(aWM) + GetColSpacing(-1), + aBorderPadding.BStart(aWM) + GetRowSpacing(-1)); while (colGroupFrame) { MOZ_ASSERT(colGroupFrame->GetType() == nsGkAtoms::tableColGroupFrame); nscoord colGroupWidth = 0; @@ -1552,8 +1554,9 @@ nsTableFrame::IntrinsicISizeOffsets(nsRenderingContext* aRenderingContext) result.hPadding = 0; result.hPctPadding = 0; - nsMargin outerBC = GetIncludedOuterBCBorder(); - result.hBorder = outerBC.LeftRight(); + WritingMode wm = GetWritingMode(); + LogicalMargin outerBC = GetIncludedOuterBCBorder(wm); + result.hBorder = outerBC.IStartEnd(wm); } return result; @@ -1785,6 +1788,7 @@ nsTableFrame::Reflow(nsPresContext* aPresContext, DO_GLOBAL_REFLOW_COUNT("nsTableFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); bool isPaginated = aPresContext->IsPaginated(); + WritingMode wm = aReflowState.GetWritingMode(); aStatus = NS_FRAME_COMPLETE; if (!GetPrevInFlow() && !mTableLayoutStrategy) { @@ -1877,8 +1881,8 @@ nsTableFrame::Reflow(nsPresContext* aPresContext, if (lastChildReflowed && NS_FRAME_IS_NOT_COMPLETE(aStatus)) { // if there is an incomplete child, then set the desired height to include it but not the next one - nsMargin borderPadding = GetChildAreaOffset(&aReflowState); - aDesiredSize.Height() = borderPadding.bottom + GetRowSpacing(GetRowCount()) + + LogicalMargin borderPadding = GetChildAreaOffset(wm, &aReflowState); + aDesiredSize.Height() = borderPadding.BEnd(wm) + GetRowSpacing(GetRowCount()) + lastChildReflowed->GetNormalRect().YMost(); } haveDesiredHeight = true; @@ -1902,11 +1906,11 @@ nsTableFrame::Reflow(nsPresContext* aPresContext, ProcessRowInserted(aDesiredSize.Height()); } - nsMargin borderPadding = GetChildAreaOffset(&aReflowState); - SetColumnDimensions(aDesiredSize.Height(), borderPadding); + LogicalMargin borderPadding = GetChildAreaOffset(wm, &aReflowState); + SetColumnDimensions(aDesiredSize.Height(), wm, borderPadding); if (NeedToCollapse() && (NS_UNCONSTRAINEDSIZE != aReflowState.AvailableWidth())) { - AdjustForCollapsingRowsCols(aDesiredSize, borderPadding); + AdjustForCollapsingRowsCols(aDesiredSize, wm, borderPadding); } // If there are any relatively-positioned table parts, we need to reflow their @@ -1918,8 +1922,8 @@ nsTableFrame::Reflow(nsPresContext* aPresContext, if (!ShouldApplyOverflowClipping(this, aReflowState.mStyleDisplay)) { // collapsed border may leak out - nsMargin bcMargin = GetExcludedOuterBCBorder(); - tableRect.Inflate(bcMargin); + LogicalMargin bcMargin = GetExcludedOuterBCBorder(wm); + tableRect.Inflate(bcMargin.GetPhysicalMargin(wm)); } aDesiredSize.mOverflowAreas.UnionAllWith(tableRect); @@ -2007,8 +2011,9 @@ nsTableFrame::UpdateOverflow() // As above in Reflow, make sure the table overflow area includes the table // rect, and check for collapsed borders leaking out. if (!ShouldApplyOverflowClipping(this, StyleDisplay())) { - nsMargin bcMargin = GetExcludedOuterBCBorder(); - bounds.Inflate(bcMargin); + WritingMode wm = GetWritingMode(); + LogicalMargin bcMargin = GetExcludedOuterBCBorder(wm); + bounds.Inflate(bcMargin.GetPhysicalMargin(wm)); } nsOverflowAreas overflowAreas(bounds, bounds); @@ -2123,7 +2128,8 @@ nsTableFrame::PushChildren(const RowGroupArray& aRowGroups, // reflow so that it has no effect on the calculations of reflow. void nsTableFrame::AdjustForCollapsingRowsCols(nsHTMLReflowMetrics& aDesiredSize, - nsMargin aBorderPadding) + const WritingMode aWM, + const LogicalMargin& aBorderPadding) { nscoord yTotalOffset = 0; // total offset among all rows in all row groups @@ -2137,7 +2143,7 @@ nsTableFrame::AdjustForCollapsingRowsCols(nsHTMLReflowMetrics& aDesiredSize, OrderRowGroups(rowGroups); nsTableFrame* firstInFlow = static_cast(FirstInFlow()); - nscoord width = firstInFlow->GetCollapsedWidth(aBorderPadding); + nscoord width = firstInFlow->GetCollapsedWidth(aWM, aBorderPadding); nscoord rgWidth = width - GetColSpacing(-1) - GetColSpacing(GetColCount()); nsOverflowAreas overflow; @@ -2158,11 +2164,12 @@ nsTableFrame::AdjustForCollapsingRowsCols(nsHTMLReflowMetrics& aDesiredSize, nscoord -nsTableFrame::GetCollapsedWidth(nsMargin aBorderPadding) +nsTableFrame::GetCollapsedWidth(const WritingMode aWM, + const LogicalMargin& aBorderPadding) { NS_ASSERTION(!GetPrevInFlow(), "GetCollapsedWidth called on next in flow"); nscoord width = GetColSpacing(GetColCount()); - width += aBorderPadding.left + aBorderPadding.right; + width += aBorderPadding.IStartEnd(aWM); for (nsIFrame* groupFrame : mColGroups) { const nsStyleVisibility* groupVis = groupFrame->StyleVisibility(); bool collapseGroup = (NS_STYLE_VISIBILITY_COLLAPSE == groupVis->mVisible); @@ -2550,7 +2557,8 @@ nsTableFrame::GetUsedBorder() const if (!IsBorderCollapse()) return nsContainerFrame::GetUsedBorder(); - return GetIncludedOuterBCBorder(); + WritingMode wm = GetWritingMode(); + return GetIncludedOuterBCBorder(wm).GetPhysicalMargin(wm); } /* virtual */ nsMargin @@ -2595,74 +2603,72 @@ DivideBCBorderSize(BCPixelSize aPixelSize, aLargeHalf = aPixelSize - aSmallHalf; } -nsMargin -nsTableFrame::GetOuterBCBorder() const +LogicalMargin +nsTableFrame::GetOuterBCBorder(const WritingMode aWM) const { if (NeedToCalcBCBorders()) const_cast(this)->CalcBCBorders(); - nsMargin border(0, 0, 0, 0); int32_t p2t = nsPresContext::AppUnitsPerCSSPixel(); BCPropertyData* propData = GetBCProperty(); if (propData) { - border.top = BC_BORDER_START_HALF_COORD(p2t, propData->mTopBorderWidth); - border.right = BC_BORDER_END_HALF_COORD(p2t, propData->mRightBorderWidth); - border.bottom = BC_BORDER_END_HALF_COORD(p2t, propData->mBottomBorderWidth); - border.left = BC_BORDER_START_HALF_COORD(p2t, propData->mLeftBorderWidth); + return LogicalMargin( + aWM, + BC_BORDER_START_HALF_COORD(p2t, propData->mTopBorderWidth), + BC_BORDER_END_HALF_COORD(p2t, propData->mRightBorderWidth), + BC_BORDER_END_HALF_COORD(p2t, propData->mBottomBorderWidth), + BC_BORDER_START_HALF_COORD(p2t, propData->mLeftBorderWidth)); } - return border; + return LogicalMargin(GetWritingMode()); } -nsMargin -nsTableFrame::GetIncludedOuterBCBorder() const +LogicalMargin +nsTableFrame::GetIncludedOuterBCBorder(const WritingMode aWM) const { if (NeedToCalcBCBorders()) const_cast(this)->CalcBCBorders(); - nsMargin border(0, 0, 0, 0); int32_t p2t = nsPresContext::AppUnitsPerCSSPixel(); BCPropertyData* propData = GetBCProperty(); if (propData) { - border.top += BC_BORDER_START_HALF_COORD(p2t, propData->mTopBorderWidth); - border.right += BC_BORDER_END_HALF_COORD(p2t, propData->mRightCellBorderWidth); - border.bottom += BC_BORDER_END_HALF_COORD(p2t, propData->mBottomBorderWidth); - border.left += BC_BORDER_START_HALF_COORD(p2t, propData->mLeftCellBorderWidth); + return LogicalMargin( + aWM, + BC_BORDER_START_HALF_COORD(p2t, propData->mTopBorderWidth), + BC_BORDER_END_HALF_COORD(p2t, propData->mRightCellBorderWidth), + BC_BORDER_END_HALF_COORD(p2t, propData->mBottomBorderWidth), + BC_BORDER_START_HALF_COORD(p2t, propData->mLeftCellBorderWidth)); } - return border; + return LogicalMargin(GetWritingMode()); } -nsMargin -nsTableFrame::GetExcludedOuterBCBorder() const +LogicalMargin +nsTableFrame::GetExcludedOuterBCBorder(const WritingMode aWM) const { - return GetOuterBCBorder() - GetIncludedOuterBCBorder(); + return GetOuterBCBorder(aWM) - GetIncludedOuterBCBorder(aWM); } -static -void GetSeparateModelBorderPadding(const nsHTMLReflowState* aReflowState, - nsStyleContext& aStyleContext, - nsMargin& aBorderPadding) +static LogicalMargin +GetSeparateModelBorderPadding(const WritingMode aWM, + const nsHTMLReflowState* aReflowState, + nsStyleContext* aStyleContext) { // XXXbz Either we _do_ have a reflow state and then we can use its // mComputedBorderPadding or we don't and then we get the padding // wrong! - const nsStyleBorder* border = aStyleContext.StyleBorder(); - aBorderPadding = border->GetComputedBorder(); + const nsStyleBorder* border = aStyleContext->StyleBorder(); + LogicalMargin borderPadding(aWM, border->GetComputedBorder()); if (aReflowState) { - aBorderPadding += aReflowState->ComputedPhysicalPadding(); + borderPadding += aReflowState->ComputedLogicalPadding(); } + return borderPadding; } -nsMargin -nsTableFrame::GetChildAreaOffset(const nsHTMLReflowState* aReflowState) const +LogicalMargin +nsTableFrame::GetChildAreaOffset(const WritingMode aWM, + const nsHTMLReflowState* aReflowState) const { - nsMargin offset(0,0,0,0); - if (IsBorderCollapse()) { - offset = GetIncludedOuterBCBorder(); - } - else { - GetSeparateModelBorderPadding(aReflowState, *mStyleContext, offset); - } - return offset; + return IsBorderCollapse() ? GetIncludedOuterBCBorder(aWM) : + GetSeparateModelBorderPadding(aWM, aReflowState, mStyleContext); } void @@ -3218,7 +3224,8 @@ nsTableFrame::CalcDesiredHeight(const nsHTMLReflowState& aReflowState, aDesiredSize.Height() = 0; return; } - nsMargin borderPadding = GetChildAreaOffset(&aReflowState); + WritingMode wm = aReflowState.GetWritingMode(); + LogicalMargin borderPadding = GetChildAreaOffset(wm, &aReflowState); // get the natural height based on the last child's (row group) rect RowGroupArray rowGroups; @@ -3238,7 +3245,7 @@ nsTableFrame::CalcDesiredHeight(const nsHTMLReflowState& aReflowState, } int32_t rowCount = cellMap->GetRowCount(); int32_t colCount = cellMap->GetColCount(); - nscoord desiredHeight = borderPadding.top + borderPadding.bottom; + nscoord desiredHeight = borderPadding.BStartEnd(wm); if (rowCount > 0 && colCount > 0) { desiredHeight += GetRowSpacing(-1); for (uint32_t rgX = 0; rgX < rowGroups.Length(); rgX++) { @@ -3301,7 +3308,8 @@ void nsTableFrame::DistributeHeightToRows(const nsHTMLReflowState& aReflowState, nscoord aAmount) { - nsMargin borderPadding = GetChildAreaOffset(&aReflowState); + WritingMode wm = aReflowState.GetWritingMode(); + LogicalMargin borderPadding = GetChildAreaOffset(wm, &aReflowState); RowGroupArray rowGroups; OrderRowGroups(rowGroups); @@ -3311,7 +3319,7 @@ nsTableFrame::DistributeHeightToRows(const nsHTMLReflowState& aReflowState, // height, and base the pct on the table height. If the row group had a computed // height, then this was already done in nsTableRowGroupFrame::CalculateRowHeights nscoord pctBasis = aReflowState.ComputedHeight() - GetRowSpacing(-1, GetRowCount()); - nscoord yOriginRG = borderPadding.top + GetRowSpacing(0); + nscoord yOriginRG = borderPadding.BStart(wm) + GetRowSpacing(0); nscoord yEndRG = yOriginRG; uint32_t rgX; for (rgX = 0; rgX < rowGroups.Length(); rgX++) { @@ -3449,7 +3457,7 @@ nsTableFrame::DistributeHeightToRows(const nsHTMLReflowState& aReflowState, } // allocate the extra height to the unstyled row groups and rows nscoord heightToDistribute = aAmount - amountUsed; - yOriginRG = borderPadding.top + GetRowSpacing(-1); + yOriginRG = borderPadding.BStart(wm) + GetRowSpacing(-1); yEndRG = yOriginRG; for (rgX = 0; rgX < rowGroups.Length(); rgX++) { nsTableRowGroupFrame* rgFrame = rowGroups[rgX]; @@ -3726,8 +3734,9 @@ nsTableFrame::CalcBorderBoxHeight(const nsHTMLReflowState& aState) { nscoord height = aState.ComputedHeight(); if (NS_AUTOHEIGHT != height) { - nsMargin borderPadding = GetChildAreaOffset(&aState); - height += borderPadding.top + borderPadding.bottom; + WritingMode wm = aState.GetWritingMode(); + LogicalMargin borderPadding = GetChildAreaOffset(wm, &aState); + height += borderPadding.BStartEnd(wm); } height = std::max(0, height); @@ -6386,9 +6395,10 @@ BCPaintBorderIterator::BCPaintBorderIterator(nsTableFrame* aTable) , mTableWM(aTable->StyleContext()) { mVerInfo = nullptr; - nsMargin childAreaOffset = mTable->GetChildAreaOffset(nullptr); + LogicalMargin childAreaOffset = mTable->GetChildAreaOffset(mTableWM, nullptr); // y position of first row in damage area - mInitialOffsetY = mTable->GetPrevInFlow() ? 0 : childAreaOffset.top; + mInitialOffsetY = + mTable->GetPrevInFlow() ? 0 : childAreaOffset.BStart(mTableWM); mNumTableRows = mTable->GetRowCount(); mNumTableCols = mTable->GetColCount(); @@ -6465,15 +6475,16 @@ BCPaintBorderIterator::SetDamageArea(const nsRect& aDirtyRect) return false; int32_t leftCol, rightCol; // columns are in the range [leftCol, rightCol) - nsMargin childAreaOffset = mTable->GetChildAreaOffset(nullptr); + LogicalMargin childAreaOffset = mTable->GetChildAreaOffset(mTableWM, nullptr); if (mTableWM.IsBidiLTR()) { - mInitialOffsetX = childAreaOffset.left; // x position of first col in - // damage area + // x position of first col in damage area + mInitialOffsetX = childAreaOffset.IStart(mTableWM); leftCol = 0; rightCol = mNumTableCols; } else { // x position of first col in damage area - mInitialOffsetX = mTable->GetRect().width - childAreaOffset.right; + mInitialOffsetX = + mTable->GetRect().width - childAreaOffset.IStart(mTableWM); leftCol = mNumTableCols-1; rightCol = -1; } @@ -6509,7 +6520,8 @@ BCPaintBorderIterator::SetDamageArea(const nsRect& aDirtyRect) } if (!mTableWM.IsBidiLTR()) { uint32_t temp; - mInitialOffsetX = mTable->GetRect().width - childAreaOffset.right; + mInitialOffsetX = + mTable->GetRect().width - childAreaOffset.IStart(mTableWM); temp = startColIndex; startColIndex = endColIndex; endColIndex = temp; for (uint32_t column = 0; column < startColIndex; column++) { nsTableColFrame* colFrame = mTableFirstInFlow->GetColFrame(column); diff --git a/layout/tables/nsTableFrame.h b/layout/tables/nsTableFrame.h index 50dd8bfae809..93071f3613b1 100644 --- a/layout/tables/nsTableFrame.h +++ b/layout/tables/nsTableFrame.h @@ -25,6 +25,10 @@ class nsTableRowFrame; class nsTableColGroupFrame; class nsITableLayoutStrategy; class nsStyleContext; +namespace mozilla { +class WritingMode; +class LogicalMargin; +} struct nsTableReflowState; struct BCPropertyData; @@ -123,6 +127,8 @@ enum nsTableColType { class nsTableFrame : public nsContainerFrame { typedef mozilla::image::DrawResult DrawResult; + typedef mozilla::WritingMode WritingMode; + typedef mozilla::LogicalMargin LogicalMargin; public: NS_DECL_QUERYFRAME_TARGET(nsTableFrame) @@ -206,7 +212,8 @@ public: virtual nsMargin GetUsedMargin() const override; // Get the offset from the border box to the area where the row groups fit - nsMargin GetChildAreaOffset(const nsHTMLReflowState* aReflowState) const; + LogicalMargin GetChildAreaOffset(const WritingMode aWM, + const nsHTMLReflowState* aReflowState) const; /** helper method to find the table parent of any table frame object */ static nsTableFrame* GetTableFrame(nsIFrame* aSourceFrame); @@ -273,18 +280,18 @@ public: * the table) of the largest segment (?) of border-collapsed border on * the table on each side, or 0 for non border-collapsed tables. */ - nsMargin GetOuterBCBorder() const; + LogicalMargin GetOuterBCBorder(const WritingMode aWM) const; /** Same as above, but only if it's included from the border-box width * of the table. */ - nsMargin GetIncludedOuterBCBorder() const; + LogicalMargin GetIncludedOuterBCBorder(const WritingMode aWM) const; /** Same as above, but only if it's excluded from the border-box width * of the table. This is the area that leaks out into the margin * (or potentially past it, if there is no margin). */ - nsMargin GetExcludedOuterBCBorder() const; + LogicalMargin GetExcludedOuterBCBorder(const WritingMode aWM) const; /** * In quirks mode, the size of the table background is reduced @@ -632,7 +639,8 @@ protected: * on columns and colgroups * @param aBorderPadding the border and padding of the table */ - nscoord GetCollapsedWidth(nsMargin aBorderPadding); + nscoord GetCollapsedWidth(const WritingMode aWM, + const LogicalMargin& aBorderPadding); /** Adjust the table for visibility.collapse set on rowgroups, rows, @@ -641,7 +649,8 @@ protected: * @param aBorderPadding the border and padding of the table */ void AdjustForCollapsingRowsCols(nsHTMLReflowMetrics& aDesiredSize, - nsMargin aBorderPadding); + const WritingMode aWM, + const LogicalMargin& aBorderPadding); /** FixupPositionedTableParts is called at the end of table reflow to reflow * the absolutely positioned descendants of positioned table parts. This is @@ -801,8 +810,8 @@ protected: void ExpandBCDamageArea(mozilla::TableArea& aRect) const; - void SetColumnDimensions(nscoord aHeight, - const nsMargin& aReflowState); + void SetColumnDimensions(nscoord aHeight, WritingMode aWM, + const LogicalMargin& aBorderPadding); int32_t CollectRows(nsIFrame* aFrame, nsTArray& aCollection); diff --git a/layout/tables/nsTableOuterFrame.cpp b/layout/tables/nsTableOuterFrame.cpp index f30630edb56e..9284a9c66c45 100644 --- a/layout/tables/nsTableOuterFrame.cpp +++ b/layout/tables/nsTableOuterFrame.cpp @@ -242,7 +242,9 @@ nsTableOuterFrame::InitChildReflowState(nsPresContext& aPresContext, nsMargin* pCollapsePadding = nullptr; if (aReflowState.frame == InnerTableFrame() && InnerTableFrame()->IsBorderCollapse()) { - collapseBorder = InnerTableFrame()->GetIncludedOuterBCBorder(); + WritingMode wm = aReflowState.GetWritingMode(); + LogicalMargin border = InnerTableFrame()->GetIncludedOuterBCBorder(wm); + collapseBorder = border.GetPhysicalMargin(wm); pCollapseBorder = &collapseBorder; pCollapsePadding = &collapsePadding; } From 6822bb6669f875831b2cdc959cd5c1db44677537 Mon Sep 17 00:00:00 2001 From: Xidorn Quan Date: Wed, 10 Jun 2015 13:13:49 +1200 Subject: [PATCH 36/95] Bug 1172664 - Use [NSApplication setPresentationOptions:] instead of SetSystemUIMode for hide os chrome. r=smichaud --HG-- extra : source : 2508b0bb8b91a883e39a1026364bab0947266288 --- widget/cocoa/nsCocoaUtils.mm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/widget/cocoa/nsCocoaUtils.mm b/widget/cocoa/nsCocoaUtils.mm index a31753ba0c27..c75958764031 100644 --- a/widget/cocoa/nsCocoaUtils.mm +++ b/widget/cocoa/nsCocoaUtils.mm @@ -253,15 +253,15 @@ void nsCocoaUtils::HideOSChromeOnScreen(bool aShouldHide, NSScreen* aScreen) NS_ASSERTION(sDockHiddenCount >= 0, "Unbalanced HideMenuAndDockForWindow calls"); } - // TODO This should be upgraded to use [NSApplication setPresentationOptions:] - // when support for 10.5 is dropped. + NSApplicationPresentationOptions options; if (sMenuBarHiddenCount > 0) { - ::SetSystemUIMode(kUIModeAllHidden, 0); + options = NSApplicationPresentationHideDock | NSApplicationPresentationHideMenuBar; } else if (sDockHiddenCount > 0) { - ::SetSystemUIMode(kUIModeContentHidden, 0); + options = NSApplicationPresentationHideDock; } else { - ::SetSystemUIMode(kUIModeNormal, 0); + options = NSApplicationPresentationDefault; } + [NSApp setPresentationOptions:options]; NS_OBJC_END_TRY_ABORT_BLOCK; } From 28b7eca00799a5a312f8ffffecfcfacc13e77c2d Mon Sep 17 00:00:00 2001 From: Xidorn Quan Date: Wed, 10 Jun 2015 13:14:57 +1200 Subject: [PATCH 37/95] Bug 1166960 - Remove redundant call to UnlockPointer and unnecessary check before calling that function. r=smaug --HG-- extra : source : 6a578de8d395e9b8e0054b02ef543689467d86af --- dom/base/nsDocument.cpp | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index 46144076de3a..d8e30570ec50 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -11196,12 +11196,8 @@ ExitFullscreenInDocTree(nsIDocument* aMaybeNotARootDoc) void nsDocument::ExitFullscreen(nsIDocument* aDoc) { - // Unlock the pointer, if it's locked. - nsCOMPtr pointerLockedElement = - do_QueryReferent(EventStateManager::sPointerLockedElement); - if (pointerLockedElement) { - UnlockPointer(); - } + // Unlock the pointer + UnlockPointer(); if (aDoc) { ExitFullscreenInDocTree(aDoc); @@ -11258,11 +11254,7 @@ nsDocument::RestorePreviousFullScreenState() } // If fullscreen mode is updated the pointer should be unlocked - nsCOMPtr pointerLockedElement = - do_QueryReferent(EventStateManager::sPointerLockedElement); - if (pointerLockedElement) { - UnlockPointer(); - } + UnlockPointer(); nsCOMPtr fullScreenDoc = GetFullscreenLeaf(this); @@ -11271,7 +11263,6 @@ nsDocument::RestorePreviousFullScreenState() while (doc != this) { NS_ASSERTION(doc->IsFullScreenDoc(), "Should be full-screen doc"); static_cast(doc)->CleanupFullscreenState(); - UnlockPointer(); DispatchFullScreenChange(doc); doc = doc->GetParentDocument(); } @@ -11280,7 +11271,6 @@ nsDocument::RestorePreviousFullScreenState() NS_ASSERTION(doc == this, "Must have reached this doc."); while (doc != nullptr) { static_cast(doc)->FullScreenStackPop(); - UnlockPointer(); DispatchFullScreenChange(doc); if (static_cast(doc)->mFullScreenStack.IsEmpty()) { // Full-screen stack in document is empty. Go back up to the parent @@ -11666,19 +11656,10 @@ nsDocument::RequestFullScreen(Element* aElement, // Remember the root document, so that if a full-screen document is hidden // we can reset full-screen state in the remaining visible full-screen documents. nsIDocument* fullScreenRootDoc = nsContentUtils::GetRootDocument(this); - if (fullScreenRootDoc->IsFullScreenDoc()) { - // A document is already in fullscreen, unlock the mouse pointer - // before setting a new document to fullscreen - UnlockPointer(); - } // If a document is already in fullscreen, then unlock the mouse pointer // before setting a new document to fullscreen - nsCOMPtr pointerLockedElement = - do_QueryReferent(EventStateManager::sPointerLockedElement); - if (pointerLockedElement) { - UnlockPointer(); - } + UnlockPointer(); // Process options -- in this case, just HMD if (aOptions.mVRHMDDevice) { From ab11dfb2092d6be7aabd89765352fcb3d1c04d78 Mon Sep 17 00:00:00 2001 From: Gregory Szorc Date: Thu, 4 Jun 2015 11:24:03 -0700 Subject: [PATCH 38/95] Bug 1168607 - Add get method to finders; r=glandium Today, the *Finder classes are optimized for doing matching and returning multiple results. However, sometimes only looking for a single file is wanted. This commit implements the "get" method on all the *Finder classes. It returns a BaseFile or None. FileFinder._find_file has been refactored into FileFinder.get to avoid code duplication. --HG-- extra : commitid : K9It2ZJ3Rbo extra : rebase_source : a56f8f70aa1902d26373a7196eae2847cce653d3 --- python/mozbuild/mozpack/files.py | 31 +++++++++++++++------- python/mozbuild/mozpack/test/test_files.py | 16 +++++++++++ 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/python/mozbuild/mozpack/files.py b/python/mozbuild/mozpack/files.py index 63135a8e2eb7..bdbcdf7d4cbc 100644 --- a/python/mozbuild/mozpack/files.py +++ b/python/mozbuild/mozpack/files.py @@ -713,6 +713,20 @@ class BaseFinder(object): for p, f in self._find(pattern): yield p, self._minify_file(p, f) + def get(self, path): + """Obtain a single file. + + Where ``find`` is tailored towards matching multiple files, this method + is used for retrieving a single file. Use this method when performance + is critical. + + Returns a ``BaseFile`` if at most one file exists or ``None`` otherwise. + """ + files = list(self.find(path)) + if len(files) != 1: + return None + return files[0][1] + def __iter__(self): ''' Iterates over all files under the base directory (excluding files @@ -788,7 +802,8 @@ class FileFinder(BaseFinder): elif os.path.isdir(os.path.join(self.base, pattern)): return self._find_dir(pattern) else: - return self._find_file(pattern) + f = self.get(pattern) + return ((pattern, f),) if f else () def _find_dir(self, path): ''' @@ -810,23 +825,19 @@ class FileFinder(BaseFinder): for p_, f in self._find(mozpath.join(path, p)): yield p_, f - def _find_file(self, path): - ''' - Actual implementation of FileFinder.find() when the given pattern - corresponds to an existing file under the base directory. - ''' + def get(self, path): srcpath = os.path.join(self.base, path) if not os.path.exists(srcpath): - return + return None for p in self.ignore: if mozpath.match(path, p): - return + return None if self.find_executables and is_executable(srcpath): - yield path, ExecutableFile(srcpath) + return ExecutableFile(srcpath) else: - yield path, File(srcpath) + return File(srcpath) def _find_glob(self, base, pattern): ''' diff --git a/python/mozbuild/mozpack/test/test_files.py b/python/mozbuild/mozpack/test/test_files.py index 99bd40b5ed74..b1cb8f43bb6d 100644 --- a/python/mozbuild/mozpack/test/test_files.py +++ b/python/mozbuild/mozpack/test/test_files.py @@ -911,6 +911,16 @@ class TestFileFinder(MatchTestTemplate, TestWithTmpDir): self.do_match_test() self.do_finder_test(self.finder) + def test_get(self): + self.prepare_match_test() + finder = FileFinder(self.tmpdir) + + self.assertIsNone(finder.get('does-not-exist')) + res = finder.get('bar') + self.assertIsInstance(res, File) + self.assertEqual(mozpath.normpath(res.path), + mozpath.join(self.tmpdir, 'bar')) + def test_ignored_dirs(self): """Ignored directories should not have results returned.""" self.prepare_match_test() @@ -969,6 +979,9 @@ class TestJarFinder(MatchTestTemplate, TestWithTmpDir): self.finder = JarFinder(self.tmppath('test.jar'), reader) self.do_match_test() + self.assertIsNone(self.finder.get('does-not-exist')) + self.assertIsInstance(self.finder.get('bar'), DeflatedFile) + class TestComposedFinder(MatchTestTemplate, TestWithTmpDir): def add(self, path, content=None): @@ -1000,6 +1013,9 @@ class TestComposedFinder(MatchTestTemplate, TestWithTmpDir): }) self.do_match_test() + self.assertIsNone(self.finder.get('does-not-exist')) + self.assertIsInstance(self.finder.get('bar'), File) + if __name__ == '__main__': mozunit.main() From 4bee702035362fd4c6f877b4b9662e8a53af1859 Mon Sep 17 00:00:00 2001 From: Gregory Szorc Date: Tue, 2 Jun 2015 09:37:45 -0700 Subject: [PATCH 39/95] Bug 1168607 - Add a read() method to File; r=glandium Passing raw file handles around is a bit dangerous because it could lead to leaking file descriptors. Add a read() method that handles the simple case of obtaining the full contents of a File instance. This should ideally be a method on BaseFile. But this would require extra work and isn't needed. So we've deferred it until bug 1170329. --HG-- extra : commitid : 82qw76XmpjC extra : rebase_source : 422b16c5a3b1577f080097925aeaeb560aa3e798 --- python/mozbuild/mozpack/files.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/python/mozbuild/mozpack/files.py b/python/mozbuild/mozpack/files.py index bdbcdf7d4cbc..6735682c6633 100644 --- a/python/mozbuild/mozpack/files.py +++ b/python/mozbuild/mozpack/files.py @@ -189,6 +189,9 @@ class BaseFile(object): assert self.path is not None return open(self.path, 'rb') + def read(self): + raise NotImplementedError('BaseFile.read() not implemented. Bug 1170329.') + @property def mode(self): ''' @@ -227,6 +230,12 @@ class File(BaseFile): # - leave away sticky bit, setuid, setgid return ret + def read(self): + '''Return the contents of the file.''' + with open(self.path, 'rb') as fh: + return fh.read() + + class ExecutableFile(File): ''' File class for executable and library files on OS/2, OS/X and ELF systems. From 8ce366a5f7553c647005cc984376c430382f797b Mon Sep 17 00:00:00 2001 From: Gregory Szorc Date: Tue, 9 Jun 2015 18:16:35 -0700 Subject: [PATCH 40/95] Bug 1168607 - Use mozpack Finders for reading moz.build files; r=glandium Sometimes moz.build data may not come from the local filesystem. To support defining moz.build data in other backing stores, we switch moz.build reading to use mozpack's *Finder classes for I/O. The use of a FileFinder bound to / is sub-optimal. We should ideally be creating a finder bound to topsrcdir. However, doing this would require refactoring a lot of path handling in the reader, as that code makes many assumptions that paths are absolute. This would be excellent follow-up work. While I was here, I cleaned up some linter warnings for unused imports. On my machine, this commit results in a slight slowdown of moz.build reading. Before, `mach build-backend` was consistently reporting 1.99s for reading 2,572 moz.build files. After, it is consistently reporting 2.07s, an increase of 4%. This is likely due to a) function call overhead b) the cost of instantiating a few thousand File instances c) FileFinder performing an os.path.exists() before returning File instances. I believe the regression is tolerable. --HG-- extra : commitid : 1WDcrSU3SQD extra : rebase_source : a23aa5a4063c6f7080ee00b6f0fe0ee532da3ce7 --- python/mozbuild/mozbuild/frontend/reader.py | 19 +++++++++++-------- python/mozbuild/mozbuild/frontend/sandbox.py | 18 +++++++++--------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/python/mozbuild/mozbuild/frontend/reader.py b/python/mozbuild/mozbuild/frontend/reader.py index 8c281728ec69..0c54dae14788 100644 --- a/python/mozbuild/mozbuild/frontend/reader.py +++ b/python/mozbuild/mozbuild/frontend/reader.py @@ -39,7 +39,6 @@ from mozbuild.util import ( EmptyValue, memoize, ReadOnlyDefaultDict, - ReadOnlyDict, ) from mozbuild.backend.configenvironment import ConfigEnvironment @@ -53,6 +52,7 @@ from .data import ( ) from .sandbox import ( + default_finder, SandboxError, SandboxExecutionError, SandboxLoadError, @@ -172,10 +172,10 @@ class MozbuildSandbox(Sandbox): metadata is a dict of metadata that can be used during the sandbox evaluation. """ - def __init__(self, context, metadata={}): + def __init__(self, context, metadata={}, finder=default_finder): assert isinstance(context, Context) - Sandbox.__init__(self, context) + Sandbox.__init__(self, context, finder=finder) self._log = logging.getLogger(__name__) @@ -391,7 +391,8 @@ class MozbuildSandbox(Sandbox): 'special_variables': self.metadata.get('special_variables', {}), 'subcontexts': self.metadata.get('subcontexts', {}), 'templates': self.metadata.get('templates', {}) - }) + }, finder=self._finder) + template.exec_in_sandbox(sandbox, *args, **kwargs) # This is gross, but allows the merge to happen. Eventually, the @@ -853,12 +854,13 @@ class BuildReader(object): each sandbox evaluation. Its return value is ignored. """ - def __init__(self, config): + def __init__(self, config, finder=default_finder): self.config = config self._log = logging.getLogger(__name__) self._read_files = set() self._execution_stack = [] + self._finder = finder def read_topsrcdir(self): """Read the tree of linked moz.build files. @@ -1091,7 +1093,8 @@ class BuildReader(object): config.external_source_dir = None context = Context(VARIABLES, config) - sandbox = MozbuildSandbox(context, metadata=metadata) + sandbox = MozbuildSandbox(context, metadata=metadata, + finder=self._finder) sandbox.exec_file(path) context.execution_time = time.time() - time_start @@ -1127,7 +1130,7 @@ class BuildReader(object): non_unified_sources = set() for s in gyp_dir.non_unified_sources: source = SourcePath(context, s) - if not os.path.exists(source.full_path): + if not self._finder.get(source.full_path): raise SandboxValidationError('Cannot find %s.' % source, context) non_unified_sources.add(source) @@ -1215,7 +1218,7 @@ class BuildReader(object): @memoize def exists(path): - return os.path.exists(path) + return self._finder.get(path) is not None def itermozbuild(path): subpath = '' diff --git a/python/mozbuild/mozbuild/frontend/sandbox.py b/python/mozbuild/mozbuild/frontend/sandbox.py index 83f951de0e24..1d12f45f6694 100644 --- a/python/mozbuild/mozbuild/frontend/sandbox.py +++ b/python/mozbuild/mozbuild/frontend/sandbox.py @@ -19,15 +19,16 @@ user-friendly error messages in the case of errors. from __future__ import unicode_literals -import copy import os import sys import weakref -from contextlib import contextmanager - from mozbuild.util import ReadOnlyDict -from context import Context +from .context import Context +from mozpack.files import FileFinder + + +default_finder = FileFinder('/', find_executables=False) def alphabetical_sorted(iterable, cmp=None, key=lambda x: x.lower(), @@ -108,7 +109,7 @@ class Sandbox(dict): 'int': int, }) - def __init__(self, context, builtins=None): + def __init__(self, context, builtins=None, finder=default_finder): """Initialize a Sandbox ready for execution. """ self._builtins = builtins or self.BUILTINS @@ -132,6 +133,8 @@ class Sandbox(dict): # Current literal source being executed. self._current_source = None + self._finder = finder + @property def _context(self): return self._active_contexts[-1] @@ -143,11 +146,8 @@ class Sandbox(dict): """ assert os.path.isabs(path) - source = None - try: - with open(path, 'rt') as fd: - source = fd.read() + source = self._finder.get(path).read() except Exception as e: raise SandboxLoadError(self._context.source_stack, sys.exc_info()[2], read_error=path) From 4f13520461514645298509e4c77a3b98b4668257 Mon Sep 17 00:00:00 2001 From: Gregory Szorc Date: Tue, 9 Jun 2015 13:39:01 -0700 Subject: [PATCH 41/95] Bug 1168607 - Implement a finder that reads from a Mercurial repo; r=glandium Now that moz.build files use finders for I/O, we can start reading moz.build data from other sources. Version control is essentially a filesystem. We implement a finder that speaks to Mercurial to obtain file data. It is able to obtain file data from a specific revision in the repository. We use the hglib package (which uses the Mercurial command server) for speaking with Mercurial. This adds overhead compared to consuming the raw Mercurial APIs. However, it also avoids GPL side-effects of importing Mercurial's Python modules. Testing shows that performance is good but not great. A follow-up commit will introduce a GPL licensed Mercurial finder. For now, get the base functionality in place. --HG-- extra : commitid : BkwaQOW9MiR extra : rebase_source : 915d6015317ccc79c228a76eed861d9f43e2fd17 --- python/mozbuild/mozpack/files.py | 106 ++++++++++++++++++--- python/mozbuild/mozpack/test/test_files.py | 65 +++++++++++++ 2 files changed, 158 insertions(+), 13 deletions(-) diff --git a/python/mozbuild/mozpack/files.py b/python/mozbuild/mozpack/files.py index 6735682c6633..7b779ea41adf 100644 --- a/python/mozbuild/mozpack/files.py +++ b/python/mozbuild/mozpack/files.py @@ -34,6 +34,12 @@ from tempfile import ( NamedTemporaryFile, ) +try: + import hglib +except ImportError: + hglib = None + + # For clean builds, copying files on win32 using CopyFile through ctypes is # ~2x as fast as using shutil.copyfile. if platform.system() != 'Windows': @@ -776,6 +782,30 @@ class BaseFinder(object): return file + def _find_helper(self, pattern, files, file_getter): + """Generic implementation of _find. + + A few *Finder implementations share logic for returning results. + This function implements the custom logic. + + The ``file_getter`` argument is a callable that receives a path + that is known to exist. The callable should return a ``BaseFile`` + instance. + """ + if '*' in pattern: + for p in files: + if mozpath.match(p, pattern): + yield p, file_getter(p) + elif pattern == '': + for p in files: + yield p, file_getter(p) + elif pattern in files: + yield pattern, file_getter(pattern) + else: + for p in files: + if mozpath.basedir(p, [pattern]) == pattern: + yield p, file_getter(p) + class FileFinder(BaseFinder): ''' @@ -905,19 +935,8 @@ class JarFinder(BaseFinder): Actual implementation of JarFinder.find(), dispatching to specialized member functions depending on what kind of pattern was given. ''' - if '*' in pattern: - for p in self._files: - if mozpath.match(p, pattern): - yield p, DeflatedFile(self._files[p]) - elif pattern == '': - for p in self._files: - yield p, DeflatedFile(self._files[p]) - elif pattern in self._files: - yield pattern, DeflatedFile(self._files[pattern]) - else: - for p in self._files: - if mozpath.basedir(p, [pattern]) == pattern: - yield p, DeflatedFile(self._files[p]) + return self._find_helper(pattern, self._files, + lambda x: DeflatedFile(self._files[x])) class ComposedFinder(BaseFinder): @@ -945,3 +964,64 @@ class ComposedFinder(BaseFinder): def find(self, pattern): for p in self.files.match(pattern): yield p, self.files[p] + + +class MercurialFile(BaseFile): + """File class for holding data from Mercurial.""" + def __init__(self, client, rev, path): + self._content = client.cat([path], rev=rev) + + def read(self): + return self._content + + +class MercurialRevisionFinder(BaseFinder): + """A finder that operates on a specific Mercurial revision.""" + + def __init__(self, repo, rev='.', **kwargs): + """Create a finder attached to a specific revision in a repository. + + If no revision is given, open the parent of the working directory. + """ + if not hglib: + raise Exception('hglib package not found') + + super(MercurialRevisionFinder, self).__init__(base=repo, **kwargs) + + self._root = repo + # We change directories here otherwise we have to deal with relative + # paths. + oldcwd = os.getcwd() + os.chdir(self._root) + try: + self._client = hglib.open(path=repo, encoding=b'utf-8') + finally: + os.chdir(oldcwd) + self._rev = rev if rev is not None else b'.' + self._files = OrderedDict() + + # Immediately populate the list of files in the repo since nearly every + # operation requires this list. + out = self._client.rawcommand([b'files', b'--rev', self._rev]) + for relpath in out.splitlines(): + self._files[relpath] = None + + def _find(self, pattern): + return self._find_helper(pattern, self._files, self._get) + + def get(self, path): + try: + return self._get(path) + except KeyError: + return None + + def _get(self, path): + # We lazy populate self._files because potentially creating tens of + # thousands of MercurialFile instances for every file in the repo is + # inefficient. + f = self._files[path] + if not f: + f = MercurialFile(self._client, self._rev, path) + self._files[path] = f + + return f diff --git a/python/mozbuild/mozpack/test/test_files.py b/python/mozbuild/mozpack/test/test_files.py index b1cb8f43bb6d..471ca58aaf0a 100644 --- a/python/mozbuild/mozpack/test/test_files.py +++ b/python/mozbuild/mozpack/test/test_files.py @@ -19,11 +19,20 @@ from mozpack.files import ( GeneratedFile, JarFinder, ManifestFile, + MercurialFile, + MercurialRevisionFinder, MinifiedJavaScript, MinifiedProperties, PreprocessedFile, XPTFile, ) + +# We don't have hglib installed everywhere. +try: + import hglib +except ImportError: + hglib = None + from mozpack.mozjar import ( JarReader, JarWriter, @@ -1017,5 +1026,61 @@ class TestComposedFinder(MatchTestTemplate, TestWithTmpDir): self.assertIsInstance(self.finder.get('bar'), File) +@unittest.skipUnless(hglib, 'hglib not available') +class TestMercurialRevisionFinder(MatchTestTemplate, TestWithTmpDir): + def setUp(self): + super(TestMercurialRevisionFinder, self).setUp() + hglib.init(self.tmpdir) + + def add(self, path): + c = hglib.open(self.tmpdir) + ensureParentDir(self.tmppath(path)) + with open(self.tmppath(path), 'wb') as fh: + fh.write(path) + c.add(self.tmppath(path)) + + def do_check(self, pattern, result): + do_check(self, self.finder, pattern, result) + + def test_default_revision(self): + self.prepare_match_test() + c = hglib.open(self.tmpdir) + c.commit('initial commit') + self.finder = MercurialRevisionFinder(self.tmpdir) + self.do_match_test() + + self.assertIsNone(self.finder.get('does-not-exist')) + self.assertIsInstance(self.finder.get('bar'), MercurialFile) + + def test_old_revision(self): + c = hglib.open(self.tmpdir) + with open(self.tmppath('foo'), 'wb') as fh: + fh.write('foo initial') + c.add(self.tmppath('foo')) + c.commit('initial') + + with open(self.tmppath('foo'), 'wb') as fh: + fh.write('foo second') + with open(self.tmppath('bar'), 'wb') as fh: + fh.write('bar second') + c.add(self.tmppath('bar')) + c.commit('second') + # This wipes out the working directory, ensuring the finder isn't + # finding anything from the filesystem. + c.rawcommand(['update', 'null']) + + finder = MercurialRevisionFinder(self.tmpdir, rev='0') + f = finder.get('foo') + self.assertEqual(f.read(), 'foo initial') + self.assertEqual(f.read(), 'foo initial', 'read again for good measure') + self.assertIsNone(finder.get('bar')) + + finder = MercurialRevisionFinder(self.tmpdir, rev='1') + f = finder.get('foo') + self.assertEqual(f.read(), 'foo second') + f = finder.get('bar') + self.assertEqual(f.read(), 'bar second') + + if __name__ == '__main__': mozunit.main() From ba5d71304d4b72ca9f6e3db6c1c0b82516526843 Mon Sep 17 00:00:00 2001 From: Gregory Szorc Date: Mon, 8 Jun 2015 09:33:46 -0700 Subject: [PATCH 42/95] Bug 1168607 - Add mode to MercurialFileFinder to support non-relative paths; r=glandium The moz.build reader uses absolute paths when referencing moz.build files. *Finder classes expect paths to be relative to a base. When we switched the reader to use *Finder instances for I/O, we simply provided a default FileFinder based at the filesystem root. This was quick and easy. Things worked. Unfortunately, that solution isn't ideal because not all *Finder instances can accept absolute paths like that. The MercurialRevisionFinder is one of them. Changing the moz.build reader to talk in terms of relative paths is a lot of work. While this would be ideal, it is significantly easier to defer the problem until later and hack up MercurialRevisionFinder to accept absolute paths. This commit does exactly that. Bug 1171069 has been filed to track converting BuildReader to relative paths. --HG-- extra : commitid : 2JmzOBldBLy extra : rebase_source : a8af6ce88dd9e2b98f131c92b45c3ece852e13d2 --- python/mozbuild/mozpack/files.py | 24 ++++++++++++++++++++-- python/mozbuild/mozpack/test/test_files.py | 22 ++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/python/mozbuild/mozpack/files.py b/python/mozbuild/mozpack/files.py index 7b779ea41adf..a3fd903161fb 100644 --- a/python/mozbuild/mozpack/files.py +++ b/python/mozbuild/mozpack/files.py @@ -978,17 +978,28 @@ class MercurialFile(BaseFile): class MercurialRevisionFinder(BaseFinder): """A finder that operates on a specific Mercurial revision.""" - def __init__(self, repo, rev='.', **kwargs): + def __init__(self, repo, rev='.', recognize_repo_paths=False, **kwargs): """Create a finder attached to a specific revision in a repository. If no revision is given, open the parent of the working directory. + + ``recognize_repo_paths`` will enable a mode where ``.get()`` will + recognize full paths that include the repo's path. Typically Finder + instances are "bound" to a base directory and paths are relative to + that directory. This mode changes that. When this mode is activated, + ``.find()`` will not work! This mode exists to support the moz.build + reader, which uses absolute paths instead of relative paths. The reader + should eventually be rewritten to use relative paths and this hack + should be removed (TODO bug 1171069). """ if not hglib: raise Exception('hglib package not found') super(MercurialRevisionFinder, self).__init__(base=repo, **kwargs) - self._root = repo + self._root = mozpath.normpath(repo).rstrip('/') + self._recognize_repo_paths = recognize_repo_paths + # We change directories here otherwise we have to deal with relative # paths. oldcwd = os.getcwd() @@ -1007,9 +1018,18 @@ class MercurialRevisionFinder(BaseFinder): self._files[relpath] = None def _find(self, pattern): + if self._recognize_repo_paths: + raise NotImplementedError('cannot use find with recognize_repo_path') + return self._find_helper(pattern, self._files, self._get) def get(self, path): + if self._recognize_repo_paths: + if not path.startswith(self._root): + raise ValueError('lookups in recognize_repo_paths mode must be ' + 'prefixed with repo path: %s' % path) + path = path[len(self._root) + 1:] + try: return self._get(path) except KeyError: diff --git a/python/mozbuild/mozpack/test/test_files.py b/python/mozbuild/mozpack/test/test_files.py index 471ca58aaf0a..db9ac081810f 100644 --- a/python/mozbuild/mozpack/test/test_files.py +++ b/python/mozbuild/mozpack/test/test_files.py @@ -1081,6 +1081,28 @@ class TestMercurialRevisionFinder(MatchTestTemplate, TestWithTmpDir): f = finder.get('bar') self.assertEqual(f.read(), 'bar second') + def test_recognize_repo_paths(self): + c = hglib.open(self.tmpdir) + with open(self.tmppath('foo'), 'wb') as fh: + fh.write('initial') + c.add(self.tmppath('foo')) + c.commit('initial') + c.rawcommand(['update', 'null']) + + finder = MercurialRevisionFinder(self.tmpdir, rev='0', + recognize_repo_paths=True) + with self.assertRaises(NotImplementedError): + list(finder.find('')) + + with self.assertRaises(ValueError): + finder.get('foo') + with self.assertRaises(ValueError): + finder.get('') + + f = finder.get(self.tmppath('foo')) + self.assertIsInstance(f, MercurialFile) + self.assertEqual(f.read(), 'initial') + if __name__ == '__main__': mozunit.main() From d5d6c72dd3f493cf26e5a08d6c8b892909654bea Mon Sep 17 00:00:00 2001 From: Gregory Szorc Date: Tue, 9 Jun 2015 13:43:22 -0700 Subject: [PATCH 43/95] Bug 1168607 - Make `mach file-info` work with Mercurial repos; r=glandium This commit adds support for specifying a Mercurial revision with `mach file-info`. Aside from being a potentially useful feature, it proves that MercurialRevisionFinder works with BuildReader. --HG-- extra : commitid : 7143XT9ENqb extra : rebase_source : d8c0c98d536d07db76653b648fd4b7d74d8f43ae --- .../mozbuild/frontend/mach_commands.py | 51 +++++++++++++++---- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/python/mozbuild/mozbuild/frontend/mach_commands.py b/python/mozbuild/mozbuild/frontend/mach_commands.py index 7e3c89d434f7..ff498c76c2d3 100644 --- a/python/mozbuild/mozbuild/frontend/mach_commands.py +++ b/python/mozbuild/mozbuild/frontend/mach_commands.py @@ -5,6 +5,7 @@ from __future__ import print_function, unicode_literals from collections import defaultdict +import os from mach.decorators import ( CommandArgument, @@ -88,12 +89,14 @@ class MozbuildFileCommands(MachCommandBase): @SubCommand('file-info', 'bugzilla-component', 'Show Bugzilla component info for files listed.') + @CommandArgument('-r', '--rev', + help='Version control revision to look up info from') @CommandArgument('paths', nargs='+', help='Paths whose data to query') - def file_info_bugzilla(self, paths): + def file_info_bugzilla(self, paths, rev=None): components = defaultdict(set) try: - for p, m in self._get_files_info(paths).items(): + for p, m in self._get_files_info(paths, rev=rev).items(): components[m.get('BUG_COMPONENT')].add(p) except InvalidPathException as e: print(e.message) @@ -106,24 +109,31 @@ class MozbuildFileCommands(MachCommandBase): @SubCommand('file-info', 'missing-bugzilla', 'Show files missing Bugzilla component info') + @CommandArgument('-r', '--rev', + help='Version control revision to look up info from') @CommandArgument('paths', nargs='+', help='Paths whose data to query') - def file_info_missing_bugzilla(self, paths): + def file_info_missing_bugzilla(self, paths, rev=None): try: - for p, m in sorted(self._get_files_info(paths).items()): + for p, m in sorted(self._get_files_info(paths, rev=rev).items()): if 'BUG_COMPONENT' not in m: print(p) except InvalidPathException as e: print(e.message) return 1 - def _get_reader(self): - from mozbuild.frontend.reader import BuildReader, EmptyConfig - config = EmptyConfig(self.topsrcdir) - return BuildReader(config) + def _get_reader(self, finder): + from mozbuild.frontend.reader import ( + BuildReader, + EmptyConfig, + ) - def _get_files_info(self, paths): - from mozpack.files import FileFinder + config = EmptyConfig(self.topsrcdir) + return BuildReader(config, finder=finder) + + def _get_files_info(self, paths, rev=None): + from mozbuild.frontend.reader import default_finder + from mozpack.files import FileFinder, MercurialRevisionFinder # Normalize to relative from topsrcdir. relpaths = [] @@ -134,7 +144,23 @@ class MozbuildFileCommands(MachCommandBase): relpaths.append(mozpath.relpath(a, self.topsrcdir)) + repo = None + if rev: + hg_path = os.path.join(self.topsrcdir, '.hg') + if not os.path.exists(hg_path): + raise InvalidPathException('a Mercurial repo is required ' + 'when specifying a revision') + + repo = self.topsrcdir + + # We need two finders because the reader's finder operates on + # absolute paths. finder = FileFinder(self.topsrcdir, find_executables=False) + if repo: + reader_finder = MercurialRevisionFinder(repo, rev=rev, + recognize_repo_paths=True) + else: + reader_finder = default_finder # Expand wildcards. allpaths = [] @@ -144,9 +170,12 @@ class MozbuildFileCommands(MachCommandBase): allpaths.append(p) continue + if repo: + raise InvalidPathException('cannot use wildcard in version control mode') + for path, f in finder.find(p): if path not in allpaths: allpaths.append(path) - reader = self._get_reader() + reader = self._get_reader(finder=reader_finder) return reader.files_info(allpaths) From 013f437636845d1c735facdfb4a2bc1493a87377 Mon Sep 17 00:00:00 2001 From: Gregory Szorc Date: Tue, 9 Jun 2015 13:49:45 -0700 Subject: [PATCH 44/95] Bug 1168607 - Add a native Mercurial finder; r=glandium The hglib Mercurial finder was nice. But it is somewhat slow, as it involves a separate Mercurial process. This commit introduces a native Mercurial finder that speaks directly to a Mercurial repository instance. It is significantly faster. The new code is isolated to its own file because it imports Mercurial code, which is GPL. --HG-- extra : commitid : 8CzDFt3lQmx extra : rebase_source : 1540ad20d795086926b316612062e2a1f10c4958 --- python/mozbuild/mozpack/files.py | 2 +- python/mozbuild/mozpack/hg.py | 93 ++++++++++++++++++++++ python/mozbuild/mozpack/test/test_files.py | 24 ++++-- 3 files changed, 113 insertions(+), 6 deletions(-) create mode 100644 python/mozbuild/mozpack/hg.py diff --git a/python/mozbuild/mozpack/files.py b/python/mozbuild/mozpack/files.py index a3fd903161fb..e0681f490b21 100644 --- a/python/mozbuild/mozpack/files.py +++ b/python/mozbuild/mozpack/files.py @@ -1013,7 +1013,7 @@ class MercurialRevisionFinder(BaseFinder): # Immediately populate the list of files in the repo since nearly every # operation requires this list. - out = self._client.rawcommand([b'files', b'--rev', self._rev]) + out = self._client.rawcommand([b'files', b'--rev', str(self._rev)]) for relpath in out.splitlines(): self._files[relpath] = None diff --git a/python/mozbuild/mozpack/hg.py b/python/mozbuild/mozpack/hg.py new file mode 100644 index 000000000000..3971ec6fd573 --- /dev/null +++ b/python/mozbuild/mozpack/hg.py @@ -0,0 +1,93 @@ +# Copyright (C) 2015 Mozilla Contributors +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# As a special exception, the copyright holders of this code give you +# permission to combine this code with the software known as 'mozbuild', +# and to distribute those combinations without any restriction +# coming from the use of this file. (The General Public License +# restrictions do apply in other respects; for example, they cover +# modification of the file, and distribution when not combined with +# mozbuild.) +# +# If you modify this code, you may extend this exception to your +# version of the code, but you are not obliged to do so. If you +# do not wish to do so, delete this exception statement from your +# version. + +import mercurial.error as error +import mercurial.hg as hg +import mercurial.ui as hgui + +from .files import ( + BaseFinder, + MercurialFile, +) +import mozpack.path as mozpath + + +# This isn't a complete implementation of BaseFile. But it is complete +# enough for moz.build reading. +class MercurialNativeFile(MercurialFile): + def __init__(self, data): + self.data = data + + def read(self): + return self.data + + +class MercurialNativeRevisionFinder(BaseFinder): + def __init__(self, repo, rev='.', recognize_repo_paths=False): + """Create a finder attached to a specific changeset. + + Accepts a Mercurial localrepo and changectx instance. + """ + if isinstance(repo, (str, unicode)): + path = repo + repo = hg.repository(hgui.ui(), repo) + else: + path = repo.root + + super(MercurialNativeRevisionFinder, self).__init__(base=repo.root) + + self._repo = repo + self._rev = rev + self._root = mozpath.normpath(path) + self._recognize_repo_paths = recognize_repo_paths + + def _find(self, pattern): + if self._recognize_repo_paths: + raise NotImplementedError('cannot use find with recognize_repo_path') + + return self._find_helper(pattern, self._repo[self._rev], self._get) + + def get(self, path): + if self._recognize_repo_paths: + if not path.startswith(self._root): + raise ValueError('lookups in recognize_repo_paths mode must be ' + 'prefixed with repo path: %s' % path) + path = path[len(self._root) + 1:] + + return self._get(path) + + def _get(self, path): + if isinstance(path, unicode): + path = path.encode('utf-8', 'replace') + + try: + fctx = self._repo.filectx(path, self._rev) + return MercurialNativeFile(fctx.data()) + except error.LookupError: + return None diff --git a/python/mozbuild/mozpack/test/test_files.py b/python/mozbuild/mozpack/test/test_files.py index db9ac081810f..ccd2b978b6f5 100644 --- a/python/mozbuild/mozpack/test/test_files.py +++ b/python/mozbuild/mozpack/test/test_files.py @@ -33,6 +33,11 @@ try: except ImportError: hglib = None +try: + from mozpack.hg import MercurialNativeRevisionFinder +except ImportError: + MercurialNativeRevisionFinder = None + from mozpack.mozjar import ( JarReader, JarWriter, @@ -1042,11 +1047,14 @@ class TestMercurialRevisionFinder(MatchTestTemplate, TestWithTmpDir): def do_check(self, pattern, result): do_check(self, self.finder, pattern, result) + def _get_finder(self, *args, **kwargs): + return MercurialRevisionFinder(*args, **kwargs) + def test_default_revision(self): self.prepare_match_test() c = hglib.open(self.tmpdir) c.commit('initial commit') - self.finder = MercurialRevisionFinder(self.tmpdir) + self.finder = self._get_finder(self.tmpdir) self.do_match_test() self.assertIsNone(self.finder.get('does-not-exist')) @@ -1069,13 +1077,13 @@ class TestMercurialRevisionFinder(MatchTestTemplate, TestWithTmpDir): # finding anything from the filesystem. c.rawcommand(['update', 'null']) - finder = MercurialRevisionFinder(self.tmpdir, rev='0') + finder = self._get_finder(self.tmpdir, 0) f = finder.get('foo') self.assertEqual(f.read(), 'foo initial') self.assertEqual(f.read(), 'foo initial', 'read again for good measure') self.assertIsNone(finder.get('bar')) - finder = MercurialRevisionFinder(self.tmpdir, rev='1') + finder = MercurialRevisionFinder(self.tmpdir, rev=1) f = finder.get('foo') self.assertEqual(f.read(), 'foo second') f = finder.get('bar') @@ -1089,8 +1097,8 @@ class TestMercurialRevisionFinder(MatchTestTemplate, TestWithTmpDir): c.commit('initial') c.rawcommand(['update', 'null']) - finder = MercurialRevisionFinder(self.tmpdir, rev='0', - recognize_repo_paths=True) + finder = self._get_finder(self.tmpdir, 0, + recognize_repo_paths=True) with self.assertRaises(NotImplementedError): list(finder.find('')) @@ -1104,5 +1112,11 @@ class TestMercurialRevisionFinder(MatchTestTemplate, TestWithTmpDir): self.assertEqual(f.read(), 'initial') +@unittest.skipUnless(MercurialNativeRevisionFinder, 'hgnative not available') +class TestMercurialNativeRevisionFinder(TestMercurialRevisionFinder): + def _get_finder(self, *args, **kwargs): + return MercurialNativeRevisionFinder(*args, **kwargs) + + if __name__ == '__main__': mozunit.main() From 008f4df152aafcfc7ba3c0166a395c591d76f0d7 Mon Sep 17 00:00:00 2001 From: Eric Rahm Date: Tue, 9 Jun 2015 18:25:43 -0700 Subject: [PATCH 45/95] Bug 1171716 - Part 1: Add NS_ReleaseOnMainThread. r=froydnj --- xpcom/glue/nsProxyRelease.h | 58 ++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/xpcom/glue/nsProxyRelease.h b/xpcom/glue/nsProxyRelease.h index 5d95780d226f..d98a01b46f92 100644 --- a/xpcom/glue/nsProxyRelease.h +++ b/xpcom/glue/nsProxyRelease.h @@ -57,7 +57,7 @@ NS_ProxyRelease(nsIEventTarget* aTarget, nsRefPtr& aDoomed, * the doomed object; the object to be released on the target thread. * @param aAlwaysProxy * normally, if NS_ProxyRelease is called on the target thread, then the - * doomed object will released directly. however, if this parameter is + * doomed object will be released directly. However, if this parameter is * true, then an event will always be posted to the target thread for * asynchronous release. */ @@ -65,6 +65,62 @@ nsresult NS_ProxyRelease(nsIEventTarget* aTarget, nsISupports* aDoomed, bool aAlwaysProxy = false); +/** + * Ensure that a nsCOMPtr is released on the main thread. + * + * @see NS_ReleaseOnMainThread( nsISupports*, bool) + */ +template +inline NS_HIDDEN_(nsresult) +NS_ReleaseOnMainThread(nsCOMPtr& aDoomed, + bool aAlwaysProxy = false) +{ + T* raw = nullptr; + aDoomed.swap(raw); + return NS_ReleaseOnMainThread(raw, aAlwaysProxy); +} + +/** + * Ensure that a nsRefPtr is released on the main thread. + * + * @see NS_ReleaseOnMainThread(nsISupports*, bool) + */ +template +inline NS_HIDDEN_(nsresult) +NS_ReleaseOnMainThread(nsRefPtr& aDoomed, + bool aAlwaysProxy = false) +{ + T* raw = nullptr; + aDoomed.swap(raw); + return NS_ReleaseOnMainThread(raw, aAlwaysProxy); +} + +/** + * Ensures that the delete of a nsISupports object occurs on the main thread. + * + * @param aDoomed + * the doomed object; the object to be released on the main thread. + * @param aAlwaysProxy + * normally, if NS_ReleaseOnMainThread is called on the main thread, + * then the doomed object will be released directly. However, if this + * parameter is true, then an event will always be posted to the main + * thread for asynchronous release. + */ +nsresult +NS_ReleaseOnMainThread(nsISupports* aDoomed, + bool aAlwaysProxy = false) +{ + // NS_ProxyRelease treats a null event target as "the current thread". So a + // handle on the main thread is only necessary when we're not already on the + // main thread or the release must happen asynchronously. + nsCOMPtr mainThread; + if (!NS_IsMainThread() || aAlwaysProxy) { + NS_GetMainThread(getter_AddRefs(mainThread)); + } + + return NS_ProxyRelease(mainThread, aDoomed, aAlwaysProxy); +} + /** * Class to safely handle main-thread-only pointers off the main thread. * From 1f36355681d09a047a9f71fdb3c5170e3a609d7e Mon Sep 17 00:00:00 2001 From: Eric Rahm Date: Tue, 9 Jun 2015 18:25:44 -0700 Subject: [PATCH 46/95] Bug 1171716 - Part 2: Use NS_ReleaseOnMainThread in nsBaseChannel. r=froydnj --- netwerk/base/nsBaseChannel.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/netwerk/base/nsBaseChannel.cpp b/netwerk/base/nsBaseChannel.cpp index 342048032283..7baffeedf731 100644 --- a/netwerk/base/nsBaseChannel.cpp +++ b/netwerk/base/nsBaseChannel.cpp @@ -69,14 +69,7 @@ nsBaseChannel::nsBaseChannel() nsBaseChannel::~nsBaseChannel() { - if (mLoadInfo) { - nsCOMPtr mainThread; - NS_GetMainThread(getter_AddRefs(mainThread)); - - nsILoadInfo *forgetableLoadInfo; - mLoadInfo.forget(&forgetableLoadInfo); - NS_ProxyRelease(mainThread, forgetableLoadInfo, false); - } + NS_ReleaseOnMainThread(mLoadInfo); } nsresult From 42e8d5e05f18e056d74cbabf87fa339e06aa1b1c Mon Sep 17 00:00:00 2001 From: Eric Rahm Date: Tue, 9 Jun 2015 18:25:46 -0700 Subject: [PATCH 47/95] Bug 1171716 - Part 3: Use NS_ReleaseOnMainThread in WebSocketChannel dtor. r=froydnj --- .../protocol/websocket/WebSocketChannel.cpp | 28 +++---------------- 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/netwerk/protocol/websocket/WebSocketChannel.cpp b/netwerk/protocol/websocket/WebSocketChannel.cpp index 856c397f4082..5016c1ad5704 100644 --- a/netwerk/protocol/websocket/WebSocketChannel.cpp +++ b/netwerk/protocol/websocket/WebSocketChannel.cpp @@ -1185,33 +1185,13 @@ WebSocketChannel::~WebSocketChannel() while ((mCurrentOut = (OutboundMessage *) mOutgoingMessages.PopFront())) delete mCurrentOut; - nsCOMPtr mainThread; - nsIURI *forgettable; - NS_GetMainThread(getter_AddRefs(mainThread)); - - if (mURI) { - mURI.forget(&forgettable); - NS_ProxyRelease(mainThread, forgettable, false); - } - - if (mOriginalURI) { - mOriginalURI.forget(&forgettable); - NS_ProxyRelease(mainThread, forgettable, false); - } + NS_ReleaseOnMainThread(mURI); + NS_ReleaseOnMainThread(mOriginalURI); mListenerMT = nullptr; - if (mLoadGroup) { - nsILoadGroup *forgettableGroup; - mLoadGroup.forget(&forgettableGroup); - NS_ProxyRelease(mainThread, forgettableGroup, false); - } - - if (mLoadInfo) { - nsILoadInfo *forgetableLoadInfo; - mLoadInfo.forget(&forgetableLoadInfo); - NS_ProxyRelease(mainThread, forgetableLoadInfo, false); - } + NS_ReleaseOnMainThread(mLoadGroup); + NS_ReleaseOnMainThread(mLoadInfo); } NS_IMETHODIMP From e773b354158f93e9dfbb27253cb246d39dbab732 Mon Sep 17 00:00:00 2001 From: Eric Rahm Date: Tue, 9 Jun 2015 18:25:47 -0700 Subject: [PATCH 48/95] Bug 1171716 - Part 4: Use NS_ReleaseOnMainThread in JarChannel dtor. r=froydnj --- modules/libjar/nsJARChannel.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/modules/libjar/nsJARChannel.cpp b/modules/libjar/nsJARChannel.cpp index 7addea33fa1d..304deba2e5c5 100644 --- a/modules/libjar/nsJARChannel.cpp +++ b/modules/libjar/nsJARChannel.cpp @@ -213,14 +213,7 @@ nsJARChannel::nsJARChannel() nsJARChannel::~nsJARChannel() { - if (mLoadInfo) { - nsCOMPtr mainThread; - NS_GetMainThread(getter_AddRefs(mainThread)); - - nsILoadInfo *forgetableLoadInfo; - mLoadInfo.forget(&forgetableLoadInfo); - NS_ProxyRelease(mainThread, forgetableLoadInfo, false); - } + NS_ReleaseOnMainThread(mLoadInfo); // release owning reference to the jar handler nsJARProtocolHandler *handler = gJarHandler; From 3d28a45468c40e4802a6dd9a3e8410b1890a575a Mon Sep 17 00:00:00 2001 From: Eric Rahm Date: Tue, 9 Jun 2015 18:25:48 -0700 Subject: [PATCH 49/95] Bug 1171716 - Part 5: Use NS_ReleaseOnMainThread in HttpBaseChannel dtor. r=froydnj --- netwerk/protocol/http/HttpBaseChannel.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp index 454bcd0e2e0a..c53b98b35d37 100644 --- a/netwerk/protocol/http/HttpBaseChannel.cpp +++ b/netwerk/protocol/http/HttpBaseChannel.cpp @@ -103,14 +103,7 @@ HttpBaseChannel::~HttpBaseChannel() { LOG(("Destroying HttpBaseChannel @%x\n", this)); - if (mLoadInfo) { - nsCOMPtr mainThread; - NS_GetMainThread(getter_AddRefs(mainThread)); - - nsILoadInfo *forgetableLoadInfo; - mLoadInfo.forget(&forgetableLoadInfo); - NS_ProxyRelease(mainThread, forgetableLoadInfo, false); - } + NS_ReleaseOnMainThread(mLoadInfo); // Make sure we don't leak CleanRedirectCacheChainIfNecessary(); From 54bccdc15f67e4c2c57002533b43b1808f97bb42 Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Tue, 9 Jun 2015 18:48:37 -0700 Subject: [PATCH 50/95] Backed out 5 changesets (bug 1171716) for android bustage Backed out changeset 4986f8464f9c (bug 1171716) Backed out changeset bc8405b07d10 (bug 1171716) Backed out changeset 10e18e494630 (bug 1171716) Backed out changeset be499a3cae5d (bug 1171716) Backed out changeset f75717d3eba0 (bug 1171716) --- modules/libjar/nsJARChannel.cpp | 9 ++- netwerk/base/nsBaseChannel.cpp | 9 ++- netwerk/protocol/http/HttpBaseChannel.cpp | 9 ++- .../protocol/websocket/WebSocketChannel.cpp | 28 +++++++-- xpcom/glue/nsProxyRelease.h | 58 +------------------ 5 files changed, 49 insertions(+), 64 deletions(-) diff --git a/modules/libjar/nsJARChannel.cpp b/modules/libjar/nsJARChannel.cpp index 304deba2e5c5..7addea33fa1d 100644 --- a/modules/libjar/nsJARChannel.cpp +++ b/modules/libjar/nsJARChannel.cpp @@ -213,7 +213,14 @@ nsJARChannel::nsJARChannel() nsJARChannel::~nsJARChannel() { - NS_ReleaseOnMainThread(mLoadInfo); + if (mLoadInfo) { + nsCOMPtr mainThread; + NS_GetMainThread(getter_AddRefs(mainThread)); + + nsILoadInfo *forgetableLoadInfo; + mLoadInfo.forget(&forgetableLoadInfo); + NS_ProxyRelease(mainThread, forgetableLoadInfo, false); + } // release owning reference to the jar handler nsJARProtocolHandler *handler = gJarHandler; diff --git a/netwerk/base/nsBaseChannel.cpp b/netwerk/base/nsBaseChannel.cpp index 7baffeedf731..342048032283 100644 --- a/netwerk/base/nsBaseChannel.cpp +++ b/netwerk/base/nsBaseChannel.cpp @@ -69,7 +69,14 @@ nsBaseChannel::nsBaseChannel() nsBaseChannel::~nsBaseChannel() { - NS_ReleaseOnMainThread(mLoadInfo); + if (mLoadInfo) { + nsCOMPtr mainThread; + NS_GetMainThread(getter_AddRefs(mainThread)); + + nsILoadInfo *forgetableLoadInfo; + mLoadInfo.forget(&forgetableLoadInfo); + NS_ProxyRelease(mainThread, forgetableLoadInfo, false); + } } nsresult diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp index c53b98b35d37..454bcd0e2e0a 100644 --- a/netwerk/protocol/http/HttpBaseChannel.cpp +++ b/netwerk/protocol/http/HttpBaseChannel.cpp @@ -103,7 +103,14 @@ HttpBaseChannel::~HttpBaseChannel() { LOG(("Destroying HttpBaseChannel @%x\n", this)); - NS_ReleaseOnMainThread(mLoadInfo); + if (mLoadInfo) { + nsCOMPtr mainThread; + NS_GetMainThread(getter_AddRefs(mainThread)); + + nsILoadInfo *forgetableLoadInfo; + mLoadInfo.forget(&forgetableLoadInfo); + NS_ProxyRelease(mainThread, forgetableLoadInfo, false); + } // Make sure we don't leak CleanRedirectCacheChainIfNecessary(); diff --git a/netwerk/protocol/websocket/WebSocketChannel.cpp b/netwerk/protocol/websocket/WebSocketChannel.cpp index 5016c1ad5704..856c397f4082 100644 --- a/netwerk/protocol/websocket/WebSocketChannel.cpp +++ b/netwerk/protocol/websocket/WebSocketChannel.cpp @@ -1185,13 +1185,33 @@ WebSocketChannel::~WebSocketChannel() while ((mCurrentOut = (OutboundMessage *) mOutgoingMessages.PopFront())) delete mCurrentOut; - NS_ReleaseOnMainThread(mURI); - NS_ReleaseOnMainThread(mOriginalURI); + nsCOMPtr mainThread; + nsIURI *forgettable; + NS_GetMainThread(getter_AddRefs(mainThread)); + + if (mURI) { + mURI.forget(&forgettable); + NS_ProxyRelease(mainThread, forgettable, false); + } + + if (mOriginalURI) { + mOriginalURI.forget(&forgettable); + NS_ProxyRelease(mainThread, forgettable, false); + } mListenerMT = nullptr; - NS_ReleaseOnMainThread(mLoadGroup); - NS_ReleaseOnMainThread(mLoadInfo); + if (mLoadGroup) { + nsILoadGroup *forgettableGroup; + mLoadGroup.forget(&forgettableGroup); + NS_ProxyRelease(mainThread, forgettableGroup, false); + } + + if (mLoadInfo) { + nsILoadInfo *forgetableLoadInfo; + mLoadInfo.forget(&forgetableLoadInfo); + NS_ProxyRelease(mainThread, forgetableLoadInfo, false); + } } NS_IMETHODIMP diff --git a/xpcom/glue/nsProxyRelease.h b/xpcom/glue/nsProxyRelease.h index d98a01b46f92..5d95780d226f 100644 --- a/xpcom/glue/nsProxyRelease.h +++ b/xpcom/glue/nsProxyRelease.h @@ -57,7 +57,7 @@ NS_ProxyRelease(nsIEventTarget* aTarget, nsRefPtr& aDoomed, * the doomed object; the object to be released on the target thread. * @param aAlwaysProxy * normally, if NS_ProxyRelease is called on the target thread, then the - * doomed object will be released directly. However, if this parameter is + * doomed object will released directly. however, if this parameter is * true, then an event will always be posted to the target thread for * asynchronous release. */ @@ -65,62 +65,6 @@ nsresult NS_ProxyRelease(nsIEventTarget* aTarget, nsISupports* aDoomed, bool aAlwaysProxy = false); -/** - * Ensure that a nsCOMPtr is released on the main thread. - * - * @see NS_ReleaseOnMainThread( nsISupports*, bool) - */ -template -inline NS_HIDDEN_(nsresult) -NS_ReleaseOnMainThread(nsCOMPtr& aDoomed, - bool aAlwaysProxy = false) -{ - T* raw = nullptr; - aDoomed.swap(raw); - return NS_ReleaseOnMainThread(raw, aAlwaysProxy); -} - -/** - * Ensure that a nsRefPtr is released on the main thread. - * - * @see NS_ReleaseOnMainThread(nsISupports*, bool) - */ -template -inline NS_HIDDEN_(nsresult) -NS_ReleaseOnMainThread(nsRefPtr& aDoomed, - bool aAlwaysProxy = false) -{ - T* raw = nullptr; - aDoomed.swap(raw); - return NS_ReleaseOnMainThread(raw, aAlwaysProxy); -} - -/** - * Ensures that the delete of a nsISupports object occurs on the main thread. - * - * @param aDoomed - * the doomed object; the object to be released on the main thread. - * @param aAlwaysProxy - * normally, if NS_ReleaseOnMainThread is called on the main thread, - * then the doomed object will be released directly. However, if this - * parameter is true, then an event will always be posted to the main - * thread for asynchronous release. - */ -nsresult -NS_ReleaseOnMainThread(nsISupports* aDoomed, - bool aAlwaysProxy = false) -{ - // NS_ProxyRelease treats a null event target as "the current thread". So a - // handle on the main thread is only necessary when we're not already on the - // main thread or the release must happen asynchronously. - nsCOMPtr mainThread; - if (!NS_IsMainThread() || aAlwaysProxy) { - NS_GetMainThread(getter_AddRefs(mainThread)); - } - - return NS_ProxyRelease(mainThread, aDoomed, aAlwaysProxy); -} - /** * Class to safely handle main-thread-only pointers off the main thread. * From f61d5cbfd528be65465ad3af6c788008a9a57e29 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Tue, 9 Jun 2015 09:54:24 +0900 Subject: [PATCH 51/95] Bug 1172632 - Don't guess malloc_usable_size type of argument based on ANDROID_VERSION in mozjemalloc, but use the result of the configure test instead. r=njn --- memory/mozjemalloc/jemalloc.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/memory/mozjemalloc/jemalloc.c b/memory/mozjemalloc/jemalloc.c index f8e36e178a9f..9113d2676a78 100644 --- a/memory/mozjemalloc/jemalloc.c +++ b/memory/mozjemalloc/jemalloc.c @@ -6514,13 +6514,8 @@ malloc_good_size_impl(size_t size) } -#if defined(MOZ_MEMORY_ANDROID) && (ANDROID_VERSION < 19) MOZ_MEMORY_API size_t -malloc_usable_size_impl(void *ptr) -#else -MOZ_MEMORY_API size_t -malloc_usable_size_impl(const void *ptr) -#endif +malloc_usable_size_impl(MALLOC_USABLE_SIZE_CONST_PTR void *ptr) { DARWIN_ONLY(return (szone->size)(szone, ptr)); From d2f37fb96902ccb91f25c7121b2eab361ee7240d Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Wed, 10 Jun 2015 09:58:50 +0900 Subject: [PATCH 52/95] bug 1172632 - Move some allocator related configure checks in a common location for both top-level and js/src to use. r=mshal --- aclocal.m4 | 1 + build/autoconf/alloc.m4 | 53 +++++++++++++++++++++++++++++++++++++++++ configure.in | 46 +---------------------------------- js/src/aclocal.m4 | 1 + js/src/configure.in | 13 ++-------- 5 files changed, 58 insertions(+), 56 deletions(-) create mode 100644 build/autoconf/alloc.m4 diff --git a/aclocal.m4 b/aclocal.m4 index 90356f99b79b..5f3065187022 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -33,6 +33,7 @@ builtin(include, build/autoconf/winsdk.m4)dnl builtin(include, build/autoconf/icu.m4)dnl builtin(include, build/autoconf/ffi.m4)dnl builtin(include, build/autoconf/clang-plugin.m4)dnl +builtin(include, build/autoconf/alloc.m4)dnl MOZ_PROG_CHECKMSYS() diff --git a/build/autoconf/alloc.m4 b/build/autoconf/alloc.m4 new file mode 100644 index 000000000000..8234a608d44d --- /dev/null +++ b/build/autoconf/alloc.m4 @@ -0,0 +1,53 @@ +dnl This Source Code Form is subject to the terms of the Mozilla Public +dnl License, v. 2.0. If a copy of the MPL was not distributed with this +dnl file, You can obtain one at http://mozilla.org/MPL/2.0/. + +dnl Check for the existence of various allocation headers/functions +AC_DEFUN([MOZ_CHECK_ALLOCATOR],[ + +MALLOC_HEADERS="malloc.h malloc_np.h malloc/malloc.h sys/malloc.h" +MALLOC_H= + +for file in $MALLOC_HEADERS; do + MOZ_CHECK_HEADER($file, [MALLOC_H=$file]) + if test "$MALLOC_H" != ""; then + AC_DEFINE_UNQUOTED(MALLOC_H, <$MALLOC_H>) + break + fi +done + +MOZ_CHECK_HEADERS(alloca.h) + +AC_CHECK_FUNCS(strndup posix_memalign memalign) + +AC_CHECK_FUNCS(malloc_usable_size) +MALLOC_USABLE_SIZE_CONST_PTR=const +MOZ_CHECK_HEADERS([malloc.h], [ + AC_MSG_CHECKING([whether malloc_usable_size definition can use const argument]) + AC_TRY_COMPILE([#include + #include + size_t malloc_usable_size(const void *ptr);], + [return malloc_usable_size(0);], + AC_MSG_RESULT([yes]), + AC_MSG_RESULT([no]) + MALLOC_USABLE_SIZE_CONST_PTR=) +]) +AC_DEFINE_UNQUOTED([MALLOC_USABLE_SIZE_CONST_PTR],[$MALLOC_USABLE_SIZE_CONST_PTR]) + + +dnl In newer bionic headers, valloc is built but not defined, +dnl so we check more carefully here. +AC_MSG_CHECKING([for valloc in malloc.h]) +AC_EGREP_HEADER(valloc, malloc.h, + AC_DEFINE(HAVE_VALLOC) + AC_MSG_RESULT([yes]), + AC_MSG_RESULT([no])) + +AC_MSG_CHECKING([for valloc in unistd.h]) +AC_EGREP_HEADER(valloc, unistd.h, + AC_DEFINE(HAVE_VALLOC) + AC_MSG_RESULT([yes]), + AC_MSG_RESULT([no])) + + +]) diff --git a/configure.in b/configure.in index 0d541675bd58..988797d65255 100644 --- a/configure.in +++ b/configure.in @@ -3399,51 +3399,7 @@ if test -n "$MOZ_LINKER" -a "$OS_TARGET" = "Android"; then fi fi -dnl Check for the existence of various allocation headers/functions - -MALLOC_HEADERS="malloc.h malloc_np.h malloc/malloc.h sys/malloc.h" -MALLOC_H= - -for file in $MALLOC_HEADERS; do - MOZ_CHECK_HEADER($file, [MALLOC_H=$file]) - if test "$MALLOC_H" != ""; then - AC_DEFINE_UNQUOTED(MALLOC_H, <$MALLOC_H>) - break - fi -done - -MOZ_CHECK_HEADERS(alloca.h) - -AC_CHECK_FUNCS(strndup posix_memalign memalign) - -AC_CHECK_FUNCS(malloc_usable_size) -MALLOC_USABLE_SIZE_CONST_PTR=const -MOZ_CHECK_HEADERS([malloc.h], [ - AC_MSG_CHECKING([whether malloc_usable_size definition can use const argument]) - AC_TRY_COMPILE([#include - #include - size_t malloc_usable_size(const void *ptr);], - [return malloc_usable_size(0);], - AC_MSG_RESULT([yes]), - AC_MSG_RESULT([no]) - MALLOC_USABLE_SIZE_CONST_PTR=) -]) -AC_DEFINE_UNQUOTED([MALLOC_USABLE_SIZE_CONST_PTR],[$MALLOC_USABLE_SIZE_CONST_PTR]) - - -dnl In newer bionic headers, valloc is built but not defined, -dnl so we check more carefully here. -AC_MSG_CHECKING([for valloc in malloc.h]) -AC_EGREP_HEADER(valloc, malloc.h, - AC_DEFINE(HAVE_VALLOC) - AC_MSG_RESULT([yes]), - AC_MSG_RESULT([no])) - -AC_MSG_CHECKING([for valloc in unistd.h]) -AC_EGREP_HEADER(valloc, unistd.h, - AC_DEFINE(HAVE_VALLOC) - AC_MSG_RESULT([yes]), - AC_MSG_RESULT([no])) +MOZ_CHECK_ALLOCATOR dnl See if compiler supports some gcc-style attributes diff --git a/js/src/aclocal.m4 b/js/src/aclocal.m4 index 99c73acc12ac..fc36340880f8 100644 --- a/js/src/aclocal.m4 +++ b/js/src/aclocal.m4 @@ -32,6 +32,7 @@ builtin(include, ../../build/autoconf/winsdk.m4)dnl builtin(include, ../../build/autoconf/icu.m4)dnl builtin(include, ../../build/autoconf/ffi.m4)dnl builtin(include, ../../build/autoconf/clang-plugin.m4)dnl +builtin(include, ../../build/autoconf/alloc.m4)dnl define([__MOZ_AC_INIT_PREPARE], defn([AC_INIT_PREPARE])) define([AC_INIT_PREPARE], diff --git a/js/src/configure.in b/js/src/configure.in index 9c21772292d3..4f72dc31d569 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -3847,18 +3847,9 @@ dnl ======================================================== dnl JavaScript shell dnl ======================================================== -MALLOC_HEADERS="malloc.h malloc_np.h malloc/malloc.h sys/malloc.h" -MALLOC_H= +MOZ_CHECK_ALLOCATOR -for file in $MALLOC_HEADERS; do - MOZ_CHECK_HEADER($file, [MALLOC_H=$file]) - if test "$MALLOC_H" != ""; then - AC_DEFINE_UNQUOTED(MALLOC_H, <$MALLOC_H>) - break - fi -done - -AC_CHECK_FUNCS(setlocale localeconv malloc_size malloc_usable_size) +AC_CHECK_FUNCS(setlocale localeconv) AC_SUBST(MOZILLA_VERSION) From 68221d7d351362fb61a7acbd2548d4494b638cac Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Wed, 10 Jun 2015 09:00:34 +0900 Subject: [PATCH 53/95] Bug 1172668 - Unbreak DMD on OS X after bug 1168719. r=gps Bug 1168719 added a generic replace malloc library which name happened to be the same as the existing dummy library used to link replace malloc on OSX. Change the name of that dummy library. --- memory/replace/dummy/moz.build | 2 +- mozglue/build/replace_malloc.mk | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/memory/replace/dummy/moz.build b/memory/replace/dummy/moz.build index 219598d88b1b..7bc32fb1f3e4 100644 --- a/memory/replace/dummy/moz.build +++ b/memory/replace/dummy/moz.build @@ -9,6 +9,6 @@ SOURCES += [ 'dummy_replace_malloc.c', ] -SharedLibrary('replace_malloc') +SharedLibrary('dummy_replace_malloc') DISABLE_STL_WRAPPING = True diff --git a/mozglue/build/replace_malloc.mk b/mozglue/build/replace_malloc.mk index 467f2a5c80a6..7f436f2eea3b 100644 --- a/mozglue/build/replace_malloc.mk +++ b/mozglue/build/replace_malloc.mk @@ -25,6 +25,8 @@ ifneq ($(MOZ_REPLACE_MALLOC_LINKAGE),compiler support) OS_LDFLAGS += -flat_namespace endif ifeq ($(MOZ_REPLACE_MALLOC_LINKAGE),dummy library) -OS_LDFLAGS += -Wl,-weak_library,$(DEPTH)/memory/replace/dummy/$(DLL_PREFIX)replace_malloc$(DLL_SUFFIX) +OS_LDFLAGS += -Wl,-weak_library,$(DEPTH)/memory/replace/dummy/$(DLL_PREFIX)dummy_replace_malloc$(DLL_SUFFIX) endif + +EXTRA_DEPS += $(topsrcdir)/mozglue/build/replace_malloc.mk endif From 7cbdd8c8fdedc2ecb5f15928d20dc9221114a242 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Wed, 10 Jun 2015 09:21:24 +0900 Subject: [PATCH 54/95] Bug 1169769 - Stop pretending js/src is a top-level directory. r=gps It hasn't been a top-level directory since bug 969164. --- js/src/Makefile.in | 2 -- 1 file changed, 2 deletions(-) diff --git a/js/src/Makefile.in b/js/src/Makefile.in index cce9859aa69a..93b74fc54ba7 100644 --- a/js/src/Makefile.in +++ b/js/src/Makefile.in @@ -12,8 +12,6 @@ ifneq ($(make_min_ver),$(firstword $(sort $(make_min_ver) $(MAKE_VERSION)))) $(error GNU Make $(make_min_ver) or higher is required) endif -TOPLEVEL_BUILD := 1 - run_for_side_effects := $(shell echo 'MAKE: $(MAKE)') ifdef JS_HAS_CTYPES From b8459e912cdd3085b855863ba4285e917bd64c97 Mon Sep 17 00:00:00 2001 From: Dan Glastonbury Date: Mon, 1 Jun 2015 16:49:47 +1000 Subject: [PATCH 55/95] Bug 1170454: Fix up instance type for VAOs. r=smaug,r=jgilbert --HG-- rename : dom/canvas/WebGLVertexArrayGL.h => dom/canvas/WebGLVertexArrayObject.cpp rename : dom/canvas/WebGLVertexArrayGL.h => dom/canvas/WebGLVertexArrayObject.h --- dom/canvas/WebGL2Context.h | 2 ++ dom/canvas/WebGL2ContextVAOs.cpp | 19 ++++++----- dom/canvas/WebGLContext.h | 2 ++ dom/canvas/WebGLContextVertexArray.cpp | 8 ++++- dom/canvas/WebGLVertexArrayGL.h | 8 ++--- dom/canvas/WebGLVertexArrayObject.cpp | 35 ++++++++++++++++++++ dom/canvas/WebGLVertexArrayObject.h | 42 ++++++++++++++++++++++++ dom/canvas/moz.build | 2 ++ dom/webidl/WebGL2RenderingContext.webidl | 4 --- 9 files changed, 104 insertions(+), 18 deletions(-) create mode 100644 dom/canvas/WebGLVertexArrayObject.cpp create mode 100644 dom/canvas/WebGLVertexArrayObject.h diff --git a/dom/canvas/WebGL2Context.h b/dom/canvas/WebGL2Context.h index ce8b15ce3e70..26988f26773c 100644 --- a/dom/canvas/WebGL2Context.h +++ b/dom/canvas/WebGL2Context.h @@ -365,6 +365,8 @@ private: GLsizei width, GLsizei height, GLsizei depth, const char* info); + // CreateVertexArrayImpl is assumed to be infallible. + virtual WebGLVertexArray* CreateVertexArrayImpl() override; virtual bool ValidateAttribPointerType(bool integerMode, GLenum type, GLsizei* alignment, const char* info) override; virtual bool ValidateBufferTarget(GLenum target, const char* info) override; virtual bool ValidateBufferIndexedTarget(GLenum target, const char* info) override; diff --git a/dom/canvas/WebGL2ContextVAOs.cpp b/dom/canvas/WebGL2ContextVAOs.cpp index 2957bfd4a3ba..5e58c91b0a2e 100644 --- a/dom/canvas/WebGL2ContextVAOs.cpp +++ b/dom/canvas/WebGL2ContextVAOs.cpp @@ -5,16 +5,17 @@ #include "WebGL2Context.h" #include "GLContext.h" +#include "WebGLVertexArrayObject.h" -using namespace mozilla; -using namespace mozilla::dom; +namespace mozilla { // ------------------------------------------------------------------------- // Vertex Array Object -// TODO(djg): Implemented in WebGLContext -/* - already_AddRefed CreateVertexArray(); - void DeleteVertexArray(WebGLVertexArrayObject* vertexArray); - bool IsVertexArray(WebGLVertexArrayObject* vertexArray); - void BindVertexArray(WebGLVertexArrayObject* vertexArray); -*/ + +WebGLVertexArray* +WebGL2Context::CreateVertexArrayImpl() +{ + return dom::WebGLVertexArrayObject::Create(this); +} + +} // namespace mozilla diff --git a/dom/canvas/WebGLContext.h b/dom/canvas/WebGLContext.h index fe4f637cb3c8..babc0ac83124 100644 --- a/dom/canvas/WebGLContext.h +++ b/dom/canvas/WebGLContext.h @@ -1390,6 +1390,8 @@ private: private: // ------------------------------------------------------------------------- // Context customization points + virtual WebGLVertexArray* CreateVertexArrayImpl(); + virtual bool ValidateAttribPointerType(bool integerMode, GLenum type, GLsizei* alignment, const char* info) = 0; virtual bool ValidateBufferTarget(GLenum target, const char* info) = 0; virtual bool ValidateBufferIndexedTarget(GLenum target, const char* info) = 0; diff --git a/dom/canvas/WebGLContextVertexArray.cpp b/dom/canvas/WebGLContextVertexArray.cpp index 5e90abf754ac..904691c5664a 100644 --- a/dom/canvas/WebGLContextVertexArray.cpp +++ b/dom/canvas/WebGLContextVertexArray.cpp @@ -51,7 +51,7 @@ WebGLContext::CreateVertexArray() if (IsContextLost()) return nullptr; - nsRefPtr globj = WebGLVertexArray::Create(this); + nsRefPtr globj = CreateVertexArrayImpl(); MakeContextCurrent(); globj->GenVertexArray(); @@ -59,6 +59,12 @@ WebGLContext::CreateVertexArray() return globj.forget(); } +WebGLVertexArray* +WebGLContext::CreateVertexArrayImpl() +{ + return WebGLVertexArray::Create(this); +} + void WebGLContext::DeleteVertexArray(WebGLVertexArray* array) { diff --git a/dom/canvas/WebGLVertexArrayGL.h b/dom/canvas/WebGLVertexArrayGL.h index 84993461a6a5..28f7f58efd60 100644 --- a/dom/canvas/WebGLVertexArrayGL.h +++ b/dom/canvas/WebGLVertexArrayGL.h @@ -10,15 +10,17 @@ namespace mozilla { -class WebGLVertexArrayGL final +class WebGLVertexArrayGL : public WebGLVertexArray { + friend class WebGLVertexArray; + public: virtual void DeleteImpl() override; virtual void BindVertexArrayImpl() override; virtual void GenVertexArray() override; -private: +protected: explicit WebGLVertexArrayGL(WebGLContext* webgl) : WebGLVertexArray(webgl) { } @@ -26,8 +28,6 @@ private: ~WebGLVertexArrayGL() { DeleteOnce(); } - - friend class WebGLVertexArray; }; } // namespace mozilla diff --git a/dom/canvas/WebGLVertexArrayObject.cpp b/dom/canvas/WebGLVertexArrayObject.cpp new file mode 100644 index 000000000000..71ec32e50ba5 --- /dev/null +++ b/dom/canvas/WebGLVertexArrayObject.cpp @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "WebGLVertexArrayObject.h" + +#include "mozilla/dom/WebGL2RenderingContextBinding.h" + +namespace mozilla { +namespace dom { + +WebGLVertexArray* +WebGLVertexArrayObject::Create(WebGLContext* webgl) +{ + // WebGL 2: This is core in GL ES 3. If support is missing something + // is very wrong. + bool vaoSupport = webgl->GL()->IsSupported(gl::GLFeature::vertex_array_object); + MOZ_RELEASE_ASSERT(vaoSupport, "Vertex Array Objects aren't supported."); + if (vaoSupport) + return new WebGLVertexArrayObject(webgl); + + return nullptr; +} + +JSObject* +WebGLVertexArrayObject::WrapObject(JSContext* cx, + JS::Handle givenProto) +{ + return dom::WebGLVertexArrayObjectBinding::Wrap(cx, this, givenProto); +} + +} // namespace dom +} // namespace mozilla diff --git a/dom/canvas/WebGLVertexArrayObject.h b/dom/canvas/WebGLVertexArrayObject.h new file mode 100644 index 000000000000..a58bff9ebb66 --- /dev/null +++ b/dom/canvas/WebGLVertexArrayObject.h @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef mozilla_dom_WebGLVertexArrayObject_h +#define mozilla_dom_WebGLVertexArrayObject_h + +#include "WebGLVertexArrayGL.h" + +namespace mozilla { +namespace dom { + +/** + * This class implements the DOM bindings for WebGL 2 VAO. + * + * This exists to so the object returned from gl.createVertexArray() + * is an instance of WebGLVertexArrayObject (to match the WebGL 2 + * spec.) + */ +class WebGLVertexArrayObject final + : public WebGLVertexArrayGL +{ +public: + static WebGLVertexArray* Create(WebGLContext* webgl); + + virtual JSObject* WrapObject(JSContext* cx, JS::Handle givenProto) override; + +private: + explicit WebGLVertexArrayObject(WebGLContext* webgl) + : WebGLVertexArrayGL(webgl) + { } + + ~WebGLVertexArrayObject() { + DeleteOnce(); + } +}; + +} // namespace dom +} // namespace mozilla + +#endif // !mozilla_dom_WebGLVertexArrayObject_h diff --git a/dom/canvas/moz.build b/dom/canvas/moz.build index b80b30ebe987..e8b1541be24d 100644 --- a/dom/canvas/moz.build +++ b/dom/canvas/moz.build @@ -31,6 +31,7 @@ EXPORTS.mozilla.dom += [ 'CanvasUtils.h', 'ImageData.h', 'TextMetrics.h', + 'WebGLVertexArrayObject.h', ] # http://support.microsoft.com/kb/143208 @@ -128,6 +129,7 @@ UNIFIED_SOURCES += [ 'WebGLVertexArray.cpp', 'WebGLVertexArrayFake.cpp', 'WebGLVertexArrayGL.cpp', + 'WebGLVertexArrayObject.cpp', ] LOCAL_INCLUDES += [ '/js/xpconnect/wrappers', diff --git a/dom/webidl/WebGL2RenderingContext.webidl b/dom/webidl/WebGL2RenderingContext.webidl index 34aaee3ecfe3..8d4b7e16487d 100644 --- a/dom/webidl/WebGL2RenderingContext.webidl +++ b/dom/webidl/WebGL2RenderingContext.webidl @@ -26,11 +26,9 @@ interface WebGLSync { interface WebGLTransformFeedback { }; -/* [Pref="webgl.enable-prototype-webgl2"] interface WebGLVertexArrayObject { }; -*/ [Pref="webgl.enable-prototype-webgl2"] interface WebGL2RenderingContext : WebGLRenderingContext @@ -475,10 +473,8 @@ interface WebGL2RenderingContext : WebGLRenderingContext void uniformBlockBinding(WebGLProgram? program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); /* Vertex Array Objects */ - /* WebGLVertexArrayObject? createVertexArray(); void deleteVertexArray(WebGLVertexArrayObject? vertexArray); [WebGLHandlesContextLoss] GLboolean isVertexArray(WebGLVertexArrayObject? vertexArray); void bindVertexArray(WebGLVertexArrayObject? array); - */ }; From 00e19f02eda808288cfb758bf77857cfb765672b Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Wed, 10 Jun 2015 11:17:45 +0900 Subject: [PATCH 56/95] Fixup for bug 1172632 on a CLOSED TREE. r=me --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 988797d65255..95a69317d5a8 100644 --- a/configure.in +++ b/configure.in @@ -3399,8 +3399,6 @@ if test -n "$MOZ_LINKER" -a "$OS_TARGET" = "Android"; then fi fi -MOZ_CHECK_ALLOCATOR - dnl See if compiler supports some gcc-style attributes AC_CACHE_CHECK(for __attribute__((always_inline)), @@ -3435,6 +3433,8 @@ fi AC_HAVE_FUNCS(localeconv) fi # ! SKIP_COMPILER_CHECKS +MOZ_CHECK_ALLOCATOR + TARGET_XPCOM_ABI= if test -n "${CPU_ARCH}" -a -n "${TARGET_COMPILER_ABI}"; then TARGET_XPCOM_ABI="${CPU_ARCH}-${TARGET_COMPILER_ABI}" From dbca0c72ec64b346f4416ed7a91df4dadaaab056 Mon Sep 17 00:00:00 2001 From: Edwin Flores Date: Wed, 10 Jun 2015 14:39:05 +1200 Subject: [PATCH 57/95] Bug 1172393 - Let XPCOM shutdown properly on Windows versions later than XP - r=mccr8 --- xpcom/build/XPCOMInit.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xpcom/build/XPCOMInit.cpp b/xpcom/build/XPCOMInit.cpp index c227ecebf29c..78cc67d389f7 100644 --- a/xpcom/build/XPCOMInit.cpp +++ b/xpcom/build/XPCOMInit.cpp @@ -93,6 +93,7 @@ extern nsresult nsStringInputStreamConstructor(nsISupports*, REFNSIID, void**); #include "SpecialSystemDirectory.h" #if defined(XP_WIN) +#include "mozilla/WindowsVersion.h" #include "nsWindowsRegKey.h" #endif @@ -954,7 +955,7 @@ ShutdownXPCOM(nsIServiceManager* aServMgr) // On Windows XP debug, there are intermittent failures in // dom/media/tests/mochitest/test_peerConnection_basicH264Video.html // if we don't exit early in a child process. See bug 1073310. - if (XRE_GetProcessType() == GeckoProcessType_Content) { + if (XRE_GetProcessType() == GeckoProcessType_Content && !IsVistaOrLater()) { NS_WARNING("Exiting child process early!"); exit(0); } From 477384f63ed54f196dabdf5db82ce2040cfc5490 Mon Sep 17 00:00:00 2001 From: Chris Pearce Date: Wed, 10 Jun 2015 14:42:04 +1200 Subject: [PATCH 58/95] Bug 1173225 - Add pref to control whether we trial create a GMPVideoDecoder. r=edwin --- dom/media/eme/GMPVideoDecoderTrialCreator.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dom/media/eme/GMPVideoDecoderTrialCreator.cpp b/dom/media/eme/GMPVideoDecoderTrialCreator.cpp index f5cf67251ded..3de9c34416ab 100644 --- a/dom/media/eme/GMPVideoDecoderTrialCreator.cpp +++ b/dom/media/eme/GMPVideoDecoderTrialCreator.cpp @@ -60,6 +60,10 @@ TrialCreatePrefName(const nsAString& aKeySystem) GMPVideoDecoderTrialCreator::TrialCreateState GMPVideoDecoderTrialCreator::GetCreateTrialState(const nsAString& aKeySystem) { + if (Preferences::GetBool("media.gmp.always-trial-create", false)) { + return Pending; + } + const char* pref = TrialCreatePrefName(aKeySystem); if (!pref) { return Pending; From aa0f7c2a75ed1507072bff671a898b39d0b7d782 Mon Sep 17 00:00:00 2001 From: Chris Pearce Date: Wed, 10 Jun 2015 14:42:10 +1200 Subject: [PATCH 59/95] Bug 1164245 - Add envvar check to disable stack clearing after generating GMP node id. r=edwin --- dom/media/gmp/GMPLoader.cpp | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/dom/media/gmp/GMPLoader.cpp b/dom/media/gmp/GMPLoader.cpp index 21a2c2bbf278..d2229c592642 100644 --- a/dom/media/gmp/GMPLoader.cpp +++ b/dom/media/gmp/GMPLoader.cpp @@ -9,6 +9,7 @@ #include "mozilla/Attributes.h" #include "gmp-entrypoints.h" #include "prlink.h" +#include "prenv.h" #include @@ -168,22 +169,25 @@ GMPLoaderImpl::Load(const char* aLibPath, if (!rlz_lib::BytesToString(digest, SHA256_LENGTH, &nodeId)) { return false; } - // We've successfully bound the origin salt to node id. - // rlz_lib::GetRawMachineId and/or the system functions it - // called could have left user identifiable data on the stack, - // so carefully zero the stack down to the guard page. - uint8_t* top; - uint8_t* bottom; - if (!GetStackAfterCurrentFrame(&top, &bottom)) { - return false; - } - assert(top >= bottom); - // Inline instructions equivalent to RtlSecureZeroMemory(). - // We can't just use RtlSecureZeroMemory here directly, as in debug - // builds, RtlSecureZeroMemory() can't be inlined, and the stack - // memory it uses would get wiped by itself running, causing crashes. - for (volatile uint8_t* p = (volatile uint8_t*)bottom; p < top; p++) { - *p = 0; + + if (!PR_GetEnv("MOZ_GMP_DISABLE_NODE_ID_CLEANUP")) { + // We've successfully bound the origin salt to node id. + // rlz_lib::GetRawMachineId and/or the system functions it + // called could have left user identifiable data on the stack, + // so carefully zero the stack down to the guard page. + uint8_t* top; + uint8_t* bottom; + if (!GetStackAfterCurrentFrame(&top, &bottom)) { + return false; + } + assert(top >= bottom); + // Inline instructions equivalent to RtlSecureZeroMemory(). + // We can't just use RtlSecureZeroMemory here directly, as in debug + // builds, RtlSecureZeroMemory() can't be inlined, and the stack + // memory it uses would get wiped by itself running, causing crashes. + for (volatile uint8_t* p = (volatile uint8_t*)bottom; p < top; p++) { + *p = 0; + } } } else #endif From b5cfdf944835389bfa9212048a820890f1f0000e Mon Sep 17 00:00:00 2001 From: JW Wang Date: Wed, 10 Jun 2015 06:14:09 +0800 Subject: [PATCH 60/95] Bug 1172769 - add some handy methods. r=bholley. --- dom/media/AbstractThread.cpp | 12 ++++++++++++ dom/media/AbstractThread.h | 4 ++++ dom/media/StateMirroring.h | 4 ++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/dom/media/AbstractThread.cpp b/dom/media/AbstractThread.cpp index 304e79971674..e01e06c96e59 100644 --- a/dom/media/AbstractThread.cpp +++ b/dom/media/AbstractThread.cpp @@ -133,4 +133,16 @@ AbstractThread::InitStatics() sCurrentThreadTLS.set(sMainThread); } +void +AbstractThread::DispatchStateChange(already_AddRefed aRunnable) +{ + GetCurrent()->TailDispatcher().AddStateChangeTask(this, Move(aRunnable)); +} + +/* static */ void +AbstractThread::DispatchDirectTask(already_AddRefed aRunnable) +{ + GetCurrent()->TailDispatcher().AddDirectTask(Move(aRunnable)); +} + } // namespace mozilla diff --git a/dom/media/AbstractThread.h b/dom/media/AbstractThread.h index 6ff785e55c66..587b6eb212c8 100644 --- a/dom/media/AbstractThread.h +++ b/dom/media/AbstractThread.h @@ -79,6 +79,10 @@ public: // Must be called exactly once during startup. static void InitStatics(); + void DispatchStateChange(already_AddRefed aRunnable); + + static void DispatchDirectTask(already_AddRefed aRunnable); + protected: virtual ~AbstractThread() {} static ThreadLocal sCurrentThreadTLS; diff --git a/dom/media/StateMirroring.h b/dom/media/StateMirroring.h index bf8a8734a8fb..abc806c2f5e4 100644 --- a/dom/media/StateMirroring.h +++ b/dom/media/StateMirroring.h @@ -197,7 +197,7 @@ private: // updates at all if the value ends up where it started. if (!alreadyNotifying) { nsCOMPtr r = NS_NewRunnableMethod(this, &Impl::DoNotify); - AbstractThread::GetCurrent()->TailDispatcher().AddDirectTask(r.forget()); + AbstractThread::DispatchDirectTask(r.forget()); } } @@ -222,7 +222,7 @@ private: } for (size_t i = 0; i < mMirrors.Length(); ++i) { - OwnerThread()->TailDispatcher().AddStateChangeTask(mMirrors[i]->OwnerThread(), MakeNotifier(mMirrors[i])); + mMirrors[i]->OwnerThread()->DispatchStateChange(MakeNotifier(mMirrors[i])); } } From 74023554afaead489870abc349d0d6816d5bd158 Mon Sep 17 00:00:00 2001 From: JW Wang Date: Wed, 10 Jun 2015 10:55:56 +0800 Subject: [PATCH 61/95] Bug 1172778 - Update readyState when audio samples are popped by AudioSink. r=cpearce. --- dom/media/MediaDecoderStateMachine.cpp | 45 ++++++++++++-------------- dom/media/MediaDecoderStateMachine.h | 8 ++--- 2 files changed, 23 insertions(+), 30 deletions(-) diff --git a/dom/media/MediaDecoderStateMachine.cpp b/dom/media/MediaDecoderStateMachine.cpp index e4dfbeaa29d4..9cd7d1f4d801 100644 --- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -272,6 +272,14 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder, // timeEndPeriod() call. timeBeginPeriod(1); #endif + + AudioQueue().AddPopListener( + NS_NewRunnableMethod(this, &MediaDecoderStateMachine::OnAudioPopped), + mTaskQueue); + + VideoQueue().AddPopListener( + NS_NewRunnableMethod(this, &MediaDecoderStateMachine::OnVideoPopped), + mTaskQueue); } MediaDecoderStateMachine::~MediaDecoderStateMachine() @@ -581,7 +589,7 @@ void MediaDecoderStateMachine::SendStreamData() // the decoding speed. if (a && a->mTime <= clockTime) { OnAudioEndTimeUpdate(std::max(mAudioEndTime, a->GetEndTime())); - nsRefPtr releaseMe = PopAudio(); + nsRefPtr releaseMe = AudioQueue().PopFront(); continue; } break; @@ -905,22 +913,25 @@ MediaDecoderStateMachine::PushFront(VideoData* aSample) UpdateNextFrameStatus(); } -already_AddRefed -MediaDecoderStateMachine::PopAudio() +void +MediaDecoderStateMachine::OnAudioPopped() { MOZ_ASSERT(OnTaskQueue()); - nsRefPtr sample = AudioQueue().PopFront(); + ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); UpdateNextFrameStatus(); - return sample.forget(); + DispatchAudioDecodeTaskIfNeeded(); } -already_AddRefed -MediaDecoderStateMachine::PopVideo() +void +MediaDecoderStateMachine::OnVideoPopped() { MOZ_ASSERT(OnTaskQueue()); - nsRefPtr sample = VideoQueue().PopFront(); + ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); UpdateNextFrameStatus(); - return sample.forget(); + DispatchVideoDecodeTaskIfNeeded(); + // Notify the decode thread that the video queue's buffers may have + // free'd up space for more frames. + mDecoder->GetReentrantMonitor().NotifyAll(); } void @@ -2283,17 +2294,6 @@ MediaDecoderStateMachine::DecodeFirstFrame() MOZ_ASSERT(mState == DECODER_STATE_DECODING_FIRSTFRAME); DECODER_LOG("DecodeFirstFrame started"); - if (HasAudio()) { - RefPtr decodeTask( - NS_NewRunnableMethod(this, &MediaDecoderStateMachine::DispatchAudioDecodeTaskIfNeeded)); - AudioQueue().AddPopListener(decodeTask, TaskQueue()); - } - if (HasVideo()) { - RefPtr decodeTask( - NS_NewRunnableMethod(this, &MediaDecoderStateMachine::DispatchVideoDecodeTaskIfNeeded)); - VideoQueue().AddPopListener(decodeTask, TaskQueue()); - } - if (IsRealTime()) { SetStartTime(0); nsresult res = FinishDecodeFirstFrame(); @@ -2925,10 +2925,7 @@ void MediaDecoderStateMachine::AdvanceFrame() currentFrame->mTime, clock_time, ++droppedFrames); } currentFrame = frame; - nsRefPtr releaseMe = PopVideo(); - // Notify the decode thread that the video queue's buffers may have - // free'd up space for more frames. - mDecoder->GetReentrantMonitor().NotifyAll(); + nsRefPtr releaseMe = VideoQueue().PopFront(); OnPlaybackOffsetUpdate(frame->mOffset); if (VideoQueue().GetSize() == 0) break; diff --git a/dom/media/MediaDecoderStateMachine.h b/dom/media/MediaDecoderStateMachine.h index fc37b344c13b..b2a0f505094d 100644 --- a/dom/media/MediaDecoderStateMachine.h +++ b/dom/media/MediaDecoderStateMachine.h @@ -420,12 +420,8 @@ protected: void PushFront(AudioData* aSample); void PushFront(VideoData* aSample); - // Pops MediaData* samples from their respective MediaQueues. - // Note that the audio queue is also drained on the audio thread, - // which we can't easily react to - This should be fixed when we - // remove the audio thread in bug 750596. - already_AddRefed PopAudio(); - already_AddRefed PopVideo(); + void OnAudioPopped(); + void OnVideoPopped(); void VolumeChanged(); void LogicalPlaybackRateChanged(); From 90a7ccba6dd4bcded765ca79fb805ec905d66f36 Mon Sep 17 00:00:00 2001 From: Dan Glastonbury Date: Thu, 21 May 2015 09:50:28 +1000 Subject: [PATCH 62/95] Bug 1167504 - Part 1: Remove BindableName - Framebuffer. r=jgilbert --- dom/canvas/WebGLContextGL.cpp | 25 ++++++++++++++++++++----- dom/canvas/WebGLContextUtils.cpp | 6 +++--- dom/canvas/WebGLFramebuffer.cpp | 12 ++++++++++-- dom/canvas/WebGLFramebuffer.h | 16 +++++++++++++--- 4 files changed, 46 insertions(+), 13 deletions(-) diff --git a/dom/canvas/WebGLContextGL.cpp b/dom/canvas/WebGLContextGL.cpp index b92b25afa31b..a1af6547957c 100644 --- a/dom/canvas/WebGLContextGL.cpp +++ b/dom/canvas/WebGLContextGL.cpp @@ -159,9 +159,11 @@ WebGLContext::BindFramebuffer(GLenum target, WebGLFramebuffer* wfb) if (!wfb) { gl->fBindFramebuffer(target, 0); } else { - wfb->BindTo(target); - GLuint framebuffername = wfb->GLName(); + GLuint framebuffername = wfb->mGLName; gl->fBindFramebuffer(target, framebuffername); +#ifdef ANDROID + wfb->mIsFB = true; +#endif } switch (target) { @@ -1691,9 +1693,22 @@ WebGLContext::IsFramebuffer(WebGLFramebuffer* fb) if (IsContextLost()) return false; - return ValidateObjectAllowDeleted("isFramebuffer", fb) && - !fb->IsDeleted() && - fb->HasEverBeenBound(); + if (!ValidateObjectAllowDeleted("isFramebuffer", fb)) + return false; + + if (fb->IsDeleted()) + return false; + +#ifdef ANDROID + if (gl->WorkAroundDriverBugs() && + gl->Renderer() == GLRenderer::AndroidEmulator) + { + return fb->mIsFB; + } +#endif + + MakeContextCurrent(); + return gl->fIsFramebuffer(fb->mGLName); } bool diff --git a/dom/canvas/WebGLContextUtils.cpp b/dom/canvas/WebGLContextUtils.cpp index 7ad7aef72ae1..a1694b3d25f9 100644 --- a/dom/canvas/WebGLContextUtils.cpp +++ b/dom/canvas/WebGLContextUtils.cpp @@ -1098,15 +1098,15 @@ WebGLContext::AssertCachedBindings() // Bound object state if (IsWebGL2()) { - GLuint bound = mBoundDrawFramebuffer ? mBoundDrawFramebuffer->GLName() + GLuint bound = mBoundDrawFramebuffer ? mBoundDrawFramebuffer->mGLName : 0; AssertUintParamCorrect(gl, LOCAL_GL_DRAW_FRAMEBUFFER_BINDING, bound); - bound = mBoundReadFramebuffer ? mBoundReadFramebuffer->GLName() : 0; + bound = mBoundReadFramebuffer ? mBoundReadFramebuffer->mGLName : 0; AssertUintParamCorrect(gl, LOCAL_GL_READ_FRAMEBUFFER_BINDING, bound); } else { MOZ_ASSERT(mBoundDrawFramebuffer == mBoundReadFramebuffer); - GLuint bound = mBoundDrawFramebuffer ? mBoundDrawFramebuffer->GLName() + GLuint bound = mBoundDrawFramebuffer ? mBoundDrawFramebuffer->mGLName : 0; AssertUintParamCorrect(gl, LOCAL_GL_FRAMEBUFFER_BINDING, bound); } diff --git a/dom/canvas/WebGLFramebuffer.cpp b/dom/canvas/WebGLFramebuffer.cpp index b037e0cf017e..bf713ff8d1ca 100644 --- a/dom/canvas/WebGLFramebuffer.cpp +++ b/dom/canvas/WebGLFramebuffer.cpp @@ -404,14 +404,18 @@ WebGLFramebuffer::AttachPoint::FinalizeAttachment(gl::GLContext* gl, // WebGLFramebuffer WebGLFramebuffer::WebGLFramebuffer(WebGLContext* webgl, GLuint fbo) - : WebGLBindableName(fbo) - , WebGLContextBoundObject(webgl) + : WebGLContextBoundObject(webgl) + , mGLName(fbo) , mStatus(0) , mReadBufferMode(LOCAL_GL_COLOR_ATTACHMENT0) , mColorAttachment0(this, LOCAL_GL_COLOR_ATTACHMENT0) , mDepthAttachment(this, LOCAL_GL_DEPTH_ATTACHMENT) , mStencilAttachment(this, LOCAL_GL_STENCIL_ATTACHMENT) , mDepthStencilAttachment(this, LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) +#ifdef ANDROID + , mIsFB(false) +#endif + { mContext->mFramebuffers.insertBack(this); } @@ -432,6 +436,10 @@ WebGLFramebuffer::Delete() mContext->MakeContextCurrent(); mContext->gl->fDeleteFramebuffers(1, &mGLName); LinkedListElement::removeFrom(mContext->mFramebuffers); + +#ifdef ANDROID + mIsFB = false; +#endif } void diff --git a/dom/canvas/WebGLFramebuffer.h b/dom/canvas/WebGLFramebuffer.h index dbe21350ec3b..220f225dc3d9 100644 --- a/dom/canvas/WebGLFramebuffer.h +++ b/dom/canvas/WebGLFramebuffer.h @@ -8,7 +8,6 @@ #include "mozilla/LinkedList.h" #include "nsWrapperCache.h" -#include "WebGLBindableName.h" #include "WebGLObjectModel.h" #include "WebGLStrongTypes.h" @@ -23,12 +22,13 @@ namespace gl { class WebGLFramebuffer final : public nsWrapperCache - , public WebGLBindableName , public WebGLRefCountedObject , public LinkedListElement , public WebGLContextBoundObject , public SupportsWeakPtr { + friend class WebGLContext; + public: MOZ_DECLARE_WEAKREFERENCE_TYPENAME(WebGLFramebuffer) @@ -53,7 +53,6 @@ public: } bool IsDefined() const; - bool IsDeleteRequested() const; TexInternalFormat EffectiveInternalFormat() const; @@ -99,6 +98,8 @@ public: FBAttachment attachmentLoc) const; }; + const GLuint mGLName; + private: mutable GLenum mStatus; @@ -111,6 +112,15 @@ private: AttachPoint mDepthStencilAttachment; nsTArray mMoreColorAttachments; +#ifdef ANDROID + // Bug 1140459: Some drivers (including our test slaves!) don't + // give reasonable answers for IsRenderbuffer, maybe others. + // This shows up on Android 2.3 emulator. + // + // So we track the `is a Framebuffer` state ourselves. + bool mIsFB; +#endif + public: WebGLFramebuffer(WebGLContext* webgl, GLuint fbo); From dde34b92c8e098f65d9ef940589c2756b94e57e2 Mon Sep 17 00:00:00 2001 From: Dan Glastonbury Date: Thu, 21 May 2015 09:53:02 +1000 Subject: [PATCH 63/95] Bug 1167504 - Part 2: Remove BindableName - Renderbuffer. r=jgilbert --- dom/canvas/WebGLContextGL.cpp | 25 +++++++++++++++++++------ dom/canvas/WebGLRenderbuffer.cpp | 9 +++++++-- dom/canvas/WebGLRenderbuffer.h | 13 +++++++++++-- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/dom/canvas/WebGLContextGL.cpp b/dom/canvas/WebGLContextGL.cpp index a1af6547957c..310be1b23f0b 100644 --- a/dom/canvas/WebGLContextGL.cpp +++ b/dom/canvas/WebGLContextGL.cpp @@ -198,15 +198,15 @@ WebGLContext::BindRenderbuffer(GLenum target, WebGLRenderbuffer* wrb) if (wrb && wrb->IsDeleted()) return; - if (wrb) - wrb->BindTo(target); - MakeContextCurrent(); // Sometimes we emulate renderbuffers (depth-stencil emu), so there's not // always a 1-1 mapping from `wrb` to GL name. Just have `wrb` handle it. if (wrb) { wrb->BindRenderbuffer(); +#ifdef ANDROID + wrb->mIsRB = true; +#endif } else { gl->fBindRenderbuffer(target, 0); } @@ -1726,9 +1726,22 @@ WebGLContext::IsRenderbuffer(WebGLRenderbuffer* rb) if (IsContextLost()) return false; - return ValidateObjectAllowDeleted("isRenderBuffer", rb) && - !rb->IsDeleted() && - rb->HasEverBeenBound(); + if (!ValidateObjectAllowDeleted("isRenderBuffer", rb)) + return false; + + if (rb->IsDeleted()) + return false; + +#ifdef ANDROID + if (gl->WorkAroundDriverBugs() && + gl->Renderer() == GLRenderer::AndroidEmulator) + { + return rb->mIsRB; + } +#endif + + MakeContextCurrent(); + return gl->fIsRenderbuffer(rb->PrimaryGLName()); } bool diff --git a/dom/canvas/WebGLRenderbuffer.cpp b/dom/canvas/WebGLRenderbuffer.cpp index 9919aa15ed39..d9583dcd57fd 100644 --- a/dom/canvas/WebGLRenderbuffer.cpp +++ b/dom/canvas/WebGLRenderbuffer.cpp @@ -47,14 +47,16 @@ WebGLRenderbuffer::WrapObject(JSContext* cx, JS::Handle aGivenProto) } WebGLRenderbuffer::WebGLRenderbuffer(WebGLContext* webgl) - : WebGLBindable() - , WebGLContextBoundObject(webgl) + : WebGLContextBoundObject(webgl) , mPrimaryRB(0) , mSecondaryRB(0) , mInternalFormat(0) , mInternalFormatForGL(0) , mImageDataStatus(WebGLImageDataStatus::NoImageData) , mSamples(1) +#ifdef ANDROID + , mIsRB(false) +#endif { mContext->MakeContextCurrent(); @@ -75,6 +77,9 @@ WebGLRenderbuffer::Delete() mContext->gl->fDeleteRenderbuffers(1, &mSecondaryRB); LinkedListElement::removeFrom(mContext->mRenderbuffers); +#ifdef ANDROID + mIsRB = false; +#endif } int64_t diff --git a/dom/canvas/WebGLRenderbuffer.h b/dom/canvas/WebGLRenderbuffer.h index e10dd77437f3..440dfdba5590 100644 --- a/dom/canvas/WebGLRenderbuffer.h +++ b/dom/canvas/WebGLRenderbuffer.h @@ -8,7 +8,6 @@ #include "mozilla/LinkedList.h" #include "nsWrapperCache.h" -#include "WebGLBindableName.h" #include "WebGLFramebufferAttachable.h" #include "WebGLObjectModel.h" @@ -16,7 +15,6 @@ namespace mozilla { class WebGLRenderbuffer final : public nsWrapperCache - , public WebGLBindable , public WebGLRefCountedObject , public LinkedListElement , public WebGLRectangleObject @@ -41,6 +39,8 @@ public: GLsizei Samples() const { return mSamples; } void SetSamples(GLsizei samples) { mSamples = samples; } + GLuint PrimaryGLName() const { return mPrimaryRB; } + GLenum InternalFormat() const { return mInternalFormat; } void SetInternalFormat(GLenum internalFormat) { mInternalFormat = internalFormat; @@ -80,7 +80,16 @@ protected: GLenum mInternalFormatForGL; WebGLImageDataStatus mImageDataStatus; GLsizei mSamples; +#ifdef ANDROID + // Bug 1140459: Some drivers (including our test slaves!) don't + // give reasonable answers for IsRenderbuffer, maybe others. + // This shows up on Android 2.3 emulator. + // + // So we track the `is a Renderbuffer` state ourselves. + bool mIsRB; +#endif + friend class WebGLContext; friend class WebGLFramebuffer; }; From e6e4f1da2dfbf2ac995140d1cdef34b767dbfcd3 Mon Sep 17 00:00:00 2001 From: Dan Glastonbury Date: Thu, 21 May 2015 09:54:05 +1000 Subject: [PATCH 64/95] Bug 1167504 - Part 3: Remove BindableName - Sampler. r=jgilbert --- dom/canvas/WebGL2ContextSamplers.cpp | 3 ++- dom/canvas/WebGLContextUnchecked.cpp | 16 +++++++--------- dom/canvas/WebGLSampler.cpp | 4 ++-- dom/canvas/WebGLSampler.h | 4 ++-- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/dom/canvas/WebGL2ContextSamplers.cpp b/dom/canvas/WebGL2ContextSamplers.cpp index 922ed4ad15f1..bad4b50bdb54 100644 --- a/dom/canvas/WebGL2ContextSamplers.cpp +++ b/dom/canvas/WebGL2ContextSamplers.cpp @@ -54,7 +54,8 @@ WebGL2Context::IsSampler(WebGLSampler* sampler) if (sampler->IsDeleted()) return false; - return !sampler->HasEverBeenBound(); + MakeContextCurrent(); + return gl->fIsSampler(sampler->mGLName); } void diff --git a/dom/canvas/WebGLContextUnchecked.cpp b/dom/canvas/WebGLContextUnchecked.cpp index 3b0acf1867e2..7cd586fa1ed7 100644 --- a/dom/canvas/WebGLContextUnchecked.cpp +++ b/dom/canvas/WebGLContextUnchecked.cpp @@ -56,9 +56,7 @@ void WebGLContextUnchecked::BindSampler(GLuint unit, WebGLSampler* sampler) { gl->MakeCurrent(); - gl->fBindSampler(unit, sampler ? sampler->GLName() : 0); - if (sampler) - sampler->BindTo(LOCAL_GL_SAMPLER_BINDING); + gl->fBindSampler(unit, sampler ? sampler->mGLName : 0); } GLint @@ -69,7 +67,7 @@ WebGLContextUnchecked::GetSamplerParameteriv(WebGLSampler* sampler, GLint param = 0; gl->MakeCurrent(); - gl->fGetSamplerParameteriv(sampler->GLName(), pname, ¶m); + gl->fGetSamplerParameteriv(sampler->mGLName, pname, ¶m); return param; } @@ -82,7 +80,7 @@ WebGLContextUnchecked::GetSamplerParameterfv(WebGLSampler* sampler, GLfloat param = 0.0f; gl->MakeCurrent(); - gl->fGetSamplerParameterfv(sampler->GLName(), pname, ¶m); + gl->fGetSamplerParameterfv(sampler->mGLName, pname, ¶m); return param; } @@ -93,7 +91,7 @@ WebGLContextUnchecked::SamplerParameteri(WebGLSampler* sampler, { MOZ_ASSERT(sampler, "Did you validate?"); gl->MakeCurrent(); - gl->fSamplerParameteri(sampler->GLName(), pname, param); + gl->fSamplerParameteri(sampler->mGLName, pname, param); } void @@ -103,7 +101,7 @@ WebGLContextUnchecked::SamplerParameteriv(WebGLSampler* sampler, { MOZ_ASSERT(sampler, "Did you validate?"); gl->MakeCurrent(); - gl->fSamplerParameteriv(sampler->GLName(), pname, param); + gl->fSamplerParameteriv(sampler->mGLName, pname, param); } void @@ -113,7 +111,7 @@ WebGLContextUnchecked::SamplerParameterf(WebGLSampler* sampler, { MOZ_ASSERT(sampler, "Did you validate?"); gl->MakeCurrent(); - gl->fSamplerParameterf(sampler->GLName(), pname, param); + gl->fSamplerParameterf(sampler->mGLName, pname, param); } void @@ -123,7 +121,7 @@ WebGLContextUnchecked::SamplerParameterfv(WebGLSampler* sampler, { MOZ_ASSERT(sampler, "Did you validate?"); gl->MakeCurrent(); - gl->fSamplerParameterfv(sampler->GLName(), pname, param); + gl->fSamplerParameterfv(sampler->mGLName, pname, param); } } // namespace mozilla diff --git a/dom/canvas/WebGLSampler.cpp b/dom/canvas/WebGLSampler.cpp index 8d8cc7be50e6..8f91968586b5 100644 --- a/dom/canvas/WebGLSampler.cpp +++ b/dom/canvas/WebGLSampler.cpp @@ -12,8 +12,8 @@ namespace mozilla { WebGLSampler::WebGLSampler(WebGLContext* webgl, GLuint sampler) - : WebGLBindableName(sampler), - WebGLContextBoundObject(webgl) + : WebGLContextBoundObject(webgl) + , mGLName(sampler) { mContext->mSamplers.insertBack(this); } diff --git a/dom/canvas/WebGLSampler.h b/dom/canvas/WebGLSampler.h index ba2ef77c9b11..8ab1387c9b05 100644 --- a/dom/canvas/WebGLSampler.h +++ b/dom/canvas/WebGLSampler.h @@ -8,14 +8,12 @@ #include "mozilla/LinkedList.h" #include "nsWrapperCache.h" -#include "WebGLBindableName.h" #include "WebGLObjectModel.h" namespace mozilla { class WebGLSampler final : public nsWrapperCache - , public WebGLBindableName , public WebGLRefCountedObject , public LinkedListElement , public WebGLContextBoundObject @@ -25,6 +23,8 @@ class WebGLSampler final public: explicit WebGLSampler(WebGLContext* webgl, GLuint sampler); + const GLuint mGLName; + void Delete(); WebGLContext* GetParentObject() const; From e1b36d0a8466d6e0350ee06af7c86aca9a56f004 Mon Sep 17 00:00:00 2001 From: Dan Glastonbury Date: Thu, 21 May 2015 09:55:34 +1000 Subject: [PATCH 65/95] Bug 1167504 - Part 4: Remove BindableName - Texture. r=jgilbert --- dom/canvas/WebGLContext.cpp | 2 +- dom/canvas/WebGLContextDraw.cpp | 4 ++-- dom/canvas/WebGLContextGL.cpp | 2 +- dom/canvas/WebGLContextUtils.cpp | 4 ++-- dom/canvas/WebGLFramebuffer.cpp | 2 +- dom/canvas/WebGLTexture.cpp | 21 ++++++++++----------- dom/canvas/WebGLTexture.h | 11 +++++++++-- 7 files changed, 26 insertions(+), 20 deletions(-) diff --git a/dom/canvas/WebGLContext.cpp b/dom/canvas/WebGLContext.cpp index 1f45067d1432..97303063b634 100644 --- a/dom/canvas/WebGLContext.cpp +++ b/dom/canvas/WebGLContext.cpp @@ -1880,7 +1880,7 @@ WebGLContext::TexImageFromVideoElement(const TexImageTarget texImageTarget, : gl::OriginPos::TopLeft; bool ok = gl->BlitHelper()->BlitImageToTexture(srcImage.get(), srcImage->GetSize(), - tex->GLName(), + tex->mGLName, texImageTarget.get(), destOrigin); if (ok) { diff --git a/dom/canvas/WebGLContextDraw.cpp b/dom/canvas/WebGLContextDraw.cpp index c7fa619210b9..40f4bd79f77a 100644 --- a/dom/canvas/WebGLContextDraw.cpp +++ b/dom/canvas/WebGLContextDraw.cpp @@ -737,11 +737,11 @@ WebGLContext::UnbindFakeBlackTextures() for (int32_t i = 0; i < mGLMaxTextureUnits; ++i) { if (mBound2DTextures[i] && mBound2DTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded) { gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i); - gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mBound2DTextures[i]->GLName()); + gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mBound2DTextures[i]->mGLName); } if (mBoundCubeMapTextures[i] && mBoundCubeMapTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded) { gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i); - gl->fBindTexture(LOCAL_GL_TEXTURE_CUBE_MAP, mBoundCubeMapTextures[i]->GLName()); + gl->fBindTexture(LOCAL_GL_TEXTURE_CUBE_MAP, mBoundCubeMapTextures[i]->mGLName); } } diff --git a/dom/canvas/WebGLContextGL.cpp b/dom/canvas/WebGLContextGL.cpp index 310be1b23f0b..2dd6f40ba3f8 100644 --- a/dom/canvas/WebGLContextGL.cpp +++ b/dom/canvas/WebGLContextGL.cpp @@ -739,7 +739,7 @@ WebGLContext::DeleteTexture(WebGLTexture* tex) (mBound3DTextures[i] == tex && tex->Target() == LOCAL_GL_TEXTURE_3D)) { ActiveTexture(LOCAL_GL_TEXTURE0 + i); - BindTexture(tex->Target().get(), nullptr); + BindTexture(tex->Target(), nullptr); } } ActiveTexture(LOCAL_GL_TEXTURE0 + activeTexture); diff --git a/dom/canvas/WebGLContextUtils.cpp b/dom/canvas/WebGLContextUtils.cpp index a1694b3d25f9..cc8dbb92f659 100644 --- a/dom/canvas/WebGLContextUtils.cpp +++ b/dom/canvas/WebGLContextUtils.cpp @@ -1119,11 +1119,11 @@ WebGLContext::AssertCachedBindings() AssertUintParamCorrect(gl, LOCAL_GL_ACTIVE_TEXTURE, activeTexture); WebGLTexture* curTex = ActiveBoundTextureForTarget(LOCAL_GL_TEXTURE_2D); - bound = curTex ? curTex->GLName() : 0; + bound = curTex ? curTex->mGLName : 0; AssertUintParamCorrect(gl, LOCAL_GL_TEXTURE_BINDING_2D, bound); curTex = ActiveBoundTextureForTarget(LOCAL_GL_TEXTURE_CUBE_MAP); - bound = curTex ? curTex->GLName() : 0; + bound = curTex ? curTex->mGLName : 0; AssertUintParamCorrect(gl, LOCAL_GL_TEXTURE_BINDING_CUBE_MAP, bound); // Buffers diff --git a/dom/canvas/WebGLFramebuffer.cpp b/dom/canvas/WebGLFramebuffer.cpp index bf713ff8d1ca..de5c5bcbc8d2 100644 --- a/dom/canvas/WebGLFramebuffer.cpp +++ b/dom/canvas/WebGLFramebuffer.cpp @@ -378,7 +378,7 @@ WebGLFramebuffer::AttachPoint::FinalizeAttachment(gl::GLContext* gl, const GLenum imageTarget = ImageTarget().get(); const GLint mipLevel = MipLevel(); - const GLuint glName = Texture()->GLName(); + const GLuint glName = Texture()->mGLName; if (attachmentLoc == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) { gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT, diff --git a/dom/canvas/WebGLTexture.cpp b/dom/canvas/WebGLTexture.cpp index eb84901e501a..aeaaa89f28c9 100644 --- a/dom/canvas/WebGLTexture.cpp +++ b/dom/canvas/WebGLTexture.cpp @@ -24,8 +24,9 @@ WebGLTexture::WrapObject(JSContext* cx, JS::Handle aGivenProto) { } WebGLTexture::WebGLTexture(WebGLContext* webgl, GLuint tex) - : WebGLBindableName(tex) - , WebGLContextBoundObject(webgl) + : WebGLContextBoundObject(webgl) + , mGLName(tex) + , mTarget(LOCAL_GL_NONE) , mMinFilter(LOCAL_GL_NEAREST_MIPMAP_LINEAR) , mMagFilter(LOCAL_GL_LINEAR) , mWrapS(LOCAL_GL_REPEAT) @@ -142,7 +143,7 @@ WebGLTexture::Bind(TexTarget texTarget) bool firstTimeThisTextureIsBound = !HasEverBeenBound(); if (firstTimeThisTextureIsBound) { - BindTo(texTarget); + mTarget = texTarget.get(); } else if (texTarget != Target()) { mContext->ErrorInvalidOperation("bindTexture: This texture has already" " been bound to a different target."); @@ -152,9 +153,7 @@ WebGLTexture::Bind(TexTarget texTarget) return; } - GLuint name = GLName(); - - mContext->gl->fBindTexture(texTarget.get(), name); + mContext->gl->fBindTexture(texTarget.get(), mGLName); if (firstTimeThisTextureIsBound) { mFacesCount = (texTarget == LOCAL_GL_TEXTURE_CUBE_MAP) ? 6 : 1; @@ -229,7 +228,7 @@ WebGLTexture::SetCustomMipmap() imageInfo.mWidth = std::max(imageInfo.mWidth / 2, 1); imageInfo.mHeight = std::max(imageInfo.mHeight / 2, 1); imageInfo.mDepth = std::max(imageInfo.mDepth / 2, 1); - for(size_t face = 0; face < mFacesCount; ++face) { + for (size_t face = 0; face < mFacesCount; ++face) { ImageInfoAtFace(face, level) = imageInfo; } } @@ -276,8 +275,8 @@ WebGLTexture::IsMipmapCubeComplete() const return false; for (int i = 0; i < 6; i++) { - const TexImageTarget face = TexImageTargetForTargetAndFace(LOCAL_GL_TEXTURE_CUBE_MAP, - i); + const TexImageTarget face = + TexImageTargetForTargetAndFace(LOCAL_GL_TEXTURE_CUBE_MAP, i); if (!DoesMipmapHaveAllLevelsConsistentlyDefined(face)) return false; } @@ -626,7 +625,7 @@ WebGLTexture::EnsureNoUninitializedImageData(TexImageTarget imageTarget, // Try to clear with glClear. if (imageTarget == LOCAL_GL_TEXTURE_2D) { - bool cleared = ClearWithTempFB(mContext, GLName(), imageTarget, level, + bool cleared = ClearWithTempFB(mContext, mGLName, imageTarget, level, imageInfo.mEffectiveInternalFormat, imageInfo.mHeight, imageInfo.mWidth); if (cleared) { @@ -637,7 +636,7 @@ WebGLTexture::EnsureNoUninitializedImageData(TexImageTarget imageTarget, } // That didn't work. Try uploading zeros then. - gl::ScopedBindTexture autoBindTex(mContext->gl, GLName(), mTarget.get()); + gl::ScopedBindTexture autoBindTex(mContext->gl, mGLName, mTarget); size_t bitspertexel = GetBitsPerTexel(imageInfo.mEffectiveInternalFormat); MOZ_ASSERT((bitspertexel % 8) == 0); // That would only happen for diff --git a/dom/canvas/WebGLTexture.h b/dom/canvas/WebGLTexture.h index b253e5058da1..5545fdaadb0c 100644 --- a/dom/canvas/WebGLTexture.h +++ b/dom/canvas/WebGLTexture.h @@ -12,7 +12,6 @@ #include "mozilla/LinkedList.h" #include "nsAlgorithm.h" #include "nsWrapperCache.h" -#include "WebGLBindableName.h" #include "WebGLFramebufferAttachable.h" #include "WebGLObjectModel.h" #include "WebGLStrongTypes.h" @@ -31,7 +30,6 @@ IsPOTAssumingNonnegative(GLsizei x) // WrapObject calls in GetParameter and GetFramebufferAttachmentParameter. class WebGLTexture final : public nsWrapperCache - , public WebGLBindableName , public WebGLRefCountedObject , public LinkedListElement , public WebGLContextBoundObject @@ -42,6 +40,9 @@ public: void Delete(); + bool HasEverBeenBound() const { return mTarget != LOCAL_GL_NONE; } + GLenum Target() const { return mTarget; } + WebGLContext* GetParentObject() const { return Context(); } @@ -62,6 +63,12 @@ protected: // We store information about the various images that are part of this // texture. (cubemap faces, mipmap levels) +public: + const GLuint mGLName; + +protected: + GLenum mTarget; + public: class ImageInfo : public WebGLRectangleObject From 3922303a1467c0867b917e8e24f73c94f5ddca0a Mon Sep 17 00:00:00 2001 From: Dan Glastonbury Date: Thu, 21 May 2015 09:57:48 +1000 Subject: [PATCH 66/95] Bug 1167504 - Part 5: Remove BindableName - Transform Feedback. r=jgilbert --- dom/canvas/WebGL2ContextTransformFeedback.cpp | 7 ++----- dom/canvas/WebGLTransformFeedback.cpp | 4 ++-- dom/canvas/WebGLTransformFeedback.h | 5 +++-- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/dom/canvas/WebGL2ContextTransformFeedback.cpp b/dom/canvas/WebGL2ContextTransformFeedback.cpp index b651a6963cb9..a1db81b78c57 100644 --- a/dom/canvas/WebGL2ContextTransformFeedback.cpp +++ b/dom/canvas/WebGL2ContextTransformFeedback.cpp @@ -60,7 +60,7 @@ WebGL2Context::IsTransformFeedback(WebGLTransformFeedback* tf) return false; MakeContextCurrent(); - return gl->fIsTransformFeedback(tf->GLName()); + return gl->fIsTransformFeedback(tf->mGLName); } void @@ -84,11 +84,8 @@ WebGL2Context::BindTransformFeedback(GLenum target, WebGLTransformFeedback* tf) if (tf && tf->IsDeleted()) return ErrorInvalidOperation("bindTransformFeedback: Attempt to bind deleted id"); - if (tf) - tf->BindTo(LOCAL_GL_TRANSFORM_FEEDBACK); - MakeContextCurrent(); - gl->fBindTransformFeedback(target, tf ? tf->GLName() : 0); + gl->fBindTransformFeedback(target, tf ? tf->mGLName : 0); if (tf) mBoundTransformFeedback = tf; else diff --git a/dom/canvas/WebGLTransformFeedback.cpp b/dom/canvas/WebGLTransformFeedback.cpp index b4dc42054a1f..8aabc47a2d0c 100644 --- a/dom/canvas/WebGLTransformFeedback.cpp +++ b/dom/canvas/WebGLTransformFeedback.cpp @@ -13,8 +13,8 @@ namespace mozilla { WebGLTransformFeedback::WebGLTransformFeedback(WebGLContext* webgl, GLuint tf) - : WebGLBindableName(tf) - , WebGLContextBoundObject(webgl) + : WebGLContextBoundObject(webgl) + , mGLName(tf) , mMode(LOCAL_GL_NONE) , mIsActive(false) , mIsPaused(false) diff --git a/dom/canvas/WebGLTransformFeedback.h b/dom/canvas/WebGLTransformFeedback.h index 09e7f6e30147..d373e4929287 100644 --- a/dom/canvas/WebGLTransformFeedback.h +++ b/dom/canvas/WebGLTransformFeedback.h @@ -8,14 +8,12 @@ #include "mozilla/LinkedList.h" #include "nsWrapperCache.h" -#include "WebGLBindableName.h" #include "WebGLObjectModel.h" namespace mozilla { class WebGLTransformFeedback final : public nsWrapperCache - , public WebGLBindableName , public WebGLRefCountedObject , public LinkedListElement , public WebGLContextBoundObject @@ -30,11 +28,14 @@ public: WebGLContext* GetParentObject() const; virtual JSObject* WrapObject(JSContext* cx, JS::Handle aGivenProto) override; + const GLuint mGLName; + NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTransformFeedback) NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLTransformFeedback) private: ~WebGLTransformFeedback(); + GLenum mMode; bool mIsActive; bool mIsPaused; From 88aef4ad04c6743c6575c85f30f90d2a1017164b Mon Sep 17 00:00:00 2001 From: Dan Glastonbury Date: Thu, 21 May 2015 09:58:36 +1000 Subject: [PATCH 67/95] Bug 1167504 - Part 6: Remove BindableName - Vertex Array. r=jgilbert --- dom/canvas/WebGLContextVertexArray.cpp | 11 ++++++-- dom/canvas/WebGLVertexArray.cpp | 9 ++++-- dom/canvas/WebGLVertexArray.h | 13 ++++----- dom/canvas/WebGLVertexArrayFake.cpp | 18 ++++++++++++ dom/canvas/WebGLVertexArrayFake.h | 13 +++++---- dom/canvas/WebGLVertexArrayGL.cpp | 38 +++++++++++++++++++++++++- dom/canvas/WebGLVertexArrayGL.h | 16 +++++++---- 7 files changed, 93 insertions(+), 25 deletions(-) diff --git a/dom/canvas/WebGLContextVertexArray.cpp b/dom/canvas/WebGLContextVertexArray.cpp index 904691c5664a..a4d5b6cb8948 100644 --- a/dom/canvas/WebGLContextVertexArray.cpp +++ b/dom/canvas/WebGLContextVertexArray.cpp @@ -92,9 +92,14 @@ WebGLContext::IsVertexArray(WebGLVertexArray* array) if (!array) return false; - return ValidateObjectAllowDeleted("isVertexArray", array) && - !array->IsDeleted() && - array->HasEverBeenBound(); + if (!ValidateObjectAllowDeleted("isVertexArray", array)) + return false; + + if (array->IsDeleted()) + return false; + + MakeContextCurrent(); + return array->IsVertexArray(); } } // namespace mozilla diff --git a/dom/canvas/WebGLVertexArray.cpp b/dom/canvas/WebGLVertexArray.cpp index a64d663fdc71..ab7abfd43470 100644 --- a/dom/canvas/WebGLVertexArray.cpp +++ b/dom/canvas/WebGLVertexArray.cpp @@ -21,8 +21,7 @@ WebGLVertexArray::WrapObject(JSContext* cx, JS::Handle aGivenProto) } WebGLVertexArray::WebGLVertexArray(WebGLContext* webgl) - : WebGLBindable() - , WebGLContextBoundObject(webgl) + : WebGLContextBoundObject(webgl) , mGLName(0) { mContext->mVertexArrays.insertBack(this); @@ -50,6 +49,12 @@ WebGLVertexArray::Delete() mAttribs.Clear(); } +bool +WebGLVertexArray::IsVertexArray() +{ + return IsVertexArrayImpl(); +} + void WebGLVertexArray::EnsureAttrib(GLuint index) { diff --git a/dom/canvas/WebGLVertexArray.h b/dom/canvas/WebGLVertexArray.h index 10c14a99c6c5..332fc5981861 100644 --- a/dom/canvas/WebGLVertexArray.h +++ b/dom/canvas/WebGLVertexArray.h @@ -8,7 +8,6 @@ #include "mozilla/LinkedList.h" #include "nsWrapperCache.h" -#include "WebGLBindableName.h" #include "WebGLBuffer.h" #include "WebGLObjectModel.h" #include "WebGLStrongTypes.h" @@ -20,7 +19,6 @@ class WebGLVertexArrayFake; class WebGLVertexArray : public nsWrapperCache - , public WebGLBindable , public WebGLRefCountedObject , public LinkedListElement , public WebGLContextBoundObject @@ -31,14 +29,9 @@ public: void BindVertexArray() { // Bind to dummy value to signal that this vertex array has ever been // bound. - BindTo(LOCAL_GL_VERTEX_ARRAY_BINDING); BindVertexArrayImpl(); }; - virtual void GenVertexArray() = 0; - virtual void BindVertexArrayImpl() = 0; - virtual void DeleteImpl() = 0; - void EnsureAttrib(GLuint index); bool HasAttrib(GLuint index) const { return index < mAttribs.Length(); @@ -49,6 +42,7 @@ public: // Implement parent classes: void Delete(); + bool IsVertexArray(); WebGLContext* GetParentObject() const { return Context(); @@ -68,6 +62,11 @@ protected: MOZ_ASSERT(IsDeleted()); } + virtual void GenVertexArray() = 0; + virtual void BindVertexArrayImpl() = 0; + virtual void DeleteImpl() = 0; + virtual bool IsVertexArrayImpl() = 0; + GLuint mGLName; nsTArray mAttribs; WebGLRefPtr mElementArrayBuffer; diff --git a/dom/canvas/WebGLVertexArrayFake.cpp b/dom/canvas/WebGLVertexArrayFake.cpp index b12f99687d44..e5e59096873b 100644 --- a/dom/canvas/WebGLVertexArrayFake.cpp +++ b/dom/canvas/WebGLVertexArrayFake.cpp @@ -10,6 +10,11 @@ namespace mozilla { +WebGLVertexArrayFake::WebGLVertexArrayFake(WebGLContext* webgl) + : WebGLVertexArray(webgl) + , mIsVAO(false) +{ } + void WebGLVertexArrayFake::BindVertexArrayImpl() { @@ -52,6 +57,19 @@ WebGLVertexArrayFake::BindVertexArrayImpl() } mContext->BindBuffer(LOCAL_GL_ARRAY_BUFFER, prevBuffer); + mIsVAO = true; +} + +void +WebGLVertexArrayFake::DeleteImpl() +{ + mIsVAO = false; +} + +bool +WebGLVertexArrayFake::IsVertexArrayImpl() +{ + return mIsVAO; } } // namespace mozilla diff --git a/dom/canvas/WebGLVertexArrayFake.h b/dom/canvas/WebGLVertexArrayFake.h index 365c48755717..6f970c965747 100644 --- a/dom/canvas/WebGLVertexArrayFake.h +++ b/dom/canvas/WebGLVertexArrayFake.h @@ -13,21 +13,22 @@ namespace mozilla { class WebGLVertexArrayFake final : public WebGLVertexArray { -public: + friend class WebGLVertexArray; + +protected: virtual void BindVertexArrayImpl() override; - virtual void DeleteImpl() override {}; + virtual void DeleteImpl() override; virtual void GenVertexArray() override {}; + virtual bool IsVertexArrayImpl() override; private: - explicit WebGLVertexArrayFake(WebGLContext* webgl) - : WebGLVertexArray(webgl) - { } + explicit WebGLVertexArrayFake(WebGLContext* webgl); ~WebGLVertexArrayFake() { DeleteOnce(); } - friend class WebGLVertexArray; + bool mIsVAO; }; } // namespace mozilla diff --git a/dom/canvas/WebGLVertexArrayGL.cpp b/dom/canvas/WebGLVertexArrayGL.cpp index 06d1f76c1716..e88c2a4b911a 100644 --- a/dom/canvas/WebGLVertexArrayGL.cpp +++ b/dom/canvas/WebGLVertexArrayGL.cpp @@ -10,6 +10,18 @@ namespace mozilla { +WebGLVertexArrayGL::WebGLVertexArrayGL(WebGLContext* webgl) + : WebGLVertexArray(webgl) +#if defined(XP_LINUX) + , mIsVAO(false) +#endif +{ } + +WebGLVertexArrayGL::~WebGLVertexArrayGL() +{ + DeleteOnce(); +} + void WebGLVertexArrayGL::DeleteImpl() { @@ -17,14 +29,21 @@ WebGLVertexArrayGL::DeleteImpl() mContext->MakeContextCurrent(); mContext->gl->fDeleteVertexArrays(1, &mGLName); + +#if defined(XP_LINUX) + mIsVAO = false; +#endif } void WebGLVertexArrayGL::BindVertexArrayImpl() { mContext->mBoundVertexArray = this; - mContext->gl->fBindVertexArray(mGLName); + +#if defined(XP_LINUX) + mIsVAO = true; +#endif } void @@ -33,4 +52,21 @@ WebGLVertexArrayGL::GenVertexArray() mContext->gl->fGenVertexArrays(1, &mGLName); } +bool +WebGLVertexArrayGL::IsVertexArrayImpl() +{ +#if defined(XP_LINUX) + gl::GLContext* gl = mContext->gl; + if (gl->WorkAroundDriverBugs() && + gl->Vendor() == gl::GLVendor::VMware && + gl->Renderer() == gl::GLRenderer::GalliumLlvmpipe) + { + return mIsVAO; + } +#endif + + mContext->MakeContextCurrent(); + return mContext->gl->fIsVertexArray(mGLName) != 0; +} + } // namespace mozilla diff --git a/dom/canvas/WebGLVertexArrayGL.h b/dom/canvas/WebGLVertexArrayGL.h index 28f7f58efd60..4923804347c2 100644 --- a/dom/canvas/WebGLVertexArrayGL.h +++ b/dom/canvas/WebGLVertexArrayGL.h @@ -19,15 +19,19 @@ public: virtual void DeleteImpl() override; virtual void BindVertexArrayImpl() override; virtual void GenVertexArray() override; + virtual bool IsVertexArrayImpl() override; protected: - explicit WebGLVertexArrayGL(WebGLContext* webgl) - : WebGLVertexArray(webgl) - { } + explicit WebGLVertexArrayGL(WebGLContext* webgl); + ~WebGLVertexArrayGL(); - ~WebGLVertexArrayGL() { - DeleteOnce(); - } +#if defined(XP_LINUX) + // Bug 1140459: Some drivers (including our test slaves!) don't + // give reasonable answers for IsRenderbuffer, maybe others. + // + // So we track the `is a VAO` state ourselves. + bool mIsVAO; +#endif }; } // namespace mozilla From bdc3ac46019f168f4b3cbba76ad788f25426c277 Mon Sep 17 00:00:00 2001 From: Dan Glastonbury Date: Fri, 22 May 2015 15:49:30 +1000 Subject: [PATCH 68/95] Bug 1167504 - Part 7: Remove BindableName - Buffer. r=jgilbert --- dom/canvas/WebGL2ContextBuffers.cpp | 8 ++++---- dom/canvas/WebGLBuffer.cpp | 17 +++++++++++++++-- dom/canvas/WebGLBuffer.h | 12 +++++++++--- dom/canvas/WebGLContextDraw.cpp | 6 +++--- dom/canvas/WebGLContextUnchecked.cpp | 6 +++--- dom/canvas/WebGLContextUtils.cpp | 4 ++-- 6 files changed, 36 insertions(+), 17 deletions(-) diff --git a/dom/canvas/WebGL2ContextBuffers.cpp b/dom/canvas/WebGL2ContextBuffers.cpp index 7f35f5e0ef96..56e50cfda4c4 100644 --- a/dom/canvas/WebGL2ContextBuffers.cpp +++ b/dom/canvas/WebGL2ContextBuffers.cpp @@ -71,7 +71,7 @@ WebGL2Context::ValidateBufferForTarget(GLenum target, WebGLBuffer* buffer, } ErrorInvalidOperation("%s: buffer already bound to a incompatible target %s", - info, EnumName(buffer->Target().get())); + info, EnumName(buffer->Target())); return false; } @@ -155,7 +155,7 @@ WebGL2Context::GetBufferSubData(GLenum target, GLintptr offset, { if (IsContextLost()) return; - + // For the WebGLBuffer bound to the passed target, read // returnedData.byteLength bytes from the buffer starting at byte // offset offset and write them to returnedData. @@ -168,7 +168,7 @@ WebGL2Context::GetBufferSubData(GLenum target, GLintptr offset, // If offset is less than zero, an INVALID_VALUE error is // generated. if (offset < 0) - return ErrorInvalidValue("getBufferSubData: negative offset"); + return ErrorInvalidValue("getBufferSubData: negative offset"); // If returnedData is null then an INVALID_VALUE error is // generated. @@ -179,7 +179,7 @@ WebGL2Context::GetBufferSubData(GLenum target, GLintptr offset, WebGLBuffer* boundBuffer = bufferSlot.get(); if (!boundBuffer) return ErrorInvalidOperation("getBufferSubData: no buffer bound"); - + // If offset + returnedData.byteLength would extend beyond the end // of the buffer an INVALID_VALUE error is generated. const dom::ArrayBuffer& data = maybeData.Value(); diff --git a/dom/canvas/WebGLBuffer.cpp b/dom/canvas/WebGLBuffer.cpp index d6909bd2a107..7126f0880149 100644 --- a/dom/canvas/WebGLBuffer.cpp +++ b/dom/canvas/WebGLBuffer.cpp @@ -13,8 +13,9 @@ namespace mozilla { WebGLBuffer::WebGLBuffer(WebGLContext* webgl, GLuint buf) - : WebGLBindableName(buf) - , WebGLContextBoundObject(webgl) + : WebGLContextBoundObject(webgl) + , mGLName(buf) + , mTarget(LOCAL_GL_NONE) , mByteLength(0) { mContext->mBuffers.insertBack(this); @@ -35,6 +36,18 @@ WebGLBuffer::Delete() LinkedListElement::remove(); // remove from mContext->mBuffers } +void +WebGLBuffer::BindTo(GLenum target) +{ + MOZ_ASSERT(target != LOCAL_GL_NONE, "Can't bind to GL_NONE."); + MOZ_ASSERT(!HasEverBeenBound() || mTarget == target, "Rebinding is illegal."); + + bool targetChanged = (target != mTarget); + mTarget = target; + if (targetChanged) + OnTargetChanged(); +} + void WebGLBuffer::OnTargetChanged() { diff --git a/dom/canvas/WebGLBuffer.h b/dom/canvas/WebGLBuffer.h index 76b5bfc9e6c7..f5a810473ec5 100644 --- a/dom/canvas/WebGLBuffer.h +++ b/dom/canvas/WebGLBuffer.h @@ -10,7 +10,6 @@ #include "mozilla/LinkedList.h" #include "mozilla/MemoryReporting.h" #include "nsWrapperCache.h" -#include "WebGLBindableName.h" #include "WebGLObjectModel.h" #include "WebGLStrongTypes.h" #include "WebGLTypes.h" @@ -21,7 +20,6 @@ class WebGLElementArrayCache; class WebGLBuffer final : public nsWrapperCache - , public WebGLBindableName , public WebGLRefCountedObject , public LinkedListElement , public WebGLContextBoundObject @@ -41,6 +39,10 @@ public: void ElementArrayCacheBufferSubData(size_t pos, const void* ptr, size_t updateSizeInBytes); + void BindTo(GLenum target); + bool HasEverBeenBound() const { return mTarget != LOCAL_GL_NONE; } + GLenum Target() const { return mTarget; } + bool Validate(GLenum type, uint32_t max_allowed, size_t first, size_t count, uint32_t* const out_upperBound); @@ -52,13 +54,17 @@ public: virtual JSObject* WrapObject(JSContext* cx, JS::Handle aGivenProto) override; + const GLenum mGLName; + NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLBuffer) NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLBuffer) protected: ~WebGLBuffer(); - virtual void OnTargetChanged() override; + void OnTargetChanged(); + + GLenum mTarget; WebGLsizeiptr mByteLength; nsAutoPtr mCache; diff --git a/dom/canvas/WebGLContextDraw.cpp b/dom/canvas/WebGLContextDraw.cpp index 40f4bd79f77a..f78a0d71be55 100644 --- a/dom/canvas/WebGLContextDraw.cpp +++ b/dom/canvas/WebGLContextDraw.cpp @@ -600,7 +600,7 @@ WebGLContext::DoFakeVertexAttrib0(GLuint vertexCount) } GLenum error = GetAndFlushUnderlyingGLErrors(); - gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundArrayBuffer ? mBoundArrayBuffer->GLName() : 0); + gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundArrayBuffer ? mBoundArrayBuffer->mGLName : 0); // note that we do this error checking and early return AFTER having restored the buffer binding above if (error) { @@ -626,7 +626,7 @@ WebGLContext::UndoFakeVertexAttrib0() if (mBoundVertexArray->HasAttrib(0) && mBoundVertexArray->mAttribs[0].buf) { const WebGLVertexAttribData& attrib0 = mBoundVertexArray->mAttribs[0]; - gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, attrib0.buf->GLName()); + gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, attrib0.buf->mGLName); if (attrib0.integer) { gl->fVertexAttribIPointer(0, attrib0.size, @@ -645,7 +645,7 @@ WebGLContext::UndoFakeVertexAttrib0() gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0); } - gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundArrayBuffer ? mBoundArrayBuffer->GLName() : 0); + gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundArrayBuffer ? mBoundArrayBuffer->mGLName : 0); } WebGLContextFakeBlackStatus diff --git a/dom/canvas/WebGLContextUnchecked.cpp b/dom/canvas/WebGLContextUnchecked.cpp index 7cd586fa1ed7..3824bc303735 100644 --- a/dom/canvas/WebGLContextUnchecked.cpp +++ b/dom/canvas/WebGLContextUnchecked.cpp @@ -24,21 +24,21 @@ void WebGLContextUnchecked::BindBuffer(GLenum target, WebGLBuffer* buffer) { gl->MakeCurrent(); - gl->fBindBuffer(target, buffer ? buffer->GLName() : 0); + gl->fBindBuffer(target, buffer ? buffer->mGLName : 0); } void WebGLContextUnchecked::BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buffer) { gl->MakeCurrent(); - gl->fBindBufferBase(target, index, buffer ? buffer->GLName() : 0); + gl->fBindBufferBase(target, index, buffer ? buffer->mGLName : 0); } void WebGLContextUnchecked::BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer, WebGLintptr offset, WebGLsizeiptr size) { gl->MakeCurrent(); - gl->fBindBufferRange(target, index, buffer ? buffer->GLName() : 0, offset, size); + gl->fBindBufferRange(target, index, buffer ? buffer->mGLName : 0, offset, size); } void diff --git a/dom/canvas/WebGLContextUtils.cpp b/dom/canvas/WebGLContextUtils.cpp index cc8dbb92f659..b735dd1b461d 100644 --- a/dom/canvas/WebGLContextUtils.cpp +++ b/dom/canvas/WebGLContextUtils.cpp @@ -1127,12 +1127,12 @@ WebGLContext::AssertCachedBindings() AssertUintParamCorrect(gl, LOCAL_GL_TEXTURE_BINDING_CUBE_MAP, bound); // Buffers - bound = mBoundArrayBuffer ? mBoundArrayBuffer->GLName() : 0; + bound = mBoundArrayBuffer ? mBoundArrayBuffer->mGLName : 0; AssertUintParamCorrect(gl, LOCAL_GL_ARRAY_BUFFER_BINDING, bound); MOZ_ASSERT(mBoundVertexArray); WebGLBuffer* curBuff = mBoundVertexArray->mElementArrayBuffer; - bound = curBuff ? curBuff->GLName() : 0; + bound = curBuff ? curBuff->mGLName : 0; AssertUintParamCorrect(gl, LOCAL_GL_ELEMENT_ARRAY_BUFFER_BINDING, bound); MOZ_ASSERT(!GetAndFlushUnderlyingGLErrors()); From da00b1f5f94a830aee05fdb5b6c4af79b43daf0e Mon Sep 17 00:00:00 2001 From: Dan Glastonbury Date: Wed, 3 Jun 2015 12:51:13 +1000 Subject: [PATCH 69/95] Bug 1167504 - Part 9: Remove BindableName - Queries. r=jgilbert --- .../WebGLExtensionDisjointTimerQuery.cpp | 12 ++++++------ dom/canvas/WebGLShader.cpp | 5 +++++ dom/canvas/WebGLTimerQuery.cpp | 17 +++++++++++++++-- dom/canvas/WebGLTimerQuery.h | 18 +++++++++--------- 4 files changed, 35 insertions(+), 17 deletions(-) diff --git a/dom/canvas/WebGLExtensionDisjointTimerQuery.cpp b/dom/canvas/WebGLExtensionDisjointTimerQuery.cpp index 13c1e4eb2e70..4be7e8a80668 100644 --- a/dom/canvas/WebGLExtensionDisjointTimerQuery.cpp +++ b/dom/canvas/WebGLExtensionDisjointTimerQuery.cpp @@ -93,8 +93,8 @@ WebGLExtensionDisjointTimerQuery::BeginQueryEXT(GLenum target, mContext->MakeContextCurrent(); gl::GLContext* gl = mContext->GL(); - gl->fBeginQuery(target, query->GLName()); - query->BindTo(LOCAL_GL_TIME_ELAPSED_EXT); + gl->fBeginQuery(target, query->mGLName); + query->mTarget = LOCAL_GL_TIME_ELAPSED_EXT; mActiveQuery = query; } @@ -137,8 +137,8 @@ WebGLExtensionDisjointTimerQuery::QueryCounterEXT(WebGLTimerQuery* query, } mContext->MakeContextCurrent(); - mContext->GL()->fQueryCounter(query->GLName(), target); - query->BindTo(LOCAL_GL_TIMESTAMP_EXT); + mContext->GL()->fQueryCounter(query->mGLName, target); + query->mTarget = LOCAL_GL_TIMESTAMP_EXT; } void @@ -210,7 +210,7 @@ WebGLExtensionDisjointTimerQuery::GetQueryObjectEXT(JSContext* cx, switch (pname) { case LOCAL_GL_QUERY_RESULT_EXT: { GLuint64 result = 0; - mContext->GL()->fGetQueryObjectui64v(query->GLName(), + mContext->GL()->fGetQueryObjectui64v(query->mGLName, LOCAL_GL_QUERY_RESULT_EXT, &result); retval.set(JS::NumberValue(result)); @@ -218,7 +218,7 @@ WebGLExtensionDisjointTimerQuery::GetQueryObjectEXT(JSContext* cx, } case LOCAL_GL_QUERY_RESULT_AVAILABLE_EXT: { GLuint avail = 0; - mContext->GL()->fGetQueryObjectuiv(query->GLName(), + mContext->GL()->fGetQueryObjectuiv(query->mGLName, LOCAL_GL_QUERY_RESULT_AVAILABLE_EXT, &avail); retval.set(JS::BooleanValue(bool(avail))); diff --git a/dom/canvas/WebGLShader.cpp b/dom/canvas/WebGLShader.cpp index e202f27485c0..de311d679a0a 100644 --- a/dom/canvas/WebGLShader.cpp +++ b/dom/canvas/WebGLShader.cpp @@ -92,6 +92,11 @@ TranslateWithoutValidation(const nsACString& sourceNS, bool isWebGL2, switch (glesslVersion) { case 100: + if (!versionStrLen) { + /* According to ARB_ES2_compatibility extension glsl + * should accept #version 100 for ES 2 shaders. */ + reversionedSource.insert(versionStrStart, "#version 100\n"); + } break; case 300: reversionedSource.insert(versionStrStart, "#version 330\n"); diff --git a/dom/canvas/WebGLTimerQuery.cpp b/dom/canvas/WebGLTimerQuery.cpp index 5625cde4fb84..e10fdfd495c5 100644 --- a/dom/canvas/WebGLTimerQuery.cpp +++ b/dom/canvas/WebGLTimerQuery.cpp @@ -20,11 +20,17 @@ WebGLTimerQuery::WrapObject(JSContext* cx, JS::Handle aGivenProto) } WebGLTimerQuery::WebGLTimerQuery(WebGLContext* webgl, GLuint aName) - : WebGLBindableName(aName) - , WebGLContextBoundObject(webgl) + : WebGLContextBoundObject(webgl) + , mGLName(aName) + , mTarget(LOCAL_GL_NONE) { } +WebGLTimerQuery::~WebGLTimerQuery() +{ + DeleteOnce(); +} + WebGLTimerQuery* WebGLTimerQuery::Create(WebGLContext* webgl) { @@ -41,6 +47,13 @@ WebGLTimerQuery::Delete() mContext->gl->fDeleteQueries(1, &mGLName); } +WebGLContext* +WebGLTimerQuery::GetParentObject() const +{ + return Context(); +} + + NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLTimerQuery) NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLTimerQuery, AddRef) diff --git a/dom/canvas/WebGLTimerQuery.h b/dom/canvas/WebGLTimerQuery.h index 38c7830649aa..d1224e931754 100644 --- a/dom/canvas/WebGLTimerQuery.h +++ b/dom/canvas/WebGLTimerQuery.h @@ -14,32 +14,32 @@ namespace mozilla { class WebGLTimerQuery final : public nsWrapperCache - , public WebGLBindableName , public WebGLRefCountedObject , public WebGLContextBoundObject { public: static WebGLTimerQuery* Create(WebGLContext* webgl); - // WebGLRefCountedObject void Delete(); - // nsWrapperCache - WebGLContext* GetParentObject() const { - return Context(); - } + bool HasEverBeenBound() const { return mTarget != LOCAL_GL_NONE; } + GLenum Target() const { return mTarget; } + + WebGLContext* GetParentObject() const; // NS virtual JSObject* WrapObject(JSContext* cx, JS::Handle aGivenProto) override; + const GLenum mGLName; + NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTimerQuery) NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLTimerQuery) private: explicit WebGLTimerQuery(WebGLContext* webgl, GLuint aName); - ~WebGLTimerQuery() { - DeleteOnce(); - } + ~WebGLTimerQuery(); + + GLenum mTarget; friend class WebGLExtensionDisjointTimerQuery; }; From 61f17d66569b8839fac5a3b76f1d82d538ef3124 Mon Sep 17 00:00:00 2001 From: Dan Glastonbury Date: Thu, 21 May 2015 16:36:05 +1000 Subject: [PATCH 70/95] Bug 1167504 - Part 10: Remove WebGLBindableName.h. r=jgilbert --- dom/canvas/WebGLBindableName.h | 70 ---------------------------------- 1 file changed, 70 deletions(-) delete mode 100644 dom/canvas/WebGLBindableName.h diff --git a/dom/canvas/WebGLBindableName.h b/dom/canvas/WebGLBindableName.h deleted file mode 100644 index d92616fb292e..000000000000 --- a/dom/canvas/WebGLBindableName.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef WEBGLBINDABLENAME_H_ -#define WEBGLBINDABLENAME_H_ - -#include "WebGLTypes.h" - -#include "GLDefs.h" -#include "mozilla/TypeTraits.h" -#include "mozilla/Assertions.h" - -namespace mozilla { - -/** Represents a binding to a GL binding point - */ -template -class WebGLBindable -{ -public: - WebGLBindable() : mTarget(LOCAL_GL_NONE) { } - bool HasEverBeenBound() const { return mTarget != LOCAL_GL_NONE; } - - void BindTo(T target) { - MOZ_ASSERT(target != LOCAL_GL_NONE, "Can't bind to GL_NONE."); - MOZ_ASSERT(!HasEverBeenBound() || mTarget == target, "Rebinding is illegal."); - - bool targetChanged = (target != mTarget); - mTarget = target; - if (targetChanged) - OnTargetChanged(); - } - - T Target() const { - MOZ_ASSERT(HasEverBeenBound()); - return mTarget; - } - -protected: - //! Called after mTarget has been changed by BindTo(target). - virtual void OnTargetChanged() {} - - T mTarget; -}; - - -/** Represents a GL name that can be bound to a target. - */ -template -class WebGLBindableName - : public WebGLBindable -{ -public: - - explicit WebGLBindableName(GLuint aName) - : WebGLBindable() - , mGLName(aName) - { } - GLuint GLName() const { return mGLName; } - -protected: - const GLuint mGLName; -}; - - -} // namespace mozilla - -#endif // !WEBGLBINDABLENAME_H_ From a116578a52c8058e23ce82dc395d9fd85cba2b6c Mon Sep 17 00:00:00 2001 From: Dan Glastonbury Date: Thu, 21 May 2015 09:59:14 +1000 Subject: [PATCH 71/95] Bug 1167504 - Part 11: Clean up buffer binding constraints. r=jgilbert Checked against http://www.khronos.org/registry/webgl/sdk/tests/conformance2/buffers/ --- dom/canvas/WebGL1Context.h | 1 - dom/canvas/WebGL1ContextBuffers.cpp | 16 ---- dom/canvas/WebGL2Context.h | 1 - dom/canvas/WebGL2ContextBuffers.cpp | 51 ++++------ dom/canvas/WebGLBuffer.cpp | 53 ++++++----- dom/canvas/WebGLBuffer.h | 19 ++-- dom/canvas/WebGLContext.h | 4 +- dom/canvas/WebGLContextBuffers.cpp | 136 ++++++++++++++++++++++----- dom/canvas/WebGLContextReporter.cpp | 3 +- dom/canvas/WebGLContextUnchecked.cpp | 11 +++ dom/canvas/WebGLContextValidate.cpp | 6 +- 11 files changed, 196 insertions(+), 105 deletions(-) diff --git a/dom/canvas/WebGL1Context.h b/dom/canvas/WebGL1Context.h index a20845a6b627..a47be758cc8e 100644 --- a/dom/canvas/WebGL1Context.h +++ b/dom/canvas/WebGL1Context.h @@ -33,7 +33,6 @@ private: virtual bool ValidateAttribPointerType(bool integerMode, GLenum type, GLsizei* alignment, const char* info) override; virtual bool ValidateBufferTarget(GLenum target, const char* info) override; virtual bool ValidateBufferIndexedTarget(GLenum target, const char* info) override; - virtual bool ValidateBufferForTarget(GLenum target, WebGLBuffer* buffer, const char* info) override; virtual bool ValidateBufferUsageEnum(GLenum usage, const char* info) override; virtual bool ValidateQueryTarget(GLenum target, const char* info) override; virtual bool ValidateUniformMatrixTranspose(bool transpose, const char* info) override; diff --git a/dom/canvas/WebGL1ContextBuffers.cpp b/dom/canvas/WebGL1ContextBuffers.cpp index 77fe5ff8ff06..c4449748ad27 100644 --- a/dom/canvas/WebGL1ContextBuffers.cpp +++ b/dom/canvas/WebGL1ContextBuffers.cpp @@ -35,22 +35,6 @@ WebGL1Context::ValidateBufferIndexedTarget(GLenum target, const char* info) return false; } -/** Buffer and Target validation for BindBuffer */ -bool -WebGL1Context::ValidateBufferForTarget(GLenum target, WebGLBuffer* buffer, - const char* info) -{ - if (!buffer) - return true; - - if (buffer->HasEverBeenBound() && target != buffer->Target()) { - ErrorInvalidOperation("%s: buffer already bound to a different target", info); - return false; - } - - return true; -} - bool WebGL1Context::ValidateBufferUsageEnum(GLenum usage, const char* info) { diff --git a/dom/canvas/WebGL2Context.h b/dom/canvas/WebGL2Context.h index 26988f26773c..c6c00493cb03 100644 --- a/dom/canvas/WebGL2Context.h +++ b/dom/canvas/WebGL2Context.h @@ -370,7 +370,6 @@ private: virtual bool ValidateAttribPointerType(bool integerMode, GLenum type, GLsizei* alignment, const char* info) override; virtual bool ValidateBufferTarget(GLenum target, const char* info) override; virtual bool ValidateBufferIndexedTarget(GLenum target, const char* info) override; - virtual bool ValidateBufferForTarget(GLenum target, WebGLBuffer* buffer, const char* info) override; virtual bool ValidateBufferUsageEnum(GLenum usage, const char* info) override; virtual bool ValidateQueryTarget(GLenum target, const char* info) override; virtual bool ValidateUniformMatrixTranspose(bool transpose, const char* info) override; diff --git a/dom/canvas/WebGL2ContextBuffers.cpp b/dom/canvas/WebGL2ContextBuffers.cpp index 56e50cfda4c4..415021be7996 100644 --- a/dom/canvas/WebGL2ContextBuffers.cpp +++ b/dom/canvas/WebGL2ContextBuffers.cpp @@ -45,36 +45,6 @@ WebGL2Context::ValidateBufferIndexedTarget(GLenum target, const char* info) } } -bool -WebGL2Context::ValidateBufferForTarget(GLenum target, WebGLBuffer* buffer, - const char* info) -{ - if (!buffer) - return true; - - switch (target) { - case LOCAL_GL_COPY_READ_BUFFER: - case LOCAL_GL_COPY_WRITE_BUFFER: - return true; - - case LOCAL_GL_ELEMENT_ARRAY_BUFFER: - return !buffer->HasEverBeenBound() || - buffer->Target() == LOCAL_GL_ELEMENT_ARRAY_BUFFER; - - case LOCAL_GL_ARRAY_BUFFER: - case LOCAL_GL_PIXEL_PACK_BUFFER: - case LOCAL_GL_PIXEL_UNPACK_BUFFER: - case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER: - case LOCAL_GL_UNIFORM_BUFFER: - return !buffer->HasEverBeenBound() || - buffer->Target() != LOCAL_GL_ELEMENT_ARRAY_BUFFER; - } - - ErrorInvalidOperation("%s: buffer already bound to a incompatible target %s", - info, EnumName(buffer->Target())); - return false; -} - bool WebGL2Context::ValidateBufferUsageEnum(GLenum usage, const char* info) { @@ -123,7 +93,7 @@ WebGL2Context::CopyBufferSubData(GLenum readTarget, GLenum writeTarget, if (!readBuffer) return ErrorInvalidOperation("copyBufferSubData: No buffer bound to readTarget"); - const WebGLBuffer* writeBuffer = writeBufferSlot.get(); + WebGLBuffer* writeBuffer = writeBufferSlot.get(); if (!writeBuffer) return ErrorInvalidOperation("copyBufferSubData: No buffer bound to writeTarget"); @@ -145,8 +115,27 @@ WebGL2Context::CopyBufferSubData(GLenum readTarget, GLenum writeTarget, return; } + WebGLBuffer::Kind readType = readBuffer->Content(); + WebGLBuffer::Kind writeType = writeBuffer->Content(); + + if (readType != WebGLBuffer::Kind::Undefined && + writeType != WebGLBuffer::Kind::Undefined && + writeType != readType) + { + ErrorInvalidOperation("copyBufferSubData: Can't copy %s data to %s data", + (readType == WebGLBuffer::Kind::OtherData) ? "other" : "element", + (writeType == WebGLBuffer::Kind::OtherData) ? "other" : "element"); + return; + } + WebGLContextUnchecked::CopyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size); + + if (writeType == WebGLBuffer::Kind::Undefined) { + writeBuffer->BindTo( + (readType == WebGLBuffer::Kind::OtherData) ? LOCAL_GL_ARRAY_BUFFER + : LOCAL_GL_ELEMENT_ARRAY_BUFFER); + } } void diff --git a/dom/canvas/WebGLBuffer.cpp b/dom/canvas/WebGLBuffer.cpp index 7126f0880149..cb28be5f6477 100644 --- a/dom/canvas/WebGLBuffer.cpp +++ b/dom/canvas/WebGLBuffer.cpp @@ -15,7 +15,7 @@ namespace mozilla { WebGLBuffer::WebGLBuffer(WebGLContext* webgl, GLuint buf) : WebGLContextBoundObject(webgl) , mGLName(buf) - , mTarget(LOCAL_GL_NONE) + , mContent(Kind::Undefined) , mByteLength(0) { mContext->mBuffers.insertBack(this); @@ -26,6 +26,34 @@ WebGLBuffer::~WebGLBuffer() DeleteOnce(); } +void +WebGLBuffer::BindTo(GLenum target) +{ + switch (target) { + case LOCAL_GL_ELEMENT_ARRAY_BUFFER: + mContent = Kind::ElementArray; + if (!mCache) + mCache = new WebGLElementArrayCache; + break; + + case LOCAL_GL_ARRAY_BUFFER: + case LOCAL_GL_PIXEL_PACK_BUFFER: + case LOCAL_GL_PIXEL_UNPACK_BUFFER: + case LOCAL_GL_UNIFORM_BUFFER: + case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER: + mContent = Kind::OtherData; + break; + + case LOCAL_GL_COPY_READ_BUFFER: + case LOCAL_GL_COPY_WRITE_BUFFER: + /* Do nothing. Doesn't set the type of the buffer contents. */ + break; + + default: + MOZ_CRASH(); + } +} + void WebGLBuffer::Delete() { @@ -36,30 +64,11 @@ WebGLBuffer::Delete() LinkedListElement::remove(); // remove from mContext->mBuffers } -void -WebGLBuffer::BindTo(GLenum target) -{ - MOZ_ASSERT(target != LOCAL_GL_NONE, "Can't bind to GL_NONE."); - MOZ_ASSERT(!HasEverBeenBound() || mTarget == target, "Rebinding is illegal."); - - bool targetChanged = (target != mTarget); - mTarget = target; - if (targetChanged) - OnTargetChanged(); -} - -void -WebGLBuffer::OnTargetChanged() -{ - if (!mCache && mTarget == LOCAL_GL_ELEMENT_ARRAY_BUFFER) - mCache = new WebGLElementArrayCache; -} - bool WebGLBuffer::ElementArrayCacheBufferData(const void* ptr, size_t bufferSizeInBytes) { - if (mTarget == LOCAL_GL_ELEMENT_ARRAY_BUFFER) + if (mContent == Kind::ElementArray) return mCache->BufferData(ptr, bufferSizeInBytes); return true; @@ -69,7 +78,7 @@ void WebGLBuffer::ElementArrayCacheBufferSubData(size_t pos, const void* ptr, size_t updateSizeInBytes) { - if (mTarget == LOCAL_GL_ELEMENT_ARRAY_BUFFER) + if (mContent == Kind::ElementArray) mCache->BufferSubData(pos, ptr, updateSizeInBytes); } diff --git a/dom/canvas/WebGLBuffer.h b/dom/canvas/WebGLBuffer.h index f5a810473ec5..ef831fe5b244 100644 --- a/dom/canvas/WebGLBuffer.h +++ b/dom/canvas/WebGLBuffer.h @@ -25,8 +25,18 @@ class WebGLBuffer final , public WebGLContextBoundObject { public: + + enum class Kind { + Undefined, + ElementArray, + OtherData + }; + explicit WebGLBuffer(WebGLContext* webgl, GLuint buf); + void BindTo(GLenum target); + Kind Content() const { return mContent; } + void Delete(); size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const; @@ -39,10 +49,6 @@ public: void ElementArrayCacheBufferSubData(size_t pos, const void* ptr, size_t updateSizeInBytes); - void BindTo(GLenum target); - bool HasEverBeenBound() const { return mTarget != LOCAL_GL_NONE; } - GLenum Target() const { return mTarget; } - bool Validate(GLenum type, uint32_t max_allowed, size_t first, size_t count, uint32_t* const out_upperBound); @@ -62,10 +68,7 @@ public: protected: ~WebGLBuffer(); - void OnTargetChanged(); - - GLenum mTarget; - + Kind mContent; WebGLsizeiptr mByteLength; nsAutoPtr mCache; }; diff --git a/dom/canvas/WebGLContext.h b/dom/canvas/WebGLContext.h index babc0ac83124..55c5d802631d 100644 --- a/dom/canvas/WebGLContext.h +++ b/dom/canvas/WebGLContext.h @@ -939,6 +939,8 @@ protected: WebGLRefPtr& GetBufferSlotByTargetIndexed(GLenum target, GLuint index); + GLenum GetCurrentBinding(WebGLBuffer* buffer) const; + // ----------------------------------------------------------------------------- // Queries (WebGL2ContextQueries.cpp) protected: @@ -1395,7 +1397,7 @@ private: virtual bool ValidateAttribPointerType(bool integerMode, GLenum type, GLsizei* alignment, const char* info) = 0; virtual bool ValidateBufferTarget(GLenum target, const char* info) = 0; virtual bool ValidateBufferIndexedTarget(GLenum target, const char* info) = 0; - virtual bool ValidateBufferForTarget(GLenum target, WebGLBuffer* buffer, const char* info) = 0; + virtual bool ValidateBufferForTarget(GLenum target, WebGLBuffer* buffer, const char* info); virtual bool ValidateBufferUsageEnum(GLenum usage, const char* info) = 0; virtual bool ValidateQueryTarget(GLenum usage, const char* info) = 0; virtual bool ValidateUniformMatrixTranspose(bool transpose, const char* info) = 0; diff --git a/dom/canvas/WebGLContextBuffers.cpp b/dom/canvas/WebGLContextBuffers.cpp index 526e324f79c6..67a36ab9dbfc 100644 --- a/dom/canvas/WebGLContextBuffers.cpp +++ b/dom/canvas/WebGLContextBuffers.cpp @@ -20,24 +20,7 @@ WebGLContext::UpdateBoundBuffer(GLenum target, WebGLBuffer* buffer) if (!buffer) return; - /* https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.1 - * - * In the WebGL 2 API, buffers have their WebGL buffer type - * initially set to undefined. Calling bindBuffer, bindBufferRange - * or bindBufferBase with the target argument set to any buffer - * binding point except COPY_READ_BUFFER or COPY_WRITE_BUFFER will - * then set the WebGL buffer type of the buffer being bound - * according to the table above. - * - * Any call to one of these functions which attempts to bind a - * WebGLBuffer that has the element array WebGL buffer type to a - * binding point that falls under other data, or bind a - * WebGLBuffer which has the other data WebGL buffer type to - * ELEMENT_ARRAY_BUFFER will generate an INVALID_OPERATION error, - * and the state of the binding point will remain untouched. - */ - if (target != LOCAL_GL_COPY_READ_BUFFER && target != LOCAL_GL_COPY_WRITE_BUFFER) - buffer->BindTo(target); + buffer->BindTo(target); } void @@ -435,9 +418,89 @@ WebGLContext::IsBuffer(WebGLBuffer* buffer) if (IsContextLost()) return false; - return ValidateObjectAllowDeleted("isBuffer", buffer) && - !buffer->IsDeleted() && - buffer->HasEverBeenBound(); + if (!ValidateObjectAllowDeleted("isBuffer", buffer)) + return false; + + if (buffer->IsDeleted()) + return false; + + MakeContextCurrent(); + return gl->fIsBuffer(buffer->mGLName); +} + +bool +WebGLContext::ValidateBufferForTarget(GLenum target, WebGLBuffer* buffer, + const char* info) +{ + if (!buffer) + return true; + + /* https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.1 + * + * In the WebGL 2 API, buffers have their WebGL buffer type + * initially set to undefined. Calling bindBuffer, bindBufferRange + * or bindBufferBase with the target argument set to any buffer + * binding point except COPY_READ_BUFFER or COPY_WRITE_BUFFER will + * then set the WebGL buffer type of the buffer being bound + * according to the table above. + * + * Any call to one of these functions which attempts to bind a + * WebGLBuffer that has the element array WebGL buffer type to a + * binding point that falls under other data, or bind a + * WebGLBuffer which has the other data WebGL buffer type to + * ELEMENT_ARRAY_BUFFER will generate an INVALID_OPERATION error, + * and the state of the binding point will remain untouched. + */ + + GLenum boundTo = GetCurrentBinding(buffer); + if (boundTo != LOCAL_GL_NONE) { + if (target == LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER && + boundTo != LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER) + { + ErrorInvalidOperation("Can't bind buffer to TRANSFORM_FEEDBACK_BUFFER as the " + "buffer is already bound to another bind point."); + return false; + } + else if (target != LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER && + boundTo == LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER) + { + ErrorInvalidOperation("Can't bind buffer to bind point as it is currently " + "bound to TRANSFORM_FEEDBACK_BUFFER."); + return false; + } + } + + WebGLBuffer::Kind content = buffer->Content(); + if (content == WebGLBuffer::Kind::Undefined) + return true; + + switch (target) { + case LOCAL_GL_COPY_READ_BUFFER: + case LOCAL_GL_COPY_WRITE_BUFFER: + return true; + + case LOCAL_GL_ELEMENT_ARRAY_BUFFER: + if (content == WebGLBuffer::Kind::ElementArray) + return true; + break; + + case LOCAL_GL_ARRAY_BUFFER: + case LOCAL_GL_PIXEL_PACK_BUFFER: + case LOCAL_GL_PIXEL_UNPACK_BUFFER: + case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER: + case LOCAL_GL_UNIFORM_BUFFER: + if (content == WebGLBuffer::Kind::OtherData) + return true; + break; + + default: + MOZ_CRASH(); + } + + ErrorInvalidOperation("%s: buffer already contains %s data.", info, + content == WebGLBuffer::Kind::OtherData ? "other" : "element"); + + return false; } bool @@ -510,6 +573,37 @@ WebGLContext::GetBufferSlotByTargetIndexed(GLenum target, GLuint index) } } +GLenum +WebGLContext::GetCurrentBinding(WebGLBuffer* buffer) const +{ + if (mBoundArrayBuffer == buffer) + return LOCAL_GL_ARRAY_BUFFER; + + if (mBoundCopyReadBuffer == buffer) + return LOCAL_GL_COPY_READ_BUFFER; + + if (mBoundCopyWriteBuffer == buffer) + return LOCAL_GL_COPY_WRITE_BUFFER; + + if (mBoundPixelPackBuffer == buffer) + return LOCAL_GL_PIXEL_PACK_BUFFER; + + if (mBoundPixelUnpackBuffer == buffer) + return LOCAL_GL_PIXEL_UNPACK_BUFFER; + + if (mBoundTransformFeedbackBuffer == buffer || + mBoundTransformFeedbackBuffers.Contains(buffer)) { + return LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER; + } + + if (mBoundUniformBuffer == buffer || + mBoundUniformBuffers.Contains(buffer)) { + return LOCAL_GL_UNIFORM_BUFFER; + } + + return LOCAL_GL_NONE; +} + GLenum WebGLContext::CheckedBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) diff --git a/dom/canvas/WebGLContextReporter.cpp b/dom/canvas/WebGLContextReporter.cpp index b7f88473923d..9f78046db833 100644 --- a/dom/canvas/WebGLContextReporter.cpp +++ b/dom/canvas/WebGLContextReporter.cpp @@ -126,8 +126,7 @@ WebGLMemoryTracker::GetBufferCacheMemoryUsed() buffer; buffer = buffer->getNext()) { - if (buffer->HasEverBeenBound() && - buffer->Target() == LOCAL_GL_ELEMENT_ARRAY_BUFFER) { + if (buffer->Content() == WebGLBuffer::Kind::ElementArray) { result += buffer->SizeOfIncludingThis(WebGLBufferMallocSizeOf); } } diff --git a/dom/canvas/WebGLContextUnchecked.cpp b/dom/canvas/WebGLContextUnchecked.cpp index 3824bc303735..43e7eaf37693 100644 --- a/dom/canvas/WebGLContextUnchecked.cpp +++ b/dom/canvas/WebGLContextUnchecked.cpp @@ -38,6 +38,17 @@ void WebGLContextUnchecked::BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer, WebGLintptr offset, WebGLsizeiptr size) { gl->MakeCurrent(); + +#ifdef XP_MACOSX + if (buffer && buffer->Content() == WebGLBuffer::Kind::Undefined && + gl->WorkAroundDriverBugs()) + { + // BindBufferRange will fail if the buffer's contents is undefined. + // Bind so driver initializes the buffer. + gl->fBindBuffer(target, buffer->mGLName); + } +#endif + gl->fBindBufferRange(target, index, buffer ? buffer->mGLName : 0, offset, size); } diff --git a/dom/canvas/WebGLContextValidate.cpp b/dom/canvas/WebGLContextValidate.cpp index c45a7705ef99..846401c1cc26 100644 --- a/dom/canvas/WebGLContextValidate.cpp +++ b/dom/canvas/WebGLContextValidate.cpp @@ -266,8 +266,10 @@ WebGLContext::ValidateDataRanges(WebGLintptr readOffset, WebGLintptr writeOffset MOZ_ASSERT((CheckedInt(writeOffset) + size).isValid()); bool separate = (readOffset + size < writeOffset || writeOffset + size < readOffset); - if (!separate) - ErrorInvalidValue("%s: ranges [readOffset, readOffset + size) and [writeOffset, writeOffset + size) overlap"); + if (!separate) { + ErrorInvalidValue("%s: ranges [readOffset, readOffset + size) and [writeOffset, " + "writeOffset + size) overlap", info); + } return separate; } From 9fea68d7477450af98981d3a8ee754a7fa52e259 Mon Sep 17 00:00:00 2001 From: Dan Glastonbury Date: Tue, 2 Jun 2015 11:07:57 +1000 Subject: [PATCH 72/95] Bug 1167504 - Part 12: Return new buffer binding points from getParameter. r=jgilbert --- dom/canvas/WebGLContextState.cpp | 50 +++++++++++++++++++------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/dom/canvas/WebGLContextState.cpp b/dom/canvas/WebGLContextState.cpp index c617562dffba..d6f4eae7431e 100644 --- a/dom/canvas/WebGLContextState.cpp +++ b/dom/canvas/WebGLContextState.cpp @@ -194,21 +194,38 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv) if (IsWebGL2()) { switch (pname) { - case LOCAL_GL_MAX_SAMPLES: - case LOCAL_GL_MAX_UNIFORM_BLOCK_SIZE: - case LOCAL_GL_MAX_VERTEX_UNIFORM_COMPONENTS: { - GLint val; - gl->fGetIntegerv(pname, &val); - return JS::NumberValue(uint32_t(val)); - } + case LOCAL_GL_MAX_SAMPLES: + case LOCAL_GL_MAX_UNIFORM_BLOCK_SIZE: + case LOCAL_GL_MAX_VERTEX_UNIFORM_COMPONENTS: { + GLint val; + gl->fGetIntegerv(pname, &val); + return JS::NumberValue(uint32_t(val)); + } - case LOCAL_GL_TEXTURE_BINDING_3D: { - return WebGLObjectAsJSValue(cx, mBound3DTextures[mActiveTexture].get(), rv); - } + case LOCAL_GL_TEXTURE_BINDING_3D: + return WebGLObjectAsJSValue(cx, mBound3DTextures[mActiveTexture].get(), rv); - // DRAW_FRAMEBUFFER_BINDING is the same as FRAMEBUFFER_BINDING. - case LOCAL_GL_READ_FRAMEBUFFER_BINDING: - return WebGLObjectAsJSValue(cx, mBoundReadFramebuffer.get(), rv); + // DRAW_FRAMEBUFFER_BINDING is the same as FRAMEBUFFER_BINDING. + case LOCAL_GL_READ_FRAMEBUFFER_BINDING: + return WebGLObjectAsJSValue(cx, mBoundReadFramebuffer.get(), rv); + + case LOCAL_GL_PIXEL_PACK_BUFFER_BINDING: + return WebGLObjectAsJSValue(cx, mBoundPixelPackBuffer.get(), rv); + + case LOCAL_GL_PIXEL_UNPACK_BUFFER_BINDING: + return WebGLObjectAsJSValue(cx, mBoundPixelUnpackBuffer.get(), rv); + + case LOCAL_GL_UNIFORM_BUFFER_BINDING: + return WebGLObjectAsJSValue(cx, mBoundUniformBuffer.get(), rv); + + case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + return WebGLObjectAsJSValue(cx, mBoundTransformFeedbackBuffer.get(), rv); + + case LOCAL_GL_COPY_READ_BUFFER_BINDING: + return WebGLObjectAsJSValue(cx, mBoundCopyReadBuffer.get(), rv); + + case LOCAL_GL_COPY_WRITE_BUFFER_BINDING: + return WebGLObjectAsJSValue(cx, mBoundCopyWriteBuffer.get(), rv); } } @@ -533,13 +550,6 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv) return WebGLObjectAsJSValue(cx, mBoundArrayBuffer.get(), rv); } - case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: { - if (!IsWebGL2()) { - break; - } - return WebGLObjectAsJSValue(cx, mBoundTransformFeedbackBuffer.get(), rv); - } - case LOCAL_GL_ELEMENT_ARRAY_BUFFER_BINDING: { return WebGLObjectAsJSValue(cx, mBoundVertexArray->mElementArrayBuffer.get(), rv); } From 71efcb229e0afe5720f2063cb646cb38ffd648be Mon Sep 17 00:00:00 2001 From: Dan Glastonbury Date: Tue, 2 Jun 2015 11:08:55 +1000 Subject: [PATCH 73/95] Bug 1167504 - Part 13: Unbind buffers from cached state on buffer deletion. r=jgilbert --- dom/canvas/WebGLContextBuffers.cpp | 46 +++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/dom/canvas/WebGLContextBuffers.cpp b/dom/canvas/WebGLContextBuffers.cpp index 67a36ab9dbfc..f0d419df69ea 100644 --- a/dom/canvas/WebGLContextBuffers.cpp +++ b/dom/canvas/WebGLContextBuffers.cpp @@ -393,12 +393,50 @@ WebGLContext::DeleteBuffer(WebGLBuffer* buffer) if (!buffer || buffer->IsDeleted()) return; - if (mBoundArrayBuffer == buffer) - BindBuffer(LOCAL_GL_ARRAY_BUFFER, static_cast(nullptr)); + // TODO: Extract this into a helper function? + if (mBoundArrayBuffer == buffer) { + WebGLContextUnchecked::BindBuffer(LOCAL_GL_ARRAY_BUFFER, nullptr); + mBoundArrayBuffer = nullptr; + } if (mBoundVertexArray->mElementArrayBuffer == buffer) { - BindBuffer(LOCAL_GL_ELEMENT_ARRAY_BUFFER, - static_cast(nullptr)); + WebGLContextUnchecked::BindBuffer(LOCAL_GL_ELEMENT_ARRAY_BUFFER, nullptr); + mBoundVertexArray->mElementArrayBuffer = nullptr; + } + + // WebGL binding points + if (IsWebGL2()) { + if (mBoundCopyReadBuffer == buffer) + mBoundCopyReadBuffer = nullptr; + + if (mBoundCopyWriteBuffer == buffer) + mBoundCopyWriteBuffer = nullptr; + + if (mBoundPixelPackBuffer == buffer) + mBoundPixelPackBuffer = nullptr; + + if (mBoundPixelUnpackBuffer == buffer) + mBoundPixelUnpackBuffer = nullptr; + + if (mBoundTransformFeedbackBuffer == buffer) + mBoundTransformFeedbackBuffer = nullptr; + + if (mBoundUniformBuffer == buffer) + mBoundUniformBuffer = nullptr; + + const size_t xfBufferCount = mBoundTransformFeedbackBuffers.Length(); + for (size_t n = 0; n < xfBufferCount; n++) { + if (mBoundTransformFeedbackBuffers[n] == buffer) { + mBoundTransformFeedbackBuffers[n] = nullptr; + } + } + + const size_t uniformBufferCount = mBoundUniformBuffers.Length(); + for (size_t n = 0; n < uniformBufferCount; n++) { + if (mBoundUniformBuffers[n] == buffer) { + mBoundUniformBuffers[n] = nullptr; + } + } } for (int32_t i = 0; i < mGLMaxVertexAttribs; i++) { From 3d39da47b9d38476b51f2f64fe2f204b627d5e0f Mon Sep 17 00:00:00 2001 From: Bill McCloskey Date: Fri, 8 May 2015 12:52:49 -0700 Subject: [PATCH 74/95] Bug 1163861 - Pass window IDs in nsILoadInfo (r=ckerschb) --- netwerk/base/LoadInfo.cpp | 59 +++++++++++++++++-- netwerk/base/LoadInfo.h | 8 ++- netwerk/base/nsILoadInfo.idl | 42 +++++++++---- netwerk/ipc/NeckoChannelParams.ipdlh | 12 +++- netwerk/protocol/ftp/FTPChannelChild.cpp | 4 ++ netwerk/protocol/ftp/FTPChannelParent.cpp | 9 ++- netwerk/protocol/ftp/FTPChannelParent.h | 4 +- netwerk/protocol/http/HttpChannelChild.cpp | 4 ++ netwerk/protocol/http/HttpChannelParent.cpp | 9 ++- netwerk/protocol/http/HttpChannelParent.h | 4 +- .../websocket/WebSocketChannelChild.cpp | 2 + .../websocket/WebSocketChannelParent.cpp | 4 +- 12 files changed, 133 insertions(+), 28 deletions(-) diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp index 51e12f65b69b..264893e1f85b 100644 --- a/netwerk/base/LoadInfo.cpp +++ b/netwerk/base/LoadInfo.cpp @@ -7,8 +7,11 @@ #include "mozilla/LoadInfo.h" #include "mozilla/Assertions.h" +#include "nsFrameLoader.h" +#include "nsIDocShell.h" #include "nsIDocument.h" #include "nsIDOMDocument.h" +#include "nsIFrameLoader.h" #include "nsISupportsImpl.h" #include "nsISupportsUtils.h" @@ -28,8 +31,9 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, , mSecurityFlags(aSecurityFlags) , mContentPolicyType(aContentPolicyType) , mBaseURI(aBaseURI) - , mInnerWindowID(aLoadingContext ? - aLoadingContext->OwnerDoc()->InnerWindowID() : 0) + , mInnerWindowID(0) + , mOuterWindowID(0) + , mParentOuterWindowID(0) { MOZ_ASSERT(mLoadingPrincipal); MOZ_ASSERT(mTriggeringPrincipal); @@ -43,18 +47,51 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, if (mSecurityFlags & nsILoadInfo::SEC_SANDBOXED) { mSecurityFlags ^= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL; } + + if (aLoadingContext) { + nsCOMPtr outerWindow; + + // When the element being loaded is a frame, we choose the frame's window + // for the window ID and the frame element's window as the parent + // window. This is the behavior that Chrome exposes to add-ons. + nsCOMPtr frameLoaderOwner = do_QueryInterface(aLoadingContext); + if (frameLoaderOwner) { + nsCOMPtr fl = frameLoaderOwner->GetFrameLoader(); + nsCOMPtr docShell; + if (fl && NS_SUCCEEDED(fl->GetDocShell(getter_AddRefs(docShell))) && docShell) { + outerWindow = do_GetInterface(docShell); + } + } else { + outerWindow = aLoadingContext->OwnerDoc()->GetWindow(); + } + + if (outerWindow) { + nsCOMPtr inner = outerWindow->GetCurrentInnerWindow(); + mInnerWindowID = inner ? inner->WindowID() : 0; + mOuterWindowID = outerWindow->WindowID(); + + nsCOMPtr parent; + outerWindow->GetParent(getter_AddRefs(parent)); + nsCOMPtr piParent = do_QueryInterface(parent); + mParentOuterWindowID = piParent->WindowID(); + } + } } LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, nsIPrincipal* aTriggeringPrincipal, nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType, - uint32_t aInnerWindowID) + uint64_t aInnerWindowID, + uint64_t aOuterWindowID, + uint64_t aParentOuterWindowID) : mLoadingPrincipal(aLoadingPrincipal) , mTriggeringPrincipal(aTriggeringPrincipal) , mSecurityFlags(aSecurityFlags) , mContentPolicyType(aContentPolicyType) , mInnerWindowID(aInnerWindowID) + , mOuterWindowID(aOuterWindowID) + , mParentOuterWindowID(aParentOuterWindowID) { MOZ_ASSERT(mLoadingPrincipal); MOZ_ASSERT(mTriggeringPrincipal); @@ -154,10 +191,24 @@ LoadInfo::BaseURI() } NS_IMETHODIMP -LoadInfo::GetInnerWindowID(uint32_t* aResult) +LoadInfo::GetInnerWindowID(uint64_t* aResult) { *aResult = mInnerWindowID; return NS_OK; } +NS_IMETHODIMP +LoadInfo::GetOuterWindowID(uint64_t* aResult) +{ + *aResult = mOuterWindowID; + return NS_OK; +} + +NS_IMETHODIMP +LoadInfo::GetParentOuterWindowID(uint64_t* aResult) +{ + *aResult = mParentOuterWindowID; + return NS_OK; +} + } // namespace mozilla diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h index ba4e659e8de8..fe0b54b099d0 100644 --- a/netwerk/base/LoadInfo.h +++ b/netwerk/base/LoadInfo.h @@ -53,7 +53,9 @@ private: nsIPrincipal* aTriggeringPrincipal, nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType, - uint32_t aInnerWindowID); + uint64_t aInnerWindowID, + uint64_t aOuterWindowID, + uint64_t aParentOuterWindowID); friend class net::HttpChannelParent; friend class net::FTPChannelParent; @@ -67,7 +69,9 @@ private: nsSecurityFlags mSecurityFlags; nsContentPolicyType mContentPolicyType; nsCOMPtr mBaseURI; - uint32_t mInnerWindowID; + uint64_t mInnerWindowID; + uint64_t mOuterWindowID; + uint64_t mParentOuterWindowID; }; } // namespace mozilla diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl index d68c29e40a29..9025d4ae5b0c 100644 --- a/netwerk/base/nsILoadInfo.idl +++ b/netwerk/base/nsILoadInfo.idl @@ -17,7 +17,7 @@ typedef unsigned long nsSecurityFlags; /** * An nsILoadOwner represents per-load information about who started the load. */ -[scriptable, builtinclass, uuid(768a1f20-57d4-462a-812a-41c04e5d1e19)] +[scriptable, builtinclass, uuid(dcf54f49-2d63-4c34-9da1-54df235f354c)] interface nsILoadInfo : nsISupports { /** @@ -182,22 +182,44 @@ interface nsILoadInfo : nsISupports nsIURI binaryBaseURI(); /** - * The innerWindowId of the loadingDocument, used to identify - * the loadingDocument in e10s where the loadingDocument is - * not available. + * Typically these are the window IDs of the window in which the element being + * loaded lives. However, if the element being loaded is (or, more generally, if the element QIs to + * nsIFrameLoaderOwner) then the window IDs are for the window containing the + * foo.html document. In this case, parentOuterWindowID is the window ID of + * the window containing the element. * - * Warning: If the loadingDocument is null, then the - * innerWindowId is 0. + * Note that these window IDs can be 0 if the window is not + * available. parentOuterWindowID will be the same as outerWindowID if the + * window has no parent. */ - readonly attribute unsigned long innerWindowID; + readonly attribute unsigned long long innerWindowID; + readonly attribute unsigned long long outerWindowID; + readonly attribute unsigned long long parentOuterWindowID; %{ C++ - inline uint32_t GetInnerWindowID() + inline uint64_t GetInnerWindowID() { - uint32_t result; + uint64_t result; mozilla::DebugOnly rv = GetInnerWindowID(&result); MOZ_ASSERT(NS_SUCCEEDED(rv)); return result; } -%} + + inline uint64_t GetOuterWindowID() + { + uint64_t result; + mozilla::DebugOnly rv = GetOuterWindowID(&result); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + return result; + } + + inline uint64_t GetParentOuterWindowID() + { + uint64_t result; + mozilla::DebugOnly rv = GetParentOuterWindowID(&result); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + return result; + } + %} }; diff --git a/netwerk/ipc/NeckoChannelParams.ipdlh b/netwerk/ipc/NeckoChannelParams.ipdlh index bfcb5de343e3..f5f3e836c266 100644 --- a/netwerk/ipc/NeckoChannelParams.ipdlh +++ b/netwerk/ipc/NeckoChannelParams.ipdlh @@ -65,7 +65,9 @@ struct HttpChannelOpenArgs PrincipalInfo triggeringPrincipalInfo; uint32_t securityFlags; uint32_t contentPolicyType; - uint32_t innerWindowID; + uint64_t innerWindowID; + uint64_t outerWindowID; + uint64_t parentOuterWindowID; OptionalHttpResponseHead synthesizedResponseHead; uint32_t cacheKey; }; @@ -96,7 +98,9 @@ struct FTPChannelOpenArgs PrincipalInfo triggeringPrincipalInfo; uint32_t securityFlags; uint32_t contentPolicyType; - uint32_t innerWindowID; + uint64_t innerWindowID; + uint64_t outerWindowID; + uint64_t parentOuterWindowID; }; struct FTPChannelConnectArgs @@ -142,7 +146,9 @@ struct WebSocketLoadInfoArgs PrincipalInfo triggeringPrincipalInfo; uint32_t securityFlags; uint32_t contentPolicyType; - uint32_t innerWindowID; + uint64_t innerWindowID; + uint64_t outerWindowID; + uint64_t parentOuterWindowID; }; } // namespace ipc diff --git a/netwerk/protocol/ftp/FTPChannelChild.cpp b/netwerk/protocol/ftp/FTPChannelChild.cpp index a573b17c68b7..f32c7b27c895 100644 --- a/netwerk/protocol/ftp/FTPChannelChild.cpp +++ b/netwerk/protocol/ftp/FTPChannelChild.cpp @@ -163,6 +163,8 @@ propagateLoadInfo(nsILoadInfo *aLoadInfo, openArgs.securityFlags() = aLoadInfo->GetSecurityFlags(); openArgs.contentPolicyType() = aLoadInfo->GetContentPolicyType(); openArgs.innerWindowID() = aLoadInfo->GetInnerWindowID(); + openArgs.outerWindowID() = aLoadInfo->GetOuterWindowID(); + openArgs.parentOuterWindowID() = aLoadInfo->GetParentOuterWindowID(); return; } @@ -174,6 +176,8 @@ propagateLoadInfo(nsILoadInfo *aLoadInfo, openArgs.securityFlags() = nsILoadInfo::SEC_NORMAL; openArgs.contentPolicyType() = nsIContentPolicy::TYPE_OTHER; openArgs.innerWindowID() = 0; + openArgs.outerWindowID() = 0; + openArgs.parentOuterWindowID() = 0; } NS_IMETHODIMP diff --git a/netwerk/protocol/ftp/FTPChannelParent.cpp b/netwerk/protocol/ftp/FTPChannelParent.cpp index 32e200d05c9b..c0a9b0f503d6 100644 --- a/netwerk/protocol/ftp/FTPChannelParent.cpp +++ b/netwerk/protocol/ftp/FTPChannelParent.cpp @@ -89,7 +89,8 @@ FTPChannelParent::Init(const FTPChannelCreationArgs& aArgs) const FTPChannelOpenArgs& a = aArgs.get_FTPChannelOpenArgs(); return DoAsyncOpen(a.uri(), a.startPos(), a.entityID(), a.uploadStream(), a.requestingPrincipalInfo(), a.triggeringPrincipalInfo(), - a.securityFlags(), a.contentPolicyType(), a.innerWindowID()); + a.securityFlags(), a.contentPolicyType(), + a.innerWindowID(), a.outerWindowID(), a.parentOuterWindowID()); } case FTPChannelCreationArgs::TFTPChannelConnectArgs: { @@ -111,7 +112,9 @@ FTPChannelParent::DoAsyncOpen(const URIParams& aURI, const ipc::PrincipalInfo& aTriggeringPrincipalInfo, const uint32_t& aSecurityFlags, const uint32_t& aContentPolicyType, - const uint32_t& aInnerWindowID) + const uint64_t& aInnerWindowID, + const uint64_t& aOuterWindowID, + const uint64_t& aParentOuterWindowID) { nsCOMPtr uri = DeserializeURI(aURI); if (!uri) @@ -154,7 +157,7 @@ FTPChannelParent::DoAsyncOpen(const URIParams& aURI, nsCOMPtr loadInfo = new mozilla::LoadInfo(requestingPrincipal, triggeringPrincipal, aSecurityFlags, aContentPolicyType, - aInnerWindowID); + aInnerWindowID, aOuterWindowID, aParentOuterWindowID); nsCOMPtr chan; rv = NS_NewChannelInternal(getter_AddRefs(chan), uri, loadInfo, diff --git a/netwerk/protocol/ftp/FTPChannelParent.h b/netwerk/protocol/ftp/FTPChannelParent.h index e47368982161..654367e04587 100644 --- a/netwerk/protocol/ftp/FTPChannelParent.h +++ b/netwerk/protocol/ftp/FTPChannelParent.h @@ -68,7 +68,9 @@ protected: const ipc::PrincipalInfo& aTriggeringPrincipalInfo, const uint32_t& aSecurityFlags, const uint32_t& aContentPolicyType, - const uint32_t& aInnerWindowID); + const uint64_t& aInnerWindowID, + const uint64_t& aOuterWindowID, + const uint64_t& aParentOuterWindowID); // used to connect redirected-to channel in parent with just created // ChildChannel. Used during HTTP->FTP redirects. diff --git a/netwerk/protocol/http/HttpChannelChild.cpp b/netwerk/protocol/http/HttpChannelChild.cpp index d1fa7d50b4bc..1c94daea8577 100644 --- a/netwerk/protocol/http/HttpChannelChild.cpp +++ b/netwerk/protocol/http/HttpChannelChild.cpp @@ -1489,6 +1489,8 @@ propagateLoadInfo(nsILoadInfo *aLoadInfo, openArgs.securityFlags() = aLoadInfo->GetSecurityFlags(); openArgs.contentPolicyType() = aLoadInfo->GetContentPolicyType(); openArgs.innerWindowID() = aLoadInfo->GetInnerWindowID(); + openArgs.outerWindowID() = aLoadInfo->GetOuterWindowID(); + openArgs.parentOuterWindowID() = aLoadInfo->GetParentOuterWindowID(); return; } @@ -1500,6 +1502,8 @@ propagateLoadInfo(nsILoadInfo *aLoadInfo, openArgs.securityFlags() = nsILoadInfo::SEC_NORMAL; openArgs.contentPolicyType() = nsIContentPolicy::TYPE_OTHER; openArgs.innerWindowID() = 0; + openArgs.outerWindowID() = 0; + openArgs.parentOuterWindowID() = 0; } NS_IMETHODIMP diff --git a/netwerk/protocol/http/HttpChannelParent.cpp b/netwerk/protocol/http/HttpChannelParent.cpp index 5ae9477a76e3..36e8e5f103a4 100644 --- a/netwerk/protocol/http/HttpChannelParent.cpp +++ b/netwerk/protocol/http/HttpChannelParent.cpp @@ -121,7 +121,8 @@ HttpChannelParent::Init(const HttpChannelCreationArgs& aArgs) a.entityID(), a.chooseApplicationCache(), a.appCacheClientID(), a.allowSpdy(), a.allowAltSvc(), a.fds(), a.requestingPrincipalInfo(), a.triggeringPrincipalInfo(), - a.securityFlags(), a.contentPolicyType(), a.innerWindowID(), + a.securityFlags(), a.contentPolicyType(), + a.innerWindowID(), a.outerWindowID(), a.parentOuterWindowID(), a.synthesizedResponseHead(), a.cacheKey()); } case HttpChannelCreationArgs::THttpChannelConnectArgs: @@ -280,7 +281,9 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI, const ipc::PrincipalInfo& aTriggeringPrincipalInfo, const uint32_t& aSecurityFlags, const uint32_t& aContentPolicyType, - const uint32_t& aInnerWindowID, + const uint64_t& aInnerWindowID, + const uint64_t& aOuterWindowID, + const uint64_t& aParentOuterWindowID, const OptionalHttpResponseHead& aSynthesizedResponseHead, const uint32_t& aCacheKey) { @@ -335,7 +338,7 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI, nsCOMPtr loadInfo = new mozilla::LoadInfo(requestingPrincipal, triggeringPrincipal, aSecurityFlags, aContentPolicyType, - aInnerWindowID); + aInnerWindowID, aOuterWindowID, aParentOuterWindowID); nsCOMPtr channel; rv = NS_NewChannelInternal(getter_AddRefs(channel), uri, loadInfo, diff --git a/netwerk/protocol/http/HttpChannelParent.h b/netwerk/protocol/http/HttpChannelParent.h index 07e8626de876..da1a2f1bb248 100644 --- a/netwerk/protocol/http/HttpChannelParent.h +++ b/netwerk/protocol/http/HttpChannelParent.h @@ -120,7 +120,9 @@ protected: const ipc::PrincipalInfo& aTriggeringPrincipalInfo, const uint32_t& aSecurityFlags, const uint32_t& aContentPolicyType, - const uint32_t& aInnerWindowID, + const uint64_t& aInnerWindowID, + const uint64_t& aOuterWindowID, + const uint64_t& aParentOuterWindowID, const OptionalHttpResponseHead& aSynthesizedResponseHead, const uint32_t& aCacheKey); diff --git a/netwerk/protocol/websocket/WebSocketChannelChild.cpp b/netwerk/protocol/websocket/WebSocketChannelChild.cpp index bd11aa023967..9e3d4bfd821c 100644 --- a/netwerk/protocol/websocket/WebSocketChannelChild.cpp +++ b/netwerk/protocol/websocket/WebSocketChannelChild.cpp @@ -470,6 +470,8 @@ propagateLoadInfo(nsILoadInfo *aLoadInfo, wsArgs.securityFlags() = aLoadInfo->GetSecurityFlags(); wsArgs.contentPolicyType() = aLoadInfo->GetContentPolicyType(); wsArgs.innerWindowID() = aLoadInfo->GetInnerWindowID(); + wsArgs.outerWindowID() = aLoadInfo->GetOuterWindowID(); + wsArgs.parentOuterWindowID() = aLoadInfo->GetParentOuterWindowID(); } NS_IMETHODIMP diff --git a/netwerk/protocol/websocket/WebSocketChannelParent.cpp b/netwerk/protocol/websocket/WebSocketChannelParent.cpp index 0adfade13b86..c7ae60a23453 100644 --- a/netwerk/protocol/websocket/WebSocketChannelParent.cpp +++ b/netwerk/protocol/websocket/WebSocketChannelParent.cpp @@ -111,7 +111,9 @@ WebSocketChannelParent::RecvAsyncOpen(const URIParams& aURI, triggeringPrincipal, aLoadInfoArgs.securityFlags(), aLoadInfoArgs.contentPolicyType(), - aLoadInfoArgs.innerWindowID()); + aLoadInfoArgs.innerWindowID(), + aLoadInfoArgs.outerWindowID(), + aLoadInfoArgs.parentOuterWindowID()); rv = mChannel->SetLoadInfo(loadInfo); if (NS_FAILED(rv)) { goto fail; From 8e239523cca0df7c9bf75d03f9722d13e8a6f841 Mon Sep 17 00:00:00 2001 From: Bill McCloskey Date: Fri, 8 May 2015 15:04:27 -0700 Subject: [PATCH 75/95] Bug 1163861 - Include windowID in all WebRequest notifications (r=Mossop) --- toolkit/modules/addons/WebRequest.jsm | 5 ++++- toolkit/modules/tests/browser/browser_WebRequest.js | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/toolkit/modules/addons/WebRequest.jsm b/toolkit/modules/addons/WebRequest.jsm index 9912c62b803d..b7f9d1ccc81a 100644 --- a/toolkit/modules/addons/WebRequest.jsm +++ b/toolkit/modules/addons/WebRequest.jsm @@ -245,7 +245,8 @@ let HttpObserverManager = { let channel = request.QueryInterface(Ci.nsIHttpChannel); let loadContext = this.getLoadContext(channel); let browser = loadContext ? loadContext.topFrameElement : null; - let policyType = channel.loadInfo.contentPolicyType; + let loadInfo = channel.loadInfo; + let policyType = loadInfo.contentPolicyType; let requestHeaders; let responseHeaders; @@ -262,6 +263,8 @@ let HttpObserverManager = { method: channel.requestMethod, browser: browser, type: WebRequestCommon.typeForPolicyType(policyType), + windowId: loadInfo.outerWindowID, + parentWindowId: loadInfo.parentOuterWindowID, }; if (opts.requestHeaders) { if (!requestHeaders) { diff --git a/toolkit/modules/tests/browser/browser_WebRequest.js b/toolkit/modules/tests/browser/browser_WebRequest.js index f205509135de..8eefcc2e4086 100644 --- a/toolkit/modules/tests/browser/browser_WebRequest.js +++ b/toolkit/modules/tests/browser/browser_WebRequest.js @@ -63,6 +63,9 @@ function onBeforeSendHeaders(details) is(details.browser, expected_browser, "correct element"); checkType(details); + + let id = windowIDs.get(details.url); + is(id, details.windowId, "window ID same in onBeforeSendHeaders as onBeforeRequest"); } if (details.url.indexOf("_redirect.") != -1) { return {redirectUrl: details.url.replace("_redirect.", "_good.")}; From 82b1bbba3bb3961f687b43a31135bdc1e877aaf5 Mon Sep 17 00:00:00 2001 From: Bill McCloskey Date: Wed, 3 Jun 2015 11:48:20 -0700 Subject: [PATCH 76/95] Bug 1171219 - Support for badged toolbarbuttons with panels (r=neil) --- toolkit/content/widgets/toolbarbutton.xml | 17 +++++++++++++++++ toolkit/content/xul.css | 5 +++++ 2 files changed, 22 insertions(+) diff --git a/toolkit/content/widgets/toolbarbutton.xml b/toolkit/content/widgets/toolbarbutton.xml index bfc91a7b00da..1bc10ff66c79 100644 --- a/toolkit/content/widgets/toolbarbutton.xml +++ b/toolkit/content/widgets/toolbarbutton.xml @@ -95,4 +95,21 @@ xbl:inherits="xbl:text=label,accesskey,wrap"/> + + + + + + + + + + + + + diff --git a/toolkit/content/xul.css b/toolkit/content/xul.css index 82c34bb311e9..e3fc95651bc8 100644 --- a/toolkit/content/xul.css +++ b/toolkit/content/xul.css @@ -143,6 +143,11 @@ toolbarbutton[type="panel"] { -moz-binding: url("chrome://global/content/bindings/toolbarbutton.xml#menu"); } +toolbarbutton.badged-button[type="menu"], +toolbarbutton.badged-button[type="panel"] { + -moz-binding: url("chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton-badged-menu"); +} + toolbarbutton[type="menu-button"] { -moz-binding: url("chrome://global/content/bindings/toolbarbutton.xml#menu-button"); } From 1a885b7b9963a6cf6a49aa2bc4cf0018decaa721 Mon Sep 17 00:00:00 2001 From: Bill McCloskey Date: Wed, 3 Jun 2015 11:52:47 -0700 Subject: [PATCH 77/95] Bug 1171234 - Include triggering node in load info when doing prefetching (r=ckerschb) --- uriloader/prefetch/nsPrefetchService.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/uriloader/prefetch/nsPrefetchService.cpp b/uriloader/prefetch/nsPrefetchService.cpp index d72abde572de..b2567a57fa8e 100644 --- a/uriloader/prefetch/nsPrefetchService.cpp +++ b/uriloader/prefetch/nsPrefetchService.cpp @@ -1,3 +1,4 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* 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/. */ @@ -185,15 +186,17 @@ nsPrefetchNode::OpenChannel() return NS_ERROR_FAILURE; } nsCOMPtr loadGroup = source->OwnerDoc()->GetDocumentLoadGroup(); - nsresult rv = NS_NewChannel(getter_AddRefs(mChannel), - mURI, - nsContentUtils::GetSystemPrincipal(), - nsILoadInfo::SEC_NORMAL, - nsIContentPolicy::TYPE_OTHER, - loadGroup, // aLoadGroup - this, // aCallbacks - nsIRequest::LOAD_BACKGROUND | - nsICachingChannel::LOAD_ONLY_IF_MODIFIED); + nsresult rv = NS_NewChannelInternal(getter_AddRefs(mChannel), + mURI, + source, + source->NodePrincipal(), + nullptr, //aTriggeringPrincipal + nsILoadInfo::SEC_NORMAL, + nsIContentPolicy::TYPE_OTHER, + loadGroup, // aLoadGroup + this, // aCallbacks + nsIRequest::LOAD_BACKGROUND | + nsICachingChannel::LOAD_ONLY_IF_MODIFIED); NS_ENSURE_SUCCESS(rv, rv); From eca105eb0b33c01277efbbb173634000e2dd0d48 Mon Sep 17 00:00:00 2001 From: Bill McCloskey Date: Wed, 3 Jun 2015 11:53:39 -0700 Subject: [PATCH 78/95] Bug 1171245 - Include changes attributes in TabAttrModified event (r=ttaubert) --- browser/base/content/tabbrowser.xml | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index cc4be82adbb2..794f5b6c4754 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -692,7 +692,7 @@ if (this.mTab.hasAttribute("busy")) { this.mTab.removeAttribute("busy"); - this.mTabBrowser._tabAttrModified(this.mTab); + this.mTabBrowser._tabAttrModified(this.mTab, ["busy"]); if (!this.mTab.selected) this.mTab.setAttribute("unread", "true"); } @@ -892,7 +892,7 @@ aTab.setAttribute("image", sizedIconUrl); else aTab.removeAttribute("image"); - this._tabAttrModified(aTab); + this._tabAttrModified(aTab, ["image"]); } this._callProgressListeners(browser, "onLinkIconAvailable", [browser.mIconURL]); @@ -1167,8 +1167,8 @@ }); this.mCurrentTab.dispatchEvent(event); - this._tabAttrModified(oldTab); - this._tabAttrModified(this.mCurrentTab); + this._tabAttrModified(oldTab, ["selected"]); + this._tabAttrModified(this.mCurrentTab, ["selected"]); if (oldBrowser != newBrowser && oldBrowser.docShell && @@ -1300,14 +1300,18 @@ + @@ -1318,7 +1322,7 @@ @@ -1363,7 +1367,7 @@ aTab.label = title; aTab.crop = crop; - this._tabAttrModified(aTab); + this._tabAttrModified(aTab, ["label", "crop"]); if (aTab.selected) this.updateTitlebar(); @@ -2449,7 +2453,7 @@ var isBusy = aOtherTab.hasAttribute("busy"); if (isBusy) { aOurTab.setAttribute("busy", "true"); - this._tabAttrModified(aOurTab); + this._tabAttrModified(aOurTab, ["busy"]); if (aOurTab.selected) this.mIsBusy = true; } From 3623e42122a69f69c6d9df2eb6461e78f88a5e45 Mon Sep 17 00:00:00 2001 From: Chris Peterson Date: Thu, 4 Jun 2015 00:00:23 -0700 Subject: [PATCH 79/95] Bug 1171358 - Fix -Wunreachable-code-return warning in libmar/tool. r=rstrong --- modules/libmar/tool/mar.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/libmar/tool/mar.c b/modules/libmar/tool/mar.c index 88110098416a..30d626661818 100644 --- a/modules/libmar/tool/mar.c +++ b/modules/libmar/tool/mar.c @@ -412,6 +412,4 @@ int main(int argc, char **argv) { print_usage(); return -1; } - - return 0; } From 1755f9e8bb7f499d47863db94f63a88f87d0aaf0 Mon Sep 17 00:00:00 2001 From: Chris Peterson Date: Sat, 6 Jun 2015 12:35:37 -0700 Subject: [PATCH 80/95] Bug 1026761 - CID 749761: nsAStreamCopier::Process can use sourceCondition, sinkCondition uninitialized. r=froydnj --- xpcom/io/nsStreamUtils.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/xpcom/io/nsStreamUtils.cpp b/xpcom/io/nsStreamUtils.cpp index be326480e3bf..bd3691650003 100644 --- a/xpcom/io/nsStreamUtils.cpp +++ b/xpcom/io/nsStreamUtils.cpp @@ -274,7 +274,6 @@ public: return; } - nsresult sourceCondition, sinkCondition; nsresult cancelStatus; bool canceled; { @@ -283,6 +282,13 @@ public: cancelStatus = mCancelStatus; } + // If the copy was canceled before Process() was even called, then + // sourceCondition and sinkCondition should be set to error results to + // ensure we don't call Finish() on a canceled nsISafeOutputStream. + MOZ_ASSERT(NS_FAILED(cancelStatus) == canceled, "cancel needs an error"); + nsresult sourceCondition = cancelStatus; + nsresult sinkCondition = cancelStatus; + // Copy data from the source to the sink until we hit failure or have // copied all the data. for (;;) { From 12f1be1ab26cca661369d94b64fff275541c9e21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Pag=C3=A8s?= Date: Tue, 9 Jun 2015 20:55:07 +0200 Subject: [PATCH 81/95] Bug 1060940 - remove mozrunner confusing and broken code for getting version information; r=ahal --HG-- extra : commitid : E3oQVx2bT8V extra : rebase_source : 41644fcf75b2b5b638268a23f2c7df530279c5fb --- testing/mozbase/mozrunner/mozrunner/cli.py | 42 ++-------------------- 1 file changed, 3 insertions(+), 39 deletions(-) diff --git a/testing/mozbase/mozrunner/mozrunner/cli.py b/testing/mozbase/mozrunner/mozrunner/cli.py index 85c03d8bf596..37e11401ad85 100644 --- a/testing/mozbase/mozrunner/mozrunner/cli.py +++ b/testing/mozbase/mozrunner/mozrunner/cli.py @@ -2,7 +2,6 @@ # 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 optparse import os import sys @@ -54,20 +53,7 @@ class CLI(MozProfileCLI): module = "mozrunner" def __init__(self, args=sys.argv[1:]): - self.metadata = getattr(sys.modules[self.module], - 'package_metadata', - {}) - version = self.metadata.get('Version') - parser_args = {'description': self.metadata.get('Summary')} - if version: - parser_args['version'] = "%prog " + version - self.parser = optparse.OptionParser(**parser_args) - self.add_options(self.parser) - (self.options, self.args) = self.parser.parse_args(args) - - if getattr(self.options, 'info', None): - self.print_metadata() - sys.exit(0) + MozProfileCLI.__init__(self, args=args) # choose appropriate runner and profile classes app = self.options.app @@ -80,6 +66,8 @@ class CLI(MozProfileCLI): def add_options(self, parser): """add options to the parser""" + parser.description = ("Reliable start/stop/configuration of Mozilla" + " Applications (Firefox, Thunderbird, etc.)") # add profile options MozProfileCLI.add_options(self, parser) @@ -101,30 +89,6 @@ class CLI(MozProfileCLI): parser.add_option('--interactive', dest='interactive', action='store_true', help="run the program interactively") - if self.metadata: - parser.add_option("--info", dest="info", default=False, - action="store_true", - help="Print module information") - - ### methods for introspecting data - - def get_metadata_from_egg(self): - import pkg_resources - ret = {} - dist = pkg_resources.get_distribution(self.module) - if dist.has_metadata("PKG-INFO"): - for line in dist.get_metadata_lines("PKG-INFO"): - key, value = line.split(':', 1) - ret[key] = value - if dist.has_metadata("requires.txt"): - ret["Dependencies"] = "\n" + dist.get_metadata("requires.txt") - return ret - - def print_metadata(self, data=("Name", "Version", "Summary", "Home-page", - "Author", "Author-email", "License", "Platform", "Dependencies")): - for key in data: - if key in self.metadata: - print key + ": " + self.metadata[key] ### methods for running From e590c075d682f1a073b05008e6424ce516425bf1 Mon Sep 17 00:00:00 2001 From: Jan Varga Date: Tue, 9 Jun 2015 17:27:50 +0200 Subject: [PATCH 82/95] Bug 1157670 - Fixing an incorrect assertion in QuotaManager.cpp leads to an assertion failure; r=bent --- dom/quota/QuotaManager.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dom/quota/QuotaManager.cpp b/dom/quota/QuotaManager.cpp index fd3cab50cc8a..5b020ba8bdf3 100644 --- a/dom/quota/QuotaManager.cpp +++ b/dom/quota/QuotaManager.cpp @@ -5098,7 +5098,9 @@ OriginParser::HandleToken(const nsDependentCSubstring& aToken) return; } - mState = eExpectingDriveLetterOrPathnameComponent; + mState = + mTokenizer.hasMoreTokens() ? eExpectingDriveLetterOrPathnameComponent + : eComplete; return; } @@ -5216,7 +5218,7 @@ OriginParser::HandleToken(const nsDependentCSubstring& aToken) void OriginParser::HandleTrailingSeparator() { - MOZ_ASSERT(mState = eComplete); + MOZ_ASSERT(mState == eComplete); MOZ_ASSERT(mSchemaType == eFile); mPathnameComponents.AppendElement(EmptyCString()); From d731a60f51c991a8afc401721e2da22b335ade33 Mon Sep 17 00:00:00 2001 From: Jim Chen Date: Wed, 10 Jun 2015 00:25:01 -0400 Subject: [PATCH 83/95] Bug 1166309 - Move mozglue loading to GeckoThread; r=snorp --- mobile/android/base/GeckoApplication.java | 2 -- mobile/android/base/GeckoThread.java | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mobile/android/base/GeckoApplication.java b/mobile/android/base/GeckoApplication.java index f5ab7b6a5aa5..170e1a446336 100644 --- a/mobile/android/base/GeckoApplication.java +++ b/mobile/android/base/GeckoApplication.java @@ -11,7 +11,6 @@ import org.mozilla.gecko.db.BrowserDB; import org.mozilla.gecko.db.LocalBrowserDB; import org.mozilla.gecko.home.HomePanelsManager; import org.mozilla.gecko.lwt.LightweightTheme; -import org.mozilla.gecko.mozglue.GeckoLoader; import org.mozilla.gecko.util.Clipboard; import org.mozilla.gecko.util.HardwareUtils; import org.mozilla.gecko.util.ThreadUtils; @@ -127,7 +126,6 @@ public class GeckoApplication extends Application HardwareUtils.init(context); Clipboard.init(context); FilePicker.init(context); - GeckoLoader.loadMozGlue(context); DownloadsIntegration.init(); HomePanelsManager.getInstance().init(context); diff --git a/mobile/android/base/GeckoThread.java b/mobile/android/base/GeckoThread.java index 41741f41453d..0b5b2f508b07 100644 --- a/mobile/android/base/GeckoThread.java +++ b/mobile/android/base/GeckoThread.java @@ -90,6 +90,8 @@ public class GeckoThread extends Thread implements GeckoEventListener { final Locale locale = Locale.getDefault(); final Context context = GeckoAppShell.getContext(); + GeckoLoader.loadMozGlue(context); + final Resources res = context.getResources(); if (locale.toString().equalsIgnoreCase("zh_hk")) { final Locale mappedLocale = Locale.TRADITIONAL_CHINESE; From 3e4d973c837a158d0e3ec1db59b734bf93bb0533 Mon Sep 17 00:00:00 2001 From: Jim Chen Date: Wed, 10 Jun 2015 00:25:01 -0400 Subject: [PATCH 84/95] Bug 1166309 - Move gfx mozglue dependency to after Gecko starts; r=snorp --- mobile/android/base/gfx/BufferedImage.java | 21 ++++++++++++----- mobile/android/base/gfx/LayerRenderer.java | 27 ++++++++++++---------- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/mobile/android/base/gfx/BufferedImage.java b/mobile/android/base/gfx/BufferedImage.java index 9e63e3e59b9d..4dbcf61bbcdb 100644 --- a/mobile/android/base/gfx/BufferedImage.java +++ b/mobile/android/base/gfx/BufferedImage.java @@ -15,6 +15,7 @@ import java.nio.ByteBuffer; /** A buffered image that simply saves a buffer of pixel data. */ public class BufferedImage { private ByteBuffer mBuffer; + private Bitmap mBitmap; private IntSize mSize; private int mFormat; @@ -29,14 +30,13 @@ public class BufferedImage { public BufferedImage(Bitmap bitmap) { mFormat = bitmapConfigToFormat(bitmap.getConfig()); mSize = new IntSize(bitmap.getWidth(), bitmap.getHeight()); - - int bpp = bitsPerPixelForFormat(mFormat); - mBuffer = DirectBufferAllocator.allocate(mSize.getArea() * bpp); - bitmap.copyPixelsToBuffer(mBuffer.asIntBuffer()); + mBitmap = bitmap; } private synchronized void freeBuffer() { - mBuffer = DirectBufferAllocator.free(mBuffer); + if (mBuffer != null) { + mBuffer = DirectBufferAllocator.free(mBuffer); + } } public void destroy() { @@ -47,7 +47,16 @@ public class BufferedImage { } } - public ByteBuffer getBuffer() { return mBuffer; } + public ByteBuffer getBuffer() { + if (mBuffer == null) { + int bpp = bitsPerPixelForFormat(mFormat); + mBuffer = DirectBufferAllocator.allocate(mSize.getArea() * bpp); + mBitmap.copyPixelsToBuffer(mBuffer.asIntBuffer()); + mBitmap = null; + } + return mBuffer; + } + public IntSize getSize() { return mSize; } public int getFormat() { return mFormat; } diff --git a/mobile/android/base/gfx/LayerRenderer.java b/mobile/android/base/gfx/LayerRenderer.java index 24aa2f023574..5c932996b343 100644 --- a/mobile/android/base/gfx/LayerRenderer.java +++ b/mobile/android/base/gfx/LayerRenderer.java @@ -161,12 +161,6 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener { mFrameTimings = new int[60]; mCurrentFrame = mFrameTimingsSum = mDroppedFrames = 0; - // Initialize the FloatBuffer that will be used to store all vertices and texture - // coordinates in draw() commands. - mCoordByteBuffer = DirectBufferAllocator.allocate(COORD_BUFFER_SIZE * 4); - mCoordByteBuffer.order(ByteOrder.nativeOrder()); - mCoordBuffer = mCoordByteBuffer.asFloatBuffer(); - Tabs.registerOnTabsChangedListener(this); mZoomedViewListeners = new ArrayList(); } @@ -190,9 +184,11 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener { } public void destroy() { - DirectBufferAllocator.free(mCoordByteBuffer); - mCoordByteBuffer = null; - mCoordBuffer = null; + if (mCoordByteBuffer != null) { + DirectBufferAllocator.free(mCoordByteBuffer); + mCoordByteBuffer = null; + mCoordBuffer = null; + } mHorizScrollLayer.destroy(); mVertScrollLayer.destroy(); Tabs.unregisterOnTabsChangedListener(this); @@ -348,10 +344,17 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener { private RenderContext createContext(RectF viewport, RectF pageRect, float zoomFactor, PointF offset) { if (mCoordBuffer == null) { - throw new IllegalStateException(); + // Initialize the FloatBuffer that will be used to store all vertices and texture + // coordinates in draw() commands. + mCoordByteBuffer = DirectBufferAllocator.allocate(COORD_BUFFER_SIZE * 4); + mCoordByteBuffer.order(ByteOrder.nativeOrder()); + mCoordBuffer = mCoordByteBuffer.asFloatBuffer(); + if (mCoordBuffer == null) { + throw new IllegalStateException(); + } } - return new RenderContext(viewport, pageRect, zoomFactor, offset, mPositionHandle, mTextureHandle, - mCoordBuffer); + return new RenderContext(viewport, pageRect, zoomFactor, offset, + mPositionHandle, mTextureHandle, mCoordBuffer); } private void updateDroppedFrames(long frameStartTime) { From eda68cee3d889d3cfb3602e053b06e3fe2297116 Mon Sep 17 00:00:00 2001 From: Jim Chen Date: Wed, 10 Jun 2015 00:25:01 -0400 Subject: [PATCH 85/95] Bug 1166309 - Make GeckoJarReader load mozglue if necessary; r=mfinkle r=rnewman --- mobile/android/base/BrowserLocaleManager.java | 2 +- mobile/android/base/db/LocalBrowserDB.java | 2 +- mobile/android/base/favicons/Favicons.java | 3 ++- .../base/favicons/LoadFaviconTask.java | 2 +- mobile/android/base/gfx/BitmapUtils.java | 6 +++-- .../base/updater/UpdateServiceHelper.java | 2 +- mobile/android/base/util/GeckoJarReader.java | 22 +++++++++++-------- .../search/providers/SearchEngineManager.java | 9 ++++---- .../tests/browser/junit3/TestJarReader.java | 13 ++++++----- .../tests/browser/robocop/testJarReader.java | 13 ++++++----- 10 files changed, 44 insertions(+), 30 deletions(-) diff --git a/mobile/android/base/BrowserLocaleManager.java b/mobile/android/base/BrowserLocaleManager.java index 86087fdc78fe..c5433a02bdda 100644 --- a/mobile/android/base/BrowserLocaleManager.java +++ b/mobile/android/base/BrowserLocaleManager.java @@ -400,7 +400,7 @@ public class BrowserLocaleManager implements LocaleManager { final String resPath = "res/multilocale.json"; final String jarURL = GeckoJarReader.getJarURL(context, resPath); - final String contents = GeckoJarReader.getText(jarURL); + final String contents = GeckoJarReader.getText(context, jarURL); if (contents == null) { // GeckoJarReader logs and swallows exceptions. return null; diff --git a/mobile/android/base/db/LocalBrowserDB.java b/mobile/android/base/db/LocalBrowserDB.java index 9a897b185e7e..a98217e9b627 100644 --- a/mobile/android/base/db/LocalBrowserDB.java +++ b/mobile/android/base/db/LocalBrowserDB.java @@ -483,7 +483,7 @@ public class LocalBrowserDB implements BrowserDB { } final String bitmapPath = GeckoJarReader.getJarURL(context, context.getString(faviconId)); - final InputStream iStream = GeckoJarReader.getStream(bitmapPath); + final InputStream iStream = GeckoJarReader.getStream(context, bitmapPath); return IOUtils.readFully(iStream, DEFAULT_FAVICON_BUFFER_SIZE); } diff --git a/mobile/android/base/favicons/Favicons.java b/mobile/android/base/favicons/Favicons.java index afb2a86e72ae..43f4408fa75d 100644 --- a/mobile/android/base/favicons/Favicons.java +++ b/mobile/android/base/favicons/Favicons.java @@ -494,7 +494,8 @@ public class Favicons { } private static Bitmap loadBrandingBitmap(Context context, String name) { - Bitmap b = GeckoJarReader.getBitmap(context.getResources(), + Bitmap b = GeckoJarReader.getBitmap(context, + context.getResources(), getBrandingBitmapPath(context, name)); if (b == null) { throw new IllegalStateException("Bitmap " + name + " missing from JAR!"); diff --git a/mobile/android/base/favicons/LoadFaviconTask.java b/mobile/android/base/favicons/LoadFaviconTask.java index f49797027016..77bf3e1fe3de 100644 --- a/mobile/android/base/favicons/LoadFaviconTask.java +++ b/mobile/android/base/favicons/LoadFaviconTask.java @@ -196,7 +196,7 @@ public class LoadFaviconTask { if (uri.startsWith("jar:jar:")) { Log.d(LOGTAG, "Fetching favicon from JAR."); try { - return GeckoJarReader.getBitmap(context.getResources(), uri); + return GeckoJarReader.getBitmap(context, context.getResources(), uri); } catch (Exception e) { // Just about anything could happen here. Log.w(LOGTAG, "Error fetching favicon from JAR.", e); diff --git a/mobile/android/base/gfx/BitmapUtils.java b/mobile/android/base/gfx/BitmapUtils.java index 7c46e6e135dc..4d1d5bff40cf 100644 --- a/mobile/android/base/gfx/BitmapUtils.java +++ b/mobile/android/base/gfx/BitmapUtils.java @@ -86,12 +86,14 @@ public final class BitmapUtils { public Drawable doInBackground() { try { if (data.startsWith("jar:jar")) { - return GeckoJarReader.getBitmapDrawable(context.getResources(), data); + return GeckoJarReader.getBitmapDrawable( + context, context.getResources(), data); } // Don't attempt to validate the JAR signature when loading an add-on icon if (data.startsWith("jar:file")) { - return GeckoJarReader.getBitmapDrawable(context.getResources(), Uri.decode(data)); + return GeckoJarReader.getBitmapDrawable( + context, context.getResources(), Uri.decode(data)); } final URL url = new URL(data); diff --git a/mobile/android/base/updater/UpdateServiceHelper.java b/mobile/android/base/updater/UpdateServiceHelper.java index 7fc5ed4428f2..9a8f428a2d15 100644 --- a/mobile/android/base/updater/UpdateServiceHelper.java +++ b/mobile/android/base/updater/UpdateServiceHelper.java @@ -103,7 +103,7 @@ public class UpdateServiceHelper { ApplicationInfo info = pm.getApplicationInfo(AppConstants.ANDROID_PACKAGE_NAME, 0); String updateLocaleUrl = "jar:jar:file://" + info.sourceDir + "!/" + AppConstants.OMNIJAR_NAME + "!/update.locale"; - final String jarLocale = GeckoJarReader.getText(updateLocaleUrl); + final String jarLocale = GeckoJarReader.getText(context, updateLocaleUrl); if (jarLocale != null) { locale = jarLocale.trim(); } diff --git a/mobile/android/base/util/GeckoJarReader.java b/mobile/android/base/util/GeckoJarReader.java index b690e06a8a44..c2a3dce1a54d 100644 --- a/mobile/android/base/util/GeckoJarReader.java +++ b/mobile/android/base/util/GeckoJarReader.java @@ -6,6 +6,7 @@ package org.mozilla.gecko.util; import android.content.Context; import org.mozilla.gecko.AppConstants; +import org.mozilla.gecko.mozglue.GeckoLoader; import org.mozilla.gecko.mozglue.NativeZip; import android.content.res.Resources; @@ -31,12 +32,13 @@ public final class GeckoJarReader { private GeckoJarReader() {} - public static Bitmap getBitmap(Resources resources, String url) { - BitmapDrawable drawable = getBitmapDrawable(resources, url); + public static Bitmap getBitmap(Context context, Resources resources, String url) { + BitmapDrawable drawable = getBitmapDrawable(context, resources, url); return (drawable != null) ? drawable.getBitmap() : null; } - public static BitmapDrawable getBitmapDrawable(Resources resources, String url) { + public static BitmapDrawable getBitmapDrawable(Context context, Resources resources, + String url) { Stack jarUrls = parseUrl(url); InputStream inputStream = null; BitmapDrawable bitmap = null; @@ -44,7 +46,7 @@ public final class GeckoJarReader { NativeZip zip = null; try { // Load the initial jar file as a zip - zip = getZipFile(jarUrls.pop()); + zip = getZipFile(context, jarUrls.pop()); inputStream = getStream(zip, jarUrls, url); if (inputStream != null) { bitmap = new BitmapDrawable(resources, inputStream); @@ -67,14 +69,14 @@ public final class GeckoJarReader { return bitmap; } - public static String getText(String url) { + public static String getText(Context context, String url) { Stack jarUrls = parseUrl(url); NativeZip zip = null; BufferedReader reader = null; String text = null; try { - zip = getZipFile(jarUrls.pop()); + zip = getZipFile(context, jarUrls.pop()); InputStream input = getStream(zip, jarUrls, url); if (input != null) { reader = new BufferedReader(new InputStreamReader(input)); @@ -98,16 +100,18 @@ public final class GeckoJarReader { return text; } - private static NativeZip getZipFile(String url) throws IOException, URISyntaxException { + private static NativeZip getZipFile(Context context, String url) + throws IOException, URISyntaxException { URI fileUrl = new URI(url); + GeckoLoader.loadMozGlue(context); return new NativeZip(fileUrl.getPath()); } @RobocopTarget - public static InputStream getStream(String url) { + public static InputStream getStream(Context context, String url) { Stack jarUrls = parseUrl(url); try { - NativeZip zip = getZipFile(jarUrls.pop()); + NativeZip zip = getZipFile(context, jarUrls.pop()); return getStream(zip, jarUrls, url); } catch (Exception ex) { // Some JNI code throws IllegalArgumentException on a bad file name; diff --git a/mobile/android/search/java/org/mozilla/search/providers/SearchEngineManager.java b/mobile/android/search/java/org/mozilla/search/providers/SearchEngineManager.java index e8531e808d24..c951229f9544 100644 --- a/mobile/android/search/java/org/mozilla/search/providers/SearchEngineManager.java +++ b/mobile/android/search/java/org/mozilla/search/providers/SearchEngineManager.java @@ -619,7 +619,7 @@ public class SearchEngineManager implements SharedPreferences.OnSharedPreference final String languageTag = Locales.getLanguageTag(locale); String url = getSearchPluginsJarURL(context, languageTag, fileName); - InputStream in = GeckoJarReader.getStream(url); + InputStream in = GeckoJarReader.getStream(context, url); if (in != null) { return in; } @@ -628,7 +628,7 @@ public class SearchEngineManager implements SharedPreferences.OnSharedPreference final String language = Locales.getLanguage(locale); if (!languageTag.equals(language)) { url = getSearchPluginsJarURL(context, language, fileName); - in = GeckoJarReader.getStream(url); + in = GeckoJarReader.getStream(context, url); if (in != null) { return in; } @@ -636,7 +636,7 @@ public class SearchEngineManager implements SharedPreferences.OnSharedPreference // Finally, fall back to default locale defined in chrome registry. url = getSearchPluginsJarURL(context, getFallbackLocale(), fileName); - return GeckoJarReader.getStream(url); + return GeckoJarReader.getStream(context, url); } /** @@ -650,7 +650,8 @@ public class SearchEngineManager implements SharedPreferences.OnSharedPreference return fallbackLocale; } - final InputStream in = GeckoJarReader.getStream(GeckoJarReader.getJarURL(context, "chrome/chrome.manifest")); + final InputStream in = GeckoJarReader.getStream( + context, GeckoJarReader.getJarURL(context, "chrome/chrome.manifest")); final BufferedReader br = getBufferedReader(in); try { diff --git a/mobile/android/tests/browser/junit3/src/org/mozilla/tests/browser/junit3/TestJarReader.java b/mobile/android/tests/browser/junit3/src/org/mozilla/tests/browser/junit3/TestJarReader.java index fe0dfffb43fe..cc8b058a9878 100644 --- a/mobile/android/tests/browser/junit3/src/org/mozilla/tests/browser/junit3/TestJarReader.java +++ b/mobile/android/tests/browser/junit3/src/org/mozilla/tests/browser/junit3/TestJarReader.java @@ -9,38 +9,41 @@ import android.test.InstrumentationTestCase; import org.mozilla.gecko.AppConstants; import org.mozilla.gecko.util.GeckoJarReader; +import android.content.Context; + /** * A basic jar reader test. Tests reading a png from fennec's apk, as well as * loading some invalid jar urls. */ public class TestJarReader extends InstrumentationTestCase { public void testJarReader() { + final Context context = getInstrumentation().getTargetContext().getApplicationContext(); String appPath = getInstrumentation().getTargetContext().getPackageResourcePath(); assertNotNull(appPath); // Test reading a file from a jar url that looks correct. String url = "jar:file://" + appPath + "!/" + AppConstants.OMNIJAR_NAME; - InputStream stream = GeckoJarReader.getStream("jar:" + url + "!/chrome/chrome/content/branding/favicon32.png"); + InputStream stream = GeckoJarReader.getStream(context, "jar:" + url + "!/chrome/chrome/content/branding/favicon32.png"); assertNotNull(stream); // Test looking for an non-existent file in a jar. url = "jar:file://" + appPath + "!/" + AppConstants.OMNIJAR_NAME; - stream = GeckoJarReader.getStream("jar:" + url + "!/chrome/chrome/content/branding/nonexistent_file.png"); + stream = GeckoJarReader.getStream(context, "jar:" + url + "!/chrome/chrome/content/branding/nonexistent_file.png"); assertNull(stream); // Test looking for a file that doesn't exist in the APK. url = "jar:file://" + appPath + "!/" + "BAD" + AppConstants.OMNIJAR_NAME; - stream = GeckoJarReader.getStream("jar:" + url + "!/chrome/chrome/content/branding/favicon32.png"); + stream = GeckoJarReader.getStream(context, "jar:" + url + "!/chrome/chrome/content/branding/favicon32.png"); assertNull(stream); // Test looking for an jar with an invalid url. url = "jar:file://" + appPath + "!" + "!/" + AppConstants.OMNIJAR_NAME; - stream = GeckoJarReader.getStream("jar:" + url + "!/chrome/chrome/content/branding/nonexistent_file.png"); + stream = GeckoJarReader.getStream(context, "jar:" + url + "!/chrome/chrome/content/branding/nonexistent_file.png"); assertNull(stream); // Test looking for a file that doesn't exist on disk. url = "jar:file://" + appPath + "BAD" + "!/" + AppConstants.OMNIJAR_NAME; - stream = GeckoJarReader.getStream("jar:" + url + "!/chrome/chrome/content/branding/favicon32.png"); + stream = GeckoJarReader.getStream(context, "jar:" + url + "!/chrome/chrome/content/branding/favicon32.png"); assertNull(stream); } } diff --git a/mobile/android/tests/browser/robocop/testJarReader.java b/mobile/android/tests/browser/robocop/testJarReader.java index 82d82fbaa253..81109ef14c81 100644 --- a/mobile/android/tests/browser/robocop/testJarReader.java +++ b/mobile/android/tests/browser/robocop/testJarReader.java @@ -9,6 +9,8 @@ import java.io.InputStream; import org.mozilla.gecko.AppConstants; import org.mozilla.gecko.util.GeckoJarReader; +import android.content.Context; + /** * A basic jar reader test. Tests reading a png from fennec's apk, as well * as loading some invalid jar urls. @@ -22,32 +24,33 @@ public class testJarReader extends BaseTest { } public void testJarReader() { + final Context context = getInstrumentation().getTargetContext().getApplicationContext(); String appPath = getActivity().getApplication().getPackageResourcePath(); mAsserter.isnot(appPath, null, "getPackageResourcePath is non-null"); // Test reading a file from a jar url that looks correct. String url = "jar:file://" + appPath + "!/" + AppConstants.OMNIJAR_NAME; - InputStream stream = GeckoJarReader.getStream("jar:" + url + "!/chrome/chrome/content/branding/favicon32.png"); + InputStream stream = GeckoJarReader.getStream(context, "jar:" + url + "!/chrome/chrome/content/branding/favicon32.png"); mAsserter.isnot(stream, null, "JarReader returned non-null for valid file in valid jar"); // Test looking for an non-existent file in a jar. url = "jar:file://" + appPath + "!/" + AppConstants.OMNIJAR_NAME; - stream = GeckoJarReader.getStream("jar:" + url + "!/chrome/chrome/content/branding/nonexistent_file.png"); + stream = GeckoJarReader.getStream(context, "jar:" + url + "!/chrome/chrome/content/branding/nonexistent_file.png"); mAsserter.is(stream, null, "JarReader returned null for non-existent file in valid jar"); // Test looking for a file that doesn't exist in the APK. url = "jar:file://" + appPath + "!/" + "BAD" + AppConstants.OMNIJAR_NAME; - stream = GeckoJarReader.getStream("jar:" + url + "!/chrome/chrome/content/branding/favicon32.png"); + stream = GeckoJarReader.getStream(context, "jar:" + url + "!/chrome/chrome/content/branding/favicon32.png"); mAsserter.is(stream, null, "JarReader returned null for valid file in invalid jar file"); // Test looking for an jar with an invalid url. url = "jar:file://" + appPath + "!" + "!/" + AppConstants.OMNIJAR_NAME; - stream = GeckoJarReader.getStream("jar:" + url + "!/chrome/chrome/content/branding/nonexistent_file.png"); + stream = GeckoJarReader.getStream(context, "jar:" + url + "!/chrome/chrome/content/branding/nonexistent_file.png"); mAsserter.is(stream, null, "JarReader returned null for bad jar url"); // Test looking for a file that doesn't exist on disk. url = "jar:file://" + appPath + "BAD" + "!/" + AppConstants.OMNIJAR_NAME; - stream = GeckoJarReader.getStream("jar:" + url + "!/chrome/chrome/content/branding/favicon32.png"); + stream = GeckoJarReader.getStream(context, "jar:" + url + "!/chrome/chrome/content/branding/favicon32.png"); mAsserter.is(stream, null, "JarReader returned null for a non-existent APK"); // This test completes very quickly. If it completes too soon, the From 6e11cec452c50e6b47c19ae5e2c14e3223d73851 Mon Sep 17 00:00:00 2001 From: Jim Chen Date: Wed, 10 Jun 2015 00:25:01 -0400 Subject: [PATCH 86/95] Bug 1166309 - Set interface and don't load mozglue in GeckoView; r=snorp --- mobile/android/base/GeckoView.java | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/mobile/android/base/GeckoView.java b/mobile/android/base/GeckoView.java index 9ce45f0bf6ef..33d7c0dcf3ad 100644 --- a/mobile/android/base/GeckoView.java +++ b/mobile/android/base/GeckoView.java @@ -119,6 +119,14 @@ public class GeckoView extends LayerView } private void init(Context context, String url, boolean doInit) { + + // Set the GeckoInterface if the context is an activity and the GeckoInterface + // has not already been set + if (context instanceof Activity && getGeckoInterface() == null) { + setGeckoInterface(new BaseGeckoInterface(context)); + GeckoAppShell.setContextGetter(this); + } + // Perform common initialization for Fennec/GeckoView. GeckoAppShell.setLayerView(this); @@ -141,19 +149,11 @@ public class GeckoView extends LayerView } catch (NoClassDefFoundError ex) {} if (!isGeckoActivity) { - // Set the GeckoInterface if the context is an activity and the GeckoInterface - // has not already been set - if (context instanceof Activity && getGeckoInterface() == null) { - setGeckoInterface(new BaseGeckoInterface(context)); - } - Clipboard.init(context); HardwareUtils.init(context); // If you want to use GeckoNetworkManager, start it. - GeckoLoader.loadMozGlue(context); - final GeckoProfile profile = GeckoProfile.get(context); } @@ -164,7 +164,6 @@ public class GeckoView extends LayerView GeckoThread.ensureInit(null, null, null); } - GeckoAppShell.setContextGetter(this); if (context instanceof Activity) { Tabs tabs = Tabs.getInstance(); tabs.attachToContext(context); From 74d83f7f6be554c4caf11ce512139ecc740871e1 Mon Sep 17 00:00:00 2001 From: Jim Chen Date: Wed, 10 Jun 2015 00:25:02 -0400 Subject: [PATCH 87/95] Bug 1166452 - Add DelayedInit module for Fennec startup; r=mfinkle --- mobile/android/modules/DelayedInit.jsm | 175 +++++++++++++++++++++++++ mobile/android/modules/moz.build | 1 + 2 files changed, 176 insertions(+) create mode 100644 mobile/android/modules/DelayedInit.jsm diff --git a/mobile/android/modules/DelayedInit.jsm b/mobile/android/modules/DelayedInit.jsm new file mode 100644 index 000000000000..301f432516e2 --- /dev/null +++ b/mobile/android/modules/DelayedInit.jsm @@ -0,0 +1,175 @@ +/* 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/. */ +"use strict" + +const { classes: Cc, interfaces: Ci, utils: Cu } = Components; + +this.EXPORTED_SYMBOLS = ["DelayedInit"]; + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + +XPCOMUtils.defineLazyServiceGetter(this, "MessageLoop", + "@mozilla.org/message-loop;1", + "nsIMessageLoop"); + +/** + * Use DelayedInit to schedule initializers to run some time after startup. + * Initializers are added to a list of pending inits. Whenever the main thread + * message loop is idle, DelayedInit will start running initializers from the + * pending list. To prevent monopolizing the message loop, every idling period + * has a maximum duration. When that's reached, we give up the message loop and + * wait for the next idle. + * + * DelayedInit is compatible with lazy getters like those from XPCOMUtils. When + * the lazy getter is first accessed, its corresponding initializer is run + * automatically if it hasn't been run already. Each initializer also has a + * maximum wait parameter that specifies a mandatory timeout; when the timeout + * is reached, the initializer is forced to run. + * + * DelayedInit.schedule(() => Foo.init(), null, null, 5000); + * + * In the example above, Foo.init will run automatically when the message loop + * becomes idle, or when 5000ms has elapsed, whichever comes first. + * + * DelayedInit.schedule(() => Foo.init(), this, "Foo", 5000); + * + * In the example above, Foo.init will run automatically when the message loop + * becomes idle, when |this.Foo| is accessed, or when 5000ms has elapsed, + * whichever comes first. + * + * It may be simpler to have a wrapper for DelayedInit.schedule. For example, + * + * function InitLater(fn, obj, name) { + * return DelayedInit.schedule(fn, obj, name, 5000); // constant max wait + * } + * InitLater(() => Foo.init()); + * InitLater(() => Bar.init(), this, "Bar"); + */ +let DelayedInit = { + schedule: function (fn, object, name, maxWait) { + return Impl.scheduleInit(fn, object, name, maxWait); + }, +}; + +// Maximum duration for each idling period. Pending inits are run until this +// duration is exceeded; then we wait for next idling period. +const MAX_IDLE_RUN_MS = 50; + +let Impl = { + pendingInits: [], + + onIdle: function () { + let startTime = Cu.now(); + let time = startTime; + let nextDue; + + // Go through all the pending inits. Even if we don't run them, + // we still need to find out when the next timeout should be. + for (let init of this.pendingInits) { + if (init.complete) { + continue; + } + + if (time - startTime < MAX_IDLE_RUN_MS) { + init.maybeInit(); + time = Cu.now(); + } else { + // We ran out of time; find when the next closest due time is. + nextDue = nextDue ? Math.min(nextDue, init.due) : init.due; + } + } + + // Get rid of completed ones. + this.pendingInits = this.pendingInits.filter((init) => !init.complete); + + if (nextDue !== undefined) { + // Schedule the next idle, if we still have pending inits. + MessageLoop.postIdleTask(() => this.onIdle(), + Math.max(0, nextDue - time)); + } + }, + + addPendingInit: function (fn, wait) { + let init = { + fn: fn, + due: Cu.now() + wait, + complete: false, + maybeInit: function () { + if (this.complete) { + return false; + } + this.complete = true; + this.fn.call(); + this.fn = null; + return true; + }, + }; + + if (!this.pendingInits.length) { + // Schedule for the first idle. + MessageLoop.postIdleTask(() => this.onIdle(), wait); + } + this.pendingInits.push(init); + return init; + }, + + scheduleInit: function (fn, object, name, wait) { + let init = this.addPendingInit(fn, wait); + + if (!object || !name) { + // No lazy getter needed. + return; + } + + // Get any existing information about the property. + let prop = Object.getOwnPropertyDescriptor(object, name) || + { configurable: true, enumerable: true, writable: true }; + + if (!prop.configurable) { + // Object.defineProperty won't work, so just perform init here. + init.maybeInit(); + return; + } + + // Define proxy getter/setter that will call first initializer first, + // before delegating the get/set to the original target. + Object.defineProperty(object, name, { + get: function proxy_getter() { + init.maybeInit(); + + // If the initializer actually ran, it may have replaced our proxy + // property with a real one, so we need to reload he property. + let newProp = Object.getOwnPropertyDescriptor(object, name); + if (newProp.get !== proxy_getter) { + // Set prop if newProp doesn't refer to our proxy property. + prop = newProp; + } else { + // Otherwise, reset to the original property. + Object.defineProperty(object, name, prop); + } + + if (prop.get) { + return prop.get.call(object); + } + return prop.value; + }, + set: function (newVal) { + init.maybeInit(); + + // Since our initializer already ran, + // we can get rid of our proxy property. + if (prop.get || prop.set) { + Object.defineProperty(object, name, prop); + return prop.set.call(object); + } + + prop.value = newVal; + Object.defineProperty(object, name, prop); + return newVal; + }, + configurable: true, + enumerable: true, + }); + } +}; diff --git a/mobile/android/modules/moz.build b/mobile/android/modules/moz.build index d46fd556a59f..ef9c0bb3387e 100644 --- a/mobile/android/modules/moz.build +++ b/mobile/android/modules/moz.build @@ -9,6 +9,7 @@ EXTRA_JS_MODULES += [ 'AndroidLog.jsm', 'ContactService.jsm', 'dbg-browser-actors.js', + 'DelayedInit.jsm', 'DownloadNotifications.jsm', 'HelperApps.jsm', 'Home.jsm', From cffd5d53703d438829dea2a91fe8a65e2a5cf24b Mon Sep 17 00:00:00 2001 From: Jim Chen Date: Wed, 10 Jun 2015 00:25:02 -0400 Subject: [PATCH 88/95] Bug 1166452 - Convert delayed startup to using DelayedInit; r=mfinkle --- mobile/android/chrome/content/browser.js | 70 ++++++++++++------------ 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index 156cf2231e13..908f378ad1c6 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -13,6 +13,7 @@ Cu.import("resource://gre/modules/AppConstants.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/AddonManager.jsm"); +Cu.import("resource://gre/modules/DelayedInit.jsm"); Cu.import('resource://gre/modules/Payment.jsm'); Cu.import("resource://gre/modules/NotificationDB.jsm"); Cu.import("resource://gre/modules/SpatialNavigation.jsm"); @@ -375,41 +376,6 @@ var BrowserApp = { dump("zerdatime " + Date.now() + " - browser chrome startup finished."); this.deck = document.getElementById("browsers"); - this.deck.addEventListener("DOMContentLoaded", function BrowserApp_delayedStartup() { - try { - BrowserApp.deck.removeEventListener("DOMContentLoaded", BrowserApp_delayedStartup, false); - Services.obs.notifyObservers(window, "browser-delayed-startup-finished", ""); - Messaging.sendRequest({ type: "Gecko:DelayedStartup" }); - - // Queue up some other performance-impacting initializations - Services.tm.mainThread.dispatch(function() { - // Spin up some services which impact performance. - Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager); - Services.search.init(); - - // Spin up some features which impact performance. - CastingApps.init(); - DownloadNotifications.init(); - - if (AppConstants.MOZ_SAFE_BROWSING) { - // Bug 778855 - Perf regression if we do this here. To be addressed in bug 779008. - SafeBrowsing.init(); - }; - - // Delay this a minute because there's no rush - setTimeout(() => { - BrowserApp.gmpInstallManager = new GMPInstallManager(); - BrowserApp.gmpInstallManager.simpleCheckAndInstall().then(null, () => {}); - }, 1000 * 60); - }, Ci.nsIThread.DISPATCH_NORMAL); - - if (AppConstants.NIGHTLY_BUILD) { - WebcompatReporter.init(); - Telemetry.addData("TRACKING_PROTECTION_ENABLED", - Services.prefs.getBoolPref("privacy.trackingprotection.enabled")); - } - } catch(ex) { console.log(ex); } - }, false); BrowserEventHandler.init(); ViewportHandler.init(); @@ -553,6 +519,40 @@ var BrowserApp = { // Notify Java that Gecko has loaded. Messaging.sendRequest({ type: "Gecko:Ready" }); + + this.deck.addEventListener("DOMContentLoaded", function BrowserApp_delayedStartup() { + BrowserApp.deck.removeEventListener("DOMContentLoaded", BrowserApp_delayedStartup, false); + + function InitLater(fn, object, name) { + return DelayedInit.schedule(fn, object, name, 15000 /* 15s max wait */); + } + + InitLater(() => Services.obs.notifyObservers(window, "browser-delayed-startup-finished", "")); + InitLater(() => Messaging.sendRequest({ type: "Gecko:DelayedStartup" })); + + if (AppConstants.NIGHTLY_BUILD) { + InitLater(() => Telemetry.addData("TRACKING_PROTECTION_ENABLED", + Services.prefs.getBoolPref("privacy.trackingprotection.enabled"))); + InitLater(() => WebcompatReporter.init()); + } + + InitLater(() => CastingApps.init(), window, "CastingApps"); + InitLater(() => Services.search.init(), Services, "search"); + InitLater(() => DownloadNotifications.init(), window, "DownloadNotifications"); + + if (AppConstants.MOZ_SAFE_BROWSING) { + // Bug 778855 - Perf regression if we do this here. To be addressed in bug 779008. + InitLater(() => SafeBrowsing.init(), window, "SafeBrowsing"); + } + + InitLater(() => Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager)); + + InitLater(() => { + BrowserApp.gmpInstallManager = new GMPInstallManager(); + BrowserApp.gmpInstallManager.simpleCheckAndInstall().then(null, () => {}); + }, BrowserApp, "gmpInstallManager"); + + }, false); }, get _startupStatus() { From e9debda7c4255e2116270c7cfe0559e89d21d435 Mon Sep 17 00:00:00 2001 From: JW Wang Date: Wed, 10 Jun 2015 12:49:41 +0800 Subject: [PATCH 89/95] Bug 1172392 - Align update of audio end time of decoded stream with that of AudioSink. r=roc. --- dom/media/MediaDecoderStateMachine.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/dom/media/MediaDecoderStateMachine.cpp b/dom/media/MediaDecoderStateMachine.cpp index 9cd7d1f4d801..de3fee733c3b 100644 --- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -500,6 +500,12 @@ void MediaDecoderStateMachine::SendStreamData() endPosition = std::max(endPosition, mediaStream->TicksToTimeRoundDown(mInfo.mAudio.mRate, stream->mAudioFramesWritten)); + + CheckedInt64 playedUsecs = mStreamStartTime + + FramesToUsecs(stream->mAudioFramesWritten, mInfo.mAudio.mRate); + if (playedUsecs.isValid()) { + OnAudioEndTimeUpdate(playedUsecs.value()); + } } if (mInfo.HasVideo()) { @@ -588,7 +594,6 @@ void MediaDecoderStateMachine::SendStreamData() // Therefore we only discard those behind the stream clock to throttle // the decoding speed. if (a && a->mTime <= clockTime) { - OnAudioEndTimeUpdate(std::max(mAudioEndTime, a->GetEndTime())); nsRefPtr releaseMe = AudioQueue().PopFront(); continue; } @@ -3477,6 +3482,9 @@ void MediaDecoderStateMachine::DispatchAudioCaptured() // the 1st frame. But this is OK since we will update mStreamStartTime // again in SetStartTime(). self->mStreamStartTime = self->GetMediaTime(); + // Reset mAudioEndTime which will be updated as we send audio data to + // stream. Otherwise it will remain -1 if we don't have audio. + self->mAudioEndTime = -1; self->mAudioCaptured = true; self->ScheduleStateMachine(); } From 197c33cfb2d4c4a0a20cb9edeaac968e3faa555b Mon Sep 17 00:00:00 2001 From: Francois Marier Date: Wed, 10 Jun 2015 17:35:18 +1200 Subject: [PATCH 90/95] Bug 1165816 - Cancel remote application reputation requests after a certain timeout. r=gcp --- browser/app/profile/firefox.js | 1 + .../downloads/ApplicationReputation.cpp | 42 +++++++++++++++---- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index 7291b13592e6..5f957ff66bd3 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -975,6 +975,7 @@ pref("browser.safebrowsing.enabled", true); pref("browser.safebrowsing.malware.enabled", true); pref("browser.safebrowsing.downloads.enabled", true); pref("browser.safebrowsing.downloads.remote.enabled", true); +pref("browser.safebrowsing.downloads.remote.timeout_ms", 10000); pref("browser.safebrowsing.debug", false); pref("browser.safebrowsing.updateURL", "https://safebrowsing.google.com/safebrowsing/downloads?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2&key=%GOOGLE_API_KEY%"); diff --git a/toolkit/components/downloads/ApplicationReputation.cpp b/toolkit/components/downloads/ApplicationReputation.cpp index bb5fee56839c..ae1d1dbf1c8c 100644 --- a/toolkit/components/downloads/ApplicationReputation.cpp +++ b/toolkit/components/downloads/ApplicationReputation.cpp @@ -18,6 +18,7 @@ #include "nsIScriptSecurityManager.h" #include "nsIStreamListener.h" #include "nsIStringStream.h" +#include "nsITimer.h" #include "nsIUploadChannel2.h" #include "nsIURI.h" #include "nsIUrlClassifierDBService.h" @@ -60,6 +61,7 @@ using safe_browsing::ClientDownloadRequest_SignatureInfo; #define PREF_SB_MALWARE_ENABLED "browser.safebrowsing.malware.enabled" #define PREF_SB_DOWNLOADS_ENABLED "browser.safebrowsing.downloads.enabled" #define PREF_SB_DOWNLOADS_REMOTE_ENABLED "browser.safebrowsing.downloads.remote.enabled" +#define PREF_SB_DOWNLOADS_REMOTE_TIMEOUT "browser.safebrowsing.downloads.remote.timeout_ms" #define PREF_GENERAL_LOCALE "general.useragent.locale" #define PREF_DOWNLOAD_BLOCK_TABLE "urlclassifier.downloadBlockTable" #define PREF_DOWNLOAD_ALLOW_TABLE "urlclassifier.downloadAllowTable" @@ -75,12 +77,14 @@ class PendingDBLookup; // nsIApplicationReputationQuery and an nsIApplicationReputationCallback. Once // created by ApplicationReputationService, it is guaranteed to call mCallback. // This class is private to ApplicationReputationService. -class PendingLookup final : public nsIStreamListener +class PendingLookup final : public nsIStreamListener, + public nsITimerCallback { public: NS_DECL_ISUPPORTS NS_DECL_NSIREQUESTOBSERVER NS_DECL_NSISTREAMLISTENER + NS_DECL_NSITIMERCALLBACK // Constructor and destructor. PendingLookup(nsIApplicationReputationQuery* aQuery, @@ -125,6 +129,12 @@ private: // When we started this query TimeStamp mStartTime; + // The channel used to talk to the remote lookup server + nsCOMPtr mChannel; + + // Timer to abort this lookup if it takes too long + nsCOMPtr mTimeoutTimer; + // A protocol buffer for storing things we need in the remote request. We // store the resource chain (redirect information) as well as signature // information extracted using the Windows Authenticode API, if the binary is @@ -741,6 +751,11 @@ PendingLookup::DoLookupInternal() nsresult PendingLookup::OnComplete(bool shouldBlock, nsresult rv) { + if (mTimeoutTimer) { + mTimeoutTimer->Cancel(); + mTimeoutTimer = nullptr; + } + Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_SHOULD_BLOCK, shouldBlock); double t = (TimeStamp::Now() - mStartTime).ToMilliseconds(); @@ -929,7 +944,6 @@ PendingLookup::SendRemoteQueryInternal() NS_ENSURE_SUCCESS(rv, rv); // Set up the channel to transmit the request to the service. - nsCOMPtr channel; nsCOMPtr ios = do_GetService(NS_IOSERVICE_CONTRACTID, &rv); rv = ios->NewChannel2(serviceUrl, nullptr, @@ -939,14 +953,14 @@ PendingLookup::SendRemoteQueryInternal() nullptr, // aTriggeringPrincipal nsILoadInfo::SEC_NORMAL, nsIContentPolicy::TYPE_OTHER, - getter_AddRefs(channel)); + getter_AddRefs(mChannel)); NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr httpChannel(do_QueryInterface(channel, &rv)); + nsCOMPtr httpChannel(do_QueryInterface(mChannel, &rv)); NS_ENSURE_SUCCESS(rv, rv); // Upload the protobuf to the application reputation service. - nsCOMPtr uploadChannel = do_QueryInterface(channel, &rv); + nsCOMPtr uploadChannel = do_QueryInterface(mChannel, &rv); NS_ENSURE_SUCCESS(rv, rv); rv = uploadChannel->ExplicitSetUploadStream(sstream, @@ -958,15 +972,29 @@ PendingLookup::SendRemoteQueryInternal() // sent with this request. See bug 897516. nsCOMPtr loadContext = new mozilla::LoadContext(NECKO_SAFEBROWSING_APP_ID); - rv = channel->SetNotificationCallbacks(loadContext); + rv = mChannel->SetNotificationCallbacks(loadContext); NS_ENSURE_SUCCESS(rv, rv); - rv = channel->AsyncOpen(this, nullptr); + uint32_t timeoutMs = Preferences::GetUint(PREF_SB_DOWNLOADS_REMOTE_TIMEOUT, 10000); + mTimeoutTimer = do_CreateInstance(NS_TIMER_CONTRACTID); + mTimeoutTimer->InitWithCallback(this, timeoutMs, nsITimer::TYPE_ONE_SHOT); + + rv = mChannel->AsyncOpen(this, nullptr); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; } +NS_IMETHODIMP +PendingLookup::Notify(nsITimer* aTimer) +{ + LOG(("Remote lookup timed out [this = %p]", this)); + MOZ_ASSERT(aTimer == mTimeoutTimer); + mChannel->Cancel(NS_ERROR_NET_TIMEOUT); + mTimeoutTimer->Cancel(); + return NS_OK; +} + //////////////////////////////////////////////////////////////////////////////// //// nsIStreamListener static NS_METHOD From c6652e94747896da728913a671b2e735bac19b5d Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Wed, 10 Jun 2015 07:23:45 +0100 Subject: [PATCH 91/95] Bug 1165693 - patch 2 - Cache family-name lookups in gfxFcPlatformFontList::FindFamily, to avoid repeating expensive calls to FcConfigSubstitute. r=jdaggett --- gfx/thebes/gfxFcPlatformFontList.cpp | 20 +++++++++++++++++--- gfx/thebes/gfxFcPlatformFontList.h | 3 +++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/gfx/thebes/gfxFcPlatformFontList.cpp b/gfx/thebes/gfxFcPlatformFontList.cpp index 4df7243862ba..7d8af32614d9 100644 --- a/gfx/thebes/gfxFcPlatformFontList.cpp +++ b/gfx/thebes/gfxFcPlatformFontList.cpp @@ -910,7 +910,10 @@ gfxFontconfigFont::GetGlyphRenderingOptions(const TextRunDrawParams* aRunParams) #endif gfxFcPlatformFontList::gfxFcPlatformFontList() - : mLocalNames(64), mGenericMappings(32), mLastConfig(nullptr) + : mLocalNames(64) + , mGenericMappings(32) + , mFcSubstituteCache(64) + , mLastConfig(nullptr) { // if the rescan interval is set, start the timer int rescanInterval = FcConfigGetRescanInterval(nullptr); @@ -1036,6 +1039,8 @@ gfxFcPlatformFontList::InitFontList() mLocalNames.Clear(); mGenericMappings.Clear(); + mFcSubstituteCache.Clear(); + sSentinelFirstFamily = nullptr; // iterate over available fonts FcFontSet* systemFonts = FcConfigGetFonts(nullptr, FcSetSystem); @@ -1048,7 +1053,6 @@ gfxFcPlatformFontList::InitFontList() #endif mOtherFamilyNamesInitialized = true; - sSentinelFirstFamily = nullptr; return NS_OK; } @@ -1240,6 +1244,14 @@ gfxFcPlatformFontList::FindFamily(const nsAString& aFamily, // In this case fontconfig is including Tex Gyre Heros and // Nimbus Sans L as alternatives for Helvetica. + // Because the FcConfigSubstitute call is quite expensive, we cache the + // actual font family found via this process. So check the cache first: + NS_ConvertUTF16toUTF8 familyToFind(familyName); + gfxFontFamily* cached = mFcSubstituteCache.GetWeak(familyToFind); + if (cached) { + return cached; + } + const FcChar8* kSentinelName = ToFcChar8Ptr("-moz-sentinel"); if (!sSentinelFirstFamily) { nsAutoRef sentinelSubst(FcPatternCreate()); @@ -1250,7 +1262,6 @@ gfxFcPlatformFontList::FindFamily(const nsAString& aFamily, // substitutions for font, -moz-sentinel pattern nsAutoRef fontWithSentinel(FcPatternCreate()); - NS_ConvertUTF16toUTF8 familyToFind(familyName); FcPatternAddString(fontWithSentinel, FC_FAMILY, ToFcChar8Ptr(familyToFind.get())); FcPatternAddString(fontWithSentinel, FC_FAMILY, kSentinelName); FcConfigSubstitute(nullptr, fontWithSentinel, FcMatchPattern); @@ -1269,6 +1280,9 @@ gfxFcPlatformFontList::FindFamily(const nsAString& aFamily, } gfxFontFamily* foundFamily = gfxPlatformFontList::FindFamily(subst); if (foundFamily) { + // We've figured out what family the given name maps to, after any + // fontconfig subsitutions. Cache it to speed up future lookups. + mFcSubstituteCache.Put(familyToFind, foundFamily); return foundFamily; } } diff --git a/gfx/thebes/gfxFcPlatformFontList.h b/gfx/thebes/gfxFcPlatformFontList.h index b700b466ef19..a4cba6bc89f5 100644 --- a/gfx/thebes/gfxFcPlatformFontList.h +++ b/gfx/thebes/gfxFcPlatformFontList.h @@ -256,6 +256,9 @@ protected: // caching generic/lang ==> font family nsRefPtrHashtable mGenericMappings; + // caching family lookups as found by FindFamily after resolving substitutions + nsRefPtrHashtable mFcSubstituteCache; + nsCOMPtr mCheckFontUpdatesTimer; nsCountedRef mLastConfig; From 7f6957db606c18924949e48cccd802a162007730 Mon Sep 17 00:00:00 2001 From: Dan Glastonbury Date: Tue, 9 Jun 2015 15:29:21 +1000 Subject: [PATCH 92/95] Bug 1170452 - Remove constants for texture swizzle and prim restart. r=smaug --- dom/webidl/WebGL2RenderingContext.webidl | 5 ----- 1 file changed, 5 deletions(-) diff --git a/dom/webidl/WebGL2RenderingContext.webidl b/dom/webidl/WebGL2RenderingContext.webidl index 8d4b7e16487d..b8bba687887b 100644 --- a/dom/webidl/WebGL2RenderingContext.webidl +++ b/dom/webidl/WebGL2RenderingContext.webidl @@ -236,7 +236,6 @@ interface WebGL2RenderingContext : WebGLRenderingContext const GLenum RGB8_SNORM = 0x8F96; const GLenum RGBA8_SNORM = 0x8F97; const GLenum SIGNED_NORMALIZED = 0x8F9C; - const GLenum PRIMITIVE_RESTART_FIXED_INDEX = 0x8D69; const GLenum COPY_READ_BUFFER = 0x8F36; const GLenum COPY_WRITE_BUFFER = 0x8F37; const GLenum COPY_READ_BUFFER_BINDING = 0x8F36; /* Same as COPY_READ_BUFFER */ @@ -289,10 +288,6 @@ interface WebGL2RenderingContext : WebGLRenderingContext const GLenum ANY_SAMPLES_PASSED_CONSERVATIVE = 0x8D6A; const GLenum SAMPLER_BINDING = 0x8919; const GLenum RGB10_A2UI = 0x906F; - const GLenum TEXTURE_SWIZZLE_R = 0x8E42; - const GLenum TEXTURE_SWIZZLE_G = 0x8E43; - const GLenum TEXTURE_SWIZZLE_B = 0x8E44; - const GLenum TEXTURE_SWIZZLE_A = 0x8E45; const GLenum GREEN = 0x1904; const GLenum BLUE = 0x1905; const GLenum INT_2_10_10_10_REV = 0x8D9F; From 917fe2297ed81484fa5ecf1575b7086054d76f32 Mon Sep 17 00:00:00 2001 From: Lars T Hansen Date: Tue, 9 Jun 2015 13:15:34 +0200 Subject: [PATCH 93/95] Bug 1172638 - guard a test case. r=bbouvier --- js/src/jit-test/tests/asm.js/testBug1164391.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/js/src/jit-test/tests/asm.js/testBug1164391.js b/js/src/jit-test/tests/asm.js/testBug1164391.js index 9aa04b2da70c..6acdd88b2c0f 100644 --- a/js/src/jit-test/tests/asm.js/testBug1164391.js +++ b/js/src/jit-test/tests/asm.js/testBug1164391.js @@ -1,3 +1,6 @@ +if (!this.SharedArrayBuffer) + quit(0); + function m(stdlib, ffi, heap) { "use asm"; var HEAP32 = new stdlib.SharedInt32Array(heap); From d1e564952fbbe88c0d1cda33138e83a5765fea8d Mon Sep 17 00:00:00 2001 From: Hannes Verschore Date: Tue, 2 Jun 2015 12:25:45 +0200 Subject: [PATCH 94/95] Bug 1139376: Ionmonkey - Make removing of guards aware of phis, r=nbp --- js/src/jit-test/tests/ion/bug1139376.js | 13 ++++++++ js/src/jit/RangeAnalysis.cpp | 41 ++++++++++++++++--------- js/src/jit/ValueNumbering.cpp | 2 +- 3 files changed, 40 insertions(+), 16 deletions(-) create mode 100644 js/src/jit-test/tests/ion/bug1139376.js diff --git a/js/src/jit-test/tests/ion/bug1139376.js b/js/src/jit-test/tests/ion/bug1139376.js new file mode 100644 index 000000000000..28f0c3819b90 --- /dev/null +++ b/js/src/jit-test/tests/ion/bug1139376.js @@ -0,0 +1,13 @@ +// |jit-test| error:ReferenceError + +(function() { + var $10=0; + while (1) { + switch (stack.label & 2) { + case 1: + return $8|0; + case 49: + if ($10) {} + } + } +})()() diff --git a/js/src/jit/RangeAnalysis.cpp b/js/src/jit/RangeAnalysis.cpp index e07e1395e9fb..75d3f924c594 100644 --- a/js/src/jit/RangeAnalysis.cpp +++ b/js/src/jit/RangeAnalysis.cpp @@ -3335,8 +3335,8 @@ RangeAnalysis::prepareForUCE(bool* shouldRemoveDeadCode) return tryRemovingGuards(); } -bool RangeAnalysis::tryRemovingGuards() { - +bool RangeAnalysis::tryRemovingGuards() +{ MDefinitionVector guards(alloc()); for (ReversePostorderIterator block = graph_.rpoBegin(); block != graph_.rpoEnd(); block++) { @@ -3344,6 +3344,7 @@ bool RangeAnalysis::tryRemovingGuards() { if (!iter->isGuardRangeBailouts()) continue; + iter->setInWorklist(); if (!guards.append(*iter)) return false; } @@ -3364,20 +3365,22 @@ bool RangeAnalysis::tryRemovingGuards() { guard->setGuardRangeBailouts(); #endif - if (!guard->range()) - continue; + if (!guard->isPhi()) { + if (!guard->range()) + continue; - // Filter the range of the instruction based on its MIRType. - Range typeFilteredRange(guard); + // Filter the range of the instruction based on its MIRType. + Range typeFilteredRange(guard); - // If the output range is updated by adding the inner range, - // then the MIRType act as an effectful filter. As we do not know if - // this filtered Range might change or not the result of the - // previous comparison, we have to keep this instruction as a guard - // because it has to bailout in order to restrict the Range to its - // MIRType. - if (typeFilteredRange.update(guard->range())) - continue; + // If the output range is updated by adding the inner range, + // then the MIRType act as an effectful filter. As we do not know if + // this filtered Range might change or not the result of the + // previous comparison, we have to keep this instruction as a guard + // because it has to bailout in order to restrict the Range to its + // MIRType. + if (typeFilteredRange.update(guard->range())) + continue; + } guard->setNotGuardRangeBailouts(); @@ -3386,19 +3389,27 @@ bool RangeAnalysis::tryRemovingGuards() { MDefinition* operand = guard->getOperand(op); // Already marked. - if (operand->isGuardRangeBailouts()) + if (operand->isInWorklist()) continue; + MOZ_ASSERT(!operand->isGuardRangeBailouts()); + // No need to mark as a guard, since it is has already an even more // restrictive flag set. if (!DeadIfUnused(operand)) continue; + operand->setInWorklist(); operand->setGuardRangeBailouts(); if (!guards.append(operand)) return false; } } + for (size_t i = 0; i < guards.length(); i++) { + MDefinition* guard = guards[i]; + guard->setNotInWorklist(); + } + return true; } diff --git a/js/src/jit/ValueNumbering.cpp b/js/src/jit/ValueNumbering.cpp index bad38b333589..401de19613db 100644 --- a/js/src/jit/ValueNumbering.cpp +++ b/js/src/jit/ValueNumbering.cpp @@ -682,7 +682,7 @@ ValueNumberer::loopHasOptimizablePhi(MBasicBlock* header) const // values from backedges. for (MPhiIterator iter(header->phisBegin()), end(header->phisEnd()); iter != end; ++iter) { MPhi* phi = *iter; - MOZ_ASSERT(phi->hasUses(), "Missed an unused phi"); + MOZ_ASSERT_IF(!phi->hasUses(), !DeadIfUnused(phi)); if (phi->operandIfRedundant() || hasLeader(phi, header)) return true; // Phi can be simplified. From 978b9197c2391536cf64c5a54f4b6f72d1ff63a2 Mon Sep 17 00:00:00 2001 From: Georg Fritzsche Date: Wed, 10 Jun 2015 12:31:44 +0200 Subject: [PATCH 95/95] Bug 1173310 - TelemetrySend.jsm is not importing Timer.jsm. r=dexter,a=tomcat --- toolkit/components/telemetry/TelemetrySend.jsm | 1 + 1 file changed, 1 insertion(+) diff --git a/toolkit/components/telemetry/TelemetrySend.jsm b/toolkit/components/telemetry/TelemetrySend.jsm index 17d324b3d261..706799dee3a3 100644 --- a/toolkit/components/telemetry/TelemetrySend.jsm +++ b/toolkit/components/telemetry/TelemetrySend.jsm @@ -24,6 +24,7 @@ Cu.import("resource://gre/modules/Preferences.jsm"); Cu.import("resource://gre/modules/PromiseUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm", this); Cu.import("resource://gre/modules/TelemetryUtils.jsm", this); +Cu.import("resource://gre/modules/Timer.jsm", this); XPCOMUtils.defineLazyModuleGetter(this, "AsyncShutdown", "resource://gre/modules/AsyncShutdown.jsm");