diff --git a/browser/devtools/webaudioeditor/test/browser.ini b/browser/devtools/webaudioeditor/test/browser.ini index 9a5d8e178a05..ee07505b7936 100644 --- a/browser/devtools/webaudioeditor/test/browser.ini +++ b/browser/devtools/webaudioeditor/test/browser.ini @@ -9,6 +9,7 @@ support-files = doc_media-node-creation.html doc_destroy-nodes.html doc_connect-toggle.html + doc_connect-param.html 440hz_sine.ogg head.js @@ -20,6 +21,7 @@ support-files = [browser_audionode-actor-is-source.js] [browser_webaudio-actor-simple.js] [browser_webaudio-actor-destroy-node.js] +[browser_webaudio-actor-connect-param.js] [browser_wa_destroy-node-01.js] diff --git a/browser/devtools/webaudioeditor/test/browser_webaudio-actor-connect-param.js b/browser/devtools/webaudioeditor/test/browser_webaudio-actor-connect-param.js new file mode 100644 index 000000000000..af4078225535 --- /dev/null +++ b/browser/devtools/webaudioeditor/test/browser_webaudio-actor-connect-param.js @@ -0,0 +1,26 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Test the `connect-param` event on the web audio actor. + */ + +function spawnTest () { + let [target, debuggee, front] = yield initBackend(CONNECT_PARAM_URL); + let [_, _, [destNode, carrierNode, modNode, gainNode], _, connectParam] = yield Promise.all([ + front.setup({ reload: true }), + once(front, "start-context"), + getN(front, "create-node", 4), + get2(front, "connect-node"), + once(front, "connect-param") + ]); + + info(connectParam); + + is(connectParam.source.actorID, modNode.actorID, "`connect-param` has correct actor for `source`"); + is(connectParam.dest.actorID, gainNode.actorID, "`connect-param` has correct actor for `dest`"); + is(connectParam.param, "gain", "`connect-param` has correct parameter name for `param`"); + + yield removeTab(target.tab); + finish(); +} diff --git a/browser/devtools/webaudioeditor/test/doc_connect-param.html b/browser/devtools/webaudioeditor/test/doc_connect-param.html new file mode 100644 index 000000000000..9185c0b05d59 --- /dev/null +++ b/browser/devtools/webaudioeditor/test/doc_connect-param.html @@ -0,0 +1,28 @@ + + + + + + + Web Audio Editor test page + + + + + + + + diff --git a/browser/devtools/webaudioeditor/test/head.js b/browser/devtools/webaudioeditor/test/head.js index 22aa1f037998..ec4aa4a305e3 100644 --- a/browser/devtools/webaudioeditor/test/head.js +++ b/browser/devtools/webaudioeditor/test/head.js @@ -28,6 +28,7 @@ const MEDIA_NODES_URL = EXAMPLE_URL + "doc_media-node-creation.html"; const BUFFER_AND_ARRAY_URL = EXAMPLE_URL + "doc_buffer-and-array.html"; const DESTROY_NODES_URL = EXAMPLE_URL + "doc_destroy-nodes.html"; const CONNECT_TOGGLE_URL = EXAMPLE_URL + "doc_connect-toggle.html"; +const CONNECT_PARAM_URL = EXAMPLE_URL + "doc_connect-param.html"; // All tests are asynchronous. waitForExplicitFinish(); diff --git a/build/mobile/remoteautomation.py b/build/mobile/remoteautomation.py index bb9d7845c4b3..cddbfcd075cf 100644 --- a/build/mobile/remoteautomation.py +++ b/build/mobile/remoteautomation.py @@ -86,7 +86,7 @@ class RemoteAutomation(Automation): topActivity = self._devicemanager.getTopActivity() if topActivity == proc.procName: - proc.kill() + proc.kill(True) if status == 1: if maxTime: print "TEST-UNEXPECTED-FAIL | %s | application ran for longer than " \ @@ -287,5 +287,26 @@ class RemoteAutomation(Automation): return status - def kill(self): - self.dm.killProcess(self.procName) + def kill(self, stagedShutdown = False): + if stagedShutdown: + # Trigger an ANR report with "kill -3" (SIGQUIT) + self.dm.killProcess(self.procName, 3) + time.sleep(3) + # Trigger a breakpad dump with "kill -6" (SIGABRT) + self.dm.killProcess(self.procName, 6) + # Wait for process to end + retries = 0 + while retries < 3: + pid = self.dm.processExist(self.procName) + if pid and pid > 0: + print "%s still alive after SIGABRT: waiting..." % self.procName + time.sleep(5) + else: + return + retries += 1 + self.dm.killProcess(self.procName, 9) + pid = self.dm.processExist(self.procName) + if pid and pid > 0: + self.dm.killProcess(self.procName) + else: + self.dm.killProcess(self.procName) diff --git a/content/html/content/src/HTMLTrackElement.cpp b/content/html/content/src/HTMLTrackElement.cpp index 5e8f2a4144b2..df1fe317dd63 100644 --- a/content/html/content/src/HTMLTrackElement.cpp +++ b/content/html/content/src/HTMLTrackElement.cpp @@ -228,7 +228,12 @@ HTMLTrackElement::LoadResource() return; } - CreateTextTrack(); + // We may already have a TextTrack at this point if GetTrack() has already + // been called. This happens, for instance, if script tries to get the + // TextTrack before its mTrackElement has been bound to the DOM tree. + if (!mTrack) { + CreateTextTrack(); + } // Check for a Content Security Policy to pass down to the channel // created to load the media content. diff --git a/content/media/test/mochitest.ini b/content/media/test/mochitest.ini index 0f03d89af815..1117297b821d 100644 --- a/content/media/test/mochitest.ini +++ b/content/media/test/mochitest.ini @@ -321,6 +321,7 @@ skip-if = os == 'win' # bug 894922 [test_bug895305.html] [test_bug919265.html] [test_bug957847.html] +[test_bug1018933.html] [test_can_play_type.html] [test_can_play_type_mpeg.html] skip-if = buildapp == 'b2g' # bug 1021675 diff --git a/content/media/test/test_bug1018933.html b/content/media/test/test_bug1018933.html new file mode 100644 index 000000000000..ef2e2f139f77 --- /dev/null +++ b/content/media/test/test_bug1018933.html @@ -0,0 +1,50 @@ + + + + + + Regression test for bug 1018933 - HTMLTrackElement should create only one TextTrack + + + + + +

