From 2cbcc06b8b0bf706fb4f3e71282bcbcf54b30546 Mon Sep 17 00:00:00 2001 From: Tooru Fujisawa Date: Wed, 8 Mar 2017 20:36:51 +0900 Subject: [PATCH 01/57] Bug 1345162 - Fix identifier handling in Parser::standaloneFunction to follow new token kinds. r=till --- js/src/frontend/Parser.cpp | 2 +- .../tests/parser/standalone-function-name.js | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 js/src/jit-test/tests/parser/standalone-function-name.js diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index e14ebaf84225..9a24f52acc0b 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -2495,7 +2495,7 @@ Parser::standaloneFunction(HandleFunction fun, } // Skip function name, if present. - if (tt == TOK_NAME || tt == TOK_YIELD) { + if (TokenKindIsPossibleIdentifierName(tt)) { MOZ_ASSERT(tokenStream.currentName() == fun->explicitName()); } else { MOZ_ASSERT(fun->explicitName() == nullptr); diff --git a/js/src/jit-test/tests/parser/standalone-function-name.js b/js/src/jit-test/tests/parser/standalone-function-name.js new file mode 100644 index 000000000000..e676d7cb9c54 --- /dev/null +++ b/js/src/jit-test/tests/parser/standalone-function-name.js @@ -0,0 +1,22 @@ +function test(name) { + eval(` +function ${name}(stdlib, foreign, heap) { + "use asm"; + var ffi = foreign.t; + return {}; +} +${name}(15, 10); +`); +} + +test("as"); +test("async"); +test("await"); +test("each"); +test("from"); +test("get"); +test("let"); +test("of"); +test("set"); +test("static"); +test("target"); From dccaffb21300fc150a4b8a03bd97ed88b21074f0 Mon Sep 17 00:00:00 2001 From: "Nicolas B. Pierron" Date: Wed, 8 Mar 2017 13:33:07 +0000 Subject: [PATCH 02/57] Bug 1325073 - Rename mozilla::MakeGenericErrorResult to mozilla::Err. r=Waldo --- js/src/jit/Ion.h | 13 +------------ js/src/jscntxt.cpp | 4 ++-- mfbt/Result.h | 6 +++--- mfbt/tests/TestResult.cpp | 8 ++++---- 4 files changed, 10 insertions(+), 21 deletions(-) diff --git a/js/src/jit/Ion.h b/js/src/jit/Ion.h index 2ea0fbf20d47..03e66fa24f7a 100644 --- a/js/src/jit/Ion.h +++ b/js/src/jit/Ion.h @@ -8,7 +8,6 @@ #define jit_Ion_h #include "mozilla/MemoryReporting.h" -#include "mozilla/Move.h" #include "mozilla/Result.h" #include "jscntxt.h" @@ -41,19 +40,9 @@ enum class AbortReason : uint8_t { template using AbortReasonOr = mozilla::Result; +using mozilla::Err; using mozilla::Ok; -// This is the equivalent of the following, except that these are functions and -// not types, which makes this syntax invalid: -// using Err = mozilla::MakeGenericErrorResult; -template -inline mozilla::GenericErrorResult -Err(E&& aErrorValue) -{ - return mozilla::MakeGenericErrorResult(mozilla::Forward(aErrorValue)); -} - - static_assert(sizeof(AbortReasonOr) <= sizeof(uintptr_t), "Unexpected size of AbortReasonOr"); static_assert(sizeof(AbortReasonOr) <= sizeof(uintptr_t), diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index 7ae13a3e5a73..5270c17eecb9 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -1118,7 +1118,7 @@ JSContext::alreadyReportedOOM() MOZ_ASSERT(isThrowingOutOfMemory()); } #endif - return mozilla::MakeGenericErrorResult(reportedOOM); + return mozilla::Err(reportedOOM); } mozilla::GenericErrorResult @@ -1128,7 +1128,7 @@ JSContext::alreadyReportedError() if (!helperThread()) MOZ_ASSERT(isExceptionPending()); #endif - return mozilla::MakeGenericErrorResult(reportedError); + return mozilla::Err(reportedError); } JSContext::JSContext(JSRuntime* runtime, const JS::ContextOptions& options) diff --git a/mfbt/Result.h b/mfbt/Result.h index a076e9929632..09c64b7ba5bb 100644 --- a/mfbt/Result.h +++ b/mfbt/Result.h @@ -401,7 +401,7 @@ public: template inline GenericErrorResult -MakeGenericErrorResult(E&& aErrorValue) +Err(E&& aErrorValue) { return GenericErrorResult(aErrorValue); } @@ -418,7 +418,7 @@ MakeGenericErrorResult(E&& aErrorValue) do { \ auto mozTryTempResult_ = (expr); \ if (mozTryTempResult_.isErr()) { \ - return ::mozilla::MakeGenericErrorResult(mozTryTempResult_.unwrapErr()); \ + return ::mozilla::Err(mozTryTempResult_.unwrapErr()); \ } \ } while (0) @@ -433,7 +433,7 @@ MakeGenericErrorResult(E&& aErrorValue) do { \ auto mozTryVarTempResult_ = (expr); \ if (mozTryVarTempResult_.isErr()) { \ - return ::mozilla::MakeGenericErrorResult( \ + return ::mozilla::Err( \ mozTryVarTempResult_.unwrapErr()); \ } \ (target) = mozTryVarTempResult_.unwrap(); \ diff --git a/mfbt/tests/TestResult.cpp b/mfbt/tests/TestResult.cpp index 81746ea6f194..ae8c13bb5569 100644 --- a/mfbt/tests/TestResult.cpp +++ b/mfbt/tests/TestResult.cpp @@ -7,8 +7,8 @@ #include #include "mozilla/Result.h" +using mozilla::Err; using mozilla::GenericErrorResult; -using mozilla::MakeGenericErrorResult; using mozilla::Ok; using mozilla::Result; @@ -52,7 +52,7 @@ static GenericErrorResult Fail() { static Failed failed; - return MakeGenericErrorResult(failed); + return Err(failed); } static Result @@ -131,7 +131,7 @@ BasicTests() MOZ_RELEASE_ASSERT(res.isOk()); MOZ_RELEASE_ASSERT(*res.unwrap() == 123); - res = MakeGenericErrorResult(d); + res = Err(d); MOZ_RELEASE_ASSERT(res.isErr()); MOZ_RELEASE_ASSERT(&res.unwrapErr() == &d); MOZ_RELEASE_ASSERT(res.unwrapErr() == 3.14); @@ -147,7 +147,7 @@ static Result Explode() { static Snafu snafu; - return MakeGenericErrorResult(&snafu); + return Err(&snafu); } static Result From 7cc6c9c9efd7f0e5e9ae98c640fbcd3254680910 Mon Sep 17 00:00:00 2001 From: Honza Bambas Date: Mon, 6 Mar 2017 05:39:00 +0100 Subject: [PATCH 03/57] Bug 1321026 - Have an argument to change the number of parallel tests when running xpcshelltests, r=ted --- testing/xpcshell/mach_commands.py | 4 ++++ testing/xpcshell/runxpcshelltests.py | 12 +++++++----- testing/xpcshell/xpcshellcommandline.py | 5 +++++ 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/testing/xpcshell/mach_commands.py b/testing/xpcshell/mach_commands.py index d821ff46fbd7..e8755228e46f 100644 --- a/testing/xpcshell/mach_commands.py +++ b/testing/xpcshell/mach_commands.py @@ -24,6 +24,7 @@ from mach.decorators import ( Command, ) +from multiprocessing import cpu_count from xpcshellcommandline import parser_desktop, parser_remote here = os.path.abspath(os.path.dirname(__file__)) @@ -259,6 +260,9 @@ class MachCommands(MachCommandBase): {"mach": sys.stdout}, {"verbose": True}) + if not params['threadCount']: + params['threadCount'] = int((cpu_count() * 3) / 2) + if conditions.is_android(self): from mozrunner.devices.android_device import verify_android_device verify_android_device(self) diff --git a/testing/xpcshell/runxpcshelltests.py b/testing/xpcshell/runxpcshelltests.py index df90356d1f65..739c8b9f1074 100755 --- a/testing/xpcshell/runxpcshelltests.py +++ b/testing/xpcshell/runxpcshelltests.py @@ -1092,7 +1092,8 @@ class XPCShellTests(object): testClass=XPCShellTestThread, failureManifest=None, log=None, stream=None, jsDebugger=False, jsDebuggerPort=0, test_tags=None, dump_tests=None, utility_path=None, - rerun_failures=False, failure_manifest=None, jscovdir=None, **otherOptions): + rerun_failures=False, threadCount=NUM_THREADS, + failure_manifest=None, jscovdir=None, **otherOptions): """Run xpcshell tests. |xpcshell|, is the xpcshell executable to use to run the tests. @@ -1193,6 +1194,7 @@ class XPCShellTests(object): self.pluginsPath = pluginsPath self.sequential = sequential self.failure_manifest = failure_manifest + self.threadCount = threadCount or NUM_THREADS self.jscovdir = jscovdir self.testCount = 0 @@ -1347,10 +1349,10 @@ class XPCShellTests(object): if self.sequential: self.log.info("Running tests sequentially.") else: - self.log.info("Using at most %d threads." % NUM_THREADS) + self.log.info("Using at most %d threads." % self.threadCount) - # keep a set of NUM_THREADS running tests and start running the - # tests in the queue at most NUM_THREADS at a time + # keep a set of threadCount running tests and start running the + # tests in the queue at most threadCount at a time running_tests = set() keep_going = True exceptions = [] @@ -1368,7 +1370,7 @@ class XPCShellTests(object): break # if there's room to run more tests, start running them - while keep_going and tests_queue and (len(running_tests) < NUM_THREADS): + while keep_going and tests_queue and (len(running_tests) < self.threadCount): test = tests_queue.popleft() running_tests.add(test) test.start() diff --git a/testing/xpcshell/xpcshellcommandline.py b/testing/xpcshell/xpcshellcommandline.py index d2a8e6bc1306..6618982dfc55 100644 --- a/testing/xpcshell/xpcshellcommandline.py +++ b/testing/xpcshell/xpcshellcommandline.py @@ -112,6 +112,11 @@ def add_common_arguments(parser): action="store", help="Path to a manifest file from which to rerun failures " "(with --rerun-failure) or in which to record failed tests") + parser.add_argument("--threads", + type=int, dest="threadCount", default=0, + help="override the number of jobs (threads) when running tests in parallel, " + "the default is CPU x 1.5 when running via mach and CPU x 4 when running " + "in automation") parser.add_argument("testPaths", nargs="*", default=None, help="Paths of tests to run.") From e335b6c61b3dbd24c664f3d6405ed7db59ff4443 Mon Sep 17 00:00:00 2001 From: Leonardo Couto Date: Mon, 6 Mar 2017 22:31:51 +0100 Subject: [PATCH 04/57] Bug 1341107 - Don't consider cached requests on netmonitor summary. r=Honza --- devtools/client/netmonitor/selectors/requests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devtools/client/netmonitor/selectors/requests.js b/devtools/client/netmonitor/selectors/requests.js index a82adc3004be..84ae69b43185 100644 --- a/devtools/client/netmonitor/selectors/requests.js +++ b/devtools/client/netmonitor/selectors/requests.js @@ -82,7 +82,7 @@ const getDisplayedRequestsSummary = createSelector( totals.contentSize += item.contentSize; } - if (typeof item.transferredSize == "number") { + if (typeof item.transferredSize == "number" && !item.fromCache) { totals.transferredSize += item.transferredSize; } From d813effa4b12a275bf7d5c5ca850ad23dc32ab79 Mon Sep 17 00:00:00 2001 From: Dragana Damjanovic Date: Wed, 8 Mar 2017 04:04:00 +0100 Subject: [PATCH 05/57] Bug 1341572 - Fix multiple HalfOpen socket for a single transaction. r=mcmanus --HG-- extra : amend_source : 210b719d438b20dcaaae5f8bfff1b1715a9fc3e5 --- .../protocol/http/ConnectionDiagnostics.cpp | 10 + netwerk/protocol/http/NullHttpTransaction.cpp | 6 + netwerk/protocol/http/NullHttpTransaction.h | 1 + netwerk/protocol/http/nsHttpConnection.cpp | 21 +- netwerk/protocol/http/nsHttpConnection.h | 8 + netwerk/protocol/http/nsHttpConnectionMgr.cpp | 254 +++++++++++++----- netwerk/protocol/http/nsHttpConnectionMgr.h | 59 +++- 7 files changed, 285 insertions(+), 74 deletions(-) diff --git a/netwerk/protocol/http/ConnectionDiagnostics.cpp b/netwerk/protocol/http/ConnectionDiagnostics.cpp index a8f43256db52..b3d216983318 100644 --- a/netwerk/protocol/http/ConnectionDiagnostics.cpp +++ b/netwerk/protocol/http/ConnectionDiagnostics.cpp @@ -204,5 +204,15 @@ nsHttpTransaction::PrintDiagnostics(nsCString &log) log.AppendPrintf(" restart count = %u\n", mRestartCount); } +void +nsHttpConnectionMgr::PendingTransactionInfo::PrintDiagnostics(nsCString &log) +{ + log.AppendPrintf(" ::: Pending transaction\n"); + mTransaction->PrintDiagnostics(log); + RefPtr halfOpen = do_QueryReferent(mHalfOpen); + log.AppendPrintf(" Waiting for half open sock: %p or connection: %p\n", + halfOpen.get(), mActiveConn.get()); +} + } // namespace net } // namespace mozilla diff --git a/netwerk/protocol/http/NullHttpTransaction.cpp b/netwerk/protocol/http/NullHttpTransaction.cpp index 501407795f3c..ddbdf1c3311f 100644 --- a/netwerk/protocol/http/NullHttpTransaction.cpp +++ b/netwerk/protocol/http/NullHttpTransaction.cpp @@ -141,6 +141,12 @@ NullHttpTransaction::Claim() return true; } +void +NullHttpTransaction::Unclaim() +{ + mClaimed = false; +} + void NullHttpTransaction::SetConnection(nsAHttpConnection *conn) { diff --git a/netwerk/protocol/http/NullHttpTransaction.h b/netwerk/protocol/http/NullHttpTransaction.h index 9fa07947f6d9..934643266314 100644 --- a/netwerk/protocol/http/NullHttpTransaction.h +++ b/netwerk/protocol/http/NullHttpTransaction.h @@ -39,6 +39,7 @@ public: uint32_t caps); MOZ_MUST_USE bool Claim(); + void Unclaim(); // Overload of nsAHttpTransaction methods bool IsNullTransaction() override final { return true; } diff --git a/netwerk/protocol/http/nsHttpConnection.cpp b/netwerk/protocol/http/nsHttpConnection.cpp index a83a6faca332..993c17cacda6 100644 --- a/netwerk/protocol/http/nsHttpConnection.cpp +++ b/netwerk/protocol/http/nsHttpConnection.cpp @@ -2074,11 +2074,22 @@ nsHttpConnection::DisableTCPKeepalives() // nsHttpConnection::nsISupports //----------------------------------------------------------------------------- -NS_IMPL_ISUPPORTS(nsHttpConnection, - nsIInputStreamCallback, - nsIOutputStreamCallback, - nsITransportEventSink, - nsIInterfaceRequestor) +NS_IMPL_ADDREF(nsHttpConnection) +NS_IMPL_RELEASE(nsHttpConnection) + +NS_INTERFACE_MAP_BEGIN(nsHttpConnection) + NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) + NS_INTERFACE_MAP_ENTRY(nsIInputStreamCallback) + NS_INTERFACE_MAP_ENTRY(nsIOutputStreamCallback) + NS_INTERFACE_MAP_ENTRY(nsITransportEventSink) + NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) + // we have no macro that covers this case. + if (aIID.Equals(NS_GET_IID(nsHttpConnection)) ) { + AddRef(); + *aInstancePtr = this; + return NS_OK; + } else +NS_INTERFACE_MAP_END //----------------------------------------------------------------------------- // nsHttpConnection::nsIInputStreamCallback diff --git a/netwerk/protocol/http/nsHttpConnection.h b/netwerk/protocol/http/nsHttpConnection.h index 230412e25811..5cc43040411a 100644 --- a/netwerk/protocol/http/nsHttpConnection.h +++ b/netwerk/protocol/http/nsHttpConnection.h @@ -31,6 +31,10 @@ namespace net { class nsHttpHandler; class ASpdySession; +// 1dcc863e-db90-4652-a1fe-13fea0b54e46 +#define NS_HTTPCONNECTION_IID \ +{ 0x1dcc863e, 0xdb90, 0x4652, {0xa1, 0xfe, 0x13, 0xfe, 0xa0, 0xb5, 0x4e, 0x46 }} + //----------------------------------------------------------------------------- // nsHttpConnection - represents a connection to a HTTP server (or proxy) // @@ -46,10 +50,12 @@ class nsHttpConnection final : public nsAHttpSegmentReader , public nsIInterfaceRequestor , public NudgeTunnelCallback , public ARefBase + , public nsSupportsWeakReference { virtual ~nsHttpConnection(); public: + NS_DECLARE_STATIC_IID_ACCESSOR(NS_HTTPCONNECTION_IID) NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSAHTTPSEGMENTREADER NS_DECL_NSAHTTPSEGMENTWRITER @@ -376,6 +382,8 @@ private: bool mDid0RTTSpdy; }; +NS_DEFINE_STATIC_IID_ACCESSOR(nsHttpConnection, NS_HTTPCONNECTION_IID) + } // namespace net } // namespace mozilla diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.cpp b/netwerk/protocol/http/nsHttpConnectionMgr.cpp index 0c9ecf66961a..f0b365216a07 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp +++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp @@ -44,31 +44,34 @@ namespace net { NS_IMPL_ISUPPORTS(nsHttpConnectionMgr, nsIObserver) -static void -InsertTransactionSorted(nsTArray > &pendingQ, nsHttpTransaction *trans) +void +nsHttpConnectionMgr::InsertTransactionSorted(nsTArray > &pendingQ, + nsHttpConnectionMgr::PendingTransactionInfo *pendingTransInfo) { // insert into queue with smallest valued number first. search in reverse // order under the assumption that many of the existing transactions will // have the same priority (usually 0). + nsHttpTransaction *trans = pendingTransInfo->mTransaction; + for (int32_t i = pendingQ.Length() - 1; i >= 0; --i) { - nsHttpTransaction *t = pendingQ[i]; + nsHttpTransaction *t = pendingQ[i]->mTransaction; if (trans->Priority() >= t->Priority()) { if (ChaosMode::isActive(ChaosFeature::NetworkScheduling)) { int32_t samePriorityCount; for (samePriorityCount = 0; i - samePriorityCount >= 0; ++samePriorityCount) { - if (pendingQ[i - samePriorityCount]->Priority() != trans->Priority()) { + if (pendingQ[i - samePriorityCount]->mTransaction->Priority() != trans->Priority()) { break; } } // skip over 0...all of the elements with the same priority. i -= ChaosMode::randomUint32LessThan(samePriorityCount + 1); } - pendingQ.InsertElementAt(i+1, trans); + pendingQ.InsertElementAt(i+1, pendingTransInfo); return; } } - pendingQ.InsertElementAt(0, trans); + pendingQ.InsertElementAt(0, pendingTransInfo); } //----------------------------------------------------------------------------- @@ -627,7 +630,8 @@ nsHttpConnectionMgr::LookupConnectionEntry(nsHttpConnectionInfo *ci, return preferred; } - if (trans && preferred->mPendingQ.Contains(trans)) + if (trans && + preferred->mPendingQ.Contains(trans, PendingComparator())) return preferred; // Neither conn nor trans found in preferred, use the default entry @@ -881,7 +885,7 @@ nsHttpConnectionMgr::ProcessPendingQForEntry(nsConnectionEntry *ent, bool consid ProcessSpdyPendingQ(ent); - nsHttpTransaction *trans; + PendingTransactionInfo *pendingTransInfo; nsresult rv; bool dispatchedSuccessfully = false; @@ -889,24 +893,58 @@ nsHttpConnectionMgr::ProcessPendingQForEntry(nsConnectionEntry *ent, bool consid // Keep iterating afterwards only until a transaction fails to dispatch. // if considerAll == true then try and dispatch all items. for (uint32_t i = 0; i < ent->mPendingQ.Length(); ) { - trans = ent->mPendingQ[i]; + pendingTransInfo = ent->mPendingQ[i]; + LOG(("nsHttpConnectionMgr::ProcessPendingQForEntry " + "[trans=%p, halfOpen=%p, activeConn=%p]\n", + pendingTransInfo->mTransaction.get(), + pendingTransInfo->mHalfOpen.get(), + pendingTransInfo->mActiveConn.get())); // When this transaction has already established a half-open // connection, we want to prevent any duplicate half-open // connections from being established and bound to this // transaction. Allow only use of an idle persistent connection // (if found) for transactions referred by a half-open connection. - bool alreadyHalfOpen = false; - for (int32_t j = 0; j < ((int32_t) ent->mHalfOpens.Length()); ++j) { - if (ent->mHalfOpens[j]->Transaction() == trans) { - alreadyHalfOpen = true; - break; + bool alreadyHalfOpenOrWaitingForTLS = false; + if (pendingTransInfo->mHalfOpen) { + MOZ_ASSERT(!pendingTransInfo->mActiveConn); + RefPtr halfOpen = + do_QueryReferent(pendingTransInfo->mHalfOpen); + if (halfOpen) { + // The half open socket was made for this transaction, in + // that case ent->mHalfOpens[j]->Transaction() == trans or + // the half open socket was opened speculatively and this + // transaction took it (in this case it must be: + // ent->mHalfOpens[j]->Transaction().IsNullTransaction()) + MOZ_ASSERT(halfOpen->Transaction()->IsNullTransaction() || + halfOpen->Transaction() == pendingTransInfo->mTransaction); + alreadyHalfOpenOrWaitingForTLS = true; + } else { + // If we have not found the halfOpen socket, remove the pointer. + pendingTransInfo->mHalfOpen = nullptr; + } + } else if (pendingTransInfo->mActiveConn) { + MOZ_ASSERT(!pendingTransInfo->mHalfOpen); + RefPtr activeConn = + do_QueryReferent(pendingTransInfo->mActiveConn); + // Check if this transaction claimed a connection that is still + // performing tls handshake with a NullHttpTransaction or it is between + // finishing tls and relaiming (When nullTrans finishes tls handshake, + // httpConnection does not have a transaction any more and a + // ReclaimConnection is dispatched). + if (activeConn && + (!activeConn->Transaction() || + activeConn->Transaction()->IsNullTransaction())) { + alreadyHalfOpenOrWaitingForTLS = true; + } else { + // If we have not found the connection, remove the pointer. + pendingTransInfo->mActiveConn = nullptr; } } rv = TryDispatchTransaction(ent, - alreadyHalfOpen || !!trans->TunnelProvider(), - trans); + alreadyHalfOpenOrWaitingForTLS || !!pendingTransInfo->mTransaction->TunnelProvider(), + pendingTransInfo); if (NS_SUCCEEDED(rv) || (rv != NS_ERROR_NOT_AVAILABLE)) { if (NS_SUCCEEDED(rv)) LOG((" dispatching pending transaction...\n")); @@ -915,8 +953,9 @@ nsHttpConnectionMgr::ProcessPendingQForEntry(nsConnectionEntry *ent, bool consid "TryDispatchTransaction returning hard error %" PRIx32 "\n", static_cast(rv))); - if (ent->mPendingQ.RemoveElement(trans)) { - // trans is now potentially destroyed + ReleaseClaimedSockets(ent, pendingTransInfo); + if (ent->mPendingQ.RemoveElement(pendingTransInfo)) { + // pendingTransInfo is now potentially destroyed dispatchedSuccessfully = true; continue; // dont ++i as we just made the array shorter } @@ -1062,8 +1101,10 @@ nsHttpConnectionMgr::RestrictConnections(nsConnectionEntry *ent) // returns other NS_ERROR on hard failure conditions nsresult nsHttpConnectionMgr::MakeNewConnection(nsConnectionEntry *ent, - nsHttpTransaction *trans) + PendingTransactionInfo *pendingTransInfo) { + nsHttpTransaction *trans = pendingTransInfo->mTransaction; + LOG(("nsHttpConnectionMgr::MakeNewConnection %p ent=%p trans=%p", this, ent, trans)); MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); @@ -1082,6 +1123,8 @@ nsHttpConnectionMgr::MakeNewConnection(nsConnectionEntry *ent, uint32_t flags; ent->mHalfOpens[i]->SetSpeculative(false); + pendingTransInfo->mHalfOpen = + do_GetWeakReference(static_cast(ent->mHalfOpens[i])); nsISocketTransport *transport = ent->mHalfOpens[i]->SocketTransport(); if (transport && NS_SUCCEEDED(transport->GetConnectionFlags(&flags))) { flags &= ~nsISocketTransport::DISABLE_RFC1918; @@ -1113,6 +1156,8 @@ nsHttpConnectionMgr::MakeNewConnection(nsConnectionEntry *ent, LOG(("nsHttpConnectionMgr::MakeNewConnection [ci = %s] " "Claiming a null transaction for later use\n", ent->mConnInfo->HashKey().get())); + pendingTransInfo->mActiveConn = + do_GetWeakReference(static_cast(ent->mActiveConns[i])); return NS_OK; } } @@ -1189,7 +1234,8 @@ nsHttpConnectionMgr::MakeNewConnection(nsConnectionEntry *ent, if (AtActiveConnectionLimit(ent, trans->Caps())) return NS_ERROR_NOT_AVAILABLE; - nsresult rv = CreateTransport(ent, trans, trans->Caps(), false, false, true); + nsresult rv = CreateTransport(ent, trans, trans->Caps(), false, false, + true, pendingTransInfo); if (NS_FAILED(rv)) { /* hard failure */ LOG(("nsHttpConnectionMgr::MakeNewConnection [ci = %s trans = %p] " @@ -1213,13 +1259,18 @@ nsHttpConnectionMgr::MakeNewConnection(nsConnectionEntry *ent, nsresult nsHttpConnectionMgr::TryDispatchTransaction(nsConnectionEntry *ent, bool onlyReusedConnection, - nsHttpTransaction *trans) + PendingTransactionInfo *pendingTransInfo) { MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); + + nsHttpTransaction *trans = pendingTransInfo->mTransaction; + LOG(("nsHttpConnectionMgr::TryDispatchTransaction without conn " - "[trans=%p ci=%p ci=%s caps=%x tunnelprovider=%p onlyreused=%d " - "active=%" PRIuSIZE " idle=%" PRIuSIZE "]\n", trans, - ent->mConnInfo.get(), ent->mConnInfo->HashKey().get(), + "[trans=%p halfOpen=%p conn=%p ci=%p ci=%s caps=%x tunnelprovider=%p " + "onlyreused=%d active=%" PRIuSIZE " idle=%" PRIuSIZE "]\n", trans, + pendingTransInfo->mHalfOpen.get(), + pendingTransInfo->mActiveConn.get(), ent->mConnInfo.get(), + ent->mConnInfo->HashKey().get(), uint32_t(trans->Caps()), trans->TunnelProvider(), onlyReusedConnection, ent->mActiveConns.Length(), ent->mIdleConns.Length())); @@ -1355,7 +1406,7 @@ nsHttpConnectionMgr::TryDispatchTransaction(nsConnectionEntry *ent, // step 4 if (!onlyReusedConnection) { - nsresult rv = MakeNewConnection(ent, trans); + nsresult rv = MakeNewConnection(ent, pendingTransInfo); if (NS_SUCCEEDED(rv)) { // this function returns NOT_AVAILABLE for asynchronous connects LOG((" dispatched step 4 (async new conn) trans=%p\n", trans)); @@ -1584,6 +1635,7 @@ nsHttpConnectionMgr::ProcessNewTransaction(nsHttpTransaction *trans) nsAHttpConnection *wrappedConnection = trans->Connection(); RefPtr conn; + RefPtr pendingTransInfo; if (wrappedConnection) conn = wrappedConnection->TakeHttpConnection(); @@ -1607,7 +1659,8 @@ nsHttpConnectionMgr::ProcessNewTransaction(nsHttpTransaction *trans) trans->SetConnection(nullptr); rv = DispatchTransaction(ent, trans, conn); } else { - rv = TryDispatchTransaction(ent, !!trans->TunnelProvider(), trans); + pendingTransInfo = new PendingTransactionInfo(trans); + rv = TryDispatchTransaction(ent, !!trans->TunnelProvider(), pendingTransInfo); } if (NS_SUCCEEDED(rv)) { @@ -1620,7 +1673,10 @@ nsHttpConnectionMgr::ProcessNewTransaction(nsHttpTransaction *trans) "[trans=%p pending-count=%" PRIuSIZE "]\n", trans, ent->mPendingQ.Length()+1)); // put this transaction on the pending queue... - InsertTransactionSorted(ent->mPendingQ, trans); + if (!pendingTransInfo) { + pendingTransInfo = new PendingTransactionInfo(trans); + } + InsertTransactionSorted(ent->mPendingQ, pendingTransInfo); return NS_OK; } @@ -1661,13 +1717,43 @@ nsHttpConnectionMgr::RecvdConnect() ConditionallyStopTimeoutTick(); } +void +nsHttpConnectionMgr::ReleaseClaimedSockets(nsConnectionEntry *ent, + PendingTransactionInfo * pendingTransInfo) +{ + if (pendingTransInfo->mHalfOpen) { + RefPtr halfOpen = + do_QueryReferent(pendingTransInfo->mHalfOpen); + if (halfOpen) { + if (halfOpen->Transaction() && + halfOpen->Transaction()->IsNullTransaction()) { + LOG(("nsHttpConnectionMgr::ReleaseClaimedSockets - mark halfOpne %p " + "speculative again.", halfOpen.get())); + halfOpen->SetSpeculative(true); + } + } + pendingTransInfo->mHalfOpen = nullptr; + } else if (pendingTransInfo->mActiveConn) { + RefPtr activeConn = + do_QueryReferent(pendingTransInfo->mActiveConn); + if (activeConn && activeConn->Transaction() && + activeConn->Transaction()->IsNullTransaction()) { + NullHttpTransaction *nullTrans = activeConn->Transaction()->QueryNullTransaction(); + nullTrans->Unclaim(); + LOG(("nsHttpConnectionMgr::ReleaseClaimedSockets - mark %p unclaimed.", + activeConn.get())); + } + } +} + nsresult nsHttpConnectionMgr::CreateTransport(nsConnectionEntry *ent, nsAHttpTransaction *trans, uint32_t caps, bool speculative, bool isFromPredictor, - bool allow1918) + bool allow1918, + PendingTransactionInfo *pendingTransInfo) { MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); @@ -1691,6 +1777,11 @@ nsHttpConnectionMgr::CreateTransport(nsConnectionEntry *ent, nsresult rv = sock->SetupPrimaryStreams(); NS_ENSURE_SUCCESS(rv, rv); + if (pendingTransInfo) { + pendingTransInfo->mHalfOpen = + do_GetWeakReference(static_cast(sock)); + } + ent->mHalfOpens.AppendElement(sock); mNumHalfOpenConns++; return NS_OK; @@ -1709,37 +1800,39 @@ nsHttpConnectionMgr::ProcessSpdyPendingQ(nsConnectionEntry *ent) if (!conn || !conn->CanDirectlyActivate()) return; - nsTArray > leftovers; + nsTArray > leftovers; uint32_t index; // Dispatch all the transactions we can for (index = 0; index < ent->mPendingQ.Length() && conn->CanDirectlyActivate(); ++index) { - nsHttpTransaction *trans = ent->mPendingQ[index]; + PendingTransactionInfo *pendingTransInfo = ent->mPendingQ[index]; - if (!(trans->Caps() & NS_HTTP_ALLOW_KEEPALIVE) || - trans->Caps() & NS_HTTP_DISALLOW_SPDY) { - leftovers.AppendElement(trans); + if (!(pendingTransInfo->mTransaction->Caps() & NS_HTTP_ALLOW_KEEPALIVE) || + pendingTransInfo->mTransaction->Caps() & NS_HTTP_DISALLOW_SPDY) { + leftovers.AppendElement(pendingTransInfo); continue; } - nsresult rv = DispatchTransaction(ent, trans, conn); + nsresult rv = DispatchTransaction(ent, pendingTransInfo->mTransaction, + conn); if (NS_FAILED(rv)) { // this cannot happen, but if due to some bug it does then // close the transaction MOZ_ASSERT(false, "Dispatch SPDY Transaction"); LOG(("ProcessSpdyPendingQ Dispatch Transaction failed trans=%p\n", - trans)); - trans->Close(rv); + pendingTransInfo->mTransaction.get())); + pendingTransInfo->mTransaction->Close(rv); } + ReleaseClaimedSockets(ent, pendingTransInfo); } // Slurp up the rest of the pending queue into our leftovers bucket (we // might have some left if conn->CanDirectlyActivate returned false) for (; index < ent->mPendingQ.Length(); ++index) { - nsHttpTransaction *trans = ent->mPendingQ[index]; - leftovers.AppendElement(trans); + PendingTransactionInfo *pendingTransInfo = ent->mPendingQ[index]; + leftovers.AppendElement(pendingTransInfo); } // Put the leftovers back in the pending queue and get rid of the @@ -1854,8 +1947,8 @@ nsHttpConnectionMgr::OnMsgShutdown(int32_t, ARefBase *param) // Close all pending transactions. while (ent->mPendingQ.Length()) { - nsHttpTransaction *trans = ent->mPendingQ[0]; - trans->Close(NS_ERROR_ABORT); + PendingTransactionInfo *pendingTransInfo = ent->mPendingQ[0]; + pendingTransInfo->mTransaction->Close(NS_ERROR_ABORT); ent->mPendingQ.RemoveElementAt(0); } @@ -1923,10 +2016,11 @@ nsHttpConnectionMgr::OnMsgReschedTransaction(int32_t priority, ARefBase *param) nullptr, trans); if (ent) { - int32_t index = ent->mPendingQ.IndexOf(trans); + int32_t index = ent->mPendingQ.IndexOf(trans, 0, PendingComparator()); if (index >= 0) { + RefPtr pendingTransInfo = ent->mPendingQ[index]; ent->mPendingQ.RemoveElementAt(index); - InsertTransactionSorted(ent->mPendingQ, trans); + InsertTransactionSorted(ent->mPendingQ, pendingTransInfo); } } } @@ -1955,23 +2049,29 @@ nsHttpConnectionMgr::OnMsgCancelTransaction(int32_t reason, ARefBase *param) LookupConnectionEntry(trans->ConnectionInfo(), nullptr, trans); if (ent) { - int32_t transIndex = ent->mPendingQ.IndexOf(trans); + int32_t transIndex = ent->mPendingQ.IndexOf(trans, 0, PendingComparator()); + // We will abandon all half-open sockets belonging to the given + // transaction. + RefPtr pendingTransInfo; if (transIndex >= 0) { LOG(("nsHttpConnectionMgr::OnMsgCancelTransaction [trans=%p]" " found in pending queue\n", trans)); + pendingTransInfo = ent->mPendingQ[transIndex]; + // We do not need to ReleaseClaimedSockets while we are going + // to close them all any way! ent->mPendingQ.RemoveElementAt(transIndex); } // Abandon all half-open sockets belonging to the given transaction. - for (uint32_t index = 0; - index < ent->mHalfOpens.Length(); - ++index) { - nsHalfOpenSocket *half = ent->mHalfOpens[index]; - if (trans == half->Transaction()) { + if (pendingTransInfo) { + RefPtr half = + do_QueryReferent(pendingTransInfo->mHalfOpen); + if (half) { + MOZ_ASSERT(trans == half->Transaction() || + half->Transaction()->IsNullTransaction()); half->Abandon(); - // there is only one, and now mHalfOpens[] has been changed. - break; } + pendingTransInfo->mHalfOpen = nullptr; } } @@ -2051,10 +2151,10 @@ nsHttpConnectionMgr::OnMsgCancelTransactions(int32_t code, ARefBase *param) } for (int32_t i = ent->mPendingQ.Length() - 1; i >= 0; --i) { - nsHttpTransaction *trans = ent->mPendingQ[i]; + PendingTransactionInfo *pendingTransInfo = ent->mPendingQ[i]; LOG(("nsHttpConnectionMgr::OnMsgCancelTransactions %s %p %p\n", - ci->HashKey().get(), ent, trans)); - trans->Close(reason); + ci->HashKey().get(), ent, pendingTransInfo->mTransaction.get())); + pendingTransInfo->mTransaction->Close(reason); ent->mPendingQ.RemoveElementAt(i); } } @@ -2605,7 +2705,8 @@ nsHttpConnectionMgr::OnMsgSpeculativeConnect(int32_t, ARefBase *param) !AtActiveConnectionLimit(ent, args->mTrans->Caps())) { DebugOnly rv = CreateTransport(ent, args->mTrans, args->mTrans->Caps(), true, - isFromPredictor, allow1918); + isFromPredictor, allow1918, + nullptr); MOZ_ASSERT(NS_SUCCEEDED(rv)); } else { LOG(("OnMsgSpeculativeConnect Transport " @@ -2639,12 +2740,22 @@ ConnectionHandle::PushBack(const char *buf, uint32_t bufLen) //////////////////////// nsHalfOpenSocket +NS_IMPL_ADDREF(nsHttpConnectionMgr::nsHalfOpenSocket) +NS_IMPL_RELEASE(nsHttpConnectionMgr::nsHalfOpenSocket) -NS_IMPL_ISUPPORTS(nsHttpConnectionMgr::nsHalfOpenSocket, - nsIOutputStreamCallback, - nsITransportEventSink, - nsIInterfaceRequestor, - nsITimerCallback) +NS_INTERFACE_MAP_BEGIN(nsHttpConnectionMgr::nsHalfOpenSocket) + NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) + NS_INTERFACE_MAP_ENTRY(nsIOutputStreamCallback) + NS_INTERFACE_MAP_ENTRY(nsITransportEventSink) + NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) + NS_INTERFACE_MAP_ENTRY(nsITimerCallback) + // we have no macro that covers this case. + if (aIID.Equals(NS_GET_IID(nsHttpConnectionMgr::nsHalfOpenSocket)) ) { + AddRef(); + *aInstancePtr = this; + return NS_OK; + } else +NS_INTERFACE_MAP_END nsHttpConnectionMgr:: nsHalfOpenSocket::nsHalfOpenSocket(nsConnectionEntry *ent, @@ -3051,14 +3162,16 @@ nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out) mHasConnected = true; // if this is still in the pending list, remove it and dispatch it - index = mEnt->mPendingQ.IndexOf(mTransaction); + index = mEnt->mPendingQ.IndexOf(mTransaction, 0, PendingComparator()); if (index != -1) { MOZ_ASSERT(!mSpeculative, "Speculative Half Open found mTransaction"); - RefPtr temp = mEnt->mPendingQ[index]; + RefPtr temp = mEnt->mPendingQ[index]; mEnt->mPendingQ.RemoveElementAt(index); gHttpHandler->ConnMgr()->AddActiveConn(conn, mEnt); - rv = gHttpHandler->ConnMgr()->DispatchTransaction(mEnt, temp, conn); + rv = gHttpHandler->ConnMgr()->DispatchTransaction(mEnt, + temp->mTransaction, + conn); } else { // this transaction was dispatched off the pending q before all the // sockets established themselves. @@ -3111,8 +3224,21 @@ nsHttpConnectionMgr::nsHalfOpenSocket::OnTransportStatus(nsITransport *trans, { MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); - if (mTransaction) - mTransaction->OnTransportStatus(trans, status, progress); + if (mTransaction) { + if ((trans == mSocketTransport) || + ((trans == mBackupTransport) && (status == NS_NET_STATUS_CONNECTED_TO) && + mEnt->mPendingQ.Contains(mTransaction, PendingComparator()))) { + // Send this status event only if the transaction is still panding, + // i.e. it has not found a free already connected socket. + // Sockets in halfOpen state can only get following events: + // NS_NET_STATUS_RESOLVING_HOST, NS_NET_STATUS_RESOLVED_HOST, + // NS_NET_STATUS_CONNECTING_TO and NS_NET_STATUS_CONNECTED_TO. + // mBackupTransport is only started after + // NS_NET_STATUS_CONNECTING_TO of mSocketTransport, so ignore all + // mBackupTransport events until NS_NET_STATUS_CONNECTED_TO. + mTransaction->OnTransportStatus(trans, status, progress); + } + } MOZ_ASSERT(trans == mSocketTransport || trans == mBackupTransport); if (status == NS_NET_STATUS_CONNECTED_TO) { diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.h b/netwerk/protocol/http/nsHttpConnectionMgr.h index 652cdcb57b35..550deda8bc54 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.h +++ b/netwerk/protocol/http/nsHttpConnectionMgr.h @@ -18,6 +18,7 @@ #include "mozilla/Attributes.h" #include "AlternateServices.h" #include "ARefBase.h" +#include "nsWeakReference.h" #include "nsIObserver.h" #include "nsITimer.h" @@ -30,6 +31,10 @@ class EventTokenBucket; class NullHttpTransaction; struct HttpRetParams; +// 8d411b53-54bc-4a99-8b78-ff125eab1564 +#define NS_HALFOPENSOCKET_IID \ +{ 0x8d411b53, 0x54bc, 0x4a99, {0x8b, 0x78, 0xff, 0x12, 0x5e, 0xab, 0x15, 0x64 }} + //----------------------------------------------------------------------------- // message handlers have this signature @@ -196,6 +201,7 @@ private: virtual ~nsHttpConnectionMgr(); class nsHalfOpenSocket; + class PendingTransactionInfo; // nsConnectionEntry // @@ -210,7 +216,7 @@ private: ~nsConnectionEntry(); RefPtr mConnInfo; - nsTArray > mPendingQ; // pending transaction queue + nsTArray > mPendingQ; // pending transaction queue nsTArray > mActiveConns; // active connections nsTArray > mIdleConns; // idle persistent connections nsTArray mHalfOpens; // half open connections @@ -271,11 +277,13 @@ private: class nsHalfOpenSocket final : public nsIOutputStreamCallback, public nsITransportEventSink, public nsIInterfaceRequestor, - public nsITimerCallback + public nsITimerCallback, + public nsSupportsWeakReference { ~nsHalfOpenSocket(); public: + NS_DECLARE_STATIC_IID_ACCESSOR(NS_HALFOPENSOCKET_IID) NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSIOUTPUTSTREAMCALLBACK NS_DECL_NSITRANSPORTEVENTSINK @@ -356,6 +364,35 @@ private: }; friend class nsHalfOpenSocket; + class PendingTransactionInfo : public ARefBase + { + public: + explicit PendingTransactionInfo(nsHttpTransaction * trans) + : mTransaction(trans) + {} + + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PendingTransactionInfo) + + void PrintDiagnostics(nsCString &log); + public: // meant to be public. + RefPtr mTransaction; + nsWeakPtr mHalfOpen; + nsWeakPtr mActiveConn; + + private: + virtual ~PendingTransactionInfo() {} + }; + friend class PendingTransactionInfo; + + class PendingComparator + { + public: + bool Equals(const PendingTransactionInfo *aPendingTrans, + const nsAHttpTransaction *aTrans) const { + return aPendingTrans->mTransaction.get() == aTrans; + } + }; + //------------------------------------------------------------------------- // NOTE: these members may be accessed from any thread (use mReentrantMonitor) //------------------------------------------------------------------------- @@ -379,7 +416,7 @@ private: bool AtActiveConnectionLimit(nsConnectionEntry *, uint32_t caps); MOZ_MUST_USE nsresult TryDispatchTransaction(nsConnectionEntry *ent, bool onlyReusedConnection, - nsHttpTransaction *trans); + PendingTransactionInfo *pendingTransInfo); MOZ_MUST_USE nsresult DispatchTransaction(nsConnectionEntry *, nsHttpTransaction *, nsHttpConnection *); @@ -395,17 +432,27 @@ private: void ReportProxyTelemetry(nsConnectionEntry *ent); MOZ_MUST_USE nsresult CreateTransport(nsConnectionEntry *, nsAHttpTransaction *, uint32_t, bool, - bool, bool); + bool, bool, + PendingTransactionInfo *pendingTransInfo); void AddActiveConn(nsHttpConnection *, nsConnectionEntry *); void DecrementActiveConnCount(nsHttpConnection *); void StartedConnect(); void RecvdConnect(); + // This function will unclaim the claimed connection or set a halfOpen + // socket to the speculative state if the transaction claiming them ends up + // using another connection. + void ReleaseClaimedSockets(nsConnectionEntry *ent, + PendingTransactionInfo * pendingTransInfo); + + void InsertTransactionSorted(nsTArray > &pendingQ, + PendingTransactionInfo *pendingTransInfo); + nsConnectionEntry *GetOrCreateConnectionEntry(nsHttpConnectionInfo *, bool allowWildCard); MOZ_MUST_USE nsresult MakeNewConnection(nsConnectionEntry *ent, - nsHttpTransaction *trans); + PendingTransactionInfo *pendingTransInfo); // Manage the preferred spdy connection entry for this address nsConnectionEntry *GetSpdyPreferredEnt(nsConnectionEntry *aOriginalEntry); @@ -490,6 +537,8 @@ private: nsCString mLogData; }; +NS_DEFINE_STATIC_IID_ACCESSOR(nsHttpConnectionMgr::nsHalfOpenSocket, NS_HALFOPENSOCKET_IID) + } // namespace net } // namespace mozilla From 14999e4cbfcfd2c17056b28b4aa6b24d51ab0851 Mon Sep 17 00:00:00 2001 From: Vera Sipicki Date: Fri, 3 Mar 2017 05:37:17 -0500 Subject: [PATCH 06/57] Bug 1342706 - Disabled text selection for learn-more-link in order to prettify copied header responses; r=Honza --- devtools/client/shared/components/tree/tree-view.css | 1 + 1 file changed, 1 insertion(+) diff --git a/devtools/client/shared/components/tree/tree-view.css b/devtools/client/shared/components/tree/tree-view.css index 987dbb5ca59c..5cd5e85566aa 100644 --- a/devtools/client/shared/components/tree/tree-view.css +++ b/devtools/client/shared/components/tree/tree-view.css @@ -85,6 +85,7 @@ /* Learn More link */ .treeTable .treeValueCell .learn-more-link { + -moz-user-select: none; color: var(--theme-highlight-blue); cursor: pointer; margin: 0 5px; From 8bd1b579497d953a8ce2c0dd1df48b384ba25184 Mon Sep 17 00:00:00 2001 From: Joshua Pinkney Date: Tue, 7 Mar 2017 11:10:00 +0100 Subject: [PATCH 07/57] Bug 1343803 - "Middle-mouse click on [Learn More] should open tab without immediately switching to it" r=honza --- devtools/client/netmonitor/shared/components/mdn-link.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/devtools/client/netmonitor/shared/components/mdn-link.js b/devtools/client/netmonitor/shared/components/mdn-link.js index 4d6aa3389bac..dd104c2520cf 100644 --- a/devtools/client/netmonitor/shared/components/mdn-link.js +++ b/devtools/client/netmonitor/shared/components/mdn-link.js @@ -37,7 +37,11 @@ function onLearnMoreClick(e, url) { e.preventDefault(); let win = Services.wm.getMostRecentWindow(gDevTools.chromeWindowType); - win.openUILinkIn(url, "tab"); + if (e.button === 1) { + win.openUILinkIn(url, "tabshifted"); + } else { + win.openUILinkIn(url, "tab"); + } } module.exports = MDNLink; From 48f2d4f0e9e50d305a831ef7b7383809bf6b256c Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Wed, 8 Mar 2017 07:23:47 -0700 Subject: [PATCH 08/57] Bug 1344315 - Suppress protected data checks when handing off runtimes between cooperative threads, r=jandem. --HG-- extra : rebase_source : a5b9b72ddd254c3f1b494ba5cf7dd83ccc82cc88 --- js/src/jit-test/tests/basic/bug1344315.js | 3 +++ js/src/vm/Runtime.cpp | 7 +++++++ js/src/vm/Runtime.h | 4 ++-- 3 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 js/src/jit-test/tests/basic/bug1344315.js diff --git a/js/src/jit-test/tests/basic/bug1344315.js b/js/src/jit-test/tests/basic/bug1344315.js new file mode 100644 index 000000000000..b67b274f9cdc --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1344315.js @@ -0,0 +1,3 @@ +if (helperThreadCount() === 0) + quit(); +evalInCooperativeThread('cooperativeYield(); var dbg = new Debugger();'); diff --git a/js/src/vm/Runtime.cpp b/js/src/vm/Runtime.cpp index 9fd4cab8293e..7f8986aa43bb 100644 --- a/js/src/vm/Runtime.cpp +++ b/js/src/vm/Runtime.cpp @@ -342,6 +342,13 @@ JSRuntime::destroyRuntime() static void CheckCanChangeActiveContext(JSRuntime* rt) { + // The runtime might not currently have an active context, in which case + // the accesses below to ActiveThreadData data would not normally be + // allowed. Suppress protected data checks so these accesses will be + // tolerated --- if the active context is null then we're about to set it + // to the current thread. + AutoNoteSingleThreadedRegion anstr; + MOZ_RELEASE_ASSERT(!rt->activeContextChangeProhibited()); MOZ_RELEASE_ASSERT(!rt->activeContext() || rt->gc.canChangeActiveContext(rt->activeContext())); diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h index 8ce1dfdf0fe5..a1d6f3901be2 100644 --- a/js/src/vm/Runtime.h +++ b/js/src/vm/Runtime.h @@ -340,11 +340,11 @@ struct JSRuntime : public js::MallocProvider js::ActiveThreadData> cooperatingContexts_; // Count of AutoProhibitActiveContextChange instances on the active context. - mozilla::Atomic activeContextChangeProhibited_; + js::ActiveThreadData activeContextChangeProhibited_; // Count of beginSingleThreadedExecution() calls that have occurred with no // matching endSingleThreadedExecution(). - mozilla::Atomic singleThreadedExecutionRequired_; + js::ActiveThreadData singleThreadedExecutionRequired_; // Whether some thread has called beginSingleThreadedExecution() and we are // in the associated callback (which may execute JS on other threads). From 8325eed6e782313fc2c8644ff4dffb3967d7f85d Mon Sep 17 00:00:00 2001 From: Ben Kelly Date: Wed, 8 Mar 2017 10:19:26 -0500 Subject: [PATCH 09/57] Bug 1345132 Fix races in test_claim.html mochitest. r=catalinb --- .../test/serviceworkers/claim_worker_1.js | 27 +++++++++-------- .../test/serviceworkers/claim_worker_2.js | 29 +++++++++---------- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/dom/workers/test/serviceworkers/claim_worker_1.js b/dom/workers/test/serviceworkers/claim_worker_1.js index e5f6392d3f94..6cef9e0b4a67 100644 --- a/dom/workers/test/serviceworkers/claim_worker_1.js +++ b/dom/workers/test/serviceworkers/claim_worker_1.js @@ -10,19 +10,18 @@ onactivate = function(e) { // should be 0 result.match_count_before = matched.length; }).then(function() { - var claimPromise = self.clients.claim().then(function(ret) { - result.resolve_value = ret; - }); - - return claimPromise.then(self.clients.matchAll().then(function(matched) { - // should be 2 - result.match_count_after = matched.length; - for (i = 0; i < matched.length; i++) { - matched[i].postMessage(result); - } - if (result.match_count_after !== 2) { - dump("ERROR: claim_worker_1 failed to capture clients.\n"); - } - })); + return self.clients.claim(); + }).then(function(ret) { + result.resolve_value = ret; + return self.clients.matchAll(); + }).then(function(matched) { + // should be 2 + result.match_count_after = matched.length; + for (i = 0; i < matched.length; i++) { + matched[i].postMessage(result); + } + if (result.match_count_after !== 2) { + dump("ERROR: claim_worker_1 failed to capture clients.\n"); + } }); } diff --git a/dom/workers/test/serviceworkers/claim_worker_2.js b/dom/workers/test/serviceworkers/claim_worker_2.js index 863ba1fc0bef..10272dd4ade9 100644 --- a/dom/workers/test/serviceworkers/claim_worker_2.js +++ b/dom/workers/test/serviceworkers/claim_worker_2.js @@ -10,21 +10,20 @@ onactivate = function(e) { // should be 0 result.match_count_before = matched.length; }).then(function() { - var claimPromise = self.clients.claim().then(function(ret) { - result.resolve_value = ret; - }); - - return claimPromise.then(self.clients.matchAll().then(function(matched) { - // should be 1 - result.match_count_after = matched.length; - if (result.match_count_after === 1) { - matched[0].postMessage(result); - } else { - dump("ERROR: claim_worker_2 failed to capture clients.\n"); - for (let i = 0; i < matched.length; ++i) { - dump('### ### matched[' + i + ']: ' + matched[i].url + '\n'); - } + return clients.claim(); + }).then(function(ret) { + result.resolve_value = ret; + return clients.matchAll(); + }).then(function(matched) { + // should be 1 + result.match_count_after = matched.length; + if (result.match_count_after === 1) { + matched[0].postMessage(result); + } else { + dump("ERROR: claim_worker_2 failed to capture clients.\n"); + for (let i = 0; i < matched.length; ++i) { + dump('### ### matched[' + i + ']: ' + matched[i].url + '\n'); } - })); + } }); } From f7810a3e1393538c55756cad5ed4a7053597f4db Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Wed, 8 Mar 2017 16:29:50 +0100 Subject: [PATCH 10/57] Backed out changeset ca1f19ad3de6 (bug 1341572) for causing test failures in test_altsvc.js --HG-- extra : rebase_source : 7377d5bf1efe761d07af2d64a2a8e8a429687f14 --- .../protocol/http/ConnectionDiagnostics.cpp | 10 - netwerk/protocol/http/NullHttpTransaction.cpp | 6 - netwerk/protocol/http/NullHttpTransaction.h | 1 - netwerk/protocol/http/nsHttpConnection.cpp | 21 +- netwerk/protocol/http/nsHttpConnection.h | 8 - netwerk/protocol/http/nsHttpConnectionMgr.cpp | 254 +++++------------- netwerk/protocol/http/nsHttpConnectionMgr.h | 59 +--- 7 files changed, 74 insertions(+), 285 deletions(-) diff --git a/netwerk/protocol/http/ConnectionDiagnostics.cpp b/netwerk/protocol/http/ConnectionDiagnostics.cpp index b3d216983318..a8f43256db52 100644 --- a/netwerk/protocol/http/ConnectionDiagnostics.cpp +++ b/netwerk/protocol/http/ConnectionDiagnostics.cpp @@ -204,15 +204,5 @@ nsHttpTransaction::PrintDiagnostics(nsCString &log) log.AppendPrintf(" restart count = %u\n", mRestartCount); } -void -nsHttpConnectionMgr::PendingTransactionInfo::PrintDiagnostics(nsCString &log) -{ - log.AppendPrintf(" ::: Pending transaction\n"); - mTransaction->PrintDiagnostics(log); - RefPtr halfOpen = do_QueryReferent(mHalfOpen); - log.AppendPrintf(" Waiting for half open sock: %p or connection: %p\n", - halfOpen.get(), mActiveConn.get()); -} - } // namespace net } // namespace mozilla diff --git a/netwerk/protocol/http/NullHttpTransaction.cpp b/netwerk/protocol/http/NullHttpTransaction.cpp index ddbdf1c3311f..501407795f3c 100644 --- a/netwerk/protocol/http/NullHttpTransaction.cpp +++ b/netwerk/protocol/http/NullHttpTransaction.cpp @@ -141,12 +141,6 @@ NullHttpTransaction::Claim() return true; } -void -NullHttpTransaction::Unclaim() -{ - mClaimed = false; -} - void NullHttpTransaction::SetConnection(nsAHttpConnection *conn) { diff --git a/netwerk/protocol/http/NullHttpTransaction.h b/netwerk/protocol/http/NullHttpTransaction.h index 934643266314..9fa07947f6d9 100644 --- a/netwerk/protocol/http/NullHttpTransaction.h +++ b/netwerk/protocol/http/NullHttpTransaction.h @@ -39,7 +39,6 @@ public: uint32_t caps); MOZ_MUST_USE bool Claim(); - void Unclaim(); // Overload of nsAHttpTransaction methods bool IsNullTransaction() override final { return true; } diff --git a/netwerk/protocol/http/nsHttpConnection.cpp b/netwerk/protocol/http/nsHttpConnection.cpp index 993c17cacda6..a83a6faca332 100644 --- a/netwerk/protocol/http/nsHttpConnection.cpp +++ b/netwerk/protocol/http/nsHttpConnection.cpp @@ -2074,22 +2074,11 @@ nsHttpConnection::DisableTCPKeepalives() // nsHttpConnection::nsISupports //----------------------------------------------------------------------------- -NS_IMPL_ADDREF(nsHttpConnection) -NS_IMPL_RELEASE(nsHttpConnection) - -NS_INTERFACE_MAP_BEGIN(nsHttpConnection) - NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) - NS_INTERFACE_MAP_ENTRY(nsIInputStreamCallback) - NS_INTERFACE_MAP_ENTRY(nsIOutputStreamCallback) - NS_INTERFACE_MAP_ENTRY(nsITransportEventSink) - NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) - // we have no macro that covers this case. - if (aIID.Equals(NS_GET_IID(nsHttpConnection)) ) { - AddRef(); - *aInstancePtr = this; - return NS_OK; - } else -NS_INTERFACE_MAP_END +NS_IMPL_ISUPPORTS(nsHttpConnection, + nsIInputStreamCallback, + nsIOutputStreamCallback, + nsITransportEventSink, + nsIInterfaceRequestor) //----------------------------------------------------------------------------- // nsHttpConnection::nsIInputStreamCallback diff --git a/netwerk/protocol/http/nsHttpConnection.h b/netwerk/protocol/http/nsHttpConnection.h index 5cc43040411a..230412e25811 100644 --- a/netwerk/protocol/http/nsHttpConnection.h +++ b/netwerk/protocol/http/nsHttpConnection.h @@ -31,10 +31,6 @@ namespace net { class nsHttpHandler; class ASpdySession; -// 1dcc863e-db90-4652-a1fe-13fea0b54e46 -#define NS_HTTPCONNECTION_IID \ -{ 0x1dcc863e, 0xdb90, 0x4652, {0xa1, 0xfe, 0x13, 0xfe, 0xa0, 0xb5, 0x4e, 0x46 }} - //----------------------------------------------------------------------------- // nsHttpConnection - represents a connection to a HTTP server (or proxy) // @@ -50,12 +46,10 @@ class nsHttpConnection final : public nsAHttpSegmentReader , public nsIInterfaceRequestor , public NudgeTunnelCallback , public ARefBase - , public nsSupportsWeakReference { virtual ~nsHttpConnection(); public: - NS_DECLARE_STATIC_IID_ACCESSOR(NS_HTTPCONNECTION_IID) NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSAHTTPSEGMENTREADER NS_DECL_NSAHTTPSEGMENTWRITER @@ -382,8 +376,6 @@ private: bool mDid0RTTSpdy; }; -NS_DEFINE_STATIC_IID_ACCESSOR(nsHttpConnection, NS_HTTPCONNECTION_IID) - } // namespace net } // namespace mozilla diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.cpp b/netwerk/protocol/http/nsHttpConnectionMgr.cpp index f0b365216a07..0c9ecf66961a 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp +++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp @@ -44,34 +44,31 @@ namespace net { NS_IMPL_ISUPPORTS(nsHttpConnectionMgr, nsIObserver) -void -nsHttpConnectionMgr::InsertTransactionSorted(nsTArray > &pendingQ, - nsHttpConnectionMgr::PendingTransactionInfo *pendingTransInfo) +static void +InsertTransactionSorted(nsTArray > &pendingQ, nsHttpTransaction *trans) { // insert into queue with smallest valued number first. search in reverse // order under the assumption that many of the existing transactions will // have the same priority (usually 0). - nsHttpTransaction *trans = pendingTransInfo->mTransaction; - for (int32_t i = pendingQ.Length() - 1; i >= 0; --i) { - nsHttpTransaction *t = pendingQ[i]->mTransaction; + nsHttpTransaction *t = pendingQ[i]; if (trans->Priority() >= t->Priority()) { if (ChaosMode::isActive(ChaosFeature::NetworkScheduling)) { int32_t samePriorityCount; for (samePriorityCount = 0; i - samePriorityCount >= 0; ++samePriorityCount) { - if (pendingQ[i - samePriorityCount]->mTransaction->Priority() != trans->Priority()) { + if (pendingQ[i - samePriorityCount]->Priority() != trans->Priority()) { break; } } // skip over 0...all of the elements with the same priority. i -= ChaosMode::randomUint32LessThan(samePriorityCount + 1); } - pendingQ.InsertElementAt(i+1, pendingTransInfo); + pendingQ.InsertElementAt(i+1, trans); return; } } - pendingQ.InsertElementAt(0, pendingTransInfo); + pendingQ.InsertElementAt(0, trans); } //----------------------------------------------------------------------------- @@ -630,8 +627,7 @@ nsHttpConnectionMgr::LookupConnectionEntry(nsHttpConnectionInfo *ci, return preferred; } - if (trans && - preferred->mPendingQ.Contains(trans, PendingComparator())) + if (trans && preferred->mPendingQ.Contains(trans)) return preferred; // Neither conn nor trans found in preferred, use the default entry @@ -885,7 +881,7 @@ nsHttpConnectionMgr::ProcessPendingQForEntry(nsConnectionEntry *ent, bool consid ProcessSpdyPendingQ(ent); - PendingTransactionInfo *pendingTransInfo; + nsHttpTransaction *trans; nsresult rv; bool dispatchedSuccessfully = false; @@ -893,58 +889,24 @@ nsHttpConnectionMgr::ProcessPendingQForEntry(nsConnectionEntry *ent, bool consid // Keep iterating afterwards only until a transaction fails to dispatch. // if considerAll == true then try and dispatch all items. for (uint32_t i = 0; i < ent->mPendingQ.Length(); ) { - pendingTransInfo = ent->mPendingQ[i]; - LOG(("nsHttpConnectionMgr::ProcessPendingQForEntry " - "[trans=%p, halfOpen=%p, activeConn=%p]\n", - pendingTransInfo->mTransaction.get(), - pendingTransInfo->mHalfOpen.get(), - pendingTransInfo->mActiveConn.get())); + trans = ent->mPendingQ[i]; // When this transaction has already established a half-open // connection, we want to prevent any duplicate half-open // connections from being established and bound to this // transaction. Allow only use of an idle persistent connection // (if found) for transactions referred by a half-open connection. - bool alreadyHalfOpenOrWaitingForTLS = false; - if (pendingTransInfo->mHalfOpen) { - MOZ_ASSERT(!pendingTransInfo->mActiveConn); - RefPtr halfOpen = - do_QueryReferent(pendingTransInfo->mHalfOpen); - if (halfOpen) { - // The half open socket was made for this transaction, in - // that case ent->mHalfOpens[j]->Transaction() == trans or - // the half open socket was opened speculatively and this - // transaction took it (in this case it must be: - // ent->mHalfOpens[j]->Transaction().IsNullTransaction()) - MOZ_ASSERT(halfOpen->Transaction()->IsNullTransaction() || - halfOpen->Transaction() == pendingTransInfo->mTransaction); - alreadyHalfOpenOrWaitingForTLS = true; - } else { - // If we have not found the halfOpen socket, remove the pointer. - pendingTransInfo->mHalfOpen = nullptr; - } - } else if (pendingTransInfo->mActiveConn) { - MOZ_ASSERT(!pendingTransInfo->mHalfOpen); - RefPtr activeConn = - do_QueryReferent(pendingTransInfo->mActiveConn); - // Check if this transaction claimed a connection that is still - // performing tls handshake with a NullHttpTransaction or it is between - // finishing tls and relaiming (When nullTrans finishes tls handshake, - // httpConnection does not have a transaction any more and a - // ReclaimConnection is dispatched). - if (activeConn && - (!activeConn->Transaction() || - activeConn->Transaction()->IsNullTransaction())) { - alreadyHalfOpenOrWaitingForTLS = true; - } else { - // If we have not found the connection, remove the pointer. - pendingTransInfo->mActiveConn = nullptr; + bool alreadyHalfOpen = false; + for (int32_t j = 0; j < ((int32_t) ent->mHalfOpens.Length()); ++j) { + if (ent->mHalfOpens[j]->Transaction() == trans) { + alreadyHalfOpen = true; + break; } } rv = TryDispatchTransaction(ent, - alreadyHalfOpenOrWaitingForTLS || !!pendingTransInfo->mTransaction->TunnelProvider(), - pendingTransInfo); + alreadyHalfOpen || !!trans->TunnelProvider(), + trans); if (NS_SUCCEEDED(rv) || (rv != NS_ERROR_NOT_AVAILABLE)) { if (NS_SUCCEEDED(rv)) LOG((" dispatching pending transaction...\n")); @@ -953,9 +915,8 @@ nsHttpConnectionMgr::ProcessPendingQForEntry(nsConnectionEntry *ent, bool consid "TryDispatchTransaction returning hard error %" PRIx32 "\n", static_cast(rv))); - ReleaseClaimedSockets(ent, pendingTransInfo); - if (ent->mPendingQ.RemoveElement(pendingTransInfo)) { - // pendingTransInfo is now potentially destroyed + if (ent->mPendingQ.RemoveElement(trans)) { + // trans is now potentially destroyed dispatchedSuccessfully = true; continue; // dont ++i as we just made the array shorter } @@ -1101,10 +1062,8 @@ nsHttpConnectionMgr::RestrictConnections(nsConnectionEntry *ent) // returns other NS_ERROR on hard failure conditions nsresult nsHttpConnectionMgr::MakeNewConnection(nsConnectionEntry *ent, - PendingTransactionInfo *pendingTransInfo) + nsHttpTransaction *trans) { - nsHttpTransaction *trans = pendingTransInfo->mTransaction; - LOG(("nsHttpConnectionMgr::MakeNewConnection %p ent=%p trans=%p", this, ent, trans)); MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); @@ -1123,8 +1082,6 @@ nsHttpConnectionMgr::MakeNewConnection(nsConnectionEntry *ent, uint32_t flags; ent->mHalfOpens[i]->SetSpeculative(false); - pendingTransInfo->mHalfOpen = - do_GetWeakReference(static_cast(ent->mHalfOpens[i])); nsISocketTransport *transport = ent->mHalfOpens[i]->SocketTransport(); if (transport && NS_SUCCEEDED(transport->GetConnectionFlags(&flags))) { flags &= ~nsISocketTransport::DISABLE_RFC1918; @@ -1156,8 +1113,6 @@ nsHttpConnectionMgr::MakeNewConnection(nsConnectionEntry *ent, LOG(("nsHttpConnectionMgr::MakeNewConnection [ci = %s] " "Claiming a null transaction for later use\n", ent->mConnInfo->HashKey().get())); - pendingTransInfo->mActiveConn = - do_GetWeakReference(static_cast(ent->mActiveConns[i])); return NS_OK; } } @@ -1234,8 +1189,7 @@ nsHttpConnectionMgr::MakeNewConnection(nsConnectionEntry *ent, if (AtActiveConnectionLimit(ent, trans->Caps())) return NS_ERROR_NOT_AVAILABLE; - nsresult rv = CreateTransport(ent, trans, trans->Caps(), false, false, - true, pendingTransInfo); + nsresult rv = CreateTransport(ent, trans, trans->Caps(), false, false, true); if (NS_FAILED(rv)) { /* hard failure */ LOG(("nsHttpConnectionMgr::MakeNewConnection [ci = %s trans = %p] " @@ -1259,18 +1213,13 @@ nsHttpConnectionMgr::MakeNewConnection(nsConnectionEntry *ent, nsresult nsHttpConnectionMgr::TryDispatchTransaction(nsConnectionEntry *ent, bool onlyReusedConnection, - PendingTransactionInfo *pendingTransInfo) + nsHttpTransaction *trans) { MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); - - nsHttpTransaction *trans = pendingTransInfo->mTransaction; - LOG(("nsHttpConnectionMgr::TryDispatchTransaction without conn " - "[trans=%p halfOpen=%p conn=%p ci=%p ci=%s caps=%x tunnelprovider=%p " - "onlyreused=%d active=%" PRIuSIZE " idle=%" PRIuSIZE "]\n", trans, - pendingTransInfo->mHalfOpen.get(), - pendingTransInfo->mActiveConn.get(), ent->mConnInfo.get(), - ent->mConnInfo->HashKey().get(), + "[trans=%p ci=%p ci=%s caps=%x tunnelprovider=%p onlyreused=%d " + "active=%" PRIuSIZE " idle=%" PRIuSIZE "]\n", trans, + ent->mConnInfo.get(), ent->mConnInfo->HashKey().get(), uint32_t(trans->Caps()), trans->TunnelProvider(), onlyReusedConnection, ent->mActiveConns.Length(), ent->mIdleConns.Length())); @@ -1406,7 +1355,7 @@ nsHttpConnectionMgr::TryDispatchTransaction(nsConnectionEntry *ent, // step 4 if (!onlyReusedConnection) { - nsresult rv = MakeNewConnection(ent, pendingTransInfo); + nsresult rv = MakeNewConnection(ent, trans); if (NS_SUCCEEDED(rv)) { // this function returns NOT_AVAILABLE for asynchronous connects LOG((" dispatched step 4 (async new conn) trans=%p\n", trans)); @@ -1635,7 +1584,6 @@ nsHttpConnectionMgr::ProcessNewTransaction(nsHttpTransaction *trans) nsAHttpConnection *wrappedConnection = trans->Connection(); RefPtr conn; - RefPtr pendingTransInfo; if (wrappedConnection) conn = wrappedConnection->TakeHttpConnection(); @@ -1659,8 +1607,7 @@ nsHttpConnectionMgr::ProcessNewTransaction(nsHttpTransaction *trans) trans->SetConnection(nullptr); rv = DispatchTransaction(ent, trans, conn); } else { - pendingTransInfo = new PendingTransactionInfo(trans); - rv = TryDispatchTransaction(ent, !!trans->TunnelProvider(), pendingTransInfo); + rv = TryDispatchTransaction(ent, !!trans->TunnelProvider(), trans); } if (NS_SUCCEEDED(rv)) { @@ -1673,10 +1620,7 @@ nsHttpConnectionMgr::ProcessNewTransaction(nsHttpTransaction *trans) "[trans=%p pending-count=%" PRIuSIZE "]\n", trans, ent->mPendingQ.Length()+1)); // put this transaction on the pending queue... - if (!pendingTransInfo) { - pendingTransInfo = new PendingTransactionInfo(trans); - } - InsertTransactionSorted(ent->mPendingQ, pendingTransInfo); + InsertTransactionSorted(ent->mPendingQ, trans); return NS_OK; } @@ -1717,43 +1661,13 @@ nsHttpConnectionMgr::RecvdConnect() ConditionallyStopTimeoutTick(); } -void -nsHttpConnectionMgr::ReleaseClaimedSockets(nsConnectionEntry *ent, - PendingTransactionInfo * pendingTransInfo) -{ - if (pendingTransInfo->mHalfOpen) { - RefPtr halfOpen = - do_QueryReferent(pendingTransInfo->mHalfOpen); - if (halfOpen) { - if (halfOpen->Transaction() && - halfOpen->Transaction()->IsNullTransaction()) { - LOG(("nsHttpConnectionMgr::ReleaseClaimedSockets - mark halfOpne %p " - "speculative again.", halfOpen.get())); - halfOpen->SetSpeculative(true); - } - } - pendingTransInfo->mHalfOpen = nullptr; - } else if (pendingTransInfo->mActiveConn) { - RefPtr activeConn = - do_QueryReferent(pendingTransInfo->mActiveConn); - if (activeConn && activeConn->Transaction() && - activeConn->Transaction()->IsNullTransaction()) { - NullHttpTransaction *nullTrans = activeConn->Transaction()->QueryNullTransaction(); - nullTrans->Unclaim(); - LOG(("nsHttpConnectionMgr::ReleaseClaimedSockets - mark %p unclaimed.", - activeConn.get())); - } - } -} - nsresult nsHttpConnectionMgr::CreateTransport(nsConnectionEntry *ent, nsAHttpTransaction *trans, uint32_t caps, bool speculative, bool isFromPredictor, - bool allow1918, - PendingTransactionInfo *pendingTransInfo) + bool allow1918) { MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); @@ -1777,11 +1691,6 @@ nsHttpConnectionMgr::CreateTransport(nsConnectionEntry *ent, nsresult rv = sock->SetupPrimaryStreams(); NS_ENSURE_SUCCESS(rv, rv); - if (pendingTransInfo) { - pendingTransInfo->mHalfOpen = - do_GetWeakReference(static_cast(sock)); - } - ent->mHalfOpens.AppendElement(sock); mNumHalfOpenConns++; return NS_OK; @@ -1800,39 +1709,37 @@ nsHttpConnectionMgr::ProcessSpdyPendingQ(nsConnectionEntry *ent) if (!conn || !conn->CanDirectlyActivate()) return; - nsTArray > leftovers; + nsTArray > leftovers; uint32_t index; // Dispatch all the transactions we can for (index = 0; index < ent->mPendingQ.Length() && conn->CanDirectlyActivate(); ++index) { - PendingTransactionInfo *pendingTransInfo = ent->mPendingQ[index]; + nsHttpTransaction *trans = ent->mPendingQ[index]; - if (!(pendingTransInfo->mTransaction->Caps() & NS_HTTP_ALLOW_KEEPALIVE) || - pendingTransInfo->mTransaction->Caps() & NS_HTTP_DISALLOW_SPDY) { - leftovers.AppendElement(pendingTransInfo); + if (!(trans->Caps() & NS_HTTP_ALLOW_KEEPALIVE) || + trans->Caps() & NS_HTTP_DISALLOW_SPDY) { + leftovers.AppendElement(trans); continue; } - nsresult rv = DispatchTransaction(ent, pendingTransInfo->mTransaction, - conn); + nsresult rv = DispatchTransaction(ent, trans, conn); if (NS_FAILED(rv)) { // this cannot happen, but if due to some bug it does then // close the transaction MOZ_ASSERT(false, "Dispatch SPDY Transaction"); LOG(("ProcessSpdyPendingQ Dispatch Transaction failed trans=%p\n", - pendingTransInfo->mTransaction.get())); - pendingTransInfo->mTransaction->Close(rv); + trans)); + trans->Close(rv); } - ReleaseClaimedSockets(ent, pendingTransInfo); } // Slurp up the rest of the pending queue into our leftovers bucket (we // might have some left if conn->CanDirectlyActivate returned false) for (; index < ent->mPendingQ.Length(); ++index) { - PendingTransactionInfo *pendingTransInfo = ent->mPendingQ[index]; - leftovers.AppendElement(pendingTransInfo); + nsHttpTransaction *trans = ent->mPendingQ[index]; + leftovers.AppendElement(trans); } // Put the leftovers back in the pending queue and get rid of the @@ -1947,8 +1854,8 @@ nsHttpConnectionMgr::OnMsgShutdown(int32_t, ARefBase *param) // Close all pending transactions. while (ent->mPendingQ.Length()) { - PendingTransactionInfo *pendingTransInfo = ent->mPendingQ[0]; - pendingTransInfo->mTransaction->Close(NS_ERROR_ABORT); + nsHttpTransaction *trans = ent->mPendingQ[0]; + trans->Close(NS_ERROR_ABORT); ent->mPendingQ.RemoveElementAt(0); } @@ -2016,11 +1923,10 @@ nsHttpConnectionMgr::OnMsgReschedTransaction(int32_t priority, ARefBase *param) nullptr, trans); if (ent) { - int32_t index = ent->mPendingQ.IndexOf(trans, 0, PendingComparator()); + int32_t index = ent->mPendingQ.IndexOf(trans); if (index >= 0) { - RefPtr pendingTransInfo = ent->mPendingQ[index]; ent->mPendingQ.RemoveElementAt(index); - InsertTransactionSorted(ent->mPendingQ, pendingTransInfo); + InsertTransactionSorted(ent->mPendingQ, trans); } } } @@ -2049,29 +1955,23 @@ nsHttpConnectionMgr::OnMsgCancelTransaction(int32_t reason, ARefBase *param) LookupConnectionEntry(trans->ConnectionInfo(), nullptr, trans); if (ent) { - int32_t transIndex = ent->mPendingQ.IndexOf(trans, 0, PendingComparator()); - // We will abandon all half-open sockets belonging to the given - // transaction. - RefPtr pendingTransInfo; + int32_t transIndex = ent->mPendingQ.IndexOf(trans); if (transIndex >= 0) { LOG(("nsHttpConnectionMgr::OnMsgCancelTransaction [trans=%p]" " found in pending queue\n", trans)); - pendingTransInfo = ent->mPendingQ[transIndex]; - // We do not need to ReleaseClaimedSockets while we are going - // to close them all any way! ent->mPendingQ.RemoveElementAt(transIndex); } // Abandon all half-open sockets belonging to the given transaction. - if (pendingTransInfo) { - RefPtr half = - do_QueryReferent(pendingTransInfo->mHalfOpen); - if (half) { - MOZ_ASSERT(trans == half->Transaction() || - half->Transaction()->IsNullTransaction()); + for (uint32_t index = 0; + index < ent->mHalfOpens.Length(); + ++index) { + nsHalfOpenSocket *half = ent->mHalfOpens[index]; + if (trans == half->Transaction()) { half->Abandon(); + // there is only one, and now mHalfOpens[] has been changed. + break; } - pendingTransInfo->mHalfOpen = nullptr; } } @@ -2151,10 +2051,10 @@ nsHttpConnectionMgr::OnMsgCancelTransactions(int32_t code, ARefBase *param) } for (int32_t i = ent->mPendingQ.Length() - 1; i >= 0; --i) { - PendingTransactionInfo *pendingTransInfo = ent->mPendingQ[i]; + nsHttpTransaction *trans = ent->mPendingQ[i]; LOG(("nsHttpConnectionMgr::OnMsgCancelTransactions %s %p %p\n", - ci->HashKey().get(), ent, pendingTransInfo->mTransaction.get())); - pendingTransInfo->mTransaction->Close(reason); + ci->HashKey().get(), ent, trans)); + trans->Close(reason); ent->mPendingQ.RemoveElementAt(i); } } @@ -2705,8 +2605,7 @@ nsHttpConnectionMgr::OnMsgSpeculativeConnect(int32_t, ARefBase *param) !AtActiveConnectionLimit(ent, args->mTrans->Caps())) { DebugOnly rv = CreateTransport(ent, args->mTrans, args->mTrans->Caps(), true, - isFromPredictor, allow1918, - nullptr); + isFromPredictor, allow1918); MOZ_ASSERT(NS_SUCCEEDED(rv)); } else { LOG(("OnMsgSpeculativeConnect Transport " @@ -2740,22 +2639,12 @@ ConnectionHandle::PushBack(const char *buf, uint32_t bufLen) //////////////////////// nsHalfOpenSocket -NS_IMPL_ADDREF(nsHttpConnectionMgr::nsHalfOpenSocket) -NS_IMPL_RELEASE(nsHttpConnectionMgr::nsHalfOpenSocket) -NS_INTERFACE_MAP_BEGIN(nsHttpConnectionMgr::nsHalfOpenSocket) - NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) - NS_INTERFACE_MAP_ENTRY(nsIOutputStreamCallback) - NS_INTERFACE_MAP_ENTRY(nsITransportEventSink) - NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) - NS_INTERFACE_MAP_ENTRY(nsITimerCallback) - // we have no macro that covers this case. - if (aIID.Equals(NS_GET_IID(nsHttpConnectionMgr::nsHalfOpenSocket)) ) { - AddRef(); - *aInstancePtr = this; - return NS_OK; - } else -NS_INTERFACE_MAP_END +NS_IMPL_ISUPPORTS(nsHttpConnectionMgr::nsHalfOpenSocket, + nsIOutputStreamCallback, + nsITransportEventSink, + nsIInterfaceRequestor, + nsITimerCallback) nsHttpConnectionMgr:: nsHalfOpenSocket::nsHalfOpenSocket(nsConnectionEntry *ent, @@ -3162,16 +3051,14 @@ nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out) mHasConnected = true; // if this is still in the pending list, remove it and dispatch it - index = mEnt->mPendingQ.IndexOf(mTransaction, 0, PendingComparator()); + index = mEnt->mPendingQ.IndexOf(mTransaction); if (index != -1) { MOZ_ASSERT(!mSpeculative, "Speculative Half Open found mTransaction"); - RefPtr temp = mEnt->mPendingQ[index]; + RefPtr temp = mEnt->mPendingQ[index]; mEnt->mPendingQ.RemoveElementAt(index); gHttpHandler->ConnMgr()->AddActiveConn(conn, mEnt); - rv = gHttpHandler->ConnMgr()->DispatchTransaction(mEnt, - temp->mTransaction, - conn); + rv = gHttpHandler->ConnMgr()->DispatchTransaction(mEnt, temp, conn); } else { // this transaction was dispatched off the pending q before all the // sockets established themselves. @@ -3224,21 +3111,8 @@ nsHttpConnectionMgr::nsHalfOpenSocket::OnTransportStatus(nsITransport *trans, { MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); - if (mTransaction) { - if ((trans == mSocketTransport) || - ((trans == mBackupTransport) && (status == NS_NET_STATUS_CONNECTED_TO) && - mEnt->mPendingQ.Contains(mTransaction, PendingComparator()))) { - // Send this status event only if the transaction is still panding, - // i.e. it has not found a free already connected socket. - // Sockets in halfOpen state can only get following events: - // NS_NET_STATUS_RESOLVING_HOST, NS_NET_STATUS_RESOLVED_HOST, - // NS_NET_STATUS_CONNECTING_TO and NS_NET_STATUS_CONNECTED_TO. - // mBackupTransport is only started after - // NS_NET_STATUS_CONNECTING_TO of mSocketTransport, so ignore all - // mBackupTransport events until NS_NET_STATUS_CONNECTED_TO. - mTransaction->OnTransportStatus(trans, status, progress); - } - } + if (mTransaction) + mTransaction->OnTransportStatus(trans, status, progress); MOZ_ASSERT(trans == mSocketTransport || trans == mBackupTransport); if (status == NS_NET_STATUS_CONNECTED_TO) { diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.h b/netwerk/protocol/http/nsHttpConnectionMgr.h index 550deda8bc54..652cdcb57b35 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.h +++ b/netwerk/protocol/http/nsHttpConnectionMgr.h @@ -18,7 +18,6 @@ #include "mozilla/Attributes.h" #include "AlternateServices.h" #include "ARefBase.h" -#include "nsWeakReference.h" #include "nsIObserver.h" #include "nsITimer.h" @@ -31,10 +30,6 @@ class EventTokenBucket; class NullHttpTransaction; struct HttpRetParams; -// 8d411b53-54bc-4a99-8b78-ff125eab1564 -#define NS_HALFOPENSOCKET_IID \ -{ 0x8d411b53, 0x54bc, 0x4a99, {0x8b, 0x78, 0xff, 0x12, 0x5e, 0xab, 0x15, 0x64 }} - //----------------------------------------------------------------------------- // message handlers have this signature @@ -201,7 +196,6 @@ private: virtual ~nsHttpConnectionMgr(); class nsHalfOpenSocket; - class PendingTransactionInfo; // nsConnectionEntry // @@ -216,7 +210,7 @@ private: ~nsConnectionEntry(); RefPtr mConnInfo; - nsTArray > mPendingQ; // pending transaction queue + nsTArray > mPendingQ; // pending transaction queue nsTArray > mActiveConns; // active connections nsTArray > mIdleConns; // idle persistent connections nsTArray mHalfOpens; // half open connections @@ -277,13 +271,11 @@ private: class nsHalfOpenSocket final : public nsIOutputStreamCallback, public nsITransportEventSink, public nsIInterfaceRequestor, - public nsITimerCallback, - public nsSupportsWeakReference + public nsITimerCallback { ~nsHalfOpenSocket(); public: - NS_DECLARE_STATIC_IID_ACCESSOR(NS_HALFOPENSOCKET_IID) NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSIOUTPUTSTREAMCALLBACK NS_DECL_NSITRANSPORTEVENTSINK @@ -364,35 +356,6 @@ private: }; friend class nsHalfOpenSocket; - class PendingTransactionInfo : public ARefBase - { - public: - explicit PendingTransactionInfo(nsHttpTransaction * trans) - : mTransaction(trans) - {} - - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PendingTransactionInfo) - - void PrintDiagnostics(nsCString &log); - public: // meant to be public. - RefPtr mTransaction; - nsWeakPtr mHalfOpen; - nsWeakPtr mActiveConn; - - private: - virtual ~PendingTransactionInfo() {} - }; - friend class PendingTransactionInfo; - - class PendingComparator - { - public: - bool Equals(const PendingTransactionInfo *aPendingTrans, - const nsAHttpTransaction *aTrans) const { - return aPendingTrans->mTransaction.get() == aTrans; - } - }; - //------------------------------------------------------------------------- // NOTE: these members may be accessed from any thread (use mReentrantMonitor) //------------------------------------------------------------------------- @@ -416,7 +379,7 @@ private: bool AtActiveConnectionLimit(nsConnectionEntry *, uint32_t caps); MOZ_MUST_USE nsresult TryDispatchTransaction(nsConnectionEntry *ent, bool onlyReusedConnection, - PendingTransactionInfo *pendingTransInfo); + nsHttpTransaction *trans); MOZ_MUST_USE nsresult DispatchTransaction(nsConnectionEntry *, nsHttpTransaction *, nsHttpConnection *); @@ -432,27 +395,17 @@ private: void ReportProxyTelemetry(nsConnectionEntry *ent); MOZ_MUST_USE nsresult CreateTransport(nsConnectionEntry *, nsAHttpTransaction *, uint32_t, bool, - bool, bool, - PendingTransactionInfo *pendingTransInfo); + bool, bool); void AddActiveConn(nsHttpConnection *, nsConnectionEntry *); void DecrementActiveConnCount(nsHttpConnection *); void StartedConnect(); void RecvdConnect(); - // This function will unclaim the claimed connection or set a halfOpen - // socket to the speculative state if the transaction claiming them ends up - // using another connection. - void ReleaseClaimedSockets(nsConnectionEntry *ent, - PendingTransactionInfo * pendingTransInfo); - - void InsertTransactionSorted(nsTArray > &pendingQ, - PendingTransactionInfo *pendingTransInfo); - nsConnectionEntry *GetOrCreateConnectionEntry(nsHttpConnectionInfo *, bool allowWildCard); MOZ_MUST_USE nsresult MakeNewConnection(nsConnectionEntry *ent, - PendingTransactionInfo *pendingTransInfo); + nsHttpTransaction *trans); // Manage the preferred spdy connection entry for this address nsConnectionEntry *GetSpdyPreferredEnt(nsConnectionEntry *aOriginalEntry); @@ -537,8 +490,6 @@ private: nsCString mLogData; }; -NS_DEFINE_STATIC_IID_ACCESSOR(nsHttpConnectionMgr::nsHalfOpenSocket, NS_HALFOPENSOCKET_IID) - } // namespace net } // namespace mozilla From eb065403f270fa016d78b6181dc932982e64e3ad Mon Sep 17 00:00:00 2001 From: Dylan Roeh Date: Tue, 7 Mar 2017 08:59:10 -0600 Subject: [PATCH 11/57] Bug 1338055 - Prevent crash from destroying PromptService multiple times. r=sebastian --- mobile/android/base/java/org/mozilla/gecko/GeckoApp.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java b/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java index 7af1c65b8d21..d77f7cc144a2 100644 --- a/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java +++ b/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java @@ -2405,8 +2405,10 @@ public abstract class GeckoApp "Update:Install", null); - if (mPromptService != null) + if (mPromptService != null) { mPromptService.destroy(); + mPromptService = null; + } final HealthRecorder rec = mHealthRecorder; mHealthRecorder = null; From 37de7414cbd9036dcb8aae3b42fb4e46c714213a Mon Sep 17 00:00:00 2001 From: Andreas Farre Date: Tue, 28 Feb 2017 18:08:06 +0100 Subject: [PATCH 12/57] Bug 1337392 - Only place cursor at textarea/input end if content was changed. r=smaug MozReview-Commit-ID: CmlN9Pn97Nl --- layout/forms/nsTextControlFrame.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/layout/forms/nsTextControlFrame.cpp b/layout/forms/nsTextControlFrame.cpp index 50936ac64a15..27cd1afc11f8 100644 --- a/layout/forms/nsTextControlFrame.cpp +++ b/layout/forms/nsTextControlFrame.cpp @@ -305,13 +305,18 @@ nsTextControlFrame::EnsureEditorInitialized() // editor. mEditorHasBeenInitialized = true; - nsAutoString val; - txtCtrl->GetTextEditorValue(val, true); - int32_t length = val.Length(); - - // Set the selection to the end of the text field. (bug 1287655) if (weakFrame.IsAlive()) { - SetSelectionEndPoints(length, length); + int32_t position = 0; + + // Set the selection to the end of the text field (bug 1287655), + // but only if the contents has changed (bug 1337392). + if (txtCtrl->ValueChanged()) { + nsAutoString val; + txtCtrl->GetTextEditorValue(val, true); + position = val.Length(); + } + + SetSelectionEndPoints(position, position); } } NS_ENSURE_STATE(weakFrame.IsAlive()); From 85536fcfc4014ab664bee7b12bfb5b80cfeaf2d7 Mon Sep 17 00:00:00 2001 From: Andreas Farre Date: Wed, 1 Mar 2017 14:35:08 +0100 Subject: [PATCH 13/57] Bug 1337392 - Update test cases to match new cursor behavior. r=smaug MozReview-Commit-ID: 4BdZyeqTBAx --- accessible/tests/mochitest/jsat/test_content_text.html | 8 ++++---- accessible/tests/mochitest/states/test_inputs.html | 1 + devtools/client/netmonitor/test/browser_net_resend.js | 3 +++ dom/html/test/test_bug613019.html | 2 ++ editor/libeditor/tests/test_bug850043.html | 1 + layout/base/tests/bug1082486-1.html | 2 -- layout/base/tests/bug646382-1-ref.html | 2 -- layout/base/tests/bug646382-2-ref.html | 2 -- layout/base/tests/bug664087-1-ref.html | 2 -- layout/base/tests/bug664087-2-ref.html | 2 -- layout/base/tests/bug956530-1.html | 3 ++- layout/base/tests/input-maxlength-invalid-change.html | 2 +- layout/base/tests/input-maxlength-ui-invalid-change.html | 2 +- layout/base/tests/input-maxlength-ui-valid-change.html | 2 +- layout/base/tests/input-maxlength-valid-change.html | 2 +- layout/base/tests/input-minlength-invalid-change.html | 2 +- layout/base/tests/input-minlength-ui-invalid-change.html | 2 +- layout/base/tests/input-minlength-ui-valid-change.html | 2 +- layout/base/tests/input-minlength-valid-change.html | 2 +- layout/base/tests/textarea-maxlength-invalid-change.html | 2 +- .../base/tests/textarea-maxlength-ui-invalid-change.html | 2 +- .../base/tests/textarea-maxlength-ui-valid-change.html | 2 +- layout/base/tests/textarea-maxlength-valid-change.html | 2 +- layout/base/tests/textarea-minlength-invalid-change.html | 2 +- .../base/tests/textarea-minlength-ui-invalid-change.html | 2 +- .../base/tests/textarea-minlength-ui-valid-change.html | 2 +- layout/base/tests/textarea-minlength-valid-change.html | 2 +- layout/forms/test/bug287446_subframe.html | 9 ++++----- layout/forms/test/test_bug353539.html | 4 +--- layout/forms/test/test_bug534785.html | 4 ++-- layout/reftests/bugs/240933-1.html | 4 ++-- widget/tests/test_native_key_bindings_mac.html | 4 ---- 32 files changed, 38 insertions(+), 47 deletions(-) diff --git a/accessible/tests/mochitest/jsat/test_content_text.html b/accessible/tests/mochitest/jsat/test_content_text.html index 41e1a260daf6..558b819e9f8c 100644 --- a/accessible/tests/mochitest/jsat/test_content_text.html +++ b/accessible/tests/mochitest/jsat/test_content_text.html @@ -68,16 +68,16 @@ new ExpectedEditState({ editing: true, multiline: true, - atStart: false, - atEnd: true + atStart: true, + atEnd: false }), new ExpectedCursorChange( ['Please refrain from Mayoneggs during this salmonella scare.', {string: 'textarea'}]), - new ExpectedTextSelectionChanged(59, 59) + new ExpectedTextSelectionChanged(0, 0) ], [ContentMessages.activateCurrent(10), - new ExpectedTextCaretChanged(10, 59), + new ExpectedTextCaretChanged(0, 10), new ExpectedEditState({ editing: true, multiline: true, atStart: false, diff --git a/accessible/tests/mochitest/states/test_inputs.html b/accessible/tests/mochitest/states/test_inputs.html index 6114abd0f8ed..20c6deaf8ab6 100644 --- a/accessible/tests/mochitest/states/test_inputs.html +++ b/accessible/tests/mochitest/states/test_inputs.html @@ -107,6 +107,7 @@ // (per spec, min/maxlength validity is affected by interactive edits) var mininp = document.getElementById("minlength"); mininp.focus(); + mininp.setSelectionRange(mininp.value.length, mininp.value.length); synthesizeKey("VK_BACK_SPACE", {}); ok(!mininp.validity.valid, "input should be invalid after interactive edits"); diff --git a/devtools/client/netmonitor/test/browser_net_resend.js b/devtools/client/netmonitor/test/browser_net_resend.js index 6e08dec9be64..d9a5079e0183 100644 --- a/devtools/client/netmonitor/test/browser_net_resend.js +++ b/devtools/client/netmonitor/test/browser_net_resend.js @@ -106,6 +106,7 @@ add_task(function* () { let queryFocus = once(query, "focus", false); // Bug 1195825: Due to some unexplained dark-matter with promise, // focus only works if delayed by one tick. + query.setSelectionRange(query.value.length, query.value.length); executeSoon(() => query.focus()); yield queryFocus; @@ -115,6 +116,7 @@ add_task(function* () { let headers = document.getElementById("custom-headers-value"); let headersFocus = once(headers, "focus", false); + headers.setSelectionRange(headers.value.length, headers.value.length); headers.focus(); yield headersFocus; @@ -129,6 +131,7 @@ add_task(function* () { let postData = document.getElementById("custom-postdata-value"); let postFocus = once(postData, "focus", false); + postData.setSelectionRange(postData.value.length, postData.value.length); postData.focus(); yield postFocus; diff --git a/dom/html/test/test_bug613019.html b/dom/html/test/test_bug613019.html index d4694cef909c..bb28d108a1e8 100644 --- a/dom/html/test/test_bug613019.html +++ b/dom/html/test/test_bug613019.html @@ -27,6 +27,7 @@ function testInteractivityOfMaxLength(elem) { is(elem.value, "Test", "Element has incorrect starting value."); is(elem.validity.tooLong, false, "Element should not be tooLong."); + elem.setSelectionRange(elem.value.length, elem.value.length) elem.focus(); synthesizeKey("VK_BACK_SPACE", {}); @@ -47,6 +48,7 @@ function testInteractivityOfMinLength(elem) { is(elem.value, "Test", "Element has incorrect starting value."); is(elem.validity.tooLong, false, "Element should not be tooShort."); + elem.setSelectionRange(elem.value.length, elem.value.length) elem.focus(); synthesizeKey("e", {}); diff --git a/editor/libeditor/tests/test_bug850043.html b/editor/libeditor/tests/test_bug850043.html index a110c15f994d..b811c86a6fe7 100644 --- a/editor/libeditor/tests/test_bug850043.html +++ b/editor/libeditor/tests/test_bug850043.html @@ -30,6 +30,7 @@ SimpleTest.waitForFocus(() => { getService(SpecialPowers.Ci.nsIFocusManager); let element = document.getElementById("textarea"); + element.setSelectionRange(element.value.length, element.value.length); element.focus(); is(SpecialPowers.unwrap(fm.focusedElement), element, "failed to move focus"); diff --git a/layout/base/tests/bug1082486-1.html b/layout/base/tests/bug1082486-1.html index 634198b0a6a6..de6801f39dbb 100644 --- a/layout/base/tests/bug1082486-1.html +++ b/layout/base/tests/bug1082486-1.html @@ -15,8 +15,6 @@ diff --git a/layout/base/tests/bug646382-1-ref.html b/layout/base/tests/bug646382-1-ref.html index 819b3c0d6494..03acde5b57a5 100644 --- a/layout/base/tests/bug646382-1-ref.html +++ b/layout/base/tests/bug646382-1-ref.html @@ -7,8 +7,6 @@ - diff --git a/layout/forms/test/test_bug353539.html b/layout/forms/test/test_bug353539.html index d0f636b16f3d..6ada2b115d19 100644 --- a/layout/forms/test/test_bug353539.html +++ b/layout/forms/test/test_bug353539.html @@ -27,7 +27,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=353539

 ');
