mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-27 04:05:32 +00:00
Merge m-i to m-c, a=merge
This commit is contained in:
commit
9a9db76df7
1
config/external/nss/nss.def
vendored
1
config/external/nss/nss.def
vendored
@ -680,3 +680,4 @@ VFY_VerifyData
|
||||
VFY_VerifyDataDirect
|
||||
VFY_VerifyDataWithAlgorithmID
|
||||
_SGN_VerifyPKCS1DigestInfo
|
||||
PK11_PQG_ParamGenV2
|
||||
|
@ -1452,13 +1452,8 @@ NS_IMETHODIMP nsPermissionManager::Observe(nsISupports *aSubject, const char *aT
|
||||
// The profile is about to change,
|
||||
// or is going away because the application is shutting down.
|
||||
mIsShuttingDown = true;
|
||||
if (!nsCRT::strcmp(someData, MOZ_UTF16("shutdown-cleanse"))) {
|
||||
// Clear the permissions file and close the db asynchronously
|
||||
RemoveAllInternal(false);
|
||||
} else {
|
||||
RemoveAllFromMemory();
|
||||
CloseDB(false);
|
||||
}
|
||||
RemoveAllFromMemory();
|
||||
CloseDB(false);
|
||||
}
|
||||
else if (!nsCRT::strcmp(aTopic, "profile-do-change")) {
|
||||
// the profile has already changed; init the db from the new location
|
||||
|
@ -80,13 +80,13 @@ _observer.prototype = {
|
||||
|
||||
// Close the cookie database. If a generator is supplied, it will be invoked
|
||||
// once the close is complete.
|
||||
function do_close_profile(generator, cleanse) {
|
||||
function do_close_profile(generator) {
|
||||
// Register an observer for db close.
|
||||
let obs = new _observer(generator, "cookie-db-closed");
|
||||
|
||||
// Close the db.
|
||||
let service = Services.cookies.QueryInterface(Ci.nsIObserver);
|
||||
service.observe(null, "profile-before-change", cleanse ? cleanse : "");
|
||||
service.observe(null, "profile-before-change", "shutdown-persist");
|
||||
}
|
||||
|
||||
// Load the cookie database. If a generator is supplied, it will be invoked
|
||||
|
@ -74,15 +74,9 @@ function do_run_test() {
|
||||
do_check_eq(Services.cookies.countCookiesFromHost(uri1.host), 4);
|
||||
do_check_eq(Services.cookies.countCookiesFromHost(uri2.host), 0);
|
||||
|
||||
// cleanse them
|
||||
do_close_profile(test_generator, "shutdown-cleanse");
|
||||
yield;
|
||||
do_load_profile();
|
||||
do_check_eq(Services.cookies.countCookiesFromHost(uri1.host), 0);
|
||||
do_check_eq(Services.cookies.countCookiesFromHost(uri2.host), 0);
|
||||
|
||||
// test with cookies set to session-only
|
||||
Services.prefs.setIntPref("network.cookie.lifetimePolicy", 2);
|
||||
Services.cookies.removeAll();
|
||||
do_set_cookies(uri1, channel1, false, [1, 2, 3, 4]);
|
||||
do_set_cookies(uri2, channel2, true, [1, 2, 3, 4]);
|
||||
|
||||
|
@ -66,15 +66,9 @@ function do_run_test() {
|
||||
do_check_eq(Services.cookies.countCookiesFromHost(uri1.host), 4);
|
||||
do_check_eq(Services.cookies.countCookiesFromHost(uri2.host), 0);
|
||||
|
||||
// cleanse them
|
||||
do_close_profile(test_generator, "shutdown-cleanse");
|
||||
yield;
|
||||
do_load_profile();
|
||||
do_check_eq(Services.cookies.countCookiesFromHost(uri1.host), 0);
|
||||
do_check_eq(Services.cookies.countCookiesFromHost(uri2.host), 0);
|
||||
|
||||
// test with third party cookies for session only.
|
||||
Services.prefs.setBoolPref("network.cookie.thirdparty.sessionOnly", true);
|
||||
Services.cookies.removeAll();
|
||||
do_set_cookies(uri1, channel2, false, [1, 2, 3, 4]);
|
||||
do_set_cookies(uri2, channel1, true, [1, 2, 3, 4]);
|
||||
|
||||
|
@ -15,9 +15,6 @@
|
||||
|
||||
#include "harfbuzz/hb.h"
|
||||
|
||||
// Chosen this as to resemble DWrite's own oblique face style.
|
||||
#define OBLIQUE_SKEW_FACTOR 0.3
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
|
@ -196,13 +196,11 @@ FT2FontEntry::CreateScaledFont(const gfxFontStyle *aStyle)
|
||||
aStyle->allowSyntheticStyle;
|
||||
|
||||
if (needsOblique) {
|
||||
const double kSkewFactor = 0.25;
|
||||
|
||||
cairo_matrix_t style;
|
||||
cairo_matrix_init(&style,
|
||||
1, //xx
|
||||
0, //yx
|
||||
-1 * kSkewFactor, //xy
|
||||
-1 * OBLIQUE_SKEW_FACTOR, //xy
|
||||
1, //yy
|
||||
0, //x0
|
||||
0); //y0
|
||||
|
@ -2271,6 +2271,18 @@ gfxFont::Measure(gfxTextRun *aTextRun,
|
||||
metrics.mBoundingBox -= gfxPoint(x, 0);
|
||||
}
|
||||
|
||||
// If the font may be rendered with a fake-italic effect, we need to allow
|
||||
// for the top-right of the glyphs being skewed to the right, and the
|
||||
// bottom-left being skewed further left.
|
||||
if (mStyle.style != NS_FONT_STYLE_NORMAL && !mFontEntry->IsItalic()) {
|
||||
gfxFloat extendLeftEdge =
|
||||
ceil(OBLIQUE_SKEW_FACTOR * metrics.mBoundingBox.YMost());
|
||||
gfxFloat extendRightEdge =
|
||||
ceil(OBLIQUE_SKEW_FACTOR * -metrics.mBoundingBox.y);
|
||||
metrics.mBoundingBox.width += extendLeftEdge + extendRightEdge;
|
||||
metrics.mBoundingBox.x -= extendLeftEdge;
|
||||
}
|
||||
|
||||
if (baselineOffset != 0) {
|
||||
metrics.mAscent -= baselineOffset;
|
||||
metrics.mDescent += baselineOffset;
|
||||
|
@ -50,6 +50,14 @@ class gfxTextContextPaint;
|
||||
|
||||
#define SMALL_CAPS_SCALE_FACTOR 0.8
|
||||
|
||||
// The skew factor used for synthetic-italic [oblique] fonts;
|
||||
// we use a platform-dependent value to harmonize with the platform's own APIs.
|
||||
#ifdef XP_WIN
|
||||
#define OBLIQUE_SKEW_FACTOR 0.3
|
||||
#else
|
||||
#define OBLIQUE_SKEW_FACTOR 0.25
|
||||
#endif
|
||||
|
||||
struct gfxTextRunDrawCallbacks;
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -168,8 +168,6 @@ gfxGDIFont::Measure(gfxTextRun *aTextRun,
|
||||
return metrics;
|
||||
}
|
||||
|
||||
#define OBLIQUE_SKEW_FACTOR 0.3
|
||||
|
||||
void
|
||||
gfxGDIFont::Initialize()
|
||||
{
|
||||
|
@ -68,13 +68,11 @@ gfxMacFont::gfxMacFont(MacOSFontEntry *aFontEntry, const gfxFontStyle *aFontStyl
|
||||
mStyle.allowSyntheticStyle;
|
||||
|
||||
if (needsOblique) {
|
||||
double skewfactor = (needsOblique ? Fix2X(kATSItalicQDSkew) : 0);
|
||||
|
||||
cairo_matrix_t style;
|
||||
cairo_matrix_init(&style,
|
||||
1, //xx
|
||||
0, //yx
|
||||
-1 * skewfactor, //xy
|
||||
-1 * OBLIQUE_SKEW_FACTOR, //xy
|
||||
1, //yy
|
||||
0, //x0
|
||||
0); //y0
|
||||
|
@ -271,6 +271,9 @@ private:
|
||||
DECL_GFX_PREF(Live, "layers.draw-layer-info", DrawLayerInfo, bool, false);
|
||||
DECL_GFX_PREF(Live, "layers.dump", LayersDump, bool, false);
|
||||
DECL_GFX_PREF(Live, "layers.dump-texture", LayersDumpTexture, bool, false);
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
DECL_GFX_PREF(Live, "layers.dump-decision", LayersDumpDecision, bool, false);
|
||||
#endif
|
||||
|
||||
// 0 is "no change" for contrast, positive values increase it, negative values
|
||||
// decrease it until we hit mid gray at -1 contrast, after that it gets weird.
|
||||
|
@ -1438,17 +1438,19 @@ gfxUtils::CopyAsDataURI(DrawTarget* aDT)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
static bool sDumpPaintList = getenv("MOZ_DUMP_PAINT_LIST") != 0;
|
||||
|
||||
/* static */ bool
|
||||
gfxUtils::DumpPaintList() {
|
||||
return sDumpPaintList || gfxPrefs::LayoutDumpDisplayList();
|
||||
gfxUtils::DumpDisplayList() {
|
||||
return gfxPrefs::LayoutDumpDisplayList();
|
||||
}
|
||||
|
||||
FILE *gfxUtils::sDumpPaintFile = stderr;
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
bool gfxUtils::sDumpPainting = getenv("MOZ_DUMP_PAINT") != 0;
|
||||
bool gfxUtils::sDumpPaintingToFile = getenv("MOZ_DUMP_PAINT_TO_FILE") != 0;
|
||||
FILE *gfxUtils::sDumpPaintFile = nullptr;
|
||||
#else
|
||||
bool gfxUtils::sDumpPainting = false;
|
||||
bool gfxUtils::sDumpPaintingToFile = false;
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -291,13 +291,11 @@ public:
|
||||
static void CopyAsDataURI(SourceSurface* aSourceSurface);
|
||||
static void CopyAsDataURI(DrawTarget* aDT);
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
static bool DumpPaintList();
|
||||
static bool DumpDisplayList();
|
||||
|
||||
static bool sDumpPainting;
|
||||
static bool sDumpPaintingToFile;
|
||||
static FILE* sDumpPaintFile;
|
||||
#endif
|
||||
};
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -359,6 +359,9 @@ MessageChannel::Connected() const
|
||||
bool
|
||||
MessageChannel::CanSend() const
|
||||
{
|
||||
if (!mMonitor) {
|
||||
return false;
|
||||
}
|
||||
MonitorAutoLock lock(*mMonitor);
|
||||
return Connected();
|
||||
}
|
||||
|
@ -4200,16 +4200,16 @@ ParseNode::getConstantValue(ExclusiveContext *cx, AllowConstantObjects allowObje
|
||||
case PNK_NULL:
|
||||
vp.setNull();
|
||||
return true;
|
||||
case PNK_SPREAD:
|
||||
return false;
|
||||
case PNK_CALLSITEOBJ:
|
||||
case PNK_ARRAY: {
|
||||
RootedValue value(cx);
|
||||
unsigned count;
|
||||
ParseNode *pn;
|
||||
|
||||
if (allowObjects == DontAllowObjects)
|
||||
return false;
|
||||
if (allowObjects == DontAllowObjects) {
|
||||
vp.setMagic(JS_GENERIC_MAGIC);
|
||||
return true;
|
||||
}
|
||||
if (allowObjects == DontAllowNestedObjects)
|
||||
allowObjects = DontAllowObjects;
|
||||
|
||||
@ -4231,6 +4231,10 @@ ParseNode::getConstantValue(ExclusiveContext *cx, AllowConstantObjects allowObje
|
||||
for (; pn; idx++, pn = pn->pn_next) {
|
||||
if (!pn->getConstantValue(cx, allowObjects, &value))
|
||||
return false;
|
||||
if (value.isMagic(JS_GENERIC_MAGIC)) {
|
||||
vp.setMagic(JS_GENERIC_MAGIC);
|
||||
return true;
|
||||
}
|
||||
id = INT_TO_JSID(idx);
|
||||
if (!JSObject::defineGeneric(cx, obj, id, value, nullptr, nullptr, JSPROP_ENUMERATE))
|
||||
return false;
|
||||
@ -4245,8 +4249,10 @@ ParseNode::getConstantValue(ExclusiveContext *cx, AllowConstantObjects allowObje
|
||||
MOZ_ASSERT(isOp(JSOP_NEWINIT));
|
||||
MOZ_ASSERT(!(pn_xflags & PNX_NONCONST));
|
||||
|
||||
if (allowObjects == DontAllowObjects)
|
||||
return false;
|
||||
if (allowObjects == DontAllowObjects) {
|
||||
vp.setMagic(JS_GENERIC_MAGIC);
|
||||
return true;
|
||||
}
|
||||
if (allowObjects == DontAllowNestedObjects)
|
||||
allowObjects = DontAllowObjects;
|
||||
|
||||
@ -4260,6 +4266,10 @@ ParseNode::getConstantValue(ExclusiveContext *cx, AllowConstantObjects allowObje
|
||||
for (ParseNode *pn = pn_head; pn; pn = pn->pn_next) {
|
||||
if (!pn->pn_right->getConstantValue(cx, allowObjects, &value))
|
||||
return false;
|
||||
if (value.isMagic(JS_GENERIC_MAGIC)) {
|
||||
vp.setMagic(JS_GENERIC_MAGIC);
|
||||
return true;
|
||||
}
|
||||
|
||||
ParseNode *pnid = pn->pn_left;
|
||||
if (pnid->isKind(PNK_NUMBER)) {
|
||||
@ -7191,28 +7201,29 @@ frontend::EmitTree(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
// If the array consists entirely of primitive values, make a
|
||||
// template object with copy on write elements that can be reused
|
||||
// every time the initializer executes.
|
||||
RootedValue value(cx);
|
||||
if (bce->emitterMode != BytecodeEmitter::SelfHosting &&
|
||||
pn->pn_count != 0 &&
|
||||
pn->getConstantValue(cx, ParseNode::DontAllowNestedObjects, &value))
|
||||
{
|
||||
// Note: the type of the template object might not yet reflect
|
||||
// that the object has copy on write elements. When the
|
||||
// interpreter or JIT compiler fetches the template, it should
|
||||
// use types::GetOrFixupCopyOnWriteObject to make sure the type
|
||||
// for the template is accurate. We don't do this here as we
|
||||
// want to use types::InitObject, which requires a finished
|
||||
// script.
|
||||
NativeObject *obj = &value.toObject().as<NativeObject>();
|
||||
if (!ObjectElements::MakeElementsCopyOnWrite(cx, obj))
|
||||
if (bce->emitterMode != BytecodeEmitter::SelfHosting && pn->pn_count != 0) {
|
||||
RootedValue value(cx);
|
||||
if (!pn->getConstantValue(cx, ParseNode::DontAllowNestedObjects, &value))
|
||||
return false;
|
||||
if (!value.isMagic(JS_GENERIC_MAGIC)) {
|
||||
// Note: the type of the template object might not yet reflect
|
||||
// that the object has copy on write elements. When the
|
||||
// interpreter or JIT compiler fetches the template, it should
|
||||
// use types::GetOrFixupCopyOnWriteObject to make sure the type
|
||||
// for the template is accurate. We don't do this here as we
|
||||
// want to use types::InitObject, which requires a finished
|
||||
// script.
|
||||
NativeObject *obj = &value.toObject().as<NativeObject>();
|
||||
if (!ObjectElements::MakeElementsCopyOnWrite(cx, obj))
|
||||
return false;
|
||||
|
||||
ObjectBox *objbox = bce->parser->newObjectBox(obj);
|
||||
if (!objbox)
|
||||
return false;
|
||||
ObjectBox *objbox = bce->parser->newObjectBox(obj);
|
||||
if (!objbox)
|
||||
return false;
|
||||
|
||||
ok = EmitObjectOp(cx, objbox, JSOP_NEWARRAY_COPYONWRITE, bce);
|
||||
break;
|
||||
ok = EmitObjectOp(cx, objbox, JSOP_NEWARRAY_COPYONWRITE, bce);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -836,7 +836,7 @@ class GCRuntime
|
||||
|
||||
bool poked;
|
||||
|
||||
volatile js::HeapState heapState;
|
||||
mozilla::Atomic<js::HeapState> heapState;
|
||||
|
||||
/*
|
||||
* ForkJoin workers enter and leave GC independently; this counter
|
||||
|
@ -434,6 +434,15 @@ namespace gc {
|
||||
template <typename T>
|
||||
static bool
|
||||
IsMarked(T **thingp)
|
||||
{
|
||||
MOZ_ASSERT_IF(!ThingIsPermanentAtom(*thingp),
|
||||
CurrentThreadCanAccessRuntime((*thingp)->runtimeFromMainThread()));
|
||||
return IsMarkedFromAnyThread(thingp);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static bool
|
||||
IsMarkedFromAnyThread(T **thingp)
|
||||
{
|
||||
MOZ_ASSERT(thingp);
|
||||
MOZ_ASSERT(*thingp);
|
||||
@ -456,8 +465,8 @@ IsMarked(T **thingp)
|
||||
}
|
||||
}
|
||||
|
||||
Zone *zone = (*thingp)->asTenured().zone();
|
||||
if (!zone->isCollecting() || zone->isGCFinished())
|
||||
Zone *zone = (*thingp)->asTenured().zoneFromAnyThread();
|
||||
if (!zone->isCollectingFromAnyThread() || zone->isGCFinished())
|
||||
return true;
|
||||
#ifdef JSGC_COMPACTING
|
||||
if (zone->isGCCompacting() && IsForwarded(*thingp))
|
||||
@ -598,6 +607,12 @@ Is##base##Marked(type **thingp)
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
Is##base##MarkedFromAnyThread(BarrieredBase<type*> *thingp) \
|
||||
{ \
|
||||
return IsMarkedFromAnyThread<type>(thingp->unsafeGet()); \
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
Is##base##Marked(BarrieredBase<type*> *thingp) \
|
||||
{ \
|
||||
return IsMarked<type>(thingp->unsafeGet()); \
|
||||
|
@ -97,6 +97,7 @@ void Mark##base##Range(JSTracer *trc, size_t len, HeapPtr<type*> *thing, const c
|
||||
void Mark##base##RootRange(JSTracer *trc, size_t len, type **thing, const char *name); \
|
||||
bool Is##base##Marked(type **thingp); \
|
||||
bool Is##base##Marked(BarrieredBase<type*> *thingp); \
|
||||
bool Is##base##MarkedFromAnyThread(BarrieredBase<type*> *thingp); \
|
||||
bool Is##base##AboutToBeFinalized(type **thingp); \
|
||||
bool Is##base##AboutToBeFinalizedFromAnyThread(type **thingp); \
|
||||
bool Is##base##AboutToBeFinalized(BarrieredBase<type*> *thingp); \
|
||||
|
10
js/src/jit-test/tests/basic/bug1113980.js
Normal file
10
js/src/jit-test/tests/basic/bug1113980.js
Normal file
@ -0,0 +1,10 @@
|
||||
var p = Proxy.create({
|
||||
getOwnPropertyDescriptor: function() {
|
||||
return {value: 1, configurable: true, writable: true};
|
||||
},
|
||||
defineProperty: function() {
|
||||
}
|
||||
}, null);
|
||||
|
||||
var o = Object.create(p);
|
||||
o.a = 1;
|
@ -182,8 +182,10 @@ js::SetPropertyIgnoringNamedGetter(JSContext *cx, const BaseProxyHandler *handle
|
||||
}
|
||||
desc.value().set(vp.get());
|
||||
|
||||
if (descIsOwn)
|
||||
return handler->defineProperty(cx, receiver, id, desc);
|
||||
if (descIsOwn) {
|
||||
MOZ_ASSERT(desc.object() == proxy);
|
||||
return handler->defineProperty(cx, proxy, id, desc);
|
||||
}
|
||||
return JSObject::defineGeneric(cx, receiver, id, desc.value(),
|
||||
desc.getter(), desc.setter(), desc.attributes());
|
||||
}
|
||||
|
@ -773,7 +773,7 @@ RegExpCompartment::sweep(JSRuntime *rt)
|
||||
// the RegExpShared if it was accidentally marked earlier but wasn't
|
||||
// marked by the current trace.
|
||||
bool keep = shared->marked() &&
|
||||
!IsStringAboutToBeFinalizedFromAnyThread(shared->source.unsafeGet());
|
||||
IsStringMarkedFromAnyThread(&shared->source);
|
||||
for (size_t i = 0; i < ArrayLength(shared->compilationArray); i++) {
|
||||
RegExpShared::RegExpCompilation &compilation = shared->compilationArray[i];
|
||||
if (compilation.jitCode &&
|
||||
|
@ -455,7 +455,6 @@ DisplayItemClip::Shutdown()
|
||||
gNoClip = nullptr;
|
||||
}
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
nsCString
|
||||
DisplayItemClip::ToString() const
|
||||
{
|
||||
@ -473,6 +472,5 @@ DisplayItemClip::ToString() const
|
||||
}
|
||||
return str;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
@ -164,9 +164,7 @@ public:
|
||||
|
||||
void MoveBy(nsPoint aPoint);
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
nsCString ToString() const;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Find the largest N such that the first N rounded rects in 'this' are
|
||||
|
@ -278,8 +278,10 @@ public:
|
||||
nsAutoCString mLog;
|
||||
|
||||
#define FLB_LOG_PAINTED_LAYER_DECISION(pld, ...) \
|
||||
pld->mLog.AppendPrintf("\t\t\t\t"); \
|
||||
pld->mLog.AppendPrintf(__VA_ARGS__);
|
||||
if (gfxPrefs::LayersDumpDecision()) { \
|
||||
pld->mLog.AppendPrintf("\t\t\t\t"); \
|
||||
pld->mLog.AppendPrintf(__VA_ARGS__); \
|
||||
}
|
||||
#else
|
||||
#define FLB_LOG_PAINTED_LAYER_DECISION(...)
|
||||
#endif
|
||||
@ -4423,7 +4425,6 @@ FrameLayerBuilder::PaintItems(nsTArray<ClippedDisplayItem>& aItems,
|
||||
nsIFrame* frame = cdi->mItem->Frame();
|
||||
frame->AddStateBits(NS_FRAME_PAINTED_THEBES);
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
|
||||
if (gfxUtils::sDumpPainting) {
|
||||
DebugPaintItem(aDrawTarget, aPresContext, cdi->mItem, aBuilder);
|
||||
} else {
|
||||
@ -4681,13 +4682,11 @@ FrameLayerBuilder::CheckDOMModified()
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
/* static */ void
|
||||
FrameLayerBuilder::DumpRetainedLayerTree(LayerManager* aManager, std::stringstream& aStream, bool aDumpHtml)
|
||||
{
|
||||
aManager->Dump(aStream, "", aDumpHtml);
|
||||
}
|
||||
#endif
|
||||
|
||||
gfx::Rect
|
||||
CalculateBounds(const nsTArray<DisplayItemClip::RoundedRect>& aRects, int32_t A2D)
|
||||
|
@ -268,13 +268,11 @@ public:
|
||||
const nsIntRegion& aRegionToInvalidate,
|
||||
void* aCallbackData);
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
/**
|
||||
* Dumps this FrameLayerBuilder's retained layer manager's retained
|
||||
* layer tree. Defaults to dumping to stdout in non-HTML format.
|
||||
*/
|
||||
static void DumpRetainedLayerTree(LayerManager* aManager, std::stringstream& aStream, bool aDumpHtml = false);
|
||||
#endif
|
||||
|
||||
/******* PRIVATE METHODS to FrameLayerBuilder.cpp ********/
|
||||
/* These are only in the public section because they need
|
||||
|
@ -2052,7 +2052,6 @@ nsDisplaySolidColor::Paint(nsDisplayListBuilder* aBuilder,
|
||||
drawTarget->FillRect(rect, ColorPattern(ToDeviceColor(mColor)));
|
||||
}
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
void
|
||||
nsDisplaySolidColor::WriteDebugInfo(std::stringstream& aStream)
|
||||
{
|
||||
@ -2062,7 +2061,6 @@ nsDisplaySolidColor::WriteDebugInfo(std::stringstream& aStream)
|
||||
<< (int)NS_GET_B(mColor) << ","
|
||||
<< (int)NS_GET_A(mColor) << ")";
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
RegisterThemeGeometry(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
|
||||
@ -2768,13 +2766,11 @@ nsDisplayThemedBackground::~nsDisplayThemedBackground()
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
void
|
||||
nsDisplayThemedBackground::WriteDebugInfo(std::stringstream& aStream)
|
||||
{
|
||||
aStream << " (themed, appearance:" << (int)mAppearance << ")";
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
nsDisplayThemedBackground::HitTest(nsDisplayListBuilder* aBuilder,
|
||||
@ -2973,14 +2969,12 @@ nsDisplayBackgroundColor::HitTest(nsDisplayListBuilder* aBuilder,
|
||||
aOutFrames->AppendElement(mFrame);
|
||||
}
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
void
|
||||
nsDisplayBackgroundColor::WriteDebugInfo(std::stringstream& aStream)
|
||||
{
|
||||
aStream << " (rgba " << mColor.r << "," << mColor.g << ","
|
||||
<< mColor.b << "," << mColor.a << ")";
|
||||
}
|
||||
#endif
|
||||
|
||||
already_AddRefed<Layer>
|
||||
nsDisplayClearBackground::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
@ -3098,7 +3092,6 @@ nsDisplayLayerEventRegions::AddInactiveScrollPort(const nsRect& aRect)
|
||||
mDispatchToContentHitRegion.Or(mDispatchToContentHitRegion, aRect);
|
||||
}
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
void
|
||||
nsDisplayLayerEventRegions::WriteDebugInfo(std::stringstream& aStream)
|
||||
{
|
||||
@ -3112,7 +3105,6 @@ nsDisplayLayerEventRegions::WriteDebugInfo(std::stringstream& aStream)
|
||||
AppendToString(aStream, mDispatchToContentHitRegion, " (dispatchToContentRegion ", ")");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
nsDisplayCaret::nsDisplayCaret(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aCaretFrame)
|
||||
@ -3810,13 +3802,11 @@ bool nsDisplayOpacity::TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* a
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
void
|
||||
nsDisplayOpacity::WriteDebugInfo(std::stringstream& aStream)
|
||||
{
|
||||
aStream << " (opacity " << mOpacity << ")";
|
||||
}
|
||||
#endif
|
||||
|
||||
nsDisplayMixBlendMode::nsDisplayMixBlendMode(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame, nsDisplayList* aList,
|
||||
@ -4575,14 +4565,12 @@ nsDisplayScrollLayer::GetScrollLayerCount()
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
void
|
||||
nsDisplayScrollLayer::WriteDebugInfo(std::stringstream& aStream)
|
||||
{
|
||||
aStream << " (scrollframe " << mScrollFrame
|
||||
<< " scrolledFrame " << mScrolledFrame << ")";
|
||||
}
|
||||
#endif
|
||||
|
||||
nsDisplayScrollInfoLayer::nsDisplayScrollInfoLayer(
|
||||
nsDisplayListBuilder* aBuilder,
|
||||
@ -5763,13 +5751,11 @@ bool nsDisplayTransform::UntransformVisibleRect(nsDisplayListBuilder* aBuilder,
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
void
|
||||
nsDisplayTransform::WriteDebugInfo(std::stringstream& aStream)
|
||||
{
|
||||
AppendToString(aStream, GetTransform());
|
||||
}
|
||||
#endif
|
||||
|
||||
nsDisplaySVGEffects::nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame, nsDisplayList* aList)
|
||||
|
@ -99,14 +99,9 @@ typedef mozilla::EnumSet<mozilla::gfx::CompositionOp> BlendModeSet;
|
||||
*/
|
||||
|
||||
// All types are defined in nsDisplayItemTypes.h
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
#define NS_DISPLAY_DECL_NAME(n, e) \
|
||||
virtual const char* Name() { return n; } \
|
||||
virtual Type GetType() { return e; }
|
||||
#else
|
||||
#define NS_DISPLAY_DECL_NAME(n, e) \
|
||||
virtual Type GetType() { return e; }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This manages a display list and is passed as a parameter to
|
||||
@ -1378,15 +1373,13 @@ public:
|
||||
const DisplayItemClip* aClip) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
|
||||
/**
|
||||
* For debugging and stuff
|
||||
*/
|
||||
virtual const char* Name() = 0;
|
||||
|
||||
virtual void WriteDebugInfo(std::stringstream& aStream) {}
|
||||
#endif
|
||||
|
||||
nsDisplayItem* GetAbove() { return mAbove; }
|
||||
|
||||
@ -1949,9 +1942,7 @@ public:
|
||||
nsDisplayGeneric(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
||||
PaintCallback aPaint, const char* aName, Type aType)
|
||||
: nsDisplayItem(aBuilder, aFrame), mPaint(aPaint)
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
, mName(aName)
|
||||
#endif
|
||||
, mType(aType)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsDisplayGeneric);
|
||||
@ -1978,9 +1969,7 @@ public:
|
||||
|
||||
protected:
|
||||
PaintCallback mPaint;
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
const char* mName;
|
||||
#endif
|
||||
Type mType;
|
||||
};
|
||||
|
||||
@ -2204,9 +2193,7 @@ public:
|
||||
ComputeInvalidationRegionDifference(aBuilder, geometry, aInvalidRegion);
|
||||
}
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
virtual void WriteDebugInfo(std::stringstream& aStream) MOZ_OVERRIDE;
|
||||
#endif
|
||||
|
||||
NS_DISPLAY_DECL_NAME("SolidColor", TYPE_SOLID_COLOR)
|
||||
|
||||
@ -2365,9 +2352,7 @@ public:
|
||||
const nsDisplayItemGeometry* aGeometry,
|
||||
nsRegion* aInvalidRegion) MOZ_OVERRIDE;
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
virtual void WriteDebugInfo(std::stringstream& aStream) MOZ_OVERRIDE;
|
||||
#endif
|
||||
protected:
|
||||
nsRect GetBoundsInternal();
|
||||
|
||||
@ -2428,9 +2413,7 @@ public:
|
||||
}
|
||||
|
||||
NS_DISPLAY_DECL_NAME("BackgroundColor", TYPE_BACKGROUND_COLOR)
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
virtual void WriteDebugInfo(std::stringstream& aStream) MOZ_OVERRIDE;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
const nsStyleBackground* mBackgroundStyle;
|
||||
@ -2669,9 +2652,7 @@ public:
|
||||
const nsRegion& MaybeHitRegion() { return mMaybeHitRegion; }
|
||||
const nsRegion& DispatchToContentHitRegion() { return mDispatchToContentHitRegion; }
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
virtual void WriteDebugInfo(std::stringstream& aStream) MOZ_OVERRIDE;
|
||||
#endif
|
||||
|
||||
private:
|
||||
// Relative to aFrame's reference frame.
|
||||
@ -2879,9 +2860,7 @@ public:
|
||||
virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
|
||||
bool NeedsActiveLayer(nsDisplayListBuilder* aBuilder);
|
||||
NS_DISPLAY_DECL_NAME("Opacity", TYPE_OPACITY)
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
virtual void WriteDebugInfo(std::stringstream& aStream) MOZ_OVERRIDE;
|
||||
#endif
|
||||
|
||||
bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
|
||||
|
||||
@ -3177,9 +3156,7 @@ public:
|
||||
virtual nsIFrame* GetScrollFrame() { return mScrollFrame; }
|
||||
virtual nsIFrame* GetScrolledFrame() { return mScrolledFrame; }
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
virtual void WriteDebugInfo(std::stringstream& aStream) MOZ_OVERRIDE;
|
||||
#endif
|
||||
|
||||
bool IsDisplayPortOpaque() { return mDisplayPortContentsOpaque; }
|
||||
|
||||
@ -3588,9 +3565,7 @@ public:
|
||||
*/
|
||||
bool ShouldPrerender(nsDisplayListBuilder* aBuilder);
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
virtual void WriteDebugInfo(std::stringstream& aStream) MOZ_OVERRIDE;
|
||||
#endif
|
||||
|
||||
private:
|
||||
void SetReferenceFrameToAncestor(nsDisplayListBuilder* aBuilder);
|
||||
|
@ -121,7 +121,6 @@ nsLayoutDebugger::GetStyleSize(nsIPresShell* aPresentation,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
std::ostream& operator<<(std::ostream& os, const nsPrintfCString& rhs) {
|
||||
os << rhs.get();
|
||||
return os;
|
||||
@ -158,12 +157,14 @@ PrintDisplayItemTo(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem,
|
||||
nsDisplayList* list = aItem->GetChildren();
|
||||
const DisplayItemClip& clip = aItem->GetClip();
|
||||
nsRegion opaque = aItem->GetOpaqueRegion(aBuilder, &snap);
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
if (aDumpHtml && aItem->Painted()) {
|
||||
nsCString string(aItem->Name());
|
||||
string.Append('-');
|
||||
string.AppendInt((uint64_t)aItem);
|
||||
aStream << nsPrintfCString("<a href=\"javascript:ViewImage('%s')\">", string.BeginReading());
|
||||
}
|
||||
#endif
|
||||
aStream << nsPrintfCString("%s p=0x%p f=0x%p(%s) %sbounds(%d,%d,%d,%d) layerBounds(%d,%d,%d,%d) visible(%d,%d,%d,%d) componentAlpha(%d,%d,%d,%d) clip(%s) %s",
|
||||
aItem->Name(), aItem, (void*)f, NS_ConvertUTF16toUTF8(fName).get(),
|
||||
(aItem->ZIndex() ? nsPrintfCString("z=%d ", aItem->ZIndex()).get() : ""),
|
||||
@ -197,9 +198,11 @@ PrintDisplayItemTo(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem,
|
||||
// Display item specific debug info
|
||||
aItem->WriteDebugInfo(aStream);
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
if (aDumpHtml && aItem->Painted()) {
|
||||
aStream << "</a>";
|
||||
}
|
||||
#endif
|
||||
uint32_t key = aItem->GetPerFrameKey();
|
||||
Layer* layer = mozilla::FrameLayerBuilder::GetDebugOldLayerFor(f, key);
|
||||
if (layer) {
|
||||
@ -209,11 +212,13 @@ PrintDisplayItemTo(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem,
|
||||
aStream << nsPrintfCString(" layer=0x%p", layer);
|
||||
}
|
||||
}
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
if (aItem->GetType() == nsDisplayItem::TYPE_SVG_EFFECTS) {
|
||||
nsCString str;
|
||||
(static_cast<nsDisplaySVGEffects*>(aItem))->PrintEffects(str);
|
||||
aStream << str.get();
|
||||
}
|
||||
#endif
|
||||
aStream << "\n";
|
||||
|
||||
if (aDumpSublist && list) {
|
||||
@ -263,6 +268,7 @@ nsFrame::PrintDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
PrintDisplayListTo(aBuilder, aList, aStream, 0, aDumpHtml);
|
||||
}
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
static void
|
||||
PrintDisplayListSetItem(nsDisplayListBuilder* aBuilder,
|
||||
const char* aItemName,
|
||||
|
@ -3103,14 +3103,17 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
|
||||
willFlushRetainedLayers = true;
|
||||
}
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
FILE* savedDumpFile = gfxUtils::sDumpPaintFile;
|
||||
|
||||
bool profilerNeedsDisplayList = profiler_feature_active("displaylistdump");
|
||||
bool consoleNeedsDisplayList = gfxUtils::DumpPaintList() || gfxUtils::sDumpPainting;
|
||||
bool consoleNeedsDisplayList = gfxUtils::DumpDisplayList() || gfxUtils::sDumpPainting;
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
FILE* savedDumpFile = gfxUtils::sDumpPaintFile;
|
||||
#endif
|
||||
|
||||
UniquePtr<std::stringstream> ss = MakeUnique<std::stringstream>();
|
||||
UniquePtr<std::stringstream> ss;
|
||||
if (consoleNeedsDisplayList || profilerNeedsDisplayList) {
|
||||
ss = MakeUnique<std::stringstream>();
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
if (gfxUtils::sDumpPaintingToFile) {
|
||||
nsCString string("dump-");
|
||||
string.AppendInt(gPaintCount);
|
||||
@ -3122,6 +3125,7 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
|
||||
if (gfxUtils::sDumpPaintingToFile) {
|
||||
*ss << "<html><head><script>var array = {}; function ViewImage(index) { window.location = array[index]; }</script></head><body>";
|
||||
}
|
||||
#endif
|
||||
*ss << nsPrintfCString("Painting --- before optimization (dirty %d,%d,%d,%d):\n",
|
||||
dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height).get();
|
||||
nsFrame::PrintDisplayList(&builder, list, *ss, gfxUtils::sDumpPaintingToFile);
|
||||
@ -3139,7 +3143,6 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
|
||||
ss = MakeUnique<std::stringstream>();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t flags = nsDisplayList::PAINT_DEFAULT;
|
||||
if (aFlags & PAINT_WIDGET_LAYERS) {
|
||||
@ -3178,11 +3181,12 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
|
||||
Telemetry::AccumulateTimeDelta(Telemetry::PAINT_RASTERIZE_TIME,
|
||||
paintStart);
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
if (consoleNeedsDisplayList || profilerNeedsDisplayList) {
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
if (gfxUtils::sDumpPaintingToFile) {
|
||||
*ss << "</script>";
|
||||
}
|
||||
#endif
|
||||
*ss << "Painting --- after optimization:\n";
|
||||
nsFrame::PrintDisplayList(&builder, list, *ss, gfxUtils::sDumpPaintingToFile);
|
||||
|
||||
@ -3191,9 +3195,6 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
|
||||
FrameLayerBuilder::DumpRetainedLayerTree(layerManager, *ss,
|
||||
gfxUtils::sDumpPaintingToFile);
|
||||
}
|
||||
if (gfxUtils::sDumpPaintingToFile) {
|
||||
*ss << "</body></html>";
|
||||
}
|
||||
|
||||
if (profilerNeedsDisplayList && !consoleNeedsDisplayList) {
|
||||
profiler_log(ss->str().c_str());
|
||||
@ -3202,13 +3203,17 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
|
||||
fprint_stderr(gfxUtils::sDumpPaintFile, *ss);
|
||||
}
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
if (gfxUtils::sDumpPaintingToFile) {
|
||||
*ss << "</body></html>";
|
||||
}
|
||||
if (gfxUtils::sDumpPaintingToFile) {
|
||||
fclose(gfxUtils::sDumpPaintFile);
|
||||
}
|
||||
gfxUtils::sDumpPaintFile = savedDumpFile;
|
||||
gPaintCount++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Update the widget's opaque region information. This sets
|
||||
// glass boundaries on Windows. Also set up the window dragging region
|
||||
|
@ -731,7 +731,7 @@ public:
|
||||
static bool GetShowEventTargetFrameBorder();
|
||||
|
||||
#endif
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
|
||||
public:
|
||||
|
||||
static void PrintDisplayItem(nsDisplayListBuilder* aBuilder,
|
||||
@ -757,7 +757,6 @@ public:
|
||||
std::stringstream& aStream,
|
||||
bool aDumpHtml = false);
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
// Start Display Reflow Debugging
|
||||
|
32
layout/reftests/bugs/1116480-1-fakeitalic-overflow-ref.html
Normal file
32
layout/reftests/bugs/1116480-1-fakeitalic-overflow-ref.html
Normal file
@ -0,0 +1,32 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8'/>
|
||||
<meta name='viewport' content='initial-scale=1' />
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: test;
|
||||
src: url(../fonts/dejavu-sans/DejaVuSans.ttf);
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: test;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 1rem 0 0.3rem;
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
font-style: italic;
|
||||
position: absolute;
|
||||
font-size: 8em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class='container'>
|
||||
<div class='placeholder'>aÍz
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
32
layout/reftests/bugs/1116480-1-fakeitalic-overflow.html
Normal file
32
layout/reftests/bugs/1116480-1-fakeitalic-overflow.html
Normal file
@ -0,0 +1,32 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8'/>
|
||||
<meta name='viewport' content='initial-scale=1' />
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: test;
|
||||
src: url(../fonts/dejavu-sans/DejaVuSans.ttf);
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: test;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 1rem 0 0.3rem;
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
font-style: italic;
|
||||
position: absolute;
|
||||
font-size: 8em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class='container'>
|
||||
<div class='placeholder'>a‮Í‬z
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1850,3 +1850,4 @@ test-pref(layout.testing.overlay-scrollbars.always-visible,false) == 1081072-1.h
|
||||
fuzzy-if(winWidget&&!layersGPUAccelerated,1,31) == 1081185-1.html 1081185-1-ref.html
|
||||
== 1097437-1.html 1097437-1-ref.html
|
||||
== 1105137-1.html 1105137-1-ref.html
|
||||
fuzzy-if(d2d,36,304) HTTP(..) == 1116480-1-fakeitalic-overflow.html 1116480-1-fakeitalic-overflow-ref.html
|
||||
|
@ -2224,10 +2224,8 @@ pref("layout.interruptible-reflow.enabled", true);
|
||||
// specific information is available).
|
||||
pref("layout.frame_rate", -1);
|
||||
|
||||
// pref to dump the display list to the log. Useful for debugging invalidation problems.
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
// pref to dump the display list to the log. Useful for debugging drawing.
|
||||
pref("layout.display-list.dump", false);
|
||||
#endif
|
||||
|
||||
// pref to control precision of the frame rate timer. When true,
|
||||
// we use a "precise" timer, which means each notification fires
|
||||
|
@ -23,7 +23,7 @@ namespace mozilla
|
||||
[ref] native nsCStringTArrayRef(nsTArray<nsCString>);
|
||||
[ref] native mozillaPkixTime(mozilla::pkix::Time);
|
||||
|
||||
[scriptable, uuid(46555f70-3ab5-11e4-8613-180373d97f23)]
|
||||
[scriptable, uuid(e219eace-0e04-42ba-b203-58a8b327867c)]
|
||||
interface nsISiteSecurityService : nsISupports
|
||||
{
|
||||
const uint32_t HEADER_HSTS = 0;
|
||||
@ -100,12 +100,6 @@ interface nsISiteSecurityService : nsISupports
|
||||
in string aHost,
|
||||
in uint32_t aFlags);
|
||||
|
||||
/**
|
||||
* Checks if the given security info is for a host with a broken
|
||||
* transport layer (certificate errors like invalid CN).
|
||||
*/
|
||||
boolean shouldIgnoreHeaders(in nsISupports aSecurityInfo);
|
||||
|
||||
/**
|
||||
* Checks whether or not the URI's hostname has a given security state set.
|
||||
* For example, for HSTS:
|
||||
|
@ -145,10 +145,8 @@ NS_IMETHODIMP DummyChannel::EnsureChildFd()
|
||||
NS_IMETHODIMP DummyChannel::Run()
|
||||
{
|
||||
nsresult rv = mListener->OnStartRequest(this, mListenerContext);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
mPending = false;
|
||||
rv = mListener->OnStopRequest(this, mListenerContext, NS_ERROR_FILE_NOT_FOUND);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (mLoadGroup) {
|
||||
mLoadGroup->RemoveRequest(this, mListenerContext, NS_ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
@ -3266,7 +3266,9 @@ nsHttpChannel::OnCacheEntryAvailable(nsICacheEntry *entry,
|
||||
nsresult rv;
|
||||
|
||||
LOG(("nsHttpChannel::OnCacheEntryAvailable [this=%p entry=%p "
|
||||
"new=%d appcache=%p status=%x]\n", this, entry, aNew, aAppCache, status));
|
||||
"new=%d appcache=%p status=%x mAppCache=%p mAppCacheForWrite=%p]\n",
|
||||
this, entry, aNew, aAppCache, status,
|
||||
mApplicationCache.get(), mApplicationCacheForWrite.get()));
|
||||
|
||||
// if the channel's already fired onStopRequest, then we should ignore
|
||||
// this event.
|
||||
@ -3376,10 +3378,11 @@ nsHttpChannel::OnOfflineCacheEntryAvailable(nsICacheEntry *aEntry,
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (!mApplicationCache)
|
||||
mApplicationCache = aAppCache;
|
||||
|
||||
if (NS_SUCCEEDED(aEntryStatus)) {
|
||||
if (!mApplicationCache) {
|
||||
mApplicationCache = aAppCache;
|
||||
}
|
||||
|
||||
// We successfully opened an offline cache session and the entry,
|
||||
// so indicate we will load from the offline cache.
|
||||
mLoadedFromApplicationCache = true;
|
||||
@ -3396,6 +3399,10 @@ nsHttpChannel::OnOfflineCacheEntryAvailable(nsICacheEntry *aEntry,
|
||||
}
|
||||
|
||||
if (!mApplicationCacheForWrite && !mFallbackChannel) {
|
||||
if (!mApplicationCache) {
|
||||
mApplicationCache = aAppCache;
|
||||
}
|
||||
|
||||
// Check for namespace match.
|
||||
nsCOMPtr<nsIApplicationCacheNamespace> namespaceEntry;
|
||||
rv = mApplicationCache->GetMatchingNamespace(mSpec,
|
||||
|
@ -217,15 +217,15 @@ Result
|
||||
AppTrustDomain::VerifySignedData(const SignedDataWithSignature& signedData,
|
||||
Input subjectPublicKeyInfo)
|
||||
{
|
||||
return ::mozilla::pkix::VerifySignedData(signedData, subjectPublicKeyInfo,
|
||||
mMinimumNonECCBits, mPinArg);
|
||||
return ::mozilla::pkix::VerifySignedDataNSS(signedData, subjectPublicKeyInfo,
|
||||
mMinimumNonECCBits, mPinArg);
|
||||
}
|
||||
|
||||
Result
|
||||
AppTrustDomain::DigestBuf(Input item, /*out*/ uint8_t* digestBuf,
|
||||
size_t digestBufLen)
|
||||
{
|
||||
return ::mozilla::pkix::DigestBuf(item, digestBuf, digestBufLen);
|
||||
return ::mozilla::pkix::DigestBufNSS(item, digestBuf, digestBufLen);
|
||||
}
|
||||
|
||||
Result
|
||||
@ -252,8 +252,8 @@ AppTrustDomain::IsChainValid(const DERArray& certChain, Time time)
|
||||
Result
|
||||
AppTrustDomain::CheckPublicKey(Input subjectPublicKeyInfo)
|
||||
{
|
||||
return ::mozilla::pkix::CheckPublicKey(subjectPublicKeyInfo,
|
||||
mMinimumNonECCBits);
|
||||
return ::mozilla::pkix::CheckPublicKeyNSS(subjectPublicKeyInfo,
|
||||
mMinimumNonECCBits);
|
||||
}
|
||||
|
||||
} } // namespace mozilla::psm
|
||||
|
@ -258,15 +258,15 @@ Result
|
||||
NSSCertDBTrustDomain::VerifySignedData(const SignedDataWithSignature& signedData,
|
||||
Input subjectPublicKeyInfo)
|
||||
{
|
||||
return ::mozilla::pkix::VerifySignedData(signedData, subjectPublicKeyInfo,
|
||||
mMinimumNonECCBits, mPinArg);
|
||||
return ::mozilla::pkix::VerifySignedDataNSS(signedData, subjectPublicKeyInfo,
|
||||
mMinimumNonECCBits, mPinArg);
|
||||
}
|
||||
|
||||
Result
|
||||
NSSCertDBTrustDomain::DigestBuf(Input item,
|
||||
/*out*/ uint8_t* digestBuf, size_t digestBufLen)
|
||||
{
|
||||
return ::mozilla::pkix::DigestBuf(item, digestBuf, digestBufLen);
|
||||
return ::mozilla::pkix::DigestBufNSS(item, digestBuf, digestBufLen);
|
||||
}
|
||||
|
||||
|
||||
@ -700,8 +700,8 @@ NSSCertDBTrustDomain::IsChainValid(const DERArray& certArray, Time time)
|
||||
Result
|
||||
NSSCertDBTrustDomain::CheckPublicKey(Input subjectPublicKeyInfo)
|
||||
{
|
||||
return ::mozilla::pkix::CheckPublicKey(subjectPublicKeyInfo,
|
||||
mMinimumNonECCBits);
|
||||
return ::mozilla::pkix::CheckPublicKeyNSS(subjectPublicKeyInfo,
|
||||
mMinimumNonECCBits);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include "CertVerifier.h"
|
||||
#include "nsCRTGlue.h"
|
||||
#include "nsISSLStatus.h"
|
||||
#include "nsISSLStatusProvider.h"
|
||||
#include "nsISocketProvider.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsNetUtil.h"
|
||||
@ -965,39 +964,6 @@ nsSiteSecurityService::IsSecureHost(uint32_t aType, const char* aHost,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// Verify the trustworthiness of the security info (are there any cert errors?)
|
||||
NS_IMETHODIMP
|
||||
nsSiteSecurityService::ShouldIgnoreHeaders(nsISupports* aSecurityInfo,
|
||||
bool* aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
bool tlsIsBroken = false;
|
||||
nsCOMPtr<nsISSLStatusProvider> sslprov = do_QueryInterface(aSecurityInfo);
|
||||
NS_ENSURE_TRUE(sslprov, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsISSLStatus> sslstat;
|
||||
rv = sslprov->GetSSLStatus(getter_AddRefs(sslstat));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(sslstat, NS_ERROR_FAILURE);
|
||||
|
||||
bool trustcheck;
|
||||
rv = sslstat->GetIsDomainMismatch(&trustcheck);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
tlsIsBroken = tlsIsBroken || trustcheck;
|
||||
|
||||
rv = sslstat->GetIsNotValidAtThisTime(&trustcheck);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
tlsIsBroken = tlsIsBroken || trustcheck;
|
||||
|
||||
rv = sslstat->GetIsUntrusted(&trustcheck);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
tlsIsBroken = tlsIsBroken || trustcheck;
|
||||
|
||||
*aResult = tlsIsBroken;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSiteSecurityService::ClearAll()
|
||||
{
|
||||
|
@ -54,10 +54,18 @@
|
||||
'nosts': 'SECURE'}},
|
||||
};
|
||||
|
||||
function whenDelayedStartupFinished(aWindow, aCallback) {
|
||||
SpecialPowers.Services.obs.addObserver(function observer(aSubject, aTopic) {
|
||||
if (aWindow == aSubject) {
|
||||
SpecialPowers.Services.obs.removeObserver(observer, aTopic);
|
||||
SimpleTest.executeSoon(aCallback);
|
||||
}
|
||||
}, "browser-delayed-startup-finished", false);
|
||||
}
|
||||
|
||||
function testOnWindow(aIsPrivate, aCallback) {
|
||||
var win = mainWindow.OpenBrowserWindow({private: aIsPrivate});
|
||||
win.addEventListener("load", function onLoad() {
|
||||
win.removeEventListener("load", onLoad, false);
|
||||
whenDelayedStartupFinished(win, function () {
|
||||
win.gBrowser.addEventListener("DOMContentLoaded", function onInnerLoad() {
|
||||
if (win.content.location.href != CONTENT_PAGE) {
|
||||
win.gBrowser.loadURI(CONTENT_PAGE);
|
||||
@ -67,7 +75,7 @@
|
||||
SimpleTest.executeSoon(function() { aCallback(win); });
|
||||
}, true);
|
||||
win.gBrowser.loadURI(CONTENT_PAGE);
|
||||
}, true);
|
||||
});
|
||||
}
|
||||
|
||||
function startRound(win, isPrivate, round) {
|
||||
|
@ -124,7 +124,7 @@ private:
|
||||
const uint8_t* data;
|
||||
size_t len;
|
||||
|
||||
void operator=(const Input&) /* = delete */; // Use Init instead.
|
||||
void operator=(const Input&) = delete; // Use Init instead.
|
||||
};
|
||||
|
||||
inline bool
|
||||
@ -291,7 +291,7 @@ public:
|
||||
Mark(const Reader& input, const uint8_t* mark) : input(input), mark(mark) { }
|
||||
const Reader& input;
|
||||
const uint8_t* const mark;
|
||||
void operator=(const Mark&) /* = delete */;
|
||||
void operator=(const Mark&) = delete;
|
||||
};
|
||||
|
||||
Mark GetMark() const { return Mark(*this, input); }
|
||||
@ -320,8 +320,8 @@ private:
|
||||
const uint8_t* input;
|
||||
const uint8_t* end;
|
||||
|
||||
Reader(const Reader&) /* = delete */;
|
||||
void operator=(const Reader&) /* = delete */;
|
||||
Reader(const Reader&) = delete;
|
||||
void operator=(const Reader&) = delete;
|
||||
};
|
||||
|
||||
inline bool
|
||||
|
@ -69,8 +69,8 @@ public:
|
||||
protected:
|
||||
T* mValue;
|
||||
|
||||
ScopedPtr(const ScopedPtr&) /* = delete */;
|
||||
void operator=(const ScopedPtr&) /* = delete */;
|
||||
ScopedPtr(const ScopedPtr&) = delete;
|
||||
void operator=(const ScopedPtr&) = delete;
|
||||
};
|
||||
|
||||
template <typename T, void(&Destroyer)(T*)>
|
||||
|
@ -80,7 +80,7 @@ public:
|
||||
private:
|
||||
F f;
|
||||
B1& b1;
|
||||
void operator=(const Bind1&) /*= delete*/;
|
||||
void operator=(const Bind1&) = delete;
|
||||
};
|
||||
|
||||
template <typename R, typename P1, typename B1, typename B2>
|
||||
@ -94,7 +94,7 @@ private:
|
||||
F f;
|
||||
B1& b1;
|
||||
B2& b2;
|
||||
void operator=(const Bind2&) /*= delete*/;
|
||||
void operator=(const Bind2&) = delete;
|
||||
};
|
||||
|
||||
template <typename R, typename P1, typename B1, typename B2, typename B3>
|
||||
@ -110,7 +110,7 @@ private:
|
||||
B1& b1;
|
||||
B2& b2;
|
||||
B3& b3;
|
||||
void operator=(const Bind3&) /*= delete*/;
|
||||
void operator=(const Bind3&) = delete;
|
||||
};
|
||||
|
||||
template <typename R, typename P1, typename B1, typename B2, typename B3,
|
||||
@ -128,7 +128,7 @@ private:
|
||||
B2& b2;
|
||||
B3& b3;
|
||||
B4& b4;
|
||||
void operator=(const Bind4&) /*= delete*/;
|
||||
void operator=(const Bind4&) = delete;
|
||||
};
|
||||
|
||||
template <typename R, typename C1, typename P1, typename P2, typename P3,
|
||||
@ -148,7 +148,7 @@ public:
|
||||
private:
|
||||
const F f;
|
||||
C1& that;
|
||||
void operator=(const BindToMemberFunction4&) /*= delete*/;
|
||||
void operator=(const BindToMemberFunction4&) = delete;
|
||||
};
|
||||
|
||||
template <typename R, typename P1, typename B1, typename B2, typename B3,
|
||||
@ -167,7 +167,7 @@ private:
|
||||
B3 b3;
|
||||
B4 b4;
|
||||
B5 b5;
|
||||
void operator=(const Bind5&) /*= delete*/;
|
||||
void operator=(const Bind5&) = delete;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
@ -25,13 +25,7 @@
|
||||
#ifndef mozilla_pkix__enumclass_h
|
||||
#define mozilla_pkix__enumclass_h
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1700)
|
||||
// Microsoft added support for "enum class" in Visual C++ 2012. Before that,
|
||||
// Visual C++ has supported typed enums for longer than that, but using typed
|
||||
// enums results in C4480: nonstandard extension used: specifying underlying
|
||||
// type for enum.
|
||||
#define MOZILLA_PKIX_ENUM_CLASS __pragma(warning(suppress: 4480)) enum
|
||||
#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 407)
|
||||
#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 407)
|
||||
// GCC before version 4.7 may crash when compiling code that static_casts a
|
||||
// value of scoped typed enum type. See
|
||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=48106.
|
||||
|
@ -32,10 +32,10 @@
|
||||
namespace mozilla { namespace pkix {
|
||||
|
||||
// Verify the given signed data using the given public key.
|
||||
Result VerifySignedData(const SignedDataWithSignature& sd,
|
||||
Input subjectPublicKeyInfo,
|
||||
unsigned int minimumNonECCBits,
|
||||
void* pkcs11PinArg);
|
||||
Result VerifySignedDataNSS(const SignedDataWithSignature& sd,
|
||||
Input subjectPublicKeyInfo,
|
||||
unsigned int minimumNonECCBits,
|
||||
void* pkcs11PinArg);
|
||||
|
||||
// Computes the SHA-1 hash of the data in the current item.
|
||||
//
|
||||
@ -48,13 +48,13 @@ Result VerifySignedData(const SignedDataWithSignature& sd,
|
||||
// TODO: Taking the output buffer as (uint8_t*, size_t) is counter to our
|
||||
// other, extensive, memory safety efforts in mozilla::pkix, and we should find
|
||||
// a way to provide a more-obviously-safe interface.
|
||||
Result DigestBuf(Input item, /*out*/ uint8_t* digestBuf,
|
||||
size_t digestBufLen);
|
||||
Result DigestBufNSS(Input item, /*out*/ uint8_t* digestBuf,
|
||||
size_t digestBufLen);
|
||||
|
||||
// Checks, for RSA keys and DSA keys, that the modulus is at least the given
|
||||
// number of bits.
|
||||
Result CheckPublicKey(Input subjectPublicKeyInfo,
|
||||
unsigned int minimumNonECCBits);
|
||||
Result CheckPublicKeyNSS(Input subjectPublicKeyInfo,
|
||||
unsigned int minimumNonECCBits);
|
||||
|
||||
Result MapPRErrorCodeToResult(PRErrorCode errorCode);
|
||||
PRErrorCode MapResultToPRErrorCode(Result result);
|
||||
|
@ -80,8 +80,7 @@ public:
|
||||
SignatureAlgorithm algorithm;
|
||||
Input signature;
|
||||
|
||||
private:
|
||||
void operator=(const SignedDataWithSignature&) /*= delete*/;
|
||||
void operator=(const SignedDataWithSignature&) = delete;
|
||||
};
|
||||
|
||||
MOZILLA_PKIX_ENUM_CLASS EndEntityOrCA { MustBeEndEntity = 0, MustBeCA = 1 };
|
||||
@ -148,8 +147,8 @@ public:
|
||||
const Input issuer;
|
||||
const Input issuerSubjectPublicKeyInfo;
|
||||
const Input serialNumber;
|
||||
private:
|
||||
void operator=(const CertID&) /*= delete*/;
|
||||
|
||||
void operator=(const CertID&) = delete;
|
||||
};
|
||||
|
||||
class DERArray
|
||||
@ -209,28 +208,26 @@ public:
|
||||
protected:
|
||||
IssuerChecker();
|
||||
virtual ~IssuerChecker();
|
||||
private:
|
||||
IssuerChecker(const IssuerChecker&) /*= delete*/;
|
||||
void operator=(const IssuerChecker&) /*= delete*/;
|
||||
|
||||
IssuerChecker(const IssuerChecker&) = delete;
|
||||
void operator=(const IssuerChecker&) = delete;
|
||||
};
|
||||
|
||||
// Search for a CA certificate with the given name. The implementation must
|
||||
// call checker.Check with the DER encoding of the potential issuer
|
||||
// certificate. The implementation must follow these rules:
|
||||
//
|
||||
// * The subject name of the certificate given to checker.Check must be equal
|
||||
// to encodedIssuerName.
|
||||
// * The implementation must be reentrant and must limit the amount of stack
|
||||
// space it uses; see the note on reentrancy and stack usage below.
|
||||
// * When checker.Check does not return SECSuccess then immediately return
|
||||
// SECFailure.
|
||||
// * When checker.Check returns SECSuccess and sets keepGoing = false, then
|
||||
// immediately return SECSuccess.
|
||||
// * When checker.Check returns SECSuccess and sets keepGoing = true, then
|
||||
// * When checker.Check does not return Success then immediately return its
|
||||
// return value.
|
||||
// * When checker.Check returns Success and sets keepGoing = false, then
|
||||
// immediately return Success.
|
||||
// * When checker.Check returns Success and sets keepGoing = true, then
|
||||
// call checker.Check again with a different potential issuer certificate,
|
||||
// if any more are available.
|
||||
// * When no more potential issuer certificates are available, return
|
||||
// SECSuccess.
|
||||
// Success.
|
||||
// * Don't call checker.Check with the same potential issuer certificate more
|
||||
// than once in a given call of FindIssuer.
|
||||
// * The given time parameter may be used to filter out certificates that are
|
||||
@ -255,6 +252,13 @@ public:
|
||||
//
|
||||
// checker.Check is responsible for limiting the recursion to a reasonable
|
||||
// limit.
|
||||
//
|
||||
// checker.Check will verify that the subject's issuer field matches the
|
||||
// potential issuer's subject field. It will also check that the potential
|
||||
// issuer is valid at the given time. However, if the FindIssuer
|
||||
// implementation has an efficient way of filtering potential issuers by name
|
||||
// and/or validity period itself, then it is probably better for performance
|
||||
// for it to do so.
|
||||
virtual Result FindIssuer(Input encodedIssuerName,
|
||||
IssuerChecker& checker, Time time) = 0;
|
||||
|
||||
@ -265,24 +269,22 @@ public:
|
||||
// use.
|
||||
//
|
||||
// This function may be called multiple times, regardless of whether it
|
||||
// returns SECSuccess or SECFailure. It is guaranteed that BuildCertChain
|
||||
// will not return SECSuccess unless the last call to IsChainValid returns
|
||||
// SECSuccess. Further, it is guaranteed that when BuildCertChain returns
|
||||
// SECSuccess the last chain passed to IsChainValid is the valid chain that
|
||||
// should be used for further operations that require the whole chain.
|
||||
// returns success or failure. It is guaranteed that BuildCertChain will not
|
||||
// return Success unless the last call to IsChainValid returns Success. Further,
|
||||
// it is guaranteed that when BuildCertChain returns Success the last chain
|
||||
// passed to IsChainValid is the valid chain that should be used for further
|
||||
// operations that require the whole chain.
|
||||
//
|
||||
// Keep in mind, in particular, that if the application saves a copy of the
|
||||
// certificate chain the last invocation of IsChainValid during a validation,
|
||||
// it is still possible for BuildCertChain to fail (return SECFailure), in
|
||||
// which case the application must not assume anything about the validity of
|
||||
// the last certificate chain passed to IsChainValid; especially, it would be
|
||||
// very wrong to assume that the certificate chain is valid.
|
||||
// it is still possible for BuildCertChain to fail, in which case the
|
||||
// application must not assume anything about the validity of the last
|
||||
// certificate chain passed to IsChainValid; especially, it would be very
|
||||
// wrong to assume that the certificate chain is valid.
|
||||
//
|
||||
// certChain.GetDER(0) is the trust anchor.
|
||||
virtual Result IsChainValid(const DERArray& certChain, Time time) = 0;
|
||||
|
||||
// issuerCertToDup is only non-const so CERT_DupCertificate can be called on
|
||||
// it.
|
||||
virtual Result CheckRevocation(EndEntityOrCA endEntityOrCA,
|
||||
const CertID& certID, Time time,
|
||||
/*optional*/ const Input* stapledOCSPresponse,
|
||||
@ -322,9 +324,8 @@ public:
|
||||
protected:
|
||||
TrustDomain() { }
|
||||
|
||||
private:
|
||||
TrustDomain(const TrustDomain&) /* = delete */;
|
||||
void operator=(const TrustDomain&) /* = delete */;
|
||||
TrustDomain(const TrustDomain&) = delete;
|
||||
void operator=(const TrustDomain&) = delete;
|
||||
};
|
||||
|
||||
} } // namespace mozilla::pkix
|
||||
|
@ -84,8 +84,8 @@ private:
|
||||
Result result;
|
||||
bool resultWasSet;
|
||||
|
||||
PathBuildingStep(const PathBuildingStep&) /*= delete*/;
|
||||
void operator=(const PathBuildingStep&) /*= delete*/;
|
||||
PathBuildingStep(const PathBuildingStep&) = delete;
|
||||
void operator=(const PathBuildingStep&) = delete;
|
||||
};
|
||||
|
||||
Result
|
||||
@ -139,8 +139,17 @@ PathBuildingStep::Check(Input potentialIssuerDER,
|
||||
return RecordResult(rv, keepGoing);
|
||||
}
|
||||
|
||||
// RFC5280 4.2.1.1. Authority Key Identifier
|
||||
// RFC5280 4.2.1.2. Subject Key Identifier
|
||||
// Simple TrustDomain::FindIssuers implementations may pass in all possible
|
||||
// CA certificates without any filtering. Because of this, we don't consider
|
||||
// a mismatched name to be an error. Instead, we just pretend that any
|
||||
// certificate without a matching name was never passed to us. In particular,
|
||||
// we treat the case where the TrustDomain only asks us to check CA
|
||||
// certificates with mismatched names as equivalent to the case where the
|
||||
// TrustDomain never called Check() at all.
|
||||
if (!InputsAreEqual(potentialIssuer.GetSubject(), subject.GetIssuer())) {
|
||||
keepGoing = true;
|
||||
return Success;
|
||||
}
|
||||
|
||||
// Loop prevention, done as recommended by RFC4158 Section 5.2
|
||||
// TODO: this doesn't account for subjectAltNames!
|
||||
|
@ -166,9 +166,6 @@ template <typename Decoder>
|
||||
inline Result
|
||||
Nested(Reader& input, uint8_t outerTag, uint8_t innerTag, Decoder decoder)
|
||||
{
|
||||
// XXX: This doesn't work (in VS2010):
|
||||
// return Nested(input, outerTag, bind(Nested, _1, innerTag, decoder));
|
||||
|
||||
Reader nestedInput;
|
||||
Result rv = ExpectTagAndGetValue(input, outerTag, nestedInput);
|
||||
if (rv != Success) {
|
||||
|
@ -39,7 +39,7 @@ namespace mozilla { namespace pkix {
|
||||
|
||||
typedef ScopedPtr<SECKEYPublicKey, SECKEY_DestroyPublicKey> ScopedSECKeyPublicKey;
|
||||
|
||||
Result
|
||||
static Result
|
||||
CheckPublicKeySize(Input subjectPublicKeyInfo, unsigned int minimumNonECCBits,
|
||||
/*out*/ ScopedSECKeyPublicKey& publicKey)
|
||||
{
|
||||
@ -59,18 +59,18 @@ CheckPublicKeySize(Input subjectPublicKeyInfo, unsigned int minimumNonECCBits,
|
||||
case ecKey:
|
||||
// TODO(bug 1077790): We should check which curve.
|
||||
return Success;
|
||||
case dsaKey: // fall through
|
||||
case rsaKey:
|
||||
if (SECKEY_PublicKeyStrengthInBits(publicKey.get()) < minimumNonECCBits) {
|
||||
return Result::ERROR_INADEQUATE_KEY_SIZE;
|
||||
}
|
||||
break;
|
||||
case nullKey:
|
||||
case fortezzaKey:
|
||||
case dhKey:
|
||||
case keaKey:
|
||||
case rsaPssKey:
|
||||
case rsaOaepKey:
|
||||
case dsaKey: // fall through
|
||||
case nullKey: // fall through
|
||||
case fortezzaKey: // fall through
|
||||
case dhKey: // fall through
|
||||
case keaKey: // fall through
|
||||
case rsaPssKey: // fall through
|
||||
case rsaOaepKey: // fall through
|
||||
default:
|
||||
return Result::ERROR_UNSUPPORTED_KEYALG;
|
||||
}
|
||||
@ -79,16 +79,16 @@ CheckPublicKeySize(Input subjectPublicKeyInfo, unsigned int minimumNonECCBits,
|
||||
}
|
||||
|
||||
Result
|
||||
CheckPublicKey(Input subjectPublicKeyInfo, unsigned int minimumNonECCBits)
|
||||
CheckPublicKeyNSS(Input subjectPublicKeyInfo, unsigned int minimumNonECCBits)
|
||||
{
|
||||
ScopedSECKeyPublicKey unused;
|
||||
return CheckPublicKeySize(subjectPublicKeyInfo, minimumNonECCBits, unused);
|
||||
}
|
||||
|
||||
Result
|
||||
VerifySignedData(const SignedDataWithSignature& sd,
|
||||
Input subjectPublicKeyInfo, unsigned int minimumNonECCBits,
|
||||
void* pkcs11PinArg)
|
||||
VerifySignedDataNSS(const SignedDataWithSignature& sd,
|
||||
Input subjectPublicKeyInfo, unsigned int minimumNonECCBits,
|
||||
void* pkcs11PinArg)
|
||||
{
|
||||
SECOidTag pubKeyAlg;
|
||||
SECOidTag digestAlg;
|
||||
@ -125,10 +125,10 @@ VerifySignedData(const SignedDataWithSignature& sd,
|
||||
pubKeyAlg = SEC_OID_PKCS1_RSA_ENCRYPTION;
|
||||
digestAlg = SEC_OID_SHA1;
|
||||
break;
|
||||
case SignatureAlgorithm::unsupported_algorithm:
|
||||
case SignatureAlgorithm::unsupported_algorithm: // fall through
|
||||
default:
|
||||
PR_NOT_REACHED("unknown signature algorithm");
|
||||
return Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED;
|
||||
return NotReached("unknown signature algorithm",
|
||||
Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
|
||||
}
|
||||
|
||||
Result rv;
|
||||
@ -159,13 +159,12 @@ VerifySignedData(const SignedDataWithSignature& sd,
|
||||
}
|
||||
|
||||
Result
|
||||
DigestBuf(Input item, /*out*/ uint8_t* digestBuf, size_t digestBufLen)
|
||||
DigestBufNSS(Input item, /*out*/ uint8_t* digestBuf, size_t digestBufLen)
|
||||
{
|
||||
static_assert(TrustDomain::DIGEST_LENGTH == SHA1_LENGTH,
|
||||
"TrustDomain::DIGEST_LENGTH must be 20 (SHA-1 digest length)");
|
||||
if (digestBufLen != TrustDomain::DIGEST_LENGTH) {
|
||||
PR_NOT_REACHED("invalid hash length");
|
||||
return Result::FATAL_ERROR_INVALID_ARGS;
|
||||
return NotReached("invalid hash length", Result::FATAL_ERROR_INVALID_ARGS);
|
||||
}
|
||||
SECItem itemSECItem = UnsafeMapInputToSECItem(item);
|
||||
if (itemSECItem.len >
|
||||
|
@ -71,9 +71,8 @@ public:
|
||||
Time* validThrough;
|
||||
bool expired;
|
||||
|
||||
private:
|
||||
Context(const Context&); // delete
|
||||
void operator=(const Context&); // delete
|
||||
Context(const Context&) = delete;
|
||||
void operator=(const Context&) = delete;
|
||||
};
|
||||
|
||||
// Verify that potentialSigner is a valid delegated OCSP response signing cert
|
||||
|
@ -143,8 +143,8 @@ private:
|
||||
Result RememberExtension(Reader& extnID, const Input& extnValue,
|
||||
bool critical, /*out*/ bool& understood);
|
||||
|
||||
BackCert(const BackCert&) /* = delete */;
|
||||
void operator=(const BackCert&); /* = delete */;
|
||||
BackCert(const BackCert&) = delete;
|
||||
void operator=(const BackCert&) = delete;
|
||||
};
|
||||
|
||||
class NonOwningDERArray : public DERArray
|
||||
@ -183,8 +183,8 @@ private:
|
||||
Input items[MAX_LENGTH]; // avoids any heap allocations
|
||||
size_t numItems;
|
||||
|
||||
NonOwningDERArray(const NonOwningDERArray&) /* = delete*/;
|
||||
void operator=(const NonOwningDERArray&) /* = delete*/;
|
||||
NonOwningDERArray(const NonOwningDERArray&) = delete;
|
||||
void operator=(const NonOwningDERArray&) = delete;
|
||||
};
|
||||
|
||||
inline unsigned int
|
||||
|
@ -30,8 +30,6 @@ CXXFLAGS += ['-Wall']
|
||||
# -Wall with Visual C++ enables too many problematic warnings
|
||||
if CONFIG['_MSC_VER']:
|
||||
CXXFLAGS += [
|
||||
'-wd4480', # nonstandard extension used: specifying underlying type for
|
||||
# enum 'enum'
|
||||
'-wd4514', # 'function': unreferenced inline function has been removed
|
||||
'-wd4668', # 'symbol' is not defined as a preprocessor macro...
|
||||
'-wd4710', # 'function': function not inlined
|
||||
|
@ -32,8 +32,8 @@ using namespace mozilla::pkix;
|
||||
using namespace mozilla::pkix::test;
|
||||
|
||||
static ByteString
|
||||
CreateCert(const char* issuerCN,
|
||||
const char* subjectCN,
|
||||
CreateCert(const char* issuerCN, // null means "empty name"
|
||||
const char* subjectCN, // null means "empty name"
|
||||
EndEntityOrCA endEntityOrCA,
|
||||
/*optional modified*/ std::map<ByteString, ByteString>*
|
||||
subjectDERToCertDER = nullptr)
|
||||
@ -43,8 +43,8 @@ CreateCert(const char* issuerCN,
|
||||
ByteString serialNumber(CreateEncodedSerialNumber(serialNumberValue));
|
||||
EXPECT_FALSE(ENCODING_FAILED(serialNumber));
|
||||
|
||||
ByteString issuerDER(CNToDERName(issuerCN));
|
||||
ByteString subjectDER(CNToDERName(subjectCN));
|
||||
ByteString issuerDER(issuerCN ? CNToDERName(issuerCN) : Name(ByteString()));
|
||||
ByteString subjectDER(subjectCN ? CNToDERName(subjectCN) : Name(ByteString()));
|
||||
|
||||
ByteString extensions[2];
|
||||
if (endEntityOrCA == EndEntityOrCA::MustBeCA) {
|
||||
@ -361,3 +361,208 @@ TEST_F(pkixbuild, NoRevocationCheckingForExpiredCert)
|
||||
CertPolicyId::anyPolicy,
|
||||
nullptr));
|
||||
}
|
||||
|
||||
class DSSTrustDomain : public TrustDomain
|
||||
{
|
||||
public:
|
||||
virtual Result GetCertTrust(EndEntityOrCA, const CertPolicyId&,
|
||||
Input, /*out*/ TrustLevel& trustLevel)
|
||||
{
|
||||
trustLevel = TrustLevel::TrustAnchor;
|
||||
return Success;
|
||||
}
|
||||
|
||||
virtual Result FindIssuer(Input, IssuerChecker&, Time)
|
||||
{
|
||||
ADD_FAILURE();
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
}
|
||||
|
||||
virtual Result CheckRevocation(EndEntityOrCA, const CertID&, Time,
|
||||
/*optional*/ const Input*,
|
||||
/*optional*/ const Input*)
|
||||
{
|
||||
ADD_FAILURE();
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
}
|
||||
|
||||
virtual Result IsChainValid(const DERArray&, Time)
|
||||
{
|
||||
return Success;
|
||||
}
|
||||
|
||||
virtual Result VerifySignedData(const SignedDataWithSignature& signedData,
|
||||
Input subjectPublicKeyInfo)
|
||||
{
|
||||
ADD_FAILURE();
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
}
|
||||
|
||||
virtual Result DigestBuf(Input, /*out*/uint8_t*, size_t)
|
||||
{
|
||||
ADD_FAILURE();
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
}
|
||||
|
||||
virtual Result CheckPublicKey(Input subjectPublicKeyInfo)
|
||||
{
|
||||
return TestCheckPublicKey(subjectPublicKeyInfo);
|
||||
}
|
||||
};
|
||||
|
||||
class pkixbuild_DSS : public ::testing::Test { };
|
||||
|
||||
TEST_F(pkixbuild_DSS, DSSEndEntityKeyNotAccepted)
|
||||
{
|
||||
DSSTrustDomain trustDomain;
|
||||
|
||||
ByteString serialNumber(CreateEncodedSerialNumber(1));
|
||||
ASSERT_FALSE(ENCODING_FAILED(serialNumber));
|
||||
|
||||
ByteString subjectDER(CNToDERName("DSS"));
|
||||
ASSERT_FALSE(ENCODING_FAILED(subjectDER));
|
||||
ScopedTestKeyPair subjectKey(GenerateDSSKeyPair());
|
||||
ASSERT_TRUE(subjectKey);
|
||||
|
||||
ByteString issuerDER(CNToDERName("RSA"));
|
||||
ASSERT_FALSE(ENCODING_FAILED(issuerDER));
|
||||
ScopedTestKeyPair issuerKey(CloneReusedKeyPair());
|
||||
ASSERT_TRUE(issuerKey);
|
||||
|
||||
ByteString cert(CreateEncodedCertificate(v3, sha256WithRSAEncryption,
|
||||
serialNumber, issuerDER,
|
||||
oneDayBeforeNow, oneDayAfterNow,
|
||||
subjectDER, *subjectKey, nullptr,
|
||||
*issuerKey, sha256WithRSAEncryption));
|
||||
ASSERT_FALSE(ENCODING_FAILED(cert));
|
||||
Input certDER;
|
||||
ASSERT_EQ(Success, certDER.Init(cert.data(), cert.length()));
|
||||
|
||||
ASSERT_EQ(Result::ERROR_UNSUPPORTED_KEYALG,
|
||||
BuildCertChain(trustDomain, certDER, Now(),
|
||||
EndEntityOrCA::MustBeEndEntity,
|
||||
KeyUsage::noParticularKeyUsageRequired,
|
||||
KeyPurposeId::id_kp_serverAuth,
|
||||
CertPolicyId::anyPolicy,
|
||||
nullptr/*stapledOCSPResponse*/));
|
||||
}
|
||||
|
||||
class IssuerNameCheckTrustDomain : public TrustDomain
|
||||
{
|
||||
public:
|
||||
IssuerNameCheckTrustDomain(const ByteString& issuer, bool expectedKeepGoing)
|
||||
: issuer(issuer)
|
||||
, expectedKeepGoing(expectedKeepGoing)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Result GetCertTrust(EndEntityOrCA endEntityOrCA,
|
||||
const CertPolicyId&, Input,
|
||||
/*out*/ TrustLevel& trustLevel)
|
||||
{
|
||||
trustLevel = endEntityOrCA == EndEntityOrCA::MustBeCA
|
||||
? TrustLevel::TrustAnchor
|
||||
: TrustLevel::InheritsTrust;
|
||||
return Success;
|
||||
}
|
||||
|
||||
virtual Result FindIssuer(Input subjectCert, IssuerChecker& checker, Time)
|
||||
{
|
||||
Input issuerInput;
|
||||
EXPECT_EQ(Success, issuerInput.Init(issuer.data(), issuer.length()));
|
||||
bool keepGoing;
|
||||
EXPECT_EQ(Success,
|
||||
checker.Check(issuerInput, nullptr /*additionalNameConstraints*/,
|
||||
keepGoing));
|
||||
EXPECT_EQ(expectedKeepGoing, keepGoing);
|
||||
return Success;
|
||||
}
|
||||
|
||||
virtual Result CheckRevocation(EndEntityOrCA, const CertID&, Time,
|
||||
/*optional*/ const Input*,
|
||||
/*optional*/ const Input*)
|
||||
{
|
||||
return Success;
|
||||
}
|
||||
|
||||
virtual Result IsChainValid(const DERArray&, Time)
|
||||
{
|
||||
return Success;
|
||||
}
|
||||
|
||||
virtual Result VerifySignedData(const SignedDataWithSignature& signedData,
|
||||
Input subjectPublicKeyInfo)
|
||||
{
|
||||
return TestVerifySignedData(signedData, subjectPublicKeyInfo);
|
||||
}
|
||||
|
||||
virtual Result DigestBuf(Input, /*out*/uint8_t*, size_t)
|
||||
{
|
||||
ADD_FAILURE();
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
}
|
||||
|
||||
virtual Result CheckPublicKey(Input subjectPublicKeyInfo)
|
||||
{
|
||||
return TestCheckPublicKey(subjectPublicKeyInfo);
|
||||
}
|
||||
|
||||
private:
|
||||
const ByteString issuer;
|
||||
const bool expectedKeepGoing;
|
||||
};
|
||||
|
||||
struct IssuerNameCheckParams
|
||||
{
|
||||
const char* subjectIssuerCN; // null means "empty name"
|
||||
const char* issuerSubjectCN; // null means "empty name"
|
||||
bool matches;
|
||||
};
|
||||
|
||||
static const IssuerNameCheckParams ISSUER_NAME_CHECK_PARAMS[] =
|
||||
{
|
||||
{ "foo", "foo", true },
|
||||
{ "foo", "bar", false },
|
||||
{ "f", "foo", false }, // prefix
|
||||
{ "foo", "f", false }, // prefix
|
||||
{ "foo", "Foo", false }, // case sensitive
|
||||
{ "", "", true },
|
||||
{ nullptr, nullptr, true }, // XXX(bug 1115718)
|
||||
};
|
||||
|
||||
class pkixbuild_IssuerNameCheck
|
||||
: public ::testing::Test
|
||||
, public ::testing::WithParamInterface<IssuerNameCheckParams>
|
||||
{
|
||||
};
|
||||
|
||||
TEST_P(pkixbuild_IssuerNameCheck, MatchingName)
|
||||
{
|
||||
const IssuerNameCheckParams& params(GetParam());
|
||||
|
||||
ByteString issuerCertDER(CreateCert(params.issuerSubjectCN,
|
||||
params.issuerSubjectCN,
|
||||
EndEntityOrCA::MustBeCA, nullptr));
|
||||
ASSERT_FALSE(ENCODING_FAILED(issuerCertDER));
|
||||
|
||||
ByteString subjectCertDER(CreateCert(params.subjectIssuerCN, "end-entity",
|
||||
EndEntityOrCA::MustBeEndEntity,
|
||||
nullptr));
|
||||
ASSERT_FALSE(ENCODING_FAILED(subjectCertDER));
|
||||
|
||||
Input subjectCertDERInput;
|
||||
ASSERT_EQ(Success, subjectCertDERInput.Init(subjectCertDER.data(),
|
||||
subjectCertDER.length()));
|
||||
|
||||
IssuerNameCheckTrustDomain trustDomain(issuerCertDER, !params.matches);
|
||||
ASSERT_EQ(params.matches ? Success : Result::ERROR_UNKNOWN_ISSUER,
|
||||
BuildCertChain(trustDomain, subjectCertDERInput, Now(),
|
||||
EndEntityOrCA::MustBeEndEntity,
|
||||
KeyUsage::noParticularKeyUsageRequired,
|
||||
KeyPurposeId::id_kp_serverAuth,
|
||||
CertPolicyId::anyPolicy,
|
||||
nullptr/*stapledOCSPResponse*/));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(pkixbuild_IssuerNameCheck, pkixbuild_IssuerNameCheck,
|
||||
testing::ValuesIn(ISSUER_NAME_CHECK_PARAMS));
|
||||
|
@ -86,9 +86,8 @@ public:
|
||||
return TestCheckPublicKey(subjectPublicKeyInfo);
|
||||
}
|
||||
|
||||
private:
|
||||
OCSPTestTrustDomain(const OCSPTestTrustDomain&) /*delete*/;
|
||||
void operator=(const OCSPTestTrustDomain&) /*delete*/;
|
||||
OCSPTestTrustDomain(const OCSPTestTrustDomain&) = delete;
|
||||
void operator=(const OCSPTestTrustDomain&) = delete;
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "cryptohi.h"
|
||||
#include "keyhi.h"
|
||||
#include "nss.h"
|
||||
#include "pk11pqg.h"
|
||||
#include "pk11pub.h"
|
||||
#include "pkix/pkixnss.h"
|
||||
#include "pkixder.h"
|
||||
@ -212,13 +213,6 @@ GenerateKeyPairInner()
|
||||
}
|
||||
|
||||
abort();
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1700)
|
||||
// Older versions of MSVC don't know that abort() never returns, so silence
|
||||
// its warning by adding a redundant and never-reached return. But, only do
|
||||
// it for that ancient compiler, because some other compilers will rightly
|
||||
// warn that the return statement is unreachable.
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
@ -241,6 +235,53 @@ CloneReusedKeyPair()
|
||||
return reusedKeyPair->Clone();
|
||||
}
|
||||
|
||||
TestKeyPair*
|
||||
GenerateDSSKeyPair()
|
||||
{
|
||||
InitNSSIfNeeded();
|
||||
|
||||
ScopedPtr<PK11SlotInfo, PK11_FreeSlot> slot(PK11_GetInternalSlot());
|
||||
if (!slot) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PQGParams* pqgParamsTemp = nullptr;
|
||||
PQGVerify* pqgVerify = nullptr;
|
||||
if (PK11_PQG_ParamGenV2(2048u, 256u, 256u / 8u, &pqgParamsTemp, &pqgVerify)
|
||||
!= SECSuccess) {
|
||||
return nullptr;
|
||||
}
|
||||
PK11_PQG_DestroyVerify(pqgVerify);
|
||||
ScopedPtr<PQGParams, PK11_PQG_DestroyParams> params(pqgParamsTemp);
|
||||
|
||||
SECKEYPublicKey* publicKeyTemp = nullptr;
|
||||
ScopedSECKEYPrivateKey
|
||||
privateKey(PK11_GenerateKeyPair(slot.get(), CKM_DSA_KEY_PAIR_GEN,
|
||||
params.get(), &publicKeyTemp, false, true,
|
||||
nullptr));
|
||||
if (!privateKey) {
|
||||
return nullptr;
|
||||
}
|
||||
ScopedSECKEYPublicKey publicKey(publicKeyTemp);
|
||||
|
||||
ScopedSECItem spkiDER(SECKEY_EncodeDERSubjectPublicKeyInfo(publicKey.get()));
|
||||
if (!spkiDER) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ScopedPtr<CERTSubjectPublicKeyInfo, SECKEY_DestroySubjectPublicKeyInfo>
|
||||
spki(SECKEY_CreateSubjectPublicKeyInfo(publicKey.get()));
|
||||
if (!spki) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SECItem spkDER = spki->subjectPublicKey;
|
||||
DER_ConvertBitString(&spkDER); // bits to bytes
|
||||
return CreateTestKeyPair(ByteString(spkiDER->data, spkiDER->len),
|
||||
ByteString(spkDER.data, spkDER.len),
|
||||
privateKey.release());
|
||||
}
|
||||
|
||||
ByteString
|
||||
SHA1(const ByteString& toHash)
|
||||
{
|
||||
@ -259,7 +300,7 @@ Result
|
||||
TestCheckPublicKey(Input subjectPublicKeyInfo)
|
||||
{
|
||||
InitNSSIfNeeded();
|
||||
return CheckPublicKey(subjectPublicKeyInfo, MINIMUM_TEST_KEY_BITS);
|
||||
return CheckPublicKeyNSS(subjectPublicKeyInfo, MINIMUM_TEST_KEY_BITS);
|
||||
}
|
||||
|
||||
Result
|
||||
@ -267,15 +308,15 @@ TestVerifySignedData(const SignedDataWithSignature& signedData,
|
||||
Input subjectPublicKeyInfo)
|
||||
{
|
||||
InitNSSIfNeeded();
|
||||
return VerifySignedData(signedData, subjectPublicKeyInfo,
|
||||
MINIMUM_TEST_KEY_BITS, nullptr);
|
||||
return VerifySignedDataNSS(signedData, subjectPublicKeyInfo,
|
||||
MINIMUM_TEST_KEY_BITS, nullptr);
|
||||
}
|
||||
|
||||
Result
|
||||
TestDigestBuf(Input item, /*out*/ uint8_t* digestBuf, size_t digestBufLen)
|
||||
{
|
||||
InitNSSIfNeeded();
|
||||
return DigestBuf(item, digestBuf, digestBufLen);
|
||||
return DigestBufNSS(item, digestBuf, digestBufLen);
|
||||
}
|
||||
|
||||
} } } // namespace mozilla::pkix::test
|
||||
|
@ -247,12 +247,13 @@ protected:
|
||||
{
|
||||
}
|
||||
|
||||
TestKeyPair(const TestKeyPair&) /*= delete*/;
|
||||
void operator=(const TestKeyPair&) /*= delete*/;
|
||||
TestKeyPair(const TestKeyPair&) = delete;
|
||||
void operator=(const TestKeyPair&) = delete;
|
||||
};
|
||||
|
||||
TestKeyPair* CloneReusedKeyPair();
|
||||
TestKeyPair* GenerateKeyPair();
|
||||
TestKeyPair* GenerateDSSKeyPair();
|
||||
inline void DeleteTestKeyPair(TestKeyPair* keyPair) { delete keyPair; }
|
||||
typedef ScopedPtr<TestKeyPair, DeleteTestKeyPair> ScopedTestKeyPair;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user