+
+
+
+
+
+ + diff --git a/dom/plugins/ipc/PluginInstanceChild.cpp b/dom/plugins/ipc/PluginInstanceChild.cpp index a54ab1dd623a..50791ba61833 100644 --- a/dom/plugins/ipc/PluginInstanceChild.cpp +++ b/dom/plugins/ipc/PluginInstanceChild.cpp @@ -12,7 +12,6 @@ #include "StreamNotifyChild.h" #include "PluginProcessChild.h" #include "gfxASurface.h" -#include "gfxContext.h" #include "gfxPlatform.h" #include "gfx2DGlue.h" #include "nsNPAPIPluginInstance.h" @@ -2787,12 +2786,6 @@ PluginInstanceChild::DoAsyncSetWindow(const gfxSurfaceType& aSurfaceType, } } -static inline gfxRect -GfxFromNsRect(const nsIntRect& aRect) -{ - return gfxRect(aRect.x, aRect.y, aRect.width, aRect.height); -} - bool PluginInstanceChild::CreateOptSurface(void) { @@ -3454,12 +3447,14 @@ PluginInstanceChild::ShowPluginFrame() PLUGIN_LOG_DEBUG((" (on background)")); // Source the background pixels ... { - nsRefPtr ctx = - new gfxContext(mHelperSurface ? mHelperSurface : mCurrentSurface); - ctx->SetSource(mBackground); - ctx->SetOperator(gfxContext::OPERATOR_SOURCE); - ctx->Rectangle(gfxRect(rect.x, rect.y, rect.width, rect.height)); - ctx->Fill(); + nsRefPtr surface = + mHelperSurface ? mHelperSurface : mCurrentSurface; + RefPtr dt = CreateDrawTargetForSurface(surface); + RefPtr backgroundSurface = + gfxPlatform::GetSourceSurfaceForSurface(dt, mBackground); + dt->CopySurface(backgroundSurface, + ToIntRect(rect), + ToIntPoint(rect.TopLeft())); } // ... and hand off to the plugin // BEWARE: mBackground may die during this call @@ -3583,18 +3578,17 @@ PluginInstanceChild::ReadbackDifferenceRect(const nsIntRect& rect) mSurfaceDifferenceRect.width, mSurfaceDifferenceRect.height)); // Read back previous content - nsRefPtr ctx = new gfxContext(mCurrentSurface); - ctx->SetOperator(gfxContext::OPERATOR_SOURCE); - ctx->SetSource(mBackSurface); + RefPtr dt = CreateDrawTargetForSurface(mCurrentSurface); + RefPtr source = + gfxPlatform::GetSourceSurfaceForSurface(dt, mBackSurface); // Subtract from mSurfaceDifferenceRect area which is overlapping with rect nsIntRegion result; result.Sub(mSurfaceDifferenceRect, nsIntRegion(rect)); nsIntRegionRectIterator iter(result); const nsIntRect* r; while ((r = iter.Next()) != nullptr) { - ctx->Rectangle(GfxFromNsRect(*r)); + dt->CopySurface(source, ToIntRect(*r), ToIntPoint(r->TopLeft())); } - ctx->Fill(); return true; } diff --git a/dom/wifi/WifiWorker.js b/dom/wifi/WifiWorker.js index 4569007004ed..a24e01d854e0 100644 --- a/dom/wifi/WifiWorker.js +++ b/dom/wifi/WifiWorker.js @@ -3309,13 +3309,13 @@ WifiWorker.prototype = { return; } - let certDB2 = Cc["@mozilla.org/security/x509certdb;1"] - .getService(Ci.nsIX509CertDB2); - if (!certDB2) { + let certDB = Cc["@mozilla.org/security/x509certdb;1"] + .getService(Ci.nsIX509CertDB); + if (!certDB) { self._sendMessage(message, false, "Failed to query NSS DB service", msg); } - let certList = certDB2.getCerts(); + let certList = certDB.getCerts(); if (!certList) { self._sendMessage(message, false, "Failed to get certificate List", msg); } @@ -3332,7 +3332,7 @@ WifiWorker.prototype = { }; while (certListEnum.hasMoreElements()) { - let certInfo = certListEnum.getNext().QueryInterface(Ci.nsIX509Cert3); + let certInfo = certListEnum.getNext().QueryInterface(Ci.nsIX509Cert); let certNicknameInfo = /WIFI\_([A-Z]*)\_(.*)/.exec(certInfo.nickname); if (!certNicknameInfo) { continue; diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp index 845a59ddf441..8a73dda1d69c 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -21,7 +21,6 @@ #include "nsPIDOMWindow.h" #include -#include "BackgroundChild.h" #include "GeckoProfiler.h" #include "js/OldDebugAPI.h" #include "jsfriendapi.h" @@ -41,7 +40,6 @@ #include "nsContentUtils.h" #include "nsCycleCollector.h" #include "nsDOMJSUtils.h" -#include "nsIIPCBackgroundChildCreateCallback.h" #include "nsISupportsImpl.h" #include "nsLayoutStatics.h" #include "nsNetUtil.h" @@ -66,12 +64,6 @@ #include "WorkerPrivate.h" #include "WorkerRunnable.h" -#ifdef ENABLE_TESTS -#include "BackgroundChildImpl.h" -#include "mozilla/ipc/PBackgroundChild.h" -#include "prrng.h" -#endif - using namespace mozilla; using namespace mozilla::dom; @@ -169,10 +161,6 @@ RuntimeService* gRuntimeService = nullptr; // Only non-null during the call to Init. RuntimeService* gRuntimeServiceDuringInit = nullptr; -#ifdef ENABLE_TESTS -bool gTestPBackground = false; -#endif // ENABLE_TESTS - enum { ID_Worker = 0, ID_ChromeWorker, @@ -911,37 +899,6 @@ private: WorkerPrivate* mWorkerPrivate; }; -class WorkerBackgroundChildCallback MOZ_FINAL : - public nsIIPCBackgroundChildCreateCallback -{ - bool* mDone; - -public: - WorkerBackgroundChildCallback(bool* aDone) - : mDone(aDone) - { - MOZ_ASSERT(mDone); - } - - NS_DECL_ISUPPORTS - -private: - ~WorkerBackgroundChildCallback() - { } - - virtual void - ActorCreated(PBackgroundChild* aActor) MOZ_OVERRIDE - { - *mDone = true; - } - - virtual void - ActorFailed() MOZ_OVERRIDE - { - *mDone = true; - } -}; - class WorkerThreadPrimaryRunnable MOZ_FINAL : public nsRunnable { WorkerPrivate* mWorkerPrivate; @@ -984,9 +941,6 @@ private: ~WorkerThreadPrimaryRunnable() { } - nsresult - SynchronouslyCreatePBackground(); - NS_DECL_NSIRUNNABLE }; @@ -1086,28 +1040,6 @@ public: } #endif -#ifdef ENABLE_TESTS - void - TestPBackground() - { - using namespace mozilla::ipc; - if (gTestPBackground) { - // Randomize value to validate workers are not cross-posting messages. - uint32_t testValue; - PRSize randomSize = PR_GetRandomNoise(&testValue, sizeof(testValue)); - MOZ_RELEASE_ASSERT(randomSize == sizeof(testValue)); - nsCString testStr; - testStr.AppendInt(testValue); - testStr.AppendInt(reinterpret_cast(PR_GetCurrentThread())); - PBackgroundChild* existingBackgroundChild = - BackgroundChild::GetForCurrentThread(); - MOZ_RELEASE_ASSERT(existingBackgroundChild); - bool ok = existingBackgroundChild->SendPBackgroundTestConstructor(testStr); - MOZ_RELEASE_ASSERT(ok); - } - } -#endif // #ENABLE_TESTS - private: WorkerThread() : nsThread(nsThread::NOT_MAIN_THREAD, WORKER_STACK_SIZE), @@ -1311,10 +1243,6 @@ RuntimeService::GetOrCreateService() return nullptr; } -#ifdef ENABLE_TESTS - gTestPBackground = mozilla::Preferences::GetBool("pbackground.testing", false); -#endif // ENABLE_TESTS - // The observer service now owns us until shutdown. gRuntimeService = service; } @@ -1604,6 +1532,10 @@ RuntimeService::ScheduleWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate) return false; } +#ifdef DEBUG + thread->SetAcceptingNonWorkerRunnables(false); +#endif + return true; } @@ -2592,20 +2524,8 @@ RuntimeService::WorkerThread::Observer::OnProcessNextEvent( bool aMayWait, uint32_t aRecursionDepth) { - using mozilla::ipc::BackgroundChild; - mWorkerPrivate->AssertIsOnWorkerThread(); - - // If the PBackground child is not created yet, then we must permit - // blocking event processing to support SynchronouslyCreatePBackground(). - // If this occurs then we are spinning on the event queue at the start of - // PrimaryWorkerRunnable::Run() and don't want to process the event in - // mWorkerPrivate yet. - if (aMayWait) { - MOZ_ASSERT(aRecursionDepth == 2); - MOZ_ASSERT(!BackgroundChild::GetForCurrentThread()); - return NS_OK; - } + MOZ_ASSERT(!aMayWait); mWorkerPrivate->OnProcessNextEvent(aRecursionDepth); return NS_OK; @@ -2649,15 +2569,11 @@ LogViolationDetailsRunnable::Run() return NS_OK; } -NS_IMPL_ISUPPORTS(WorkerBackgroundChildCallback, nsIIPCBackgroundChildCreateCallback) - NS_IMPL_ISUPPORTS_INHERITED0(WorkerThreadPrimaryRunnable, nsRunnable) NS_IMETHODIMP WorkerThreadPrimaryRunnable::Run() { - using mozilla::ipc::BackgroundChild; - #ifdef MOZ_NUWA_PROCESS if (IsNuwaProcess()) { NS_ASSERTION(NuwaMarkCurrentThread != nullptr, @@ -2676,19 +2592,6 @@ WorkerThreadPrimaryRunnable::Run() profiler_register_thread(threadName.get(), &stackBaseGuess); - // Note: SynchronouslyCreatePBackground() must be called prior to - // mThread->SetWorker() in order to avoid accidentally consuming - // worker messages here. - nsresult rv = SynchronouslyCreatePBackground(); - if (NS_WARN_IF(NS_FAILED(rv))) { - // XXX need to fire an error at parent. - return rv; - } - -#ifdef ENABLE_TESTS - mThread->TestPBackground(); -#endif - mThread->SetWorker(mWorkerPrivate); mWorkerPrivate->AssertIsOnWorkerThread(); @@ -2722,12 +2625,6 @@ WorkerThreadPrimaryRunnable::Run() JS_ReportPendingException(cx); } -#ifdef ENABLE_TESTS - mThread->TestPBackground(); -#endif - - BackgroundChild::CloseForCurrentThread(); - #ifdef MOZ_ENABLE_PROFILER_SPS if (stack) { stack->sampleRuntime(nullptr); @@ -2766,38 +2663,6 @@ WorkerThreadPrimaryRunnable::Run() return NS_OK; } -nsresult -WorkerThreadPrimaryRunnable::SynchronouslyCreatePBackground() -{ - using mozilla::ipc::BackgroundChild; - - MOZ_ASSERT(!BackgroundChild::GetForCurrentThread()); - - bool done = false; - nsCOMPtr callback = - new WorkerBackgroundChildCallback(&done); - - if (NS_WARN_IF(!BackgroundChild::GetOrCreateForCurrentThread(callback))) { - return NS_ERROR_FAILURE; - } - - while (!done) { - if (NS_WARN_IF(!NS_ProcessNextEvent(mThread, true /* aMayWay */))) { - return NS_ERROR_FAILURE; - } - } - - if (NS_WARN_IF(!BackgroundChild::GetForCurrentThread())) { - return NS_ERROR_FAILURE; - } - -#ifdef DEBUG - mThread->SetAcceptingNonWorkerRunnables(false); -#endif - - return NS_OK; -} - NS_IMPL_ISUPPORTS_INHERITED0(WorkerThreadPrimaryRunnable::FinishedRunnable, nsRunnable) diff --git a/gfx/layers/LayerScope.cpp b/gfx/layers/LayerScope.cpp index 42c974602b81..f3ed68389992 100644 --- a/gfx/layers/LayerScope.cpp +++ b/gfx/layers/LayerScope.cpp @@ -12,6 +12,8 @@ #include "mozilla/Preferences.h" #include "mozilla/Endian.h" #include "TexturePoolOGL.h" +#include "mozilla/layers/CompositorOGL.h" +#include "mozilla/layers/LayerManagerComposite.h" #include "mozilla/layers/TextureHostOGL.h" #include "gfxColor.h" @@ -317,6 +319,7 @@ public: } void AppendDebugData(DebugGLData *aDebugData); + void CleanDebugData(); void DispatchDebugData(); private: nsTArray > mHandlers; @@ -325,7 +328,37 @@ private: nsCOMPtr mServerSocket; }; -static StaticAutoPtr gLayerScopeWebSocketManager; +// Static class to create and destory LayerScopeWebSocketManager object +class WebSocketHelper +{ +public: + static void CreateServerSocket() + { + // Create Web Server Socket (which has to be on the main thread) + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + if (!sWebSocketManager) { + sWebSocketManager = new LayerScopeWebSocketManager(); + } + } + + static void DestroyServerSocket() + { + // Destroy Web Server Socket + if (sWebSocketManager) { + sWebSocketManager->RemoveAllConnections(); + } + } + + static LayerScopeWebSocketManager* GetSocketManager() + { + return sWebSocketManager.get(); + } + +private: + static StaticAutoPtr sWebSocketManager; +}; + +StaticAutoPtr WebSocketHelper::sWebSocketManager; class DebugGLData : public LinkedListElement { public: @@ -378,9 +411,9 @@ public: } static bool WriteToStream(void *ptr, uint32_t size) { - if (!gLayerScopeWebSocketManager) + if (!WebSocketHelper::GetSocketManager()) return true; - return gLayerScopeWebSocketManager->WriteAll(ptr, size); + return WebSocketHelper::GetSocketManager()->WriteAll(ptr, size); } protected: @@ -428,83 +461,97 @@ public: class DebugGLTextureData : public DebugGLData { public: - DebugGLTextureData(GLContext* cx, void* layerRef, GLuint target, GLenum name, DataSourceSurface* img) + DebugGLTextureData(GLContext* cx, + void* layerRef, + GLenum target, + GLuint name, + DataSourceSurface* img) : DebugGLData(DebugGLData::TextureData, cx), mLayerRef(layerRef), mTarget(target), mName(name), - mImage(img) - { } + mDatasize(0) + { + // pre-packing + // DataSourceSurface may have locked buffer, + // so we should compress now, and then it could + // be unlocked outside. + pack(img); + } void *GetLayerRef() const { return mLayerRef; } GLuint GetName() const { return mName; } - DataSourceSurface* GetImage() const { return mImage; } GLenum GetTextureTarget() const { return mTarget; } virtual bool Write() { - DebugGLData::TexturePacket packet; - char* dataptr = nullptr; - uint32_t datasize = 0; - std::auto_ptr compresseddata; - - packet.type = mDataType; - packet.ptr = static_cast(mContextAddress); - packet.layerref = reinterpret_cast(mLayerRef); - packet.name = mName; - packet.format = 0; - packet.target = mTarget; - packet.dataFormat = LOCAL_GL_RGBA; - - if (mImage) { - packet.width = mImage->GetSize().width; - packet.height = mImage->GetSize().height; - packet.stride = mImage->Stride(); - packet.dataSize = mImage->GetSize().height * mImage->Stride(); - - dataptr = (char*) mImage->GetData(); - datasize = packet.dataSize; - - compresseddata = std::auto_ptr((char*) moz_malloc(LZ4::maxCompressedSize(datasize))); - if (compresseddata.get()) { - int ndatasize = LZ4::compress(dataptr, datasize, compresseddata.get()); - if (ndatasize > 0) { - datasize = ndatasize; - dataptr = compresseddata.get(); - - packet.dataFormat = (1 << 16) | packet.dataFormat; - packet.dataSize = datasize; - } - } - } else { - packet.width = 0; - packet.height = 0; - packet.stride = 0; - packet.dataSize = 0; - } - // write the packet header data - if (!WriteToStream(&packet, sizeof(packet))) + if (!WriteToStream(&mPacket, sizeof(mPacket))) return false; // then the image data - if (!WriteToStream(dataptr, datasize)) + if (mCompresseddata.get() && !WriteToStream(mCompresseddata.get(), mDatasize)) return false; // then pad out to 4 bytes - if (datasize % 4 != 0) { + if (mDatasize % 4 != 0) { static char buf[] = { 0, 0, 0, 0 }; - if (!WriteToStream(buf, 4 - (datasize % 4))) + if (!WriteToStream(buf, 4 - (mDatasize % 4))) return false; } return true; } +private: + void pack(DataSourceSurface* aImage) { + mPacket.type = mDataType; + mPacket.ptr = static_cast(mContextAddress); + mPacket.layerref = reinterpret_cast(mLayerRef); + mPacket.name = mName; + mPacket.format = 0; + mPacket.target = mTarget; + mPacket.dataFormat = LOCAL_GL_RGBA; + + if (aImage) { + mPacket.width = aImage->GetSize().width; + mPacket.height = aImage->GetSize().height; + mPacket.stride = aImage->Stride(); + mPacket.dataSize = aImage->GetSize().height * aImage->Stride(); + + mCompresseddata = std::auto_ptr( + (char*)moz_malloc(LZ4::maxCompressedSize(mPacket.dataSize))); + if (mCompresseddata.get()) { + int ndatasize = LZ4::compress((char*)aImage->GetData(), + mPacket.dataSize, + mCompresseddata.get()); + if (ndatasize > 0) { + mDatasize = ndatasize; + + mPacket.dataFormat = (1 << 16) | mPacket.dataFormat; + mPacket.dataSize = mDatasize; + } else { + NS_WARNING("Compress data failed"); + } + } else { + NS_WARNING("Couldn't moz_malloc for compressed data."); + } + } else { + mPacket.width = 0; + mPacket.height = 0; + mPacket.stride = 0; + mPacket.dataSize = 0; + } + } + protected: void* mLayerRef; GLenum mTarget; GLuint mName; - RefPtr mImage; + + // Packet data + DebugGLData::TexturePacket mPacket; + std::auto_ptr mCompresseddata; + uint32_t mDatasize; }; class DebugGLColorData : public DebugGLData { @@ -539,18 +586,6 @@ protected: nsIntSize mSize; }; -static bool -CheckSender() -{ - if (!gLayerScopeWebSocketManager) - return false; - - if (!gLayerScopeWebSocketManager->IsConnected()) - return false; - - return true; -} - class DebugListener : public nsIServerSocketListener { virtual ~DebugListener() { } @@ -566,11 +601,11 @@ public: NS_IMETHODIMP OnSocketAccepted(nsIServerSocket *aServ, nsISocketTransport *aTransport) { - if (!gLayerScopeWebSocketManager) + if (!WebSocketHelper::GetSocketManager()) return NS_OK; printf_stderr("*** LayerScope: Accepted connection\n"); - gLayerScopeWebSocketManager->AddConnection(aTransport); + WebSocketHelper::GetSocketManager()->AddConnection(aTransport); return NS_OK; } @@ -594,24 +629,19 @@ public: NS_DECL_THREADSAFE_ISUPPORTS - DebugDataSender() { - mList = new LinkedList(); - } + DebugDataSender() { } void Append(DebugGLData *d) { - mList->insertBack(d); + mList.insertBack(d); } void Cleanup() { - if (!mList) + if (mList.isEmpty()) return; DebugGLData *d; - while ((d = mList->popFirst()) != nullptr) + while ((d = mList.popFirst()) != nullptr) delete d; - delete mList; - - mList = nullptr; } /* nsIRunnable impl; send the data */ @@ -620,7 +650,7 @@ public: DebugGLData *d; nsresult rv = NS_OK; - while ((d = mList->popFirst()) != nullptr) { + while ((d = mList.popFirst()) != nullptr) { std::auto_ptr cleaner(d); if (!d->Write()) { rv = NS_ERROR_FAILURE; @@ -631,84 +661,124 @@ public: Cleanup(); if (NS_FAILED(rv)) { - LayerScope::DestroyServerSocket(); + WebSocketHelper::DestroyServerSocket(); } return NS_OK; } protected: - LinkedList *mList; + LinkedList mList; }; NS_IMPL_ISUPPORTS(DebugDataSender, nsIRunnable); -void -LayerScope::CreateServerSocket() +/* + * LayerScope SendXXX Structure + * 1. SendLayer + * 2. SendEffectChain + * 1. SendTexturedEffect + * -> SendTextureSource + * 2. SendYCbCrEffect + * -> SendTextureSource + * 3. SendColor + */ +class SenderHelper { - if (!gfxPrefs::LayerScopeEnabled()) { +// Sender public APIs +public: + static void SendLayer(LayerComposite* aLayer, + int aWidth, + int aHeight); + + static void SendEffectChain(gl::GLContext* aGLContext, + const EffectChain& aEffectChain, + int aWidth = 0, + int aHeight = 0); + +// Sender private functions +private: + static void SendColor(void* aLayerRef, + const gfxRGBA& aColor, + int aWidth, + int aHeight); + static void SendTextureSource(GLContext* aGLContext, + void* aLayerRef, + TextureSourceOGL* aSource, + bool aFlipY); + static void SendTexturedEffect(GLContext* aGLContext, + void* aLayerRef, + const TexturedEffect* aEffect); + static void SendYCbCrEffect(GLContext* aGLContext, + void* aLayerRef, + const EffectYCbCr* aEffect); +}; + + +// ---------------------------------------------- +// SenderHelper implementation +// ---------------------------------------------- +void +SenderHelper::SendLayer(LayerComposite* aLayer, + int aWidth, + int aHeight) +{ + MOZ_ASSERT(aLayer && aLayer->GetLayer()); + if (!aLayer || !aLayer->GetLayer()) { return; } - if (!gLayerScopeWebSocketManager) { - gLayerScopeWebSocketManager = new LayerScopeWebSocketManager(); + switch (aLayer->GetLayer()->GetType()) { + case Layer::TYPE_COLOR: { + EffectChain effect; + aLayer->GenEffectChain(effect); + SenderHelper::SendEffectChain(nullptr, effect, aWidth, aHeight); + break; + } + case Layer::TYPE_IMAGE: + case Layer::TYPE_CANVAS: + case Layer::TYPE_THEBES: { + // Get CompositableHost and Compositor + CompositableHost* compHost = aLayer->GetCompositableHost(); + Compositor* comp = compHost->GetCompositor(); + // Send EffectChain only for CompositorOGL + if (LayersBackend::LAYERS_OPENGL == comp->GetBackendType()) { + CompositorOGL* compOGL = static_cast(comp); + EffectChain effect; + // Generate primary effect (lock and gen) + AutoLockCompositableHost lock(compHost); + aLayer->GenEffectChain(effect); + SenderHelper::SendEffectChain(compOGL->gl(), effect); + } + break; + } + case Layer::TYPE_CONTAINER: + default: + break; } } void -LayerScope::DestroyServerSocket() +SenderHelper::SendColor(void* aLayerRef, + const gfxRGBA& aColor, + int aWidth, + int aHeight) { - if (gLayerScopeWebSocketManager) { - gLayerScopeWebSocketManager->RemoveAllConnections(); - } -} - -void -LayerScope::BeginFrame(GLContext* aGLContext, int64_t aFrameStamp) -{ - if (!gLayerScopeWebSocketManager) - return; - - if (!gLayerScopeWebSocketManager->IsConnected()) - return; - -#if 0 - // if we're sending data in between frames, flush the list down the socket, - // and start a new one - if (gCurrentSender) { - gDebugSenderThread->Dispatch(gCurrentSender, NS_DISPATCH_NORMAL); - } -#endif - - gLayerScopeWebSocketManager->AppendDebugData(new DebugGLData(DebugGLData::FrameStart, aGLContext, aFrameStamp)); -} - -void -LayerScope::EndFrame(GLContext* aGLContext) -{ - if (!CheckSender()) - return; - - gLayerScopeWebSocketManager->AppendDebugData(new DebugGLData(DebugGLData::FrameEnd, aGLContext)); - gLayerScopeWebSocketManager->DispatchDebugData(); -} - -static void -SendColor(void* aLayerRef, const gfxRGBA& aColor, int aWidth, int aHeight) -{ - if (!CheckSender()) - return; - - gLayerScopeWebSocketManager->AppendDebugData( + WebSocketHelper::GetSocketManager()->AppendDebugData( new DebugGLColorData(aLayerRef, aColor, aWidth, aHeight)); } -static void -SendTextureSource(GLContext* aGLContext, - void* aLayerRef, - TextureSourceOGL* aSource, - bool aFlipY) +void +SenderHelper::SendTextureSource(GLContext* aGLContext, + void* aLayerRef, + TextureSourceOGL* aSource, + bool aFlipY) { + MOZ_ASSERT(aGLContext); + if (!aGLContext) { + return; + } + GLenum textureTarget = aSource->GetTextureTarget(); ShaderConfigOGL config = ShaderConfigFromTargetAndFormat(textureTarget, aSource->GetFormat()); @@ -736,15 +806,15 @@ SendTextureSource(GLContext* aGLContext, size, shaderConfig, aFlipY); - gLayerScopeWebSocketManager->AppendDebugData( + WebSocketHelper::GetSocketManager()->AppendDebugData( new DebugGLTextureData(aGLContext, aLayerRef, textureTarget, textureId, img)); } -static void -SendTexturedEffect(GLContext* aGLContext, - void* aLayerRef, - const TexturedEffect* aEffect) +void +SenderHelper::SendTexturedEffect(GLContext* aGLContext, + void* aLayerRef, + const TexturedEffect* aEffect) { TextureSourceOGL* source = aEffect->mTexture->AsSourceOGL(); if (!source) @@ -754,10 +824,10 @@ SendTexturedEffect(GLContext* aGLContext, SendTextureSource(aGLContext, aLayerRef, source, flipY); } -static void -SendYCbCrEffect(GLContext* aGLContext, - void* aLayerRef, - const EffectYCbCr* aEffect) +void +SenderHelper::SendYCbCrEffect(GLContext* aGLContext, + void* aLayerRef, + const EffectYCbCr* aEffect) { TextureSource* sourceYCbCr = aEffect->mTexture; if (!sourceYCbCr) @@ -775,49 +845,48 @@ SendYCbCrEffect(GLContext* aGLContext, } void -LayerScope::SendEffectChain(GLContext* aGLContext, - const EffectChain& aEffectChain, - int aWidth, int aHeight) +SenderHelper::SendEffectChain(GLContext* aGLContext, + const EffectChain& aEffectChain, + int aWidth, + int aHeight) { - if (!CheckSender()) - return; - const Effect* primaryEffect = aEffectChain.mPrimaryEffect; switch (primaryEffect->mType) { - case EffectTypes::RGB: - { - const TexturedEffect* texturedEffect = - static_cast(primaryEffect); - SendTexturedEffect(aGLContext, aEffectChain.mLayerRef, texturedEffect); - } - break; - case EffectTypes::YCBCR: - { - const EffectYCbCr* yCbCrEffect = - static_cast(primaryEffect); - SendYCbCrEffect(aGLContext, aEffectChain.mLayerRef, yCbCrEffect); - } - case EffectTypes::SOLID_COLOR: - { - const EffectSolidColor* solidColorEffect = - static_cast(primaryEffect); - gfxRGBA color(solidColorEffect->mColor.r, - solidColorEffect->mColor.g, - solidColorEffect->mColor.b, - solidColorEffect->mColor.a); - SendColor(aEffectChain.mLayerRef, color, aWidth, aHeight); - } - break; - case EffectTypes::COMPONENT_ALPHA: - case EffectTypes::RENDER_TARGET: - default: - break; + case EffectTypes::RGB: { + const TexturedEffect* texturedEffect = + static_cast(primaryEffect); + SendTexturedEffect(aGLContext, aEffectChain.mLayerRef, texturedEffect); + break; + } + case EffectTypes::YCBCR: { + const EffectYCbCr* yCbCrEffect = + static_cast(primaryEffect); + SendYCbCrEffect(aGLContext, aEffectChain.mLayerRef, yCbCrEffect); + break; + } + case EffectTypes::SOLID_COLOR: { + const EffectSolidColor* solidColorEffect = + static_cast(primaryEffect); + gfxRGBA color(solidColorEffect->mColor.r, + solidColorEffect->mColor.g, + solidColorEffect->mColor.b, + solidColorEffect->mColor.a); + SendColor(aEffectChain.mLayerRef, color, aWidth, aHeight); + break; + } + case EffectTypes::COMPONENT_ALPHA: + case EffectTypes::RENDER_TARGET: + default: + break; } //const Effect* secondaryEffect = aEffectChain.mSecondaryEffects[EffectTypes::MASK]; // TODO: } +// ---------------------------------------------- +// LayerScopeWebSocketManager implementation +// ---------------------------------------------- LayerScopeWebSocketManager::LayerScopeWebSocketManager() { NS_NewThread(getter_AddRefs(mDebugSenderThread)); @@ -832,7 +901,8 @@ LayerScopeWebSocketManager::~LayerScopeWebSocketManager() { } -void LayerScopeWebSocketManager::AppendDebugData(DebugGLData *aDebugData) +void +LayerScopeWebSocketManager::AppendDebugData(DebugGLData *aDebugData) { if (!mCurrentSender) { mCurrentSender = new DebugDataSender(); @@ -841,11 +911,125 @@ void LayerScopeWebSocketManager::AppendDebugData(DebugGLData *aDebugData) mCurrentSender->Append(aDebugData); } -void LayerScopeWebSocketManager::DispatchDebugData() +void +LayerScopeWebSocketManager::CleanDebugData() +{ + if (mCurrentSender) { + mCurrentSender->Cleanup(); + } +} + +void +LayerScopeWebSocketManager::DispatchDebugData() { mDebugSenderThread->Dispatch(mCurrentSender, NS_DISPATCH_NORMAL); mCurrentSender = nullptr; } + +// ---------------------------------------------- +// LayerScope implementation +// ---------------------------------------------- +void +LayerScope::Init() +{ + if (!gfxPrefs::LayerScopeEnabled()) { + return; + } + + // Note: The server socket has to be created on the main thread + WebSocketHelper::CreateServerSocket(); +} + +void +LayerScope::DeInit() +{ + // Destroy Web Server Socket + WebSocketHelper::DestroyServerSocket(); +} + +void +LayerScope::SendEffectChain(gl::GLContext* aGLContext, + const EffectChain& aEffectChain, + int aWidth, + int aHeight) +{ + // Protect this public function + if (!CheckSendable()) { + return; + } + SenderHelper::SendEffectChain(aGLContext, aEffectChain, aWidth, aHeight); +} + +void +LayerScope::SendLayer(LayerComposite* aLayer, + int aWidth, + int aHeight) +{ + // Protect this public function + if (!CheckSendable()) { + return; + } + SenderHelper::SendLayer(aLayer, aWidth, aHeight); +} + +bool +LayerScope::CheckSendable() +{ + if (!WebSocketHelper::GetSocketManager()) { + return false; + } + if (!WebSocketHelper::GetSocketManager()->IsConnected()) { + return false; + } + return true; +} + +void +LayerScope::CleanLayer() +{ + if (CheckSendable()) { + WebSocketHelper::GetSocketManager()->CleanDebugData(); + } +} + +// ---------------------------------------------- +// LayerScopeAutoFrame implementation +// ---------------------------------------------- +LayerScopeAutoFrame::LayerScopeAutoFrame(int64_t aFrameStamp) +{ + // Do Begin Frame + BeginFrame(aFrameStamp); +} + +LayerScopeAutoFrame::~LayerScopeAutoFrame() +{ + // Do End Frame + EndFrame(); +} + +void +LayerScopeAutoFrame::BeginFrame(int64_t aFrameStamp) +{ + if (!LayerScope::CheckSendable()) { + return; + } + + WebSocketHelper::GetSocketManager()->AppendDebugData( + new DebugGLData(DebugGLData::FrameStart, nullptr, aFrameStamp)); +} + +void +LayerScopeAutoFrame::EndFrame() +{ + if (!LayerScope::CheckSendable()) { + return; + } + + WebSocketHelper::GetSocketManager()->AppendDebugData( + new DebugGLData(DebugGLData::FrameEnd, nullptr)); + WebSocketHelper::GetSocketManager()->DispatchDebugData(); +} + } /* layers */ } /* mozilla */ diff --git a/gfx/layers/LayerScope.h b/gfx/layers/LayerScope.h index a8ac4581fbba..883ea4c9c765 100644 --- a/gfx/layers/LayerScope.h +++ b/gfx/layers/LayerScope.h @@ -17,16 +17,32 @@ namespace gl { class GLContext; } namespace layers { struct EffectChain; +class LayerComposite; class LayerScope { public: - static void CreateServerSocket(); - static void DestroyServerSocket(); - static void BeginFrame(gl::GLContext* aGLContext, int64_t aFrameStamp); - static void EndFrame(gl::GLContext* aGLContext); + static void Init(); + static void DeInit(); static void SendEffectChain(gl::GLContext* aGLContext, const EffectChain& aEffectChain, - int aWidth, int aHeight); + int aWidth, + int aHeight); + static void SendLayer(LayerComposite* aLayer, + int aWidth, + int aHeight); + static bool CheckSendable(); + static void CleanLayer(); +}; + +// Perform BeginFrame and EndFrame automatically +class LayerScopeAutoFrame { +public: + LayerScopeAutoFrame(int64_t aFrameStamp); + ~LayerScopeAutoFrame(); + +private: + static void BeginFrame(int64_t aFrameStamp); + static void EndFrame(); }; } /* layers */ diff --git a/gfx/layers/composite/CanvasLayerComposite.cpp b/gfx/layers/composite/CanvasLayerComposite.cpp index 897f521d2390..d96f7aeb2b6d 100644 --- a/gfx/layers/composite/CanvasLayerComposite.cpp +++ b/gfx/layers/composite/CanvasLayerComposite.cpp @@ -87,18 +87,6 @@ CanvasLayerComposite::RenderLayer(const nsIntRect& aClipRect) } #endif - GraphicsFilter filter = mFilter; -#ifdef ANDROID - // Bug 691354 - // Using the LINEAR filter we get unexplained artifacts. - // Use NEAREST when no scaling is required. - Matrix matrix; - bool is2D = GetEffectiveTransform().Is2D(&matrix); - if (is2D && !ThebesMatrix(matrix).HasNonTranslationOrFlip()) { - filter = GraphicsFilter::FILTER_NEAREST; - } -#endif - EffectChain effectChain(this); AddBlendModeEffect(effectChain); @@ -108,7 +96,7 @@ CanvasLayerComposite::RenderLayer(const nsIntRect& aClipRect) mImageHost->Composite(effectChain, GetEffectiveOpacity(), GetEffectiveTransform(), - gfx::ToFilter(filter), + GetEffectFilter(), clipRect); mImageHost->BumpFlashCounter(); } @@ -132,6 +120,30 @@ CanvasLayerComposite::CleanupResources() mImageHost = nullptr; } +gfx::Filter +CanvasLayerComposite::GetEffectFilter() +{ + GraphicsFilter filter = mFilter; +#ifdef ANDROID + // Bug 691354 + // Using the LINEAR filter we get unexplained artifacts. + // Use NEAREST when no scaling is required. + Matrix matrix; + bool is2D = GetEffectiveTransform().Is2D(&matrix); + if (is2D && !ThebesMatrix(matrix).HasNonTranslationOrFlip()) { + filter = GraphicsFilter::FILTER_NEAREST; + } +#endif + return gfx::ToFilter(filter); +} + +void +CanvasLayerComposite::GenEffectChain(EffectChain& aEffect) +{ + aEffect.mLayerRef = this; + aEffect.mPrimaryEffect = mImageHost->GenEffect(GetEffectFilter()); +} + void CanvasLayerComposite::PrintInfo(std::stringstream& aStream, const char* aPrefix) { diff --git a/gfx/layers/composite/CanvasLayerComposite.h b/gfx/layers/composite/CanvasLayerComposite.h index bf0227ab934a..4bd5bc6e01c3 100644 --- a/gfx/layers/composite/CanvasLayerComposite.h +++ b/gfx/layers/composite/CanvasLayerComposite.h @@ -52,6 +52,8 @@ public: virtual void CleanupResources() MOZ_OVERRIDE; + virtual void GenEffectChain(EffectChain& aEffect) MOZ_OVERRIDE; + CompositableHost* GetCompositableHost() MOZ_OVERRIDE; virtual LayerComposite* AsLayerComposite() MOZ_OVERRIDE { return this; } @@ -63,6 +65,9 @@ public: protected: virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) MOZ_OVERRIDE; +private: + gfx::Filter GetEffectFilter(); + private: RefPtr mImageHost; }; diff --git a/gfx/layers/composite/ColorLayerComposite.cpp b/gfx/layers/composite/ColorLayerComposite.cpp index 6aeeb785b344..231e93551884 100644 --- a/gfx/layers/composite/ColorLayerComposite.cpp +++ b/gfx/layers/composite/ColorLayerComposite.cpp @@ -24,11 +24,9 @@ void ColorLayerComposite::RenderLayer(const nsIntRect& aClipRect) { EffectChain effects(this); - gfxRGBA color(GetColor()); - effects.mPrimaryEffect = new EffectSolidColor(gfx::Color(color.r, - color.g, - color.b, - color.a)); + + GenEffectChain(effects); + nsIntRect boundRect = GetBounds(); LayerManagerComposite::AutoAddMaskEffect autoMaskEffect(GetMaskLayer(), @@ -50,5 +48,16 @@ ColorLayerComposite::RenderLayer(const nsIntRect& aClipRect) transform); } +void +ColorLayerComposite::GenEffectChain(EffectChain& aEffect) +{ + aEffect.mLayerRef = this; + gfxRGBA color(GetColor()); + aEffect.mPrimaryEffect = new EffectSolidColor(gfx::Color(color.r, + color.g, + color.b, + color.a)); +} + } /* layers */ } /* mozilla */ diff --git a/gfx/layers/composite/ColorLayerComposite.h b/gfx/layers/composite/ColorLayerComposite.h index 8252ea49c133..7dc39260dbfb 100644 --- a/gfx/layers/composite/ColorLayerComposite.h +++ b/gfx/layers/composite/ColorLayerComposite.h @@ -44,6 +44,8 @@ public: virtual void RenderLayer(const nsIntRect& aClipRect) MOZ_OVERRIDE; virtual void CleanupResources() MOZ_OVERRIDE {}; + virtual void GenEffectChain(EffectChain& aEffect) MOZ_OVERRIDE; + CompositableHost* GetCompositableHost() MOZ_OVERRIDE { return nullptr; } virtual LayerComposite* AsLayerComposite() MOZ_OVERRIDE { return this; } diff --git a/gfx/layers/composite/CompositableHost.h b/gfx/layers/composite/CompositableHost.h index ba2726fd683c..acf7799d0c88 100644 --- a/gfx/layers/composite/CompositableHost.h +++ b/gfx/layers/composite/CompositableHost.h @@ -17,6 +17,7 @@ #include "mozilla/gfx/Types.h" // for Filter #include "mozilla/ipc/ProtocolUtils.h" #include "mozilla/layers/CompositorTypes.h" // for TextureInfo, etc +#include "mozilla/layers/Effects.h" // for Texture Effect #include "mozilla/layers/LayersTypes.h" // for LayerRenderState, etc #include "mozilla/layers/TextureHost.h" // for TextureHost #include "mozilla/mozalloc.h" // for operator delete @@ -289,6 +290,14 @@ public: void SetAsyncID(uint64_t aID) { mAsyncID = aID; } + virtual bool Lock() { return false; } + + virtual void Unlock() { } + + virtual TemporaryRef GenEffect(const gfx::Filter& aFilter) { + return nullptr; + } + protected: TextureInfo mTextureInfo; uint64_t mAsyncID; @@ -301,6 +310,29 @@ protected: bool mKeepAttached; }; +class AutoLockCompositableHost MOZ_FINAL +{ +public: + AutoLockCompositableHost(CompositableHost* aHost) + : mHost(aHost) + { + mSucceeded = mHost->Lock(); + } + + ~AutoLockCompositableHost() + { + if (mSucceeded) { + mHost->Unlock(); + } + } + + bool Failed() const { return !mSucceeded; } + +private: + RefPtr mHost; + bool mSucceeded; +}; + /** * Global CompositableMap, to use in the compositor thread only. * diff --git a/gfx/layers/composite/ContentHost.cpp b/gfx/layers/composite/ContentHost.cpp index c5942ba3db7b..d54ec10a4467 100644 --- a/gfx/layers/composite/ContentHost.cpp +++ b/gfx/layers/composite/ContentHost.cpp @@ -35,27 +35,6 @@ ContentHostBase::~ContentHostBase() { } -struct AutoLockContentHost -{ - AutoLockContentHost(ContentHostBase* aHost) - : mHost(aHost) - { - mSucceeded = mHost->Lock(); - } - - ~AutoLockContentHost() - { - if (mSucceeded) { - mHost->Unlock(); - } - } - - bool Failed() { return !mSucceeded; } - - ContentHostBase* mHost; - bool mSucceeded; -}; - void ContentHostBase::Composite(EffectChain& aEffectChain, float aOpacity, @@ -67,7 +46,7 @@ ContentHostBase::Composite(EffectChain& aEffectChain, { NS_ASSERTION(aVisibleRegion, "Requires a visible region"); - AutoLockContentHost lock(this); + AutoLockCompositableHost lock(this); if (lock.Failed()) { return; } @@ -78,9 +57,8 @@ ContentHostBase::Composite(EffectChain& aEffectChain, if (!source) { return; } - RefPtr effect = - CreateTexturedEffect(source, sourceOnWhite, aFilter, true); + RefPtr effect = GenEffect(aFilter); if (!effect) { return; } @@ -229,6 +207,16 @@ ContentHostBase::Composite(EffectChain& aEffectChain, aTransform, mFlashCounter); } +TemporaryRef +ContentHostBase::GenEffect(const gfx::Filter& aFilter) +{ + RefPtr source = GetTextureSource(); + RefPtr sourceOnWhite = GetTextureSourceOnWhite(); + if (!source) { + return nullptr; + } + return CreateTexturedEffect(source, sourceOnWhite, aFilter, true); +} void ContentHostTexture::UseTextureHost(TextureHost* aTexture) diff --git a/gfx/layers/composite/ContentHost.h b/gfx/layers/composite/ContentHost.h index e38d4d23de0d..40580fcea78a 100644 --- a/gfx/layers/composite/ContentHost.h +++ b/gfx/layers/composite/ContentHost.h @@ -102,12 +102,11 @@ public: virtual void SetPaintWillResample(bool aResample) { mPaintWillResample = aResample; } - virtual bool Lock() = 0; - virtual void Unlock() = 0; - virtual NewTextureSource* GetTextureSource() = 0; virtual NewTextureSource* GetTextureSourceOnWhite() = 0; + virtual TemporaryRef GenEffect(const gfx::Filter& aFilter) MOZ_OVERRIDE; + protected: virtual nsIntPoint GetOriginOffset() { @@ -150,7 +149,7 @@ public: virtual void UseComponentAlphaTextures(TextureHost* aTextureOnBlack, TextureHost* aTextureOnWhite) MOZ_OVERRIDE; - virtual bool Lock() { + virtual bool Lock() MOZ_OVERRIDE { MOZ_ASSERT(!mLocked); if (!mTextureHost) { return false; @@ -166,7 +165,7 @@ public: mLocked = true; return true; } - virtual void Unlock() { + virtual void Unlock() MOZ_OVERRIDE { MOZ_ASSERT(mLocked); mTextureHost->Unlock(); if (mTextureHostOnWhite) { @@ -175,11 +174,11 @@ public: mLocked = false; } - virtual NewTextureSource* GetTextureSource() { + virtual NewTextureSource* GetTextureSource() MOZ_OVERRIDE { MOZ_ASSERT(mLocked); return mTextureHost->GetTextureSources(); } - virtual NewTextureSource* GetTextureSourceOnWhite() { + virtual NewTextureSource* GetTextureSourceOnWhite() MOZ_OVERRIDE { MOZ_ASSERT(mLocked); if (mTextureHostOnWhite) { return mTextureHostOnWhite->GetTextureSources(); @@ -281,20 +280,20 @@ public: virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) MOZ_OVERRIDE; - virtual bool Lock() { + virtual bool Lock() MOZ_OVERRIDE { MOZ_ASSERT(!mLocked); ProcessTextureUpdates(); mLocked = true; return true; } - virtual void Unlock() { + virtual void Unlock() MOZ_OVERRIDE { MOZ_ASSERT(mLocked); mLocked = false; } - virtual NewTextureSource* GetTextureSource(); - virtual NewTextureSource* GetTextureSourceOnWhite(); + virtual NewTextureSource* GetTextureSource() MOZ_OVERRIDE; + virtual NewTextureSource* GetTextureSourceOnWhite() MOZ_OVERRIDE; private: diff --git a/gfx/layers/composite/ImageHost.cpp b/gfx/layers/composite/ImageHost.cpp index a07b3be97378..2025fe0b493b 100644 --- a/gfx/layers/composite/ImageHost.cpp +++ b/gfx/layers/composite/ImageHost.cpp @@ -31,6 +31,7 @@ ImageHost::ImageHost(const TextureInfo& aTextureInfo) : CompositableHost(aTextureInfo) , mFrontBuffer(nullptr) , mHasPictureRect(false) + , mLocked(false) {} ImageHost::~ImageHost() {} @@ -81,24 +82,17 @@ ImageHost::Composite(EffectChain& aEffectChain, mFrontBuffer->SetCompositor(GetCompositor()); mFrontBuffer->SetCompositableBackendSpecificData(GetCompositableBackendSpecificData()); - AutoLockTextureHost autoLock(mFrontBuffer); + AutoLockCompositableHost autoLock(this); if (autoLock.Failed()) { NS_WARNING("failed to lock front buffer"); return; } - RefPtr source = mFrontBuffer->GetTextureSources(); + RefPtr source = GetTextureSource(); if (!source) { return; } - bool isAlphaPremultiplied = true; - if (mFrontBuffer->GetFlags() & TextureFlags::NON_PREMULTIPLIED) - isAlphaPremultiplied = false; - - RefPtr effect = CreateTexturedEffect(mFrontBuffer->GetFormat(), - source, - aFilter, - isAlphaPremultiplied); + RefPtr effect = GenEffect(aFilter); if (!effect) { return; } @@ -243,5 +237,48 @@ ImageHost::GetAsSurface() } #endif +bool +ImageHost::Lock() +{ + MOZ_ASSERT(!mLocked); + if (!mFrontBuffer->Lock()) { + return false; + } + mLocked = true; + return true; +} + +void +ImageHost::Unlock() +{ + MOZ_ASSERT(mLocked); + mFrontBuffer->Unlock(); + mLocked = false; +} + +TemporaryRef +ImageHost::GetTextureSource() +{ + MOZ_ASSERT(mLocked); + return mFrontBuffer->GetTextureSources(); +} + +TemporaryRef +ImageHost::GenEffect(const gfx::Filter& aFilter) +{ + RefPtr source = GetTextureSource(); + if (!source) { + return nullptr; + } + bool isAlphaPremultiplied = true; + if (mFrontBuffer->GetFlags() & TextureFlags::NON_PREMULTIPLIED) + isAlphaPremultiplied = false; + + return CreateTexturedEffect(mFrontBuffer->GetFormat(), + source, + aFilter, + isAlphaPremultiplied); +} + } } diff --git a/gfx/layers/composite/ImageHost.h b/gfx/layers/composite/ImageHost.h index a41c20e5b0ab..5002a00a52a7 100644 --- a/gfx/layers/composite/ImageHost.h +++ b/gfx/layers/composite/ImageHost.h @@ -79,11 +79,20 @@ public: virtual TemporaryRef GetAsSurface() MOZ_OVERRIDE; #endif + virtual bool Lock() MOZ_OVERRIDE; + + virtual void Unlock() MOZ_OVERRIDE; + + virtual TemporaryRef GetTextureSource(); + + virtual TemporaryRef GenEffect(const gfx::Filter& aFilter) MOZ_OVERRIDE; + protected: RefPtr mFrontBuffer; nsIntRect mPictureRect; bool mHasPictureRect; + bool mLocked; }; } diff --git a/gfx/layers/composite/ImageLayerComposite.cpp b/gfx/layers/composite/ImageLayerComposite.cpp index 7c0417eea0b8..13c1c79dfdb2 100644 --- a/gfx/layers/composite/ImageLayerComposite.cpp +++ b/gfx/layers/composite/ImageLayerComposite.cpp @@ -107,7 +107,7 @@ ImageLayerComposite::RenderLayer(const nsIntRect& aClipRect) mImageHost->Composite(effectChain, GetEffectiveOpacity(), GetEffectiveTransform(), - gfx::ToFilter(mFilter), + GetEffectFilter(), clipRect); mImageHost->BumpFlashCounter(); } @@ -161,6 +161,19 @@ ImageLayerComposite::CleanupResources() mImageHost = nullptr; } +gfx::Filter +ImageLayerComposite::GetEffectFilter() +{ + return gfx::ToFilter(mFilter); +} + +void +ImageLayerComposite::GenEffectChain(EffectChain& aEffect) +{ + aEffect.mLayerRef = this; + aEffect.mPrimaryEffect = mImageHost->GenEffect(GetEffectFilter()); +} + void ImageLayerComposite::PrintInfo(std::stringstream& aStream, const char* aPrefix) { diff --git a/gfx/layers/composite/ImageLayerComposite.h b/gfx/layers/composite/ImageLayerComposite.h index 6dc854dd6bad..216f224dd219 100644 --- a/gfx/layers/composite/ImageLayerComposite.h +++ b/gfx/layers/composite/ImageLayerComposite.h @@ -51,6 +51,8 @@ public: CompositableHost* GetCompositableHost() MOZ_OVERRIDE; + virtual void GenEffectChain(EffectChain& aEffect) MOZ_OVERRIDE; + virtual LayerComposite* AsLayerComposite() MOZ_OVERRIDE { return this; } virtual const char* Name() const { return "ImageLayerComposite"; } @@ -58,6 +60,9 @@ public: protected: virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) MOZ_OVERRIDE; +private: + gfx::Filter GetEffectFilter(); + private: RefPtr mImageHost; }; diff --git a/gfx/layers/composite/LayerManagerComposite.cpp b/gfx/layers/composite/LayerManagerComposite.cpp index a4ea522c4f1e..ef225230011d 100644 --- a/gfx/layers/composite/LayerManagerComposite.cpp +++ b/gfx/layers/composite/LayerManagerComposite.cpp @@ -16,6 +16,7 @@ #include "GeckoProfiler.h" // for profiler_set_frame_number, etc #include "ImageLayerComposite.h" // for ImageLayerComposite #include "Layers.h" // for Layer, ContainerLayer, etc +#include "LayerScope.h" // for LayerScope Tool #include "ThebesLayerComposite.h" // for ThebesLayerComposite #include "TiledLayerBuffer.h" // for TiledLayerComposer #include "Units.h" // for ScreenIntRect @@ -417,6 +418,9 @@ LayerManagerComposite::Render() /** Our more efficient but less powerful alter ego, if one is available. */ nsRefPtr composer2D = mCompositor->GetWidget()->GetComposer2D(); + // Set LayerScope begin/end frame + LayerScopeAutoFrame frame(PR_Now()); + if (!mTarget && composer2D && composer2D->TryRender(mRoot, mWorldMatrix, mGeometryChanged)) { if (mFPS) { double fps = mFPS->mCompositionFps.AddFrameAndGetFps(TimeStamp::Now()); diff --git a/gfx/layers/composite/LayerManagerComposite.h b/gfx/layers/composite/LayerManagerComposite.h index 5d9dedde9a8c..fe6693f5c15d 100644 --- a/gfx/layers/composite/LayerManagerComposite.h +++ b/gfx/layers/composite/LayerManagerComposite.h @@ -74,7 +74,7 @@ class LayerManagerComposite : public LayerManager public: LayerManagerComposite(Compositor* aCompositor); ~LayerManagerComposite(); - + virtual void Destroy() MOZ_OVERRIDE; /** @@ -267,7 +267,7 @@ private: RefPtr mCompositor; nsAutoPtr mClonedLayerTreeProperties; - /** + /** * Context target, nullptr when drawing directly to our swap chain. */ RefPtr mTarget; @@ -336,11 +336,12 @@ public: virtual TiledLayerComposer* GetTiledLayerComposer() { return nullptr; } - virtual void DestroyFrontBuffer() { } void AddBlendModeEffect(EffectChain& aEffectChain); + virtual void GenEffectChain(EffectChain& aEffect) { } + /** * The following methods are * diff --git a/gfx/layers/composite/ThebesLayerComposite.cpp b/gfx/layers/composite/ThebesLayerComposite.cpp index 79ee638f8fe2..3b4870f3f835 100644 --- a/gfx/layers/composite/ThebesLayerComposite.cpp +++ b/gfx/layers/composite/ThebesLayerComposite.cpp @@ -147,7 +147,7 @@ ThebesLayerComposite::RenderLayer(const nsIntRect& aClipRect) mBuffer->Composite(effectChain, GetEffectiveOpacity(), GetEffectiveTransform(), - gfx::Filter::LINEAR, + GetEffectFilter(), clipRect, &visibleRegion, mRequiresTiledProperties ? &tiledLayerProps @@ -180,6 +180,13 @@ ThebesLayerComposite::CleanupResources() mBuffer = nullptr; } +void +ThebesLayerComposite::GenEffectChain(EffectChain& aEffect) +{ + aEffect.mLayerRef = this; + aEffect.mPrimaryEffect = mBuffer->GenEffect(GetEffectFilter()); +} + CSSToScreenScale ThebesLayerComposite::GetEffectiveResolution() { diff --git a/gfx/layers/composite/ThebesLayerComposite.h b/gfx/layers/composite/ThebesLayerComposite.h index ea39a376805e..13f468500bbc 100644 --- a/gfx/layers/composite/ThebesLayerComposite.h +++ b/gfx/layers/composite/ThebesLayerComposite.h @@ -56,6 +56,8 @@ public: virtual void CleanupResources() MOZ_OVERRIDE; + virtual void GenEffectChain(EffectChain& aEffect) MOZ_OVERRIDE; + virtual bool SetCompositableHost(CompositableHost* aHost) MOZ_OVERRIDE; virtual LayerComposite* AsLayerComposite() MOZ_OVERRIDE { return this; } @@ -81,8 +83,11 @@ protected: virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) MOZ_OVERRIDE; private: + gfx::Filter GetEffectFilter() { return gfx::Filter::LINEAR; } + CSSToScreenScale GetEffectiveResolution(); +private: RefPtr mBuffer; bool mRequiresTiledProperties; }; diff --git a/gfx/layers/opengl/CompositorOGL.cpp b/gfx/layers/opengl/CompositorOGL.cpp index b6c0bc0dc3c0..4a6bcd60e5bc 100644 --- a/gfx/layers/opengl/CompositorOGL.cpp +++ b/gfx/layers/opengl/CompositorOGL.cpp @@ -706,8 +706,6 @@ CompositorOGL::BeginFrame(const nsIntRegion& aInvalidRegion, MOZ_ASSERT(!mFrameInProgress, "frame still in progress (should have called EndFrame or AbortFrame"); - LayerScope::BeginFrame(mGLContext, PR_Now()); - mFrameInProgress = true; gfx::Rect rect; if (mUseExternalSurfaceSize) { @@ -1313,8 +1311,6 @@ CompositorOGL::EndFrame() mFrameInProgress = false; - LayerScope::EndFrame(mGLContext); - if (mTarget) { CopyToTarget(mTarget, mTargetBounds.TopLeft(), mCurrentRenderTarget->GetTransform()); mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0); diff --git a/ipc/glue/BackgroundChild.h b/ipc/glue/BackgroundChild.h index 7b0a6ad0af05..65a210a6eb1a 100644 --- a/ipc/glue/BackgroundChild.h +++ b/ipc/glue/BackgroundChild.h @@ -37,11 +37,6 @@ class PBackgroundChild; // (assuming success) GetForCurrentThread() will return the same actor every // time. // -// CloseForCurrentThread() will close the current PBackground actor. Subsequent -// calls to GetForCurrentThread will return null. CloseForCurrentThread() may -// only be called exactly once per thread. Currently it is illegal to call this -// before the PBackground actor has been created. -// // The PBackgroundChild actor and all its sub-protocol actors will be // automatically destroyed when its designated thread completes. class BackgroundChild MOZ_FINAL @@ -61,10 +56,6 @@ public: static bool GetOrCreateForCurrentThread(nsIIPCBackgroundChildCreateCallback* aCallback); - // See above. - static void - CloseForCurrentThread(); - private: // Only called by ContentChild or ContentParent. static void diff --git a/ipc/glue/BackgroundImpl.cpp b/ipc/glue/BackgroundImpl.cpp index 53a19f49d174..7ef9eae8a62c 100644 --- a/ipc/glue/BackgroundImpl.cpp +++ b/ipc/glue/BackgroundImpl.cpp @@ -350,8 +350,6 @@ class ChildImpl MOZ_FINAL : public BackgroundChildImpl nsIThread* mBoundThread; #endif - DebugOnly mActorDestroyed; - public: static bool OpenProtocolOnMainThread(nsIEventTarget* aEventTarget); @@ -374,15 +372,8 @@ public: THREADSAFETY_ASSERT(current); } - void - AssertActorDestroyed() - { - MOZ_ASSERT(mActorDestroyed, "ChildImpl::ActorDestroy not called in time"); - } - ChildImpl() : mBoundThread(nullptr) - , mActorDestroyed(false) { AssertIsOnMainThread(); } @@ -406,10 +397,6 @@ private: static bool GetOrCreateForCurrentThread(nsIIPCBackgroundChildCreateCallback* aCallback); - // Forwarded from BackgroundChild. - static void - CloseForCurrentThread(); - // Forwarded from BackgroundChildImpl. static BackgroundChildImpl::ThreadLocal* GetThreadLocalForCurrentThread(); @@ -422,17 +409,6 @@ private: if (threadLocalInfo) { if (threadLocalInfo->mActor) { threadLocalInfo->mActor->Close(); - threadLocalInfo->mActor->AssertActorDestroyed(); - // Since the actor is created on the main thread it must only - // be released on the main thread as well. - if (!NS_IsMainThread()) { - ChildImpl* actor; - threadLocalInfo->mActor.forget(&actor); - - nsCOMPtr releaser = - NS_NewNonOwningRunnableMethod(actor, &ChildImpl::Release); - MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(releaser))); - } } delete threadLocalInfo; } @@ -443,9 +419,7 @@ private: // This class is reference counted. ~ChildImpl() - { - AssertActorDestroyed(); - } + { } void SetBoundThread() @@ -861,13 +835,6 @@ BackgroundChild::GetOrCreateForCurrentThread( return ChildImpl::GetOrCreateForCurrentThread(aCallback); } -// static -void -BackgroundChild::CloseForCurrentThread() -{ - ChildImpl::CloseForCurrentThread(); -} - // ----------------------------------------------------------------------------- // BackgroundChildImpl Public Methods // ----------------------------------------------------------------------------- @@ -1611,11 +1578,7 @@ ChildImpl::GetForCurrentThread() auto threadLocalInfo = static_cast(PR_GetThreadPrivate(sThreadLocalIndex)); - if (!threadLocalInfo) { - return nullptr; - } - - return threadLocalInfo->mActor; + return threadLocalInfo ? threadLocalInfo->mActor : nullptr; } // static @@ -1679,31 +1642,6 @@ ChildImpl::GetOrCreateForCurrentThread( return true; } -// static -void -ChildImpl::CloseForCurrentThread() -{ - MOZ_ASSERT(sThreadLocalIndex != kBadThreadLocalIndex, - "BackgroundChild::Startup() was never called!"); - auto threadLocalInfo = - static_cast(PR_GetThreadPrivate(sThreadLocalIndex)); - - // If we don't have a thread local we are in one of these conditions: - // 1) Startup has not completed and we are racing - // 2) We were called again after a previous close or shutdown - // For now, these should not happen, so crash. We can add extra complexity - // in the future if it turns out we need to support these cases. - if (!threadLocalInfo) { - MOZ_CRASH("Attempting to close a non-existent PBackground actor!"); - } - - if (threadLocalInfo->mActor) { - threadLocalInfo->mActor->FlushPendingInterruptQueue(); - } - DebugOnly status = PR_SetThreadPrivate(sThreadLocalIndex, nullptr); - MOZ_ASSERT(status == PR_SUCCESS); -} - // static BackgroundChildImpl::ThreadLocal* ChildImpl::GetThreadLocalForCurrentThread() @@ -2008,7 +1946,6 @@ ChildImpl::ActorDestroy(ActorDestroyReason aWhy) { AssertIsOnBoundThread(); - mActorDestroyed = true; BackgroundChildImpl::ActorDestroy(aWhy); } diff --git a/ipc/glue/MessagePump.cpp b/ipc/glue/MessagePump.cpp index 1fed7fd2f335..456b08881ac1 100644 --- a/ipc/glue/MessagePump.cpp +++ b/ipc/glue/MessagePump.cpp @@ -7,13 +7,11 @@ #include "nsIRunnable.h" #include "nsIThread.h" #include "nsITimer.h" -#include "nsICancelableRunnable.h" #include "base/basictypes.h" #include "base/logging.h" #include "base/scoped_nsautorelease_pool.h" #include "mozilla/Assertions.h" -#include "mozilla/AutoRestore.h" #include "mozilla/DebugOnly.h" #include "nsComponentManagerUtils.h" #include "nsDebug.h" @@ -42,14 +40,12 @@ static mozilla::DebugOnly gFirstDelegate; namespace mozilla { namespace ipc { -class DoWorkRunnable MOZ_FINAL : public nsICancelableRunnable, +class DoWorkRunnable MOZ_FINAL : public nsIRunnable, public nsITimerCallback { public: DoWorkRunnable(MessagePump* aPump) : mPump(aPump) - , mCanceled(false) - , mCallingRunWhileCanceled(false) { MOZ_ASSERT(aPump); } @@ -57,15 +53,12 @@ public: NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSIRUNNABLE NS_DECL_NSITIMERCALLBACK - NS_DECL_NSICANCELABLERUNNABLE private: ~DoWorkRunnable() { } MessagePump* mPump; - bool mCanceled; - bool mCallingRunWhileCanceled; }; } /* namespace ipc */ @@ -218,17 +211,11 @@ MessagePump::DoDelayedWork(base::MessagePump::Delegate* aDelegate) } } -NS_IMPL_ISUPPORTS(DoWorkRunnable, nsIRunnable, nsITimerCallback, - nsICancelableRunnable) +NS_IMPL_ISUPPORTS(DoWorkRunnable, nsIRunnable, nsITimerCallback) NS_IMETHODIMP DoWorkRunnable::Run() { - MOZ_ASSERT(!mCanceled || mCallingRunWhileCanceled); - if (mCanceled && !mCallingRunWhileCanceled) { - return NS_OK; - } - MessageLoop* loop = MessageLoop::current(); MOZ_ASSERT(loop); @@ -255,23 +242,6 @@ DoWorkRunnable::Notify(nsITimer* aTimer) return NS_OK; } -NS_IMETHODIMP -DoWorkRunnable::Cancel() -{ - MOZ_ASSERT(!mCanceled); - MOZ_ASSERT(!mCallingRunWhileCanceled); - - // Workers require cancelable runnables, but we can't really cancel cleanly - // here. If we don't process all of these then we will leave something - // unprocessed in the chromium queue. Therefore, eagerly complete our work - // instead by immediately calling Run(). - mCanceled = true; - mozilla::AutoRestore guard(mCallingRunWhileCanceled); - mCallingRunWhileCanceled = true; - Run(); - return NS_OK; -} - void MessagePumpForChildProcess::Run(base::MessagePump::Delegate* aDelegate) { diff --git a/layout/style/nsCSSRules.cpp b/layout/style/nsCSSRules.cpp index ffcadc479833..fb3dca597b2a 100644 --- a/layout/style/nsCSSRules.cpp +++ b/layout/style/nsCSSRules.cpp @@ -31,7 +31,6 @@ #include "nsStyleUtil.h" #include "mozilla/css/Declaration.h" #include "nsCSSParser.h" -#include "nsPrintfCString.h" #include "nsDOMClassInfoID.h" #include "mozilla/dom/CSSStyleDeclarationBinding.h" #include "StyleRule.h" @@ -1408,52 +1407,6 @@ AppendSerializedFontSrc(const nsCSSValue& src, nsAString & aResult) aResult.Truncate(aResult.Length() - 2); // remove the last comma-space } -// print all characters with at least four hex digits -static void -AppendSerializedUnicodePoint(uint32_t aCode, nsACString &aBuf) -{ - aBuf.Append(nsPrintfCString("%04X", aCode)); -} - -// A unicode-range: descriptor is represented as an array of integers, -// to be interpreted as a sequence of pairs: min max min max ... -// It is in source order. (Possibly it should be sorted and overlaps -// consolidated, but right now we don't do that.) -static void -AppendSerializedUnicodeRange(nsCSSValue const & aValue, - nsAString & aResult) -{ - NS_PRECONDITION(aValue.GetUnit() == eCSSUnit_Null || - aValue.GetUnit() == eCSSUnit_Array, - "improper value unit for unicode-range:"); - aResult.Truncate(); - if (aValue.GetUnit() != eCSSUnit_Array) - return; - - nsCSSValue::Array const & sources = *aValue.GetArrayValue(); - nsAutoCString buf; - - NS_ABORT_IF_FALSE(sources.Count() % 2 == 0, - "odd number of entries in a unicode-range: array"); - - for (uint32_t i = 0; i < sources.Count(); i += 2) { - uint32_t min = sources[i].GetIntValue(); - uint32_t max = sources[i+1].GetIntValue(); - - // We don't try to replicate the U+XX?? notation. - buf.AppendLiteral("U+"); - AppendSerializedUnicodePoint(min, buf); - - if (min != max) { - buf.Append('-'); - AppendSerializedUnicodePoint(max, buf); - } - buf.AppendLiteral(", "); - } - buf.Truncate(buf.Length() - 2); // remove the last comma-space - CopyASCIItoUTF16(buf, aResult); -} - // Mapping from nsCSSFontDesc codes to nsCSSFontFaceStyleDecl fields. nsCSSValue nsCSSFontFaceStyleDecl::* const nsCSSFontFaceStyleDecl::Fields[] = { @@ -1539,7 +1492,7 @@ nsCSSFontFaceStyleDecl::GetPropertyValue(nsCSSFontDesc aFontDescID, return NS_OK; case eCSSFontDesc_UnicodeRange: - AppendSerializedUnicodeRange(val, aResult); + nsStyleUtil::AppendUnicodeRange(val, aResult); return NS_OK; case eCSSFontDesc_UNKNOWN: diff --git a/layout/style/nsStyleUtil.cpp b/layout/style/nsStyleUtil.cpp index b6226badf258..2a8ac0811428 100644 --- a/layout/style/nsStyleUtil.cpp +++ b/layout/style/nsStyleUtil.cpp @@ -13,6 +13,7 @@ #include "nsIContentPolicy.h" #include "nsIContentSecurityPolicy.h" #include "nsIURI.h" +#include "nsPrintfCString.h" using namespace mozilla; @@ -461,6 +462,51 @@ nsStyleUtil::ComputeFunctionalAlternates(const nsCSSValueList* aList, } } +// print all characters with at least four hex digits +static void +AppendSerializedUnicodePoint(uint32_t aCode, nsACString& aBuf) +{ + aBuf.Append(nsPrintfCString("%04X", aCode)); +} + +// A unicode-range: descriptor is represented as an array of integers, +// to be interpreted as a sequence of pairs: min max min max ... +// It is in source order. (Possibly it should be sorted and overlaps +// consolidated, but right now we don't do that.) +/* static */ void +nsStyleUtil::AppendUnicodeRange(const nsCSSValue& aValue, nsAString& aResult) +{ + NS_PRECONDITION(aValue.GetUnit() == eCSSUnit_Null || + aValue.GetUnit() == eCSSUnit_Array, + "improper value unit for unicode-range:"); + aResult.Truncate(); + if (aValue.GetUnit() != eCSSUnit_Array) + return; + + nsCSSValue::Array const & sources = *aValue.GetArrayValue(); + nsAutoCString buf; + + NS_ABORT_IF_FALSE(sources.Count() % 2 == 0, + "odd number of entries in a unicode-range: array"); + + for (uint32_t i = 0; i < sources.Count(); i += 2) { + uint32_t min = sources[i].GetIntValue(); + uint32_t max = sources[i+1].GetIntValue(); + + // We don't try to replicate the U+XX?? notation. + buf.AppendLiteral("U+"); + AppendSerializedUnicodePoint(min, buf); + + if (min != max) { + buf.Append('-'); + AppendSerializedUnicodePoint(max, buf); + } + buf.AppendLiteral(", "); + } + buf.Truncate(buf.Length() - 2); // remove the last comma-space + CopyASCIItoUTF16(buf, aResult); +} + /* static */ float nsStyleUtil::ColorComponentToFloat(uint8_t aAlpha) { diff --git a/layout/style/nsStyleUtil.h b/layout/style/nsStyleUtil.h index 0fddc31a3bcb..4481e5483e9a 100644 --- a/layout/style/nsStyleUtil.h +++ b/layout/style/nsStyleUtil.h @@ -64,6 +64,8 @@ public: static void AppendFontFeatureSettings(const nsCSSValue& src, nsAString& aResult); + static void AppendUnicodeRange(const nsCSSValue& aValue, nsAString& aResult); + static void AppendCSSNumber(float aNumber, nsAString& aResult) { aResult.AppendFloat(aNumber); diff --git a/mobile/android/base/AndroidManifest.xml.in b/mobile/android/base/AndroidManifest.xml.in index da37375c0b92..c7af00fa20cc 100644 --- a/mobile/android/base/AndroidManifest.xml.in +++ b/mobile/android/base/AndroidManifest.xml.in @@ -290,7 +290,9 @@ - + + diff --git a/mobile/android/base/GeckoProfile.java b/mobile/android/base/GeckoProfile.java index 37ac18a91b5d..190e6878e11f 100644 --- a/mobile/android/base/GeckoProfile.java +++ b/mobile/android/base/GeckoProfile.java @@ -200,6 +200,13 @@ public final class GeckoProfile { getGuestDir(context).mkdir(); GeckoProfile profile = getGuestProfile(context); profile.lock(); + + /* + * Now do the things that createProfileDirectory normally does -- + * right now that's kicking off DB init. + */ + profile.enqueueInitialization(); + return profile; } catch (Exception ex) { Log.e(LOGTAG, "Error creating guest profile", ex); diff --git a/mobile/android/base/ReferrerReceiver.java b/mobile/android/base/ReferrerReceiver.java deleted file mode 100644 index a83e95e0cad8..000000000000 --- a/mobile/android/base/ReferrerReceiver.java +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- - * 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/. */ - -package org.mozilla.gecko; - -import org.json.JSONException; -import org.json.JSONObject; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.util.Log; - -import java.net.URLDecoder; -import java.util.HashMap; - -public class ReferrerReceiver - extends BroadcastReceiver -{ - private static final String LOGTAG = "GeckoReferrerReceiver"; - - public static final String ACTION_INSTALL_REFERRER = "com.android.vending.INSTALL_REFERRER"; - public static final String UTM_SOURCE = "mozilla"; - - @Override - public void onReceive(Context context, Intent intent) { - if (ACTION_INSTALL_REFERRER.equals(intent.getAction())) { - String referrer = intent.getStringExtra("referrer"); - if (referrer == null) - return; - - HashMap values = new HashMap(); - try { - String referrers[] = referrer.split("&"); - for (String referrerValue : referrers) { - String keyValue[] = referrerValue.split("="); - values.put(URLDecoder.decode(keyValue[0]), URLDecoder.decode(keyValue[1])); - } - } catch (Exception e) { - } - - String source = values.get("utm_source"); - String campaign = values.get("utm_campaign"); - - if (source != null && UTM_SOURCE.equals(source) && campaign != null) { - try { - JSONObject data = new JSONObject(); - data.put("id", "playstore"); - data.put("version", campaign); - - // Try to make sure the prefs are written as a group - GeckoEvent event = GeckoEvent.createBroadcastEvent("Campaign:Set", data.toString()); - GeckoAppShell.sendEventToGecko(event); - } catch (JSONException e) { - Log.e(LOGTAG, "Error setting distribution", e); - } - } - } - } -} diff --git a/mobile/android/base/distribution/Distribution.java b/mobile/android/base/distribution/Distribution.java index b6505b27214b..bb33075c4c37 100644 --- a/mobile/android/base/distribution/Distribution.java +++ b/mobile/android/base/distribution/Distribution.java @@ -5,12 +5,19 @@ package org.mozilla.gecko.distribution; +import java.io.BufferedInputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.ProtocolException; +import java.net.SocketException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.UnknownHostException; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; @@ -19,34 +26,95 @@ import java.util.Map; import java.util.Queue; import java.util.Scanner; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.jar.JarEntry; +import java.util.jar.JarInputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import javax.net.ssl.SSLException; + +import org.apache.http.protocol.HTTP; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.mozilla.gecko.GeckoAppShell; import org.mozilla.gecko.GeckoEvent; import org.mozilla.gecko.GeckoSharedPrefs; +import org.mozilla.gecko.Telemetry; import org.mozilla.gecko.mozglue.RobocopTarget; import org.mozilla.gecko.util.ThreadUtils; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; +import android.os.SystemClock; import android.util.Log; /** * Handles distribution file loading and fetching, * and the corresponding hand-offs to Gecko. */ -public final class Distribution { +@RobocopTarget +public class Distribution { private static final String LOGTAG = "GeckoDistribution"; private static final int STATE_UNKNOWN = 0; private static final int STATE_NONE = 1; private static final int STATE_SET = 2; + private static final String FETCH_PROTOCOL = "https"; + private static final String FETCH_HOSTNAME = "distro-download.cdn.mozilla.net"; + private static final String FETCH_PATH = "/android/1/"; + private static final String FETCH_EXTENSION = ".jar"; + + private static final String EXPECTED_CONTENT_TYPE = "application/java-archive"; + + private static final String DISTRIBUTION_PATH = "distribution/"; + + /** + * Telemetry constants. + */ + private static final String HISTOGRAM_REFERRER_INVALID = "FENNEC_DISTRIBUTION_REFERRER_INVALID"; + private static final String HISTOGRAM_DOWNLOAD_TIME_MS = "FENNEC_DISTRIBUTION_DOWNLOAD_TIME_MS"; + private static final String HISTOGRAM_CODE_CATEGORY = "FENNEC_DISTRIBUTION_CODE_CATEGORY"; + + /** + * Success/failure codes. Don't exceed the maximum listed in Histograms.json. + */ + private static final int CODE_CATEGORY_STATUS_OUT_OF_RANGE = 0; + // HTTP status 'codes' run from 1 to 5. + private static final int CODE_CATEGORY_OFFLINE = 6; + private static final int CODE_CATEGORY_FETCH_EXCEPTION = 7; + + // It's a post-fetch exception if we were able to download, but not + // able to extract. + private static final int CODE_CATEGORY_POST_FETCH_EXCEPTION = 8; + private static final int CODE_CATEGORY_POST_FETCH_SECURITY_EXCEPTION = 9; + + // It's a malformed distribution if we could extract, but couldn't + // process the contents. + private static final int CODE_CATEGORY_MALFORMED_DISTRIBUTION = 10; + + // Specific fetch errors. + private static final int CODE_CATEGORY_FETCH_SOCKET_ERROR = 11; + private static final int CODE_CATEGORY_FETCH_SSL_ERROR = 12; + private static final int CODE_CATEGORY_FETCH_NON_SUCCESS_RESPONSE = 13; + private static final int CODE_CATEGORY_FETCH_INVALID_CONTENT_TYPE = 14; + + // Corresponds to the high value in Histograms.json. + private static final long MAX_DOWNLOAD_TIME_MSEC = 40000; // 40 seconds. + + + + /** + * Used as a drop-off point for ReferrerReceiver. Checked when we process + * first-run distribution. + * + * This is `protected` so that test code can clear it between runs. + */ + @RobocopTarget + protected static volatile ReferrerDescriptor referrer; + private static Distribution instance; private final Context context; @@ -70,6 +138,7 @@ public final class Distribution { return instance; } + @RobocopTarget public static class DistributionDescriptor { public final boolean valid; public final String id; @@ -140,6 +209,7 @@ public final class Distribution { * Use Context.getPackageResourcePath to find an implicit * package path. Reuses the existing Distribution if one exists. */ + @RobocopTarget public static void init(final Context context) { Distribution.init(Distribution.getInstance(context)); } @@ -166,6 +236,17 @@ public final class Distribution { this(context, context.getPackageResourcePath(), null); } + /** + * This method is called by ReferrerReceiver when we receive a post-install + * notification from Google Play. + * + * @param ref a parsed referrer value from the store-supplied intent. + */ + public static void onReceivedReferrer(ReferrerDescriptor ref) { + // Track the referrer object for distribution handling. + referrer = ref; + } + /** * Helper to grab a file in the distribution directory. * @@ -214,9 +295,11 @@ public final class Distribution { } catch (IOException e) { Log.e(LOGTAG, "Error getting distribution descriptor file.", e); + Telemetry.HistogramAdd(HISTOGRAM_CODE_CATEGORY, CODE_CATEGORY_MALFORMED_DISTRIBUTION); return null; } catch (JSONException e) { Log.e(LOGTAG, "Error parsing preferences.json", e); + Telemetry.HistogramAdd(HISTOGRAM_CODE_CATEGORY, CODE_CATEGORY_MALFORMED_DISTRIBUTION); return null; } } @@ -232,11 +315,13 @@ public final class Distribution { return new JSONArray(getFileContents(bookmarks)); } catch (IOException e) { Log.e(LOGTAG, "Error getting bookmarks", e); + Telemetry.HistogramAdd(HISTOGRAM_CODE_CATEGORY, CODE_CATEGORY_MALFORMED_DISTRIBUTION); + return null; } catch (JSONException e) { Log.e(LOGTAG, "Error parsing bookmarks.json", e); + Telemetry.HistogramAdd(HISTOGRAM_CODE_CATEGORY, CODE_CATEGORY_MALFORMED_DISTRIBUTION); + return null; } - - return null; } /** @@ -245,9 +330,12 @@ public final class Distribution { * Postcondition: if this returns true, distributionDir will have been * set and populated. * + * This method is *only* protected for use from testDistribution. + * * @return true if we've set a distribution. */ - private boolean doInit() { + @RobocopTarget + protected boolean doInit() { ThreadUtils.assertNotOnUiThread(); // Bail if we've already tried to initialize the distribution, and @@ -274,8 +362,9 @@ public final class Distribution { return true; } - // We try the APK, then the system directory. + // We try the install intent, then the APK, then the system directory. final boolean distributionSet = + checkIntentDistribution() || checkAPKDistribution() || checkSystemDistribution(); @@ -286,6 +375,153 @@ public final class Distribution { return distributionSet; } + /** + * If applicable, download and select the distribution specified in + * the referrer intent. + * + * @return true if a referrer-supplied distribution was selected. + */ + private boolean checkIntentDistribution() { + if (referrer == null) { + return false; + } + + URI uri = getReferredDistribution(referrer); + if (uri == null) { + return false; + } + + long start = SystemClock.uptimeMillis(); + Log.v(LOGTAG, "Downloading referred distribution: " + uri); + + try { + HttpURLConnection connection = (HttpURLConnection) uri.toURL().openConnection(); + + connection.setRequestProperty(HTTP.USER_AGENT, GeckoAppShell.getGeckoInterface().getDefaultUAString()); + connection.setRequestProperty("Accept", EXPECTED_CONTENT_TYPE); + + try { + final JarInputStream distro; + try { + distro = fetchDistribution(uri, connection); + } catch (Exception e) { + Log.e(LOGTAG, "Error fetching distribution from network.", e); + recordFetchTelemetry(e); + return false; + } + + long end = SystemClock.uptimeMillis(); + final long duration = end - start; + Log.d(LOGTAG, "Distro fetch took " + duration + "ms; result? " + (distro != null)); + Telemetry.HistogramAdd(HISTOGRAM_DOWNLOAD_TIME_MS, clamp(MAX_DOWNLOAD_TIME_MSEC, duration)); + + if (distro == null) { + // Nothing to do. + return false; + } + + // Try to copy distribution files from the fetched stream. + try { + Log.d(LOGTAG, "Copying files from fetched zip."); + if (copyFilesFromStream(distro)) { + // We always copy to the data dir, and we only copy files from + // a 'distribution' subdirectory. Track our dist dir now that + // we know it. + this.distributionDir = new File(getDataDir(), DISTRIBUTION_PATH); + return true; + } + } catch (SecurityException e) { + Log.e(LOGTAG, "Security exception copying files. Corrupt or malicious?", e); + Telemetry.HistogramAdd(HISTOGRAM_CODE_CATEGORY, CODE_CATEGORY_POST_FETCH_SECURITY_EXCEPTION); + } catch (Exception e) { + Log.e(LOGTAG, "Error copying files from distribution.", e); + Telemetry.HistogramAdd(HISTOGRAM_CODE_CATEGORY, CODE_CATEGORY_POST_FETCH_EXCEPTION); + } finally { + distro.close(); + } + } finally { + connection.disconnect(); + } + } catch (IOException e) { + Log.e(LOGTAG, "Error copying distribution files from network.", e); + recordFetchTelemetry(e); + } + + return false; + } + + private static final int clamp(long v, long c) { + return (int) Math.min(c, v); + } + + /** + * Fetch the provided URI, returning a {@link JarInputStream} if the response body + * is appropriate. + * + * Protected to allow for mocking. + * + * @return the entity body as a stream, or null on failure. + */ + @SuppressWarnings("static-method") + @RobocopTarget + protected JarInputStream fetchDistribution(URI uri, HttpURLConnection connection) throws IOException { + final int status = connection.getResponseCode(); + + Log.d(LOGTAG, "Distribution fetch: " + status); + // We record HTTP statuses as 2xx, 3xx, 4xx, 5xx => 2, 3, 4, 5. + final int value; + if (status > 599 || status < 100) { + Log.wtf(LOGTAG, "Unexpected HTTP status code: " + status); + value = CODE_CATEGORY_STATUS_OUT_OF_RANGE; + } else { + value = status / 100; + } + + Telemetry.HistogramAdd(HISTOGRAM_CODE_CATEGORY, value); + + if (status != 200) { + Log.w(LOGTAG, "Got status " + status + " fetching distribution."); + Telemetry.HistogramAdd(HISTOGRAM_CODE_CATEGORY, CODE_CATEGORY_FETCH_NON_SUCCESS_RESPONSE); + return null; + } + + final String contentType = connection.getContentType(); + if (contentType == null || !contentType.startsWith(EXPECTED_CONTENT_TYPE)) { + Log.w(LOGTAG, "Malformed response: invalid Content-Type."); + Telemetry.HistogramAdd(HISTOGRAM_CODE_CATEGORY, CODE_CATEGORY_FETCH_INVALID_CONTENT_TYPE); + return null; + } + + return new JarInputStream(new BufferedInputStream(connection.getInputStream()), true); + } + + private static void recordFetchTelemetry(final Exception exception) { + if (exception == null) { + // Should never happen. + Telemetry.HistogramAdd(HISTOGRAM_CODE_CATEGORY, CODE_CATEGORY_FETCH_EXCEPTION); + return; + } + + if (exception instanceof UnknownHostException) { + // Unknown host => we're offline. + Telemetry.HistogramAdd(HISTOGRAM_CODE_CATEGORY, CODE_CATEGORY_OFFLINE); + return; + } + + if (exception instanceof SSLException) { + Telemetry.HistogramAdd(HISTOGRAM_CODE_CATEGORY, CODE_CATEGORY_FETCH_SSL_ERROR); + return; + } + + if (exception instanceof ProtocolException || + exception instanceof SocketException) { + Telemetry.HistogramAdd(HISTOGRAM_CODE_CATEGORY, CODE_CATEGORY_FETCH_SOCKET_ERROR); + return; + } + + Telemetry.HistogramAdd(HISTOGRAM_CODE_CATEGORY, CODE_CATEGORY_FETCH_EXCEPTION); + } + /** * Execute tasks that wanted to run when we were done loading * the distribution. These tasks are expected to call {@link #exists()} @@ -308,7 +544,7 @@ public final class Distribution { // We always copy to the data dir, and we only copy files from // a 'distribution' subdirectory. Track our dist dir now that // we know it. - this.distributionDir = new File(getDataDir(), "distribution/"); + this.distributionDir = new File(getDataDir(), DISTRIBUTION_PATH); return true; } } catch (IOException e) { @@ -330,6 +566,41 @@ public final class Distribution { return false; } + /** + * Unpack distribution files from a downloaded jar stream. + * + * The caller is responsible for closing the provided stream. + */ + private boolean copyFilesFromStream(JarInputStream jar) throws FileNotFoundException, IOException { + final byte[] buffer = new byte[1024]; + boolean distributionSet = false; + JarEntry entry; + while ((entry = jar.getNextJarEntry()) != null) { + final String name = entry.getName(); + + if (entry.isDirectory()) { + // We'll let getDataFile deal with creating the directory hierarchy. + // Yes, we can do better, but it can wait. + continue; + } + + if (!name.startsWith(DISTRIBUTION_PATH)) { + continue; + } + + File outFile = getDataFile(name); + if (outFile == null) { + continue; + } + + distributionSet = true; + + writeStream(jar, outFile, entry.getTime(), buffer); + } + + return distributionSet; + } + /** * Copies the /distribution folder out of the APK and into the app's data directory. * Returns true if distribution files were found and copied. @@ -352,7 +623,7 @@ public final class Distribution { continue; } - if (!name.startsWith("distribution/")) { + if (!name.startsWith(DISTRIBUTION_PATH)) { continue; } @@ -413,6 +684,29 @@ public final class Distribution { return outFile; } + private URI getReferredDistribution(ReferrerDescriptor descriptor) { + final String content = descriptor.content; + if (content == null) { + return null; + } + + // We restrict here to avoid injection attacks. After all, + // we're downloading a distribution payload based on intent input. + if (!content.matches("^[a-zA-Z0-9]+$")) { + Log.e(LOGTAG, "Invalid referrer content: " + content); + Telemetry.HistogramAdd(HISTOGRAM_REFERRER_INVALID, 1); + return null; + } + + try { + return new URI(FETCH_PROTOCOL, FETCH_HOSTNAME, FETCH_PATH + content + FETCH_EXTENSION, null); + } catch (URISyntaxException e) { + // This should never occur. + Log.wtf(LOGTAG, "Invalid URI with content " + content + "!"); + return null; + } + } + /** * After calling this method, either distributionDir * will be set, or there is no distribution in use. @@ -432,7 +726,7 @@ public final class Distribution { // the APK, or it exists in /system/. // Look in each location in turn. // (This could be optimized by caching the path in shared prefs.) - File copied = new File(getDataDir(), "distribution/"); + File copied = new File(getDataDir(), DISTRIBUTION_PATH); if (copied.exists()) { return this.distributionDir = copied; } diff --git a/mobile/android/base/distribution/ReferrerDescriptor.java b/mobile/android/base/distribution/ReferrerDescriptor.java new file mode 100644 index 000000000000..f422810ed14f --- /dev/null +++ b/mobile/android/base/distribution/ReferrerDescriptor.java @@ -0,0 +1,55 @@ +/* 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/. */ + +package org.mozilla.gecko.distribution; + +import org.mozilla.gecko.mozglue.RobocopTarget; + +import android.net.Uri; + +/** + * Encapsulates access to values encoded in the "referrer" extra of an install intent. + * + * This object is immutable. + * + * Example input: + * + * "utm_source=campsource&utm_medium=campmed&utm_term=term%2Bhere&utm_content=content&utm_campaign=name" + */ +@RobocopTarget +public class ReferrerDescriptor { + public final String source; + public final String medium; + public final String term; + public final String content; + public final String campaign; + + public ReferrerDescriptor(final String referrer) { + if (referrer == null) { + source = null; + medium = null; + term = null; + content = null; + campaign = null; + return; + } + + final Uri u = new Uri.Builder() + .scheme("http") + .authority("local") + .path("/") + .encodedQuery(referrer).build(); + + source = u.getQueryParameter("utm_source"); + medium = u.getQueryParameter("utm_medium"); + term = u.getQueryParameter("utm_term"); + content = u.getQueryParameter("utm_content"); + campaign = u.getQueryParameter("utm_campaign"); + } + + @Override + public String toString() { + return "{s: " + source + ", m: " + medium + ", t: " + term + ", c: " + content + ", c: " + campaign + "}"; + } +} diff --git a/mobile/android/base/distribution/ReferrerReceiver.java b/mobile/android/base/distribution/ReferrerReceiver.java new file mode 100644 index 000000000000..9b310a08158a --- /dev/null +++ b/mobile/android/base/distribution/ReferrerReceiver.java @@ -0,0 +1,76 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- + * 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/. */ + +package org.mozilla.gecko.distribution; + +import org.json.JSONException; +import org.json.JSONObject; +import org.mozilla.gecko.GeckoAppShell; +import org.mozilla.gecko.GeckoEvent; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.text.TextUtils; +import android.util.Log; + +public class ReferrerReceiver extends BroadcastReceiver { + private static final String LOGTAG = "GeckoReferrerReceiver"; + + private static final String ACTION_INSTALL_REFERRER = "com.android.vending.INSTALL_REFERRER"; + + /** + * If the install intent has this source, we'll track the campaign ID. + */ + private static final String MOZILLA_UTM_SOURCE = "mozilla"; + + /** + * If the install intent has this campaign, we'll load the specified distribution. + */ + private static final String DISTRIBUTION_UTM_CAMPAIGN = "distribution"; + + @Override + public void onReceive(Context context, Intent intent) { + Log.v(LOGTAG, "Received intent " + intent); + if (!ACTION_INSTALL_REFERRER.equals(intent.getAction())) { + // This should never happen. + return; + } + + ReferrerDescriptor referrer = new ReferrerDescriptor(intent.getStringExtra("referrer")); + + // Track the referrer object for distribution handling. + if (TextUtils.equals(referrer.campaign, DISTRIBUTION_UTM_CAMPAIGN)) { + Distribution.onReceivedReferrer(referrer); + } else { + Log.d(LOGTAG, "Not downloading distribution: non-matching campaign."); + } + + // If this is a Mozilla campaign, pass the campaign along to Gecko. + if (TextUtils.equals(referrer.source, MOZILLA_UTM_SOURCE)) { + propagateMozillaCampaign(referrer); + } + } + + + private void propagateMozillaCampaign(ReferrerDescriptor referrer) { + if (referrer.campaign == null) { + return; + } + + try { + final JSONObject data = new JSONObject(); + data.put("id", "playstore"); + data.put("version", referrer.campaign); + String payload = data.toString(); + + // Try to make sure the prefs are written as a group. + final GeckoEvent event = GeckoEvent.createBroadcastEvent("Campaign:Set", payload); + GeckoAppShell.sendEventToGecko(event); + } catch (JSONException e) { + Log.e(LOGTAG, "Error propagating campaign identifier.", e); + } + } +} diff --git a/mobile/android/base/moz.build b/mobile/android/base/moz.build index 13ea43e45635..f8404c08c8d6 100644 --- a/mobile/android/base/moz.build +++ b/mobile/android/base/moz.build @@ -156,6 +156,8 @@ gbjar.sources += [ 'db/TabsProvider.java', 'db/TopSitesCursorWrapper.java', 'distribution/Distribution.java', + 'distribution/ReferrerDescriptor.java', + 'distribution/ReferrerReceiver.java', 'DoorHangerPopup.java', 'DynamicToolbar.java', 'EditBookmarkDialog.java', @@ -354,7 +356,6 @@ gbjar.sources += [ 'prompts/PromptService.java', 'prompts/TabInput.java', 'ReaderModeUtils.java', - 'ReferrerReceiver.java', 'Restarter.java', 'ScrollAnimator.java', 'ServiceNotificationClient.java', diff --git a/mobile/android/base/tests/testDistribution.java b/mobile/android/base/tests/testDistribution.java index 7d8b7edc2e3b..50a75e8191a3 100644 --- a/mobile/android/base/tests/testDistribution.java +++ b/mobile/android/base/tests/testDistribution.java @@ -2,19 +2,29 @@ package org.mozilla.gecko.tests; import java.io.File; import java.io.FileOutputStream; +import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URI; +import java.util.jar.JarInputStream; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.mozilla.gecko.Actions; +import org.mozilla.gecko.AppConstants; import org.mozilla.gecko.db.BrowserContract; import org.mozilla.gecko.distribution.Distribution; +import org.mozilla.gecko.distribution.ReferrerDescriptor; +import org.mozilla.gecko.mozglue.RobocopTarget; import org.mozilla.gecko.util.ThreadUtils; import android.app.Activity; +import android.content.Context; +import android.content.Intent; import android.content.SharedPreferences; +import android.util.Log; /** * Tests distribution customization. @@ -28,6 +38,38 @@ import android.content.SharedPreferences; * engine.xml */ public class testDistribution extends ContentProviderTest { + private static final String CLASS_REFERRER_RECEIVER = "org.mozilla.gecko.distribution.ReferrerReceiver"; + private static final String ACTION_INSTALL_REFERRER = "com.android.vending.INSTALL_REFERRER"; + private static final int WAIT_TIMEOUT_MSEC = 10000; + public static final String LOGTAG = "GeckoTestDistribution"; + + public static class TestableDistribution extends Distribution { + @Override + protected JarInputStream fetchDistribution(URI uri, + HttpURLConnection connection) throws IOException { + Log.i(LOGTAG, "Not downloading: this is a test."); + return null; + } + + public TestableDistribution(Context context) { + super(context); + } + + public void go() { + doInit(); + } + + @RobocopTarget + public static void clearReferrerDescriptorForTesting() { + referrer = null; + } + + @RobocopTarget + public static ReferrerDescriptor getReferrerDescriptorForTesting() { + return referrer; + } + } + private static final String MOCK_PACKAGE = "mock-package.zip"; private static final int PREF_REQUEST_ID = 0x7357; @@ -65,7 +107,7 @@ public class testDistribution extends ContentProviderTest { mAsserter.dumpLog("Background task completed. Proceeding."); } - public void testDistribution() { + public void testDistribution() throws Exception { mActivity = getActivity(); String mockPackagePath = getMockPackagePath(); @@ -87,6 +129,90 @@ public class testDistribution extends ContentProviderTest { setTestLocale("es-MX"); initDistribution(mockPackagePath); checkLocalizedPreferences("es-MX"); + + // Test the (stubbed) download interaction. + setTestLocale("en-US"); + clearDistributionPref(); + doTestValidReferrerIntent(); + + clearDistributionPref(); + doTestInvalidReferrerIntent(); + } + + public void doTestValidReferrerIntent() throws Exception { + // Send the faux-download intent. + // Equivalent to + // am broadcast -a com.android.vending.INSTALL_REFERRER \ + // -n org.mozilla.fennec/org.mozilla.gecko.distribution.ReferrerReceiver \ + // --es "referrer" "utm_source=mozilla&utm_medium=testmedium&utm_term=testterm&utm_content=testcontent&utm_campaign=distribution" + final String ref = "utm_source=mozilla&utm_medium=testmedium&utm_term=testterm&utm_content=testcontent&utm_campaign=distribution"; + final Intent intent = new Intent(ACTION_INSTALL_REFERRER); + intent.setClassName(AppConstants.ANDROID_PACKAGE_NAME, CLASS_REFERRER_RECEIVER); + intent.putExtra("referrer", ref); + mActivity.sendBroadcast(intent); + + // Wait for the intent to be processed. + final TestableDistribution distribution = new TestableDistribution(mActivity); + + final Object wait = new Object(); + distribution.addOnDistributionReadyCallback(new Runnable() { + @Override + public void run() { + mAsserter.ok(!distribution.exists(), "Not processed.", "No download because we're offline."); + ReferrerDescriptor referrerValue = TestableDistribution.getReferrerDescriptorForTesting(); + mAsserter.dumpLog("Referrer was " + referrerValue); + mAsserter.is(referrerValue.content, "testcontent", "Referrer content"); + mAsserter.is(referrerValue.medium, "testmedium", "Referrer medium"); + mAsserter.is(referrerValue.campaign, "distribution", "Referrer campaign"); + synchronized (wait) { + wait.notifyAll(); + } + } + }); + + distribution.go(); + synchronized (wait) { + wait.wait(WAIT_TIMEOUT_MSEC); + } + } + + /** + * Test processing if the campaign isn't "distribution". The intent shouldn't + * result in a download, and won't be saved as the temporary referrer, + * even if we *do* include it in a Campaign:Set message. + */ + public void doTestInvalidReferrerIntent() throws Exception { + // Send the faux-download intent. + // Equivalent to + // am broadcast -a com.android.vending.INSTALL_REFERRER \ + // -n org.mozilla.fennec/org.mozilla.gecko.distribution.ReferrerReceiver \ + // --es "referrer" "utm_source=mozilla&utm_medium=testmedium&utm_term=testterm&utm_content=testcontent&utm_campaign=testname" + final String ref = "utm_source=mozilla&utm_medium=testmedium&utm_term=testterm&utm_content=testcontent&utm_campaign=testname"; + final Intent intent = new Intent(ACTION_INSTALL_REFERRER); + intent.setClassName(AppConstants.ANDROID_PACKAGE_NAME, CLASS_REFERRER_RECEIVER); + intent.putExtra("referrer", ref); + mActivity.sendBroadcast(intent); + + // Wait for the intent to be processed. + final TestableDistribution distribution = new TestableDistribution(mActivity); + + final Object wait = new Object(); + distribution.addOnDistributionReadyCallback(new Runnable() { + @Override + public void run() { + mAsserter.ok(!distribution.exists(), "Not processed.", "No download because campaign was wrong."); + ReferrerDescriptor referrerValue = TestableDistribution.getReferrerDescriptorForTesting(); + mAsserter.is(referrerValue, null, "No referrer."); + synchronized (wait) { + wait.notifyAll(); + } + } + }); + + distribution.go(); + synchronized (wait) { + wait.wait(WAIT_TIMEOUT_MSEC); + } } // Initialize the distribution from the mock package. @@ -288,12 +414,16 @@ public class testDistribution extends ContentProviderTest { return mockPackagePath; } - // Clears the distribution pref to return distribution state to STATE_UNKNOWN + /** + * Clears the distribution pref to return distribution state to STATE_UNKNOWN, + * and wipes the in-memory referrer pigeonhole. + */ private void clearDistributionPref() { mAsserter.dumpLog("Clearing distribution pref."); SharedPreferences settings = mActivity.getSharedPreferences("GeckoApp", Activity.MODE_PRIVATE); String keyName = mActivity.getPackageName() + ".distribution_state"; settings.edit().remove(keyName).commit(); + TestableDistribution.clearReferrerDescriptorForTesting(); } @Override diff --git a/mobile/android/tests/browser/junit3/moz.build b/mobile/android/tests/browser/junit3/moz.build index 7d81516888df..c620954755e8 100644 --- a/mobile/android/tests/browser/junit3/moz.build +++ b/mobile/android/tests/browser/junit3/moz.build @@ -11,6 +11,7 @@ jar.sources += [ 'src/harness/BrowserInstrumentationTestRunner.java', 'src/harness/BrowserTestListener.java', 'src/tests/BrowserTestCase.java', + 'src/tests/TestDistribution.java', 'src/tests/TestGeckoSharedPrefs.java', 'src/tests/TestJarReader.java', 'src/tests/TestRawResource.java', diff --git a/mobile/android/tests/browser/junit3/src/tests/TestDistribution.java b/mobile/android/tests/browser/junit3/src/tests/TestDistribution.java new file mode 100644 index 000000000000..dcc2a9fafc7b --- /dev/null +++ b/mobile/android/tests/browser/junit3/src/tests/TestDistribution.java @@ -0,0 +1,36 @@ +/* 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/. */ + +package org.mozilla.gecko.browser.tests; + +import org.mozilla.gecko.distribution.ReferrerDescriptor; + +public class TestDistribution extends BrowserTestCase { + private static final String TEST_REFERRER_STRING = "utm_source=campsource&utm_medium=campmed&utm_term=term%2Bhere&utm_content=content&utm_campaign=name"; + private static final String TEST_MALFORMED_REFERRER_STRING = "utm_source=campsource&utm_medium=campmed&utm_term=term%2"; + + public void testReferrerParsing() { + ReferrerDescriptor good = new ReferrerDescriptor(TEST_REFERRER_STRING); + assertEquals("campsource", good.source); + assertEquals("campmed", good.medium); + assertEquals("term+here", good.term); + assertEquals("content", good.content); + assertEquals("name", good.campaign); + + // Uri.Builder is permissive. + ReferrerDescriptor bad = new ReferrerDescriptor(TEST_MALFORMED_REFERRER_STRING); + assertEquals("campsource", bad.source); + assertEquals("campmed", bad.medium); + assertFalse("term+here".equals(bad.term)); + assertNull(bad.content); + assertNull(bad.campaign); + + ReferrerDescriptor ugly = new ReferrerDescriptor(null); + assertNull(ugly.source); + assertNull(ugly.medium); + assertNull(ugly.term); + assertNull(ugly.content); + assertNull(ugly.campaign); + } +} diff --git a/security/apps/AppSignatureVerification.cpp b/security/apps/AppSignatureVerification.cpp index 2a7d9e37250e..e80c17e68b0e 100644 --- a/security/apps/AppSignatureVerification.cpp +++ b/security/apps/AppSignatureVerification.cpp @@ -569,7 +569,7 @@ VerifySignature(AppTrustedRoot trustedRoot, const SECItem& buffer, NS_IMETHODIMP OpenSignedAppFile(AppTrustedRoot aTrustedRoot, nsIFile* aJarFile, /*out, optional */ nsIZipReader** aZipReader, - /*out, optional */ nsIX509Cert3** aSignerCert) + /*out, optional */ nsIX509Cert** aSignerCert) { NS_ENSURE_ARG_POINTER(aJarFile); @@ -728,7 +728,7 @@ OpenSignedAppFile(AppTrustedRoot aTrustedRoot, nsIFile* aJarFile, // but we can't do that until we switch to libpkix. if (aSignerCert) { MOZ_ASSERT(CERT_LIST_HEAD(builtChain)); - nsCOMPtr signerCert = + nsCOMPtr signerCert = nsNSSCertificate::Create(CERT_LIST_HEAD(builtChain)->cert); NS_ENSURE_TRUE(signerCert, NS_ERROR_OUT_OF_MEMORY); signerCert.forget(aSignerCert); @@ -769,7 +769,7 @@ private: const nsCOMPtr mJarFile; nsMainThreadPtrHandle mCallback; nsCOMPtr mZipReader; // out - nsCOMPtr mSignerCert; // out + nsCOMPtr mSignerCert; // out }; } // unnamed namespace diff --git a/security/manager/pki/resources/content/pippki.js b/security/manager/pki/resources/content/pippki.js index c50f43f86bb7..21720ba8d354 100644 --- a/security/manager/pki/resources/content/pippki.js +++ b/security/manager/pki/resources/content/pippki.js @@ -43,7 +43,6 @@ function getDERString(cert) function getPKCS7String(cert, chainMode) { var length = {}; - cert.QueryInterface(Components.interfaces.nsIX509Cert3); var pkcs7Array = cert.exportAsCMS(chainMode, length); var pkcs7String = ''; for (var i = 0; i < pkcs7Array.length; i++) { @@ -110,10 +109,10 @@ function exportToFile(parent, cert) content = getDERString(cert); break; case 3: - content = getPKCS7String(cert, Components.interfaces.nsIX509Cert3.CMS_CHAIN_MODE_CertOnly); + content = getPKCS7String(cert, Components.interfaces.nsIX509Cert.CMS_CHAIN_MODE_CertOnly); break; case 4: - content = getPKCS7String(cert, Components.interfaces.nsIX509Cert3.CMS_CHAIN_MODE_CertChainWithRoot); + content = getPKCS7String(cert, Components.interfaces.nsIX509Cert.CMS_CHAIN_MODE_CertChainWithRoot); break; case 0: default: diff --git a/security/manager/pki/resources/content/viewCertDetails.js b/security/manager/pki/resources/content/viewCertDetails.js index bd30cf8a296b..8fe23d7d731a 100644 --- a/security/manager/pki/resources/content/viewCertDetails.js +++ b/security/manager/pki/resources/content/viewCertDetails.js @@ -3,7 +3,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ const nsIX509Cert = Components.interfaces.nsIX509Cert; -const nsIX509Cert3 = Components.interfaces.nsIX509Cert3; const nsX509CertDB = "@mozilla.org/security/x509certdb;1"; const nsIX509CertDB = Components.interfaces.nsIX509CertDB; const nsPK11TokenDB = "@mozilla.org/security/pk11tokendb;1"; @@ -94,14 +93,9 @@ function setWindowName() AddCertChain("treesetDump", chain, "dump_"); DisplayGeneralDataFromCert(cert); BuildPrettyPrint(cert); - - if (cert instanceof nsIX509Cert3) - { - cert.requestUsagesArrayAsync(new listener()); - } + cert.requestUsagesArrayAsync(new listener()); } - function addChildrenToTree(parentTree,label,value,addTwistie) { var treeChild1 = document.createElement("treechildren"); @@ -249,7 +243,7 @@ function DisplayGeneralDataFromCert(cert) addAttributeFromCert('validitystart', cert.validity.notBeforeLocalDay); // Validity end addAttributeFromCert('validityend', cert.validity.notAfterLocalDay); - + //Now to populate the fields that correspond to the issuer. var issuerCommonname, issuerOrg, issuerOrgUnit; issuerCommonname = cert.issuerCommonName; @@ -287,7 +281,7 @@ function getCurrentCert() && document.getElementById('prettyprint_tab').selected) { /* if the user manually selected a cert on the Details tab, then take that one */ - realIndex = tree.currentIndex; + realIndex = tree.currentIndex; } else { /* otherwise, take the one at the bottom of the chain (i.e. the one of the end-entity, unless we're displaying diff --git a/security/manager/ssl/public/moz.build b/security/manager/ssl/public/moz.build index f3fd5dacf19e..794beae15aa4 100644 --- a/security/manager/ssl/public/moz.build +++ b/security/manager/ssl/public/moz.build @@ -39,10 +39,7 @@ XPIDL_SOURCES += [ 'nsITokenPasswordDialogs.idl', 'nsIUserCertPicker.idl', 'nsIX509Cert.idl', - 'nsIX509Cert2.idl', - 'nsIX509Cert3.idl', 'nsIX509CertDB.idl', - 'nsIX509CertDB2.idl', 'nsIX509CertList.idl', 'nsIX509CertValidity.idl', ] diff --git a/security/manager/ssl/public/nsISSLStatus.idl b/security/manager/ssl/public/nsISSLStatus.idl index 6ddd8b221a4d..b5d51a267082 100644 --- a/security/manager/ssl/public/nsISSLStatus.idl +++ b/security/manager/ssl/public/nsISSLStatus.idl @@ -23,7 +23,7 @@ interface nsISSLStatus : nsISupports { * "unstrusted because missing or untrusted issuer" * and * "untrusted because self signed" - * query nsIX509Cert3::isSelfSigned + * query nsIX509Cert::isSelfSigned */ readonly attribute boolean isUntrusted; diff --git a/security/manager/ssl/public/nsIX509Cert.idl b/security/manager/ssl/public/nsIX509Cert.idl index 6617d5aab66c..9e9dce79ff58 100644 --- a/security/manager/ssl/public/nsIX509Cert.idl +++ b/security/manager/ssl/public/nsIX509Cert.idl @@ -9,11 +9,18 @@ interface nsIArray; interface nsIX509CertValidity; interface nsIASN1Object; +interface nsICertVerificationListener; + +%{ C++ + /* forward declaration */ + typedef struct CERTCertificateStr CERTCertificate; +%} +[ptr] native CERTCertificatePtr(CERTCertificate); /** * This represents a X.509 certificate. */ -[scriptable, uuid(891d2009-b9ba-4a0d-bebe-6b3a30e33191)] +[scriptable, uuid(f8ed8364-ced9-4c6e-86ba-48af53c393e6)] interface nsIX509Cert : nsISupports { /** @@ -33,7 +40,7 @@ interface nsIX509Cert : nsISupports { * @param length The number of strings in the returned array. * @return An array of email addresses. */ - void getEmailAddresses(out unsigned long length, + void getEmailAddresses(out unsigned long length, [retval, array, size_is(length)] out wstring addresses); /** @@ -42,7 +49,7 @@ interface nsIX509Cert : nsISupports { * The behaviour for non ASCII characters is undefined. * * @param aEmailAddress The address to search for. - * + * * @return True if the address is contained in the certificate. */ boolean containsEmailAddress(in AString aEmailAddress); @@ -138,6 +145,18 @@ interface nsIX509Cert : nsISupports { const unsigned long USER_CERT = 1 << 1; const unsigned long EMAIL_CERT = 1 << 2; const unsigned long SERVER_CERT = 1 << 3; + const unsigned long ANY_CERT = 0xffff; + + /** + * Type of this certificate + */ + readonly attribute unsigned long certType; + + /** + * True if the certificate is self-signed. CA issued + * certificates are always self-signed. + */ + readonly attribute boolean isSelfSigned; /** * Constants for certificate verification results. @@ -152,7 +171,7 @@ interface nsIX509Cert : nsISupports { const unsigned long INVALID_CA = 1 << 6; const unsigned long USAGE_NOT_ALLOWED = 1 << 7; const unsigned long SIGNATURE_ALGORITHM_DISABLED = 1 << 8; - + /** * Constants that describe the certified usages of a certificate. * @@ -172,7 +191,14 @@ interface nsIX509Cert : nsISupports { const unsigned long CERT_USAGE_AnyCA = 11; /** - * Obtain a list of certificates that contains this certificate + * Constants for specifying the chain mode when exporting a certificate + */ + const unsigned long CMS_CHAIN_MODE_CertOnly = 1; + const unsigned long CMS_CHAIN_MODE_CertChain = 2; + const unsigned long CMS_CHAIN_MODE_CertChainWithRoot = 3; + + /** + * Obtain a list of certificates that contains this certificate * and the issuing certificates of all involved issuers, * up to the root issuer. * @@ -192,9 +218,17 @@ interface nsIX509Cert : nsISupports { */ void getUsagesArray(in boolean localOnly, out uint32_t verified, - out uint32_t count, + out uint32_t count, [array, size_is(count)] out wstring usages); + /** + * Async version of nsIX509Cert::getUsagesArray() + * + * Will not block, will request results asynchronously, + * availability of results will be notified on the main thread. + */ + void requestUsagesArrayAsync(in nsICertVerificationListener cvl); + /** * Obtain a single comma separated human readable string describing * the certificate's certified usages. @@ -224,7 +258,7 @@ interface nsIX509Cert : nsISupports { [retval, array, size_is(length)] out octet data); /** - * Test whether two certificate instances represent the + * Test whether two certificate instances represent the * same certificate. * * @return Whether the certificates are equal @@ -236,4 +270,81 @@ interface nsIX509Cert : nsISupports { * digest. */ readonly attribute ACString sha256SubjectPublicKeyInfoDigest; + + /** + * Obtain the certificate wrapped in a PKCS#7 SignedData structure, + * with or without the certificate chain + * + * @param chainMode Whether to include the chain (with or without the root), + see CMS_CHAIN_MODE constants. + * @param length The number of bytes of the PKCS#7 data. + * @param data The bytes representing the PKCS#7 wrapped certificate. + */ + void exportAsCMS(in unsigned long chainMode, + out unsigned long length, + [retval, array, size_is(length)] out octet data); + + /** + * Retrieves the NSS certificate object wrapped by this interface + */ + [notxpcom, noscript] CERTCertificatePtr getCert(); + + /** + * Human readable names identifying all hardware or + * software tokens the certificate is stored on. + * + * @param length On success, the number of entries in the returned array. + * @return On success, an array containing the names of all tokens + * the certificate is stored on (may be empty). + * On failure the function throws/returns an error. + */ + void getAllTokenNames(out unsigned long length, + [retval, array, size_is(length)] out wstring + tokenNames); + + /** + * Either delete the certificate from all cert databases, + * or mark it as untrusted. + */ + void markForPermDeletion(); +}; + +[scriptable, uuid(2fd0a785-9f2d-4327-8871-8c3e0783891d)] +interface nsICertVerificationResult : nsISupports { + + /** + * This interface reflects a container of + * verification results. Call will not block. + * + * Obtain an array of human readable strings describing + * the certificate's certified usages. + * + * Mirrors the results produced by + * nsIX509Cert::getUsagesArray() + * + * As of today, this function is a one-shot object, + * only the first call will succeed. + * This allows an optimization in the implementation, + * ownership of result data will be transfered to caller. + * + * @param cert The certificate that was verified. + * @param verified The certificate verification result, + * see constants in nsIX509Cert. + * @param count The number of human readable usages returned. + * @param usages The array of human readable usages. + */ + void getUsagesArrayResult(out uint32_t verified, + out uint32_t count, + [array, size_is(count)] out wstring usages); +}; + +[scriptable, uuid(6684bce9-50db-48e1-81b7-98102bf81357)] +interface nsICertVerificationListener : nsISupports { + + /** + * Notify that results are ready, that have been requested + * using nsIX509Cert::requestUsagesArrayAsync() + */ + void notify(in nsIX509Cert verifiedCert, + in nsICertVerificationResult result); }; diff --git a/security/manager/ssl/public/nsIX509Cert2.idl b/security/manager/ssl/public/nsIX509Cert2.idl deleted file mode 100644 index 090fc3fa3484..000000000000 --- a/security/manager/ssl/public/nsIX509Cert2.idl +++ /dev/null @@ -1,30 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsIX509Cert.idl" - -interface nsIArray; -interface nsIASN1Object; - -%{ C++ - /* forward declaration */ - typedef struct CERTCertificateStr CERTCertificate; -%} -[ptr] native CERTCertificatePtr(CERTCertificate); - -/** - * This represents additional interfaces to X.509 certificates - */ -[scriptable, uuid(5b62c61c-f898-4dab-8ace-51109bb459b4)] -interface nsIX509Cert2 : nsIX509Cert { - /** - * Additional constants to classify the type of a certificate. - */ - const unsigned long ANY_CERT = 0xffff; - readonly attribute unsigned long certType; - void markForPermDeletion(); - [notxpcom, noscript] CERTCertificatePtr getCert(); -}; diff --git a/security/manager/ssl/public/nsIX509Cert3.idl b/security/manager/ssl/public/nsIX509Cert3.idl deleted file mode 100644 index f89e01e81aa2..000000000000 --- a/security/manager/ssl/public/nsIX509Cert3.idl +++ /dev/null @@ -1,98 +0,0 @@ -/* 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 "nsIX509Cert2.idl" - -interface nsICertVerificationListener; - -/** - * Extending nsIX509Cert - */ -[scriptable, uuid(399004d8-b8c7-4eb9-8362-d99f4c0161fd)] -interface nsIX509Cert3 : nsIX509Cert2 { - - /** - * Constants for specifying the chain mode when exporting a certificate - */ - const unsigned long CMS_CHAIN_MODE_CertOnly = 1; - const unsigned long CMS_CHAIN_MODE_CertChain = 2; - const unsigned long CMS_CHAIN_MODE_CertChainWithRoot = 3; - - /** - * Async version of nsIX509Cert::getUsagesArray() - * - * Will not block, will request results asynchronously, - * availability of results will be notified on the main thread. - */ - void requestUsagesArrayAsync(in nsICertVerificationListener cvl); - - /** - * Obtain the certificate wrapped in a PKCS#7 SignedData structure, - * with or without the certificate chain - * - * @param chainMode Whether to include the chain (with or without the root), - see CMS_CHAIN_MODE constants. - * @param length The number of bytes of the PKCS#7 data. - * @param data The bytes representing the PKCS#7 wrapped certificate. - */ - void exportAsCMS(in unsigned long chainMode, - out unsigned long length, - [retval, array, size_is(length)] out octet data); - - readonly attribute boolean isSelfSigned; - - /** - * Human readable names identifying all hardware or - * software tokens the certificate is stored on. - * - * @param length On success, the number of entries in the returned array. - * @return On success, an array containing the names of all tokens - * the certificate is stored on (may be empty). - * On failure the function throws/returns an error. - */ - void getAllTokenNames(out unsigned long length, - [retval, array, size_is(length)] out wstring - tokenNames); -}; - -[scriptable, uuid(2fd0a785-9f2d-4327-8871-8c3e0783891d)] -interface nsICertVerificationResult : nsISupports { - - /** - * This interface reflects a container of - * verification results. Call will not block. - * - * Obtain an array of human readable strings describing - * the certificate's certified usages. - * - * Mirrors the results produced by - * nsIX509Cert::getUsagesArray() - * - * As of today, this function is a one-shot object, - * only the first call will succeed. - * This allows an optimization in the implementation, - * ownership of result data will be transfered to caller. - * - * @param cert The certificate that was verified. - * @param verified The certificate verification result, - * see constants in nsIX509Cert. - * @param count The number of human readable usages returned. - * @param usages The array of human readable usages. - */ - void getUsagesArrayResult(out uint32_t verified, - out uint32_t count, - [array, size_is(count)] out wstring usages); -}; - - -[scriptable, uuid(6684bce9-50db-48e1-81b7-98102bf81357)] -interface nsICertVerificationListener : nsISupports { - - /** - * Notify that results are ready, that have been requested - * using nsIX509Cert3::requestUsagesArrayAsync() - */ - void notify(in nsIX509Cert3 verifiedCert, - in nsICertVerificationResult result); -}; diff --git a/security/manager/ssl/public/nsIX509CertDB.idl b/security/manager/ssl/public/nsIX509CertDB.idl index 1fbf2a33129f..cbc782214798 100644 --- a/security/manager/ssl/public/nsIX509CertDB.idl +++ b/security/manager/ssl/public/nsIX509CertDB.idl @@ -8,7 +8,6 @@ interface nsIArray; interface nsIX509Cert; -interface nsIX509Cert3; interface nsIFile; interface nsIInterfaceRequestor; interface nsIZipReader; @@ -21,16 +20,16 @@ interface nsIX509CertList; typedef uint32_t AppTrustedRoot; -[scriptable, function, uuid(0927baea-622d-4e41-a76d-255af426e7fb)] +[scriptable, function, uuid(5984db62-d0e5-4671-a082-799cf7271e24)] interface nsIOpenSignedAppFileCallback : nsISupports { void openSignedAppFileFinished(in nsresult rv, in nsIZipReader aZipReader, - in nsIX509Cert3 aSignerCert); + in nsIX509Cert aSignerCert); }; /** - * This represents a service to access and manipulate + * This represents a service to access and manipulate * X.509 certificates stored in a database. */ [scriptable, uuid(7446a5b1-84ca-491f-a2fe-0bc60a71ffa5)] @@ -49,12 +48,12 @@ interface nsIX509CertDB : nsISupports { * Given a nickname and optionally a token, * locate the matching certificate. * - * @param aToken Optionally limits the scope of + * @param aToken Optionally limits the scope of * this function to a token device. * Can be null to mean any token. * @param aNickname The nickname to be used as the key * to find a certificate. - * + * * @return The matching certificate if found. */ nsIX509Cert findCertByNickname(in nsISupports aToken, @@ -67,7 +66,7 @@ interface nsIX509CertDB : nsISupports { * * @param aDBkey Database internal key, as obtained using * attribute dbkey in nsIX509Cert. - * @param aToken Optionally limits the scope of + * @param aToken Optionally limits the scope of * this function to a token device. * Can be null to mean any token. */ @@ -79,7 +78,7 @@ interface nsIX509CertDB : nsISupports { * user, ca, or server cert - the nickname * email cert - the email address * - * @param aToken Optionally limits the scope of + * @param aToken Optionally limits the scope of * this function to a token device. * Can be null to mean any token. * @param aType Type of certificate to obtain @@ -87,7 +86,7 @@ interface nsIX509CertDB : nsISupports { * @param count The number of nicknames in the returned array * @param certNameList The returned array of certificate nicknames. */ - void findCertNicknames(in nsISupports aToken, + void findCertNicknames(in nsISupports aToken, in unsigned long aType, out unsigned long count, [array, size_is(count)] out wstring certNameList); @@ -97,7 +96,7 @@ interface nsIX509CertDB : nsISupports { * * @param aNickname The nickname to be used as the key * to find the certificate. - * + * * @return The matching certificate if found. */ nsIX509Cert findEmailEncryptionCert(in AString aNickname); @@ -107,7 +106,7 @@ interface nsIX509CertDB : nsISupports { * * @param aNickname The nickname to be used as the key * to find the certificate. - * + * * @return The matching certificate if found. */ nsIX509Cert findEmailSigningCert(in AString aNickname); @@ -115,12 +114,12 @@ interface nsIX509CertDB : nsISupports { /** * Find a certificate by email address. * - * @param aToken Optionally limits the scope of + * @param aToken Optionally limits the scope of * this function to a token device. * Can be null to mean any token. * @param aEmailAddress The email address to be used as the key * to find the certificate. - * + * * @return The matching certificate if found. */ nsIX509Cert findCertByEmailAddress(in nsISupports aToken, @@ -164,7 +163,7 @@ interface nsIX509CertDB : nsISupports { in nsIInterfaceRequestor ctx); /** - * Import a personal certificate into the database, assuming + * Import a personal certificate into the database, assuming * the database already contains the private key for this certificate. * * @param data The raw data to be imported @@ -184,7 +183,7 @@ interface nsIX509CertDB : nsISupports { /** * Modify the trust that is stored and associated to a certificate within - * a database. Separate trust is stored for + * a database. Separate trust is stored for * One call manipulates the trust for one trust type only. * See the trust type constants defined within this interface. * @@ -203,14 +202,14 @@ interface nsIX509CertDB : nsISupports { * characters, indicating SSL, Email, and Obj signing * trust. */ - void setCertTrustFromString(in nsIX509Cert3 cert, in string trustString); + void setCertTrustFromString(in nsIX509Cert cert, in string trustString); /** * Query whether a certificate is trusted for a particular use. * * @param cert Obtain the stored trust of this certificate. * @param certType The type of the certificate. See nsIX509Cert. - * @param trustType A single bit from the usages constants defined + * @param trustType A single bit from the usages constants defined * within this interface. * * @return Returns true if the certificate is trusted for the given use. @@ -222,7 +221,7 @@ interface nsIX509CertDB : nsISupports { /** * Import certificate(s) from file * - * @param aToken Optionally limits the scope of + * @param aToken Optionally limits the scope of * this function to a token device. * Can be null to mean any token. * @param aFile Identifies a file that contains the certificate @@ -237,7 +236,7 @@ interface nsIX509CertDB : nsISupports { /** * Import a PKCS#12 file containing cert(s) and key(s) into the database. * - * @param aToken Optionally limits the scope of + * @param aToken Optionally limits the scope of * this function to a token device. * Can be null to mean any token. * @param aFile Identifies a file that contains the data @@ -249,7 +248,7 @@ interface nsIX509CertDB : nsISupports { /** * Export a set of certs and keys from the database to a PKCS#12 file. * - * @param aToken Optionally limits the scope of + * @param aToken Optionally limits the scope of * this function to a token device. * Can be null to mean any token. * @param aFile Identifies a file that will be filled with the data @@ -316,7 +315,7 @@ interface nsIX509CertDB : nsISupports { in nsIFile aJarFile, in nsIOpenSignedAppFileCallback callback); - /* + /* * Add a cert to a cert DB from a binary string. * * @param certDER The raw DER encoding of a certificate. @@ -361,4 +360,20 @@ interface nsIX509CertDB : nsISupports { // Clears the OCSP cache for the current certificate verification // implementation. void clearOCSPCache(); + + /* + * Add a cert to a cert DB from a base64 encoded string. + * + * @param base64 The raw representation of a certificate, + * encoded as Base 64. + * @param aTrust decoded by CERT_DecodeTrustString. 3 comma separated characters, + * indicating SSL, Email, and Obj signing trust + * @param aName name of the cert for display purposes. + */ + void addCertFromBase64(in string base64, in string aTrust, in string aName); + + /* + * Get all the known certs in the database + */ + nsIX509CertList getCerts(); }; diff --git a/security/manager/ssl/public/nsIX509CertDB2.idl b/security/manager/ssl/public/nsIX509CertDB2.idl deleted file mode 100644 index 3b1db35ca5f5..000000000000 --- a/security/manager/ssl/public/nsIX509CertDB2.idl +++ /dev/null @@ -1,36 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsISupports.idl" - -interface nsIX509CertList; - -/** - * This represents a service to access and manipulate - * X.509 certificates stored in a database through methods - * not in nsIX509CertDB, which is frozen - * - */ -[scriptable, uuid(e0df4784-6560-45bf-b1b7-86076a0e8381)] -interface nsIX509CertDB2 : nsISupports { - - /* - * Add a cert to a cert DB from a base64 encoded string. - * - * @param base64 The raw representation of a certificate, - * encoded as Base 64. - * @param aTrust decoded by CERT_DecodeTrustString. 3 comma separated characters, - * indicating SSL, Email, and Obj signing trust - * @param aName name of the cert for display purposes. - */ - void addCertFromBase64(in string base64, in string aTrust, in string aName); - - /* - * Get all the known certs in the database - */ - nsIX509CertList getCerts(); -}; - diff --git a/security/manager/ssl/src/SSLServerCertVerification.cpp b/security/manager/ssl/src/SSLServerCertVerification.cpp index abf2f510c870..345206d7c1d4 100644 --- a/security/manager/ssl/src/SSLServerCertVerification.cpp +++ b/security/manager/ssl/src/SSLServerCertVerification.cpp @@ -689,7 +689,6 @@ BlockServerCertChangeForSpdy(nsNSSSocketInfo* infoObject, // Get the existing cert. If there isn't one, then there is // no cert change to worry about. nsCOMPtr cert; - nsCOMPtr cert2; RefPtr status(infoObject->SSLStatus()); if (!status) { @@ -700,10 +699,9 @@ BlockServerCertChangeForSpdy(nsNSSSocketInfo* infoObject, } status->GetServerCert(getter_AddRefs(cert)); - cert2 = do_QueryInterface(cert); - if (!cert2) { + if (!cert) { NS_NOTREACHED("every nsSSLStatus must have a cert" - "that implements nsIX509Cert2"); + "that implements nsIX509Cert"); PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0); return SECFailure; } @@ -715,9 +713,9 @@ BlockServerCertChangeForSpdy(nsNSSSocketInfo* infoObject, "GetNegotiatedNPN() failed during renegotiation"); if (NS_SUCCEEDED(rv) && !StringBeginsWith(negotiatedNPN, - NS_LITERAL_CSTRING("spdy/"))) + NS_LITERAL_CSTRING("spdy/"))) { return SECSuccess; - + } // If GetNegotiatedNPN() failed we will assume spdy for safety's safe if (NS_FAILED(rv)) { PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, @@ -726,11 +724,12 @@ BlockServerCertChangeForSpdy(nsNSSSocketInfo* infoObject, } // Check to see if the cert has actually changed - ScopedCERTCertificate c(cert2->GetCert()); + ScopedCERTCertificate c(cert->GetCert()); NS_ASSERTION(c, "very bad and hopefully impossible state"); bool sameCert = CERT_CompareCerts(c, serverCert); - if (sameCert) + if (sameCert) { return SECSuccess; + } // Report an error - changed cert is confirmed PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, diff --git a/security/manager/ssl/src/TransportSecurityInfo.cpp b/security/manager/ssl/src/TransportSecurityInfo.cpp index 6f1bb0ec59c0..d1e2a982e069 100644 --- a/security/manager/ssl/src/TransportSecurityInfo.cpp +++ b/security/manager/ssl/src/TransportSecurityInfo.cpp @@ -535,13 +535,9 @@ AppendErrorTextUntrusted(PRErrorCode errTrust, nsString &returnedMessage) { const char *errorID = nullptr; - nsCOMPtr cert3 = do_QueryInterface(ix509); - if (cert3) { - bool isSelfSigned; - if (NS_SUCCEEDED(cert3->GetIsSelfSigned(&isSelfSigned)) - && isSelfSigned) { - errorID = "certErrorTrust_SelfSigned"; - } + bool isSelfSigned; + if (NS_SUCCEEDED(ix509->GetIsSelfSigned(&isSelfSigned)) && isSelfSigned) { + errorID = "certErrorTrust_SelfSigned"; } if (!errorID) { @@ -690,11 +686,7 @@ AppendErrorTextMismatch(const nsString &host, const char16_t *params[1]; nsresult rv; - mozilla::pkix::ScopedCERTCertificate nssCert; - - nsCOMPtr cert2 = do_QueryInterface(ix509, &rv); - if (cert2) - nssCert = cert2->GetCert(); + mozilla::pkix::ScopedCERTCertificate nssCert(ix509->GetCert()); if (!nssCert) { // We are unable to extract the valid names, say "not valid for name". diff --git a/security/manager/ssl/src/nsCertOverrideService.cpp b/security/manager/ssl/src/nsCertOverrideService.cpp index a302a2003320..b9dd9bcd1d44 100644 --- a/security/manager/ssl/src/nsCertOverrideService.cpp +++ b/security/manager/ssl/src/nsCertOverrideService.cpp @@ -390,14 +390,11 @@ GetCertFingerprintByOidTag(nsIX509Cert *aCert, SECOidTag aOidTag, nsCString &fp) { - nsCOMPtr cert2 = do_QueryInterface(aCert); - if (!cert2) - return NS_ERROR_FAILURE; - mozilla::pkix::ScopedCERTCertificate nsscert(cert2->GetCert()); - if (!nsscert) + mozilla::pkix::ScopedCERTCertificate nsscert(aCert->GetCert()); + if (!nsscert) { return NS_ERROR_FAILURE; - + } return GetCertFingerprintByOidTag(nsscert.get(), aOidTag, fp); } @@ -425,24 +422,23 @@ GetCertFingerprintByDottedOidString(CERTCertificate* nsscert, static nsresult GetCertFingerprintByDottedOidString(nsIX509Cert *aCert, - const nsCString &dottedOid, + const nsCString &dottedOid, nsCString &fp) { - nsCOMPtr cert2 = do_QueryInterface(aCert); - if (!cert2) - return NS_ERROR_FAILURE; - mozilla::pkix::ScopedCERTCertificate nsscert(cert2->GetCert()); - if (!nsscert) + mozilla::pkix::ScopedCERTCertificate nsscert(aCert->GetCert()); + if (!nsscert) { return NS_ERROR_FAILURE; + } return GetCertFingerprintByDottedOidString(nsscert.get(), dottedOid, fp); } NS_IMETHODIMP -nsCertOverrideService::RememberValidityOverride(const nsACString & aHostName, int32_t aPort, - nsIX509Cert *aCert, - uint32_t aOverrideBits, +nsCertOverrideService::RememberValidityOverride(const nsACString& aHostName, + int32_t aPort, + nsIX509Cert* aCert, + uint32_t aOverrideBits, bool aTemporary) { NS_ENSURE_ARG_POINTER(aCert); @@ -451,13 +447,10 @@ nsCertOverrideService::RememberValidityOverride(const nsACString & aHostName, in if (aPort < -1) return NS_ERROR_INVALID_ARG; - nsCOMPtr cert2 = do_QueryInterface(aCert); - if (!cert2) - return NS_ERROR_FAILURE; - - mozilla::pkix::ScopedCERTCertificate nsscert(cert2->GetCert()); - if (!nsscert) + mozilla::pkix::ScopedCERTCertificate nsscert(aCert->GetCert()); + if (!nsscert) { return NS_ERROR_FAILURE; + } char* nickname = DefaultServerNicknameForCert(nsscert.get()); if (!aTemporary && nickname && *nickname) diff --git a/security/manager/ssl/src/nsCertTree.cpp b/security/manager/ssl/src/nsCertTree.cpp index baf7433399a7..d81f257aca8f 100644 --- a/security/manager/ssl/src/nsCertTree.cpp +++ b/security/manager/ssl/src/nsCertTree.cpp @@ -330,7 +330,7 @@ nsCertTree::nsCertCompareFunc nsCertTree::GetCompareFuncFromCertType(uint32_t aType) { switch (aType) { - case nsIX509Cert2::ANY_CERT: + case nsIX509Cert::ANY_CERT: case nsIX509Cert::USER_CERT: return CmpUserCert; case nsIX509Cert::CA_CERT: @@ -477,7 +477,7 @@ nsCertTree::GetCertsByTypeFromCertList(CERTCertList *aCertList, !CERT_LIST_END(node, aCertList); node = CERT_LIST_NEXT(node)) { - bool wantThisCert = (aWantedType == nsIX509Cert2::ANY_CERT); + bool wantThisCert = (aWantedType == nsIX509Cert::ANY_CERT); bool wantThisCertIfNoOverrides = false; bool wantThisCertIfHaveOverrides = false; bool addOverrides = false; @@ -809,12 +809,7 @@ nsCertTree::DeleteEntryObject(uint32_t index) // although there are still overrides stored, // so, we keep the cert, but remove the trust - mozilla::pkix::ScopedCERTCertificate nsscert; - - nsCOMPtr cert2 = do_QueryInterface(cert); - if (cert2) { - nsscert = cert2->GetCert(); - } + mozilla::pkix::ScopedCERTCertificate nsscert(cert->GetCert()); if (nsscert) { CERTCertTrust trust; @@ -1235,12 +1230,8 @@ nsCertTree::GetCellText(int32_t row, nsITreeColumn* col, (certdi->mIsTemporary) ? "CertExceptionTemporary" : "CertExceptionPermanent"; rv = mNSSComponent->GetPIPNSSBundleString(stringID, _retval); } else if (NS_LITERAL_STRING("typecol").Equals(colID) && cert) { - nsCOMPtr pipCert = do_QueryInterface(cert); uint32_t type = nsIX509Cert::UNKNOWN_CERT; - - if (pipCert) { - rv = pipCert->GetCertType(&type); - } + rv = cert->GetCertType(&type); switch (type) { case nsIX509Cert::USER_CERT: diff --git a/security/manager/ssl/src/nsCertVerificationThread.cpp b/security/manager/ssl/src/nsCertVerificationThread.cpp index 819dac0fd89e..1698b9be1d93 100644 --- a/security/manager/ssl/src/nsCertVerificationThread.cpp +++ b/security/manager/ssl/src/nsCertVerificationThread.cpp @@ -17,7 +17,7 @@ class DispatchCertVerificationResult : public nsRunnable { public: DispatchCertVerificationResult(const nsMainThreadPtrHandle& aListener, - nsIX509Cert3* aCert, + nsIX509Cert* aCert, nsICertVerificationResult* aResult) : mListener(aListener) , mCert(aCert) @@ -31,7 +31,7 @@ public: private: nsMainThreadPtrHandle mListener; - nsCOMPtr mCert; + nsCOMPtr mCert; nsCOMPtr mResult; }; } // anonymous namespace @@ -63,9 +63,8 @@ void nsCertVerificationJob::Run() ires = vres; } - - nsCOMPtr c3 = do_QueryInterface(mCert); - nsCOMPtr r = new DispatchCertVerificationResult(mListener, c3, ires); + + nsCOMPtr r = new DispatchCertVerificationResult(mListener, mCert, ires); NS_DispatchToMainThread(r); } diff --git a/security/manager/ssl/src/nsNSSCertificate.cpp b/security/manager/ssl/src/nsNSSCertificate.cpp index a776f0e2d32e..2c66e1bc4604 100644 --- a/security/manager/ssl/src/nsNSSCertificate.cpp +++ b/security/manager/ssl/src/nsNSSCertificate.cpp @@ -19,7 +19,6 @@ #include "nsPKCS12Blob.h" #include "nsPK11TokenDB.h" #include "nsIX509Cert.h" -#include "nsIX509Cert3.h" #include "nsNSSASN1Object.h" #include "nsString.h" #include "nsXPIDLString.h" @@ -68,8 +67,6 @@ NSSCleanupAutoPtrClass_WithParam(PLArenaPool, PORT_FreeArena, FalseParam, false) NS_IMPL_ISUPPORTS(nsNSSCertificate, nsIX509Cert, - nsIX509Cert2, - nsIX509Cert3, nsIIdentityInfo, nsISerializable, nsIClassInfo) @@ -1141,9 +1138,9 @@ nsNSSCertificate::ExportAsCMS(uint32_t chainMode, return NS_ERROR_FAILURE; switch (chainMode) { - case nsIX509Cert3::CMS_CHAIN_MODE_CertOnly: - case nsIX509Cert3::CMS_CHAIN_MODE_CertChain: - case nsIX509Cert3::CMS_CHAIN_MODE_CertChainWithRoot: + case nsIX509Cert::CMS_CHAIN_MODE_CertOnly: + case nsIX509Cert::CMS_CHAIN_MODE_CertChain: + case nsIX509Cert::CMS_CHAIN_MODE_CertChainWithRoot: break; default: return NS_ERROR_INVALID_ARG; @@ -1178,15 +1175,15 @@ nsNSSCertificate::ExportAsCMS(uint32_t chainMode, // Since CERT_CertChainFromCert() also includes the certificate itself, // we have to start at the issuing cert (to avoid duplicate certs // in the SignedData). - if (chainMode == nsIX509Cert3::CMS_CHAIN_MODE_CertChain || - chainMode == nsIX509Cert3::CMS_CHAIN_MODE_CertChainWithRoot) { + if (chainMode == nsIX509Cert::CMS_CHAIN_MODE_CertChain || + chainMode == nsIX509Cert::CMS_CHAIN_MODE_CertChainWithRoot) { ScopedCERTCertificate issuerCert( CERT_FindCertIssuer(mCert.get(), PR_Now(), certUsageAnyCA)); // the issuerCert of a self signed root is the cert itself, // so make sure we're not adding duplicates, again if (issuerCert && issuerCert != mCert.get()) { bool includeRoot = - (chainMode == nsIX509Cert3::CMS_CHAIN_MODE_CertChainWithRoot); + (chainMode == nsIX509Cert::CMS_CHAIN_MODE_CertChainWithRoot); ScopedCERTCertificateList certChain( CERT_CertChainFromCert(issuerCert, certUsageAnyCA, includeRoot)); if (certChain) { @@ -1377,11 +1374,7 @@ nsNSSCertificate::Equals(nsIX509Cert* other, bool* result) NS_ENSURE_ARG(other); NS_ENSURE_ARG(result); - nsCOMPtr other2 = do_QueryInterface(other); - if (!other2) - return NS_ERROR_FAILURE; - - ScopedCERTCertificate cert(other2->GetCert()); + ScopedCERTCertificate cert(other->GetCert()); *result = (mCert.get() == cert.get()); return NS_OK; } @@ -1552,10 +1545,7 @@ nsNSSCertList::AddCert(nsIX509Cert* aCert) if (isAlreadyShutDown()) { return NS_ERROR_NOT_AVAILABLE; } - nsCOMPtr nssCert = do_QueryInterface(aCert); - CERTCertificate* cert; - - cert = nssCert->GetCert(); + CERTCertificate* cert = aCert->GetCert(); if (!cert) { NS_ERROR("Somehow got nullptr for mCertificate in nsNSSCertificate."); return NS_ERROR_FAILURE; @@ -1577,8 +1567,7 @@ nsNSSCertList::DeleteCert(nsIX509Cert* aCert) if (isAlreadyShutDown()) { return NS_ERROR_NOT_AVAILABLE; } - nsCOMPtr nssCert = do_QueryInterface(aCert); - CERTCertificate* cert = nssCert->GetCert(); + CERTCertificate* cert = aCert->GetCert(); CERTCertListNode* node; if (!cert) { @@ -1605,8 +1594,9 @@ CERTCertList* nsNSSCertList::DupCertList(CERTCertList* aCertList, const nsNSSShutDownPreventionLock& /*proofOfLock*/) { - if (!aCertList) + if (!aCertList) { return nullptr; + } CERTCertList* newList = CERT_NewCertList(); diff --git a/security/manager/ssl/src/nsNSSCertificate.h b/security/manager/ssl/src/nsNSSCertificate.h index a8d9f50c4086..5e03b6ad0d13 100644 --- a/security/manager/ssl/src/nsNSSCertificate.h +++ b/security/manager/ssl/src/nsNSSCertificate.h @@ -7,8 +7,6 @@ #define _NS_NSSCERTIFICATE_H_ #include "nsIX509Cert.h" -#include "nsIX509Cert2.h" -#include "nsIX509Cert3.h" #include "nsIX509CertDB.h" #include "nsIX509CertList.h" #include "nsIASN1Object.h" @@ -25,7 +23,7 @@ class nsAutoString; class nsINSSComponent; class nsIASN1Sequence; -class nsNSSCertificate : public nsIX509Cert3, +class nsNSSCertificate : public nsIX509Cert, public nsIIdentityInfo, public nsISerializable, public nsIClassInfo, @@ -34,8 +32,6 @@ class nsNSSCertificate : public nsIX509Cert3, public: NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSIX509CERT - NS_DECL_NSIX509CERT2 - NS_DECL_NSIX509CERT3 NS_DECL_NSIIDENTITYINFO NS_DECL_NSISERIALIZABLE NS_DECL_NSICLASSINFO diff --git a/security/manager/ssl/src/nsNSSCertificateDB.cpp b/security/manager/ssl/src/nsNSSCertificateDB.cpp index a4f048976cf2..0d3a44015f58 100644 --- a/security/manager/ssl/src/nsNSSCertificateDB.cpp +++ b/security/manager/ssl/src/nsNSSCertificateDB.cpp @@ -82,7 +82,7 @@ attemptToLogInWithDefaultPassword() return NS_OK; } -NS_IMPL_ISUPPORTS(nsNSSCertificateDB, nsIX509CertDB, nsIX509CertDB2) +NS_IMPL_ISUPPORTS(nsNSSCertificateDB, nsIX509CertDB) nsNSSCertificateDB::nsNSSCertificateDB() : mBadCertsLock("nsNSSCertificateDB::mBadCertsLock") @@ -954,14 +954,15 @@ nsNSSCertificateDB::DeleteCertificate(nsIX509Cert *aCert) if (isAlreadyShutDown()) { return NS_ERROR_NOT_AVAILABLE; } - nsCOMPtr nssCert = do_QueryInterface(aCert); - mozilla::pkix::ScopedCERTCertificate cert(nssCert->GetCert()); - if (!cert) return NS_ERROR_FAILURE; + mozilla::pkix::ScopedCERTCertificate cert(aCert->GetCert()); + if (!cert) { + return NS_ERROR_FAILURE; + } SECStatus srv = SECSuccess; uint32_t certType; - nssCert->GetCertType(&certType); - if (NS_FAILED(nssCert->MarkForPermDeletion())) + aCert->GetCertType(&certType); + if (NS_FAILED(aCert->MarkForPermDeletion())) { return NS_ERROR_FAILURE; } @@ -998,11 +999,7 @@ nsNSSCertificateDB::SetCertTrust(nsIX509Cert *cert, } nsNSSCertTrust trust; nsresult rv; - nsCOMPtr pipCert = do_QueryInterface(cert, &rv); - if (!pipCert) { - return rv; - } - mozilla::pkix::ScopedCERTCertificate nsscert(pipCert->GetCert()); + mozilla::pkix::ScopedCERTCertificate nsscert(cert->GetCert()); rv = attemptToLogInWithDefaultPassword(); if (NS_WARN_IF(rv != NS_OK)) { @@ -1054,8 +1051,7 @@ nsNSSCertificateDB::IsCertTrusted(nsIX509Cert *cert, return NS_ERROR_NOT_AVAILABLE; } SECStatus srv; - nsCOMPtr pipCert = do_QueryInterface(cert); - mozilla::pkix::ScopedCERTCertificate nsscert(pipCert->GetCert()); + mozilla::pkix::ScopedCERTCertificate nsscert(cert->GetCert()); CERTCertTrust nsstrust; srv = CERT_GetCertTrust(nsscert.get(), &nsstrust); if (srv != SECSuccess) @@ -1284,7 +1280,8 @@ finish: /* nsIX509Cert getDefaultEmailEncryptionCert (); */ NS_IMETHODIMP -nsNSSCertificateDB::FindEmailEncryptionCert(const nsAString &aNickname, nsIX509Cert **_retval) +nsNSSCertificateDB::FindEmailEncryptionCert(const nsAString& aNickname, + nsIX509Cert** _retval) { NS_ENSURE_ARG_POINTER(_retval); *_retval = nullptr; @@ -1320,7 +1317,8 @@ nsNSSCertificateDB::FindEmailEncryptionCert(const nsAString &aNickname, nsIX509C /* nsIX509Cert getDefaultEmailSigningCert (); */ NS_IMETHODIMP -nsNSSCertificateDB::FindEmailSigningCert(const nsAString &aNickname, nsIX509Cert **_retval) +nsNSSCertificateDB::FindEmailSigningCert(const nsAString& aNickname, + nsIX509Cert** _retval) { NS_ENSURE_ARG_POINTER(_retval); *_retval = nullptr; @@ -1590,14 +1588,16 @@ nsNSSCertificateDB::get_default_nickname(CERTCertificate *cert, } } } - if (!dummycert) + if (!dummycert) { break; - + } count++; } } -NS_IMETHODIMP nsNSSCertificateDB::AddCertFromBase64(const char *aBase64, const char *aTrust, const char *aName) +NS_IMETHODIMP nsNSSCertificateDB::AddCertFromBase64(const char* aBase64, + const char* aTrust, + const char* aName) { NS_ENSURE_ARG_POINTER(aBase64); nsCOMPtr newCert; @@ -1668,7 +1668,7 @@ nsNSSCertificateDB::AddCert(const nsACString & aCertDER, const char *aTrust, } NS_IMETHODIMP -nsNSSCertificateDB::SetCertTrustFromString(nsIX509Cert3* cert, +nsNSSCertificateDB::SetCertTrustFromString(nsIX509Cert* cert, const char* trustString) { CERTCertTrust trust; @@ -1761,11 +1761,10 @@ nsNSSCertificateDB::VerifyCertNow(nsIX509Cert* aCert, EnsureIdentityInfoLoaded(); #endif - nsCOMPtr x509Cert = do_QueryInterface(aCert); - if (!x509Cert) { + ScopedCERTCertificate nssCert(aCert->GetCert()); + if (!nssCert) { return NS_ERROR_INVALID_ARG; } - ScopedCERTCertificate nssCert(x509Cert->GetCert()); RefPtr certVerifier(GetDefaultCertVerifier()); NS_ENSURE_TRUE(certVerifier, NS_ERROR_FAILURE); diff --git a/security/manager/ssl/src/nsNSSCertificateDB.h b/security/manager/ssl/src/nsNSSCertificateDB.h index 1fe5c745c6e9..142d2f8088c0 100644 --- a/security/manager/ssl/src/nsNSSCertificateDB.h +++ b/security/manager/ssl/src/nsNSSCertificateDB.h @@ -6,7 +6,6 @@ #define __NSNSSCERTIFICATEDB_H__ #include "nsIX509CertDB.h" -#include "nsIX509CertDB2.h" #include "nsNSSShutDown.h" #include "mozilla/RefPtr.h" #include "mozilla/Mutex.h" @@ -17,14 +16,12 @@ class nsIArray; class nsRecentBadCerts; class nsNSSCertificateDB : public nsIX509CertDB - , public nsIX509CertDB2 , public nsNSSShutDownObject { public: NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSIX509CERTDB - NS_DECL_NSIX509CERTDB2 nsNSSCertificateDB(); diff --git a/security/manager/ssl/src/nsNSSCertificateFakeTransport.cpp b/security/manager/ssl/src/nsNSSCertificateFakeTransport.cpp index 2dd8d7b9e6aa..f7547af5629d 100644 --- a/security/manager/ssl/src/nsNSSCertificateFakeTransport.cpp +++ b/security/manager/ssl/src/nsNSSCertificateFakeTransport.cpp @@ -12,7 +12,6 @@ #include "nsISupportsPrimitives.h" #include "nsIX509Cert.h" #include "nsNSSCertificate.h" -#include "nsNSSCertificate.h" #include "nsString.h" #include "nsXPIDLString.h" @@ -357,3 +356,55 @@ nsNSSCertificateFakeTransport::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc) *aClassIDNoAlloc = kNSSCertificateCID; return NS_OK; } + +NS_IMETHODIMP +nsNSSCertificateFakeTransport::GetCertType(unsigned int*) +{ + NS_NOTREACHED("Unimplemented on content process"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsNSSCertificateFakeTransport::GetIsSelfSigned(bool*) +{ + NS_NOTREACHED("Unimplemented on content process"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsNSSCertificateFakeTransport::RequestUsagesArrayAsync(nsICertVerificationListener*) +{ + NS_NOTREACHED("Unimplemented on content process"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsNSSCertificateFakeTransport::GetAllTokenNames(unsigned int*, + char16_t***) +{ + NS_NOTREACHED("Unimplemented on content process"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +CERTCertificate* +nsNSSCertificateFakeTransport::GetCert() +{ + NS_NOTREACHED("Unimplemented on content process"); + return nullptr; +} + +NS_IMETHODIMP +nsNSSCertificateFakeTransport::ExportAsCMS(unsigned int, + unsigned int*, + unsigned char**) +{ + NS_NOTREACHED("Unimplemented on content process"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsNSSCertificateFakeTransport::MarkForPermDeletion() +{ + NS_NOTREACHED("Unimplemented on content process"); + return NS_ERROR_NOT_IMPLEMENTED; +} \ No newline at end of file diff --git a/security/manager/ssl/src/nsNSSIOLayer.cpp b/security/manager/ssl/src/nsNSSIOLayer.cpp index 78611e44721f..19e3b7bb16aa 100644 --- a/security/manager/ssl/src/nsNSSIOLayer.cpp +++ b/security/manager/ssl/src/nsNSSIOLayer.cpp @@ -387,16 +387,19 @@ nsNSSSocketInfo::JoinConnection(const nsACString& npnProtocol, ScopedCERTCertificate nssCert; - nsCOMPtr cert2 = do_QueryInterface(SSLStatus()->mServerCert); - if (cert2) - nssCert = cert2->GetCert(); + nsCOMPtr cert(SSLStatus()->mServerCert); + if (cert) { + nssCert = cert->GetCert(); + } - if (!nssCert) + if (!nssCert) { return NS_OK; + } if (CERT_VerifyCertName(nssCert, PromiseFlatCString(hostname).get()) != - SECSuccess) - return NS_OK; + SECSuccess) { + return NS_OK; + } // All tests pass - this is joinable mJoined = true; diff --git a/security/manager/ssl/src/nsVerificationJob.h b/security/manager/ssl/src/nsVerificationJob.h index ce02178f8d60..3bf4c6a5be8d 100644 --- a/security/manager/ssl/src/nsVerificationJob.h +++ b/security/manager/ssl/src/nsVerificationJob.h @@ -10,7 +10,6 @@ #include "nspr.h" #include "nsIX509Cert.h" -#include "nsIX509Cert3.h" #include "nsProxyRelease.h" class nsBaseVerificationJob diff --git a/security/manager/ssl/tests/unit/test_getchain.js b/security/manager/ssl/tests/unit/test_getchain.js index 637b59561a54..f9a6a39aba88 100644 --- a/security/manager/ssl/tests/unit/test_getchain.js +++ b/security/manager/ssl/tests/unit/test_getchain.js @@ -8,9 +8,6 @@ do_get_profile(); // must be called before getting nsIX509CertDB const certdb = Cc["@mozilla.org/security/x509certdb;1"] .getService(Ci.nsIX509CertDB); -const certdb2 = Cc["@mozilla.org/security/x509certdb;1"] - .getService(Ci.nsIX509CertDB2); - // This is the list of certificates needed for the test // The certificates prefixed by 'int-' are intermediates let certList = [ @@ -29,7 +26,7 @@ function load_cert(cert_name, trust_string) { // the ones that I am interested in. function get_ca_array() { let ret_array = new Array(); - let allCerts = certdb2.getCerts(); + let allCerts = certdb.getCerts(); let enumerator = allCerts.getEnumerator(); while (enumerator.hasMoreElements()) { let cert = enumerator.getNext().QueryInterface(Ci.nsIX509Cert); diff --git a/security/manager/tools/genHPKPStaticPins.js b/security/manager/tools/genHPKPStaticPins.js index 04625e4f41b3..66d47ddfa344 100644 --- a/security/manager/tools/genHPKPStaticPins.js +++ b/security/manager/tools/genHPKPStaticPins.js @@ -25,7 +25,7 @@ let { FileUtils } = Cu.import("resource://gre/modules/FileUtils.jsm", {}); let { Services } = Cu.import("resource://gre/modules/Services.jsm", {}); let gCertDB = Cc["@mozilla.org/security/x509certdb;1"] - .getService(Ci.nsIX509CertDB2); + .getService(Ci.nsIX509CertDB); gCertDB.QueryInterface(Ci.nsIX509CertDB); const BUILT_IN_NICK_PREFIX = "Builtin Object Token:"; @@ -108,8 +108,7 @@ function isBuiltinToken(tokenName) { } function isCertBuiltIn(cert) { - let cert3 = cert.QueryInterface(Ci.nsIX509Cert3); - let tokenNames = cert3.getAllTokenNames({}); + let tokenNames = cert.getAllTokenNames({}); if (!tokenNames) { return false; } diff --git a/security/pkix/test/gtest/moz.build b/security/pkix/test/gtest/moz.build index 8c5020fd689c..2ebd8e8f266f 100644 --- a/security/pkix/test/gtest/moz.build +++ b/security/pkix/test/gtest/moz.build @@ -12,6 +12,7 @@ SOURCES += [ 'pkix_cert_extension_tests.cpp', 'pkix_ocsp_request_tests.cpp', 'pkixcheck_CheckKeyUsage_tests.cpp', + 'pkixcheck_CheckTimes_tests.cpp', 'pkixder_input_tests.cpp', 'pkixder_pki_types_tests.cpp', 'pkixder_universal_types_tests.cpp', diff --git a/security/pkix/test/gtest/pkixcheck_CheckTimes_tests.cpp b/security/pkix/test/gtest/pkixcheck_CheckTimes_tests.cpp new file mode 100644 index 000000000000..c6cefd4e5cf0 --- /dev/null +++ b/security/pkix/test/gtest/pkixcheck_CheckTimes_tests.cpp @@ -0,0 +1,174 @@ +/* -*- 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 code is made available to you under your choice of the following sets + * of licensing terms: + */ +/* 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/. + */ +/* Copyright 2014 Mozilla Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pkixgtest.h" +#include "pkixtestutil.h" + +using namespace mozilla::pkix; +using namespace mozilla::pkix::test; + +namespace mozilla { namespace pkix { + +extern Result CheckTimes(const CERTValidity& validity, PRTime time); + +} } // namespace mozilla::pkix + +static const SECItem empty_null = { siBuffer, nullptr, 0 }; + +static const PRTime PAST_TIME(YMDHMS(1998, 12, 31, 12, 23, 56)); + +static const uint8_t OLDER_GENERALIZEDTIME_DATA[] = { + '1', '9', '9', '9', '0', '1', '0', '1', // 1999-01-01 + '0', '0', '0', '0', '0', '0', 'Z' // 00:00:00Z +}; +static const SECItem OLDER_GENERALIZEDTIME = { + siGeneralizedTime, + const_cast(OLDER_GENERALIZEDTIME_DATA), + sizeof(OLDER_GENERALIZEDTIME_DATA) +}; + +static const uint8_t OLDER_UTCTIME_DATA[] = { + '9', '9', '0', '1', '0', '1', // (19)99-01-01 + '0', '0', '0', '0', '0', '0', 'Z' // 00:00:00Z +}; +static const SECItem OLDER_UTCTIME = { + siUTCTime, + const_cast(OLDER_UTCTIME_DATA), + sizeof(OLDER_UTCTIME_DATA) +}; + +static const PRTime NOW(YMDHMS(2016, 12, 31, 12, 23, 56)); + +static const uint8_t NEWER_GENERALIZEDTIME_DATA[] = { + '2', '0', '2', '1', '0', '1', '0', '1', // 2021-01-01 + '0', '0', '0', '0', '0', '0', 'Z' // 00:00:00Z +}; +static const SECItem NEWER_GENERALIZEDTIME = { + siGeneralizedTime, + const_cast(NEWER_GENERALIZEDTIME_DATA), + sizeof(NEWER_GENERALIZEDTIME_DATA) +}; + +static const uint8_t NEWER_UTCTIME_DATA[] = { + '2', '1', '0', '1', '0', '1', // 2021-01-01 + '0', '0', '0', '0', '0', '0', 'Z' // 00:00:00Z +}; +static const SECItem NEWER_UTCTIME = { + siUTCTime, + const_cast(NEWER_UTCTIME_DATA), + sizeof(NEWER_UTCTIME_DATA) +}; + +static const PRTime FUTURE_TIME(YMDHMS(2025, 12, 31, 12, 23, 56)); + + + +class pkixcheck_CheckTimes : public ::testing::Test +{ +public: + virtual void SetUp() + { + PR_SetError(0, 0); + } +}; + +TEST_F(pkixcheck_CheckTimes, BothEmptyNull) +{ + static const CERTValidity validity = { nullptr, empty_null, empty_null }; + ASSERT_RecoverableError(SEC_ERROR_EXPIRED_CERTIFICATE, + CheckTimes(validity, NOW)); +} + +TEST_F(pkixcheck_CheckTimes, NotBeforeEmptyNull) +{ + static const CERTValidity validity = { nullptr, empty_null, NEWER_UTCTIME }; + ASSERT_RecoverableError(SEC_ERROR_EXPIRED_CERTIFICATE, + CheckTimes(validity, NOW)); +} + +TEST_F(pkixcheck_CheckTimes, NotAfterEmptyNull) +{ + static const CERTValidity validity = { nullptr, OLDER_UTCTIME, empty_null }; + ASSERT_RecoverableError(SEC_ERROR_EXPIRED_CERTIFICATE, + CheckTimes(validity, NOW)); +} + +TEST_F(pkixcheck_CheckTimes, Valid_UTCTIME_UTCTIME) +{ + static const CERTValidity validity = { + nullptr, OLDER_UTCTIME, NEWER_UTCTIME + }; + ASSERT_Success(CheckTimes(validity, NOW)); +} + +TEST_F(pkixcheck_CheckTimes, Valid_GENERALIZEDTIME_GENERALIZEDTIME) +{ + static const CERTValidity validity = { + nullptr, OLDER_GENERALIZEDTIME, NEWER_GENERALIZEDTIME + }; + ASSERT_Success(CheckTimes(validity, NOW)); +} + +TEST_F(pkixcheck_CheckTimes, Valid_GENERALIZEDTIME_UTCTIME) +{ + static const CERTValidity validity = { + nullptr, OLDER_GENERALIZEDTIME, NEWER_UTCTIME + }; + ASSERT_Success(CheckTimes(validity, NOW)); +} + +TEST_F(pkixcheck_CheckTimes, Valid_UTCTIME_GENERALIZEDTIME) +{ + static const CERTValidity validity = { + nullptr, OLDER_UTCTIME, NEWER_GENERALIZEDTIME + }; + ASSERT_Success(CheckTimes(validity, NOW)); +} + +TEST_F(pkixcheck_CheckTimes, InvalidBeforeNotBefore) +{ + static const CERTValidity validity = { + nullptr, OLDER_UTCTIME, NEWER_UTCTIME + }; + ASSERT_RecoverableError(SEC_ERROR_EXPIRED_CERTIFICATE, + CheckTimes(validity, PAST_TIME)); +} + +TEST_F(pkixcheck_CheckTimes, InvalidAfterNotAfter) +{ + static const CERTValidity validity = { + nullptr, OLDER_UTCTIME, NEWER_UTCTIME + }; + ASSERT_RecoverableError(SEC_ERROR_EXPIRED_CERTIFICATE, + CheckTimes(validity, FUTURE_TIME)); +} + +TEST_F(pkixcheck_CheckTimes, InvalidNotAfterBeforeNotBefore) +{ + static const CERTValidity validity = { + nullptr, NEWER_UTCTIME, OLDER_UTCTIME + }; + ASSERT_RecoverableError(SEC_ERROR_EXPIRED_CERTIFICATE, + CheckTimes(validity, NOW)); +} diff --git a/security/pkix/test/gtest/pkixder_universal_types_tests.cpp b/security/pkix/test/gtest/pkixder_universal_types_tests.cpp index e7c9ddf178b1..29900668ff7a 100644 --- a/security/pkix/test/gtest/pkixder_universal_types_tests.cpp +++ b/security/pkix/test/gtest/pkixder_universal_types_tests.cpp @@ -28,9 +28,11 @@ #include "pkix/bind.h" #include "pkixder.h" +#include "pkixtestutil.h" #include "stdint.h" using namespace mozilla::pkix::der; +using namespace mozilla::pkix::test; using namespace std; namespace { @@ -305,23 +307,6 @@ TEST_F(pkixder_universal_types_tests, EnumeratedInvalidZeroLength) ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError()); } -static PRTime -YMDHMS(int16_t year, int16_t month, int16_t day, - int16_t hour, int16_t minutes, int16_t seconds) -{ - PRExplodedTime tm; - tm.tm_usec = 0; - tm.tm_sec = seconds; - tm.tm_min = minutes; - tm.tm_hour = hour; - tm.tm_mday = day; - tm.tm_month = month - 1; // tm_month is zero-based - tm.tm_year = year; - tm.tm_params.tp_gmt_offset = 0; - tm.tm_params.tp_dst_offset = 0; - return PR_ImplodeTime(&tm); -} - //////////////////////////////////////// // GeneralizedTime and TimeChoice // diff --git a/security/pkix/test/lib/pkixtestutil.cpp b/security/pkix/test/lib/pkixtestutil.cpp index 6c9f2a5c2092..4df702e66b5b 100644 --- a/security/pkix/test/lib/pkixtestutil.cpp +++ b/security/pkix/test/lib/pkixtestutil.cpp @@ -428,6 +428,23 @@ PRTimeToTimeChoice(PLArenaPool* arena, PRTime time) : GeneralizedTime); } +PRTime +YMDHMS(int16_t year, int16_t month, int16_t day, + int16_t hour, int16_t minutes, int16_t seconds) +{ + PRExplodedTime tm; + tm.tm_usec = 0; + tm.tm_sec = seconds; + tm.tm_min = minutes; + tm.tm_hour = hour; + tm.tm_mday = day; + tm.tm_month = month - 1; // tm_month is zero-based + tm.tm_year = year; + tm.tm_params.tp_gmt_offset = 0; + tm.tm_params.tp_dst_offset = 0; + return PR_ImplodeTime(&tm); +} + static SECItem* SignedData(PLArenaPool* arena, const SECItem* tbsData, SECKEYPrivateKey* privKey, SECOidTag hashAlg, diff --git a/security/pkix/test/lib/pkixtestutil.h b/security/pkix/test/lib/pkixtestutil.h index b768818bd8a5..68ff66b97e39 100644 --- a/security/pkix/test/lib/pkixtestutil.h +++ b/security/pkix/test/lib/pkixtestutil.h @@ -62,6 +62,10 @@ FILE* OpenFile(const char* dir, const char* filename, const char* mode); extern const PRTime ONE_DAY; +// e.g. YMDHMS(2016, 12, 31, 1, 23, 45) => 2016-12-31:01:23:45 (GMT) +PRTime YMDHMS(int16_t year, int16_t month, int16_t day, + int16_t hour, int16_t minutes, int16_t seconds); + SECStatus GenerateKeyPair(/*out*/ ScopedSECKEYPublicKey& publicKey, /*out*/ ScopedSECKEYPrivateKey& privateKey); diff --git a/testing/mochitest/android23.json b/testing/mochitest/android23.json index 72973f050dd4..ab9d55ec38aa 100644 --- a/testing/mochitest/android23.json +++ b/testing/mochitest/android23.json @@ -4,7 +4,6 @@ "robocop": "TIMED_OUT", "content/canvas/test/webgl-conformance": "bug 865443 - separate suite -- mochitest-gl", "content/canvas/test/webgl-mochitest/test_no_arr_points.html": "Android 2.3 aws only; bug 1030942", - "content/html/content/test/test_bug659743.xml": "Android 2.3 aws only; bug 1031103", "docshell/test/navigation/test_reserved.html": "too slow on Android 2.3 aws only; bug 1030403", "dom/media/tests/mochitest": "Android 2.3 only; bug 981881", "layout/style/test/test_media_queries.html": "Android 2.3 aws only; bug 1030419", diff --git a/testing/mozbase/mozdevice/mozdevice/devicemanagerSUT.py b/testing/mozbase/mozdevice/mozdevice/devicemanagerSUT.py index 7410836985a0..66757db803b3 100644 --- a/testing/mozbase/mozdevice/mozdevice/devicemanagerSUT.py +++ b/testing/mozbase/mozdevice/mozdevice/devicemanagerSUT.py @@ -537,20 +537,33 @@ class DeviceManagerSUT(DeviceManager): def killProcess(self, appname, sig=None): if sig: - self._logger.warn("killProcess(): sig parameter unsupported on SUT") - retries = 0 - while retries < self.retryLimit: - try: - if self.processExist(appname): - self._runCmds([{ 'cmd': 'kill ' + appname }]) - return - except DMError, err: - retries +=1 - self._logger.warn("try %d of %d failed to kill %s" % - (retries, self.retryLimit, appname)) - self._logger.debug(err) - if retries >= self.retryLimit: + pid = self.processExist(appname) + if pid and pid > 0: + try: + self.shellCheckOutput(['kill', '-%d' % sig, str(pid)], + root=True) + except DMError, err: + self._logger.warn("unable to kill -%d %s (pid %s)" % + (sig, appname, str(pid))) + self._logger.debug(err) raise err + else: + self._logger.warn("unable to kill -%d %s -- not running?" % + (sig, appname)) + else: + retries = 0 + while retries < self.retryLimit: + try: + if self.processExist(appname): + self._runCmds([{ 'cmd': 'kill ' + appname }]) + return + except DMError, err: + retries += 1 + self._logger.warn("try %d of %d failed to kill %s" % + (retries, self.retryLimit, appname)) + self._logger.debug(err) + if retries >= self.retryLimit: + raise err def getTempDir(self): return self._runCmds([{ 'cmd': 'tmpd' }]).strip() diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index 2ab5b57efe7b..a0214783eb39 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -2959,6 +2959,28 @@ "extended_statistics_ok": true, "description": "PLACES: Time to calculate the md5 hash for a backup" }, + "FENNEC_DISTRIBUTION_REFERRER_INVALID": { + "expires_in_version": "never", + "kind": "flag", + "description": "Whether the referrer intent specified an invalid distribution name", + "cpp_guard": "ANDROID" + }, + "FENNEC_DISTRIBUTION_CODE_CATEGORY": { + "expires_in_version": "never", + "kind": "enumerated", + "n_values": 20, + "description": "First digit of HTTP result code, or error category, during distribution download", + "cpp_guard": "ANDROID" + }, + "FENNEC_DISTRIBUTION_DOWNLOAD_TIME_MS": { + "expires_in_version": "never", + "kind": "exponential", + "low": 100, + "high": "40000", + "n_buckets": 30, + "description": "Time taken to download a specified distribution file (msec)", + "cpp_guard": "ANDROID" + }, "FENNEC_FAVICONS_COUNT": { "expires_in_version": "never", "kind": "exponential", diff --git a/toolkit/devtools/discovery/discovery.js b/toolkit/devtools/discovery/discovery.js index 7e14e9f581c5..fe54b81e1ed0 100644 --- a/toolkit/devtools/discovery/discovery.js +++ b/toolkit/devtools/discovery/discovery.js @@ -39,10 +39,9 @@ const UDPSocket = CC("@mozilla.org/network/udp-socket;1", "nsIUDPSocket", "init"); -// TODO Bug 1027456: May need to reserve these with IANA const SCAN_PORT = 50624; const UPDATE_PORT = 50625; -const ADDRESS = "224.0.0.200"; +const ADDRESS = "224.0.0.115"; const REPLY_TIMEOUT = 5000; const { XPCOMUtils } = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {}); @@ -158,6 +157,8 @@ function Discovery() { this._onRemoteUpdate = this._onRemoteUpdate.bind(this); this._purgeMissingDevices = this._purgeMissingDevices.bind(this); + Services.obs.addObserver(this, "network-active-changed", false); + this._getSystemInfo(); } @@ -295,6 +296,35 @@ Discovery.prototype = { this._transports.update = null; }, + observe: function(subject, topic, data) { + if (topic !== "network-active-changed") { + return; + } + let activeNetwork = subject; + if (!activeNetwork) { + log("No active network"); + return; + } + activeNetwork = activeNetwork.QueryInterface(Ci.nsINetworkInterface); + log("Active network changed to: " + activeNetwork.type); + // UDP sockets go down when the device goes offline, so we'll restart them + // when the active network goes back to WiFi. + if (activeNetwork.type === Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) { + this._restartListening(); + } + }, + + _restartListening: function() { + if (this._transports.scan) { + this._stopListeningForScan(); + this._startListeningForScan(); + } + if (this._transports.update) { + this._stopListeningForUpdate(); + this._startListeningForUpdate(); + } + }, + /** * When sending message, we can use either transport, so just pick the first * one currently alive. diff --git a/toolkit/devtools/server/actors/webaudio.js b/toolkit/devtools/server/actors/webaudio.js index 6472093f1854..4cea0f9e925d 100644 --- a/toolkit/devtools/server/actors/webaudio.js +++ b/toolkit/devtools/server/actors/webaudio.js @@ -363,7 +363,7 @@ let WebAudioActor = exports.WebAudioActor = protocol.ActorClass({ let { caller, args, window, name } = functionCall.details; let source = caller; let dest = args[0]; - let isAudioParam = dest instanceof window.AudioParam; + let isAudioParam = dest ? getConstructorName(dest) === "AudioParam" : false; // audionode.connect(param) if (name === "connect" && isAudioParam) { @@ -433,8 +433,9 @@ let WebAudioActor = exports.WebAudioActor = protocol.ActorClass({ }, "connect-param": { type: "connectParam", - source: Arg(0, "audionode"), - param: Arg(1, "string") + source: Option(0, "audionode"), + dest: Option(0, "audionode"), + param: Option(0, "string") }, "change-param": { type: "changeParam", @@ -461,12 +462,30 @@ let WebAudioActor = exports.WebAudioActor = protocol.ActorClass({ // Ensure AudioNode is wrapped. node = new XPCNativeWrapper(node); + this._instrumentParams(node); + let actor = new AudioNodeActor(this.conn, node); this.manage(actor); this._nativeToActorID.set(node.id, actor.actorID); return actor; }, + /** + * Takes an XrayWrapper node, and attaches the node's `nativeID` + * to the AudioParams as `_parentID`, as well as the the type of param + * as a string on `_paramName`. + */ + _instrumentParams: function (node) { + let type = getConstructorName(node); + Object.keys(NODE_PROPERTIES[type]) + .filter(isAudioParam.bind(null, node)) + .forEach(paramName => { + let param = node[paramName]; + param._parentID = node.id; + param._paramName = paramName; + }); + }, + /** * Takes an AudioNode and returns the stored actor for it. * In some cases, we won't have an actor stored (for example, @@ -505,10 +524,15 @@ let WebAudioActor = exports.WebAudioActor = protocol.ActorClass({ /** * Called when an audio node is connected to an audio param. - * Implement in bug 986705 */ - _onConnectParam: function (source, dest) { - // TODO bug 986705 + _onConnectParam: function (source, param) { + let sourceActor = this._getActorByNativeID(source.id); + let destActor = this._getActorByNativeID(param._parentID); + emit(this, "connect-param", { + source: sourceActor, + dest: destActor, + param: param._paramName + }); }, /** diff --git a/toolkit/modules/CertUtils.jsm b/toolkit/modules/CertUtils.jsm index bce6b65a7cb5..00a2c52935db 100644 --- a/toolkit/modules/CertUtils.jsm +++ b/toolkit/modules/CertUtils.jsm @@ -167,7 +167,6 @@ this.checkCert = if (!issuerCert) throw new Ce(certNotBuiltInErr, Cr.NS_ERROR_ABORT); - issuerCert = issuerCert.QueryInterface(Ci.nsIX509Cert3); var tokenNames = issuerCert.getAllTokenNames({}); if (!tokenNames || !tokenNames.some(isBuiltinToken)) diff --git a/toolkit/modules/Troubleshoot.jsm b/toolkit/modules/Troubleshoot.jsm index 8e8728008a41..8c65a7c79741 100644 --- a/toolkit/modules/Troubleshoot.jsm +++ b/toolkit/modules/Troubleshoot.jsm @@ -83,6 +83,7 @@ const PREFS_WHITELIST = [ const PREFS_BLACKLIST = [ /^network[.]proxy[.]/, /[.]print_to_filename$/, + /^print[.]macosx[.]pagesetup/, ]; this.Troubleshoot = { diff --git a/widget/gonk/Framebuffer.cpp b/widget/gonk/Framebuffer.cpp index f5e4a9451fb0..1e508ea0b3f9 100644 --- a/widget/gonk/Framebuffer.cpp +++ b/widget/gonk/Framebuffer.cpp @@ -15,120 +15,27 @@ * limitations under the License. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include +#include "Framebuffer.h" #include "android/log.h" +#include +#include +#include -#include "Framebuffer.h" -#include "gfxContext.h" -#include "gfxImageSurface.h" -#include "gfxUtils.h" +#include "nsSize.h" #include "mozilla/FileUtils.h" -#include "nsTArray.h" -#include "nsRegion.h" -#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args) +#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args) using namespace std; namespace mozilla { - namespace Framebuffer { -static int sFd = -1; static size_t sMappedSize; static struct fb_var_screeninfo sVi; -static size_t sActiveBuffer; -typedef vector > BufferVector; -BufferVector* sBuffers; static gfxIntSize *sScreenSize = nullptr; -BufferVector& Buffers() { return *sBuffers; } - -bool -SetGraphicsMode() -{ - ScopedClose fd(open("/dev/tty0", O_RDWR | O_SYNC)); - if (0 > fd.get()) { - // This is non-fatal; post-Cupcake kernels don't have tty0. - LOG("No /dev/tty0?"); - } else if (ioctl(fd.get(), KDSETMODE, (void*) KD_GRAPHICS)) { - LOG("Error setting graphics mode on /dev/tty0"); - return false; - } - return true; -} - -bool -Open() -{ - if (0 <= sFd) - return true; - - if (!SetGraphicsMode()) - return false; - - ScopedClose fd(open("/dev/graphics/fb0", O_RDWR)); - if (0 > fd.get()) { - LOG("Error opening framebuffer device"); - return false; - } - - struct fb_fix_screeninfo fi; - if (0 > ioctl(fd.get(), FBIOGET_FSCREENINFO, &fi)) { - LOG("Error getting fixed screeninfo"); - return false; - } - - if (0 > ioctl(fd.get(), FBIOGET_VSCREENINFO, &sVi)) { - LOG("Error getting variable screeninfo"); - return false; - } - - sMappedSize = fi.smem_len; - void* mem = mmap(0, sMappedSize, PROT_READ | PROT_WRITE, MAP_SHARED, - fd.rwget(), 0); - if (MAP_FAILED == mem) { - LOG("Error mmap'ing framebuffer"); - return false; - } - - sFd = fd.get(); - fd.forget(); - - // The android porting doc requires a /dev/graphics/fb0 device - // that's double buffered with r5g6b5 format. Hence the - // hard-coded numbers here. - gfxImageFormat format = gfxImageFormat::RGB16_565; - if (!sScreenSize) { - sScreenSize = new gfxIntSize(sVi.xres, sVi.yres); - } - long stride = fi.line_length; - size_t numFrameBytes = stride * sScreenSize->height; - - sBuffers = new BufferVector(2); - unsigned char* data = static_cast(mem); - for (size_t i = 0; i < 2; ++i, data += numFrameBytes) { - memset(data, 0, numFrameBytes); - Buffers()[i] = new gfxImageSurface(data, *sScreenSize, stride, format); - } - - // Clear the framebuffer to a known state. - Present(nsIntRect()); - - return true; -} - bool GetSize(nsIntSize *aScreenSize) { // If the framebuffer has been opened, we should always have the size. @@ -153,54 +60,5 @@ GetSize(nsIntSize *aScreenSize) { return true; } -void -Close() -{ - if (0 > sFd) - return; - - munmap(Buffers()[0]->Data(), sMappedSize); - delete sBuffers; - sBuffers = nullptr; - delete sScreenSize; - sScreenSize = nullptr; - - close(sFd); - sFd = -1; -} - -gfxASurface* -BackBuffer() -{ - return Buffers()[!sActiveBuffer]; -} - -static gfxASurface* -FrontBuffer() -{ - return Buffers()[sActiveBuffer]; -} - -void -Present(const nsIntRegion& aUpdated) -{ - sActiveBuffer = !sActiveBuffer; - - sVi.yres_virtual = sVi.yres * 2; - sVi.yoffset = sActiveBuffer * sVi.yres; - sVi.bits_per_pixel = 16; - if (ioctl(sFd, FBIOPUT_VSCREENINFO, &sVi) < 0) { - LOG("Error presenting front buffer"); - } - - nsRefPtr ctx = new gfxContext(BackBuffer()); - gfxUtils::PathFromRegion(ctx, aUpdated); - ctx->Clip(); - ctx->SetSource(FrontBuffer()); - ctx->SetOperator(gfxContext::OPERATOR_SOURCE); - ctx->Paint(1.0); -} - } // namespace Framebuffer - } // namespace mozilla diff --git a/widget/gonk/Framebuffer.h b/widget/gonk/Framebuffer.h index 7d2147f249e7..263e49ec9929 100644 --- a/widget/gonk/Framebuffer.h +++ b/widget/gonk/Framebuffer.h @@ -15,48 +15,14 @@ * limitations under the License. */ -class gfxASurface; -class nsIntRegion; class nsIntSize; namespace mozilla { - namespace Framebuffer { -// -// The general usage of Framebuffer is -// -// -- in initialization code -- -// Open(); -// -// -- ready to paint next frame -- -// nsRefPtr backBuffer = BackBuffer(); -// // ... -// Paint(backBuffer); -// // ... -// Present(); -// - -// Return true if the fbdev was successfully opened. If this fails, -// the result of all further calls is undefined. Open() is idempotent. -bool Open(); - -// After Close(), the result of all further calls is undefined. -// Close() is idempotent, and Open() can be called again after -// Close(). -void Close(); - // Return true if the fbdev was successfully opened or the size was // already cached. bool GetSize(nsIntSize *aScreenSize); -// Return the buffer to be drawn into, that will be the next frame. -gfxASurface* BackBuffer(); - -// Swap the front buffer for the back buffer. |aUpdated| is the -// region of the back buffer that was repainted. -void Present(const nsIntRegion& aUpdated); - } // namespace Framebuffer - } // namespace mozilla diff --git a/widget/gonk/HwcComposer2D.cpp b/widget/gonk/HwcComposer2D.cpp index b2a83141f548..dc24eb4a9c40 100644 --- a/widget/gonk/HwcComposer2D.cpp +++ b/widget/gonk/HwcComposer2D.cpp @@ -19,9 +19,9 @@ #include "libdisplay/GonkDisplay.h" #include "Framebuffer.h" -#include "GLContext.h" // for GLContext #include "HwcUtils.h" #include "HwcComposer2D.h" +#include "LayerScope.h" #include "mozilla/layers/LayerManagerComposite.h" #include "mozilla/layers/PLayerTransaction.h" #include "mozilla/layers/ShadowLayerUtilsGralloc.h" @@ -807,8 +807,12 @@ HwcComposer2D::TryRender(Layer* aRoot, return false; } + // Send data to LayerScope for debugging + SendtoLayerScope(); + if (!TryHwComposition()) { LOGD("H/W Composition failed"); + LayerScope::CleanLayer(); return false; } @@ -816,4 +820,19 @@ HwcComposer2D::TryRender(Layer* aRoot, return true; } +void +HwcComposer2D::SendtoLayerScope() +{ + if (!LayerScope::CheckSendable()) { + return; + } + + const int len = mList->numHwLayers; + for (int i = 0; i < len; ++i) { + LayerComposite* layer = mHwcLayerMap[i]; + const hwc_rect_t r = mList->hwLayers[i].displayFrame; + LayerScope::SendLayer(layer, r.right - r.left, r.bottom - r.top); + } +} + } // namespace mozilla diff --git a/widget/gonk/HwcComposer2D.h b/widget/gonk/HwcComposer2D.h index 927004f5556f..f7d25ec245f3 100644 --- a/widget/gonk/HwcComposer2D.h +++ b/widget/gonk/HwcComposer2D.h @@ -97,6 +97,7 @@ private: const gfxMatrix& aParentTransform, const gfxMatrix& aGLWorldTransform); void setCrop(HwcLayer* layer, hwc_rect_t srcCrop); void setHwcGeometry(bool aGeometryChanged); + void SendtoLayerScope(); HwcDevice* mHwc; HwcList* mList; diff --git a/widget/gonk/nsWindow.cpp b/widget/gonk/nsWindow.cpp index b59a65a4defe..8bc5ad0509ad 100644 --- a/widget/gonk/nsWindow.cpp +++ b/widget/gonk/nsWindow.cpp @@ -68,14 +68,10 @@ static uint32_t sScreenRotation; static uint32_t sPhysicalScreenRotation; static nsIntRect sVirtualBounds; -static nsRefPtr sGLContext; static nsTArray sTopWindows; static nsWindow *gFocusedWindow = nullptr; -static bool sFramebufferOpen; -static bool sUsingOMTC; static bool sUsingHwc; static bool sScreenInitialized; -static nsRefPtr sOMTCSurface; namespace { @@ -160,15 +156,11 @@ nsWindow::nsWindow() // to know the color depth, which asks our native window. // This has to happen after other init has finished. gfxPlatform::GetPlatform(); - sUsingOMTC = ShouldUseOffMainThreadCompositing(); - + if (!ShouldUseOffMainThreadCompositing()) { + MOZ_CRASH("How can we render apps, then?"); + } //Update sUsingHwc whenever layers.composer2d.enabled changes Preferences::AddBoolVarCache(&sUsingHwc, "layers.composer2d.enabled"); - - if (sUsingOMTC) { - sOMTCSurface = new gfxImageSurface(gfxIntSize(1, 1), - gfxImageFormat::RGB24); - } } } @@ -201,35 +193,6 @@ nsWindow::DoDraw(void) LayerManager* lm = targetWindow->GetLayerManager(); if (mozilla::layers::LayersBackend::LAYERS_CLIENT == lm->GetBackendType()) { // No need to do anything, the compositor will handle drawing - } else if (mozilla::layers::LayersBackend::LAYERS_BASIC == lm->GetBackendType()) { - MOZ_ASSERT(sFramebufferOpen || sUsingOMTC); - nsRefPtr targetSurface; - - if(sUsingOMTC) - targetSurface = sOMTCSurface; - else - targetSurface = Framebuffer::BackBuffer(); - - { - nsRefPtr ctx = new gfxContext(targetSurface); - gfxUtils::PathFromRegion(ctx, sVirtualBounds); - ctx->Clip(); - - // No double-buffering needed. - AutoLayerManagerSetup setupLayerManager( - targetWindow, ctx, mozilla::layers::BufferMode::BUFFER_NONE, - ScreenRotation(EffectiveScreenRotation())); - - listener = targetWindow->GetWidgetListener(); - if (listener) { - listener->PaintWindow(targetWindow, sVirtualBounds); - } - } - - if (!sUsingOMTC) { - targetSurface->Flush(); - Framebuffer::Present(sVirtualBounds); - } } else { NS_RUNTIMEABORT("Unexpected layer manager type"); } @@ -537,12 +500,7 @@ nsWindow::GetLayerManager(PLayerTransactionChild* aShadowManager, if (mLayerManager) { // This layer manager might be used for painting outside of DoDraw(), so we need // to set the correct rotation on it. - if (mLayerManager->GetBackendType() == LayersBackend::LAYERS_BASIC) { - BasicLayerManager* manager = - static_cast(mLayerManager.get()); - manager->SetDefaultTargetConfiguration(mozilla::layers::BufferMode::BUFFER_NONE, - ScreenRotation(EffectiveScreenRotation())); - } else if (mLayerManager->GetBackendType() == LayersBackend::LAYERS_CLIENT) { + if (mLayerManager->GetBackendType() == LayersBackend::LAYERS_CLIENT) { ClientLayerManager* manager = static_cast(mLayerManager.get()); manager->SetDefaultTargetConfiguration(mozilla::layers::BufferMode::BUFFER_NONE, @@ -561,38 +519,13 @@ nsWindow::GetLayerManager(PLayerTransactionChild* aShadowManager, return nullptr; } - if (sUsingOMTC) { - CreateCompositor(); - if (mCompositorParent) { - uint64_t rootLayerTreeId = mCompositorParent->RootLayerTreeId(); - CompositorParent::SetControllerForLayerTree(rootLayerTreeId, new ParentProcessController()); - CompositorParent::GetAPZCTreeManager(rootLayerTreeId)->SetDPI(GetDPI()); - } - if (mLayerManager) - return mLayerManager; + CreateCompositor(); + if (mCompositorParent) { + uint64_t rootLayerTreeId = mCompositorParent->RootLayerTreeId(); + CompositorParent::SetControllerForLayerTree(rootLayerTreeId, new ParentProcessController()); + CompositorParent::GetAPZCTreeManager(rootLayerTreeId)->SetDPI(GetDPI()); } - - if (mUseLayersAcceleration) { - DebugOnly fbBounds = gScreenBounds; - if (!sGLContext) { - sGLContext = GLContextProvider::CreateForWindow(this); - } - - MOZ_ASSERT(fbBounds.value == gScreenBounds); - } - - // Fall back to software rendering. - sFramebufferOpen = Framebuffer::Open(); - if (sFramebufferOpen) { - LOG("Falling back to framebuffer software rendering"); - } else { - LOGE("Failed to mmap fb(?!?), aborting ..."); - NS_RUNTIMEABORT("Can't open GL context and can't fall back on /dev/graphics/fb0 ..."); - } - - mLayerManager = new ClientLayerManager(this); - mUseLayersAcceleration = false; - + MOZ_ASSERT(mLayerManager); return mLayerManager; } diff --git a/widget/xpwidgets/nsBaseWidget.cpp b/widget/xpwidgets/nsBaseWidget.cpp index 775c99a4eeac..91a6bdcb8bc4 100644 --- a/widget/xpwidgets/nsBaseWidget.cpp +++ b/widget/xpwidgets/nsBaseWidget.cpp @@ -172,7 +172,7 @@ static void DeferredDestroyCompositor(CompositorParent* aCompositorParent, void nsBaseWidget::DestroyCompositor() { - LayerScope::DestroyServerSocket(); + LayerScope::DeInit(); if (mCompositorChild) { mCompositorChild->SendWillStop(); @@ -900,8 +900,8 @@ void nsBaseWidget::CreateCompositor(int aWidth, int aHeight) return; } - // The server socket has to be created on the main thread. - LayerScope::CreateServerSocket(); + // Initialize LayerScope on the main thread. + LayerScope::Init(); mCompositorParent = NewCompositorParent(aWidth, aHeight); MessageChannel *parentChannel = mCompositorParent->GetIPCChannel(); diff --git a/xpcom/reflect/xptcall/md/win32/moz.build b/xpcom/reflect/xptcall/md/win32/moz.build index 82f387ff6cf8..9c28b9602ad5 100644 --- a/xpcom/reflect/xptcall/md/win32/moz.build +++ b/xpcom/reflect/xptcall/md/win32/moz.build @@ -33,8 +33,7 @@ else: 'xptcinvoke.cpp', 'xptcstubs.cpp', ] - if CONFIG['TARGET_CPU'] == 'x86_64' or CONFIG['GNU_CXX']: - SOURCES['xptcinvoke.cpp'].no_pgo = True + SOURCES['xptcinvoke.cpp'].no_pgo = True FINAL_LIBRARY = 'xpcom_core' @@ -42,8 +41,3 @@ LOCAL_INCLUDES += [ '../..', '/xpcom/reflect/xptinfo', ] - -if CONFIG['TARGET_CPU'] != 'x86_64': - if not CONFIG['GNU_CXX']: - # FIXME: bug 413019 - NO_PGO = True