mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central to b2g-inbound
This commit is contained in:
commit
8ba211d938
@ -9,6 +9,7 @@ support-files =
|
|||||||
doc_media-node-creation.html
|
doc_media-node-creation.html
|
||||||
doc_destroy-nodes.html
|
doc_destroy-nodes.html
|
||||||
doc_connect-toggle.html
|
doc_connect-toggle.html
|
||||||
|
doc_connect-param.html
|
||||||
440hz_sine.ogg
|
440hz_sine.ogg
|
||||||
head.js
|
head.js
|
||||||
|
|
||||||
@ -20,6 +21,7 @@ support-files =
|
|||||||
[browser_audionode-actor-is-source.js]
|
[browser_audionode-actor-is-source.js]
|
||||||
[browser_webaudio-actor-simple.js]
|
[browser_webaudio-actor-simple.js]
|
||||||
[browser_webaudio-actor-destroy-node.js]
|
[browser_webaudio-actor-destroy-node.js]
|
||||||
|
[browser_webaudio-actor-connect-param.js]
|
||||||
|
|
||||||
[browser_wa_destroy-node-01.js]
|
[browser_wa_destroy-node-01.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();
|
||||||
|
}
|
28
browser/devtools/webaudioeditor/test/doc_connect-param.html
Normal file
28
browser/devtools/webaudioeditor/test/doc_connect-param.html
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<!-- Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||||
|
<!doctype html>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<title>Web Audio Editor test page</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<script type="text/javascript;version=1.8">
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
let ctx = new AudioContext();
|
||||||
|
let carrier = ctx.createOscillator();
|
||||||
|
let modulator = ctx.createOscillator();
|
||||||
|
let gain = ctx.createGain();
|
||||||
|
carrier.connect(gain);
|
||||||
|
gain.connect(ctx.destination);
|
||||||
|
modulator.connect(gain.gain);
|
||||||
|
modulator.start(0);
|
||||||
|
carrier.start(0);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
@ -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 BUFFER_AND_ARRAY_URL = EXAMPLE_URL + "doc_buffer-and-array.html";
|
||||||
const DESTROY_NODES_URL = EXAMPLE_URL + "doc_destroy-nodes.html";
|
const DESTROY_NODES_URL = EXAMPLE_URL + "doc_destroy-nodes.html";
|
||||||
const CONNECT_TOGGLE_URL = EXAMPLE_URL + "doc_connect-toggle.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.
|
// All tests are asynchronous.
|
||||||
waitForExplicitFinish();
|
waitForExplicitFinish();
|
||||||
|
@ -86,7 +86,7 @@ class RemoteAutomation(Automation):
|
|||||||
|
|
||||||
topActivity = self._devicemanager.getTopActivity()
|
topActivity = self._devicemanager.getTopActivity()
|
||||||
if topActivity == proc.procName:
|
if topActivity == proc.procName:
|
||||||
proc.kill()
|
proc.kill(True)
|
||||||
if status == 1:
|
if status == 1:
|
||||||
if maxTime:
|
if maxTime:
|
||||||
print "TEST-UNEXPECTED-FAIL | %s | application ran for longer than " \
|
print "TEST-UNEXPECTED-FAIL | %s | application ran for longer than " \
|
||||||
@ -287,5 +287,26 @@ class RemoteAutomation(Automation):
|
|||||||
|
|
||||||
return status
|
return status
|
||||||
|
|
||||||
def kill(self):
|
def kill(self, stagedShutdown = False):
|
||||||
self.dm.killProcess(self.procName)
|
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)
|
||||||
|
@ -228,7 +228,12 @@ HTMLTrackElement::LoadResource()
|
|||||||
return;
|
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
|
// Check for a Content Security Policy to pass down to the channel
|
||||||
// created to load the media content.
|
// created to load the media content.
|
||||||
|
@ -321,6 +321,7 @@ skip-if = os == 'win' # bug 894922
|
|||||||
[test_bug895305.html]
|
[test_bug895305.html]
|
||||||
[test_bug919265.html]
|
[test_bug919265.html]
|
||||||
[test_bug957847.html]
|
[test_bug957847.html]
|
||||||
|
[test_bug1018933.html]
|
||||||
[test_can_play_type.html]
|
[test_can_play_type.html]
|
||||||
[test_can_play_type_mpeg.html]
|
[test_can_play_type_mpeg.html]
|
||||||
skip-if = buildapp == 'b2g' # bug 1021675
|
skip-if = buildapp == 'b2g' # bug 1021675
|
||||||
|
50
content/media/test/test_bug1018933.html
Normal file
50
content/media/test/test_bug1018933.html
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=1018933
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<meta charset='utf-8'>
|
||||||
|
<title>Regression test for bug 1018933 - HTMLTrackElement should create only one TextTrack</title>
|
||||||
|
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||||
|
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p id="display"></p>
|
||||||
|
<div id="content">
|
||||||
|
</div>
|
||||||
|
<pre id="test">
|
||||||
|
<script class="testbody" type="text/javascript">
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
SpecialPowers.pushPrefEnv({"set": [["media.webvtt.enabled", true]]},
|
||||||
|
function() {
|
||||||
|
var video = document.createElement("video");
|
||||||
|
video.src = "seek.webm";
|
||||||
|
video.preload = "auto";
|
||||||
|
var trackElement = document.createElement("track");
|
||||||
|
trackElement.src = "basic.vtt";
|
||||||
|
trackElement.kind = "subtitles";
|
||||||
|
document.getElementById("content").appendChild(video);
|
||||||
|
video.appendChild(trackElement);
|
||||||
|
|
||||||
|
// Accessing the track now would have caused the bug as the track element
|
||||||
|
// shouldn't have had time to bind to the tree yet.
|
||||||
|
trackElement.track.mode = 'showing';
|
||||||
|
|
||||||
|
video.addEventListener("loadedmetadata", function run_tests() {
|
||||||
|
// Re-que run_tests() at the end of the event loop until the track
|
||||||
|
// element has loaded its data.
|
||||||
|
if (trackElement.readyState == 1) {
|
||||||
|
setTimeout(run_tests, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
is(video.textTracks.length, 1, "Video should have one TextTrack.");
|
||||||
|
SimpleTest.finish();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -12,7 +12,6 @@
|
|||||||
#include "StreamNotifyChild.h"
|
#include "StreamNotifyChild.h"
|
||||||
#include "PluginProcessChild.h"
|
#include "PluginProcessChild.h"
|
||||||
#include "gfxASurface.h"
|
#include "gfxASurface.h"
|
||||||
#include "gfxContext.h"
|
|
||||||
#include "gfxPlatform.h"
|
#include "gfxPlatform.h"
|
||||||
#include "gfx2DGlue.h"
|
#include "gfx2DGlue.h"
|
||||||
#include "nsNPAPIPluginInstance.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
|
bool
|
||||||
PluginInstanceChild::CreateOptSurface(void)
|
PluginInstanceChild::CreateOptSurface(void)
|
||||||
{
|
{
|
||||||
@ -3454,12 +3447,14 @@ PluginInstanceChild::ShowPluginFrame()
|
|||||||
PLUGIN_LOG_DEBUG((" (on background)"));
|
PLUGIN_LOG_DEBUG((" (on background)"));
|
||||||
// Source the background pixels ...
|
// Source the background pixels ...
|
||||||
{
|
{
|
||||||
nsRefPtr<gfxContext> ctx =
|
nsRefPtr<gfxASurface> surface =
|
||||||
new gfxContext(mHelperSurface ? mHelperSurface : mCurrentSurface);
|
mHelperSurface ? mHelperSurface : mCurrentSurface;
|
||||||
ctx->SetSource(mBackground);
|
RefPtr<DrawTarget> dt = CreateDrawTargetForSurface(surface);
|
||||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
RefPtr<SourceSurface> backgroundSurface =
|
||||||
ctx->Rectangle(gfxRect(rect.x, rect.y, rect.width, rect.height));
|
gfxPlatform::GetSourceSurfaceForSurface(dt, mBackground);
|
||||||
ctx->Fill();
|
dt->CopySurface(backgroundSurface,
|
||||||
|
ToIntRect(rect),
|
||||||
|
ToIntPoint(rect.TopLeft()));
|
||||||
}
|
}
|
||||||
// ... and hand off to the plugin
|
// ... and hand off to the plugin
|
||||||
// BEWARE: mBackground may die during this call
|
// BEWARE: mBackground may die during this call
|
||||||
@ -3583,18 +3578,17 @@ PluginInstanceChild::ReadbackDifferenceRect(const nsIntRect& rect)
|
|||||||
mSurfaceDifferenceRect.width, mSurfaceDifferenceRect.height));
|
mSurfaceDifferenceRect.width, mSurfaceDifferenceRect.height));
|
||||||
|
|
||||||
// Read back previous content
|
// Read back previous content
|
||||||
nsRefPtr<gfxContext> ctx = new gfxContext(mCurrentSurface);
|
RefPtr<DrawTarget> dt = CreateDrawTargetForSurface(mCurrentSurface);
|
||||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
RefPtr<SourceSurface> source =
|
||||||
ctx->SetSource(mBackSurface);
|
gfxPlatform::GetSourceSurfaceForSurface(dt, mBackSurface);
|
||||||
// Subtract from mSurfaceDifferenceRect area which is overlapping with rect
|
// Subtract from mSurfaceDifferenceRect area which is overlapping with rect
|
||||||
nsIntRegion result;
|
nsIntRegion result;
|
||||||
result.Sub(mSurfaceDifferenceRect, nsIntRegion(rect));
|
result.Sub(mSurfaceDifferenceRect, nsIntRegion(rect));
|
||||||
nsIntRegionRectIterator iter(result);
|
nsIntRegionRectIterator iter(result);
|
||||||
const nsIntRect* r;
|
const nsIntRect* r;
|
||||||
while ((r = iter.Next()) != nullptr) {
|
while ((r = iter.Next()) != nullptr) {
|
||||||
ctx->Rectangle(GfxFromNsRect(*r));
|
dt->CopySurface(source, ToIntRect(*r), ToIntPoint(r->TopLeft()));
|
||||||
}
|
}
|
||||||
ctx->Fill();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -3309,13 +3309,13 @@ WifiWorker.prototype = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let certDB2 = Cc["@mozilla.org/security/x509certdb;1"]
|
let certDB = Cc["@mozilla.org/security/x509certdb;1"]
|
||||||
.getService(Ci.nsIX509CertDB2);
|
.getService(Ci.nsIX509CertDB);
|
||||||
if (!certDB2) {
|
if (!certDB) {
|
||||||
self._sendMessage(message, false, "Failed to query NSS DB service", msg);
|
self._sendMessage(message, false, "Failed to query NSS DB service", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
let certList = certDB2.getCerts();
|
let certList = certDB.getCerts();
|
||||||
if (!certList) {
|
if (!certList) {
|
||||||
self._sendMessage(message, false, "Failed to get certificate List", msg);
|
self._sendMessage(message, false, "Failed to get certificate List", msg);
|
||||||
}
|
}
|
||||||
@ -3332,7 +3332,7 @@ WifiWorker.prototype = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
while (certListEnum.hasMoreElements()) {
|
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);
|
let certNicknameInfo = /WIFI\_([A-Z]*)\_(.*)/.exec(certInfo.nickname);
|
||||||
if (!certNicknameInfo) {
|
if (!certNicknameInfo) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
#include "nsPIDOMWindow.h"
|
#include "nsPIDOMWindow.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "BackgroundChild.h"
|
|
||||||
#include "GeckoProfiler.h"
|
#include "GeckoProfiler.h"
|
||||||
#include "js/OldDebugAPI.h"
|
#include "js/OldDebugAPI.h"
|
||||||
#include "jsfriendapi.h"
|
#include "jsfriendapi.h"
|
||||||
@ -41,7 +40,6 @@
|
|||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "nsCycleCollector.h"
|
#include "nsCycleCollector.h"
|
||||||
#include "nsDOMJSUtils.h"
|
#include "nsDOMJSUtils.h"
|
||||||
#include "nsIIPCBackgroundChildCreateCallback.h"
|
|
||||||
#include "nsISupportsImpl.h"
|
#include "nsISupportsImpl.h"
|
||||||
#include "nsLayoutStatics.h"
|
#include "nsLayoutStatics.h"
|
||||||
#include "nsNetUtil.h"
|
#include "nsNetUtil.h"
|
||||||
@ -66,12 +64,6 @@
|
|||||||
#include "WorkerPrivate.h"
|
#include "WorkerPrivate.h"
|
||||||
#include "WorkerRunnable.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;
|
||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
|
|
||||||
@ -169,10 +161,6 @@ RuntimeService* gRuntimeService = nullptr;
|
|||||||
// Only non-null during the call to Init.
|
// Only non-null during the call to Init.
|
||||||
RuntimeService* gRuntimeServiceDuringInit = nullptr;
|
RuntimeService* gRuntimeServiceDuringInit = nullptr;
|
||||||
|
|
||||||
#ifdef ENABLE_TESTS
|
|
||||||
bool gTestPBackground = false;
|
|
||||||
#endif // ENABLE_TESTS
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ID_Worker = 0,
|
ID_Worker = 0,
|
||||||
ID_ChromeWorker,
|
ID_ChromeWorker,
|
||||||
@ -911,37 +899,6 @@ private:
|
|||||||
WorkerPrivate* mWorkerPrivate;
|
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
|
class WorkerThreadPrimaryRunnable MOZ_FINAL : public nsRunnable
|
||||||
{
|
{
|
||||||
WorkerPrivate* mWorkerPrivate;
|
WorkerPrivate* mWorkerPrivate;
|
||||||
@ -984,9 +941,6 @@ private:
|
|||||||
~WorkerThreadPrimaryRunnable()
|
~WorkerThreadPrimaryRunnable()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
nsresult
|
|
||||||
SynchronouslyCreatePBackground();
|
|
||||||
|
|
||||||
NS_DECL_NSIRUNNABLE
|
NS_DECL_NSIRUNNABLE
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1086,28 +1040,6 @@ public:
|
|||||||
}
|
}
|
||||||
#endif
|
#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<int64_t>(PR_GetCurrentThread()));
|
|
||||||
PBackgroundChild* existingBackgroundChild =
|
|
||||||
BackgroundChild::GetForCurrentThread();
|
|
||||||
MOZ_RELEASE_ASSERT(existingBackgroundChild);
|
|
||||||
bool ok = existingBackgroundChild->SendPBackgroundTestConstructor(testStr);
|
|
||||||
MOZ_RELEASE_ASSERT(ok);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // #ENABLE_TESTS
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WorkerThread()
|
WorkerThread()
|
||||||
: nsThread(nsThread::NOT_MAIN_THREAD, WORKER_STACK_SIZE),
|
: nsThread(nsThread::NOT_MAIN_THREAD, WORKER_STACK_SIZE),
|
||||||
@ -1311,10 +1243,6 @@ RuntimeService::GetOrCreateService()
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_TESTS
|
|
||||||
gTestPBackground = mozilla::Preferences::GetBool("pbackground.testing", false);
|
|
||||||
#endif // ENABLE_TESTS
|
|
||||||
|
|
||||||
// The observer service now owns us until shutdown.
|
// The observer service now owns us until shutdown.
|
||||||
gRuntimeService = service;
|
gRuntimeService = service;
|
||||||
}
|
}
|
||||||
@ -1604,6 +1532,10 @@ RuntimeService::ScheduleWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
thread->SetAcceptingNonWorkerRunnables(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2592,20 +2524,8 @@ RuntimeService::WorkerThread::Observer::OnProcessNextEvent(
|
|||||||
bool aMayWait,
|
bool aMayWait,
|
||||||
uint32_t aRecursionDepth)
|
uint32_t aRecursionDepth)
|
||||||
{
|
{
|
||||||
using mozilla::ipc::BackgroundChild;
|
|
||||||
|
|
||||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
|
MOZ_ASSERT(!aMayWait);
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
mWorkerPrivate->OnProcessNextEvent(aRecursionDepth);
|
mWorkerPrivate->OnProcessNextEvent(aRecursionDepth);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@ -2649,15 +2569,11 @@ LogViolationDetailsRunnable::Run()
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(WorkerBackgroundChildCallback, nsIIPCBackgroundChildCreateCallback)
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS_INHERITED0(WorkerThreadPrimaryRunnable, nsRunnable)
|
NS_IMPL_ISUPPORTS_INHERITED0(WorkerThreadPrimaryRunnable, nsRunnable)
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
WorkerThreadPrimaryRunnable::Run()
|
WorkerThreadPrimaryRunnable::Run()
|
||||||
{
|
{
|
||||||
using mozilla::ipc::BackgroundChild;
|
|
||||||
|
|
||||||
#ifdef MOZ_NUWA_PROCESS
|
#ifdef MOZ_NUWA_PROCESS
|
||||||
if (IsNuwaProcess()) {
|
if (IsNuwaProcess()) {
|
||||||
NS_ASSERTION(NuwaMarkCurrentThread != nullptr,
|
NS_ASSERTION(NuwaMarkCurrentThread != nullptr,
|
||||||
@ -2676,19 +2592,6 @@ WorkerThreadPrimaryRunnable::Run()
|
|||||||
|
|
||||||
profiler_register_thread(threadName.get(), &stackBaseGuess);
|
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);
|
mThread->SetWorker(mWorkerPrivate);
|
||||||
|
|
||||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
@ -2722,12 +2625,6 @@ WorkerThreadPrimaryRunnable::Run()
|
|||||||
JS_ReportPendingException(cx);
|
JS_ReportPendingException(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_TESTS
|
|
||||||
mThread->TestPBackground();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
BackgroundChild::CloseForCurrentThread();
|
|
||||||
|
|
||||||
#ifdef MOZ_ENABLE_PROFILER_SPS
|
#ifdef MOZ_ENABLE_PROFILER_SPS
|
||||||
if (stack) {
|
if (stack) {
|
||||||
stack->sampleRuntime(nullptr);
|
stack->sampleRuntime(nullptr);
|
||||||
@ -2766,38 +2663,6 @@ WorkerThreadPrimaryRunnable::Run()
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
|
||||||
WorkerThreadPrimaryRunnable::SynchronouslyCreatePBackground()
|
|
||||||
{
|
|
||||||
using mozilla::ipc::BackgroundChild;
|
|
||||||
|
|
||||||
MOZ_ASSERT(!BackgroundChild::GetForCurrentThread());
|
|
||||||
|
|
||||||
bool done = false;
|
|
||||||
nsCOMPtr<nsIIPCBackgroundChildCreateCallback> 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,
|
NS_IMPL_ISUPPORTS_INHERITED0(WorkerThreadPrimaryRunnable::FinishedRunnable,
|
||||||
nsRunnable)
|
nsRunnable)
|
||||||
|
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/Endian.h"
|
#include "mozilla/Endian.h"
|
||||||
#include "TexturePoolOGL.h"
|
#include "TexturePoolOGL.h"
|
||||||
|
#include "mozilla/layers/CompositorOGL.h"
|
||||||
|
#include "mozilla/layers/LayerManagerComposite.h"
|
||||||
#include "mozilla/layers/TextureHostOGL.h"
|
#include "mozilla/layers/TextureHostOGL.h"
|
||||||
|
|
||||||
#include "gfxColor.h"
|
#include "gfxColor.h"
|
||||||
@ -317,6 +319,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AppendDebugData(DebugGLData *aDebugData);
|
void AppendDebugData(DebugGLData *aDebugData);
|
||||||
|
void CleanDebugData();
|
||||||
void DispatchDebugData();
|
void DispatchDebugData();
|
||||||
private:
|
private:
|
||||||
nsTArray<nsRefPtr<LayerScopeWebSocketHandler> > mHandlers;
|
nsTArray<nsRefPtr<LayerScopeWebSocketHandler> > mHandlers;
|
||||||
@ -325,7 +328,37 @@ private:
|
|||||||
nsCOMPtr<nsIServerSocket> mServerSocket;
|
nsCOMPtr<nsIServerSocket> mServerSocket;
|
||||||
};
|
};
|
||||||
|
|
||||||
static StaticAutoPtr<LayerScopeWebSocketManager> 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<LayerScopeWebSocketManager> sWebSocketManager;
|
||||||
|
};
|
||||||
|
|
||||||
|
StaticAutoPtr<LayerScopeWebSocketManager> WebSocketHelper::sWebSocketManager;
|
||||||
|
|
||||||
class DebugGLData : public LinkedListElement<DebugGLData> {
|
class DebugGLData : public LinkedListElement<DebugGLData> {
|
||||||
public:
|
public:
|
||||||
@ -378,9 +411,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool WriteToStream(void *ptr, uint32_t size) {
|
static bool WriteToStream(void *ptr, uint32_t size) {
|
||||||
if (!gLayerScopeWebSocketManager)
|
if (!WebSocketHelper::GetSocketManager())
|
||||||
return true;
|
return true;
|
||||||
return gLayerScopeWebSocketManager->WriteAll(ptr, size);
|
return WebSocketHelper::GetSocketManager()->WriteAll(ptr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -428,83 +461,97 @@ public:
|
|||||||
|
|
||||||
class DebugGLTextureData : public DebugGLData {
|
class DebugGLTextureData : public DebugGLData {
|
||||||
public:
|
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),
|
: DebugGLData(DebugGLData::TextureData, cx),
|
||||||
mLayerRef(layerRef),
|
mLayerRef(layerRef),
|
||||||
mTarget(target),
|
mTarget(target),
|
||||||
mName(name),
|
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; }
|
void *GetLayerRef() const { return mLayerRef; }
|
||||||
GLuint GetName() const { return mName; }
|
GLuint GetName() const { return mName; }
|
||||||
DataSourceSurface* GetImage() const { return mImage; }
|
|
||||||
GLenum GetTextureTarget() const { return mTarget; }
|
GLenum GetTextureTarget() const { return mTarget; }
|
||||||
|
|
||||||
virtual bool Write() {
|
virtual bool Write() {
|
||||||
DebugGLData::TexturePacket packet;
|
|
||||||
char* dataptr = nullptr;
|
|
||||||
uint32_t datasize = 0;
|
|
||||||
std::auto_ptr<char> compresseddata;
|
|
||||||
|
|
||||||
packet.type = mDataType;
|
|
||||||
packet.ptr = static_cast<uint64_t>(mContextAddress);
|
|
||||||
packet.layerref = reinterpret_cast<uint64_t>(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>((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
|
// write the packet header data
|
||||||
if (!WriteToStream(&packet, sizeof(packet)))
|
if (!WriteToStream(&mPacket, sizeof(mPacket)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// then the image data
|
// then the image data
|
||||||
if (!WriteToStream(dataptr, datasize))
|
if (mCompresseddata.get() && !WriteToStream(mCompresseddata.get(), mDatasize))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// then pad out to 4 bytes
|
// then pad out to 4 bytes
|
||||||
if (datasize % 4 != 0) {
|
if (mDatasize % 4 != 0) {
|
||||||
static char buf[] = { 0, 0, 0, 0 };
|
static char buf[] = { 0, 0, 0, 0 };
|
||||||
if (!WriteToStream(buf, 4 - (datasize % 4)))
|
if (!WriteToStream(buf, 4 - (mDatasize % 4)))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void pack(DataSourceSurface* aImage) {
|
||||||
|
mPacket.type = mDataType;
|
||||||
|
mPacket.ptr = static_cast<uint64_t>(mContextAddress);
|
||||||
|
mPacket.layerref = reinterpret_cast<uint64_t>(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>(
|
||||||
|
(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:
|
protected:
|
||||||
void* mLayerRef;
|
void* mLayerRef;
|
||||||
GLenum mTarget;
|
GLenum mTarget;
|
||||||
GLuint mName;
|
GLuint mName;
|
||||||
RefPtr<DataSourceSurface> mImage;
|
|
||||||
|
// Packet data
|
||||||
|
DebugGLData::TexturePacket mPacket;
|
||||||
|
std::auto_ptr<char> mCompresseddata;
|
||||||
|
uint32_t mDatasize;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DebugGLColorData : public DebugGLData {
|
class DebugGLColorData : public DebugGLData {
|
||||||
@ -539,18 +586,6 @@ protected:
|
|||||||
nsIntSize mSize;
|
nsIntSize mSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool
|
|
||||||
CheckSender()
|
|
||||||
{
|
|
||||||
if (!gLayerScopeWebSocketManager)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!gLayerScopeWebSocketManager->IsConnected())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
class DebugListener : public nsIServerSocketListener
|
class DebugListener : public nsIServerSocketListener
|
||||||
{
|
{
|
||||||
virtual ~DebugListener() { }
|
virtual ~DebugListener() { }
|
||||||
@ -566,11 +601,11 @@ public:
|
|||||||
NS_IMETHODIMP OnSocketAccepted(nsIServerSocket *aServ,
|
NS_IMETHODIMP OnSocketAccepted(nsIServerSocket *aServ,
|
||||||
nsISocketTransport *aTransport)
|
nsISocketTransport *aTransport)
|
||||||
{
|
{
|
||||||
if (!gLayerScopeWebSocketManager)
|
if (!WebSocketHelper::GetSocketManager())
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
printf_stderr("*** LayerScope: Accepted connection\n");
|
printf_stderr("*** LayerScope: Accepted connection\n");
|
||||||
gLayerScopeWebSocketManager->AddConnection(aTransport);
|
WebSocketHelper::GetSocketManager()->AddConnection(aTransport);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -594,24 +629,19 @@ public:
|
|||||||
|
|
||||||
NS_DECL_THREADSAFE_ISUPPORTS
|
NS_DECL_THREADSAFE_ISUPPORTS
|
||||||
|
|
||||||
DebugDataSender() {
|
DebugDataSender() { }
|
||||||
mList = new LinkedList<DebugGLData>();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Append(DebugGLData *d) {
|
void Append(DebugGLData *d) {
|
||||||
mList->insertBack(d);
|
mList.insertBack(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cleanup() {
|
void Cleanup() {
|
||||||
if (!mList)
|
if (mList.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DebugGLData *d;
|
DebugGLData *d;
|
||||||
while ((d = mList->popFirst()) != nullptr)
|
while ((d = mList.popFirst()) != nullptr)
|
||||||
delete d;
|
delete d;
|
||||||
delete mList;
|
|
||||||
|
|
||||||
mList = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* nsIRunnable impl; send the data */
|
/* nsIRunnable impl; send the data */
|
||||||
@ -620,7 +650,7 @@ public:
|
|||||||
DebugGLData *d;
|
DebugGLData *d;
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
|
|
||||||
while ((d = mList->popFirst()) != nullptr) {
|
while ((d = mList.popFirst()) != nullptr) {
|
||||||
std::auto_ptr<DebugGLData> cleaner(d);
|
std::auto_ptr<DebugGLData> cleaner(d);
|
||||||
if (!d->Write()) {
|
if (!d->Write()) {
|
||||||
rv = NS_ERROR_FAILURE;
|
rv = NS_ERROR_FAILURE;
|
||||||
@ -631,84 +661,124 @@ public:
|
|||||||
Cleanup();
|
Cleanup();
|
||||||
|
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
LayerScope::DestroyServerSocket();
|
WebSocketHelper::DestroyServerSocket();
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
LinkedList<DebugGLData> *mList;
|
LinkedList<DebugGLData> mList;
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(DebugDataSender, nsIRunnable);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gLayerScopeWebSocketManager) {
|
switch (aLayer->GetLayer()->GetType()) {
|
||||||
gLayerScopeWebSocketManager = new LayerScopeWebSocketManager();
|
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<CompositorOGL*>(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
|
void
|
||||||
LayerScope::DestroyServerSocket()
|
SenderHelper::SendColor(void* aLayerRef,
|
||||||
|
const gfxRGBA& aColor,
|
||||||
|
int aWidth,
|
||||||
|
int aHeight)
|
||||||
{
|
{
|
||||||
if (gLayerScopeWebSocketManager) {
|
WebSocketHelper::GetSocketManager()->AppendDebugData(
|
||||||
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(
|
|
||||||
new DebugGLColorData(aLayerRef, aColor, aWidth, aHeight));
|
new DebugGLColorData(aLayerRef, aColor, aWidth, aHeight));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
SendTextureSource(GLContext* aGLContext,
|
SenderHelper::SendTextureSource(GLContext* aGLContext,
|
||||||
void* aLayerRef,
|
void* aLayerRef,
|
||||||
TextureSourceOGL* aSource,
|
TextureSourceOGL* aSource,
|
||||||
bool aFlipY)
|
bool aFlipY)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(aGLContext);
|
||||||
|
if (!aGLContext) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
GLenum textureTarget = aSource->GetTextureTarget();
|
GLenum textureTarget = aSource->GetTextureTarget();
|
||||||
ShaderConfigOGL config = ShaderConfigFromTargetAndFormat(textureTarget,
|
ShaderConfigOGL config = ShaderConfigFromTargetAndFormat(textureTarget,
|
||||||
aSource->GetFormat());
|
aSource->GetFormat());
|
||||||
@ -736,15 +806,15 @@ SendTextureSource(GLContext* aGLContext,
|
|||||||
size,
|
size,
|
||||||
shaderConfig, aFlipY);
|
shaderConfig, aFlipY);
|
||||||
|
|
||||||
gLayerScopeWebSocketManager->AppendDebugData(
|
WebSocketHelper::GetSocketManager()->AppendDebugData(
|
||||||
new DebugGLTextureData(aGLContext, aLayerRef, textureTarget,
|
new DebugGLTextureData(aGLContext, aLayerRef, textureTarget,
|
||||||
textureId, img));
|
textureId, img));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
SendTexturedEffect(GLContext* aGLContext,
|
SenderHelper::SendTexturedEffect(GLContext* aGLContext,
|
||||||
void* aLayerRef,
|
void* aLayerRef,
|
||||||
const TexturedEffect* aEffect)
|
const TexturedEffect* aEffect)
|
||||||
{
|
{
|
||||||
TextureSourceOGL* source = aEffect->mTexture->AsSourceOGL();
|
TextureSourceOGL* source = aEffect->mTexture->AsSourceOGL();
|
||||||
if (!source)
|
if (!source)
|
||||||
@ -754,10 +824,10 @@ SendTexturedEffect(GLContext* aGLContext,
|
|||||||
SendTextureSource(aGLContext, aLayerRef, source, flipY);
|
SendTextureSource(aGLContext, aLayerRef, source, flipY);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
SendYCbCrEffect(GLContext* aGLContext,
|
SenderHelper::SendYCbCrEffect(GLContext* aGLContext,
|
||||||
void* aLayerRef,
|
void* aLayerRef,
|
||||||
const EffectYCbCr* aEffect)
|
const EffectYCbCr* aEffect)
|
||||||
{
|
{
|
||||||
TextureSource* sourceYCbCr = aEffect->mTexture;
|
TextureSource* sourceYCbCr = aEffect->mTexture;
|
||||||
if (!sourceYCbCr)
|
if (!sourceYCbCr)
|
||||||
@ -775,49 +845,48 @@ SendYCbCrEffect(GLContext* aGLContext,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LayerScope::SendEffectChain(GLContext* aGLContext,
|
SenderHelper::SendEffectChain(GLContext* aGLContext,
|
||||||
const EffectChain& aEffectChain,
|
const EffectChain& aEffectChain,
|
||||||
int aWidth, int aHeight)
|
int aWidth,
|
||||||
|
int aHeight)
|
||||||
{
|
{
|
||||||
if (!CheckSender())
|
|
||||||
return;
|
|
||||||
|
|
||||||
const Effect* primaryEffect = aEffectChain.mPrimaryEffect;
|
const Effect* primaryEffect = aEffectChain.mPrimaryEffect;
|
||||||
switch (primaryEffect->mType) {
|
switch (primaryEffect->mType) {
|
||||||
case EffectTypes::RGB:
|
case EffectTypes::RGB: {
|
||||||
{
|
const TexturedEffect* texturedEffect =
|
||||||
const TexturedEffect* texturedEffect =
|
static_cast<const TexturedEffect*>(primaryEffect);
|
||||||
static_cast<const TexturedEffect*>(primaryEffect);
|
SendTexturedEffect(aGLContext, aEffectChain.mLayerRef, texturedEffect);
|
||||||
SendTexturedEffect(aGLContext, aEffectChain.mLayerRef, texturedEffect);
|
break;
|
||||||
}
|
}
|
||||||
break;
|
case EffectTypes::YCBCR: {
|
||||||
case EffectTypes::YCBCR:
|
const EffectYCbCr* yCbCrEffect =
|
||||||
{
|
static_cast<const EffectYCbCr*>(primaryEffect);
|
||||||
const EffectYCbCr* yCbCrEffect =
|
SendYCbCrEffect(aGLContext, aEffectChain.mLayerRef, yCbCrEffect);
|
||||||
static_cast<const EffectYCbCr*>(primaryEffect);
|
break;
|
||||||
SendYCbCrEffect(aGLContext, aEffectChain.mLayerRef, yCbCrEffect);
|
}
|
||||||
}
|
case EffectTypes::SOLID_COLOR: {
|
||||||
case EffectTypes::SOLID_COLOR:
|
const EffectSolidColor* solidColorEffect =
|
||||||
{
|
static_cast<const EffectSolidColor*>(primaryEffect);
|
||||||
const EffectSolidColor* solidColorEffect =
|
gfxRGBA color(solidColorEffect->mColor.r,
|
||||||
static_cast<const EffectSolidColor*>(primaryEffect);
|
solidColorEffect->mColor.g,
|
||||||
gfxRGBA color(solidColorEffect->mColor.r,
|
solidColorEffect->mColor.b,
|
||||||
solidColorEffect->mColor.g,
|
solidColorEffect->mColor.a);
|
||||||
solidColorEffect->mColor.b,
|
SendColor(aEffectChain.mLayerRef, color, aWidth, aHeight);
|
||||||
solidColorEffect->mColor.a);
|
break;
|
||||||
SendColor(aEffectChain.mLayerRef, color, aWidth, aHeight);
|
}
|
||||||
}
|
case EffectTypes::COMPONENT_ALPHA:
|
||||||
break;
|
case EffectTypes::RENDER_TARGET:
|
||||||
case EffectTypes::COMPONENT_ALPHA:
|
default:
|
||||||
case EffectTypes::RENDER_TARGET:
|
break;
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//const Effect* secondaryEffect = aEffectChain.mSecondaryEffects[EffectTypes::MASK];
|
//const Effect* secondaryEffect = aEffectChain.mSecondaryEffects[EffectTypes::MASK];
|
||||||
// TODO:
|
// TODO:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
// LayerScopeWebSocketManager implementation
|
||||||
|
// ----------------------------------------------
|
||||||
LayerScopeWebSocketManager::LayerScopeWebSocketManager()
|
LayerScopeWebSocketManager::LayerScopeWebSocketManager()
|
||||||
{
|
{
|
||||||
NS_NewThread(getter_AddRefs(mDebugSenderThread));
|
NS_NewThread(getter_AddRefs(mDebugSenderThread));
|
||||||
@ -832,7 +901,8 @@ LayerScopeWebSocketManager::~LayerScopeWebSocketManager()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayerScopeWebSocketManager::AppendDebugData(DebugGLData *aDebugData)
|
void
|
||||||
|
LayerScopeWebSocketManager::AppendDebugData(DebugGLData *aDebugData)
|
||||||
{
|
{
|
||||||
if (!mCurrentSender) {
|
if (!mCurrentSender) {
|
||||||
mCurrentSender = new DebugDataSender();
|
mCurrentSender = new DebugDataSender();
|
||||||
@ -841,11 +911,125 @@ void LayerScopeWebSocketManager::AppendDebugData(DebugGLData *aDebugData)
|
|||||||
mCurrentSender->Append(aDebugData);
|
mCurrentSender->Append(aDebugData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayerScopeWebSocketManager::DispatchDebugData()
|
void
|
||||||
|
LayerScopeWebSocketManager::CleanDebugData()
|
||||||
|
{
|
||||||
|
if (mCurrentSender) {
|
||||||
|
mCurrentSender->Cleanup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LayerScopeWebSocketManager::DispatchDebugData()
|
||||||
{
|
{
|
||||||
mDebugSenderThread->Dispatch(mCurrentSender, NS_DISPATCH_NORMAL);
|
mDebugSenderThread->Dispatch(mCurrentSender, NS_DISPATCH_NORMAL);
|
||||||
mCurrentSender = nullptr;
|
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 */
|
} /* layers */
|
||||||
} /* mozilla */
|
} /* mozilla */
|
||||||
|
@ -17,16 +17,32 @@ namespace gl { class GLContext; }
|
|||||||
namespace layers {
|
namespace layers {
|
||||||
|
|
||||||
struct EffectChain;
|
struct EffectChain;
|
||||||
|
class LayerComposite;
|
||||||
|
|
||||||
class LayerScope {
|
class LayerScope {
|
||||||
public:
|
public:
|
||||||
static void CreateServerSocket();
|
static void Init();
|
||||||
static void DestroyServerSocket();
|
static void DeInit();
|
||||||
static void BeginFrame(gl::GLContext* aGLContext, int64_t aFrameStamp);
|
|
||||||
static void EndFrame(gl::GLContext* aGLContext);
|
|
||||||
static void SendEffectChain(gl::GLContext* aGLContext,
|
static void SendEffectChain(gl::GLContext* aGLContext,
|
||||||
const EffectChain& aEffectChain,
|
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 */
|
} /* layers */
|
||||||
|
@ -87,18 +87,6 @@ CanvasLayerComposite::RenderLayer(const nsIntRect& aClipRect)
|
|||||||
}
|
}
|
||||||
#endif
|
#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);
|
EffectChain effectChain(this);
|
||||||
AddBlendModeEffect(effectChain);
|
AddBlendModeEffect(effectChain);
|
||||||
|
|
||||||
@ -108,7 +96,7 @@ CanvasLayerComposite::RenderLayer(const nsIntRect& aClipRect)
|
|||||||
mImageHost->Composite(effectChain,
|
mImageHost->Composite(effectChain,
|
||||||
GetEffectiveOpacity(),
|
GetEffectiveOpacity(),
|
||||||
GetEffectiveTransform(),
|
GetEffectiveTransform(),
|
||||||
gfx::ToFilter(filter),
|
GetEffectFilter(),
|
||||||
clipRect);
|
clipRect);
|
||||||
mImageHost->BumpFlashCounter();
|
mImageHost->BumpFlashCounter();
|
||||||
}
|
}
|
||||||
@ -132,6 +120,30 @@ CanvasLayerComposite::CleanupResources()
|
|||||||
mImageHost = nullptr;
|
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
|
void
|
||||||
CanvasLayerComposite::PrintInfo(std::stringstream& aStream, const char* aPrefix)
|
CanvasLayerComposite::PrintInfo(std::stringstream& aStream, const char* aPrefix)
|
||||||
{
|
{
|
||||||
|
@ -52,6 +52,8 @@ public:
|
|||||||
|
|
||||||
virtual void CleanupResources() MOZ_OVERRIDE;
|
virtual void CleanupResources() MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
virtual void GenEffectChain(EffectChain& aEffect) MOZ_OVERRIDE;
|
||||||
|
|
||||||
CompositableHost* GetCompositableHost() MOZ_OVERRIDE;
|
CompositableHost* GetCompositableHost() MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual LayerComposite* AsLayerComposite() MOZ_OVERRIDE { return this; }
|
virtual LayerComposite* AsLayerComposite() MOZ_OVERRIDE { return this; }
|
||||||
@ -63,6 +65,9 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) MOZ_OVERRIDE;
|
virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
gfx::Filter GetEffectFilter();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RefPtr<CompositableHost> mImageHost;
|
RefPtr<CompositableHost> mImageHost;
|
||||||
};
|
};
|
||||||
|
@ -24,11 +24,9 @@ void
|
|||||||
ColorLayerComposite::RenderLayer(const nsIntRect& aClipRect)
|
ColorLayerComposite::RenderLayer(const nsIntRect& aClipRect)
|
||||||
{
|
{
|
||||||
EffectChain effects(this);
|
EffectChain effects(this);
|
||||||
gfxRGBA color(GetColor());
|
|
||||||
effects.mPrimaryEffect = new EffectSolidColor(gfx::Color(color.r,
|
GenEffectChain(effects);
|
||||||
color.g,
|
|
||||||
color.b,
|
|
||||||
color.a));
|
|
||||||
nsIntRect boundRect = GetBounds();
|
nsIntRect boundRect = GetBounds();
|
||||||
|
|
||||||
LayerManagerComposite::AutoAddMaskEffect autoMaskEffect(GetMaskLayer(),
|
LayerManagerComposite::AutoAddMaskEffect autoMaskEffect(GetMaskLayer(),
|
||||||
@ -50,5 +48,16 @@ ColorLayerComposite::RenderLayer(const nsIntRect& aClipRect)
|
|||||||
transform);
|
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 */
|
} /* layers */
|
||||||
} /* mozilla */
|
} /* mozilla */
|
||||||
|
@ -44,6 +44,8 @@ public:
|
|||||||
virtual void RenderLayer(const nsIntRect& aClipRect) MOZ_OVERRIDE;
|
virtual void RenderLayer(const nsIntRect& aClipRect) MOZ_OVERRIDE;
|
||||||
virtual void CleanupResources() MOZ_OVERRIDE {};
|
virtual void CleanupResources() MOZ_OVERRIDE {};
|
||||||
|
|
||||||
|
virtual void GenEffectChain(EffectChain& aEffect) MOZ_OVERRIDE;
|
||||||
|
|
||||||
CompositableHost* GetCompositableHost() MOZ_OVERRIDE { return nullptr; }
|
CompositableHost* GetCompositableHost() MOZ_OVERRIDE { return nullptr; }
|
||||||
|
|
||||||
virtual LayerComposite* AsLayerComposite() MOZ_OVERRIDE { return this; }
|
virtual LayerComposite* AsLayerComposite() MOZ_OVERRIDE { return this; }
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "mozilla/gfx/Types.h" // for Filter
|
#include "mozilla/gfx/Types.h" // for Filter
|
||||||
#include "mozilla/ipc/ProtocolUtils.h"
|
#include "mozilla/ipc/ProtocolUtils.h"
|
||||||
#include "mozilla/layers/CompositorTypes.h" // for TextureInfo, etc
|
#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/LayersTypes.h" // for LayerRenderState, etc
|
||||||
#include "mozilla/layers/TextureHost.h" // for TextureHost
|
#include "mozilla/layers/TextureHost.h" // for TextureHost
|
||||||
#include "mozilla/mozalloc.h" // for operator delete
|
#include "mozilla/mozalloc.h" // for operator delete
|
||||||
@ -289,6 +290,14 @@ public:
|
|||||||
|
|
||||||
void SetAsyncID(uint64_t aID) { mAsyncID = aID; }
|
void SetAsyncID(uint64_t aID) { mAsyncID = aID; }
|
||||||
|
|
||||||
|
virtual bool Lock() { return false; }
|
||||||
|
|
||||||
|
virtual void Unlock() { }
|
||||||
|
|
||||||
|
virtual TemporaryRef<TexturedEffect> GenEffect(const gfx::Filter& aFilter) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TextureInfo mTextureInfo;
|
TextureInfo mTextureInfo;
|
||||||
uint64_t mAsyncID;
|
uint64_t mAsyncID;
|
||||||
@ -301,6 +310,29 @@ protected:
|
|||||||
bool mKeepAttached;
|
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<CompositableHost> mHost;
|
||||||
|
bool mSucceeded;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global CompositableMap, to use in the compositor thread only.
|
* Global CompositableMap, to use in the compositor thread only.
|
||||||
*
|
*
|
||||||
|
@ -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
|
void
|
||||||
ContentHostBase::Composite(EffectChain& aEffectChain,
|
ContentHostBase::Composite(EffectChain& aEffectChain,
|
||||||
float aOpacity,
|
float aOpacity,
|
||||||
@ -67,7 +46,7 @@ ContentHostBase::Composite(EffectChain& aEffectChain,
|
|||||||
{
|
{
|
||||||
NS_ASSERTION(aVisibleRegion, "Requires a visible region");
|
NS_ASSERTION(aVisibleRegion, "Requires a visible region");
|
||||||
|
|
||||||
AutoLockContentHost lock(this);
|
AutoLockCompositableHost lock(this);
|
||||||
if (lock.Failed()) {
|
if (lock.Failed()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -78,9 +57,8 @@ ContentHostBase::Composite(EffectChain& aEffectChain,
|
|||||||
if (!source) {
|
if (!source) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RefPtr<TexturedEffect> effect =
|
|
||||||
CreateTexturedEffect(source, sourceOnWhite, aFilter, true);
|
|
||||||
|
|
||||||
|
RefPtr<TexturedEffect> effect = GenEffect(aFilter);
|
||||||
if (!effect) {
|
if (!effect) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -229,6 +207,16 @@ ContentHostBase::Composite(EffectChain& aEffectChain,
|
|||||||
aTransform, mFlashCounter);
|
aTransform, mFlashCounter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TemporaryRef<TexturedEffect>
|
||||||
|
ContentHostBase::GenEffect(const gfx::Filter& aFilter)
|
||||||
|
{
|
||||||
|
RefPtr<NewTextureSource> source = GetTextureSource();
|
||||||
|
RefPtr<NewTextureSource> sourceOnWhite = GetTextureSourceOnWhite();
|
||||||
|
if (!source) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return CreateTexturedEffect(source, sourceOnWhite, aFilter, true);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ContentHostTexture::UseTextureHost(TextureHost* aTexture)
|
ContentHostTexture::UseTextureHost(TextureHost* aTexture)
|
||||||
|
@ -102,12 +102,11 @@ public:
|
|||||||
|
|
||||||
virtual void SetPaintWillResample(bool aResample) { mPaintWillResample = aResample; }
|
virtual void SetPaintWillResample(bool aResample) { mPaintWillResample = aResample; }
|
||||||
|
|
||||||
virtual bool Lock() = 0;
|
|
||||||
virtual void Unlock() = 0;
|
|
||||||
|
|
||||||
virtual NewTextureSource* GetTextureSource() = 0;
|
virtual NewTextureSource* GetTextureSource() = 0;
|
||||||
virtual NewTextureSource* GetTextureSourceOnWhite() = 0;
|
virtual NewTextureSource* GetTextureSourceOnWhite() = 0;
|
||||||
|
|
||||||
|
virtual TemporaryRef<TexturedEffect> GenEffect(const gfx::Filter& aFilter) MOZ_OVERRIDE;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual nsIntPoint GetOriginOffset()
|
virtual nsIntPoint GetOriginOffset()
|
||||||
{
|
{
|
||||||
@ -150,7 +149,7 @@ public:
|
|||||||
virtual void UseComponentAlphaTextures(TextureHost* aTextureOnBlack,
|
virtual void UseComponentAlphaTextures(TextureHost* aTextureOnBlack,
|
||||||
TextureHost* aTextureOnWhite) MOZ_OVERRIDE;
|
TextureHost* aTextureOnWhite) MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual bool Lock() {
|
virtual bool Lock() MOZ_OVERRIDE {
|
||||||
MOZ_ASSERT(!mLocked);
|
MOZ_ASSERT(!mLocked);
|
||||||
if (!mTextureHost) {
|
if (!mTextureHost) {
|
||||||
return false;
|
return false;
|
||||||
@ -166,7 +165,7 @@ public:
|
|||||||
mLocked = true;
|
mLocked = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
virtual void Unlock() {
|
virtual void Unlock() MOZ_OVERRIDE {
|
||||||
MOZ_ASSERT(mLocked);
|
MOZ_ASSERT(mLocked);
|
||||||
mTextureHost->Unlock();
|
mTextureHost->Unlock();
|
||||||
if (mTextureHostOnWhite) {
|
if (mTextureHostOnWhite) {
|
||||||
@ -175,11 +174,11 @@ public:
|
|||||||
mLocked = false;
|
mLocked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual NewTextureSource* GetTextureSource() {
|
virtual NewTextureSource* GetTextureSource() MOZ_OVERRIDE {
|
||||||
MOZ_ASSERT(mLocked);
|
MOZ_ASSERT(mLocked);
|
||||||
return mTextureHost->GetTextureSources();
|
return mTextureHost->GetTextureSources();
|
||||||
}
|
}
|
||||||
virtual NewTextureSource* GetTextureSourceOnWhite() {
|
virtual NewTextureSource* GetTextureSourceOnWhite() MOZ_OVERRIDE {
|
||||||
MOZ_ASSERT(mLocked);
|
MOZ_ASSERT(mLocked);
|
||||||
if (mTextureHostOnWhite) {
|
if (mTextureHostOnWhite) {
|
||||||
return mTextureHostOnWhite->GetTextureSources();
|
return mTextureHostOnWhite->GetTextureSources();
|
||||||
@ -281,20 +280,20 @@ public:
|
|||||||
|
|
||||||
virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) MOZ_OVERRIDE;
|
virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual bool Lock() {
|
virtual bool Lock() MOZ_OVERRIDE {
|
||||||
MOZ_ASSERT(!mLocked);
|
MOZ_ASSERT(!mLocked);
|
||||||
ProcessTextureUpdates();
|
ProcessTextureUpdates();
|
||||||
mLocked = true;
|
mLocked = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Unlock() {
|
virtual void Unlock() MOZ_OVERRIDE {
|
||||||
MOZ_ASSERT(mLocked);
|
MOZ_ASSERT(mLocked);
|
||||||
mLocked = false;
|
mLocked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual NewTextureSource* GetTextureSource();
|
virtual NewTextureSource* GetTextureSource() MOZ_OVERRIDE;
|
||||||
virtual NewTextureSource* GetTextureSourceOnWhite();
|
virtual NewTextureSource* GetTextureSourceOnWhite() MOZ_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ ImageHost::ImageHost(const TextureInfo& aTextureInfo)
|
|||||||
: CompositableHost(aTextureInfo)
|
: CompositableHost(aTextureInfo)
|
||||||
, mFrontBuffer(nullptr)
|
, mFrontBuffer(nullptr)
|
||||||
, mHasPictureRect(false)
|
, mHasPictureRect(false)
|
||||||
|
, mLocked(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
ImageHost::~ImageHost() {}
|
ImageHost::~ImageHost() {}
|
||||||
@ -81,24 +82,17 @@ ImageHost::Composite(EffectChain& aEffectChain,
|
|||||||
mFrontBuffer->SetCompositor(GetCompositor());
|
mFrontBuffer->SetCompositor(GetCompositor());
|
||||||
mFrontBuffer->SetCompositableBackendSpecificData(GetCompositableBackendSpecificData());
|
mFrontBuffer->SetCompositableBackendSpecificData(GetCompositableBackendSpecificData());
|
||||||
|
|
||||||
AutoLockTextureHost autoLock(mFrontBuffer);
|
AutoLockCompositableHost autoLock(this);
|
||||||
if (autoLock.Failed()) {
|
if (autoLock.Failed()) {
|
||||||
NS_WARNING("failed to lock front buffer");
|
NS_WARNING("failed to lock front buffer");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RefPtr<NewTextureSource> source = mFrontBuffer->GetTextureSources();
|
RefPtr<NewTextureSource> source = GetTextureSource();
|
||||||
if (!source) {
|
if (!source) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isAlphaPremultiplied = true;
|
RefPtr<TexturedEffect> effect = GenEffect(aFilter);
|
||||||
if (mFrontBuffer->GetFlags() & TextureFlags::NON_PREMULTIPLIED)
|
|
||||||
isAlphaPremultiplied = false;
|
|
||||||
|
|
||||||
RefPtr<TexturedEffect> effect = CreateTexturedEffect(mFrontBuffer->GetFormat(),
|
|
||||||
source,
|
|
||||||
aFilter,
|
|
||||||
isAlphaPremultiplied);
|
|
||||||
if (!effect) {
|
if (!effect) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -243,5 +237,48 @@ ImageHost::GetAsSurface()
|
|||||||
}
|
}
|
||||||
#endif
|
#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<NewTextureSource>
|
||||||
|
ImageHost::GetTextureSource()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mLocked);
|
||||||
|
return mFrontBuffer->GetTextureSources();
|
||||||
|
}
|
||||||
|
|
||||||
|
TemporaryRef<TexturedEffect>
|
||||||
|
ImageHost::GenEffect(const gfx::Filter& aFilter)
|
||||||
|
{
|
||||||
|
RefPtr<NewTextureSource> source = GetTextureSource();
|
||||||
|
if (!source) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
bool isAlphaPremultiplied = true;
|
||||||
|
if (mFrontBuffer->GetFlags() & TextureFlags::NON_PREMULTIPLIED)
|
||||||
|
isAlphaPremultiplied = false;
|
||||||
|
|
||||||
|
return CreateTexturedEffect(mFrontBuffer->GetFormat(),
|
||||||
|
source,
|
||||||
|
aFilter,
|
||||||
|
isAlphaPremultiplied);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,11 +79,20 @@ public:
|
|||||||
virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() MOZ_OVERRIDE;
|
virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() MOZ_OVERRIDE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
virtual bool Lock() MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
virtual void Unlock() MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
virtual TemporaryRef<NewTextureSource> GetTextureSource();
|
||||||
|
|
||||||
|
virtual TemporaryRef<TexturedEffect> GenEffect(const gfx::Filter& aFilter) MOZ_OVERRIDE;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
RefPtr<TextureHost> mFrontBuffer;
|
RefPtr<TextureHost> mFrontBuffer;
|
||||||
nsIntRect mPictureRect;
|
nsIntRect mPictureRect;
|
||||||
bool mHasPictureRect;
|
bool mHasPictureRect;
|
||||||
|
bool mLocked;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ ImageLayerComposite::RenderLayer(const nsIntRect& aClipRect)
|
|||||||
mImageHost->Composite(effectChain,
|
mImageHost->Composite(effectChain,
|
||||||
GetEffectiveOpacity(),
|
GetEffectiveOpacity(),
|
||||||
GetEffectiveTransform(),
|
GetEffectiveTransform(),
|
||||||
gfx::ToFilter(mFilter),
|
GetEffectFilter(),
|
||||||
clipRect);
|
clipRect);
|
||||||
mImageHost->BumpFlashCounter();
|
mImageHost->BumpFlashCounter();
|
||||||
}
|
}
|
||||||
@ -161,6 +161,19 @@ ImageLayerComposite::CleanupResources()
|
|||||||
mImageHost = nullptr;
|
mImageHost = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gfx::Filter
|
||||||
|
ImageLayerComposite::GetEffectFilter()
|
||||||
|
{
|
||||||
|
return gfx::ToFilter(mFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ImageLayerComposite::GenEffectChain(EffectChain& aEffect)
|
||||||
|
{
|
||||||
|
aEffect.mLayerRef = this;
|
||||||
|
aEffect.mPrimaryEffect = mImageHost->GenEffect(GetEffectFilter());
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ImageLayerComposite::PrintInfo(std::stringstream& aStream, const char* aPrefix)
|
ImageLayerComposite::PrintInfo(std::stringstream& aStream, const char* aPrefix)
|
||||||
{
|
{
|
||||||
|
@ -51,6 +51,8 @@ public:
|
|||||||
|
|
||||||
CompositableHost* GetCompositableHost() MOZ_OVERRIDE;
|
CompositableHost* GetCompositableHost() MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
virtual void GenEffectChain(EffectChain& aEffect) MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual LayerComposite* AsLayerComposite() MOZ_OVERRIDE { return this; }
|
virtual LayerComposite* AsLayerComposite() MOZ_OVERRIDE { return this; }
|
||||||
|
|
||||||
virtual const char* Name() const { return "ImageLayerComposite"; }
|
virtual const char* Name() const { return "ImageLayerComposite"; }
|
||||||
@ -58,6 +60,9 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) MOZ_OVERRIDE;
|
virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
gfx::Filter GetEffectFilter();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RefPtr<CompositableHost> mImageHost;
|
RefPtr<CompositableHost> mImageHost;
|
||||||
};
|
};
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "GeckoProfiler.h" // for profiler_set_frame_number, etc
|
#include "GeckoProfiler.h" // for profiler_set_frame_number, etc
|
||||||
#include "ImageLayerComposite.h" // for ImageLayerComposite
|
#include "ImageLayerComposite.h" // for ImageLayerComposite
|
||||||
#include "Layers.h" // for Layer, ContainerLayer, etc
|
#include "Layers.h" // for Layer, ContainerLayer, etc
|
||||||
|
#include "LayerScope.h" // for LayerScope Tool
|
||||||
#include "ThebesLayerComposite.h" // for ThebesLayerComposite
|
#include "ThebesLayerComposite.h" // for ThebesLayerComposite
|
||||||
#include "TiledLayerBuffer.h" // for TiledLayerComposer
|
#include "TiledLayerBuffer.h" // for TiledLayerComposer
|
||||||
#include "Units.h" // for ScreenIntRect
|
#include "Units.h" // for ScreenIntRect
|
||||||
@ -417,6 +418,9 @@ LayerManagerComposite::Render()
|
|||||||
/** Our more efficient but less powerful alter ego, if one is available. */
|
/** Our more efficient but less powerful alter ego, if one is available. */
|
||||||
nsRefPtr<Composer2D> composer2D = mCompositor->GetWidget()->GetComposer2D();
|
nsRefPtr<Composer2D> composer2D = mCompositor->GetWidget()->GetComposer2D();
|
||||||
|
|
||||||
|
// Set LayerScope begin/end frame
|
||||||
|
LayerScopeAutoFrame frame(PR_Now());
|
||||||
|
|
||||||
if (!mTarget && composer2D && composer2D->TryRender(mRoot, mWorldMatrix, mGeometryChanged)) {
|
if (!mTarget && composer2D && composer2D->TryRender(mRoot, mWorldMatrix, mGeometryChanged)) {
|
||||||
if (mFPS) {
|
if (mFPS) {
|
||||||
double fps = mFPS->mCompositionFps.AddFrameAndGetFps(TimeStamp::Now());
|
double fps = mFPS->mCompositionFps.AddFrameAndGetFps(TimeStamp::Now());
|
||||||
|
@ -74,7 +74,7 @@ class LayerManagerComposite : public LayerManager
|
|||||||
public:
|
public:
|
||||||
LayerManagerComposite(Compositor* aCompositor);
|
LayerManagerComposite(Compositor* aCompositor);
|
||||||
~LayerManagerComposite();
|
~LayerManagerComposite();
|
||||||
|
|
||||||
virtual void Destroy() MOZ_OVERRIDE;
|
virtual void Destroy() MOZ_OVERRIDE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -267,7 +267,7 @@ private:
|
|||||||
RefPtr<Compositor> mCompositor;
|
RefPtr<Compositor> mCompositor;
|
||||||
nsAutoPtr<LayerProperties> mClonedLayerTreeProperties;
|
nsAutoPtr<LayerProperties> mClonedLayerTreeProperties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Context target, nullptr when drawing directly to our swap chain.
|
* Context target, nullptr when drawing directly to our swap chain.
|
||||||
*/
|
*/
|
||||||
RefPtr<gfx::DrawTarget> mTarget;
|
RefPtr<gfx::DrawTarget> mTarget;
|
||||||
@ -336,11 +336,12 @@ public:
|
|||||||
|
|
||||||
virtual TiledLayerComposer* GetTiledLayerComposer() { return nullptr; }
|
virtual TiledLayerComposer* GetTiledLayerComposer() { return nullptr; }
|
||||||
|
|
||||||
|
|
||||||
virtual void DestroyFrontBuffer() { }
|
virtual void DestroyFrontBuffer() { }
|
||||||
|
|
||||||
void AddBlendModeEffect(EffectChain& aEffectChain);
|
void AddBlendModeEffect(EffectChain& aEffectChain);
|
||||||
|
|
||||||
|
virtual void GenEffectChain(EffectChain& aEffect) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The following methods are
|
* The following methods are
|
||||||
*
|
*
|
||||||
|
@ -147,7 +147,7 @@ ThebesLayerComposite::RenderLayer(const nsIntRect& aClipRect)
|
|||||||
mBuffer->Composite(effectChain,
|
mBuffer->Composite(effectChain,
|
||||||
GetEffectiveOpacity(),
|
GetEffectiveOpacity(),
|
||||||
GetEffectiveTransform(),
|
GetEffectiveTransform(),
|
||||||
gfx::Filter::LINEAR,
|
GetEffectFilter(),
|
||||||
clipRect,
|
clipRect,
|
||||||
&visibleRegion,
|
&visibleRegion,
|
||||||
mRequiresTiledProperties ? &tiledLayerProps
|
mRequiresTiledProperties ? &tiledLayerProps
|
||||||
@ -180,6 +180,13 @@ ThebesLayerComposite::CleanupResources()
|
|||||||
mBuffer = nullptr;
|
mBuffer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ThebesLayerComposite::GenEffectChain(EffectChain& aEffect)
|
||||||
|
{
|
||||||
|
aEffect.mLayerRef = this;
|
||||||
|
aEffect.mPrimaryEffect = mBuffer->GenEffect(GetEffectFilter());
|
||||||
|
}
|
||||||
|
|
||||||
CSSToScreenScale
|
CSSToScreenScale
|
||||||
ThebesLayerComposite::GetEffectiveResolution()
|
ThebesLayerComposite::GetEffectiveResolution()
|
||||||
{
|
{
|
||||||
|
@ -56,6 +56,8 @@ public:
|
|||||||
|
|
||||||
virtual void CleanupResources() MOZ_OVERRIDE;
|
virtual void CleanupResources() MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
virtual void GenEffectChain(EffectChain& aEffect) MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual bool SetCompositableHost(CompositableHost* aHost) MOZ_OVERRIDE;
|
virtual bool SetCompositableHost(CompositableHost* aHost) MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual LayerComposite* AsLayerComposite() MOZ_OVERRIDE { return this; }
|
virtual LayerComposite* AsLayerComposite() MOZ_OVERRIDE { return this; }
|
||||||
@ -81,8 +83,11 @@ protected:
|
|||||||
virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) MOZ_OVERRIDE;
|
virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) MOZ_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
gfx::Filter GetEffectFilter() { return gfx::Filter::LINEAR; }
|
||||||
|
|
||||||
CSSToScreenScale GetEffectiveResolution();
|
CSSToScreenScale GetEffectiveResolution();
|
||||||
|
|
||||||
|
private:
|
||||||
RefPtr<ContentHost> mBuffer;
|
RefPtr<ContentHost> mBuffer;
|
||||||
bool mRequiresTiledProperties;
|
bool mRequiresTiledProperties;
|
||||||
};
|
};
|
||||||
|
@ -706,8 +706,6 @@ CompositorOGL::BeginFrame(const nsIntRegion& aInvalidRegion,
|
|||||||
|
|
||||||
MOZ_ASSERT(!mFrameInProgress, "frame still in progress (should have called EndFrame or AbortFrame");
|
MOZ_ASSERT(!mFrameInProgress, "frame still in progress (should have called EndFrame or AbortFrame");
|
||||||
|
|
||||||
LayerScope::BeginFrame(mGLContext, PR_Now());
|
|
||||||
|
|
||||||
mFrameInProgress = true;
|
mFrameInProgress = true;
|
||||||
gfx::Rect rect;
|
gfx::Rect rect;
|
||||||
if (mUseExternalSurfaceSize) {
|
if (mUseExternalSurfaceSize) {
|
||||||
@ -1313,8 +1311,6 @@ CompositorOGL::EndFrame()
|
|||||||
|
|
||||||
mFrameInProgress = false;
|
mFrameInProgress = false;
|
||||||
|
|
||||||
LayerScope::EndFrame(mGLContext);
|
|
||||||
|
|
||||||
if (mTarget) {
|
if (mTarget) {
|
||||||
CopyToTarget(mTarget, mTargetBounds.TopLeft(), mCurrentRenderTarget->GetTransform());
|
CopyToTarget(mTarget, mTargetBounds.TopLeft(), mCurrentRenderTarget->GetTransform());
|
||||||
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
|
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
|
||||||
|
@ -37,11 +37,6 @@ class PBackgroundChild;
|
|||||||
// (assuming success) GetForCurrentThread() will return the same actor every
|
// (assuming success) GetForCurrentThread() will return the same actor every
|
||||||
// time.
|
// 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
|
// The PBackgroundChild actor and all its sub-protocol actors will be
|
||||||
// automatically destroyed when its designated thread completes.
|
// automatically destroyed when its designated thread completes.
|
||||||
class BackgroundChild MOZ_FINAL
|
class BackgroundChild MOZ_FINAL
|
||||||
@ -61,10 +56,6 @@ public:
|
|||||||
static bool
|
static bool
|
||||||
GetOrCreateForCurrentThread(nsIIPCBackgroundChildCreateCallback* aCallback);
|
GetOrCreateForCurrentThread(nsIIPCBackgroundChildCreateCallback* aCallback);
|
||||||
|
|
||||||
// See above.
|
|
||||||
static void
|
|
||||||
CloseForCurrentThread();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Only called by ContentChild or ContentParent.
|
// Only called by ContentChild or ContentParent.
|
||||||
static void
|
static void
|
||||||
|
@ -350,8 +350,6 @@ class ChildImpl MOZ_FINAL : public BackgroundChildImpl
|
|||||||
nsIThread* mBoundThread;
|
nsIThread* mBoundThread;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DebugOnly<bool> mActorDestroyed;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static bool
|
static bool
|
||||||
OpenProtocolOnMainThread(nsIEventTarget* aEventTarget);
|
OpenProtocolOnMainThread(nsIEventTarget* aEventTarget);
|
||||||
@ -374,15 +372,8 @@ public:
|
|||||||
THREADSAFETY_ASSERT(current);
|
THREADSAFETY_ASSERT(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
AssertActorDestroyed()
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mActorDestroyed, "ChildImpl::ActorDestroy not called in time");
|
|
||||||
}
|
|
||||||
|
|
||||||
ChildImpl()
|
ChildImpl()
|
||||||
: mBoundThread(nullptr)
|
: mBoundThread(nullptr)
|
||||||
, mActorDestroyed(false)
|
|
||||||
{
|
{
|
||||||
AssertIsOnMainThread();
|
AssertIsOnMainThread();
|
||||||
}
|
}
|
||||||
@ -406,10 +397,6 @@ private:
|
|||||||
static bool
|
static bool
|
||||||
GetOrCreateForCurrentThread(nsIIPCBackgroundChildCreateCallback* aCallback);
|
GetOrCreateForCurrentThread(nsIIPCBackgroundChildCreateCallback* aCallback);
|
||||||
|
|
||||||
// Forwarded from BackgroundChild.
|
|
||||||
static void
|
|
||||||
CloseForCurrentThread();
|
|
||||||
|
|
||||||
// Forwarded from BackgroundChildImpl.
|
// Forwarded from BackgroundChildImpl.
|
||||||
static BackgroundChildImpl::ThreadLocal*
|
static BackgroundChildImpl::ThreadLocal*
|
||||||
GetThreadLocalForCurrentThread();
|
GetThreadLocalForCurrentThread();
|
||||||
@ -422,17 +409,6 @@ private:
|
|||||||
if (threadLocalInfo) {
|
if (threadLocalInfo) {
|
||||||
if (threadLocalInfo->mActor) {
|
if (threadLocalInfo->mActor) {
|
||||||
threadLocalInfo->mActor->Close();
|
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<nsIRunnable> releaser =
|
|
||||||
NS_NewNonOwningRunnableMethod(actor, &ChildImpl::Release);
|
|
||||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(releaser)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
delete threadLocalInfo;
|
delete threadLocalInfo;
|
||||||
}
|
}
|
||||||
@ -443,9 +419,7 @@ private:
|
|||||||
|
|
||||||
// This class is reference counted.
|
// This class is reference counted.
|
||||||
~ChildImpl()
|
~ChildImpl()
|
||||||
{
|
{ }
|
||||||
AssertActorDestroyed();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
SetBoundThread()
|
SetBoundThread()
|
||||||
@ -861,13 +835,6 @@ BackgroundChild::GetOrCreateForCurrentThread(
|
|||||||
return ChildImpl::GetOrCreateForCurrentThread(aCallback);
|
return ChildImpl::GetOrCreateForCurrentThread(aCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
|
||||||
void
|
|
||||||
BackgroundChild::CloseForCurrentThread()
|
|
||||||
{
|
|
||||||
ChildImpl::CloseForCurrentThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// BackgroundChildImpl Public Methods
|
// BackgroundChildImpl Public Methods
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@ -1611,11 +1578,7 @@ ChildImpl::GetForCurrentThread()
|
|||||||
auto threadLocalInfo =
|
auto threadLocalInfo =
|
||||||
static_cast<ThreadLocalInfo*>(PR_GetThreadPrivate(sThreadLocalIndex));
|
static_cast<ThreadLocalInfo*>(PR_GetThreadPrivate(sThreadLocalIndex));
|
||||||
|
|
||||||
if (!threadLocalInfo) {
|
return threadLocalInfo ? threadLocalInfo->mActor : nullptr;
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return threadLocalInfo->mActor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
@ -1679,31 +1642,6 @@ ChildImpl::GetOrCreateForCurrentThread(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
|
||||||
void
|
|
||||||
ChildImpl::CloseForCurrentThread()
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(sThreadLocalIndex != kBadThreadLocalIndex,
|
|
||||||
"BackgroundChild::Startup() was never called!");
|
|
||||||
auto threadLocalInfo =
|
|
||||||
static_cast<ThreadLocalInfo*>(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<PRStatus> status = PR_SetThreadPrivate(sThreadLocalIndex, nullptr);
|
|
||||||
MOZ_ASSERT(status == PR_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
BackgroundChildImpl::ThreadLocal*
|
BackgroundChildImpl::ThreadLocal*
|
||||||
ChildImpl::GetThreadLocalForCurrentThread()
|
ChildImpl::GetThreadLocalForCurrentThread()
|
||||||
@ -2008,7 +1946,6 @@ ChildImpl::ActorDestroy(ActorDestroyReason aWhy)
|
|||||||
{
|
{
|
||||||
AssertIsOnBoundThread();
|
AssertIsOnBoundThread();
|
||||||
|
|
||||||
mActorDestroyed = true;
|
|
||||||
BackgroundChildImpl::ActorDestroy(aWhy);
|
BackgroundChildImpl::ActorDestroy(aWhy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,13 +7,11 @@
|
|||||||
#include "nsIRunnable.h"
|
#include "nsIRunnable.h"
|
||||||
#include "nsIThread.h"
|
#include "nsIThread.h"
|
||||||
#include "nsITimer.h"
|
#include "nsITimer.h"
|
||||||
#include "nsICancelableRunnable.h"
|
|
||||||
|
|
||||||
#include "base/basictypes.h"
|
#include "base/basictypes.h"
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
#include "base/scoped_nsautorelease_pool.h"
|
#include "base/scoped_nsautorelease_pool.h"
|
||||||
#include "mozilla/Assertions.h"
|
#include "mozilla/Assertions.h"
|
||||||
#include "mozilla/AutoRestore.h"
|
|
||||||
#include "mozilla/DebugOnly.h"
|
#include "mozilla/DebugOnly.h"
|
||||||
#include "nsComponentManagerUtils.h"
|
#include "nsComponentManagerUtils.h"
|
||||||
#include "nsDebug.h"
|
#include "nsDebug.h"
|
||||||
@ -42,14 +40,12 @@ static mozilla::DebugOnly<MessagePump::Delegate*> gFirstDelegate;
|
|||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace ipc {
|
namespace ipc {
|
||||||
|
|
||||||
class DoWorkRunnable MOZ_FINAL : public nsICancelableRunnable,
|
class DoWorkRunnable MOZ_FINAL : public nsIRunnable,
|
||||||
public nsITimerCallback
|
public nsITimerCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DoWorkRunnable(MessagePump* aPump)
|
DoWorkRunnable(MessagePump* aPump)
|
||||||
: mPump(aPump)
|
: mPump(aPump)
|
||||||
, mCanceled(false)
|
|
||||||
, mCallingRunWhileCanceled(false)
|
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aPump);
|
MOZ_ASSERT(aPump);
|
||||||
}
|
}
|
||||||
@ -57,15 +53,12 @@ public:
|
|||||||
NS_DECL_THREADSAFE_ISUPPORTS
|
NS_DECL_THREADSAFE_ISUPPORTS
|
||||||
NS_DECL_NSIRUNNABLE
|
NS_DECL_NSIRUNNABLE
|
||||||
NS_DECL_NSITIMERCALLBACK
|
NS_DECL_NSITIMERCALLBACK
|
||||||
NS_DECL_NSICANCELABLERUNNABLE
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~DoWorkRunnable()
|
~DoWorkRunnable()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
MessagePump* mPump;
|
MessagePump* mPump;
|
||||||
bool mCanceled;
|
|
||||||
bool mCallingRunWhileCanceled;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace ipc */
|
} /* namespace ipc */
|
||||||
@ -218,17 +211,11 @@ MessagePump::DoDelayedWork(base::MessagePump::Delegate* aDelegate)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(DoWorkRunnable, nsIRunnable, nsITimerCallback,
|
NS_IMPL_ISUPPORTS(DoWorkRunnable, nsIRunnable, nsITimerCallback)
|
||||||
nsICancelableRunnable)
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
DoWorkRunnable::Run()
|
DoWorkRunnable::Run()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(!mCanceled || mCallingRunWhileCanceled);
|
|
||||||
if (mCanceled && !mCallingRunWhileCanceled) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageLoop* loop = MessageLoop::current();
|
MessageLoop* loop = MessageLoop::current();
|
||||||
MOZ_ASSERT(loop);
|
MOZ_ASSERT(loop);
|
||||||
|
|
||||||
@ -255,23 +242,6 @@ DoWorkRunnable::Notify(nsITimer* aTimer)
|
|||||||
return NS_OK;
|
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<bool> guard(mCallingRunWhileCanceled);
|
|
||||||
mCallingRunWhileCanceled = true;
|
|
||||||
Run();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MessagePumpForChildProcess::Run(base::MessagePump::Delegate* aDelegate)
|
MessagePumpForChildProcess::Run(base::MessagePump::Delegate* aDelegate)
|
||||||
{
|
{
|
||||||
|
@ -31,7 +31,6 @@
|
|||||||
#include "nsStyleUtil.h"
|
#include "nsStyleUtil.h"
|
||||||
#include "mozilla/css/Declaration.h"
|
#include "mozilla/css/Declaration.h"
|
||||||
#include "nsCSSParser.h"
|
#include "nsCSSParser.h"
|
||||||
#include "nsPrintfCString.h"
|
|
||||||
#include "nsDOMClassInfoID.h"
|
#include "nsDOMClassInfoID.h"
|
||||||
#include "mozilla/dom/CSSStyleDeclarationBinding.h"
|
#include "mozilla/dom/CSSStyleDeclarationBinding.h"
|
||||||
#include "StyleRule.h"
|
#include "StyleRule.h"
|
||||||
@ -1408,52 +1407,6 @@ AppendSerializedFontSrc(const nsCSSValue& src, nsAString & aResult)
|
|||||||
aResult.Truncate(aResult.Length() - 2); // remove the last comma-space
|
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.
|
// Mapping from nsCSSFontDesc codes to nsCSSFontFaceStyleDecl fields.
|
||||||
nsCSSValue nsCSSFontFaceStyleDecl::* const
|
nsCSSValue nsCSSFontFaceStyleDecl::* const
|
||||||
nsCSSFontFaceStyleDecl::Fields[] = {
|
nsCSSFontFaceStyleDecl::Fields[] = {
|
||||||
@ -1539,7 +1492,7 @@ nsCSSFontFaceStyleDecl::GetPropertyValue(nsCSSFontDesc aFontDescID,
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
case eCSSFontDesc_UnicodeRange:
|
case eCSSFontDesc_UnicodeRange:
|
||||||
AppendSerializedUnicodeRange(val, aResult);
|
nsStyleUtil::AppendUnicodeRange(val, aResult);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
case eCSSFontDesc_UNKNOWN:
|
case eCSSFontDesc_UNKNOWN:
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "nsIContentPolicy.h"
|
#include "nsIContentPolicy.h"
|
||||||
#include "nsIContentSecurityPolicy.h"
|
#include "nsIContentSecurityPolicy.h"
|
||||||
#include "nsIURI.h"
|
#include "nsIURI.h"
|
||||||
|
#include "nsPrintfCString.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
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
|
/* static */ float
|
||||||
nsStyleUtil::ColorComponentToFloat(uint8_t aAlpha)
|
nsStyleUtil::ColorComponentToFloat(uint8_t aAlpha)
|
||||||
{
|
{
|
||||||
|
@ -64,6 +64,8 @@ public:
|
|||||||
static void AppendFontFeatureSettings(const nsCSSValue& src,
|
static void AppendFontFeatureSettings(const nsCSSValue& src,
|
||||||
nsAString& aResult);
|
nsAString& aResult);
|
||||||
|
|
||||||
|
static void AppendUnicodeRange(const nsCSSValue& aValue, nsAString& aResult);
|
||||||
|
|
||||||
static void AppendCSSNumber(float aNumber, nsAString& aResult)
|
static void AppendCSSNumber(float aNumber, nsAString& aResult)
|
||||||
{
|
{
|
||||||
aResult.AppendFloat(aNumber);
|
aResult.AppendFloat(aNumber);
|
||||||
|
@ -290,7 +290,9 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<receiver android:name="org.mozilla.gecko.ReferrerReceiver" android:exported="true">
|
<!-- Catch install referrer so we can do post-install work. -->
|
||||||
|
<receiver android:name="org.mozilla.gecko.distribution.ReferrerReceiver"
|
||||||
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="com.android.vending.INSTALL_REFERRER" />
|
<action android:name="com.android.vending.INSTALL_REFERRER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
@ -200,6 +200,13 @@ public final class GeckoProfile {
|
|||||||
getGuestDir(context).mkdir();
|
getGuestDir(context).mkdir();
|
||||||
GeckoProfile profile = getGuestProfile(context);
|
GeckoProfile profile = getGuestProfile(context);
|
||||||
profile.lock();
|
profile.lock();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now do the things that createProfileDirectory normally does --
|
||||||
|
* right now that's kicking off DB init.
|
||||||
|
*/
|
||||||
|
profile.enqueueInitialization();
|
||||||
|
|
||||||
return profile;
|
return profile;
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Log.e(LOGTAG, "Error creating guest profile", ex);
|
Log.e(LOGTAG, "Error creating guest profile", ex);
|
||||||
|
@ -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<String, String> values = new HashMap<String, String>();
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,12 +5,19 @@
|
|||||||
|
|
||||||
package org.mozilla.gecko.distribution;
|
package org.mozilla.gecko.distribution;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
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.Collections;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -19,34 +26,95 @@ import java.util.Map;
|
|||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
import java.util.jar.JarEntry;
|
||||||
|
import java.util.jar.JarInputStream;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipFile;
|
import java.util.zip.ZipFile;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLException;
|
||||||
|
|
||||||
|
import org.apache.http.protocol.HTTP;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.mozilla.gecko.GeckoAppShell;
|
import org.mozilla.gecko.GeckoAppShell;
|
||||||
import org.mozilla.gecko.GeckoEvent;
|
import org.mozilla.gecko.GeckoEvent;
|
||||||
import org.mozilla.gecko.GeckoSharedPrefs;
|
import org.mozilla.gecko.GeckoSharedPrefs;
|
||||||
|
import org.mozilla.gecko.Telemetry;
|
||||||
import org.mozilla.gecko.mozglue.RobocopTarget;
|
import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||||
import org.mozilla.gecko.util.ThreadUtils;
|
import org.mozilla.gecko.util.ThreadUtils;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.SystemClock;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles distribution file loading and fetching,
|
* Handles distribution file loading and fetching,
|
||||||
* and the corresponding hand-offs to Gecko.
|
* and the corresponding hand-offs to Gecko.
|
||||||
*/
|
*/
|
||||||
public final class Distribution {
|
@RobocopTarget
|
||||||
|
public class Distribution {
|
||||||
private static final String LOGTAG = "GeckoDistribution";
|
private static final String LOGTAG = "GeckoDistribution";
|
||||||
|
|
||||||
private static final int STATE_UNKNOWN = 0;
|
private static final int STATE_UNKNOWN = 0;
|
||||||
private static final int STATE_NONE = 1;
|
private static final int STATE_NONE = 1;
|
||||||
private static final int STATE_SET = 2;
|
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 static Distribution instance;
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
@ -70,6 +138,7 @@ public final class Distribution {
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RobocopTarget
|
||||||
public static class DistributionDescriptor {
|
public static class DistributionDescriptor {
|
||||||
public final boolean valid;
|
public final boolean valid;
|
||||||
public final String id;
|
public final String id;
|
||||||
@ -140,6 +209,7 @@ public final class Distribution {
|
|||||||
* Use <code>Context.getPackageResourcePath</code> to find an implicit
|
* Use <code>Context.getPackageResourcePath</code> to find an implicit
|
||||||
* package path. Reuses the existing Distribution if one exists.
|
* package path. Reuses the existing Distribution if one exists.
|
||||||
*/
|
*/
|
||||||
|
@RobocopTarget
|
||||||
public static void init(final Context context) {
|
public static void init(final Context context) {
|
||||||
Distribution.init(Distribution.getInstance(context));
|
Distribution.init(Distribution.getInstance(context));
|
||||||
}
|
}
|
||||||
@ -166,6 +236,17 @@ public final class Distribution {
|
|||||||
this(context, context.getPackageResourcePath(), null);
|
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.
|
* Helper to grab a file in the distribution directory.
|
||||||
*
|
*
|
||||||
@ -214,9 +295,11 @@ public final class Distribution {
|
|||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(LOGTAG, "Error getting distribution descriptor file.", e);
|
Log.e(LOGTAG, "Error getting distribution descriptor file.", e);
|
||||||
|
Telemetry.HistogramAdd(HISTOGRAM_CODE_CATEGORY, CODE_CATEGORY_MALFORMED_DISTRIBUTION);
|
||||||
return null;
|
return null;
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
Log.e(LOGTAG, "Error parsing preferences.json", e);
|
Log.e(LOGTAG, "Error parsing preferences.json", e);
|
||||||
|
Telemetry.HistogramAdd(HISTOGRAM_CODE_CATEGORY, CODE_CATEGORY_MALFORMED_DISTRIBUTION);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -232,11 +315,13 @@ public final class Distribution {
|
|||||||
return new JSONArray(getFileContents(bookmarks));
|
return new JSONArray(getFileContents(bookmarks));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(LOGTAG, "Error getting bookmarks", e);
|
Log.e(LOGTAG, "Error getting bookmarks", e);
|
||||||
|
Telemetry.HistogramAdd(HISTOGRAM_CODE_CATEGORY, CODE_CATEGORY_MALFORMED_DISTRIBUTION);
|
||||||
|
return null;
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
Log.e(LOGTAG, "Error parsing bookmarks.json", 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
|
* Postcondition: if this returns true, distributionDir will have been
|
||||||
* set and populated.
|
* set and populated.
|
||||||
*
|
*
|
||||||
|
* This method is *only* protected for use from testDistribution.
|
||||||
|
*
|
||||||
* @return true if we've set a distribution.
|
* @return true if we've set a distribution.
|
||||||
*/
|
*/
|
||||||
private boolean doInit() {
|
@RobocopTarget
|
||||||
|
protected boolean doInit() {
|
||||||
ThreadUtils.assertNotOnUiThread();
|
ThreadUtils.assertNotOnUiThread();
|
||||||
|
|
||||||
// Bail if we've already tried to initialize the distribution, and
|
// Bail if we've already tried to initialize the distribution, and
|
||||||
@ -274,8 +362,9 @@ public final class Distribution {
|
|||||||
return true;
|
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 =
|
final boolean distributionSet =
|
||||||
|
checkIntentDistribution() ||
|
||||||
checkAPKDistribution() ||
|
checkAPKDistribution() ||
|
||||||
checkSystemDistribution();
|
checkSystemDistribution();
|
||||||
|
|
||||||
@ -286,6 +375,153 @@ public final class Distribution {
|
|||||||
return distributionSet;
|
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
|
* Execute tasks that wanted to run when we were done loading
|
||||||
* the distribution. These tasks are expected to call {@link #exists()}
|
* 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
|
// We always copy to the data dir, and we only copy files from
|
||||||
// a 'distribution' subdirectory. Track our dist dir now that
|
// a 'distribution' subdirectory. Track our dist dir now that
|
||||||
// we know it.
|
// we know it.
|
||||||
this.distributionDir = new File(getDataDir(), "distribution/");
|
this.distributionDir = new File(getDataDir(), DISTRIBUTION_PATH);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -330,6 +566,41 @@ public final class Distribution {
|
|||||||
return false;
|
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.
|
* Copies the /distribution folder out of the APK and into the app's data directory.
|
||||||
* Returns true if distribution files were found and copied.
|
* Returns true if distribution files were found and copied.
|
||||||
@ -352,7 +623,7 @@ public final class Distribution {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!name.startsWith("distribution/")) {
|
if (!name.startsWith(DISTRIBUTION_PATH)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -413,6 +684,29 @@ public final class Distribution {
|
|||||||
return outFile;
|
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 <code>distributionDir</code>
|
* After calling this method, either <code>distributionDir</code>
|
||||||
* will be set, or there is no distribution in use.
|
* 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/.
|
// the APK, or it exists in /system/.
|
||||||
// Look in each location in turn.
|
// Look in each location in turn.
|
||||||
// (This could be optimized by caching the path in shared prefs.)
|
// (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()) {
|
if (copied.exists()) {
|
||||||
return this.distributionDir = copied;
|
return this.distributionDir = copied;
|
||||||
}
|
}
|
||||||
|
55
mobile/android/base/distribution/ReferrerDescriptor.java
Normal file
55
mobile/android/base/distribution/ReferrerDescriptor.java
Normal file
@ -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 + "}";
|
||||||
|
}
|
||||||
|
}
|
76
mobile/android/base/distribution/ReferrerReceiver.java
Normal file
76
mobile/android/base/distribution/ReferrerReceiver.java
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -156,6 +156,8 @@ gbjar.sources += [
|
|||||||
'db/TabsProvider.java',
|
'db/TabsProvider.java',
|
||||||
'db/TopSitesCursorWrapper.java',
|
'db/TopSitesCursorWrapper.java',
|
||||||
'distribution/Distribution.java',
|
'distribution/Distribution.java',
|
||||||
|
'distribution/ReferrerDescriptor.java',
|
||||||
|
'distribution/ReferrerReceiver.java',
|
||||||
'DoorHangerPopup.java',
|
'DoorHangerPopup.java',
|
||||||
'DynamicToolbar.java',
|
'DynamicToolbar.java',
|
||||||
'EditBookmarkDialog.java',
|
'EditBookmarkDialog.java',
|
||||||
@ -354,7 +356,6 @@ gbjar.sources += [
|
|||||||
'prompts/PromptService.java',
|
'prompts/PromptService.java',
|
||||||
'prompts/TabInput.java',
|
'prompts/TabInput.java',
|
||||||
'ReaderModeUtils.java',
|
'ReaderModeUtils.java',
|
||||||
'ReferrerReceiver.java',
|
|
||||||
'Restarter.java',
|
'Restarter.java',
|
||||||
'ScrollAnimator.java',
|
'ScrollAnimator.java',
|
||||||
'ServiceNotificationClient.java',
|
'ServiceNotificationClient.java',
|
||||||
|
@ -2,19 +2,29 @@ package org.mozilla.gecko.tests;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.jar.JarInputStream;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.mozilla.gecko.Actions;
|
import org.mozilla.gecko.Actions;
|
||||||
|
import org.mozilla.gecko.AppConstants;
|
||||||
import org.mozilla.gecko.db.BrowserContract;
|
import org.mozilla.gecko.db.BrowserContract;
|
||||||
import org.mozilla.gecko.distribution.Distribution;
|
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 org.mozilla.gecko.util.ThreadUtils;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests distribution customization.
|
* Tests distribution customization.
|
||||||
@ -28,6 +38,38 @@ import android.content.SharedPreferences;
|
|||||||
* engine.xml
|
* engine.xml
|
||||||
*/
|
*/
|
||||||
public class testDistribution extends ContentProviderTest {
|
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 String MOCK_PACKAGE = "mock-package.zip";
|
||||||
private static final int PREF_REQUEST_ID = 0x7357;
|
private static final int PREF_REQUEST_ID = 0x7357;
|
||||||
|
|
||||||
@ -65,7 +107,7 @@ public class testDistribution extends ContentProviderTest {
|
|||||||
mAsserter.dumpLog("Background task completed. Proceeding.");
|
mAsserter.dumpLog("Background task completed. Proceeding.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testDistribution() {
|
public void testDistribution() throws Exception {
|
||||||
mActivity = getActivity();
|
mActivity = getActivity();
|
||||||
|
|
||||||
String mockPackagePath = getMockPackagePath();
|
String mockPackagePath = getMockPackagePath();
|
||||||
@ -87,6 +129,90 @@ public class testDistribution extends ContentProviderTest {
|
|||||||
setTestLocale("es-MX");
|
setTestLocale("es-MX");
|
||||||
initDistribution(mockPackagePath);
|
initDistribution(mockPackagePath);
|
||||||
checkLocalizedPreferences("es-MX");
|
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.
|
// Initialize the distribution from the mock package.
|
||||||
@ -288,12 +414,16 @@ public class testDistribution extends ContentProviderTest {
|
|||||||
return mockPackagePath;
|
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() {
|
private void clearDistributionPref() {
|
||||||
mAsserter.dumpLog("Clearing distribution pref.");
|
mAsserter.dumpLog("Clearing distribution pref.");
|
||||||
SharedPreferences settings = mActivity.getSharedPreferences("GeckoApp", Activity.MODE_PRIVATE);
|
SharedPreferences settings = mActivity.getSharedPreferences("GeckoApp", Activity.MODE_PRIVATE);
|
||||||
String keyName = mActivity.getPackageName() + ".distribution_state";
|
String keyName = mActivity.getPackageName() + ".distribution_state";
|
||||||
settings.edit().remove(keyName).commit();
|
settings.edit().remove(keyName).commit();
|
||||||
|
TestableDistribution.clearReferrerDescriptorForTesting();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -11,6 +11,7 @@ jar.sources += [
|
|||||||
'src/harness/BrowserInstrumentationTestRunner.java',
|
'src/harness/BrowserInstrumentationTestRunner.java',
|
||||||
'src/harness/BrowserTestListener.java',
|
'src/harness/BrowserTestListener.java',
|
||||||
'src/tests/BrowserTestCase.java',
|
'src/tests/BrowserTestCase.java',
|
||||||
|
'src/tests/TestDistribution.java',
|
||||||
'src/tests/TestGeckoSharedPrefs.java',
|
'src/tests/TestGeckoSharedPrefs.java',
|
||||||
'src/tests/TestJarReader.java',
|
'src/tests/TestJarReader.java',
|
||||||
'src/tests/TestRawResource.java',
|
'src/tests/TestRawResource.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);
|
||||||
|
}
|
||||||
|
}
|
@ -569,7 +569,7 @@ VerifySignature(AppTrustedRoot trustedRoot, const SECItem& buffer,
|
|||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
OpenSignedAppFile(AppTrustedRoot aTrustedRoot, nsIFile* aJarFile,
|
OpenSignedAppFile(AppTrustedRoot aTrustedRoot, nsIFile* aJarFile,
|
||||||
/*out, optional */ nsIZipReader** aZipReader,
|
/*out, optional */ nsIZipReader** aZipReader,
|
||||||
/*out, optional */ nsIX509Cert3** aSignerCert)
|
/*out, optional */ nsIX509Cert** aSignerCert)
|
||||||
{
|
{
|
||||||
NS_ENSURE_ARG_POINTER(aJarFile);
|
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.
|
// but we can't do that until we switch to libpkix.
|
||||||
if (aSignerCert) {
|
if (aSignerCert) {
|
||||||
MOZ_ASSERT(CERT_LIST_HEAD(builtChain));
|
MOZ_ASSERT(CERT_LIST_HEAD(builtChain));
|
||||||
nsCOMPtr<nsIX509Cert3> signerCert =
|
nsCOMPtr<nsIX509Cert> signerCert =
|
||||||
nsNSSCertificate::Create(CERT_LIST_HEAD(builtChain)->cert);
|
nsNSSCertificate::Create(CERT_LIST_HEAD(builtChain)->cert);
|
||||||
NS_ENSURE_TRUE(signerCert, NS_ERROR_OUT_OF_MEMORY);
|
NS_ENSURE_TRUE(signerCert, NS_ERROR_OUT_OF_MEMORY);
|
||||||
signerCert.forget(aSignerCert);
|
signerCert.forget(aSignerCert);
|
||||||
@ -769,7 +769,7 @@ private:
|
|||||||
const nsCOMPtr<nsIFile> mJarFile;
|
const nsCOMPtr<nsIFile> mJarFile;
|
||||||
nsMainThreadPtrHandle<nsIOpenSignedAppFileCallback> mCallback;
|
nsMainThreadPtrHandle<nsIOpenSignedAppFileCallback> mCallback;
|
||||||
nsCOMPtr<nsIZipReader> mZipReader; // out
|
nsCOMPtr<nsIZipReader> mZipReader; // out
|
||||||
nsCOMPtr<nsIX509Cert3> mSignerCert; // out
|
nsCOMPtr<nsIX509Cert> mSignerCert; // out
|
||||||
};
|
};
|
||||||
|
|
||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
|
@ -43,7 +43,6 @@ function getDERString(cert)
|
|||||||
function getPKCS7String(cert, chainMode)
|
function getPKCS7String(cert, chainMode)
|
||||||
{
|
{
|
||||||
var length = {};
|
var length = {};
|
||||||
cert.QueryInterface(Components.interfaces.nsIX509Cert3);
|
|
||||||
var pkcs7Array = cert.exportAsCMS(chainMode, length);
|
var pkcs7Array = cert.exportAsCMS(chainMode, length);
|
||||||
var pkcs7String = '';
|
var pkcs7String = '';
|
||||||
for (var i = 0; i < pkcs7Array.length; i++) {
|
for (var i = 0; i < pkcs7Array.length; i++) {
|
||||||
@ -110,10 +109,10 @@ function exportToFile(parent, cert)
|
|||||||
content = getDERString(cert);
|
content = getDERString(cert);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
content = getPKCS7String(cert, Components.interfaces.nsIX509Cert3.CMS_CHAIN_MODE_CertOnly);
|
content = getPKCS7String(cert, Components.interfaces.nsIX509Cert.CMS_CHAIN_MODE_CertOnly);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
content = getPKCS7String(cert, Components.interfaces.nsIX509Cert3.CMS_CHAIN_MODE_CertChainWithRoot);
|
content = getPKCS7String(cert, Components.interfaces.nsIX509Cert.CMS_CHAIN_MODE_CertChainWithRoot);
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
default:
|
default:
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
const nsIX509Cert = Components.interfaces.nsIX509Cert;
|
const nsIX509Cert = Components.interfaces.nsIX509Cert;
|
||||||
const nsIX509Cert3 = Components.interfaces.nsIX509Cert3;
|
|
||||||
const nsX509CertDB = "@mozilla.org/security/x509certdb;1";
|
const nsX509CertDB = "@mozilla.org/security/x509certdb;1";
|
||||||
const nsIX509CertDB = Components.interfaces.nsIX509CertDB;
|
const nsIX509CertDB = Components.interfaces.nsIX509CertDB;
|
||||||
const nsPK11TokenDB = "@mozilla.org/security/pk11tokendb;1";
|
const nsPK11TokenDB = "@mozilla.org/security/pk11tokendb;1";
|
||||||
@ -94,14 +93,9 @@ function setWindowName()
|
|||||||
AddCertChain("treesetDump", chain, "dump_");
|
AddCertChain("treesetDump", chain, "dump_");
|
||||||
DisplayGeneralDataFromCert(cert);
|
DisplayGeneralDataFromCert(cert);
|
||||||
BuildPrettyPrint(cert);
|
BuildPrettyPrint(cert);
|
||||||
|
cert.requestUsagesArrayAsync(new listener());
|
||||||
if (cert instanceof nsIX509Cert3)
|
|
||||||
{
|
|
||||||
cert.requestUsagesArrayAsync(new listener());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function addChildrenToTree(parentTree,label,value,addTwistie)
|
function addChildrenToTree(parentTree,label,value,addTwistie)
|
||||||
{
|
{
|
||||||
var treeChild1 = document.createElement("treechildren");
|
var treeChild1 = document.createElement("treechildren");
|
||||||
@ -249,7 +243,7 @@ function DisplayGeneralDataFromCert(cert)
|
|||||||
addAttributeFromCert('validitystart', cert.validity.notBeforeLocalDay);
|
addAttributeFromCert('validitystart', cert.validity.notBeforeLocalDay);
|
||||||
// Validity end
|
// Validity end
|
||||||
addAttributeFromCert('validityend', cert.validity.notAfterLocalDay);
|
addAttributeFromCert('validityend', cert.validity.notAfterLocalDay);
|
||||||
|
|
||||||
//Now to populate the fields that correspond to the issuer.
|
//Now to populate the fields that correspond to the issuer.
|
||||||
var issuerCommonname, issuerOrg, issuerOrgUnit;
|
var issuerCommonname, issuerOrg, issuerOrgUnit;
|
||||||
issuerCommonname = cert.issuerCommonName;
|
issuerCommonname = cert.issuerCommonName;
|
||||||
@ -287,7 +281,7 @@ function getCurrentCert()
|
|||||||
&& document.getElementById('prettyprint_tab').selected) {
|
&& document.getElementById('prettyprint_tab').selected) {
|
||||||
/* if the user manually selected a cert on the Details tab,
|
/* if the user manually selected a cert on the Details tab,
|
||||||
then take that one */
|
then take that one */
|
||||||
realIndex = tree.currentIndex;
|
realIndex = tree.currentIndex;
|
||||||
} else {
|
} else {
|
||||||
/* otherwise, take the one at the bottom of the chain
|
/* otherwise, take the one at the bottom of the chain
|
||||||
(i.e. the one of the end-entity, unless we're displaying
|
(i.e. the one of the end-entity, unless we're displaying
|
||||||
|
@ -39,10 +39,7 @@ XPIDL_SOURCES += [
|
|||||||
'nsITokenPasswordDialogs.idl',
|
'nsITokenPasswordDialogs.idl',
|
||||||
'nsIUserCertPicker.idl',
|
'nsIUserCertPicker.idl',
|
||||||
'nsIX509Cert.idl',
|
'nsIX509Cert.idl',
|
||||||
'nsIX509Cert2.idl',
|
|
||||||
'nsIX509Cert3.idl',
|
|
||||||
'nsIX509CertDB.idl',
|
'nsIX509CertDB.idl',
|
||||||
'nsIX509CertDB2.idl',
|
|
||||||
'nsIX509CertList.idl',
|
'nsIX509CertList.idl',
|
||||||
'nsIX509CertValidity.idl',
|
'nsIX509CertValidity.idl',
|
||||||
]
|
]
|
||||||
|
@ -23,7 +23,7 @@ interface nsISSLStatus : nsISupports {
|
|||||||
* "unstrusted because missing or untrusted issuer"
|
* "unstrusted because missing or untrusted issuer"
|
||||||
* and
|
* and
|
||||||
* "untrusted because self signed"
|
* "untrusted because self signed"
|
||||||
* query nsIX509Cert3::isSelfSigned
|
* query nsIX509Cert::isSelfSigned
|
||||||
*/
|
*/
|
||||||
readonly attribute boolean isUntrusted;
|
readonly attribute boolean isUntrusted;
|
||||||
|
|
||||||
|
@ -9,11 +9,18 @@
|
|||||||
interface nsIArray;
|
interface nsIArray;
|
||||||
interface nsIX509CertValidity;
|
interface nsIX509CertValidity;
|
||||||
interface nsIASN1Object;
|
interface nsIASN1Object;
|
||||||
|
interface nsICertVerificationListener;
|
||||||
|
|
||||||
|
%{ C++
|
||||||
|
/* forward declaration */
|
||||||
|
typedef struct CERTCertificateStr CERTCertificate;
|
||||||
|
%}
|
||||||
|
[ptr] native CERTCertificatePtr(CERTCertificate);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This represents a X.509 certificate.
|
* This represents a X.509 certificate.
|
||||||
*/
|
*/
|
||||||
[scriptable, uuid(891d2009-b9ba-4a0d-bebe-6b3a30e33191)]
|
[scriptable, uuid(f8ed8364-ced9-4c6e-86ba-48af53c393e6)]
|
||||||
interface nsIX509Cert : nsISupports {
|
interface nsIX509Cert : nsISupports {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -33,7 +40,7 @@ interface nsIX509Cert : nsISupports {
|
|||||||
* @param length The number of strings in the returned array.
|
* @param length The number of strings in the returned array.
|
||||||
* @return An array of email addresses.
|
* @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);
|
[retval, array, size_is(length)] out wstring addresses);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -42,7 +49,7 @@ interface nsIX509Cert : nsISupports {
|
|||||||
* The behaviour for non ASCII characters is undefined.
|
* The behaviour for non ASCII characters is undefined.
|
||||||
*
|
*
|
||||||
* @param aEmailAddress The address to search for.
|
* @param aEmailAddress The address to search for.
|
||||||
*
|
*
|
||||||
* @return True if the address is contained in the certificate.
|
* @return True if the address is contained in the certificate.
|
||||||
*/
|
*/
|
||||||
boolean containsEmailAddress(in AString aEmailAddress);
|
boolean containsEmailAddress(in AString aEmailAddress);
|
||||||
@ -138,6 +145,18 @@ interface nsIX509Cert : nsISupports {
|
|||||||
const unsigned long USER_CERT = 1 << 1;
|
const unsigned long USER_CERT = 1 << 1;
|
||||||
const unsigned long EMAIL_CERT = 1 << 2;
|
const unsigned long EMAIL_CERT = 1 << 2;
|
||||||
const unsigned long SERVER_CERT = 1 << 3;
|
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.
|
* Constants for certificate verification results.
|
||||||
@ -152,7 +171,7 @@ interface nsIX509Cert : nsISupports {
|
|||||||
const unsigned long INVALID_CA = 1 << 6;
|
const unsigned long INVALID_CA = 1 << 6;
|
||||||
const unsigned long USAGE_NOT_ALLOWED = 1 << 7;
|
const unsigned long USAGE_NOT_ALLOWED = 1 << 7;
|
||||||
const unsigned long SIGNATURE_ALGORITHM_DISABLED = 1 << 8;
|
const unsigned long SIGNATURE_ALGORITHM_DISABLED = 1 << 8;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constants that describe the certified usages of a certificate.
|
* Constants that describe the certified usages of a certificate.
|
||||||
*
|
*
|
||||||
@ -172,7 +191,14 @@ interface nsIX509Cert : nsISupports {
|
|||||||
const unsigned long CERT_USAGE_AnyCA = 11;
|
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,
|
* and the issuing certificates of all involved issuers,
|
||||||
* up to the root issuer.
|
* up to the root issuer.
|
||||||
*
|
*
|
||||||
@ -192,9 +218,17 @@ interface nsIX509Cert : nsISupports {
|
|||||||
*/
|
*/
|
||||||
void getUsagesArray(in boolean localOnly,
|
void getUsagesArray(in boolean localOnly,
|
||||||
out uint32_t verified,
|
out uint32_t verified,
|
||||||
out uint32_t count,
|
out uint32_t count,
|
||||||
[array, size_is(count)] out wstring usages);
|
[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
|
* Obtain a single comma separated human readable string describing
|
||||||
* the certificate's certified usages.
|
* the certificate's certified usages.
|
||||||
@ -224,7 +258,7 @@ interface nsIX509Cert : nsISupports {
|
|||||||
[retval, array, size_is(length)] out octet data);
|
[retval, array, size_is(length)] out octet data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether two certificate instances represent the
|
* Test whether two certificate instances represent the
|
||||||
* same certificate.
|
* same certificate.
|
||||||
*
|
*
|
||||||
* @return Whether the certificates are equal
|
* @return Whether the certificates are equal
|
||||||
@ -236,4 +270,81 @@ interface nsIX509Cert : nsISupports {
|
|||||||
* digest.
|
* digest.
|
||||||
*/
|
*/
|
||||||
readonly attribute ACString sha256SubjectPublicKeyInfoDigest;
|
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);
|
||||||
};
|
};
|
||||||
|
@ -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();
|
|
||||||
};
|
|
@ -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);
|
|
||||||
};
|
|
@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
interface nsIArray;
|
interface nsIArray;
|
||||||
interface nsIX509Cert;
|
interface nsIX509Cert;
|
||||||
interface nsIX509Cert3;
|
|
||||||
interface nsIFile;
|
interface nsIFile;
|
||||||
interface nsIInterfaceRequestor;
|
interface nsIInterfaceRequestor;
|
||||||
interface nsIZipReader;
|
interface nsIZipReader;
|
||||||
@ -21,16 +20,16 @@ interface nsIX509CertList;
|
|||||||
|
|
||||||
typedef uint32_t AppTrustedRoot;
|
typedef uint32_t AppTrustedRoot;
|
||||||
|
|
||||||
[scriptable, function, uuid(0927baea-622d-4e41-a76d-255af426e7fb)]
|
[scriptable, function, uuid(5984db62-d0e5-4671-a082-799cf7271e24)]
|
||||||
interface nsIOpenSignedAppFileCallback : nsISupports
|
interface nsIOpenSignedAppFileCallback : nsISupports
|
||||||
{
|
{
|
||||||
void openSignedAppFileFinished(in nsresult rv,
|
void openSignedAppFileFinished(in nsresult rv,
|
||||||
in nsIZipReader aZipReader,
|
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.
|
* X.509 certificates stored in a database.
|
||||||
*/
|
*/
|
||||||
[scriptable, uuid(7446a5b1-84ca-491f-a2fe-0bc60a71ffa5)]
|
[scriptable, uuid(7446a5b1-84ca-491f-a2fe-0bc60a71ffa5)]
|
||||||
@ -49,12 +48,12 @@ interface nsIX509CertDB : nsISupports {
|
|||||||
* Given a nickname and optionally a token,
|
* Given a nickname and optionally a token,
|
||||||
* locate the matching certificate.
|
* locate the matching certificate.
|
||||||
*
|
*
|
||||||
* @param aToken Optionally limits the scope of
|
* @param aToken Optionally limits the scope of
|
||||||
* this function to a token device.
|
* this function to a token device.
|
||||||
* Can be null to mean any token.
|
* Can be null to mean any token.
|
||||||
* @param aNickname The nickname to be used as the key
|
* @param aNickname The nickname to be used as the key
|
||||||
* to find a certificate.
|
* to find a certificate.
|
||||||
*
|
*
|
||||||
* @return The matching certificate if found.
|
* @return The matching certificate if found.
|
||||||
*/
|
*/
|
||||||
nsIX509Cert findCertByNickname(in nsISupports aToken,
|
nsIX509Cert findCertByNickname(in nsISupports aToken,
|
||||||
@ -67,7 +66,7 @@ interface nsIX509CertDB : nsISupports {
|
|||||||
*
|
*
|
||||||
* @param aDBkey Database internal key, as obtained using
|
* @param aDBkey Database internal key, as obtained using
|
||||||
* attribute dbkey in nsIX509Cert.
|
* attribute dbkey in nsIX509Cert.
|
||||||
* @param aToken Optionally limits the scope of
|
* @param aToken Optionally limits the scope of
|
||||||
* this function to a token device.
|
* this function to a token device.
|
||||||
* Can be null to mean any token.
|
* Can be null to mean any token.
|
||||||
*/
|
*/
|
||||||
@ -79,7 +78,7 @@ interface nsIX509CertDB : nsISupports {
|
|||||||
* user, ca, or server cert - the nickname
|
* user, ca, or server cert - the nickname
|
||||||
* email cert - the email address
|
* 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.
|
* this function to a token device.
|
||||||
* Can be null to mean any token.
|
* Can be null to mean any token.
|
||||||
* @param aType Type of certificate to obtain
|
* @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 count The number of nicknames in the returned array
|
||||||
* @param certNameList The returned array of certificate nicknames.
|
* @param certNameList The returned array of certificate nicknames.
|
||||||
*/
|
*/
|
||||||
void findCertNicknames(in nsISupports aToken,
|
void findCertNicknames(in nsISupports aToken,
|
||||||
in unsigned long aType,
|
in unsigned long aType,
|
||||||
out unsigned long count,
|
out unsigned long count,
|
||||||
[array, size_is(count)] out wstring certNameList);
|
[array, size_is(count)] out wstring certNameList);
|
||||||
@ -97,7 +96,7 @@ interface nsIX509CertDB : nsISupports {
|
|||||||
*
|
*
|
||||||
* @param aNickname The nickname to be used as the key
|
* @param aNickname The nickname to be used as the key
|
||||||
* to find the certificate.
|
* to find the certificate.
|
||||||
*
|
*
|
||||||
* @return The matching certificate if found.
|
* @return The matching certificate if found.
|
||||||
*/
|
*/
|
||||||
nsIX509Cert findEmailEncryptionCert(in AString aNickname);
|
nsIX509Cert findEmailEncryptionCert(in AString aNickname);
|
||||||
@ -107,7 +106,7 @@ interface nsIX509CertDB : nsISupports {
|
|||||||
*
|
*
|
||||||
* @param aNickname The nickname to be used as the key
|
* @param aNickname The nickname to be used as the key
|
||||||
* to find the certificate.
|
* to find the certificate.
|
||||||
*
|
*
|
||||||
* @return The matching certificate if found.
|
* @return The matching certificate if found.
|
||||||
*/
|
*/
|
||||||
nsIX509Cert findEmailSigningCert(in AString aNickname);
|
nsIX509Cert findEmailSigningCert(in AString aNickname);
|
||||||
@ -115,12 +114,12 @@ interface nsIX509CertDB : nsISupports {
|
|||||||
/**
|
/**
|
||||||
* Find a certificate by email address.
|
* 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.
|
* this function to a token device.
|
||||||
* Can be null to mean any token.
|
* Can be null to mean any token.
|
||||||
* @param aEmailAddress The email address to be used as the key
|
* @param aEmailAddress The email address to be used as the key
|
||||||
* to find the certificate.
|
* to find the certificate.
|
||||||
*
|
*
|
||||||
* @return The matching certificate if found.
|
* @return The matching certificate if found.
|
||||||
*/
|
*/
|
||||||
nsIX509Cert findCertByEmailAddress(in nsISupports aToken,
|
nsIX509Cert findCertByEmailAddress(in nsISupports aToken,
|
||||||
@ -164,7 +163,7 @@ interface nsIX509CertDB : nsISupports {
|
|||||||
in nsIInterfaceRequestor ctx);
|
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.
|
* the database already contains the private key for this certificate.
|
||||||
*
|
*
|
||||||
* @param data The raw data to be imported
|
* @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
|
* 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.
|
* One call manipulates the trust for one trust type only.
|
||||||
* See the trust type constants defined within this interface.
|
* See the trust type constants defined within this interface.
|
||||||
*
|
*
|
||||||
@ -203,14 +202,14 @@ interface nsIX509CertDB : nsISupports {
|
|||||||
* characters, indicating SSL, Email, and Obj signing
|
* characters, indicating SSL, Email, and Obj signing
|
||||||
* trust.
|
* 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.
|
* Query whether a certificate is trusted for a particular use.
|
||||||
*
|
*
|
||||||
* @param cert Obtain the stored trust of this certificate.
|
* @param cert Obtain the stored trust of this certificate.
|
||||||
* @param certType The type of the certificate. See nsIX509Cert.
|
* @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.
|
* within this interface.
|
||||||
*
|
*
|
||||||
* @return Returns true if the certificate is trusted for the given use.
|
* @return Returns true if the certificate is trusted for the given use.
|
||||||
@ -222,7 +221,7 @@ interface nsIX509CertDB : nsISupports {
|
|||||||
/**
|
/**
|
||||||
* Import certificate(s) from file
|
* 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.
|
* this function to a token device.
|
||||||
* Can be null to mean any token.
|
* Can be null to mean any token.
|
||||||
* @param aFile Identifies a file that contains the certificate
|
* @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.
|
* 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.
|
* this function to a token device.
|
||||||
* Can be null to mean any token.
|
* Can be null to mean any token.
|
||||||
* @param aFile Identifies a file that contains the data
|
* @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.
|
* 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.
|
* this function to a token device.
|
||||||
* Can be null to mean any token.
|
* Can be null to mean any token.
|
||||||
* @param aFile Identifies a file that will be filled with the data
|
* @param aFile Identifies a file that will be filled with the data
|
||||||
@ -316,7 +315,7 @@ interface nsIX509CertDB : nsISupports {
|
|||||||
in nsIFile aJarFile,
|
in nsIFile aJarFile,
|
||||||
in nsIOpenSignedAppFileCallback callback);
|
in nsIOpenSignedAppFileCallback callback);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add a cert to a cert DB from a binary string.
|
* Add a cert to a cert DB from a binary string.
|
||||||
*
|
*
|
||||||
* @param certDER The raw DER encoding of a certificate.
|
* @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
|
// Clears the OCSP cache for the current certificate verification
|
||||||
// implementation.
|
// implementation.
|
||||||
void clearOCSPCache();
|
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();
|
||||||
};
|
};
|
||||||
|
@ -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();
|
|
||||||
};
|
|
||||||
|
|
@ -689,7 +689,6 @@ BlockServerCertChangeForSpdy(nsNSSSocketInfo* infoObject,
|
|||||||
// Get the existing cert. If there isn't one, then there is
|
// Get the existing cert. If there isn't one, then there is
|
||||||
// no cert change to worry about.
|
// no cert change to worry about.
|
||||||
nsCOMPtr<nsIX509Cert> cert;
|
nsCOMPtr<nsIX509Cert> cert;
|
||||||
nsCOMPtr<nsIX509Cert2> cert2;
|
|
||||||
|
|
||||||
RefPtr<nsSSLStatus> status(infoObject->SSLStatus());
|
RefPtr<nsSSLStatus> status(infoObject->SSLStatus());
|
||||||
if (!status) {
|
if (!status) {
|
||||||
@ -700,10 +699,9 @@ BlockServerCertChangeForSpdy(nsNSSSocketInfo* infoObject,
|
|||||||
}
|
}
|
||||||
|
|
||||||
status->GetServerCert(getter_AddRefs(cert));
|
status->GetServerCert(getter_AddRefs(cert));
|
||||||
cert2 = do_QueryInterface(cert);
|
if (!cert) {
|
||||||
if (!cert2) {
|
|
||||||
NS_NOTREACHED("every nsSSLStatus must have a cert"
|
NS_NOTREACHED("every nsSSLStatus must have a cert"
|
||||||
"that implements nsIX509Cert2");
|
"that implements nsIX509Cert");
|
||||||
PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0);
|
PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0);
|
||||||
return SECFailure;
|
return SECFailure;
|
||||||
}
|
}
|
||||||
@ -715,9 +713,9 @@ BlockServerCertChangeForSpdy(nsNSSSocketInfo* infoObject,
|
|||||||
"GetNegotiatedNPN() failed during renegotiation");
|
"GetNegotiatedNPN() failed during renegotiation");
|
||||||
|
|
||||||
if (NS_SUCCEEDED(rv) && !StringBeginsWith(negotiatedNPN,
|
if (NS_SUCCEEDED(rv) && !StringBeginsWith(negotiatedNPN,
|
||||||
NS_LITERAL_CSTRING("spdy/")))
|
NS_LITERAL_CSTRING("spdy/"))) {
|
||||||
return SECSuccess;
|
return SECSuccess;
|
||||||
|
}
|
||||||
// If GetNegotiatedNPN() failed we will assume spdy for safety's safe
|
// If GetNegotiatedNPN() failed we will assume spdy for safety's safe
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
|
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
|
||||||
@ -726,11 +724,12 @@ BlockServerCertChangeForSpdy(nsNSSSocketInfo* infoObject,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check to see if the cert has actually changed
|
// 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");
|
NS_ASSERTION(c, "very bad and hopefully impossible state");
|
||||||
bool sameCert = CERT_CompareCerts(c, serverCert);
|
bool sameCert = CERT_CompareCerts(c, serverCert);
|
||||||
if (sameCert)
|
if (sameCert) {
|
||||||
return SECSuccess;
|
return SECSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
// Report an error - changed cert is confirmed
|
// Report an error - changed cert is confirmed
|
||||||
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
|
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
|
||||||
|
@ -535,13 +535,9 @@ AppendErrorTextUntrusted(PRErrorCode errTrust,
|
|||||||
nsString &returnedMessage)
|
nsString &returnedMessage)
|
||||||
{
|
{
|
||||||
const char *errorID = nullptr;
|
const char *errorID = nullptr;
|
||||||
nsCOMPtr<nsIX509Cert3> cert3 = do_QueryInterface(ix509);
|
bool isSelfSigned;
|
||||||
if (cert3) {
|
if (NS_SUCCEEDED(ix509->GetIsSelfSigned(&isSelfSigned)) && isSelfSigned) {
|
||||||
bool isSelfSigned;
|
errorID = "certErrorTrust_SelfSigned";
|
||||||
if (NS_SUCCEEDED(cert3->GetIsSelfSigned(&isSelfSigned))
|
|
||||||
&& isSelfSigned) {
|
|
||||||
errorID = "certErrorTrust_SelfSigned";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!errorID) {
|
if (!errorID) {
|
||||||
@ -690,11 +686,7 @@ AppendErrorTextMismatch(const nsString &host,
|
|||||||
const char16_t *params[1];
|
const char16_t *params[1];
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
|
||||||
mozilla::pkix::ScopedCERTCertificate nssCert;
|
mozilla::pkix::ScopedCERTCertificate nssCert(ix509->GetCert());
|
||||||
|
|
||||||
nsCOMPtr<nsIX509Cert2> cert2 = do_QueryInterface(ix509, &rv);
|
|
||||||
if (cert2)
|
|
||||||
nssCert = cert2->GetCert();
|
|
||||||
|
|
||||||
if (!nssCert) {
|
if (!nssCert) {
|
||||||
// We are unable to extract the valid names, say "not valid for name".
|
// We are unable to extract the valid names, say "not valid for name".
|
||||||
|
@ -390,14 +390,11 @@ GetCertFingerprintByOidTag(nsIX509Cert *aCert,
|
|||||||
SECOidTag aOidTag,
|
SECOidTag aOidTag,
|
||||||
nsCString &fp)
|
nsCString &fp)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIX509Cert2> cert2 = do_QueryInterface(aCert);
|
|
||||||
if (!cert2)
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
|
|
||||||
mozilla::pkix::ScopedCERTCertificate nsscert(cert2->GetCert());
|
mozilla::pkix::ScopedCERTCertificate nsscert(aCert->GetCert());
|
||||||
if (!nsscert)
|
if (!nsscert) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
return GetCertFingerprintByOidTag(nsscert.get(), aOidTag, fp);
|
return GetCertFingerprintByOidTag(nsscert.get(), aOidTag, fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,24 +422,23 @@ GetCertFingerprintByDottedOidString(CERTCertificate* nsscert,
|
|||||||
|
|
||||||
static nsresult
|
static nsresult
|
||||||
GetCertFingerprintByDottedOidString(nsIX509Cert *aCert,
|
GetCertFingerprintByDottedOidString(nsIX509Cert *aCert,
|
||||||
const nsCString &dottedOid,
|
const nsCString &dottedOid,
|
||||||
nsCString &fp)
|
nsCString &fp)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIX509Cert2> cert2 = do_QueryInterface(aCert);
|
|
||||||
if (!cert2)
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
|
|
||||||
mozilla::pkix::ScopedCERTCertificate nsscert(cert2->GetCert());
|
mozilla::pkix::ScopedCERTCertificate nsscert(aCert->GetCert());
|
||||||
if (!nsscert)
|
if (!nsscert) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
return GetCertFingerprintByDottedOidString(nsscert.get(), dottedOid, fp);
|
return GetCertFingerprintByDottedOidString(nsscert.get(), dottedOid, fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsCertOverrideService::RememberValidityOverride(const nsACString & aHostName, int32_t aPort,
|
nsCertOverrideService::RememberValidityOverride(const nsACString& aHostName,
|
||||||
nsIX509Cert *aCert,
|
int32_t aPort,
|
||||||
uint32_t aOverrideBits,
|
nsIX509Cert* aCert,
|
||||||
|
uint32_t aOverrideBits,
|
||||||
bool aTemporary)
|
bool aTemporary)
|
||||||
{
|
{
|
||||||
NS_ENSURE_ARG_POINTER(aCert);
|
NS_ENSURE_ARG_POINTER(aCert);
|
||||||
@ -451,13 +447,10 @@ nsCertOverrideService::RememberValidityOverride(const nsACString & aHostName, in
|
|||||||
if (aPort < -1)
|
if (aPort < -1)
|
||||||
return NS_ERROR_INVALID_ARG;
|
return NS_ERROR_INVALID_ARG;
|
||||||
|
|
||||||
nsCOMPtr<nsIX509Cert2> cert2 = do_QueryInterface(aCert);
|
mozilla::pkix::ScopedCERTCertificate nsscert(aCert->GetCert());
|
||||||
if (!cert2)
|
if (!nsscert) {
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
|
|
||||||
mozilla::pkix::ScopedCERTCertificate nsscert(cert2->GetCert());
|
|
||||||
if (!nsscert)
|
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
char* nickname = DefaultServerNicknameForCert(nsscert.get());
|
char* nickname = DefaultServerNicknameForCert(nsscert.get());
|
||||||
if (!aTemporary && nickname && *nickname)
|
if (!aTemporary && nickname && *nickname)
|
||||||
|
@ -330,7 +330,7 @@ nsCertTree::nsCertCompareFunc
|
|||||||
nsCertTree::GetCompareFuncFromCertType(uint32_t aType)
|
nsCertTree::GetCompareFuncFromCertType(uint32_t aType)
|
||||||
{
|
{
|
||||||
switch (aType) {
|
switch (aType) {
|
||||||
case nsIX509Cert2::ANY_CERT:
|
case nsIX509Cert::ANY_CERT:
|
||||||
case nsIX509Cert::USER_CERT:
|
case nsIX509Cert::USER_CERT:
|
||||||
return CmpUserCert;
|
return CmpUserCert;
|
||||||
case nsIX509Cert::CA_CERT:
|
case nsIX509Cert::CA_CERT:
|
||||||
@ -477,7 +477,7 @@ nsCertTree::GetCertsByTypeFromCertList(CERTCertList *aCertList,
|
|||||||
!CERT_LIST_END(node, aCertList);
|
!CERT_LIST_END(node, aCertList);
|
||||||
node = CERT_LIST_NEXT(node)) {
|
node = CERT_LIST_NEXT(node)) {
|
||||||
|
|
||||||
bool wantThisCert = (aWantedType == nsIX509Cert2::ANY_CERT);
|
bool wantThisCert = (aWantedType == nsIX509Cert::ANY_CERT);
|
||||||
bool wantThisCertIfNoOverrides = false;
|
bool wantThisCertIfNoOverrides = false;
|
||||||
bool wantThisCertIfHaveOverrides = false;
|
bool wantThisCertIfHaveOverrides = false;
|
||||||
bool addOverrides = false;
|
bool addOverrides = false;
|
||||||
@ -809,12 +809,7 @@ nsCertTree::DeleteEntryObject(uint32_t index)
|
|||||||
// although there are still overrides stored,
|
// although there are still overrides stored,
|
||||||
// so, we keep the cert, but remove the trust
|
// so, we keep the cert, but remove the trust
|
||||||
|
|
||||||
mozilla::pkix::ScopedCERTCertificate nsscert;
|
mozilla::pkix::ScopedCERTCertificate nsscert(cert->GetCert());
|
||||||
|
|
||||||
nsCOMPtr<nsIX509Cert2> cert2 = do_QueryInterface(cert);
|
|
||||||
if (cert2) {
|
|
||||||
nsscert = cert2->GetCert();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nsscert) {
|
if (nsscert) {
|
||||||
CERTCertTrust trust;
|
CERTCertTrust trust;
|
||||||
@ -1235,12 +1230,8 @@ nsCertTree::GetCellText(int32_t row, nsITreeColumn* col,
|
|||||||
(certdi->mIsTemporary) ? "CertExceptionTemporary" : "CertExceptionPermanent";
|
(certdi->mIsTemporary) ? "CertExceptionTemporary" : "CertExceptionPermanent";
|
||||||
rv = mNSSComponent->GetPIPNSSBundleString(stringID, _retval);
|
rv = mNSSComponent->GetPIPNSSBundleString(stringID, _retval);
|
||||||
} else if (NS_LITERAL_STRING("typecol").Equals(colID) && cert) {
|
} else if (NS_LITERAL_STRING("typecol").Equals(colID) && cert) {
|
||||||
nsCOMPtr<nsIX509Cert2> pipCert = do_QueryInterface(cert);
|
|
||||||
uint32_t type = nsIX509Cert::UNKNOWN_CERT;
|
uint32_t type = nsIX509Cert::UNKNOWN_CERT;
|
||||||
|
rv = cert->GetCertType(&type);
|
||||||
if (pipCert) {
|
|
||||||
rv = pipCert->GetCertType(&type);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case nsIX509Cert::USER_CERT:
|
case nsIX509Cert::USER_CERT:
|
||||||
|
@ -17,7 +17,7 @@ class DispatchCertVerificationResult : public nsRunnable
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DispatchCertVerificationResult(const nsMainThreadPtrHandle<nsICertVerificationListener>& aListener,
|
DispatchCertVerificationResult(const nsMainThreadPtrHandle<nsICertVerificationListener>& aListener,
|
||||||
nsIX509Cert3* aCert,
|
nsIX509Cert* aCert,
|
||||||
nsICertVerificationResult* aResult)
|
nsICertVerificationResult* aResult)
|
||||||
: mListener(aListener)
|
: mListener(aListener)
|
||||||
, mCert(aCert)
|
, mCert(aCert)
|
||||||
@ -31,7 +31,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
nsMainThreadPtrHandle<nsICertVerificationListener> mListener;
|
nsMainThreadPtrHandle<nsICertVerificationListener> mListener;
|
||||||
nsCOMPtr<nsIX509Cert3> mCert;
|
nsCOMPtr<nsIX509Cert> mCert;
|
||||||
nsCOMPtr<nsICertVerificationResult> mResult;
|
nsCOMPtr<nsICertVerificationResult> mResult;
|
||||||
};
|
};
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
@ -63,9 +63,8 @@ void nsCertVerificationJob::Run()
|
|||||||
|
|
||||||
ires = vres;
|
ires = vres;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIX509Cert3> c3 = do_QueryInterface(mCert);
|
nsCOMPtr<nsIRunnable> r = new DispatchCertVerificationResult(mListener, mCert, ires);
|
||||||
nsCOMPtr<nsIRunnable> r = new DispatchCertVerificationResult(mListener, c3, ires);
|
|
||||||
NS_DispatchToMainThread(r);
|
NS_DispatchToMainThread(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
#include "nsPKCS12Blob.h"
|
#include "nsPKCS12Blob.h"
|
||||||
#include "nsPK11TokenDB.h"
|
#include "nsPK11TokenDB.h"
|
||||||
#include "nsIX509Cert.h"
|
#include "nsIX509Cert.h"
|
||||||
#include "nsIX509Cert3.h"
|
|
||||||
#include "nsNSSASN1Object.h"
|
#include "nsNSSASN1Object.h"
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
#include "nsXPIDLString.h"
|
#include "nsXPIDLString.h"
|
||||||
@ -68,8 +67,6 @@ NSSCleanupAutoPtrClass_WithParam(PLArenaPool, PORT_FreeArena, FalseParam, false)
|
|||||||
|
|
||||||
NS_IMPL_ISUPPORTS(nsNSSCertificate,
|
NS_IMPL_ISUPPORTS(nsNSSCertificate,
|
||||||
nsIX509Cert,
|
nsIX509Cert,
|
||||||
nsIX509Cert2,
|
|
||||||
nsIX509Cert3,
|
|
||||||
nsIIdentityInfo,
|
nsIIdentityInfo,
|
||||||
nsISerializable,
|
nsISerializable,
|
||||||
nsIClassInfo)
|
nsIClassInfo)
|
||||||
@ -1141,9 +1138,9 @@ nsNSSCertificate::ExportAsCMS(uint32_t chainMode,
|
|||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
switch (chainMode) {
|
switch (chainMode) {
|
||||||
case nsIX509Cert3::CMS_CHAIN_MODE_CertOnly:
|
case nsIX509Cert::CMS_CHAIN_MODE_CertOnly:
|
||||||
case nsIX509Cert3::CMS_CHAIN_MODE_CertChain:
|
case nsIX509Cert::CMS_CHAIN_MODE_CertChain:
|
||||||
case nsIX509Cert3::CMS_CHAIN_MODE_CertChainWithRoot:
|
case nsIX509Cert::CMS_CHAIN_MODE_CertChainWithRoot:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return NS_ERROR_INVALID_ARG;
|
return NS_ERROR_INVALID_ARG;
|
||||||
@ -1178,15 +1175,15 @@ nsNSSCertificate::ExportAsCMS(uint32_t chainMode,
|
|||||||
// Since CERT_CertChainFromCert() also includes the certificate itself,
|
// Since CERT_CertChainFromCert() also includes the certificate itself,
|
||||||
// we have to start at the issuing cert (to avoid duplicate certs
|
// we have to start at the issuing cert (to avoid duplicate certs
|
||||||
// in the SignedData).
|
// in the SignedData).
|
||||||
if (chainMode == nsIX509Cert3::CMS_CHAIN_MODE_CertChain ||
|
if (chainMode == nsIX509Cert::CMS_CHAIN_MODE_CertChain ||
|
||||||
chainMode == nsIX509Cert3::CMS_CHAIN_MODE_CertChainWithRoot) {
|
chainMode == nsIX509Cert::CMS_CHAIN_MODE_CertChainWithRoot) {
|
||||||
ScopedCERTCertificate issuerCert(
|
ScopedCERTCertificate issuerCert(
|
||||||
CERT_FindCertIssuer(mCert.get(), PR_Now(), certUsageAnyCA));
|
CERT_FindCertIssuer(mCert.get(), PR_Now(), certUsageAnyCA));
|
||||||
// the issuerCert of a self signed root is the cert itself,
|
// the issuerCert of a self signed root is the cert itself,
|
||||||
// so make sure we're not adding duplicates, again
|
// so make sure we're not adding duplicates, again
|
||||||
if (issuerCert && issuerCert != mCert.get()) {
|
if (issuerCert && issuerCert != mCert.get()) {
|
||||||
bool includeRoot =
|
bool includeRoot =
|
||||||
(chainMode == nsIX509Cert3::CMS_CHAIN_MODE_CertChainWithRoot);
|
(chainMode == nsIX509Cert::CMS_CHAIN_MODE_CertChainWithRoot);
|
||||||
ScopedCERTCertificateList certChain(
|
ScopedCERTCertificateList certChain(
|
||||||
CERT_CertChainFromCert(issuerCert, certUsageAnyCA, includeRoot));
|
CERT_CertChainFromCert(issuerCert, certUsageAnyCA, includeRoot));
|
||||||
if (certChain) {
|
if (certChain) {
|
||||||
@ -1377,11 +1374,7 @@ nsNSSCertificate::Equals(nsIX509Cert* other, bool* result)
|
|||||||
NS_ENSURE_ARG(other);
|
NS_ENSURE_ARG(other);
|
||||||
NS_ENSURE_ARG(result);
|
NS_ENSURE_ARG(result);
|
||||||
|
|
||||||
nsCOMPtr<nsIX509Cert2> other2 = do_QueryInterface(other);
|
ScopedCERTCertificate cert(other->GetCert());
|
||||||
if (!other2)
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
|
|
||||||
ScopedCERTCertificate cert(other2->GetCert());
|
|
||||||
*result = (mCert.get() == cert.get());
|
*result = (mCert.get() == cert.get());
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -1552,10 +1545,7 @@ nsNSSCertList::AddCert(nsIX509Cert* aCert)
|
|||||||
if (isAlreadyShutDown()) {
|
if (isAlreadyShutDown()) {
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
nsCOMPtr<nsIX509Cert2> nssCert = do_QueryInterface(aCert);
|
CERTCertificate* cert = aCert->GetCert();
|
||||||
CERTCertificate* cert;
|
|
||||||
|
|
||||||
cert = nssCert->GetCert();
|
|
||||||
if (!cert) {
|
if (!cert) {
|
||||||
NS_ERROR("Somehow got nullptr for mCertificate in nsNSSCertificate.");
|
NS_ERROR("Somehow got nullptr for mCertificate in nsNSSCertificate.");
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
@ -1577,8 +1567,7 @@ nsNSSCertList::DeleteCert(nsIX509Cert* aCert)
|
|||||||
if (isAlreadyShutDown()) {
|
if (isAlreadyShutDown()) {
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
nsCOMPtr<nsIX509Cert2> nssCert = do_QueryInterface(aCert);
|
CERTCertificate* cert = aCert->GetCert();
|
||||||
CERTCertificate* cert = nssCert->GetCert();
|
|
||||||
CERTCertListNode* node;
|
CERTCertListNode* node;
|
||||||
|
|
||||||
if (!cert) {
|
if (!cert) {
|
||||||
@ -1605,8 +1594,9 @@ CERTCertList*
|
|||||||
nsNSSCertList::DupCertList(CERTCertList* aCertList,
|
nsNSSCertList::DupCertList(CERTCertList* aCertList,
|
||||||
const nsNSSShutDownPreventionLock& /*proofOfLock*/)
|
const nsNSSShutDownPreventionLock& /*proofOfLock*/)
|
||||||
{
|
{
|
||||||
if (!aCertList)
|
if (!aCertList) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
CERTCertList* newList = CERT_NewCertList();
|
CERTCertList* newList = CERT_NewCertList();
|
||||||
|
|
||||||
|
@ -7,8 +7,6 @@
|
|||||||
#define _NS_NSSCERTIFICATE_H_
|
#define _NS_NSSCERTIFICATE_H_
|
||||||
|
|
||||||
#include "nsIX509Cert.h"
|
#include "nsIX509Cert.h"
|
||||||
#include "nsIX509Cert2.h"
|
|
||||||
#include "nsIX509Cert3.h"
|
|
||||||
#include "nsIX509CertDB.h"
|
#include "nsIX509CertDB.h"
|
||||||
#include "nsIX509CertList.h"
|
#include "nsIX509CertList.h"
|
||||||
#include "nsIASN1Object.h"
|
#include "nsIASN1Object.h"
|
||||||
@ -25,7 +23,7 @@ class nsAutoString;
|
|||||||
class nsINSSComponent;
|
class nsINSSComponent;
|
||||||
class nsIASN1Sequence;
|
class nsIASN1Sequence;
|
||||||
|
|
||||||
class nsNSSCertificate : public nsIX509Cert3,
|
class nsNSSCertificate : public nsIX509Cert,
|
||||||
public nsIIdentityInfo,
|
public nsIIdentityInfo,
|
||||||
public nsISerializable,
|
public nsISerializable,
|
||||||
public nsIClassInfo,
|
public nsIClassInfo,
|
||||||
@ -34,8 +32,6 @@ class nsNSSCertificate : public nsIX509Cert3,
|
|||||||
public:
|
public:
|
||||||
NS_DECL_THREADSAFE_ISUPPORTS
|
NS_DECL_THREADSAFE_ISUPPORTS
|
||||||
NS_DECL_NSIX509CERT
|
NS_DECL_NSIX509CERT
|
||||||
NS_DECL_NSIX509CERT2
|
|
||||||
NS_DECL_NSIX509CERT3
|
|
||||||
NS_DECL_NSIIDENTITYINFO
|
NS_DECL_NSIIDENTITYINFO
|
||||||
NS_DECL_NSISERIALIZABLE
|
NS_DECL_NSISERIALIZABLE
|
||||||
NS_DECL_NSICLASSINFO
|
NS_DECL_NSICLASSINFO
|
||||||
|
@ -82,7 +82,7 @@ attemptToLogInWithDefaultPassword()
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(nsNSSCertificateDB, nsIX509CertDB, nsIX509CertDB2)
|
NS_IMPL_ISUPPORTS(nsNSSCertificateDB, nsIX509CertDB)
|
||||||
|
|
||||||
nsNSSCertificateDB::nsNSSCertificateDB()
|
nsNSSCertificateDB::nsNSSCertificateDB()
|
||||||
: mBadCertsLock("nsNSSCertificateDB::mBadCertsLock")
|
: mBadCertsLock("nsNSSCertificateDB::mBadCertsLock")
|
||||||
@ -954,14 +954,15 @@ nsNSSCertificateDB::DeleteCertificate(nsIX509Cert *aCert)
|
|||||||
if (isAlreadyShutDown()) {
|
if (isAlreadyShutDown()) {
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
nsCOMPtr<nsIX509Cert2> nssCert = do_QueryInterface(aCert);
|
mozilla::pkix::ScopedCERTCertificate cert(aCert->GetCert());
|
||||||
mozilla::pkix::ScopedCERTCertificate cert(nssCert->GetCert());
|
if (!cert) {
|
||||||
if (!cert) return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
SECStatus srv = SECSuccess;
|
SECStatus srv = SECSuccess;
|
||||||
|
|
||||||
uint32_t certType;
|
uint32_t certType;
|
||||||
nssCert->GetCertType(&certType);
|
aCert->GetCertType(&certType);
|
||||||
if (NS_FAILED(nssCert->MarkForPermDeletion()))
|
if (NS_FAILED(aCert->MarkForPermDeletion()))
|
||||||
{
|
{
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
@ -998,11 +999,7 @@ nsNSSCertificateDB::SetCertTrust(nsIX509Cert *cert,
|
|||||||
}
|
}
|
||||||
nsNSSCertTrust trust;
|
nsNSSCertTrust trust;
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
nsCOMPtr<nsIX509Cert2> pipCert = do_QueryInterface(cert, &rv);
|
mozilla::pkix::ScopedCERTCertificate nsscert(cert->GetCert());
|
||||||
if (!pipCert) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
mozilla::pkix::ScopedCERTCertificate nsscert(pipCert->GetCert());
|
|
||||||
|
|
||||||
rv = attemptToLogInWithDefaultPassword();
|
rv = attemptToLogInWithDefaultPassword();
|
||||||
if (NS_WARN_IF(rv != NS_OK)) {
|
if (NS_WARN_IF(rv != NS_OK)) {
|
||||||
@ -1054,8 +1051,7 @@ nsNSSCertificateDB::IsCertTrusted(nsIX509Cert *cert,
|
|||||||
return NS_ERROR_NOT_AVAILABLE;
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
SECStatus srv;
|
SECStatus srv;
|
||||||
nsCOMPtr<nsIX509Cert2> pipCert = do_QueryInterface(cert);
|
mozilla::pkix::ScopedCERTCertificate nsscert(cert->GetCert());
|
||||||
mozilla::pkix::ScopedCERTCertificate nsscert(pipCert->GetCert());
|
|
||||||
CERTCertTrust nsstrust;
|
CERTCertTrust nsstrust;
|
||||||
srv = CERT_GetCertTrust(nsscert.get(), &nsstrust);
|
srv = CERT_GetCertTrust(nsscert.get(), &nsstrust);
|
||||||
if (srv != SECSuccess)
|
if (srv != SECSuccess)
|
||||||
@ -1284,7 +1280,8 @@ finish:
|
|||||||
|
|
||||||
/* nsIX509Cert getDefaultEmailEncryptionCert (); */
|
/* nsIX509Cert getDefaultEmailEncryptionCert (); */
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsNSSCertificateDB::FindEmailEncryptionCert(const nsAString &aNickname, nsIX509Cert **_retval)
|
nsNSSCertificateDB::FindEmailEncryptionCert(const nsAString& aNickname,
|
||||||
|
nsIX509Cert** _retval)
|
||||||
{
|
{
|
||||||
NS_ENSURE_ARG_POINTER(_retval);
|
NS_ENSURE_ARG_POINTER(_retval);
|
||||||
*_retval = nullptr;
|
*_retval = nullptr;
|
||||||
@ -1320,7 +1317,8 @@ nsNSSCertificateDB::FindEmailEncryptionCert(const nsAString &aNickname, nsIX509C
|
|||||||
|
|
||||||
/* nsIX509Cert getDefaultEmailSigningCert (); */
|
/* nsIX509Cert getDefaultEmailSigningCert (); */
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsNSSCertificateDB::FindEmailSigningCert(const nsAString &aNickname, nsIX509Cert **_retval)
|
nsNSSCertificateDB::FindEmailSigningCert(const nsAString& aNickname,
|
||||||
|
nsIX509Cert** _retval)
|
||||||
{
|
{
|
||||||
NS_ENSURE_ARG_POINTER(_retval);
|
NS_ENSURE_ARG_POINTER(_retval);
|
||||||
*_retval = nullptr;
|
*_retval = nullptr;
|
||||||
@ -1590,14 +1588,16 @@ nsNSSCertificateDB::get_default_nickname(CERTCertificate *cert,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!dummycert)
|
if (!dummycert) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
count++;
|
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);
|
NS_ENSURE_ARG_POINTER(aBase64);
|
||||||
nsCOMPtr <nsIX509Cert> newCert;
|
nsCOMPtr <nsIX509Cert> newCert;
|
||||||
@ -1668,7 +1668,7 @@ nsNSSCertificateDB::AddCert(const nsACString & aCertDER, const char *aTrust,
|
|||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsNSSCertificateDB::SetCertTrustFromString(nsIX509Cert3* cert,
|
nsNSSCertificateDB::SetCertTrustFromString(nsIX509Cert* cert,
|
||||||
const char* trustString)
|
const char* trustString)
|
||||||
{
|
{
|
||||||
CERTCertTrust trust;
|
CERTCertTrust trust;
|
||||||
@ -1761,11 +1761,10 @@ nsNSSCertificateDB::VerifyCertNow(nsIX509Cert* aCert,
|
|||||||
EnsureIdentityInfoLoaded();
|
EnsureIdentityInfoLoaded();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
nsCOMPtr<nsIX509Cert2> x509Cert = do_QueryInterface(aCert);
|
ScopedCERTCertificate nssCert(aCert->GetCert());
|
||||||
if (!x509Cert) {
|
if (!nssCert) {
|
||||||
return NS_ERROR_INVALID_ARG;
|
return NS_ERROR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
ScopedCERTCertificate nssCert(x509Cert->GetCert());
|
|
||||||
|
|
||||||
RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
|
RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
|
||||||
NS_ENSURE_TRUE(certVerifier, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(certVerifier, NS_ERROR_FAILURE);
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
#define __NSNSSCERTIFICATEDB_H__
|
#define __NSNSSCERTIFICATEDB_H__
|
||||||
|
|
||||||
#include "nsIX509CertDB.h"
|
#include "nsIX509CertDB.h"
|
||||||
#include "nsIX509CertDB2.h"
|
|
||||||
#include "nsNSSShutDown.h"
|
#include "nsNSSShutDown.h"
|
||||||
#include "mozilla/RefPtr.h"
|
#include "mozilla/RefPtr.h"
|
||||||
#include "mozilla/Mutex.h"
|
#include "mozilla/Mutex.h"
|
||||||
@ -17,14 +16,12 @@ class nsIArray;
|
|||||||
class nsRecentBadCerts;
|
class nsRecentBadCerts;
|
||||||
|
|
||||||
class nsNSSCertificateDB : public nsIX509CertDB
|
class nsNSSCertificateDB : public nsIX509CertDB
|
||||||
, public nsIX509CertDB2
|
|
||||||
, public nsNSSShutDownObject
|
, public nsNSSShutDownObject
|
||||||
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NS_DECL_THREADSAFE_ISUPPORTS
|
NS_DECL_THREADSAFE_ISUPPORTS
|
||||||
NS_DECL_NSIX509CERTDB
|
NS_DECL_NSIX509CERTDB
|
||||||
NS_DECL_NSIX509CERTDB2
|
|
||||||
|
|
||||||
nsNSSCertificateDB();
|
nsNSSCertificateDB();
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
#include "nsISupportsPrimitives.h"
|
#include "nsISupportsPrimitives.h"
|
||||||
#include "nsIX509Cert.h"
|
#include "nsIX509Cert.h"
|
||||||
#include "nsNSSCertificate.h"
|
#include "nsNSSCertificate.h"
|
||||||
#include "nsNSSCertificate.h"
|
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
#include "nsXPIDLString.h"
|
#include "nsXPIDLString.h"
|
||||||
|
|
||||||
@ -357,3 +356,55 @@ nsNSSCertificateFakeTransport::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
|
|||||||
*aClassIDNoAlloc = kNSSCertificateCID;
|
*aClassIDNoAlloc = kNSSCertificateCID;
|
||||||
return NS_OK;
|
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;
|
||||||
|
}
|
@ -387,16 +387,19 @@ nsNSSSocketInfo::JoinConnection(const nsACString& npnProtocol,
|
|||||||
|
|
||||||
ScopedCERTCertificate nssCert;
|
ScopedCERTCertificate nssCert;
|
||||||
|
|
||||||
nsCOMPtr<nsIX509Cert2> cert2 = do_QueryInterface(SSLStatus()->mServerCert);
|
nsCOMPtr<nsIX509Cert> cert(SSLStatus()->mServerCert);
|
||||||
if (cert2)
|
if (cert) {
|
||||||
nssCert = cert2->GetCert();
|
nssCert = cert->GetCert();
|
||||||
|
}
|
||||||
|
|
||||||
if (!nssCert)
|
if (!nssCert) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
if (CERT_VerifyCertName(nssCert, PromiseFlatCString(hostname).get()) !=
|
if (CERT_VerifyCertName(nssCert, PromiseFlatCString(hostname).get()) !=
|
||||||
SECSuccess)
|
SECSuccess) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
// All tests pass - this is joinable
|
// All tests pass - this is joinable
|
||||||
mJoined = true;
|
mJoined = true;
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
#include "nspr.h"
|
#include "nspr.h"
|
||||||
|
|
||||||
#include "nsIX509Cert.h"
|
#include "nsIX509Cert.h"
|
||||||
#include "nsIX509Cert3.h"
|
|
||||||
#include "nsProxyRelease.h"
|
#include "nsProxyRelease.h"
|
||||||
|
|
||||||
class nsBaseVerificationJob
|
class nsBaseVerificationJob
|
||||||
|
@ -8,9 +8,6 @@
|
|||||||
do_get_profile(); // must be called before getting nsIX509CertDB
|
do_get_profile(); // must be called before getting nsIX509CertDB
|
||||||
const certdb = Cc["@mozilla.org/security/x509certdb;1"]
|
const certdb = Cc["@mozilla.org/security/x509certdb;1"]
|
||||||
.getService(Ci.nsIX509CertDB);
|
.getService(Ci.nsIX509CertDB);
|
||||||
const certdb2 = Cc["@mozilla.org/security/x509certdb;1"]
|
|
||||||
.getService(Ci.nsIX509CertDB2);
|
|
||||||
|
|
||||||
// This is the list of certificates needed for the test
|
// This is the list of certificates needed for the test
|
||||||
// The certificates prefixed by 'int-' are intermediates
|
// The certificates prefixed by 'int-' are intermediates
|
||||||
let certList = [
|
let certList = [
|
||||||
@ -29,7 +26,7 @@ function load_cert(cert_name, trust_string) {
|
|||||||
// the ones that I am interested in.
|
// the ones that I am interested in.
|
||||||
function get_ca_array() {
|
function get_ca_array() {
|
||||||
let ret_array = new Array();
|
let ret_array = new Array();
|
||||||
let allCerts = certdb2.getCerts();
|
let allCerts = certdb.getCerts();
|
||||||
let enumerator = allCerts.getEnumerator();
|
let enumerator = allCerts.getEnumerator();
|
||||||
while (enumerator.hasMoreElements()) {
|
while (enumerator.hasMoreElements()) {
|
||||||
let cert = enumerator.getNext().QueryInterface(Ci.nsIX509Cert);
|
let cert = enumerator.getNext().QueryInterface(Ci.nsIX509Cert);
|
||||||
|
@ -25,7 +25,7 @@ let { FileUtils } = Cu.import("resource://gre/modules/FileUtils.jsm", {});
|
|||||||
let { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
|
let { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||||
|
|
||||||
let gCertDB = Cc["@mozilla.org/security/x509certdb;1"]
|
let gCertDB = Cc["@mozilla.org/security/x509certdb;1"]
|
||||||
.getService(Ci.nsIX509CertDB2);
|
.getService(Ci.nsIX509CertDB);
|
||||||
gCertDB.QueryInterface(Ci.nsIX509CertDB);
|
gCertDB.QueryInterface(Ci.nsIX509CertDB);
|
||||||
|
|
||||||
const BUILT_IN_NICK_PREFIX = "Builtin Object Token:";
|
const BUILT_IN_NICK_PREFIX = "Builtin Object Token:";
|
||||||
@ -108,8 +108,7 @@ function isBuiltinToken(tokenName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function isCertBuiltIn(cert) {
|
function isCertBuiltIn(cert) {
|
||||||
let cert3 = cert.QueryInterface(Ci.nsIX509Cert3);
|
let tokenNames = cert.getAllTokenNames({});
|
||||||
let tokenNames = cert3.getAllTokenNames({});
|
|
||||||
if (!tokenNames) {
|
if (!tokenNames) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ SOURCES += [
|
|||||||
'pkix_cert_extension_tests.cpp',
|
'pkix_cert_extension_tests.cpp',
|
||||||
'pkix_ocsp_request_tests.cpp',
|
'pkix_ocsp_request_tests.cpp',
|
||||||
'pkixcheck_CheckKeyUsage_tests.cpp',
|
'pkixcheck_CheckKeyUsage_tests.cpp',
|
||||||
|
'pkixcheck_CheckTimes_tests.cpp',
|
||||||
'pkixder_input_tests.cpp',
|
'pkixder_input_tests.cpp',
|
||||||
'pkixder_pki_types_tests.cpp',
|
'pkixder_pki_types_tests.cpp',
|
||||||
'pkixder_universal_types_tests.cpp',
|
'pkixder_universal_types_tests.cpp',
|
||||||
|
174
security/pkix/test/gtest/pkixcheck_CheckTimes_tests.cpp
Normal file
174
security/pkix/test/gtest/pkixcheck_CheckTimes_tests.cpp
Normal file
@ -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<uint8_t*>(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<uint8_t*>(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<uint8_t*>(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<uint8_t*>(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));
|
||||||
|
}
|
@ -28,9 +28,11 @@
|
|||||||
|
|
||||||
#include "pkix/bind.h"
|
#include "pkix/bind.h"
|
||||||
#include "pkixder.h"
|
#include "pkixder.h"
|
||||||
|
#include "pkixtestutil.h"
|
||||||
#include "stdint.h"
|
#include "stdint.h"
|
||||||
|
|
||||||
using namespace mozilla::pkix::der;
|
using namespace mozilla::pkix::der;
|
||||||
|
using namespace mozilla::pkix::test;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -305,23 +307,6 @@ TEST_F(pkixder_universal_types_tests, EnumeratedInvalidZeroLength)
|
|||||||
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
|
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
|
// GeneralizedTime and TimeChoice
|
||||||
//
|
//
|
||||||
|
@ -428,6 +428,23 @@ PRTimeToTimeChoice(PLArenaPool* arena, PRTime time)
|
|||||||
: GeneralizedTime);
|
: 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*
|
static SECItem*
|
||||||
SignedData(PLArenaPool* arena, const SECItem* tbsData,
|
SignedData(PLArenaPool* arena, const SECItem* tbsData,
|
||||||
SECKEYPrivateKey* privKey, SECOidTag hashAlg,
|
SECKEYPrivateKey* privKey, SECOidTag hashAlg,
|
||||||
|
@ -62,6 +62,10 @@ FILE* OpenFile(const char* dir, const char* filename, const char* mode);
|
|||||||
|
|
||||||
extern const PRTime ONE_DAY;
|
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,
|
SECStatus GenerateKeyPair(/*out*/ ScopedSECKEYPublicKey& publicKey,
|
||||||
/*out*/ ScopedSECKEYPrivateKey& privateKey);
|
/*out*/ ScopedSECKEYPrivateKey& privateKey);
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
"robocop": "TIMED_OUT",
|
"robocop": "TIMED_OUT",
|
||||||
"content/canvas/test/webgl-conformance": "bug 865443 - separate suite -- mochitest-gl",
|
"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/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",
|
"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",
|
"dom/media/tests/mochitest": "Android 2.3 only; bug 981881",
|
||||||
"layout/style/test/test_media_queries.html": "Android 2.3 aws only; bug 1030419",
|
"layout/style/test/test_media_queries.html": "Android 2.3 aws only; bug 1030419",
|
||||||
|
@ -537,20 +537,33 @@ class DeviceManagerSUT(DeviceManager):
|
|||||||
|
|
||||||
def killProcess(self, appname, sig=None):
|
def killProcess(self, appname, sig=None):
|
||||||
if sig:
|
if sig:
|
||||||
self._logger.warn("killProcess(): sig parameter unsupported on SUT")
|
pid = self.processExist(appname)
|
||||||
retries = 0
|
if pid and pid > 0:
|
||||||
while retries < self.retryLimit:
|
try:
|
||||||
try:
|
self.shellCheckOutput(['kill', '-%d' % sig, str(pid)],
|
||||||
if self.processExist(appname):
|
root=True)
|
||||||
self._runCmds([{ 'cmd': 'kill ' + appname }])
|
except DMError, err:
|
||||||
return
|
self._logger.warn("unable to kill -%d %s (pid %s)" %
|
||||||
except DMError, err:
|
(sig, appname, str(pid)))
|
||||||
retries +=1
|
self._logger.debug(err)
|
||||||
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
|
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):
|
def getTempDir(self):
|
||||||
return self._runCmds([{ 'cmd': 'tmpd' }]).strip()
|
return self._runCmds([{ 'cmd': 'tmpd' }]).strip()
|
||||||
|
@ -2959,6 +2959,28 @@
|
|||||||
"extended_statistics_ok": true,
|
"extended_statistics_ok": true,
|
||||||
"description": "PLACES: Time to calculate the md5 hash for a backup"
|
"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": {
|
"FENNEC_FAVICONS_COUNT": {
|
||||||
"expires_in_version": "never",
|
"expires_in_version": "never",
|
||||||
"kind": "exponential",
|
"kind": "exponential",
|
||||||
|
@ -39,10 +39,9 @@ const UDPSocket = CC("@mozilla.org/network/udp-socket;1",
|
|||||||
"nsIUDPSocket",
|
"nsIUDPSocket",
|
||||||
"init");
|
"init");
|
||||||
|
|
||||||
// TODO Bug 1027456: May need to reserve these with IANA
|
|
||||||
const SCAN_PORT = 50624;
|
const SCAN_PORT = 50624;
|
||||||
const UPDATE_PORT = 50625;
|
const UPDATE_PORT = 50625;
|
||||||
const ADDRESS = "224.0.0.200";
|
const ADDRESS = "224.0.0.115";
|
||||||
const REPLY_TIMEOUT = 5000;
|
const REPLY_TIMEOUT = 5000;
|
||||||
|
|
||||||
const { XPCOMUtils } = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {});
|
const { XPCOMUtils } = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {});
|
||||||
@ -158,6 +157,8 @@ function Discovery() {
|
|||||||
this._onRemoteUpdate = this._onRemoteUpdate.bind(this);
|
this._onRemoteUpdate = this._onRemoteUpdate.bind(this);
|
||||||
this._purgeMissingDevices = this._purgeMissingDevices.bind(this);
|
this._purgeMissingDevices = this._purgeMissingDevices.bind(this);
|
||||||
|
|
||||||
|
Services.obs.addObserver(this, "network-active-changed", false);
|
||||||
|
|
||||||
this._getSystemInfo();
|
this._getSystemInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,6 +296,35 @@ Discovery.prototype = {
|
|||||||
this._transports.update = null;
|
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
|
* When sending message, we can use either transport, so just pick the first
|
||||||
* one currently alive.
|
* one currently alive.
|
||||||
|
@ -363,7 +363,7 @@ let WebAudioActor = exports.WebAudioActor = protocol.ActorClass({
|
|||||||
let { caller, args, window, name } = functionCall.details;
|
let { caller, args, window, name } = functionCall.details;
|
||||||
let source = caller;
|
let source = caller;
|
||||||
let dest = args[0];
|
let dest = args[0];
|
||||||
let isAudioParam = dest instanceof window.AudioParam;
|
let isAudioParam = dest ? getConstructorName(dest) === "AudioParam" : false;
|
||||||
|
|
||||||
// audionode.connect(param)
|
// audionode.connect(param)
|
||||||
if (name === "connect" && isAudioParam) {
|
if (name === "connect" && isAudioParam) {
|
||||||
@ -433,8 +433,9 @@ let WebAudioActor = exports.WebAudioActor = protocol.ActorClass({
|
|||||||
},
|
},
|
||||||
"connect-param": {
|
"connect-param": {
|
||||||
type: "connectParam",
|
type: "connectParam",
|
||||||
source: Arg(0, "audionode"),
|
source: Option(0, "audionode"),
|
||||||
param: Arg(1, "string")
|
dest: Option(0, "audionode"),
|
||||||
|
param: Option(0, "string")
|
||||||
},
|
},
|
||||||
"change-param": {
|
"change-param": {
|
||||||
type: "changeParam",
|
type: "changeParam",
|
||||||
@ -461,12 +462,30 @@ let WebAudioActor = exports.WebAudioActor = protocol.ActorClass({
|
|||||||
// Ensure AudioNode is wrapped.
|
// Ensure AudioNode is wrapped.
|
||||||
node = new XPCNativeWrapper(node);
|
node = new XPCNativeWrapper(node);
|
||||||
|
|
||||||
|
this._instrumentParams(node);
|
||||||
|
|
||||||
let actor = new AudioNodeActor(this.conn, node);
|
let actor = new AudioNodeActor(this.conn, node);
|
||||||
this.manage(actor);
|
this.manage(actor);
|
||||||
this._nativeToActorID.set(node.id, actor.actorID);
|
this._nativeToActorID.set(node.id, actor.actorID);
|
||||||
return actor;
|
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.
|
* Takes an AudioNode and returns the stored actor for it.
|
||||||
* In some cases, we won't have an actor stored (for example,
|
* 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.
|
* Called when an audio node is connected to an audio param.
|
||||||
* Implement in bug 986705
|
|
||||||
*/
|
*/
|
||||||
_onConnectParam: function (source, dest) {
|
_onConnectParam: function (source, param) {
|
||||||
// TODO bug 986705
|
let sourceActor = this._getActorByNativeID(source.id);
|
||||||
|
let destActor = this._getActorByNativeID(param._parentID);
|
||||||
|
emit(this, "connect-param", {
|
||||||
|
source: sourceActor,
|
||||||
|
dest: destActor,
|
||||||
|
param: param._paramName
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -167,7 +167,6 @@ this.checkCert =
|
|||||||
if (!issuerCert)
|
if (!issuerCert)
|
||||||
throw new Ce(certNotBuiltInErr, Cr.NS_ERROR_ABORT);
|
throw new Ce(certNotBuiltInErr, Cr.NS_ERROR_ABORT);
|
||||||
|
|
||||||
issuerCert = issuerCert.QueryInterface(Ci.nsIX509Cert3);
|
|
||||||
var tokenNames = issuerCert.getAllTokenNames({});
|
var tokenNames = issuerCert.getAllTokenNames({});
|
||||||
|
|
||||||
if (!tokenNames || !tokenNames.some(isBuiltinToken))
|
if (!tokenNames || !tokenNames.some(isBuiltinToken))
|
||||||
|
@ -83,6 +83,7 @@ const PREFS_WHITELIST = [
|
|||||||
const PREFS_BLACKLIST = [
|
const PREFS_BLACKLIST = [
|
||||||
/^network[.]proxy[.]/,
|
/^network[.]proxy[.]/,
|
||||||
/[.]print_to_filename$/,
|
/[.]print_to_filename$/,
|
||||||
|
/^print[.]macosx[.]pagesetup/,
|
||||||
];
|
];
|
||||||
|
|
||||||
this.Troubleshoot = {
|
this.Troubleshoot = {
|
||||||
|
@ -15,120 +15,27 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include "Framebuffer.h"
|
||||||
#include <linux/fb.h>
|
|
||||||
#include <linux/kd.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "android/log.h"
|
#include "android/log.h"
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <linux/fb.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
#include "Framebuffer.h"
|
#include "nsSize.h"
|
||||||
#include "gfxContext.h"
|
|
||||||
#include "gfxImageSurface.h"
|
|
||||||
#include "gfxUtils.h"
|
|
||||||
#include "mozilla/FileUtils.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;
|
using namespace std;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
namespace Framebuffer {
|
namespace Framebuffer {
|
||||||
|
|
||||||
static int sFd = -1;
|
|
||||||
static size_t sMappedSize;
|
static size_t sMappedSize;
|
||||||
static struct fb_var_screeninfo sVi;
|
static struct fb_var_screeninfo sVi;
|
||||||
static size_t sActiveBuffer;
|
|
||||||
typedef vector<nsRefPtr<gfxImageSurface> > BufferVector;
|
|
||||||
BufferVector* sBuffers;
|
|
||||||
static gfxIntSize *sScreenSize = nullptr;
|
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<unsigned char*>(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
|
bool
|
||||||
GetSize(nsIntSize *aScreenSize) {
|
GetSize(nsIntSize *aScreenSize) {
|
||||||
// If the framebuffer has been opened, we should always have the size.
|
// If the framebuffer has been opened, we should always have the size.
|
||||||
@ -153,54 +60,5 @@ GetSize(nsIntSize *aScreenSize) {
|
|||||||
return true;
|
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<gfxContext> 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 Framebuffer
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
@ -15,48 +15,14 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class gfxASurface;
|
|
||||||
class nsIntRegion;
|
|
||||||
class nsIntSize;
|
class nsIntSize;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
namespace Framebuffer {
|
namespace Framebuffer {
|
||||||
|
|
||||||
//
|
|
||||||
// The general usage of Framebuffer is
|
|
||||||
//
|
|
||||||
// -- in initialization code --
|
|
||||||
// Open();
|
|
||||||
//
|
|
||||||
// -- ready to paint next frame --
|
|
||||||
// nsRefPtr<gfxASurface> 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
|
// Return true if the fbdev was successfully opened or the size was
|
||||||
// already cached.
|
// already cached.
|
||||||
bool GetSize(nsIntSize *aScreenSize);
|
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 Framebuffer
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
|
|
||||||
#include "libdisplay/GonkDisplay.h"
|
#include "libdisplay/GonkDisplay.h"
|
||||||
#include "Framebuffer.h"
|
#include "Framebuffer.h"
|
||||||
#include "GLContext.h" // for GLContext
|
|
||||||
#include "HwcUtils.h"
|
#include "HwcUtils.h"
|
||||||
#include "HwcComposer2D.h"
|
#include "HwcComposer2D.h"
|
||||||
|
#include "LayerScope.h"
|
||||||
#include "mozilla/layers/LayerManagerComposite.h"
|
#include "mozilla/layers/LayerManagerComposite.h"
|
||||||
#include "mozilla/layers/PLayerTransaction.h"
|
#include "mozilla/layers/PLayerTransaction.h"
|
||||||
#include "mozilla/layers/ShadowLayerUtilsGralloc.h"
|
#include "mozilla/layers/ShadowLayerUtilsGralloc.h"
|
||||||
@ -807,8 +807,12 @@ HwcComposer2D::TryRender(Layer* aRoot,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send data to LayerScope for debugging
|
||||||
|
SendtoLayerScope();
|
||||||
|
|
||||||
if (!TryHwComposition()) {
|
if (!TryHwComposition()) {
|
||||||
LOGD("H/W Composition failed");
|
LOGD("H/W Composition failed");
|
||||||
|
LayerScope::CleanLayer();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -816,4 +820,19 @@ HwcComposer2D::TryRender(Layer* aRoot,
|
|||||||
return true;
|
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
|
} // namespace mozilla
|
||||||
|
@ -97,6 +97,7 @@ private:
|
|||||||
const gfxMatrix& aParentTransform, const gfxMatrix& aGLWorldTransform);
|
const gfxMatrix& aParentTransform, const gfxMatrix& aGLWorldTransform);
|
||||||
void setCrop(HwcLayer* layer, hwc_rect_t srcCrop);
|
void setCrop(HwcLayer* layer, hwc_rect_t srcCrop);
|
||||||
void setHwcGeometry(bool aGeometryChanged);
|
void setHwcGeometry(bool aGeometryChanged);
|
||||||
|
void SendtoLayerScope();
|
||||||
|
|
||||||
HwcDevice* mHwc;
|
HwcDevice* mHwc;
|
||||||
HwcList* mList;
|
HwcList* mList;
|
||||||
|
@ -68,14 +68,10 @@ static uint32_t sScreenRotation;
|
|||||||
static uint32_t sPhysicalScreenRotation;
|
static uint32_t sPhysicalScreenRotation;
|
||||||
static nsIntRect sVirtualBounds;
|
static nsIntRect sVirtualBounds;
|
||||||
|
|
||||||
static nsRefPtr<GLContext> sGLContext;
|
|
||||||
static nsTArray<nsWindow *> sTopWindows;
|
static nsTArray<nsWindow *> sTopWindows;
|
||||||
static nsWindow *gFocusedWindow = nullptr;
|
static nsWindow *gFocusedWindow = nullptr;
|
||||||
static bool sFramebufferOpen;
|
|
||||||
static bool sUsingOMTC;
|
|
||||||
static bool sUsingHwc;
|
static bool sUsingHwc;
|
||||||
static bool sScreenInitialized;
|
static bool sScreenInitialized;
|
||||||
static nsRefPtr<gfxASurface> sOMTCSurface;
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@ -160,15 +156,11 @@ nsWindow::nsWindow()
|
|||||||
// to know the color depth, which asks our native window.
|
// to know the color depth, which asks our native window.
|
||||||
// This has to happen after other init has finished.
|
// This has to happen after other init has finished.
|
||||||
gfxPlatform::GetPlatform();
|
gfxPlatform::GetPlatform();
|
||||||
sUsingOMTC = ShouldUseOffMainThreadCompositing();
|
if (!ShouldUseOffMainThreadCompositing()) {
|
||||||
|
MOZ_CRASH("How can we render apps, then?");
|
||||||
|
}
|
||||||
//Update sUsingHwc whenever layers.composer2d.enabled changes
|
//Update sUsingHwc whenever layers.composer2d.enabled changes
|
||||||
Preferences::AddBoolVarCache(&sUsingHwc, "layers.composer2d.enabled");
|
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();
|
LayerManager* lm = targetWindow->GetLayerManager();
|
||||||
if (mozilla::layers::LayersBackend::LAYERS_CLIENT == lm->GetBackendType()) {
|
if (mozilla::layers::LayersBackend::LAYERS_CLIENT == lm->GetBackendType()) {
|
||||||
// No need to do anything, the compositor will handle drawing
|
// No need to do anything, the compositor will handle drawing
|
||||||
} else if (mozilla::layers::LayersBackend::LAYERS_BASIC == lm->GetBackendType()) {
|
|
||||||
MOZ_ASSERT(sFramebufferOpen || sUsingOMTC);
|
|
||||||
nsRefPtr<gfxASurface> targetSurface;
|
|
||||||
|
|
||||||
if(sUsingOMTC)
|
|
||||||
targetSurface = sOMTCSurface;
|
|
||||||
else
|
|
||||||
targetSurface = Framebuffer::BackBuffer();
|
|
||||||
|
|
||||||
{
|
|
||||||
nsRefPtr<gfxContext> 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 {
|
} else {
|
||||||
NS_RUNTIMEABORT("Unexpected layer manager type");
|
NS_RUNTIMEABORT("Unexpected layer manager type");
|
||||||
}
|
}
|
||||||
@ -537,12 +500,7 @@ nsWindow::GetLayerManager(PLayerTransactionChild* aShadowManager,
|
|||||||
if (mLayerManager) {
|
if (mLayerManager) {
|
||||||
// This layer manager might be used for painting outside of DoDraw(), so we need
|
// This layer manager might be used for painting outside of DoDraw(), so we need
|
||||||
// to set the correct rotation on it.
|
// to set the correct rotation on it.
|
||||||
if (mLayerManager->GetBackendType() == LayersBackend::LAYERS_BASIC) {
|
if (mLayerManager->GetBackendType() == LayersBackend::LAYERS_CLIENT) {
|
||||||
BasicLayerManager* manager =
|
|
||||||
static_cast<BasicLayerManager*>(mLayerManager.get());
|
|
||||||
manager->SetDefaultTargetConfiguration(mozilla::layers::BufferMode::BUFFER_NONE,
|
|
||||||
ScreenRotation(EffectiveScreenRotation()));
|
|
||||||
} else if (mLayerManager->GetBackendType() == LayersBackend::LAYERS_CLIENT) {
|
|
||||||
ClientLayerManager* manager =
|
ClientLayerManager* manager =
|
||||||
static_cast<ClientLayerManager*>(mLayerManager.get());
|
static_cast<ClientLayerManager*>(mLayerManager.get());
|
||||||
manager->SetDefaultTargetConfiguration(mozilla::layers::BufferMode::BUFFER_NONE,
|
manager->SetDefaultTargetConfiguration(mozilla::layers::BufferMode::BUFFER_NONE,
|
||||||
@ -561,38 +519,13 @@ nsWindow::GetLayerManager(PLayerTransactionChild* aShadowManager,
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sUsingOMTC) {
|
CreateCompositor();
|
||||||
CreateCompositor();
|
if (mCompositorParent) {
|
||||||
if (mCompositorParent) {
|
uint64_t rootLayerTreeId = mCompositorParent->RootLayerTreeId();
|
||||||
uint64_t rootLayerTreeId = mCompositorParent->RootLayerTreeId();
|
CompositorParent::SetControllerForLayerTree(rootLayerTreeId, new ParentProcessController());
|
||||||
CompositorParent::SetControllerForLayerTree(rootLayerTreeId, new ParentProcessController());
|
CompositorParent::GetAPZCTreeManager(rootLayerTreeId)->SetDPI(GetDPI());
|
||||||
CompositorParent::GetAPZCTreeManager(rootLayerTreeId)->SetDPI(GetDPI());
|
|
||||||
}
|
|
||||||
if (mLayerManager)
|
|
||||||
return mLayerManager;
|
|
||||||
}
|
}
|
||||||
|
MOZ_ASSERT(mLayerManager);
|
||||||
if (mUseLayersAcceleration) {
|
|
||||||
DebugOnly<nsIntRect> 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;
|
|
||||||
|
|
||||||
return mLayerManager;
|
return mLayerManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@ static void DeferredDestroyCompositor(CompositorParent* aCompositorParent,
|
|||||||
|
|
||||||
void nsBaseWidget::DestroyCompositor()
|
void nsBaseWidget::DestroyCompositor()
|
||||||
{
|
{
|
||||||
LayerScope::DestroyServerSocket();
|
LayerScope::DeInit();
|
||||||
|
|
||||||
if (mCompositorChild) {
|
if (mCompositorChild) {
|
||||||
mCompositorChild->SendWillStop();
|
mCompositorChild->SendWillStop();
|
||||||
@ -900,8 +900,8 @@ void nsBaseWidget::CreateCompositor(int aWidth, int aHeight)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The server socket has to be created on the main thread.
|
// Initialize LayerScope on the main thread.
|
||||||
LayerScope::CreateServerSocket();
|
LayerScope::Init();
|
||||||
|
|
||||||
mCompositorParent = NewCompositorParent(aWidth, aHeight);
|
mCompositorParent = NewCompositorParent(aWidth, aHeight);
|
||||||
MessageChannel *parentChannel = mCompositorParent->GetIPCChannel();
|
MessageChannel *parentChannel = mCompositorParent->GetIPCChannel();
|
||||||
|
@ -33,8 +33,7 @@ else:
|
|||||||
'xptcinvoke.cpp',
|
'xptcinvoke.cpp',
|
||||||
'xptcstubs.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'
|
FINAL_LIBRARY = 'xpcom_core'
|
||||||
|
|
||||||
@ -42,8 +41,3 @@ LOCAL_INCLUDES += [
|
|||||||
'../..',
|
'../..',
|
||||||
'/xpcom/reflect/xptinfo',
|
'/xpcom/reflect/xptinfo',
|
||||||
]
|
]
|
||||||
|
|
||||||
if CONFIG['TARGET_CPU'] != 'x86_64':
|
|
||||||
if not CONFIG['GNU_CXX']:
|
|
||||||
# FIXME: bug 413019
|
|
||||||
NO_PGO = True
|
|
||||||
|
Loading…
Reference in New Issue
Block a user