-
   // Output script tags for shell.js, then browser.js, at each level of the
   // test path hierarchy.
   var prepath = "";
-  var i = 0;
-  for (var end = testpathparts.length - 1; i < end; i++) {
+  var scripts = [];
+  var end = testpathparts.length - 1;
+  for (var i = 0; i < end; i++) {
     prepath += testpathparts[i] + "/";
-    outputscripttag(prepath + "shell.js", properties);
-    outputscripttag(prepath + "browser.js", properties);
+
+    scripts.push({src: prepath + "shell.js", module: false});
+    scripts.push({src: prepath + "browser.js", module: false});
   }
 
   // Output the test script itself.
-  outputscripttag(prepath + testpathparts[i], properties);
+  var moduleTest = !!properties.module;
+  scripts.push({src: prepath + testpathparts[end], module: moduleTest});
 
   // Finally output the driver-end script to advance to the next test.
-  outputscripttag('js-test-driver-end.js', properties);
-  return;
-}
+  scripts.push({src: "js-test-driver-end.js", module: false});
 
-function outputscripttag(src, properties)
-{
-  if (!src)
-  {
-    return;
-  }
+  if (!moduleTest) {
+    // XXX bc - the first document.written script is ignored if the protocol
+    // is file:. insert an empty script tag, to work around it.
+    document.write('');
 
-  var s = '
-  
-
-
-
-
-Mozilla Bug 823965
-

- -
-
-
- - diff --git a/dom/devicestorage/test/test_add.html b/dom/devicestorage/test/test_add.html deleted file mode 100644 index a91c8cae4017..000000000000 --- a/dom/devicestorage/test/test_add.html +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - Test for basic sanity of the device storage API - - - - - - -Mozilla Bug 786922 -

- -
-
-
- - diff --git a/dom/devicestorage/test/test_addCorrectType.html b/dom/devicestorage/test/test_addCorrectType.html deleted file mode 100644 index 8b42c21c17d4..000000000000 --- a/dom/devicestorage/test/test_addCorrectType.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - Test for basic sanity of the device storage API - - - - - - -Mozilla Bug 786922 -

- -
-
-
- - diff --git a/dom/devicestorage/test/test_app_permissions.html b/dom/devicestorage/test/test_app_permissions.html deleted file mode 100644 index 339b2c053924..000000000000 --- a/dom/devicestorage/test/test_app_permissions.html +++ /dev/null @@ -1,481 +0,0 @@ - - - - - - Permission test for Device Storage - - - - -Mozilla Bug 805322 -

-
- -
-
-
-
- - diff --git a/dom/devicestorage/test/test_available.html b/dom/devicestorage/test/test_available.html deleted file mode 100644 index 6949a66208e5..000000000000 --- a/dom/devicestorage/test/test_available.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - - Test for the device storage API - - - - - - -Mozilla Bug 834595 -

- -
-
-
- - diff --git a/dom/devicestorage/test/test_basic.html b/dom/devicestorage/test/test_basic.html deleted file mode 100644 index 291093ac0a9f..000000000000 --- a/dom/devicestorage/test/test_basic.html +++ /dev/null @@ -1,141 +0,0 @@ - - - - - Test for the device storage API - - - - - - -Mozilla Bug 717103 -

- -
-
-
- - diff --git a/dom/devicestorage/test/test_dirs.html b/dom/devicestorage/test/test_dirs.html deleted file mode 100644 index 55650a9ee358..000000000000 --- a/dom/devicestorage/test/test_dirs.html +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - Test for the device storage API - - - - - - - Mozilla Bug 886627 - -

- -
-  
-  
- - - diff --git a/dom/devicestorage/test/test_diskSpace.html b/dom/devicestorage/test/test_diskSpace.html deleted file mode 100644 index b5f11d29d7fe..000000000000 --- a/dom/devicestorage/test/test_diskSpace.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - - Test for the device storage API - - - - - - -Mozilla Bug 717103 -

- -
-
-
- - diff --git a/dom/devicestorage/test/test_dotdot.html b/dom/devicestorage/test/test_dotdot.html deleted file mode 100644 index 8dceac81cefb..000000000000 --- a/dom/devicestorage/test/test_dotdot.html +++ /dev/null @@ -1,72 +0,0 @@ - - - - - Test for the device storage API - - - - - - -Mozilla Bug 717103 -

- -
-
-
- - diff --git a/dom/devicestorage/test/test_enumerate.html b/dom/devicestorage/test/test_enumerate.html deleted file mode 100644 index 2381cb00fb28..000000000000 --- a/dom/devicestorage/test/test_enumerate.html +++ /dev/null @@ -1,104 +0,0 @@ - - - - - Test for the device storage API - - - - - - -Mozilla Bug 717103 -

- -
-
-
- - diff --git a/dom/devicestorage/test/test_enumerateMultipleContinue.html b/dom/devicestorage/test/test_enumerateMultipleContinue.html deleted file mode 100644 index 6e46cc33e8c7..000000000000 --- a/dom/devicestorage/test/test_enumerateMultipleContinue.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - - Test for the device storage API - - - - - - -Mozilla Bug 717103 -

- -
-
-
- - diff --git a/dom/devicestorage/test/test_enumerateNoParam.html b/dom/devicestorage/test/test_enumerateNoParam.html deleted file mode 100644 index aa6e4acac002..000000000000 --- a/dom/devicestorage/test/test_enumerateNoParam.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - - Test for the device storage API - - - - - - -Mozilla Bug 717103 -

- -
-
-
- - - diff --git a/dom/devicestorage/test/test_enumerateOptions.html b/dom/devicestorage/test/test_enumerateOptions.html deleted file mode 100644 index b4a7cf3c2a41..000000000000 --- a/dom/devicestorage/test/test_enumerateOptions.html +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - Test for basic sanity of the device storage API - - - - - - -Mozilla Bug 717103 -

- -
-
-
- - diff --git a/dom/devicestorage/test/test_freeSpace.html b/dom/devicestorage/test/test_freeSpace.html deleted file mode 100644 index 73c8e3cc089d..000000000000 --- a/dom/devicestorage/test/test_freeSpace.html +++ /dev/null @@ -1,62 +0,0 @@ - - - - - Test for the device storage API - - - - - - -Mozilla Bug 717103 -

- -
-
-
- - diff --git a/dom/devicestorage/test/test_fs_app_permissions.html b/dom/devicestorage/test/test_fs_app_permissions.html deleted file mode 100644 index 0c6244bcad15..000000000000 --- a/dom/devicestorage/test/test_fs_app_permissions.html +++ /dev/null @@ -1,598 +0,0 @@ - - - - - - Permission test of FileSystem API for Device Storage - - - - -Mozilla Bug 910412 -

-
- -
-
-
-
- - diff --git a/dom/devicestorage/test/test_fs_appendFile.html b/dom/devicestorage/test/test_fs_appendFile.html deleted file mode 100644 index 3cb6c3954740..000000000000 --- a/dom/devicestorage/test/test_fs_appendFile.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - Test for basic sanity of the device storage API - - - - - - -Mozilla Bug 855952 -

- -
-
-
- - diff --git a/dom/devicestorage/test/test_fs_basic.html b/dom/devicestorage/test/test_fs_basic.html deleted file mode 100644 index a665af4d9381..000000000000 --- a/dom/devicestorage/test/test_fs_basic.html +++ /dev/null @@ -1,72 +0,0 @@ - - - - - Test for the FileSystem API for device storage - - - - - - -Mozilla Bug 910412 -

- -
-
-
- - diff --git a/dom/devicestorage/test/test_fs_createDirectory.html b/dom/devicestorage/test/test_fs_createDirectory.html deleted file mode 100644 index 3b573b086f42..000000000000 --- a/dom/devicestorage/test/test_fs_createDirectory.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - Test createDirectory of the FileSystem API for device storage - - - - - - -Mozilla Bug 910412 -

- -
-
-
- - diff --git a/dom/devicestorage/test/test_fs_createFile.html b/dom/devicestorage/test/test_fs_createFile.html deleted file mode 100644 index 9e5a2b5cf1f8..000000000000 --- a/dom/devicestorage/test/test_fs_createFile.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - - Test createDirectory of the FileSystem API for device storage - - - - - - -Mozilla Bug 910412 -

- -
-
-
- - diff --git a/dom/devicestorage/test/test_fs_get.html b/dom/devicestorage/test/test_fs_get.html deleted file mode 100644 index 287f57e1ef68..000000000000 --- a/dom/devicestorage/test/test_fs_get.html +++ /dev/null @@ -1,206 +0,0 @@ - - - - - Test Directory#get of the FileSystem API for device storage - - - - - - -Mozilla Bug 910412 -

- -
-
-
- - diff --git a/dom/devicestorage/test/test_fs_getFilesAndDirectories.html b/dom/devicestorage/test/test_fs_getFilesAndDirectories.html deleted file mode 100644 index 9dd88bb51581..000000000000 --- a/dom/devicestorage/test/test_fs_getFilesAndDirectories.html +++ /dev/null @@ -1,98 +0,0 @@ - - - - - Test Directory#getFilesAndDirectories of the FileSystem API for device storage - - - - - - -Mozilla Bug XXX -

- -
-
-
- - diff --git a/dom/devicestorage/test/test_fs_remove.html b/dom/devicestorage/test/test_fs_remove.html deleted file mode 100644 index aa168de05872..000000000000 --- a/dom/devicestorage/test/test_fs_remove.html +++ /dev/null @@ -1,176 +0,0 @@ - - - - - Test Directory#remove and #removeDeep of the FileSystem API for device storage - - - - - - -Mozilla Bug 934368 -

- -
-
-
- - diff --git a/dom/devicestorage/test/test_lastModificationFilter.html b/dom/devicestorage/test/test_lastModificationFilter.html deleted file mode 100644 index 00391495e1f8..000000000000 --- a/dom/devicestorage/test/test_lastModificationFilter.html +++ /dev/null @@ -1,176 +0,0 @@ - - - - - Test for the device storage API - - - - - - -Mozilla Bug 717103 -

- -
-
-
- - diff --git a/dom/devicestorage/test/test_overrideDir.html b/dom/devicestorage/test/test_overrideDir.html deleted file mode 100644 index 0a9d03c7e126..000000000000 --- a/dom/devicestorage/test/test_overrideDir.html +++ /dev/null @@ -1,163 +0,0 @@ - - - - - Test for the device storage API - - - - - - -Mozilla Bug 717103 -

- -
-
-
- - diff --git a/dom/devicestorage/test/test_overwrite.html b/dom/devicestorage/test/test_overwrite.html deleted file mode 100644 index 8e6d950bf0d4..000000000000 --- a/dom/devicestorage/test/test_overwrite.html +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - Test for basic sanity of the device storage API - - - - - - -Mozilla Bug 717103 -

- -
-
-
- - diff --git a/dom/devicestorage/test/test_sanity.html b/dom/devicestorage/test/test_sanity.html deleted file mode 100644 index 4104befba124..000000000000 --- a/dom/devicestorage/test/test_sanity.html +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - Test for basic sanity of the device storage API - - - - - - -Mozilla Bug 717103 -

- -
-
-
- - diff --git a/dom/devicestorage/test/test_usedSpace.html b/dom/devicestorage/test/test_usedSpace.html deleted file mode 100644 index 451326231078..000000000000 --- a/dom/devicestorage/test/test_usedSpace.html +++ /dev/null @@ -1,63 +0,0 @@ - - - - - Test for the device storage API - - - - - - -Mozilla Bug 717103 -

- -
-
-
- - - diff --git a/dom/devicestorage/test/test_watch.html b/dom/devicestorage/test/test_watch.html deleted file mode 100644 index adfca0801501..000000000000 --- a/dom/devicestorage/test/test_watch.html +++ /dev/null @@ -1,77 +0,0 @@ - - - - - Test for the device storage API - - - - - - -Mozilla Bug 717103 -

- -
-
-
- - diff --git a/dom/devicestorage/test/test_watchOther.html b/dom/devicestorage/test/test_watchOther.html deleted file mode 100644 index c729626e62a9..000000000000 --- a/dom/devicestorage/test/test_watchOther.html +++ /dev/null @@ -1,86 +0,0 @@ - - - - - Test for the device storage API - - - - - - -Mozilla Bug 717103 -

- -
-
-
- - diff --git a/dom/filesystem/DeviceStorageFileSystem.cpp b/dom/filesystem/DeviceStorageFileSystem.cpp index f7aeb303ec71..86fd56d579ef 100644 --- a/dom/filesystem/DeviceStorageFileSystem.cpp +++ b/dom/filesystem/DeviceStorageFileSystem.cpp @@ -6,7 +6,6 @@ #include "mozilla/dom/DeviceStorageFileSystem.h" -#include "DeviceStorage.h" #include "mozilla/Preferences.h" #include "mozilla/dom/Directory.h" #include "mozilla/dom/File.h" @@ -15,7 +14,6 @@ #include "mozilla/Unused.h" #include "nsCOMPtr.h" #include "nsDebug.h" -#include "nsDeviceStorage.h" #include "nsIFile.h" #include "nsPIDOMWindow.h" #include "nsGlobalWindow.h" @@ -42,34 +40,6 @@ DeviceStorageFileSystem::DeviceStorageFileSystem(const nsAString& aStorageType, } else { AssertIsOnBackgroundThread(); } - - // Get the permission name required to access the file system. - DebugOnly rv = - DeviceStorageTypeChecker::GetPermissionForType(mStorageType, mPermission); - NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "GetPermissionForType failed"); - - // Get the local path of the file system root. - nsCOMPtr rootFile; - DeviceStorageFile::GetRootDirectoryForType(aStorageType, - aStorageName, - getter_AddRefs(rootFile)); - - Unused << - NS_WARN_IF(!rootFile || - NS_FAILED(rootFile->GetPath(mLocalOrDeviceStorageRootPath))); - - if (!XRE_IsParentProcess()) { - return; - } - - // DeviceStorageTypeChecker is a singleton object and must be initialized on - // the main thread. We initialize it here so that we can use it on the worker - // thread. - if (NS_IsMainThread()) { - DebugOnly typeChecker = - DeviceStorageTypeChecker::CreateOrGet(); - MOZ_ASSERT(typeChecker); - } } DeviceStorageFileSystem::~DeviceStorageFileSystem() diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index d86d409fd12d..aa63e1431d31 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -175,7 +175,6 @@ #endif #include "mozilla/dom/File.h" -#include "mozilla/dom/devicestorage/DeviceStorageRequestChild.h" #include "mozilla/dom/PPresentationChild.h" #include "mozilla/dom/PresentationIPCService.h" #include "mozilla/ipc/InputStreamUtils.h" @@ -188,7 +187,6 @@ #include "URIUtils.h" #include "nsContentUtils.h" #include "nsIPrincipal.h" -#include "nsDeviceStorage.h" #include "DomainPolicy.h" #include "mozilla/dom/ipc/StructuredCloneData.h" #include "mozilla/dom/time/DateCacheCleaner.h" @@ -211,7 +209,6 @@ using namespace mozilla; using namespace mozilla::docshell; -using namespace mozilla::dom::devicestorage; using namespace mozilla::dom::ipc; using namespace mozilla::dom::workers; using namespace mozilla::media; @@ -1679,19 +1676,6 @@ ContentChild::RecvPTestShellConstructor(PTestShellChild* actor) return IPC_OK(); } -PDeviceStorageRequestChild* -ContentChild::AllocPDeviceStorageRequestChild(const DeviceStorageParams& aParams) -{ - return new DeviceStorageRequestChild(); -} - -bool -ContentChild::DeallocPDeviceStorageRequestChild(PDeviceStorageRequestChild* aDeviceStorage) -{ - delete aDeviceStorage; - return true; -} - PNeckoChild* ContentChild::AllocPNeckoChild() { @@ -2371,28 +2355,6 @@ ContentChild::RecvLastPrivateDocShellDestroyed() return IPC_OK(); } -mozilla::ipc::IPCResult -ContentChild::RecvFilePathUpdate(const nsString& aStorageType, - const nsString& aStorageName, - const nsString& aPath, - const nsCString& aReason) -{ - if (nsDOMDeviceStorage::InstanceCount() == 0) { - // No device storage instances in this process. Don't try and - // and create a DeviceStorageFile since it will fail. - - return IPC_OK(); - } - - RefPtr dsf = new DeviceStorageFile(aStorageType, aStorageName, aPath); - - nsString reason; - CopyASCIItoUTF16(aReason, reason); - nsCOMPtr obs = mozilla::services::GetObserverService(); - obs->NotifyObservers(dsf, "file-watcher-update", reason.get()); - return IPC_OK(); -} - mozilla::ipc::IPCResult ContentChild::RecvNotifyProcessPriorityChanged( const hal::ProcessPriority& aPriority) diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index 5444870c8947..6690cb2ec8ef 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -177,12 +177,6 @@ public: virtual bool DeallocPBrowserChild(PBrowserChild*) override; - virtual PDeviceStorageRequestChild* - AllocPDeviceStorageRequestChild(const DeviceStorageParams&) override; - - virtual bool - DeallocPDeviceStorageRequestChild(PDeviceStorageRequestChild*) override; - virtual PBlobChild* AllocPBlobChild(const BlobConstructorParams& aParams) override; @@ -401,11 +395,6 @@ public: virtual mozilla::ipc::IPCResult RecvLastPrivateDocShellDestroyed() override; - virtual mozilla::ipc::IPCResult RecvFilePathUpdate(const nsString& aStorageType, - const nsString& aStorageName, - const nsString& aPath, - const nsCString& aReason) override; - virtual mozilla::ipc::IPCResult RecvNotifyProcessPriorityChanged(const hal::ProcessPriority& aPriority) override; diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index fb397b5e945d..b0c8f8c674d8 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -25,7 +25,6 @@ #include "mozilla/a11y/PDocAccessible.h" #include "AudioChannelService.h" -#include "DeviceStorageStatics.h" #include "GMPServiceParent.h" #include "HandlerServiceParent.h" #include "IHistory.h" @@ -53,7 +52,6 @@ #include "mozilla/dom/ServiceWorkerRegistrar.h" #include "mozilla/dom/Storage.h" #include "mozilla/dom/StorageIPC.h" -#include "mozilla/dom/devicestorage/DeviceStorageRequestParent.h" #include "mozilla/dom/power/PowerManagerService.h" #include "mozilla/dom/Permissions.h" #include "mozilla/dom/PresentationParent.h" @@ -270,7 +268,6 @@ using base::KillProcess; #ifdef MOZ_CRASHREPORTER using namespace CrashReporter; #endif -using namespace mozilla::dom::devicestorage; using namespace mozilla::dom::power; using namespace mozilla::media; using namespace mozilla::embedding; @@ -2800,12 +2797,6 @@ ContentParent::Observe(nsISupports* aSubject, else if (!strcmp(aTopic, "last-pb-context-exited")) { Unused << SendLastPrivateDocShellDestroyed(); } - else if (!strcmp(aTopic, "file-watcher-update")) { - nsCString creason; - CopyUTF16toUTF8(aData, creason); - DeviceStorageFile* file = static_cast(aSubject); - Unused << SendFilePathUpdate(file->mStorageType, file->mStorageName, file->mPath, creason); - } #ifdef ACCESSIBILITY else if (aData && !strcmp(aTopic, "a11y-init-or-shutdown")) { if (*aData == '1') { @@ -2889,22 +2880,6 @@ ContentParent::DeallocPBrowserParent(PBrowserParent* frame) return nsIContentParent::DeallocPBrowserParent(frame); } -PDeviceStorageRequestParent* -ContentParent::AllocPDeviceStorageRequestParent(const DeviceStorageParams& aParams) -{ - RefPtr result = new DeviceStorageRequestParent(aParams); - result->Dispatch(); - return result.forget().take(); -} - -bool -ContentParent::DeallocPDeviceStorageRequestParent(PDeviceStorageRequestParent* doomed) -{ - DeviceStorageRequestParent *parent = static_cast(doomed); - NS_RELEASE(parent); - return true; -} - PBlobParent* ContentParent::AllocPBlobParent(const BlobConstructorParams& aParams) { @@ -3719,25 +3694,6 @@ ContentParent::RecvAsyncMessage(const nsString& aMsg, aData); } -mozilla::ipc::IPCResult -ContentParent::RecvFilePathUpdateNotify(const nsString& aType, - const nsString& aStorageName, - const nsString& aFilePath, - const nsCString& aReason) -{ - RefPtr dsf = new DeviceStorageFile(aType, - aStorageName, - aFilePath); - - nsCOMPtr obs = mozilla::services::GetObserverService(); - if (!obs) { - return IPC_FAIL_NO_REASON(this); - } - obs->NotifyObservers(dsf, "file-watcher-update", - NS_ConvertASCIItoUTF16(aReason).get()); - return IPC_OK(); -} - static int32_t AddGeolocationListener(nsIDOMGeoPositionCallback* watcher, nsIDOMGeoPositionErrorCallback* errorCallBack, @@ -4770,25 +4726,6 @@ ContentParent::RecvEndDriverCrashGuard(const uint32_t& aGuardType) return IPC_OK(); } -mozilla::ipc::IPCResult -ContentParent::RecvGetDeviceStorageLocation(const nsString& aType, - nsString* aPath) -{ -#ifdef MOZ_WIDGET_ANDROID - mozilla::AndroidBridge::GetExternalPublicDirectory(aType, *aPath); - return IPC_OK(); -#else - return IPC_FAIL_NO_REASON(this); -#endif -} - -mozilla::ipc::IPCResult -ContentParent::RecvGetDeviceStorageLocations(DeviceStorageLocationInfo* info) -{ - DeviceStorageStatics::GetDeviceStorageLocationsForIPC(info); - return IPC_OK(); -} - mozilla::ipc::IPCResult ContentParent::RecvGetAndroidSystemInfo(AndroidSystemInfo* aInfo) { diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index 49d867731a70..3e45cc32c4f1 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -782,12 +782,6 @@ private: virtual bool DeallocPBrowserParent(PBrowserParent* frame) override; - virtual PDeviceStorageRequestParent* - AllocPDeviceStorageRequestParent(const DeviceStorageParams&) override; - - virtual bool - DeallocPDeviceStorageRequestParent(PDeviceStorageRequestParent*) override; - virtual PBlobParent* AllocPBlobParent(const BlobConstructorParams& aParams) override; @@ -973,11 +967,6 @@ private: const IPC::Principal& aPrincipal, const ClonedMessageData& aData) override; - virtual mozilla::ipc::IPCResult RecvFilePathUpdateNotify(const nsString& aType, - const nsString& aStorageName, - const nsString& aFilePath, - const nsCString& aReason) override; - virtual mozilla::ipc::IPCResult RecvAddGeolocationListener(const IPC::Principal& aPrincipal, const bool& aHighAccuracy) override; virtual mozilla::ipc::IPCResult RecvRemoveGeolocationListener() override; @@ -1074,11 +1063,6 @@ private: void StartProfiler(nsIProfilerStartParams* aParams); - virtual mozilla::ipc::IPCResult RecvGetDeviceStorageLocation(const nsString& aType, - nsString* aPath) override; - - virtual mozilla::ipc::IPCResult RecvGetDeviceStorageLocations(DeviceStorageLocationInfo* info) override; - virtual mozilla::ipc::IPCResult RecvGetAndroidSystemInfo(AndroidSystemInfo* aInfo) override; virtual mozilla::ipc::IPCResult RecvNotifyBenchmarkResult(const nsString& aCodecName, diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index cb79b7f74c1e..9d0bcd524612 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -14,7 +14,6 @@ include protocol PCycleCollectWithLogs; include protocol PPSMContentDownloader; include protocol PExternalHelperApp; include protocol PHandlerService; -include protocol PDeviceStorageRequest; include protocol PFileDescriptorSet; include protocol PHal; include protocol PHeapSnapshotTempFileHelper; @@ -124,120 +123,6 @@ struct FontFamilyListEntry { uint8_t entryType; }; -struct DeviceStorageFreeSpaceParams -{ - nsString type; - nsString storageName; -}; - -struct DeviceStorageUsedSpaceParams -{ - nsString type; - nsString storageName; -}; - -struct DeviceStorageAvailableParams -{ - nsString type; - nsString storageName; -}; - -struct DeviceStorageStatusParams -{ - nsString type; - nsString storageName; -}; - -struct DeviceStorageFormatParams -{ - nsString type; - nsString storageName; -}; - -struct DeviceStorageMountParams -{ - nsString type; - nsString storageName; -}; - -struct DeviceStorageUnmountParams -{ - nsString type; - nsString storageName; -}; - -struct DeviceStorageAddParams -{ - nsString type; - nsString storageName; - nsString relpath; - PBlob blob; -}; - -struct DeviceStorageAppendParams -{ - nsString type; - nsString storageName; - nsString relpath; - PBlob blob; -}; - -struct DeviceStorageCreateFdParams -{ - nsString type; - nsString storageName; - nsString relpath; -}; - -struct DeviceStorageGetParams -{ - nsString type; - nsString storageName; - nsString rootDir; - nsString relpath; -}; - -struct DeviceStorageDeleteParams -{ - nsString type; - nsString storageName; - nsString relpath; -}; - -struct DeviceStorageEnumerationParams -{ - nsString type; - nsString storageName; - nsString rootdir; - uint64_t since; -}; - -union DeviceStorageParams -{ - DeviceStorageAddParams; - DeviceStorageAppendParams; - DeviceStorageCreateFdParams; - DeviceStorageGetParams; - DeviceStorageDeleteParams; - DeviceStorageEnumerationParams; - DeviceStorageFreeSpaceParams; - DeviceStorageUsedSpaceParams; - DeviceStorageAvailableParams; - DeviceStorageStatusParams; - DeviceStorageFormatParams; - DeviceStorageMountParams; - DeviceStorageUnmountParams; -}; - -struct DeviceStorageLocationInfo { - nsString music; - nsString pictures; - nsString videos; - nsString sdcard; - nsString apps; - nsString crashes; -}; - union PrefValue { nsCString; int32_t; @@ -385,7 +270,6 @@ nested(upto inside_cpow) sync protocol PContent manages PBrowser; manages PContentPermissionRequest; manages PCycleCollectWithLogs; - manages PDeviceStorageRequest; manages PPSMContentDownloader; manages PExternalHelperApp; manages PFileDescriptorSet; @@ -564,9 +448,6 @@ child: // Notify child that last-pb-context-exited notification was observed async LastPrivateDocShellDestroyed(); - async FilePathUpdate(nsString storageType, nsString storageName, nsString filepath, - nsCString reasons); - async NotifyProcessPriorityChanged(ProcessPriority priority); async MinimizeMemoryUsage(); @@ -750,7 +631,6 @@ parent: async PJavaScript(); async PRemoteSpellcheckEngine(); - async PDeviceStorageRequest(DeviceStorageParams params); async InitCrashReporter(Shmem shmem, NativeThreadId tid); @@ -936,11 +816,6 @@ parent: async AudioChannelChangeDefVolChannel(int32_t aChannel, bool aHidden); - async FilePathUpdateNotify(nsString aType, - nsString aStorageName, - nsString aFilepath, - nsCString aReason); - sync KeywordToURI(nsCString keyword) returns (nsString providerName, OptionalInputStreamParams postData, OptionalURIParams uri); @@ -1125,12 +1000,6 @@ parent: OriginAttributes aOpenerOriginAttributes, float aFullZoom); - sync GetDeviceStorageLocation(nsString type) - returns (nsString path); - - sync GetDeviceStorageLocations() - returns (DeviceStorageLocationInfo info); - sync GetAndroidSystemInfo() returns (AndroidSystemInfo info); diff --git a/dom/ipc/moz.build b/dom/ipc/moz.build index 46bac5aa9ceb..4d1a1993b5ca 100644 --- a/dom/ipc/moz.build +++ b/dom/ipc/moz.build @@ -123,7 +123,6 @@ LOCAL_INCLUDES += [ '/chrome', '/docshell/base', '/dom/base', - '/dom/devicestorage', '/dom/events', '/dom/filesystem', '/dom/geolocation', diff --git a/dom/moz.build b/dom/moz.build index fe9d7e520316..51b88e0d7172 100644 --- a/dom/moz.build +++ b/dom/moz.build @@ -50,7 +50,6 @@ DIRS += [ 'canvas', 'commandhandler', 'crypto', - 'devicestorage', 'encoding', 'events', 'fetch', diff --git a/dom/tests/mochitest/general/test_interfaces.js b/dom/tests/mochitest/general/test_interfaces.js index 5ff606b6e62f..cc6646b04b55 100644 --- a/dom/tests/mochitest/general/test_interfaces.js +++ b/dom/tests/mochitest/general/test_interfaces.js @@ -281,10 +281,6 @@ var interfaceNamesInGlobalScope = "DeviceOrientationEvent", // IMPORTANT: Do not change this list without review from a DOM peer! "DeviceProximityEvent", -// IMPORTANT: Do not change this list without review from a DOM peer! - { name: "DeviceStorageAreaListener", desktop: false}, -// IMPORTANT: Do not change this list without review from a DOM peer! - { name: "DeviceStorage", desktop: false}, // IMPORTANT: Do not change this list without review from a DOM peer! "Directory", // IMPORTANT: Do not change this list without review from a DOM peer! diff --git a/dom/webidl/DeviceStorage.webidl b/dom/webidl/DeviceStorage.webidl deleted file mode 100644 index 30ef6bd7062b..000000000000 --- a/dom/webidl/DeviceStorage.webidl +++ /dev/null @@ -1,95 +0,0 @@ -/* -*- Mode: IDL; 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/. */ - -dictionary DeviceStorageEnumerationParameters { - Date since; -}; - -[Pref="device.storage.enabled"] -interface DeviceStorage : EventTarget { - attribute EventHandler onchange; - - [Throws] - DOMRequest? add(Blob? aBlob); - [Throws] - DOMRequest? addNamed(Blob? aBlob, DOMString aName); - - /** - * Append data to a given file. - * If the file doesn't exist, a "NotFoundError" event will be dispatched. - * In the same time, it is a request.onerror case. - * If the file exists, it will be opened with the following permission: - * "PR_WRONLY|PR_CREATE_FILE|PR_APPEND". - * The function will return null when blob file is null and other unexpected situations. - * @parameter aBlob: A Blob object representing the data to append - * @parameter aName: A string representing the full name (path + file name) of the file - * to append data to. - */ - [Throws] - DOMRequest? appendNamed(Blob? aBlob, DOMString aName); - - [Throws] - DOMRequest get(DOMString aName); - [Throws] - DOMRequest getEditable(DOMString aName); - [Throws] - DOMRequest delete(DOMString aName); - - [Throws] - DOMCursor enumerate(optional DeviceStorageEnumerationParameters options); - [Throws] - DOMCursor enumerate(DOMString path, - optional DeviceStorageEnumerationParameters options); - [Throws] - DOMCursor enumerateEditable(optional DeviceStorageEnumerationParameters options); - [Throws] - DOMCursor enumerateEditable(DOMString path, - optional DeviceStorageEnumerationParameters options); - - [Throws] - DOMRequest freeSpace(); - [Throws] - DOMRequest usedSpace(); - [Throws] - DOMRequest available(); - [Throws] - DOMRequest storageStatus(); - [Throws] - DOMRequest format(); - [Throws] - DOMRequest mount(); - [Throws] - DOMRequest unmount(); - - // Note that the storageName is just a name (like sdcard), and doesn't - // include any path information. - readonly attribute DOMString storageName; - - // Indicates if the storage area denoted by storageName is capable of - // being mounted and unmounted. - readonly attribute boolean canBeMounted; - - // Indicates if the storage area denoted by storageName is capable of - // being shared and unshared. - readonly attribute boolean canBeShared; - - // Indicates if the storage area denoted by storageName is capable of - // being formatted. - readonly attribute boolean canBeFormatted; - - // Determines if this storage area is the one which will be used by default - // for storing new files. - readonly attribute boolean default; - - // Indicates if the storage area denoted by storageName is removable - readonly attribute boolean isRemovable; - - // True if the storage area is close to being full - readonly attribute boolean lowDiskSpace; - - [NewObject] - // XXXbz what type does this really return? - Promise getRoot(); -}; diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index 65cbd4d34ee1..c6ab196fb6ad 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -484,7 +484,6 @@ WEBIDL_FILES = [ 'DelayNode.webidl', 'DesktopNotification.webidl', 'DeviceMotionEvent.webidl', - 'DeviceStorage.webidl', 'Directory.webidl', 'Document.webidl', 'DocumentFragment.webidl', diff --git a/ipc/ipdl/sync-messages.ini b/ipc/ipdl/sync-messages.ini index 2500b04c053a..14d6add168d2 100644 --- a/ipc/ipdl/sync-messages.ini +++ b/ipc/ipdl/sync-messages.ini @@ -819,10 +819,6 @@ description = description = [PContent::CreateWindow] description = -[PContent::GetDeviceStorageLocation] -description = -[PContent::GetDeviceStorageLocations] -description = [PContent::GetAndroidSystemInfo] description = [PContent::UngrabPointer] diff --git a/layout/build/nsLayoutStatics.cpp b/layout/build/nsLayoutStatics.cpp index 157a0dc5ae3c..3247ed29bb8e 100644 --- a/layout/build/nsLayoutStatics.cpp +++ b/layout/build/nsLayoutStatics.cpp @@ -129,7 +129,6 @@ using namespace mozilla::system; #include "TouchManager.h" #include "MediaDecoder.h" #include "MediaPrefs.h" -#include "mozilla/dom/devicestorage/DeviceStorageStatics.h" #include "mozilla/ServoBindings.h" #include "mozilla/StaticPresData.h" #include "mozilla/dom/WebIDLGlobalNameHash.h" @@ -310,8 +309,6 @@ nsLayoutStatics::Initialize() PromiseDebugging::Init(); - mozilla::dom::devicestorage::DeviceStorageStatics::Initialize(); - mozilla::dom::WebCryptoThreadPool::Initialize(); #ifdef MOZ_STYLO diff --git a/mobile/android/components/ContentPermissionPrompt.js b/mobile/android/components/ContentPermissionPrompt.js index b5445549d34e..a28683784213 100644 --- a/mobile/android/components/ContentPermissionPrompt.js +++ b/mobile/android/components/ContentPermissionPrompt.js @@ -13,10 +13,6 @@ Cu.import("resource://gre/modules/Services.jsm"); const kEntities = { "contacts": "contacts", "desktop-notification": "desktopNotification2", - "device-storage:music": "deviceStorageMusic", - "device-storage:pictures": "deviceStoragePictures", - "device-storage:sdcard": "deviceStorageSdcard", - "device-storage:videos": "deviceStorageVideos", "geolocation": "geolocation", "flyweb-publish-server": "flyWebPublishServer", }; diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java index 905ffa784d8f..217134d5a3e5 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java @@ -2189,44 +2189,6 @@ public class GeckoAppShell return connection.getContentType(); } - /** - * Retrieve the absolute path of an external storage directory. - * - * @param type The type of directory to return - * @return Absolute path of the specified directory or null on failure - */ - @WrapForJNI(calledFrom = "gecko") - private static String getExternalPublicDirectory(final String type) { - final String state = Environment.getExternalStorageState(); - if (!Environment.MEDIA_MOUNTED.equals(state) && - !Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { - // External storage is not available. - return null; - } - - if ("sdcard".equals(type)) { - // SD card has a separate path. - return Environment.getExternalStorageDirectory().getAbsolutePath(); - } - - final String systemType; - if ("downloads".equals(type)) { - systemType = Environment.DIRECTORY_DOWNLOADS; - } else if ("pictures".equals(type)) { - systemType = Environment.DIRECTORY_PICTURES; - } else if ("videos".equals(type)) { - systemType = Environment.DIRECTORY_MOVIES; - } else if ("music".equals(type)) { - systemType = Environment.DIRECTORY_MUSIC; - } else if ("apps".equals(type)) { - File appInternalStorageDirectory = getApplicationContext().getFilesDir(); - return new File(appInternalStorageDirectory, "mozilla").getAbsolutePath(); - } else { - return null; - } - return Environment.getExternalStoragePublicDirectory(systemType).getAbsolutePath(); - } - @WrapForJNI(calledFrom = "gecko") private static int getMaxTouchPoints() { PackageManager pm = getApplicationContext().getPackageManager(); diff --git a/mobile/android/locales/en-US/chrome/browser.properties b/mobile/android/locales/en-US/chrome/browser.properties index b39e217ef3dd..8d4312708e82 100644 --- a/mobile/android/locales/en-US/chrome/browser.properties +++ b/mobile/android/locales/en-US/chrome/browser.properties @@ -145,35 +145,6 @@ flyWebPublishServer.publishServer=Publish Server imageblocking.downloadedImage=Image unblocked imageblocking.showAllImages=Show All -# Device Storage API -deviceStorageMusic.allow=Allow -deviceStorageMusic.dontAllow=Don't allow -deviceStorageMusic.ask=Allow %S access to your music? -# LOCALIZATION NOTE (deviceStorageMusic.dontAskAgain): This label appears next to a -# checkbox to indicate whether or not the user wants to make a permanent decision. -deviceStorageMusic.dontAskAgain=Don't ask again for this site - -deviceStoragePictures.allow=Allow -deviceStoragePictures.dontAllow=Don't allow -deviceStoragePictures.ask=Allow %S access to your images? -# LOCALIZATION NOTE (deviceStoragePictures.dontAskAgain): This label appears next to a -# checkbox to indicate whether or not the user wants to make a permanent decision. -deviceStoragePictures.dontAskAgain=Don't ask again for this site - -deviceStorageSdcard.allow=Allow -deviceStorageSdcard.dontAllow=Don't allow -deviceStorageSdcard.ask=Allow %S access to external storage? -# LOCALIZATION NOTE (deviceStorageSdcard.dontAskAgain): This label appears next to a -# checkbox to indicate whether or not the user wants to make a permanent decision. -deviceStorageSdcard.dontAskAgain=Don't ask again for this site - -deviceStorageVideos.allow=Allow -deviceStorageVideos.dontAllow=Don't allow -deviceStorageVideos.ask=Allow %S access to your videos? -# LOCALIZATION NOTE (deviceStorageVideos.dontAskAgain): This label appears next to a -# checkbox to indicate whether or not the user wants to make a permanent decision. -deviceStorageVideos.dontAskAgain=Don't ask again for this site - # New Tab Popup # LOCALIZATION NOTE (newtabpopup, newprivatetabpopup): Semicolon-separated list of plural forms. # See: http://developer.mozilla.org/en/docs/Localization_and_Plurals diff --git a/netwerk/test/mochitests/signed_web_packaged_app.sjs b/netwerk/test/mochitests/signed_web_packaged_app.sjs index d407a47e3ffa..6bcac6ffd45f 100644 --- a/netwerk/test/mochitests/signed_web_packaged_app.sjs +++ b/netwerk/test/mochitests/signed_web_packaged_app.sjs @@ -40,9 +40,6 @@ Content-Type: application/x-web-app-manifest+json\r { "systemXHR": { "description": "Needed to download stuff" - }, - "devicestorage:pictures": { - "description": "Need to load pictures" } } ], diff --git a/toolkit/components/jsdownloads/src/DownloadIntegration.jsm b/toolkit/components/jsdownloads/src/DownloadIntegration.jsm index 8d9f1f20e1c7..b0520780e474 100644 --- a/toolkit/components/jsdownloads/src/DownloadIntegration.jsm +++ b/toolkit/components/jsdownloads/src/DownloadIntegration.jsm @@ -273,43 +273,6 @@ this.DownloadIntegration = { yield new DownloadAutoSaveView(list, this._store).initialize(); }), -#ifdef MOZ_WIDGET_GONK - /** - * Finds the default download directory which can be either in the - * internal storage or on the sdcard. - * - * @return {Promise} - * @resolves The downloads directory string path. - */ - _getDefaultDownloadDirectory: Task.async(function* () { - let directoryPath; - let win = Services.wm.getMostRecentWindow("navigator:browser"); - let storages = win.navigator.getDeviceStorages("sdcard"); - let preferredStorageName; - // Use the first one or the default storage. - storages.forEach((aStorage) => { - if (aStorage.default || !preferredStorageName) { - preferredStorageName = aStorage.storageName; - } - }); - - // Now get the path for this storage area. - if (preferredStorageName) { - let volume = volumeService.getVolumeByName(preferredStorageName); - if (volume && volume.state === Ci.nsIVolume.STATE_MOUNTED){ - directoryPath = OS.Path.join(volume.mountPoint, "downloads"); - yield OS.File.makeDir(directoryPath, { ignoreExisting: true }); - } - } - if (directoryPath) { - return directoryPath; - } else { - throw new Components.Exception("No suitable storage for downloads.", - Cr.NS_ERROR_FILE_UNRECOGNIZED_PATH); - } - }), -#endif - /** * Determines if a Download object from the list of persistent downloads * should be saved into a file, so that it can be restored across sessions. @@ -382,8 +345,6 @@ this.DownloadIntegration = { throw new Components.Exception("DOWNLOADS_DIRECTORY is not set.", Cr.NS_ERROR_FILE_UNRECOGNIZED_PATH); } -#elifdef MOZ_WIDGET_GONK - directoryPath = this._getDefaultDownloadDirectory(); #else // For Linux, use XDG download dir, with a fallback to Home/Downloads // if the XDG user dirs are disabled. @@ -410,9 +371,6 @@ this.DownloadIntegration = { */ getPreferredDownloadsDirectory: Task.async(function* () { let directoryPath = null; -#ifdef MOZ_WIDGET_GONK - directoryPath = this._getDefaultDownloadDirectory(); -#else let prefValue = Services.prefs.getIntPref("browser.download.folderList", 1); switch(prefValue) { @@ -436,7 +394,6 @@ this.DownloadIntegration = { default: directoryPath = yield this.getSystemDownloadsDirectory(); } -#endif return directoryPath; }), diff --git a/toolkit/components/jsdownloads/src/DownloadPlatform.cpp b/toolkit/components/jsdownloads/src/DownloadPlatform.cpp index 95425071e028..1506b7c30c05 100644 --- a/toolkit/components/jsdownloads/src/DownloadPlatform.cpp +++ b/toolkit/components/jsdownloads/src/DownloadPlatform.cpp @@ -190,18 +190,6 @@ nsresult DownloadPlatform::DownloadDone(nsIURI* aSource, nsIURI* aReferrer, nsIF } } #endif - if (mozilla::Preferences::GetBool("device.storage.enabled", true)) { - // Tell DeviceStorage that a new file may have been added. - nsCOMPtr obs = mozilla::services::GetObserverService(); - nsCOMPtr pathString - = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID); - if (obs && pathString) { - if (NS_SUCCEEDED(pathString->SetData(path))) { - (void)obs->NotifyObservers(pathString, "download-watcher-notify", - u"modified"); - } - } - } } #endif diff --git a/toolkit/components/jsdownloads/test/unit/common_test_Download.js b/toolkit/components/jsdownloads/test/unit/common_test_Download.js index 9c663e5a96cb..1f085f4fcb5f 100644 --- a/toolkit/components/jsdownloads/test/unit/common_test_Download.js +++ b/toolkit/components/jsdownloads/test/unit/common_test_Download.js @@ -2273,86 +2273,6 @@ add_task(function* test_toSerializable_startTime() { do_check_eq(download1.startTime.toJSON(), download2.startTime.toJSON()); }); -/** - * This test will call the platform specific operations within - * DownloadPlatform::DownloadDone. While there is no test to verify the - * specific behaviours, this at least ensures that there is no error or crash. - */ -add_task(function* test_platform_integration() { - let downloadFiles = []; - let oldDeviceStorageEnabled = Services.prefs.getBoolPref("device.storage.enabled", false); - let downloadWatcherNotified = false; - let observer = { - observe(subject, topic, data) { - do_check_eq(topic, "download-watcher-notify"); - do_check_eq(data, "modified"); - downloadWatcherNotified = true; - } - } - Services.obs.addObserver(observer, "download-watcher-notify", false); - Services.prefs.setBoolPref("device.storage.enabled", true); - let downloadDoneCalled = false; - let monitorFn = base => ({ - __proto__: base, - downloadDone() { - return super.downloadDone(...arguments).then(() => { - downloadDoneCalled = true; - }); - }, - }); - Integration.downloads.register(monitorFn); - DownloadIntegration.allowDirectories = true; - function cleanup() { - for (let file of downloadFiles) { - file.remove(true); - } - Services.obs.removeObserver(observer, "download-watcher-notify"); - Services.prefs.setBoolPref("device.storage.enabled", oldDeviceStorageEnabled); - Integration.downloads.unregister(monitorFn); - DownloadIntegration.allowDirectories = false; - } - - for (let isPrivate of [false, true]) { - downloadDoneCalled = false; - - // Some platform specific operations only operate on files outside the - // temporary directory or in the Downloads directory (such as setting - // the Windows searchable attribute, and the Mac Downloads icon bouncing), - // so use the system Downloads directory for the target file. - let targetFilePath = yield DownloadIntegration.getSystemDownloadsDirectory(); - targetFilePath = OS.Path.join(targetFilePath, - "test" + (Math.floor(Math.random() * 1000000))); - let targetFile = new FileUtils.File(targetFilePath); - downloadFiles.push(targetFile); - - let download; - if (gUseLegacySaver) { - download = yield promiseStartLegacyDownload(httpUrl("source.txt"), - { isPrivate, targetFile }); - } else { - download = yield Downloads.createDownload({ - source: { url: httpUrl("source.txt"), isPrivate }, - target: targetFile, - }); - download.start().catch(() => {}); - } - - // Wait for the whenSucceeded promise to be resolved first. - // downloadDone should be called before the whenSucceeded promise is resolved. - yield download.whenSucceeded().then(function() { - do_check_true(downloadDoneCalled); - do_check_true(downloadWatcherNotified); - }); - - // Then, wait for the promise returned by "start" to be resolved. - yield promiseDownloadStopped(download); - - yield promiseVerifyTarget(download.target, TEST_DATA_SHORT); - } - - cleanup(); -}); - /** * Checks that downloads are added to browsing history when they start. */ diff --git a/toolkit/content/devicestorage.properties b/toolkit/content/devicestorage.properties deleted file mode 100644 index 5129a585c892..000000000000 --- a/toolkit/content/devicestorage.properties +++ /dev/null @@ -1,4 +0,0 @@ -# Extensions we recognize for DeviceStorage storage areas -pictures=*.jpe; *.jpg; *.jpeg; *.gif; *.png; *.bmp; -music=*.mp3; *.oga; *.ogg; *.m4a; *.m4b; *.m4p; *.m4r; *.3gp; *.3gpp; *.mp4; *.m3u; *.pls; *.opus; *.amr; *.wav; *.lcka; *.mka; *.flac; -videos=*.mp4; *.mpeg; *.mpg; *.ogv; *.ogx; *.webm; *.3gp; *.3gpp; *.3g2; *.ogg; *.m4v; *.ts; *.m2ts; *.avi; *.divx; *.mkv; diff --git a/toolkit/content/jar.mn b/toolkit/content/jar.mn index 93fc9f55010e..659a8cf7741b 100644 --- a/toolkit/content/jar.mn +++ b/toolkit/content/jar.mn @@ -46,7 +46,6 @@ toolkit.jar: content/global/customizeToolbar.xul #endif content/global/datepicker.xhtml - content/global/devicestorage.properties #ifndef MOZ_FENNEC content/global/editMenuOverlay.js * content/global/editMenuOverlay.xul @@ -119,4 +118,4 @@ toolkit.jar: content/global/macWindowMenu.js #endif content/global/gmp-sources/openh264.json (gmp-sources/openh264.json) - content/global/gmp-sources/widevinecdm.json (gmp-sources/widevinecdm.json) \ No newline at end of file + content/global/gmp-sources/widevinecdm.json (gmp-sources/widevinecdm.json) diff --git a/uriloader/exthandler/nsExternalHelperAppService.cpp b/uriloader/exthandler/nsExternalHelperAppService.cpp index c55c03e69c7f..6625b313a461 100644 --- a/uriloader/exthandler/nsExternalHelperAppService.cpp +++ b/uriloader/exthandler/nsExternalHelperAppService.cpp @@ -107,10 +107,6 @@ #include "mozilla/Preferences.h" #include "mozilla/ipc/URIUtils.h" -#ifdef MOZ_WIDGET_GONK -#include "nsDeviceStorage.h" -#endif - using namespace mozilla; using namespace mozilla::ipc; @@ -327,55 +323,6 @@ static nsresult GetDownloadDirectory(nsIFile **_directory, getter_AddRefs(dir)); NS_ENSURE_SUCCESS(rv, rv); } -#elif defined(MOZ_WIDGET_GONK) - // On Gonk, store the files on the sdcard in the downloads directory. - // We need to check with the volume manager which storage point is - // available. - - // Pick the default storage in case multiple (internal and external) ones - // are available. - nsString storageName; - nsDOMDeviceStorage::GetDefaultStorageName(NS_LITERAL_STRING("sdcard"), - storageName); - - RefPtr dsf( - new DeviceStorageFile(NS_LITERAL_STRING("sdcard"), - storageName, - NS_LITERAL_STRING("downloads"))); - NS_ENSURE_TRUE(dsf->mFile, NS_ERROR_FILE_ACCESS_DENIED); - - // If we're not checking for availability we're done. - if (aSkipChecks) { - dsf->mFile.forget(_directory); - return NS_OK; - } - - // Check device storage status before continuing. - nsString storageStatus; - dsf->GetStatus(storageStatus); - - // If we get an "unavailable" status, it means the sd card is not present. - // We'll also catch internal errors by looking for an empty string and assume - // the SD card isn't present when this occurs. - if (storageStatus.EqualsLiteral("unavailable") || - storageStatus.IsEmpty()) { - return NS_ERROR_FILE_NOT_FOUND; - } - - // If we get a status other than 'available' here it means the card is busy - // because it's mounted via USB or it is being formatted. - if (!storageStatus.EqualsLiteral("available")) { - return NS_ERROR_FILE_ACCESS_DENIED; - } - - bool alreadyThere; - nsresult rv = dsf->mFile->Exists(&alreadyThere); - NS_ENSURE_SUCCESS(rv, rv); - if (!alreadyThere) { - rv = dsf->mFile->Create(nsIFile::DIRECTORY_TYPE, 0770); - NS_ENSURE_SUCCESS(rv, rv); - } - dir = dsf->mFile; #elif defined(ANDROID) // We ask Java for the temporary download directory. The directory will be // different depending on whether we have the permission to write to the diff --git a/widget/android/AndroidBridge.cpp b/widget/android/AndroidBridge.cpp index a4f299882c40..6d0f461d9b12 100644 --- a/widget/android/AndroidBridge.cpp +++ b/widget/android/AndroidBridge.cpp @@ -1130,37 +1130,3 @@ nsresult AndroidBridge::InputStreamRead(Object::Param obj, char *aBuf, uint32_t *aRead = read; return NS_OK; } - -nsresult AndroidBridge::GetExternalPublicDirectory(const nsAString& aType, nsAString& aPath) { - if (XRE_IsContentProcess()) { - nsString key(aType); - nsAutoString path; - if (AndroidBridge::sStoragePaths.Get(key, &path)) { - aPath = path; - return NS_OK; - } - - // Lazily get the value from the parent. - dom::ContentChild* child = dom::ContentChild::GetSingleton(); - if (child) { - nsAutoString type(aType); - child->SendGetDeviceStorageLocation(type, &path); - if (!path.IsEmpty()) { - AndroidBridge::sStoragePaths.Put(key, path); - aPath = path; - return NS_OK; - } - } - - ALOG_BRIDGE("AndroidBridge::GetExternalPublicDirectory no cache for %s", - NS_ConvertUTF16toUTF8(aType).get()); - return NS_ERROR_NOT_AVAILABLE; - } - - auto path = GeckoAppShell::GetExternalPublicDirectory(aType); - if (!path) { - return NS_ERROR_NOT_AVAILABLE; - } - aPath = path->ToString(); - return NS_OK; -} diff --git a/widget/android/AndroidBridge.h b/widget/android/AndroidBridge.h index fb9688a44606..0da2e2c2c6ea 100644 --- a/widget/android/AndroidBridge.h +++ b/widget/android/AndroidBridge.h @@ -196,8 +196,6 @@ public: static uint32_t InputStreamAvailable(jni::Object::Param obj); static nsresult InputStreamRead(jni::Object::Param obj, char *aBuf, uint32_t aCount, uint32_t *aRead); - static nsresult GetExternalPublicDirectory(const nsAString& aType, nsAString& aPath); - protected: static nsDataHashtable sStoragePaths; diff --git a/widget/android/GeneratedJNIWrappers.cpp b/widget/android/GeneratedJNIWrappers.cpp index 401b306f0b59..79a41aa7ec16 100644 --- a/widget/android/GeneratedJNIWrappers.cpp +++ b/widget/android/GeneratedJNIWrappers.cpp @@ -335,14 +335,6 @@ auto GeckoAppShell::GetExtensionFromMimeType(mozilla::jni::String::Param a0) -> return mozilla::jni::Method::Call(GeckoAppShell::Context(), nullptr, a0); } -constexpr char GeckoAppShell::GetExternalPublicDirectory_t::name[]; -constexpr char GeckoAppShell::GetExternalPublicDirectory_t::signature[]; - -auto GeckoAppShell::GetExternalPublicDirectory(mozilla::jni::String::Param a0) -> mozilla::jni::String::LocalRef -{ - return mozilla::jni::Method::Call(GeckoAppShell::Context(), nullptr, a0); -} - constexpr char GeckoAppShell::GetHWDecoderCapability_t::name[]; constexpr char GeckoAppShell::GetHWDecoderCapability_t::signature[]; diff --git a/widget/android/GeneratedJNIWrappers.h b/widget/android/GeneratedJNIWrappers.h index 37957a59853c..e620f2fa0e21 100644 --- a/widget/android/GeneratedJNIWrappers.h +++ b/widget/android/GeneratedJNIWrappers.h @@ -951,26 +951,6 @@ public: static auto GetExtensionFromMimeType(mozilla::jni::String::Param) -> mozilla::jni::String::LocalRef; - struct GetExternalPublicDirectory_t { - typedef GeckoAppShell Owner; - typedef mozilla::jni::String::LocalRef ReturnType; - typedef mozilla::jni::String::Param SetterType; - typedef mozilla::jni::Args< - mozilla::jni::String::Param> Args; - static constexpr char name[] = "getExternalPublicDirectory"; - static constexpr char signature[] = - "(Ljava/lang/String;)Ljava/lang/String;"; - static const bool isStatic = true; - static const mozilla::jni::ExceptionMode exceptionMode = - mozilla::jni::ExceptionMode::ABORT; - static const mozilla::jni::CallingThread callingThread = - mozilla::jni::CallingThread::GECKO; - static const mozilla::jni::DispatchTarget dispatchTarget = - mozilla::jni::DispatchTarget::CURRENT; - }; - - static auto GetExternalPublicDirectory(mozilla::jni::String::Param) -> mozilla::jni::String::LocalRef; - struct GetHWDecoderCapability_t { typedef GeckoAppShell Owner; typedef bool ReturnType; diff --git a/xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp b/xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp index 9bb51eabd3d7..14e719f6c464 100644 --- a/xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp +++ b/xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp @@ -160,7 +160,6 @@ #endif #include "mozilla/dom/DataContainerEventBinding.h" #include "mozilla/dom/DataTransferBinding.h" -#include "mozilla/dom/DeviceStorageBinding.h" #include "mozilla/dom/DOMCursorBinding.h" #include "mozilla/dom/DOMExceptionBinding.h" #include "mozilla/dom/DOMParserBinding.h" From 9fa58ed2700a25b3bc25d6ffa05b0acc6acb256f Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Wed, 8 Mar 2017 20:15:45 +0100 Subject: [PATCH 46/57] Bug 1299500 - Get rid of DeviceStorage API - part 11 - FileSystem, r=ehsan --- dom/filesystem/DeviceStorageFileSystem.cpp | 195 ------------- dom/filesystem/DeviceStorageFileSystem.h | 74 ----- dom/filesystem/Directory.cpp | 7 +- dom/filesystem/FileSystemBase.cpp | 37 +-- dom/filesystem/FileSystemBase.h | 58 +--- .../FileSystemPermissionRequest.cpp | 262 ------------------ dom/filesystem/FileSystemPermissionRequest.h | 57 ---- dom/filesystem/FileSystemRequestParent.cpp | 16 +- dom/filesystem/FileSystemRequestParent.h | 15 - dom/filesystem/FileSystemTaskBase.cpp | 30 +- dom/filesystem/FileSystemTaskBase.h | 73 ++--- dom/filesystem/GetDirectoryListingTask.cpp | 14 +- dom/filesystem/GetDirectoryListingTask.h | 7 +- dom/filesystem/GetFileOrDirectoryTask.cpp | 12 - dom/filesystem/GetFileOrDirectoryTask.h | 6 - dom/filesystem/GetFilesTask.cpp | 12 - dom/filesystem/GetFilesTask.h | 6 - dom/filesystem/OSFileSystem.cpp | 18 +- dom/filesystem/compat/CallbackRunnables.cpp | 4 +- dom/filesystem/moz.build | 3 - ipc/glue/BackgroundParentImpl.cpp | 116 +------- ipc/glue/BackgroundParentImpl.h | 4 - 22 files changed, 73 insertions(+), 953 deletions(-) delete mode 100644 dom/filesystem/DeviceStorageFileSystem.cpp delete mode 100644 dom/filesystem/DeviceStorageFileSystem.h delete mode 100644 dom/filesystem/FileSystemPermissionRequest.cpp delete mode 100644 dom/filesystem/FileSystemPermissionRequest.h diff --git a/dom/filesystem/DeviceStorageFileSystem.cpp b/dom/filesystem/DeviceStorageFileSystem.cpp deleted file mode 100644 index 86fd56d579ef..000000000000 --- a/dom/filesystem/DeviceStorageFileSystem.cpp +++ /dev/null @@ -1,195 +0,0 @@ -/* -*- 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 "mozilla/dom/DeviceStorageFileSystem.h" - -#include "mozilla/Preferences.h" -#include "mozilla/dom/Directory.h" -#include "mozilla/dom/File.h" -#include "mozilla/dom/FileSystemUtils.h" -#include "mozilla/ipc/BackgroundParent.h" -#include "mozilla/Unused.h" -#include "nsCOMPtr.h" -#include "nsDebug.h" -#include "nsIFile.h" -#include "nsPIDOMWindow.h" -#include "nsGlobalWindow.h" - -using namespace mozilla::ipc; - -namespace mozilla { -namespace dom { - -DeviceStorageFileSystem::DeviceStorageFileSystem(const nsAString& aStorageType, - const nsAString& aStorageName) - : mStorageType(aStorageType) - , mStorageName(aStorageName) - , mWindowId(0) -{ - mPermissionCheckType = ePermissionCheckByTestingPref; - - if (NS_IsMainThread()) { - if (mozilla::Preferences::GetBool("device.storage.prompt.testing", false)) { - mPermissionCheckType = ePermissionCheckNotRequired; - } else { - mPermissionCheckType = ePermissionCheckRequired; - } - } else { - AssertIsOnBackgroundThread(); - } -} - -DeviceStorageFileSystem::~DeviceStorageFileSystem() -{ - AssertIsOnOwningThread(); -} - -already_AddRefed -DeviceStorageFileSystem::Clone() -{ - AssertIsOnOwningThread(); - - RefPtr fs = - new DeviceStorageFileSystem(mStorageType, mStorageName); - - fs->mWindowId = mWindowId; - - return fs.forget(); -} - -void -DeviceStorageFileSystem::Init(nsDOMDeviceStorage* aDeviceStorage) -{ - MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!"); - AssertIsOnOwningThread(); - MOZ_ASSERT(aDeviceStorage); - - nsCOMPtr window = aDeviceStorage->GetOwner(); - MOZ_ASSERT(window->IsInnerWindow()); - mWindowId = window->WindowID(); -} - -void -DeviceStorageFileSystem::Shutdown() -{ - AssertIsOnOwningThread(); - mShutdown = true; -} - -nsISupports* -DeviceStorageFileSystem::GetParentObject() const -{ - MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!"); - AssertIsOnOwningThread(); - - nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(mWindowId); - MOZ_ASSERT_IF(!mShutdown, window); - return window ? window->AsInner() : nullptr; -} - -void -DeviceStorageFileSystem::GetDirectoryName(nsIFile* aFile, nsAString& aRetval, - ErrorResult& aRv) const -{ - AssertIsOnOwningThread(); - MOZ_ASSERT(aFile); - - nsCOMPtr rootPath; - aRv = NS_NewLocalFile(LocalOrDeviceStorageRootPath(), false, - getter_AddRefs(rootPath)); - if (NS_WARN_IF(aRv.Failed())) { - return; - } - - bool equal = false; - aRv = aFile->Equals(rootPath, &equal); - if (NS_WARN_IF(aRv.Failed())) { - return; - } - - if (equal) { - aRetval = mStorageName; - return; - } - - FileSystemBase::GetDirectoryName(aFile, aRetval, aRv); - NS_WARNING_ASSERTION(!aRv.Failed(), "GetDirectoryName failed"); -} - -bool -DeviceStorageFileSystem::IsSafeFile(nsIFile* aFile) const -{ - MOZ_ASSERT(XRE_IsParentProcess(), "Should be on parent process!"); - MOZ_ASSERT(!NS_IsMainThread()); - MOZ_ASSERT(aFile); - - nsCOMPtr rootPath; - nsresult rv = NS_NewLocalFile(LocalOrDeviceStorageRootPath(), false, - getter_AddRefs(rootPath)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return false; - } - - // Check if this file belongs to this storage. - if (NS_WARN_IF(!FileSystemUtils::IsDescendantPath(rootPath, aFile))) { - return false; - } - - // Check if the file type is compatible with the storage type. - DeviceStorageTypeChecker* typeChecker - = DeviceStorageTypeChecker::CreateOrGet(); - MOZ_ASSERT(typeChecker); - return typeChecker->Check(mStorageType, aFile); -} - -bool -DeviceStorageFileSystem::IsSafeDirectory(Directory* aDir) const -{ - AssertIsOnOwningThread(); - MOZ_ASSERT(aDir); - - ErrorResult rv; - RefPtr fs = aDir->GetFileSystem(rv); - if (NS_WARN_IF(rv.Failed())) { - rv.SuppressException(); - return false; - } - - nsAutoString fsSerialization; - fs->SerializeDOMPath(fsSerialization); - - nsAutoString thisSerialization; - SerializeDOMPath(thisSerialization); - - // Check if the given directory is from this storage. - return fsSerialization == thisSerialization; -} - -void -DeviceStorageFileSystem::SerializeDOMPath(nsAString& aString) const -{ - AssertIsOnOwningThread(); - - // Generate the string representation of the file system. - aString.AssignLiteral("devicestorage-"); - aString.Append(mStorageType); - aString.Append('-'); - aString.Append(mStorageName); -} - -nsresult -DeviceStorageFileSystem::MainThreadWork() -{ - MOZ_ASSERT(NS_IsMainThread()); - - DebugOnly typeChecker = - DeviceStorageTypeChecker::CreateOrGet(); - MOZ_ASSERT(typeChecker); - return NS_OK; -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/filesystem/DeviceStorageFileSystem.h b/dom/filesystem/DeviceStorageFileSystem.h deleted file mode 100644 index ce2c39985e69..000000000000 --- a/dom/filesystem/DeviceStorageFileSystem.h +++ /dev/null @@ -1,74 +0,0 @@ -/* -*- 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_DeviceStorageFileSystem_h -#define mozilla_dom_DeviceStorageFileSystem_h - -#include "mozilla/dom/FileSystemBase.h" -#include "nsString.h" - -class nsDOMDeviceStorage; - -namespace mozilla { -namespace dom { - -class DeviceStorageFileSystem - : public FileSystemBase -{ -public: - DeviceStorageFileSystem(const nsAString& aStorageType, - const nsAString& aStorageName); - - void - Init(nsDOMDeviceStorage* aDeviceStorage); - - // Overrides FileSystemBase - - virtual already_AddRefed - Clone() override; - - virtual bool - ShouldCreateDirectory() override { return true; } - - virtual void - Shutdown() override; - - virtual nsISupports* - GetParentObject() const override; - - virtual void - GetDirectoryName(nsIFile* aFile, nsAString& aRetval, - ErrorResult& aRv) const override; - - virtual bool - IsSafeFile(nsIFile* aFile) const override; - - virtual bool - IsSafeDirectory(Directory* aDir) const override; - - virtual void - SerializeDOMPath(nsAString& aSerializedString) const override; - - virtual bool - NeedToGoToMainThread() const override { return true; } - - virtual nsresult - MainThreadWork() override; - -private: - virtual - ~DeviceStorageFileSystem(); - - nsString mStorageType; - nsString mStorageName; - - uint64_t mWindowId; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_DeviceStorageFileSystem_h diff --git a/dom/filesystem/Directory.cpp b/dom/filesystem/Directory.cpp index 828da547baab..5e8a4a745303 100644 --- a/dom/filesystem/Directory.cpp +++ b/dom/filesystem/Directory.cpp @@ -6,7 +6,6 @@ #include "mozilla/dom/Directory.h" -#include "FileSystemPermissionRequest.h" #include "GetDirectoryListingTask.h" #include "GetFilesTask.h" #include "WorkerPrivate.h" @@ -188,7 +187,8 @@ Directory::GetFilesAndDirectories(ErrorResult& aRv) return nullptr; } - FileSystemPermissionRequest::RequestForTask(task); + task->Start(); + return task->GetPromise(); } @@ -209,7 +209,8 @@ Directory::GetFiles(bool aRecursiveFlag, ErrorResult& aRv) return nullptr; } - FileSystemPermissionRequest::RequestForTask(task); + task->Start(); + return task->GetPromise(); } diff --git a/dom/filesystem/FileSystemBase.cpp b/dom/filesystem/FileSystemBase.cpp index a81641e394a1..f44f4fbf1a62 100644 --- a/dom/filesystem/FileSystemBase.cpp +++ b/dom/filesystem/FileSystemBase.cpp @@ -6,48 +6,14 @@ #include "mozilla/dom/FileSystemBase.h" -#include "DeviceStorageFileSystem.h" #include "nsCharSeparatedTokenizer.h" #include "OSFileSystem.h" namespace mozilla { namespace dom { -// static -already_AddRefed -FileSystemBase::DeserializeDOMPath(const nsAString& aString) -{ - MOZ_ASSERT(XRE_IsParentProcess(), "Only call from parent process!"); - AssertIsOnBackgroundThread(); - - if (StringBeginsWith(aString, NS_LITERAL_STRING("devicestorage-"))) { - // The string representation of devicestorage file system is of the format: - // devicestorage-StorageType-StorageName - - nsCharSeparatedTokenizer tokenizer(aString, char16_t('-')); - tokenizer.nextToken(); - - nsString storageType; - if (tokenizer.hasMoreTokens()) { - storageType = tokenizer.nextToken(); - } - - nsString storageName; - if (tokenizer.hasMoreTokens()) { - storageName = tokenizer.nextToken(); - } - - RefPtr f = - new DeviceStorageFileSystem(storageType, storageName); - return f.forget(); - } - - return RefPtr(new OSFileSystemParent(aString)).forget(); -} - FileSystemBase::FileSystemBase() : mShutdown(false) - , mPermissionCheckType(eNotSet) #ifdef DEBUG , mOwningThread(PR_GetCurrentThread()) #endif @@ -133,8 +99,7 @@ FileSystemBase::GetDOMPath(nsIFile* aFile, aRetval.Truncate(); nsCOMPtr fileSystemPath; - aRv = NS_NewLocalFile(LocalOrDeviceStorageRootPath(), - true, getter_AddRefs(fileSystemPath)); + aRv = NS_NewLocalFile(LocalRootPath(), true, getter_AddRefs(fileSystemPath)); if (NS_WARN_IF(aRv.Failed())) { return; } diff --git a/dom/filesystem/FileSystemBase.h b/dom/filesystem/FileSystemBase.h index 31844ee9b802..0b875eb147fb 100644 --- a/dom/filesystem/FileSystemBase.h +++ b/dom/filesystem/FileSystemBase.h @@ -20,10 +20,6 @@ class FileSystemBase public: NS_INLINE_DECL_REFCOUNTING(FileSystemBase) - // Create file system object from its string representation. - static already_AddRefed - DeserializeDOMPath(const nsAString& aString); - FileSystemBase(); virtual void @@ -56,9 +52,9 @@ public: * directory of the exposed root Directory (per type). */ const nsAString& - LocalOrDeviceStorageRootPath() const + LocalRootPath() const { - return mLocalOrDeviceStorageRootPath; + return mLocalRootPath; } bool @@ -76,46 +72,6 @@ public: bool GetRealPath(BlobImpl* aFile, nsIFile** aPath) const; - /* - * Get the permission name required to access this file system. - */ - const nsCString& - GetPermission() const - { - return mPermission; - } - - // The decision about doing or not doing the permission check cannot be done - // everywhere because, for some FileSystemBase implementation, this depends on - // a preference. - // This enum describes all the possible decisions. The implementation will do - // the check on the main-thread in the child and in the parent process when - // needed. - // Note: the permission check should not fail in PBackground because that - // means that the child has been compromised. If this happens the child - // process is killed. - enum ePermissionCheckType { - // When on the main-thread, we must check if we have - // device.storage.prompt.testing set to true. - ePermissionCheckByTestingPref, - - // No permission check must be done. - ePermissionCheckNotRequired, - - // Permission check is required. - ePermissionCheckRequired, - - // This is the default value. We crash if this is let like this. - eNotSet - }; - - ePermissionCheckType - PermissionCheckType() const - { - MOZ_ASSERT(mPermissionCheckType != eNotSet); - return mPermissionCheckType; - } - // IPC initialization // See how these 2 methods are used in FileSystemTaskChildBase. @@ -147,18 +103,10 @@ protected: // Directory object can have different OS 'root' path. // To be more clear, any path managed by this FileSystem implementation must // be discendant of this local root path. - // The reason why it's not just called 'localRootPath' is because for - // DeviceStorage this contains the path of the device storage SDCard, that is - // the parent directory of the exposed root path. - nsString mLocalOrDeviceStorageRootPath; + nsString mLocalRootPath; bool mShutdown; - // The permission name required to access the file system. - nsCString mPermission; - - ePermissionCheckType mPermissionCheckType; - #ifdef DEBUG PRThread* mOwningThread; #endif diff --git a/dom/filesystem/FileSystemPermissionRequest.cpp b/dom/filesystem/FileSystemPermissionRequest.cpp deleted file mode 100644 index 137bb7e4b17d..000000000000 --- a/dom/filesystem/FileSystemPermissionRequest.cpp +++ /dev/null @@ -1,262 +0,0 @@ -/* -*- 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 "FileSystemPermissionRequest.h" - -#include "mozilla/dom/FileSystemBase.h" -#include "mozilla/dom/FileSystemTaskBase.h" -#include "mozilla/dom/FileSystemUtils.h" -#include "mozilla/ipc/BackgroundChild.h" -#include "mozilla/ipc/PBackgroundChild.h" -#include "nsIDocument.h" -#include "nsIIPCBackgroundChildCreateCallback.h" -#include "nsPIDOMWindow.h" -#include "nsContentPermissionHelper.h" - -namespace mozilla { -namespace dom { - -namespace { - -// This class takes care of the PBackground initialization and, once this step -// is completed, it starts the task. -class PBackgroundInitializer final : public nsIIPCBackgroundChildCreateCallback -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSIIPCBACKGROUNDCHILDCREATECALLBACK - - static void - ScheduleTask(FileSystemTaskChildBase* aTask) - { - MOZ_ASSERT(aTask); - RefPtr pb = new PBackgroundInitializer(aTask); - } - -private: - explicit PBackgroundInitializer(FileSystemTaskChildBase* aTask) - : mTask(aTask) - { - MOZ_ASSERT(aTask); - - PBackgroundChild* actor = - mozilla::ipc::BackgroundChild::GetForCurrentThread(); - if (actor) { - ActorCreated(actor); - } else { - if (NS_WARN_IF( - !mozilla::ipc::BackgroundChild::GetOrCreateForCurrentThread(this))) { - MOZ_CRASH(); - } - } - } - - ~PBackgroundInitializer() - {} - - RefPtr mTask; -}; - -NS_IMPL_ISUPPORTS(PBackgroundInitializer, - nsIIPCBackgroundChildCreateCallback) - -void -PBackgroundInitializer::ActorFailed() -{ - MOZ_CRASH("Failed to create a PBackgroundChild actor!"); -} - -void -PBackgroundInitializer::ActorCreated(mozilla::ipc::PBackgroundChild* aActor) -{ - mTask->Start(); -} - -// This must be a CancelableRunnable because it can be dispatched to a worker -// thread. But we don't care about the Cancel() because in that case, Run() is -// not called and the task is deleted by the DTOR. -class AsyncStartRunnable final : public CancelableRunnable -{ -public: - explicit AsyncStartRunnable(FileSystemTaskChildBase* aTask) - : mTask(aTask) - { - MOZ_ASSERT(aTask); - } - - NS_IMETHOD - Run() override - { - PBackgroundInitializer::ScheduleTask(mTask); - return NS_OK; - } - -private: - RefPtr mTask; -}; - -} // anonymous namespace - -NS_IMPL_ISUPPORTS(FileSystemPermissionRequest, nsIRunnable, - nsIContentPermissionRequest) - -/* static */ void -FileSystemPermissionRequest::RequestForTask(FileSystemTaskChildBase* aTask) -{ - MOZ_ASSERT(aTask); - - RefPtr filesystem = aTask->GetFileSystem(); - if (!filesystem) { - return; - } - - if (filesystem->PermissionCheckType() == FileSystemBase::ePermissionCheckNotRequired) { - // Let's make the scheduling of this task asynchronous. - RefPtr runnable = new AsyncStartRunnable(aTask); - NS_DispatchToCurrentThread(runnable); - return; - } - - // We don't need any permission check for the FileSystem API. If we are here - // it's because we are dealing with a DeviceStorage API that is main-thread - // only. - MOZ_ASSERT(NS_IsMainThread()); - - RefPtr request = - new FileSystemPermissionRequest(aTask); - NS_DispatchToCurrentThread(request); -} - -FileSystemPermissionRequest::FileSystemPermissionRequest(FileSystemTaskChildBase* aTask) - : mTask(aTask) -{ - MOZ_ASSERT(mTask, "aTask should not be null!"); - MOZ_ASSERT(NS_IsMainThread()); - - mTask->GetPermissionAccessType(mPermissionAccess); - - RefPtr filesystem = mTask->GetFileSystem(); - if (!filesystem) { - return; - } - - mPermissionType = filesystem->GetPermission(); - - mWindow = do_QueryInterface(filesystem->GetParentObject()); - if (NS_WARN_IF(!mWindow)) { - return; - } - - nsCOMPtr doc = mWindow->GetDoc(); - if (!doc) { - return; - } - - mPrincipal = doc->NodePrincipal(); - mRequester = new nsContentPermissionRequester(mWindow); -} - -FileSystemPermissionRequest::~FileSystemPermissionRequest() -{ -} - -NS_IMETHODIMP -FileSystemPermissionRequest::GetTypes(nsIArray** aTypes) -{ - nsTArray emptyOptions; - return nsContentPermissionUtils::CreatePermissionArray(mPermissionType, - mPermissionAccess, - emptyOptions, - aTypes); -} - -NS_IMETHODIMP -FileSystemPermissionRequest::GetPrincipal(nsIPrincipal** aRequestingPrincipal) -{ - NS_IF_ADDREF(*aRequestingPrincipal = mPrincipal); - return NS_OK; -} - -NS_IMETHODIMP -FileSystemPermissionRequest::GetWindow(mozIDOMWindow** aRequestingWindow) -{ - NS_IF_ADDREF(*aRequestingWindow = mWindow); - return NS_OK; -} - -NS_IMETHODIMP -FileSystemPermissionRequest::GetElement(nsIDOMElement** aRequestingElement) -{ - *aRequestingElement = nullptr; - return NS_OK; -} - -NS_IMETHODIMP -FileSystemPermissionRequest::Cancel() -{ - MOZ_ASSERT(NS_IsMainThread()); - mTask->SetError(NS_ERROR_DOM_SECURITY_ERR); - ScheduleTask(); - return NS_OK; -} - -NS_IMETHODIMP -FileSystemPermissionRequest::Allow(JS::HandleValue aChoices) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(aChoices.isUndefined()); - ScheduleTask(); - return NS_OK; -} - -NS_IMETHODIMP -FileSystemPermissionRequest::Run() -{ - MOZ_ASSERT(NS_IsMainThread()); - - RefPtr filesystem = mTask->GetFileSystem(); - if (!filesystem) { - Cancel(); - return NS_OK; - } - - if (filesystem->PermissionCheckType() == FileSystemBase::ePermissionCheckNotRequired) { - Allow(JS::UndefinedHandleValue); - return NS_OK; - } - - if (filesystem->PermissionCheckType() == FileSystemBase::ePermissionCheckByTestingPref && - mozilla::Preferences::GetBool("device.storage.prompt.testing", false)) { - Allow(JS::UndefinedHandleValue); - return NS_OK; - } - - if (!mWindow) { - Cancel(); - return NS_OK; - } - - nsContentPermissionUtils::AskPermission(this, mWindow); - return NS_OK; -} - -NS_IMETHODIMP -FileSystemPermissionRequest::GetRequester(nsIContentPermissionRequester** aRequester) -{ - NS_ENSURE_ARG_POINTER(aRequester); - - nsCOMPtr requester = mRequester; - requester.forget(aRequester); - return NS_OK; -} - -void -FileSystemPermissionRequest::ScheduleTask() -{ - PBackgroundInitializer::ScheduleTask(mTask); -} - -} /* namespace dom */ -} /* namespace mozilla */ diff --git a/dom/filesystem/FileSystemPermissionRequest.h b/dom/filesystem/FileSystemPermissionRequest.h deleted file mode 100644 index c20ca3a25026..000000000000 --- a/dom/filesystem/FileSystemPermissionRequest.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- 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_FileSystemPermissionRequest_h -#define mozilla_dom_FileSystemPermissionRequest_h - -#include "nsIRunnable.h" -#include "nsIContentPermissionPrompt.h" -#include "nsString.h" - -class nsPIDOMWindowInner; - -namespace mozilla { -namespace dom { - -class FileSystemTaskChildBase; - -class FileSystemPermissionRequest final - : public nsIContentPermissionRequest - , public nsIRunnable -{ -public: - // Request permission for the given task. - static void - RequestForTask(FileSystemTaskChildBase* aTask); - - NS_DECL_THREADSAFE_ISUPPORTS - NS_DECL_NSICONTENTPERMISSIONREQUEST - NS_DECL_NSIRUNNABLE - -private: - explicit FileSystemPermissionRequest(FileSystemTaskChildBase* aTask); - - ~FileSystemPermissionRequest(); - - // Once the permission check has been done, we must run the task using IPC and - // PBackground. This method checks if the PBackground thread is ready to - // receive the task and in case waits for ActorCreated() to be called using - // the PBackgroundInitializer class (see FileSystemPermissionRequest.cpp). - void - ScheduleTask(); - - nsCString mPermissionType; - nsCString mPermissionAccess; - RefPtr mTask; - nsCOMPtr mWindow; - nsCOMPtr mPrincipal; - nsCOMPtr mRequester; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_FileSystemPermissionRequest_h diff --git a/dom/filesystem/FileSystemRequestParent.cpp b/dom/filesystem/FileSystemRequestParent.cpp index e789345e5516..25125b65dfb4 100644 --- a/dom/filesystem/FileSystemRequestParent.cpp +++ b/dom/filesystem/FileSystemRequestParent.cpp @@ -3,12 +3,17 @@ /* 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 "mozilla/dom/FileSystemRequestParent.h" +#include "mozilla/dom/PFileSystemParams.h" #include "GetDirectoryListingTask.h" #include "GetFileOrDirectoryTask.h" #include "mozilla/dom/FileSystemBase.h" +#include "mozilla/ipc/BackgroundParent.h" + +using namespace mozilla::ipc; namespace mozilla { namespace dom { @@ -27,7 +32,7 @@ FileSystemRequestParent::~FileSystemRequestParent() #define FILESYSTEM_REQUEST_PARENT_DISPATCH_ENTRY(name) \ case FileSystemParams::TFileSystem##name##Params: { \ const FileSystem##name##Params& p = aParams; \ - mFileSystem = FileSystemBase::DeserializeDOMPath(p.filesystem()); \ + mFileSystem = new OSFileSystemParent(p.filesystem()); \ MOZ_ASSERT(mFileSystem); \ mTask = name##TaskParent::Create(mFileSystem, p, this, rv); \ if (NS_WARN_IF(rv.Failed())) { \ @@ -61,15 +66,6 @@ FileSystemRequestParent::Initialize(const FileSystemParams& aParams) return false; } - if (mFileSystem->PermissionCheckType() != FileSystemBase::ePermissionCheckNotRequired) { - nsAutoCString access; - mTask->GetPermissionAccessType(access); - - mPermissionName = mFileSystem->GetPermission(); - mPermissionName.Append('-'); - mPermissionName.Append(access); - } - return true; } diff --git a/dom/filesystem/FileSystemRequestParent.h b/dom/filesystem/FileSystemRequestParent.h index ebc97c0ea163..a5f4cd6cc496 100644 --- a/dom/filesystem/FileSystemRequestParent.h +++ b/dom/filesystem/FileSystemRequestParent.h @@ -23,19 +23,6 @@ class FileSystemRequestParent final : public PFileSystemRequestParent public: FileSystemRequestParent(); - const nsCString& - PermissionName() const - { - return mPermissionName; - } - - FileSystemBase::ePermissionCheckType - PermissionCheckType() const - { - return mFileSystem ? mFileSystem->PermissionCheckType() - : FileSystemBase::eNotSet; - } - bool Initialize(const FileSystemParams& aParams); @@ -56,8 +43,6 @@ private: RefPtr mFileSystem; RefPtr mTask; - nsCString mPermissionName; - bool mDestroyed; }; diff --git a/dom/filesystem/FileSystemTaskBase.cpp b/dom/filesystem/FileSystemTaskBase.cpp index 8f37ff596da9..9cca5d35c483 100644 --- a/dom/filesystem/FileSystemTaskBase.cpp +++ b/dom/filesystem/FileSystemTaskBase.cpp @@ -13,7 +13,9 @@ #include "mozilla/dom/FileSystemUtils.h" #include "mozilla/dom/Promise.h" #include "mozilla/dom/ipc/BlobParent.h" +#include "mozilla/ipc/BackgroundChild.h" #include "mozilla/ipc/BackgroundParent.h" +#include "mozilla/ipc/PBackgroundChild.h" #include "mozilla/Unused.h" #include "nsProxyRelease.h" @@ -103,6 +105,8 @@ private: } // anonymous namespace +NS_IMPL_ISUPPORTS(FileSystemTaskChildBase, nsIIPCBackgroundChildCreateCallback) + /** * FileSystemTaskBase class */ @@ -132,6 +136,27 @@ FileSystemTaskChildBase::Start() { mFileSystem->AssertIsOnOwningThread(); + mozilla::ipc::PBackgroundChild* actor = + mozilla::ipc::BackgroundChild::GetForCurrentThread(); + if (actor) { + ActorCreated(actor); + } else { + if (NS_WARN_IF( + !mozilla::ipc::BackgroundChild::GetOrCreateForCurrentThread(this))) { + MOZ_CRASH(); + } + } +} + +void +FileSystemTaskChildBase::ActorFailed() +{ + MOZ_CRASH("Failed to create a PBackgroundChild actor!"); +} + +void +FileSystemTaskChildBase::ActorCreated(mozilla::ipc::PBackgroundChild* aActor) +{ if (HasError()) { // In this case we don't want to use IPC at all. RefPtr runnable = new ErrorRunnable(this); @@ -159,10 +184,7 @@ FileSystemTaskChildBase::Start() // mozilla::ipc::BackgroundChildImpl::DeallocPFileSystemRequestChild. NS_ADDREF_THIS(); - // If we are here, PBackground must be up and running, because Start() is - // called only by FileSystemPermissionRequest, and that class takes care of - // PBackground initialization. - PBackgroundChild* actor = + mozilla::ipc::PBackgroundChild* actor = mozilla::ipc::BackgroundChild::GetForCurrentThread(); MOZ_ASSERT(actor); diff --git a/dom/filesystem/FileSystemTaskBase.h b/dom/filesystem/FileSystemTaskBase.h index efd5badb38b1..86e944fa52c2 100644 --- a/dom/filesystem/FileSystemTaskBase.h +++ b/dom/filesystem/FileSystemTaskBase.h @@ -10,6 +10,7 @@ #include "mozilla/ErrorResult.h" #include "mozilla/dom/FileSystemRequestParent.h" #include "mozilla/dom/PFileSystemRequestChild.h" +#include "nsIIPCBackgroundChildCreateCallback.h" #include "nsThreadUtils.h" namespace mozilla { @@ -20,10 +21,6 @@ class FileSystemBase; class FileSystemParams; class PBlobParent; -#define DIRECTORY_READ_PERMISSION "read" -#define DIRECTORY_WRITE_PERMISSION "write" -#define DIRECTORY_CREATE_PERMISSION "create" - /* * The base class to implement a Task class. * The file system operations can only be performed in the parent process. In @@ -39,39 +36,34 @@ class PBlobParent; * Page * | * | (1) - * ______|_______________________ | __________________________________ - * | | | | | | + * ______|_________________________ | _________________________________ + * | | | | | | * | | | | | | * | V | IPC | PBackground thread on | * | [new FileSystemTaskChildBase()] | | | the parent process | - * | | | | | | - * | | (2) | | | | - * | V | | | | - * | [FileSystemPermissionRequest------------------\ | - * | ::RequestForTask()] <------------------------/ | - * | | | | | | - * | | (3) | | | - * | V | (4) | | + * | | | | | | + * | | (2) | | | + * | V | (3) | | * | [GetRequestParams]------------------->[new FileSystemTaskParentBase()] | * | | | | | - * | | | | | (5) _____________ | + * | | | | | (4) _____________ | * | | | | | | | | * | | | | | | I/O Thread | | * | | | | | | | | * | | | | ---------> [IOWork] | | * | | IPC | | | | | - * | | | | | | (6) | | + * | | | | | | (5) | | * | | | | -------------- | | * | | | | | |_____________| | * | | | | | | * | | | | V | * | | | | [HandleResult] | * | | | | | | - * | | | | (7) | - * | | (8) | V | + * | | | | (6) | + * | | (7) | V | * | [SetRequestResult]<---------------------[GetRequestResult] | * | | | | | - * | | (9) | | | | + * | | (8) | | | | * | V | | | | * |[HandlerCallback] | IPC | | * |_______|_________________________| | |_________________________________| @@ -84,44 +76,35 @@ class PBlobParent; * (1) Call FileSystem API from content page with JS. Create a task and run. * The base constructor [FileSystemTaskChildBase()] of the task should be * called. - * (2) The FileSystemTaskChildBase object is given to - * [FileSystemPermissionRequest::RequestForTask()] that will perform a - * permission check step if needed (See ePermissionCheckType enum). The real - * operation is done on the parent process but it's hidden by - * [nsContentPermissionUtils::AskPermission()]. If the permission check is not - * needed or if the page has the right permission, the - * FileSystemPermissionRequest will start the task (only once PBackground - * actor is fully initialized). - * (3) Forward the task to the parent process through the IPC and call + * (2) Forward the task to the parent process through the IPC and call * [GetRequestParams] to prepare the parameters of the IPC. * Parent: - * (4) The parent process receives IPC and handle it in + * (3) The parent process receives IPC and handle it in * FileystemRequestParent. Get the IPC parameters and create a task to run the - * IPC task. The base constructor [FileSystemTaskParentBase(aParam, aParent)] - * For security reasons, we do an additional permission check if needed. In - * the check fails, the child process will be killed. - * of the task should be called to set the task as an IPC task. - * (5) The task operation will be performed in the member function of [IOWork]. + * IPC task. + * (4) The task operation will be performed in the member function of [IOWork]. * A I/O thread will be created to run that function. If error occurs * during the operation, call [SetError] to record the error and then abort. - * (6) After finishing the task operation, call [HandleResult] to send the + * (5) After finishing the task operation, call [HandleResult] to send the * result back to the child process though the IPC. - * (7) Call [GetRequestResult] request result to prepare the parameters of the + * (6) Call [GetRequestResult] request result to prepare the parameters of the * IPC. Because the formats of the error result for different task are the * same, FileSystemTaskChildBase can handle the error message without * interfering. * Each task only needs to implement its specific success result preparation * function -[GetSuccessRequestResult]. * Child/Parent: - * (8) The process receives IPC and calls [SetRequestResult] to get the + * (7) The process receives IPC and calls [SetRequestResult] to get the * task result. Each task needs to implement its specific success result * parsing function [SetSuccessRequestResult] to get the success result. - * (9) Call [HandlerCallback] to send the task result to the content page. + * (8) Call [HandlerCallback] to send the task result to the content page. */ class FileSystemTaskChildBase : public PFileSystemRequestChild + , public nsIIPCBackgroundChildCreateCallback { public: - NS_INLINE_DECL_REFCOUNTING(FileSystemTaskChildBase) + NS_DECL_ISUPPORTS + NS_DECL_NSIIPCBACKGROUNDCHILDCREATECALLBACK /* * Start the task. It will dispatch all the information to the parent process, @@ -140,12 +123,6 @@ public: FileSystemBase* GetFileSystem() const; - /* - * Get the type of permission access required to perform this task. - */ - virtual void - GetPermissionAccessType(nsCString& aAccess) const = 0; - /* * After the task is completed, this function will be called to pass the task * result to the content page. This method is called in the owning thread. @@ -259,12 +236,6 @@ public: virtual nsresult MainThreadWork(); - /* - * Get the type of permission access required to perform this task. - */ - virtual void - GetPermissionAccessType(nsCString& aAccess) const = 0; - bool HasError() const { return NS_FAILED(mErrorValue); } diff --git a/dom/filesystem/GetDirectoryListingTask.cpp b/dom/filesystem/GetDirectoryListingTask.cpp index fcc031dae50e..25ca8685ffc1 100644 --- a/dom/filesystem/GetDirectoryListingTask.cpp +++ b/dom/filesystem/GetDirectoryListingTask.cpp @@ -13,9 +13,11 @@ #include "mozilla/dom/FileSystemUtils.h" #include "mozilla/dom/PFileSystemParams.h" #include "mozilla/dom/Promise.h" +#include "mozilla/dom/UnionTypes.h" #include "mozilla/dom/ipc/BlobChild.h" #include "mozilla/dom/ipc/BlobParent.h" #include "nsIFile.h" +#include "nsISimpleEnumerator.h" #include "nsStringGlue.h" namespace mozilla { @@ -176,12 +178,6 @@ GetDirectoryListingTaskChild::HandlerCallback() mPromise = nullptr; } -void -GetDirectoryListingTaskChild::GetPermissionAccessType(nsCString& aAccess) const -{ - aAccess.AssignLiteral(DIRECTORY_READ_PERMISSION); -} - /** * GetDirectoryListingTaskParent */ @@ -384,11 +380,5 @@ GetDirectoryListingTaskParent::IOWork() return NS_OK; } -void -GetDirectoryListingTaskParent::GetPermissionAccessType(nsCString& aAccess) const -{ - aAccess.AssignLiteral(DIRECTORY_READ_PERMISSION); -} - } // namespace dom } // namespace mozilla diff --git a/dom/filesystem/GetDirectoryListingTask.h b/dom/filesystem/GetDirectoryListingTask.h index 508286c33653..764ce478919b 100644 --- a/dom/filesystem/GetDirectoryListingTask.h +++ b/dom/filesystem/GetDirectoryListingTask.h @@ -16,6 +16,7 @@ namespace dom { class BlobImpl; class FileSystemGetDirectoryListingParams; +class OwningFileOrDirectory; class GetDirectoryListingTaskChild final : public FileSystemTaskChildBase { @@ -33,9 +34,6 @@ public: already_AddRefed GetPromise(); - virtual void - GetPermissionAccessType(nsCString& aAccess) const override; - private: // If aDirectoryOnly is set, we should ensure that the target is a directory. GetDirectoryListingTaskChild(FileSystemBase* aFileSystem, @@ -71,9 +69,6 @@ public: FileSystemRequestParent* aParent, ErrorResult& aRv); - virtual void - GetPermissionAccessType(nsCString& aAccess) const override; - private: GetDirectoryListingTaskParent(FileSystemBase* aFileSystem, const FileSystemGetDirectoryListingParams& aParam, diff --git a/dom/filesystem/GetFileOrDirectoryTask.cpp b/dom/filesystem/GetFileOrDirectoryTask.cpp index 2a609718e79f..7f721bc63375 100644 --- a/dom/filesystem/GetFileOrDirectoryTask.cpp +++ b/dom/filesystem/GetFileOrDirectoryTask.cpp @@ -154,12 +154,6 @@ GetFileOrDirectoryTaskChild::HandlerCallback() mPromise = nullptr; } -void -GetFileOrDirectoryTaskChild::GetPermissionAccessType(nsCString& aAccess) const -{ - aAccess.AssignLiteral(DIRECTORY_READ_PERMISSION); -} - /** * GetFileOrDirectoryTaskParent */ @@ -276,11 +270,5 @@ GetFileOrDirectoryTaskParent::IOWork() return NS_OK; } -void -GetFileOrDirectoryTaskParent::GetPermissionAccessType(nsCString& aAccess) const -{ - aAccess.AssignLiteral(DIRECTORY_READ_PERMISSION); -} - } // namespace dom } // namespace mozilla diff --git a/dom/filesystem/GetFileOrDirectoryTask.h b/dom/filesystem/GetFileOrDirectoryTask.h index cda18de9063e..28a9fc9354f2 100644 --- a/dom/filesystem/GetFileOrDirectoryTask.h +++ b/dom/filesystem/GetFileOrDirectoryTask.h @@ -31,9 +31,6 @@ public: already_AddRefed GetPromise(); - virtual void - GetPermissionAccessType(nsCString& aAccess) const override; - protected: virtual FileSystemParams GetRequestParams(const nsString& aSerializedDOMPath, @@ -65,9 +62,6 @@ public: FileSystemRequestParent* aParent, ErrorResult& aRv); - virtual void - GetPermissionAccessType(nsCString& aAccess) const override; - protected: virtual FileSystemResponseValue GetSuccessRequestResult(ErrorResult& aRv) const override; diff --git a/dom/filesystem/GetFilesTask.cpp b/dom/filesystem/GetFilesTask.cpp index 8dc972c1cdfa..02f0d538e260 100644 --- a/dom/filesystem/GetFilesTask.cpp +++ b/dom/filesystem/GetFilesTask.cpp @@ -149,12 +149,6 @@ GetFilesTaskChild::HandlerCallback() mPromise = nullptr; } -void -GetFilesTaskChild::GetPermissionAccessType(nsCString& aAccess) const -{ - aAccess.AssignLiteral("read"); -} - /** * GetFilesTaskParent */ @@ -259,11 +253,5 @@ GetFilesTaskParent::IOWork() return NS_OK; } -void -GetFilesTaskParent::GetPermissionAccessType(nsCString& aAccess) const -{ - aAccess.AssignLiteral(DIRECTORY_READ_PERMISSION); -} - } // namespace dom } // namespace mozilla diff --git a/dom/filesystem/GetFilesTask.h b/dom/filesystem/GetFilesTask.h index c2e89fa85da7..348b0c552c84 100644 --- a/dom/filesystem/GetFilesTask.h +++ b/dom/filesystem/GetFilesTask.h @@ -34,9 +34,6 @@ public: already_AddRefed GetPromise(); - virtual void - GetPermissionAccessType(nsCString& aAccess) const override; - private: // If aDirectoryOnly is set, we should ensure that the target is a directory. GetFilesTaskChild(FileSystemBase* aFileSystem, @@ -74,9 +71,6 @@ public: FileSystemRequestParent* aParent, ErrorResult& aRv); - virtual void - GetPermissionAccessType(nsCString& aAccess) const override; - private: GetFilesTaskParent(FileSystemBase* aFileSystem, const FileSystemGetFilesParams& aParam, diff --git a/dom/filesystem/OSFileSystem.cpp b/dom/filesystem/OSFileSystem.cpp index e083c65cecd3..1e9a5ddbd50e 100644 --- a/dom/filesystem/OSFileSystem.cpp +++ b/dom/filesystem/OSFileSystem.cpp @@ -19,12 +19,7 @@ namespace dom { OSFileSystem::OSFileSystem(const nsAString& aRootDir) { - mLocalOrDeviceStorageRootPath = aRootDir; - mPermissionCheckType = ePermissionCheckNotRequired; - -#ifdef DEBUG - mPermission.AssignLiteral("never-used"); -#endif + mLocalRootPath = aRootDir; } already_AddRefed @@ -32,7 +27,7 @@ OSFileSystem::Clone() { AssertIsOnOwningThread(); - RefPtr fs = new OSFileSystem(mLocalOrDeviceStorageRootPath); + RefPtr fs = new OSFileSystem(mLocalRootPath); if (mParent) { fs->Init(mParent); } @@ -102,7 +97,7 @@ void OSFileSystem::SerializeDOMPath(nsAString& aOutput) const { AssertIsOnOwningThread(); - aOutput = mLocalOrDeviceStorageRootPath; + aOutput = mLocalRootPath; } /** @@ -111,12 +106,7 @@ OSFileSystem::SerializeDOMPath(nsAString& aOutput) const OSFileSystemParent::OSFileSystemParent(const nsAString& aRootDir) { - mLocalOrDeviceStorageRootPath = aRootDir; - mPermissionCheckType = ePermissionCheckNotRequired; - -#ifdef DEBUG - mPermission.AssignLiteral("never-used"); -#endif + mLocalRootPath = aRootDir; } } // namespace dom diff --git a/dom/filesystem/compat/CallbackRunnables.cpp b/dom/filesystem/compat/CallbackRunnables.cpp index 7bfe43cef6bc..a4932f026866 100644 --- a/dom/filesystem/compat/CallbackRunnables.cpp +++ b/dom/filesystem/compat/CallbackRunnables.cpp @@ -20,7 +20,6 @@ #include "nsPIDOMWindow.h" #include "../GetFileOrDirectoryTask.h" -#include "../FileSystemPermissionRequest.h" namespace mozilla { namespace dom { @@ -163,7 +162,8 @@ GetEntryHelper::Run() } task->SetError(error); - FileSystemPermissionRequest::RequestForTask(task); + task->Start(); + RefPtr promise = task->GetPromise(); mParts.RemoveElementAt(0); diff --git a/dom/filesystem/moz.build b/dom/filesystem/moz.build index be2398b2034a..fa215ba9693b 100644 --- a/dom/filesystem/moz.build +++ b/dom/filesystem/moz.build @@ -12,7 +12,6 @@ DIRS += ['compat'] TEST_DIRS += ['tests'] EXPORTS.mozilla.dom += [ - 'DeviceStorageFileSystem.h', 'Directory.h', 'FileSystemBase.h', 'FileSystemRequestParent.h', @@ -23,10 +22,8 @@ EXPORTS.mozilla.dom += [ ] UNIFIED_SOURCES += [ - 'DeviceStorageFileSystem.cpp', 'Directory.cpp', 'FileSystemBase.cpp', - 'FileSystemPermissionRequest.cpp', 'FileSystemRequestParent.cpp', 'FileSystemTaskBase.cpp', 'FileSystemUtils.cpp', diff --git a/ipc/glue/BackgroundParentImpl.cpp b/ipc/glue/BackgroundParentImpl.cpp index f2a2b8cb119e..5f725cc74cdd 100644 --- a/ipc/glue/BackgroundParentImpl.cpp +++ b/ipc/glue/BackgroundParentImpl.cpp @@ -540,81 +540,6 @@ private: nsCString mOrigin; }; -class CheckPermissionRunnable final : public Runnable -{ -public: - CheckPermissionRunnable(already_AddRefed aParent, - FileSystemRequestParent* aActor, - FileSystemBase::ePermissionCheckType aPermissionCheckType, - const nsCString& aPermissionName) - : mContentParent(aParent) - , mActor(aActor) - , mPermissionCheckType(aPermissionCheckType) - , mPermissionName(aPermissionName) - , mBackgroundEventTarget(NS_GetCurrentThread()) - { - AssertIsInMainProcess(); - AssertIsOnBackgroundThread(); - - MOZ_ASSERT(mContentParent); - MOZ_ASSERT(mBackgroundEventTarget); - MOZ_ASSERT(mPermissionCheckType == FileSystemBase::ePermissionCheckRequired || - mPermissionCheckType == FileSystemBase::ePermissionCheckByTestingPref); - } - - NS_IMETHOD - Run() override - { - if (NS_IsMainThread()) { - NullifyContentParentRAII raii(mContentParent); - - // If the permission is granted, we go back to the background thread to - // dispatch this task. - if (CheckPermission()) { - return mBackgroundEventTarget->Dispatch(this, NS_DISPATCH_NORMAL); - } - - return NS_OK; - } - - AssertIsOnBackgroundThread(); - - // It can happen that this actor has been destroyed in the meantime we were - // on the main-thread. - if (!mActor->Destroyed()) { - mActor->Start(); - } - - return NS_OK; - } - -private: - ~CheckPermissionRunnable() override - { - NS_ProxyRelease(mBackgroundEventTarget, mActor.forget()); - } - - bool - CheckPermission() - { - if (mPermissionCheckType == FileSystemBase::ePermissionCheckByTestingPref && - mozilla::Preferences::GetBool("device.storage.prompt.testing", false)) { - return true; - } - - return true; - } - - RefPtr mContentParent; - - RefPtr mActor; - - FileSystemBase::ePermissionCheckType mPermissionCheckType; - nsCString mPermissionName; - - nsCOMPtr mBackgroundEventTarget; -}; - } // namespace mozilla::ipc::IPCResult @@ -846,48 +771,11 @@ BackgroundParentImpl::AllocPFileSystemRequestParent( return nullptr; } + result->Start(); + return result.forget().take(); } -mozilla::ipc::IPCResult -BackgroundParentImpl::RecvPFileSystemRequestConstructor( - PFileSystemRequestParent* aActor, - const FileSystemParams& aParams) -{ - AssertIsInMainProcess(); - AssertIsOnBackgroundThread(); - - RefPtr actor = static_cast(aActor); - - if (actor->PermissionCheckType() == FileSystemBase::ePermissionCheckNotRequired) { - actor->Start(); - return IPC_OK(); - } - - RefPtr parent = BackgroundParent::GetContentParent(this); - - // If the ContentParent is null we are dealing with a same-process actor. - if (!parent) { - actor->Start(); - return IPC_OK(); - } - - const nsCString& permissionName = actor->PermissionName(); - MOZ_ASSERT(!permissionName.IsEmpty()); - - // At this point we should have the right permission but we do the last check - // with this runnable. If the app doesn't have the permission, we kill the - // child process. - RefPtr runnable = - new CheckPermissionRunnable(parent.forget(), actor, - actor->PermissionCheckType(), permissionName); - - nsresult rv = NS_DispatchToMainThread(runnable); - MOZ_ALWAYS_TRUE(NS_SUCCEEDED(rv)); - - return IPC_OK(); -} - bool BackgroundParentImpl::DeallocPFileSystemRequestParent( PFileSystemRequestParent* aDoomed) diff --git a/ipc/glue/BackgroundParentImpl.h b/ipc/glue/BackgroundParentImpl.h index b8887e861bc0..a2b29a222e76 100644 --- a/ipc/glue/BackgroundParentImpl.h +++ b/ipc/glue/BackgroundParentImpl.h @@ -187,10 +187,6 @@ protected: virtual PFileSystemRequestParent* AllocPFileSystemRequestParent(const FileSystemParams&) override; - virtual mozilla::ipc::IPCResult - RecvPFileSystemRequestConstructor(PFileSystemRequestParent* aActor, - const FileSystemParams& aParams) override; - virtual bool DeallocPFileSystemRequestParent(PFileSystemRequestParent*) override; From c91e65240b0e725232e3cd214b61e5aa43a8cb34 Mon Sep 17 00:00:00 2001 From: Shu-yu Guo Date: Wed, 8 Mar 2017 12:00:54 -0800 Subject: [PATCH 47/57] Bug 1108941 - Implement the per-global template literal registry. (r=arai,jonco) --- js/public/MemoryMetrics.h | 1 + js/src/jit/BaselineCompiler.cpp | 4 +- js/src/jit/IonBuilder.cpp | 1 + js/src/jscompartment.cpp | 67 ++++++++++++++++++++++++++++++- js/src/jscompartment.h | 15 +++++++ js/src/vm/Interpreter-inl.h | 19 --------- js/src/vm/Interpreter.cpp | 4 +- js/src/vm/MemoryMetrics.cpp | 1 + js/src/vm/TemplateRegistry.h | 38 ++++++++++++++++++ js/xpconnect/src/XPCJSContext.cpp | 4 ++ 10 files changed, 128 insertions(+), 26 deletions(-) create mode 100644 js/src/vm/TemplateRegistry.h diff --git a/js/public/MemoryMetrics.h b/js/public/MemoryMetrics.h index b377ad5e9b68..b0b0333eb2f9 100644 --- a/js/public/MemoryMetrics.h +++ b/js/public/MemoryMetrics.h @@ -767,6 +767,7 @@ struct CompartmentStats macro(Other, MallocHeap, savedStacksSet) \ macro(Other, MallocHeap, varNamesSet) \ macro(Other, MallocHeap, nonSyntacticLexicalScopesTable) \ + macro(Other, MallocHeap, templateLiteralMap) \ macro(Other, MallocHeap, jitCompartment) \ macro(Other, MallocHeap, privateData) diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp index 5a3aa11d9fb8..6a4dd361bf83 100644 --- a/js/src/jit/BaselineCompiler.cpp +++ b/js/src/jit/BaselineCompiler.cpp @@ -1657,10 +1657,8 @@ BaselineCompiler::emit_JSOP_CALLSITEOBJ() RootedObject raw(cx, script->getObject(GET_UINT32_INDEX(pc) + 1)); if (!cso || !raw) return false; - RootedValue rawValue(cx); - rawValue.setObject(*raw); - if (!ProcessCallSiteObjOperation(cx, cso, raw, rawValue)) + if (!cx->compartment()->getTemplateLiteralObject(cx, raw, &cso)) return false; frame.push(ObjectValue(*cso)); diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index ca3a13dfcf4c..7b223e23dda1 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -2185,6 +2185,7 @@ IonBuilder::inspectOpcode(JSOp op) return jsop_regexp(info().getRegExp(pc)); case JSOP_CALLSITEOBJ: + // TODO this is wrong, need threadsafe way to get unique template obj pushConstant(ObjectValue(*(info().getObject(pc)))); return Ok(); diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 0eecf1302409..7ceddb740517 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -155,7 +155,7 @@ JSCompartment::init(JSContext* maybecx) if (!enumerators) return false; - if (!savedStacks_.init() || !varNames_.init()) { + if (!savedStacks_.init() || !varNames_.init() || !templateLiteralMap_.init()) { if (maybecx) ReportOutOfMemory(maybecx); return false; @@ -599,6 +599,64 @@ JSCompartment::addToVarNames(JSContext* cx, JS::Handle name) return false; } +/* static */ HashNumber +TemplateRegistryHashPolicy::hash(const Lookup& lookup) +{ + size_t length = GetAnyBoxedOrUnboxedInitializedLength(lookup); + HashNumber hash = 0; + for (uint32_t i = 0; i < length; i++) { + JSAtom& lookupAtom = GetAnyBoxedOrUnboxedDenseElement(lookup, i).toString()->asAtom(); + hash = mozilla::AddToHash(hash, lookupAtom.hash()); + } + return hash; +} + +/* static */ bool +TemplateRegistryHashPolicy::match(const Key& key, const Lookup& lookup) +{ + size_t length = GetAnyBoxedOrUnboxedInitializedLength(lookup); + if (GetAnyBoxedOrUnboxedInitializedLength(key) != length) + return false; + + for (uint32_t i = 0; i < length; i++) { + JSAtom* a = &GetAnyBoxedOrUnboxedDenseElement(key, i).toString()->asAtom(); + JSAtom* b = &GetAnyBoxedOrUnboxedDenseElement(lookup, i).toString()->asAtom(); + if (a != b) + return false; + } + + return true; +} + +bool +JSCompartment::getTemplateLiteralObject(JSContext* cx, HandleObject rawStrings, + MutableHandleObject templateObj) +{ + if (TemplateRegistry::AddPtr p = templateLiteralMap_.lookupForAdd(rawStrings)) { + templateObj.set(p->value()); + + // The template object must have been frozen when it was added to the + // registry. + MOZ_ASSERT(!templateObj->nonProxyIsExtensible()); + } else { + // Add the template object to the registry before freezing to avoid + // needing to call relookupOrAdd. + if (!templateLiteralMap_.add(p, rawStrings, templateObj)) + return false; + + MOZ_ASSERT(templateObj->nonProxyIsExtensible()); + RootedValue rawValue(cx, ObjectValue(*rawStrings)); + if (!DefineProperty(cx, templateObj, cx->names().raw, rawValue, nullptr, nullptr, 0)) + return false; + if (!FreezeObject(cx, rawStrings)) + return false; + if (!FreezeObject(cx, templateObj)) + return false; + } + + return true; +} + void JSCompartment::traceOutgoingCrossCompartmentWrappers(JSTracer* trc) { @@ -636,6 +694,10 @@ JSCompartment::trace(JSTracer* trc) { savedStacks_.trace(trc); + // The template registry strongly holds everything in it by design and + // spec. + templateLiteralMap_.trace(trc); + // Atoms are always tenured. if (!JS::CurrentThreadIsHeapMinorCollecting()) varNames_.trace(trc); @@ -976,6 +1038,7 @@ JSCompartment::clearTables() MOZ_ASSERT(!debugEnvs); MOZ_ASSERT(enumerators->next() == enumerators); MOZ_ASSERT(regExps.empty()); + MOZ_ASSERT(templateLiteralMap_.empty()); objectGroups.clearTables(); if (savedStacks_.initialized()) @@ -1243,6 +1306,7 @@ JSCompartment::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, size_t* savedStacksSet, size_t* varNamesSet, size_t* nonSyntacticLexicalEnvironmentsArg, + size_t* templateLiteralMap, size_t* jitCompartment, size_t* privateData) { @@ -1263,6 +1327,7 @@ JSCompartment::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, if (nonSyntacticLexicalEnvironments_) *nonSyntacticLexicalEnvironmentsArg += nonSyntacticLexicalEnvironments_->sizeOfIncludingThis(mallocSizeOf); + *templateLiteralMap += templateLiteralMap_.sizeOfExcludingThis(mallocSizeOf); if (jitCompartment_) *jitCompartment += jitCompartment_->sizeOfIncludingThis(mallocSizeOf); diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index 9f25a6bfde06..9d44217ac575 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -21,6 +21,7 @@ #include "vm/GlobalObject.h" #include "vm/PIC.h" #include "vm/SavedStacks.h" +#include "vm/TemplateRegistry.h" #include "vm/Time.h" #include "wasm/WasmCompartment.h" @@ -545,6 +546,7 @@ struct JSCompartment size_t* savedStacksSet, size_t* varNamesSet, size_t* nonSyntacticLexicalScopes, + size_t* templateLiteralMap, size_t* jitCompartment, size_t* privateData); @@ -586,6 +588,12 @@ struct JSCompartment // to use the same lexical environment to persist lexical bindings. js::ObjectWeakMap* nonSyntacticLexicalEnvironments_; + // The realm's [[TemplateMap]], used for mapping template literals to + // unique template objects used in evaluation of tagged template literals. + // + // See ES 12.2.9.3. + js::TemplateRegistry templateLiteralMap_; + public: /* During GC, stores the index of this compartment in rt->compartments. */ unsigned gcIndex; @@ -743,6 +751,13 @@ struct JSCompartment return varNames_.has(name); } + // Get a unique template object given a JS array of raw template strings + // and a template object. If a template object is found in template + // registry, that object is returned. Otherwise, the passed-in templateObj + // is added to the registry. + bool getTemplateLiteralObject(JSContext* cx, js::HandleObject rawStrings, + js::MutableHandleObject templateObj); + void findOutgoingEdges(js::gc::ZoneComponentFinder& finder); MOZ_MUST_USE bool findDeadProxyZoneEdges(bool* foundAny); diff --git a/js/src/vm/Interpreter-inl.h b/js/src/vm/Interpreter-inl.h index 0f474f71578f..857f3bf96c76 100644 --- a/js/src/vm/Interpreter-inl.h +++ b/js/src/vm/Interpreter-inl.h @@ -664,25 +664,6 @@ InitArrayElemOperation(JSContext* cx, jsbytecode* pc, HandleObject obj, uint32_t return true; } -static MOZ_ALWAYS_INLINE bool -ProcessCallSiteObjOperation(JSContext* cx, RootedObject& cso, RootedObject& raw, - RootedValue& rawValue) -{ - bool extensible; - if (!IsExtensible(cx, cso, &extensible)) - return false; - if (extensible) { - JSAtom* name = cx->names().raw; - if (!DefineProperty(cx, cso, name->asPropertyName(), rawValue, nullptr, nullptr, 0)) - return false; - if (!FreezeObject(cx, raw)) - return false; - if (!FreezeObject(cx, cso)) - return false; - } - return true; -} - #define RELATIONAL_OP(OP) \ JS_BEGIN_MACRO \ /* Optimize for two int-tagged operands (typical loop control). */ \ diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index b23957331aa8..e32c7fb2da37 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -3187,12 +3187,10 @@ END_CASE(JSOP_OBJECT) CASE(JSOP_CALLSITEOBJ) { - ReservedRooted cso(&rootObject0, script->getObject(REGS.pc)); ReservedRooted raw(&rootObject1, script->getObject(GET_UINT32_INDEX(REGS.pc) + 1)); - ReservedRooted rawValue(&rootValue0, ObjectValue(*raw)); - if (!ProcessCallSiteObjOperation(cx, cso, raw, rawValue)) + if (!cx->compartment()->getTemplateLiteralObject(cx, raw, &cso)) goto error; PUSH_OBJECT(*cso); diff --git a/js/src/vm/MemoryMetrics.cpp b/js/src/vm/MemoryMetrics.cpp index fc9ab9149607..60ba28f6a65d 100644 --- a/js/src/vm/MemoryMetrics.cpp +++ b/js/src/vm/MemoryMetrics.cpp @@ -357,6 +357,7 @@ StatsCompartmentCallback(JSContext* cx, void* data, JSCompartment* compartment) &cStats.savedStacksSet, &cStats.varNamesSet, &cStats.nonSyntacticLexicalScopesTable, + &cStats.templateLiteralMap, &cStats.jitCompartment, &cStats.privateData); } diff --git a/js/src/vm/TemplateRegistry.h b/js/src/vm/TemplateRegistry.h new file mode 100644 index 000000000000..bc22124196c8 --- /dev/null +++ b/js/src/vm/TemplateRegistry.h @@ -0,0 +1,38 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * 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 vm_TemplateRegistry_h +#define vm_TemplateRegistry_h + +#include "jsobj.h" +#include "js/GCHashTable.h" +#include "gc/Marking.h" + +namespace js { + +// Data structures to maintain unique template objects mapped to by lists of +// raw strings. +// +// See ES 12.2.9.3. + +struct TemplateRegistryHashPolicy +{ + // For use as HashPolicy. Expects keys as arrays of atoms. + using Key = JSObject*; + using Lookup = JSObject*; + + static HashNumber hash(const Lookup& lookup); + static bool match(const Key& key, const Lookup& lookup); +}; + +using TemplateRegistry = JS::GCHashMap; + +} // namespace js + +#endif // vm_TemplateRegistery_h diff --git a/js/xpconnect/src/XPCJSContext.cpp b/js/xpconnect/src/XPCJSContext.cpp index d52bd6f1b9ea..f73f55dba2f9 100644 --- a/js/xpconnect/src/XPCJSContext.cpp +++ b/js/xpconnect/src/XPCJSContext.cpp @@ -2338,6 +2338,10 @@ ReportCompartmentStats(const JS::CompartmentStats& cStats, cStats.nonSyntacticLexicalScopesTable, "The non-syntactic lexical scopes table."); + ZCREPORT_BYTES(cJSPathPrefix + NS_LITERAL_CSTRING("template-literal-map"), + cStats.templateLiteralMap, + "The template literal registry."); + ZCREPORT_BYTES(cJSPathPrefix + NS_LITERAL_CSTRING("jit-compartment"), cStats.jitCompartment, "The JIT compartment."); From 7170b1291a4ea89eaa237bdb96267304c10c2312 Mon Sep 17 00:00:00 2001 From: Shu-yu Guo Date: Wed, 8 Mar 2017 12:00:54 -0800 Subject: [PATCH 48/57] Bug 1108941 - Use the template literal registry in Ion. (r=jandem) --- js/src/jit/IonBuilder.cpp | 7 +++++-- js/src/jscompartment.cpp | 8 ++++++++ js/src/jscompartment.h | 3 +++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index 7b223e23dda1..c05f685add2f 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -2185,9 +2185,12 @@ IonBuilder::inspectOpcode(JSOp op) return jsop_regexp(info().getRegExp(pc)); case JSOP_CALLSITEOBJ: - // TODO this is wrong, need threadsafe way to get unique template obj - pushConstant(ObjectValue(*(info().getObject(pc)))); + { + JSObject* raw = script()->getObject(GET_UINT32_INDEX(pc) + 1); + JSObject* obj = script()->compartment()->getExistingTemplateLiteralObject(raw); + pushConstant(ObjectValue(*obj)); return Ok(); + } case JSOP_OBJECT: return jsop_object(info().getObject(pc)); diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 7ceddb740517..28bda78eb362 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -657,6 +657,14 @@ JSCompartment::getTemplateLiteralObject(JSContext* cx, HandleObject rawStrings, return true; } +JSObject* +JSCompartment::getExistingTemplateLiteralObject(JSObject* rawStrings) +{ + TemplateRegistry::Ptr p = templateLiteralMap_.lookup(rawStrings); + MOZ_ASSERT(p); + return p->value(); +} + void JSCompartment::traceOutgoingCrossCompartmentWrappers(JSTracer* trc) { diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index 9d44217ac575..4791b7ba6bcb 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -758,6 +758,9 @@ struct JSCompartment bool getTemplateLiteralObject(JSContext* cx, js::HandleObject rawStrings, js::MutableHandleObject templateObj); + // Per above, but an entry must already exist in the template registry. + JSObject* getExistingTemplateLiteralObject(JSObject* rawStrings); + void findOutgoingEdges(js::gc::ZoneComponentFinder& finder); MOZ_MUST_USE bool findDeadProxyZoneEdges(bool* foundAny); From 6237b16a43dad578fcb4ee5ac252bda716285650 Mon Sep 17 00:00:00 2001 From: Shu-yu Guo Date: Wed, 8 Mar 2017 12:00:55 -0800 Subject: [PATCH 49/57] Bug 1108941 - Update tests and whitelist failing test262 tests. --- js/src/tests/ecma_6/TemplateStrings/tagTempl.js | 5 +++-- js/src/tests/jstests.list | 8 -------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/js/src/tests/ecma_6/TemplateStrings/tagTempl.js b/js/src/tests/ecma_6/TemplateStrings/tagTempl.js index 1ed93a311cf7..2d452dcfa005 100644 --- a/js/src/tests/ecma_6/TemplateStrings/tagTempl.js +++ b/js/src/tests/ecma_6/TemplateStrings/tagTempl.js @@ -202,7 +202,8 @@ for (var i = 1; i < 3; i++) // Same call site object behavior assertEq(callSiteObj[1], callSiteObj[2]); -assertEq(callSiteObj[0] !== callSiteObj[1], true); +// Template objects are canonicalized +assertEq(callSiteObj[0], callSiteObj[1]); assertEq("raw" in callSiteObj[0], true); // Array length @@ -226,7 +227,7 @@ function test() { a[i] = eval("x``"); } test(); -assertEq(a[0] !== a[1], true); +assertEq(a[0], a[1]); // Test that |obj.method`template`| works var newObj = { diff --git a/js/src/tests/jstests.list b/js/src/tests/jstests.list index 7f833a985074..32ffd488cffb 100644 --- a/js/src/tests/jstests.list +++ b/js/src/tests/jstests.list @@ -380,14 +380,6 @@ skip script test262/built-ins/DataView/prototype/byteLength/detached-buffer.js skip script test262/language/statements/class/subclass/class-definition-null-proto-missing-return-override.js skip script test262/language/statements/class/subclass/class-definition-null-proto-this.js -# https://bugzilla.mozilla.org/show_bug.cgi?id=1108941 -skip script test262/language/expressions/tagged-template/cache-differing-expressions.js -skip script test262/language/expressions/tagged-template/cache-differing-expressions-eval.js -skip script test262/language/expressions/tagged-template/cache-differing-expressions-new-function.js -skip script test262/language/expressions/tagged-template/cache-identical-source.js -skip script test262/language/expressions/tagged-template/cache-identical-source-new-function.js -skip script test262/language/expressions/tagged-template/cache-identical-source-eval.js - # We're still waiting for a final decision on https://github.com/tc39/ecma402/pull/84. skip script test262/intl402/Collator/10.1.1_1.js skip script test262/intl402/NumberFormat/11.1.1_1.js From 3de9e6575373ad35a5cc61471558663e3f07fa16 Mon Sep 17 00:00:00 2001 From: Kim Moir Date: Wed, 8 Mar 2017 15:22:44 -0500 Subject: [PATCH 50/57] Bug 1345157 - Linux builds not running on-push on mozilla-beta r=aki DONTBUILD --- taskcluster/taskgraph/target_tasks.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/taskcluster/taskgraph/target_tasks.py b/taskcluster/taskgraph/target_tasks.py index 4160ff7a1076..c8ff7ec0c3f0 100644 --- a/taskcluster/taskgraph/target_tasks.py +++ b/taskcluster/taskgraph/target_tasks.py @@ -199,7 +199,6 @@ def target_tasks_nightly_linux(full_task_graph, parameters): return task.attributes.get('nightly', False) return [l for l, t in full_task_graph.tasks.iteritems() if filter(t)] - @_target_task('mozilla_beta_tasks') def target_tasks_mozilla_beta(full_task_graph, parameters): """Select the set of tasks required for a promotable beta or release build @@ -207,9 +206,15 @@ def target_tasks_mozilla_beta(full_task_graph, parameters): of builds and signing, but does not include beetmover or balrog jobs.""" def filter(task): platform = task.attributes.get('build_platform') - if platform in ('android-api-15', 'android-x86'): + if platform in ('android-api-15', 'android-x86', 'linux64-asan', + 'linux64-pgo', 'linux64-add-on-devel'): return True + if platform in ('linux64', 'linux'): + if task.attributes['build_type'] == 'debug': + return True if platform in ('linux64-nightly', 'linux-nightly'): + if task.kind in ["test"]: + return True if task.kind not in [ 'balrog', 'beetmover', 'beetmover-checksums', 'beetmover-l10n', 'checksums-signing', 'nightly-l10n', 'nightly-l10n-signing' From 7a19f87fd9e17e225adfa7c62cfe9d00d3d42908 Mon Sep 17 00:00:00 2001 From: Randell Jesup Date: Wed, 8 Mar 2017 00:24:21 -0500 Subject: [PATCH 51/57] Bug 1339246: force rebuild of Send/RecvStream if the SSRCs have been changed r=bwc MozReview-Commit-ID: HWZ8MXjtWzg --- .../signaling/src/media-conduit/VideoConduit.cpp | 14 +++++++++++--- .../signaling/src/media-conduit/VideoConduit.h | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp b/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp index dfea335b12b0..29ef05f8c4fe 100755 --- a/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp +++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp @@ -271,9 +271,11 @@ bool WebrtcVideoConduit::SetLocalSSRCs(const std::vector & aSSRCs) return false; } + MutexAutoLock lock(mCodecMutex); + // On the next StartTransmitting() or ConfigureSendMediaCodec, force + // building a new SendStream to switch SSRCs. + DeleteSendStream(); if (wasTransmitting) { - MutexAutoLock lock(mCodecMutex); - DeleteSendStream(); if (StartTransmitting() != kMediaConduitNoError) { return false; } @@ -699,10 +701,11 @@ WebrtcVideoConduit::SetRemoteSSRC(unsigned int ssrc) } mRecvSSRCSet = true; - if (current_ssrc == ssrc || !mEngineReceiving) { + if (current_ssrc == ssrc) { return true; } + bool wasReceiving = mEngineReceiving; if (StopReceiving() != kMediaConduitNoError) { return false; } @@ -713,7 +716,12 @@ WebrtcVideoConduit::SetRemoteSSRC(unsigned int ssrc) // All non-MainThread users must lock before reading/using { MutexAutoLock lock(mCodecMutex); + // On the next StartReceiving() or ConfigureRecvMediaCodec, force + // building a new RecvStream to switch SSRCs. DeleteRecvStream(); + if (!wasReceiving) { + return true; + } MediaConduitErrorCode rval = CreateRecvStream(); if (rval != kMediaConduitNoError) { CSFLogError(logTag, "%s Start Receive Error %d ", __FUNCTION__, rval); diff --git a/media/webrtc/signaling/src/media-conduit/VideoConduit.h b/media/webrtc/signaling/src/media-conduit/VideoConduit.h index 84321b97c451..78d0121ea176 100755 --- a/media/webrtc/signaling/src/media-conduit/VideoConduit.h +++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.h @@ -457,7 +457,7 @@ private: //Local database of currently applied receive codecs nsTArray> mRecvCodecList; - // protects mCurrSendCodecConfig, mInReconfig,mVideoSend/RecvStreamStats, mSend/RecvStreams + // protects mCurSendCodecConfig, mInReconfig,mVideoSend/RecvStreamStats, mSend/RecvStreams Mutex mCodecMutex; nsAutoPtr mCurSendCodecConfig; bool mInReconfig; From b45d50e7b45895ebc7cb50915aa0ffdf12fa92d2 Mon Sep 17 00:00:00 2001 From: Kim Moir Date: Wed, 8 Mar 2017 15:40:37 -0500 Subject: [PATCH 52/57] Bug 1345157 - Linux builds not running on-push on mozilla-beta r=aki DONTBUILD --- taskcluster/taskgraph/target_tasks.py | 1 + 1 file changed, 1 insertion(+) diff --git a/taskcluster/taskgraph/target_tasks.py b/taskcluster/taskgraph/target_tasks.py index c8ff7ec0c3f0..914bdd4b06a7 100644 --- a/taskcluster/taskgraph/target_tasks.py +++ b/taskcluster/taskgraph/target_tasks.py @@ -199,6 +199,7 @@ def target_tasks_nightly_linux(full_task_graph, parameters): return task.attributes.get('nightly', False) return [l for l, t in full_task_graph.tasks.iteritems() if filter(t)] + @_target_task('mozilla_beta_tasks') def target_tasks_mozilla_beta(full_task_graph, parameters): """Select the set of tasks required for a promotable beta or release build From 90071c5f6964998788d29dd449ebad4359d77339 Mon Sep 17 00:00:00 2001 From: Aaron Klotz Date: Thu, 2 Mar 2017 17:39:01 -0700 Subject: [PATCH 53/57] Bug 1344798: Allow mscom::AsyncInvoker to be able to handle proxied and non-proxied interfaces; r=jimm MozReview-Commit-ID: 6lQg6fwuvmw --HG-- extra : histedit_source : 28d66eb2ec245b8ca41baba85c7a74ecbc3341f2 --- ipc/mscom/AsyncInvoker.h | 117 +++++++++++++++++++++++++++++---------- 1 file changed, 87 insertions(+), 30 deletions(-) diff --git a/ipc/mscom/AsyncInvoker.h b/ipc/mscom/AsyncInvoker.h index 182764ec65ee..f44a61c126a8 100644 --- a/ipc/mscom/AsyncInvoker.h +++ b/ipc/mscom/AsyncInvoker.h @@ -10,6 +10,7 @@ #include "mozilla/Assertions.h" #include "mozilla/Attributes.h" #include "mozilla/DebugOnly.h" +#include "mozilla/Maybe.h" #include "mozilla/Move.h" #include "mozilla/mscom/Aggregation.h" #include "mozilla/mscom/Utils.h" @@ -194,7 +195,8 @@ public: HRESULT Wait(DWORD aTimeout = INFINITE) const { if (!mAsyncCall) { - return E_POINTER; + // Nothing to wait for + return S_OK; } return mAsyncCall->Wait(0, aTimeout); @@ -211,89 +213,144 @@ protected: /** * This class is intended for "fire-and-forget" asynchronous invocations of COM * interfaces. This requires that an interface be annotated with the - * |async_uuid| attribute in midl. + * |async_uuid| attribute in midl. We also require that there be no outparams + * in the desired asynchronous interface (otherwise that would break the + * desired "fire-and-forget" semantics). * * For example, let us suppose we have some IDL as such: * [object, uuid(...), async_uuid(...)] * interface IFoo : IUnknown * { - * HRESULT Bar(long baz); + * HRESULT Bar([in] long baz); * } * - * Then, given an IFoo, we may construct an AsyncInvoker: + * Then, given an IFoo, we may construct an AsyncInvoker: * * IFoo* foo = ...; - * AsyncInvoker myInvoker(foo); - * HRESULT hr = myInvoker->Begin_Bar(7); + * AsyncInvoker myInvoker(foo); + * HRESULT hr = myInvoker.Invoke(&IFoo::Bar, &AsyncIFoo::Begin_Bar, 7); * - * Alternatively you may use the ASYNC_INVOKER_FOR macro, which automatically - * derives the name of the asynchronous interface from the name of the - * synchronous interface: + * Alternatively you may use the ASYNC_INVOKER_FOR and ASYNC_INVOKE macros, + * which automatically deduce the name of the asynchronous interface from the + * name of the synchronous interface: * * ASYNC_INVOKER_FOR(IFoo) myInvoker(foo); + * HRESULT hr = ASYNC_INVOKE(myInvoker, Bar, 7); * * This class may also be used when a synchronous COM call must be made that * might reenter the content process. In this case, use the WaitableAsyncInvoker * variant, or the WAITABLE_ASYNC_INVOKER_FOR macro: * * WAITABLE_ASYNC_INVOKER_FOR(Ifoo) myInvoker(foo); - * myInvoker->Begin_Bar(7); - * myInvoker.Wait(); // <-- Wait for the COM call to complete. + * HRESULT hr = ASYNC_INVOKE(myInvoker, Bar, 7); + * if (SUCCEEDED(hr)) { + * myInvoker.Wait(); // <-- Wait for the COM call to complete. + * } * * In general you should avoid using the waitable version, but in some corner * cases it is absolutely necessary in order to preserve correctness while * avoiding deadlock. */ -template class WaitPolicy = detail::FireAndForgetInvoker> class MOZ_RAII AsyncInvoker final : public WaitPolicy { public: + typedef SyncInterface SyncInterfaceT; + typedef AsyncInterface AsyncInterfaceT; + /** - * @param aSyncProxy The COM object on which to invoke the asynchronous event. - * This object must be a proxy to the synchronous variant of - * AsyncInterface. + * @param aSyncObj The COM object on which to invoke the asynchronous event. + * If this object is not a proxy to the synchronous variant + * of AsyncInterface, then it will be invoked synchronously + * instead (because it is an in-process virtual method call). + * @param aIsProxy An optional hint as to whether or not aSyncObj is a proxy. + * If not specified, AsyncInvoker will automatically detect + * whether aSyncObj is a proxy, however there may be a + * performance penalty associated with that. */ - explicit AsyncInvoker(IUnknown* aSyncProxy) + explicit AsyncInvoker(SyncInterface* aSyncObj, Maybe aIsProxy = Nothing()) + : mSyncObj(ResolveIsProxy(aSyncObj, aIsProxy) ? nullptr : aSyncObj) { - MOZ_ASSERT(aSyncProxy); - MOZ_ASSERT(IsProxy(aSyncProxy)); + MOZ_ASSERT(aSyncObj); + + if (mSyncObj) { + return; + } RefPtr callFactory; - if (FAILED(aSyncProxy->QueryInterface(IID_ICallFactory, - getter_AddRefs(callFactory)))) { + if (FAILED(aSyncObj->QueryInterface(IID_ICallFactory, + getter_AddRefs(callFactory)))) { return; } mAsyncCall = new AsyncCallType(callFactory); } - explicit operator bool() const + /** + * @brief Invoke a method on the object. Member function pointers are provided + * for both the sychronous and asynchronous variants of the interface. + * If this invoker's encapsulated COM object is a proxy, then Invoke + * will call the asynchronous member function. Otherwise the + * synchronous version must be used, as the invocation will simply be a + * virtual function call that executes in-process. + * @param aSyncMethod Pointer to the method that we would like to invoke on + * the synchronous interface. + * @param aAsyncMethod Pointer to the method that we would like to invoke on + * the asynchronous interface. + */ + template + HRESULT Invoke(SyncMethod aSyncMethod, AsyncMethod aAsyncMethod, Args... aArgs) { - return mAsyncCall && mAsyncCall->GetInterface(); - } + if (mSyncObj) { + return (mSyncObj->*aSyncMethod)(Forward(aArgs)...); + } - AsyncInterface* operator->() const - { - return mAsyncCall->GetInterface(); + MOZ_ASSERT(mAsyncCall); + if (!mAsyncCall) { + return E_POINTER; + } + + AsyncInterface* asyncInterface = mAsyncCall->GetInterface(); + MOZ_ASSERT(asyncInterface); + if (!asyncInterface) { + return E_POINTER; + } + + return (asyncInterface->*aAsyncMethod)(Forward(aArgs)...); } AsyncInvoker(const AsyncInvoker& aOther) = delete; AsyncInvoker(AsyncInvoker&& aOther) = delete; AsyncInvoker& operator=(const AsyncInvoker& aOther) = delete; AsyncInvoker& operator=(AsyncInvoker&& aOther) = delete; + +private: + static bool ResolveIsProxy(SyncInterface* aSyncObj, const Maybe& aIsProxy) + { + MOZ_ASSERT(aSyncObj); + return aIsProxy.isSome() ? aIsProxy.value() : IsProxy(aSyncObj); + } + +private: + RefPtr mSyncObj; }; -template -using WaitableAsyncInvoker = AsyncInvoker; +template +using WaitableAsyncInvoker = AsyncInvoker; } // namespace mscom } // namespace mozilla #define ASYNC_INVOKER_FOR(SyncIface) \ - mozilla::mscom::AsyncInvoker + mozilla::mscom::AsyncInvoker #define WAITABLE_ASYNC_INVOKER_FOR(SyncIface) \ - mozilla::mscom::WaitableAsyncInvoker + mozilla::mscom::WaitableAsyncInvoker + +#define ASYNC_INVOKE(InvokerObj, SyncMethodName, ...) \ + InvokerObj.Invoke(&decltype(InvokerObj)::SyncInterfaceT::SyncMethodName, \ + &decltype(InvokerObj)::AsyncInterfaceT::Begin_##SyncMethodName, \ + __VA_ARGS__) #endif // mozilla_mscom_AsyncInvoker_h From 116698fb6bb90cd64505edf287e3572e57cdf4ca Mon Sep 17 00:00:00 2001 From: Aaron Klotz Date: Mon, 6 Mar 2017 17:22:43 -0700 Subject: [PATCH 54/57] Bug 1344965: Clean up mscom interfaces to improve separation of concerns; r=jimm MozReview-Commit-ID: C96y3i8hjWs --HG-- extra : histedit_source : 8cee3ff07ecd0310ac9648d903328d54588d3dde --- ipc/mscom/IHandlerPayload.h | 6 +- ipc/mscom/Interceptor.cpp | 23 +++--- ipc/mscom/Interceptor.h | 6 +- ipc/mscom/MainThreadHandoff.cpp | 14 ++-- ipc/mscom/MainThreadHandoff.h | 4 +- ipc/mscom/MainThreadInvoker.h | 16 ++++ ipc/mscom/Ptr.h | 138 +++++++++++++++++++++++++++++++- 7 files changed, 185 insertions(+), 22 deletions(-) diff --git a/ipc/mscom/IHandlerPayload.h b/ipc/mscom/IHandlerPayload.h index c2edec331d64..e82d2e8244cc 100644 --- a/ipc/mscom/IHandlerPayload.h +++ b/ipc/mscom/IHandlerPayload.h @@ -7,6 +7,8 @@ #ifndef mozilla_mscom_IHandlerPayload_h #define mozilla_mscom_IHandlerPayload_h +#include "mozilla/mscom/Ptr.h" + #include namespace mozilla { @@ -16,10 +18,10 @@ struct HandlerPayload { virtual STDMETHODIMP GetHandler(CLSID* aHandlerClsid) = 0; virtual STDMETHODIMP GetHandlerPayloadSize(REFIID aIid, - IUnknown* aTarget, + InterceptorTargetPtr aTarget, DWORD* aOutPayloadSize) = 0; virtual STDMETHODIMP WriteHandlerPayload(IStream* aStream, REFIID aIid, - IUnknown* aTarget) = 0; + InterceptorTargetPtr aTarget) = 0; virtual REFIID MarshalAs(REFIID aIid) = 0; }; diff --git a/ipc/mscom/Interceptor.cpp b/ipc/mscom/Interceptor.cpp index 369050a83f3d..8ebe477110d5 100644 --- a/ipc/mscom/Interceptor.cpp +++ b/ipc/mscom/Interceptor.cpp @@ -5,10 +5,11 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #define INITGUID + +#include "mozilla/Move.h" +#include "mozilla/mscom/DispatchForwarder.h" #include "mozilla/mscom/Interceptor.h" #include "mozilla/mscom/InterceptorLog.h" - -#include "mozilla/mscom/DispatchForwarder.h" #include "mozilla/mscom/MainThreadInvoker.h" #include "mozilla/mscom/Registration.h" #include "mozilla/mscom/Utils.h" @@ -100,8 +101,10 @@ Interceptor::GetMarshalSizeMax(REFIID riid, void* pv, DWORD dwDestContext, return hr; } + InterceptorTargetPtr targetParam(mTarget.get()); + DWORD payloadSize = 0; - hr = mEventSink->GetHandlerPayloadSize(riid, mTarget.get(), &payloadSize); + hr = mEventSink->GetHandlerPayloadSize(riid, Move(targetParam), &payloadSize); *pSize += payloadSize; return hr; } @@ -117,7 +120,8 @@ Interceptor::MarshalInterface(IStream* pStm, REFIID riid, void* pv, return hr; } - return mEventSink->WriteHandlerPayload(pStm, riid, mTarget.get()); + InterceptorTargetPtr targetParam(mTarget.get()); + return mEventSink->WriteHandlerPayload(pStm, riid, Move(targetParam)); } HRESULT @@ -152,7 +156,8 @@ Interceptor::Lookup(REFIID aIid) } HRESULT -Interceptor::GetTargetForIID(REFIID aIid, InterceptorTargetPtr& aTarget) +Interceptor::GetTargetForIID(REFIID aIid, + InterceptorTargetPtr& aTarget) { MutexAutoLock lock(mMutex); MapEntry* entry = Lookup(aIid); @@ -164,10 +169,10 @@ Interceptor::GetTargetForIID(REFIID aIid, InterceptorTargetPtr& aTarget) return E_NOINTERFACE; } -// CoGetInterceptor requires information from a typelib to be able to -// generate its emulated vtable. If a typelib is unavailable, -// CoGetInterceptor returns 0x80070002. -static const HRESULT kFileNotFound = 0x80070002; +// CoGetInterceptor requires type metadata to be able to generate its emulated +// vtable. If no registered metadata is available, CoGetInterceptor returns +// kFileNotFound. +static const HRESULT kFileNotFound = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); HRESULT Interceptor::CreateInterceptor(REFIID aIid, IUnknown* aOuter, IUnknown** aOutput) diff --git a/ipc/mscom/Interceptor.h b/ipc/mscom/Interceptor.h index 4f6d0e26fec2..f523a6031014 100644 --- a/ipc/mscom/Interceptor.h +++ b/ipc/mscom/Interceptor.h @@ -37,7 +37,8 @@ DEFINE_GUID(IID_IInterceptor, struct IInterceptor : public IUnknown { - virtual STDMETHODIMP GetTargetForIID(REFIID aIid, InterceptorTargetPtr& aTarget) = 0; + virtual STDMETHODIMP GetTargetForIID(REFIID aIid, + InterceptorTargetPtr& aTarget) = 0; virtual STDMETHODIMP GetInterceptorForIID(REFIID aIid, void** aOutInterceptor) = 0; }; @@ -93,7 +94,8 @@ public: STDMETHODIMP DisconnectObject(DWORD dwReserved) override; // IInterceptor - STDMETHODIMP GetTargetForIID(REFIID aIid, InterceptorTargetPtr& aTarget) override; + STDMETHODIMP GetTargetForIID(REFIID aIid, + InterceptorTargetPtr& aTarget) override; STDMETHODIMP GetInterceptorForIID(REFIID aIid, void** aOutInterceptor) override; private: diff --git a/ipc/mscom/MainThreadHandoff.cpp b/ipc/mscom/MainThreadHandoff.cpp index 8353dc39e90e..2796df46826b 100644 --- a/ipc/mscom/MainThreadHandoff.cpp +++ b/ipc/mscom/MainThreadHandoff.cpp @@ -246,7 +246,7 @@ MainThreadHandoff::OnCall(ICallFrame* aFrame) return hr; } - InterceptorTargetPtr targetInterface; + InterceptorTargetPtr targetInterface; hr = interceptor->GetTargetForIID(iid, targetInterface); if (FAILED(hr)) { return hr; @@ -415,23 +415,25 @@ MainThreadHandoff::GetHandler(CLSID* aHandlerClsid) } HRESULT -MainThreadHandoff::GetHandlerPayloadSize(REFIID aIid, IUnknown* aTarget, +MainThreadHandoff::GetHandlerPayloadSize(REFIID aIid, + InterceptorTargetPtr aTarget, DWORD* aOutPayloadSize) { if (!mHandlerPayload) { return E_NOTIMPL; } - return mHandlerPayload->GetHandlerPayloadSize(aIid, aTarget, aOutPayloadSize); + return mHandlerPayload->GetHandlerPayloadSize(aIid, Move(aTarget), + aOutPayloadSize); } HRESULT MainThreadHandoff::WriteHandlerPayload(IStream* aStream, REFIID aIid, - IUnknown* aTarget) + InterceptorTargetPtr aTarget) { if (!mHandlerPayload) { return E_NOTIMPL; } - return mHandlerPayload->WriteHandlerPayload(aStream, aIid, aTarget); + return mHandlerPayload->WriteHandlerPayload(aStream, aIid, Move(aTarget)); } REFIID @@ -482,7 +484,7 @@ MainThreadHandoff::OnWalkInterface(REFIID aIid, PVOID* aInterface, // as an interface that we are already managing. We can determine this by // querying (NOT casting!) both objects for IUnknown and then comparing the // resulting pointers. - InterceptorTargetPtr existingTarget; + InterceptorTargetPtr existingTarget; hr = interceptor->GetTargetForIID(aIid, existingTarget); if (SUCCEEDED(hr)) { bool areIUnknownsEqual = false; diff --git a/ipc/mscom/MainThreadHandoff.h b/ipc/mscom/MainThreadHandoff.h index 104cf8c65dcb..c52dd426b404 100644 --- a/ipc/mscom/MainThreadHandoff.h +++ b/ipc/mscom/MainThreadHandoff.h @@ -62,10 +62,10 @@ public: STDMETHODIMP SetInterceptor(IWeakReference* aInterceptor) override; STDMETHODIMP GetHandler(CLSID* aHandlerClsid) override; STDMETHODIMP GetHandlerPayloadSize(REFIID aIid, - IUnknown* aTarget, + InterceptorTargetPtr aTarget, DWORD* aOutPayloadSize) override; STDMETHODIMP WriteHandlerPayload(IStream* aStream, REFIID aIid, - IUnknown* aTarget) override; + InterceptorTargetPtr aTarget) override; REFIID MarshalAs(REFIID aIid) override; // ICallFrameWalker diff --git a/ipc/mscom/MainThreadInvoker.h b/ipc/mscom/MainThreadInvoker.h index 4bd1f803fcbf..b81a1eef91b7 100644 --- a/ipc/mscom/MainThreadInvoker.h +++ b/ipc/mscom/MainThreadInvoker.h @@ -8,7 +8,10 @@ #define mozilla_mscom_MainThreadInvoker_h #include "mozilla/AlreadyAddRefed.h" +#include "mozilla/Move.h" #include "mozilla/StaticPtr.h" +#include "nsCOMPtr.h" +#include "nsThreadUtils.h" #include @@ -32,6 +35,19 @@ private: static HANDLE sMainThread; }; +template +inline bool +InvokeOnMainThread(Class* aObject, void (Class::*aMethod)(Args...), + Args... aArgs) +{ + nsCOMPtr runnable( + NewNonOwningRunnableMethod(aObject, aMethod, + Forward(aArgs)...)); + + MainThreadInvoker invoker; + return invoker.Invoke(runnable.forget()); +} + } // namespace mscom } // namespace mozilla diff --git a/ipc/mscom/Ptr.h b/ipc/mscom/Ptr.h index c77e570b8761..9fd3c6115c6f 100644 --- a/ipc/mscom/Ptr.h +++ b/ipc/mscom/Ptr.h @@ -101,11 +101,147 @@ using MTAUniquePtr = mozilla::UniquePtr>; template using ProxyUniquePtr = mozilla::UniquePtr>; +template using InterceptorTargetPtr = - mozilla::UniquePtr; + mozilla::UniquePtr; + +namespace detail { + +// We don't have direct access to UniquePtr's storage, so we use mPtrStorage +// to receive the pointer and then set the target inside the destructor. +template +class UniquePtrGetterAddRefs +{ +public: + explicit UniquePtrGetterAddRefs(UniquePtr& aSmartPtr) + : mTargetSmartPtr(aSmartPtr) + , mPtrStorage(nullptr) + { + } + + ~UniquePtrGetterAddRefs() + { + mTargetSmartPtr.reset(mPtrStorage); + } + + operator void**() + { + return reinterpret_cast(&mPtrStorage); + } + + operator T**() + { + return &mPtrStorage; + } + + T*& operator*() + { + return mPtrStorage; + } + +private: + UniquePtr& mTargetSmartPtr; + T* mPtrStorage; +}; + +} // namespace detail + +template +inline STAUniquePtr +ToSTAUniquePtr(RefPtr&& aRefPtr) +{ + return STAUniquePtr(aRefPtr.forget().take()); +} + +template +inline STAUniquePtr +ToSTAUniquePtr(T* aRawPtr) +{ + MOZ_ASSERT(NS_IsMainThread()); + if (aRawPtr) { + aRawPtr->AddRef(); + } + return STAUniquePtr(aRawPtr); +} + +template +inline MTAUniquePtr +ToMTAUniquePtr(RefPtr&& aRefPtr) +{ + return MTAUniquePtr(aRefPtr.forget().take()); +} + +template +inline MTAUniquePtr +ToMTAUniquePtr(T* aRawPtr) +{ + MOZ_ASSERT(IsCurrentThreadMTA()); + if (aRawPtr) { + aRawPtr->AddRef(); + } + return MTAUniquePtr(aRawPtr); +} + +template +inline ProxyUniquePtr +ToProxyUniquePtr(RefPtr&& aRefPtr) +{ + return ProxyUniquePtr(aRefPtr.forget().take()); +} + +template +inline ProxyUniquePtr +ToProxyUniquePtr(T* aRawPtr) +{ + MOZ_ASSERT(IsProxy(aRawPtr)); + MOZ_ASSERT((XRE_IsParentProcess() && NS_IsMainThread()) || + (XRE_IsContentProcess() && IsCurrentThreadMTA())); + + if (aRawPtr) { + aRawPtr->AddRef(); + } + return ProxyUniquePtr(aRawPtr); +} + +template +inline detail::UniquePtrGetterAddRefs +getter_AddRefs(UniquePtr& aSmartPtr) +{ + return detail::UniquePtrGetterAddRefs(aSmartPtr); +} } // namespace mscom } // namespace mozilla +// This block makes it possible for these smart pointers to be correctly +// applied in NewRunnableMethod and friends +namespace detail { + +template +struct SmartPointerStorageClass> +{ + typedef StoreCopyPassByRRef> Type; +}; + +template +struct SmartPointerStorageClass> +{ + typedef StoreCopyPassByRRef> Type; +}; + +template +struct SmartPointerStorageClass> +{ + typedef StoreCopyPassByRRef> Type; +}; + +template +struct SmartPointerStorageClass> +{ + typedef StoreCopyPassByRRef> Type; +}; + +} // namespace detail + #endif // mozilla_mscom_Ptr_h From 45625b49e19fd2e088c7ca6d599034576713fda9 Mon Sep 17 00:00:00 2001 From: Shu-yu Guo Date: Wed, 8 Mar 2017 13:44:27 -0800 Subject: [PATCH 55/57] Bug 1108941 - Fix #include order to open a CLOSED TREE. --- js/src/vm/TemplateRegistry.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/vm/TemplateRegistry.h b/js/src/vm/TemplateRegistry.h index bc22124196c8..bac534b6f642 100644 --- a/js/src/vm/TemplateRegistry.h +++ b/js/src/vm/TemplateRegistry.h @@ -8,8 +8,8 @@ #define vm_TemplateRegistry_h #include "jsobj.h" -#include "js/GCHashTable.h" #include "gc/Marking.h" +#include "js/GCHashTable.h" namespace js { From 1dcb2c47c51f49488025bbc6d12cad2f00d733c8 Mon Sep 17 00:00:00 2001 From: Shu-yu Guo Date: Wed, 8 Mar 2017 14:24:22 -0800 Subject: [PATCH 56/57] Bug 1108941 - Followup: don't expect template literal objects to already have been canonicalized during arguments analysis. (r=jandem) --- js/src/jit/IonBuilder.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index c05f685add2f..4edf47804818 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -2185,12 +2185,17 @@ IonBuilder::inspectOpcode(JSOp op) return jsop_regexp(info().getRegExp(pc)); case JSOP_CALLSITEOBJ: - { - JSObject* raw = script()->getObject(GET_UINT32_INDEX(pc) + 1); - JSObject* obj = script()->compartment()->getExistingTemplateLiteralObject(raw); - pushConstant(ObjectValue(*obj)); + if (info().analysisMode() == Analysis_ArgumentsUsage) { + // When analyzing arguments usage, it is possible that the + // template object is not yet canonicalized. Push an incorrect + // object; it does not matter for arguments analysis. + pushConstant(ObjectValue(*info().getObject(pc))); + } else { + JSObject* raw = script()->getObject(GET_UINT32_INDEX(pc) + 1); + JSObject* obj = script()->compartment()->getExistingTemplateLiteralObject(raw); + pushConstant(ObjectValue(*obj)); + } return Ok(); - } case JSOP_OBJECT: return jsop_object(info().getObject(pc)); From 2ecd72ea5336525cef0e7418c09fa86c0a97d608 Mon Sep 17 00:00:00 2001 From: Shu-yu Guo Date: Wed, 8 Mar 2017 14:24:23 -0800 Subject: [PATCH 57/57] Bug 1108941 - Followup: fix nonunified builds on a CLOSED TREE. --- js/src/jscompartment.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 28bda78eb362..8c012e3fb470 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -35,6 +35,7 @@ #include "jsscriptinlines.h" #include "vm/NativeObject-inl.h" +#include "vm/UnboxedObject-inl.h" using namespace js; using namespace js::gc;