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