Merge inbound to mozilla-central. a=merge

This commit is contained in:
Margareta Eliza Balazs 2018-05-11 12:36:02 +03:00
Родитель 4021845f39 947f304784
Коммит 4f9a2ba08e
69 изменённых файлов: 1200 добавлений и 2738 удалений

2
browser/extensions/webcompat/bootstrap.js поставляемый
Просмотреть файл

@ -76,7 +76,7 @@ this.startup = function({webExtension}) {
// Listen to the useragentoverrides-initialized notification we get and
// initialize our overrider there. This is done to avoid slowing down the
// apparent startup proces, since we avoid loading anything before the first
// apparent startup process, since we avoid loading anything before the first
// window is visible to the user. See bug 1371442 for details.
let uaStartupObserver = {
observe(aSubject, aTopic, aData) {

Просмотреть файл

@ -23,7 +23,7 @@ class IPCPaymentActionRequest;
/*
* PaymentRequestManager is a singleton used to manage the created PaymentRequests.
* It is also the communication agent to chrome proces.
* It is also the communication agent to chrome process.
*/
class PaymentRequestManager final
{

Просмотреть файл

@ -629,7 +629,7 @@ static uint32_t GetSkiaGlyphCacheSize()
// Chromium uses 20mb and skia default uses 2mb.
// We don't need to change the font cache count since we usually
// cache thrash due to asian character sets in talos.
// Only increase memory on the content proces
// Only increase memory on the content process
uint32_t cacheSize = gfxPrefs::SkiaContentFontCacheSize() * 1024 * 1024;
if (mozilla::BrowserTabsRemoteAutostart()) {
return XRE_IsContentProcess() ? cacheSize : kDefaultGlyphCacheSize;

Просмотреть файл

@ -13,6 +13,7 @@
#include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/Logging.h"
#include "mozilla/Move.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/Sprintf.h"
#include "mozilla/Telemetry.h"
#include "mozilla/TimeStamp.h"
@ -2696,7 +2697,16 @@ MessageChannel::Close()
AssertWorkerThread();
{
MonitorAutoLock lock(*mMonitor);
// We don't use MonitorAutoLock here as that causes some sort of
// deadlock in the error/timeout-with-a-listener state below when
// compiling an optimized msvc build.
mMonitor->Lock();
// Instead just use a ScopeExit to manage the unlock.
RefPtr<RefCountedMonitor> monitor(mMonitor);
auto exit = MakeScopeExit([m = Move(monitor)] () {
m->Unlock();
});
if (ChannelError == mChannelState || ChannelTimeout == mChannelState) {
// See bug 538586: if the listener gets deleted while the
@ -2705,7 +2715,8 @@ MessageChannel::Close()
// also be deleted and the listener will never be notified
// of the channel error.
if (mListener) {
MonitorAutoUnlock unlock(*mMonitor);
exit.release(); // Explicitly unlocking, clear scope exit.
mMonitor->Unlock();
NotifyMaybeChannelError();
}
return;

Просмотреть файл

@ -3211,7 +3211,8 @@ ICCall_ConstStringSplit::Compiler::generateStubCode(MacroAssembler& masm)
masm.loadValue(sepAddr, sepVal);
masm.branchTestString(Assembler::NotEqual, sepVal, &failureRestoreArgc);
Register sep = masm.extractString(sepVal, ExtractTemp0);
Register sep = sepVal.scratchReg();
masm.unboxString(sepVal, sep);
masm.branchPtr(Assembler::NotEqual, Address(ICStubReg, offsetOfExpectedSep()),
sep, &failureRestoreArgc);
regs.add(sepVal);
@ -3226,7 +3227,8 @@ ICCall_ConstStringSplit::Compiler::generateStubCode(MacroAssembler& masm)
masm.loadValue(strAddr, strVal);
masm.branchTestString(Assembler::NotEqual, strVal, &failureRestoreArgc);
Register str = masm.extractString(strVal, ExtractTemp0);
Register str = strVal.scratchReg();
masm.unboxString(strVal, str);
masm.branchPtr(Assembler::NotEqual, Address(ICStubReg, offsetOfExpectedStr()),
str, &failureRestoreArgc);
regs.add(strVal);

Просмотреть файл

@ -7745,7 +7745,6 @@ CodeGenerator::visitCompareStrictS(LCompareStrictS* lir)
const ValueOperand leftV = ToValue(lir, LCompareStrictS::Lhs);
Register right = ToRegister(lir->right());
Register output = ToRegister(lir->output());
Register tempToUnbox = ToTempUnboxRegister(lir->tempToUnbox());
Label string, done;
@ -7754,7 +7753,12 @@ CodeGenerator::visitCompareStrictS(LCompareStrictS* lir)
masm.jump(&done);
masm.bind(&string);
Register left = masm.extractString(leftV, tempToUnbox);
#ifdef JS_NUNBOX32
Register left = leftV.payloadReg();
#else
Register left = ToTempUnboxRegister(lir->tempToUnbox());
#endif
masm.unboxString(leftV, left);
emitCompareS(lir, op, left, right, output);
masm.bind(&done);

Просмотреть файл

@ -1496,6 +1496,8 @@ void
MacroAssembler::compareStrings(JSOp op, Register left, Register right, Register result,
Label* fail)
{
MOZ_ASSERT(left != result);
MOZ_ASSERT(right != result);
MOZ_ASSERT(IsEqualityOp(op));
Label done;

Просмотреть файл

@ -1485,22 +1485,29 @@ ICCompare_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
bool
ICCompare_String::Compiler::generateStubCode(MacroAssembler& masm)
{
Label failure;
Label failure, restore;
masm.branchTestString(Assembler::NotEqual, R0, &failure);
masm.branchTestString(Assembler::NotEqual, R1, &failure);
MOZ_ASSERT(IsEqualityOp(op));
Register left = masm.extractString(R0, ExtractTemp0);
Register right = masm.extractString(R1, ExtractTemp1);
// left/right are part of R0/R1. Restore R0 and R1 in the failure case.
Register left = R0.scratchReg();
Register right = R1.scratchReg();
masm.unboxString(R0, left);
masm.unboxString(R1, right);
AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
Register scratchReg = regs.takeAny();
masm.compareStrings(op, left, right, scratchReg, &failure);
masm.compareStrings(op, left, right, scratchReg, &restore);
masm.tagValue(JSVAL_TYPE_BOOLEAN, scratchReg, R0);
EmitReturnFromIC(masm);
masm.bind(&restore);
masm.tagValue(JSVAL_TYPE_STRING, left, R0);
masm.tagValue(JSVAL_TYPE_STRING, right, R1);
masm.bind(&failure);
EmitStubGuardFailure(masm);
return true;

Просмотреть файл

@ -832,10 +832,6 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
unboxNonDouble(value, value.payloadReg(), JSVAL_TYPE_OBJECT);
return value.payloadReg();
}
Register extractString(const ValueOperand& value, Register scratch) {
unboxNonDouble(value, value.payloadReg(), JSVAL_TYPE_STRING);
return value.payloadReg();
}
Register extractSymbol(const ValueOperand& value, Register scratch) {
unboxNonDouble(value, value.payloadReg(), JSVAL_TYPE_SYMBOL);
return value.payloadReg();

Просмотреть файл

@ -418,10 +418,6 @@ class MacroAssemblerCompat : public vixl::MacroAssembler
unboxObject(value, scratch);
return scratch;
}
Register extractString(const ValueOperand& value, Register scratch) {
unboxString(value, scratch);
return scratch;
}
Register extractSymbol(const ValueOperand& value, Register scratch) {
unboxSymbol(value, scratch);
return scratch;

Просмотреть файл

@ -334,7 +334,6 @@ class MacroAssemblerNone : public Assembler
void notBoolean(ValueOperand) { MOZ_CRASH(); }
Register extractObject(Address, Register) { MOZ_CRASH(); }
Register extractObject(ValueOperand, Register) { MOZ_CRASH(); }
Register extractString(ValueOperand, Register) { MOZ_CRASH(); }
Register extractSymbol(ValueOperand, Register) { MOZ_CRASH(); }
Register extractInt32(ValueOperand, Register) { MOZ_CRASH(); }
Register extractBoolean(ValueOperand, Register) { MOZ_CRASH(); }

Просмотреть файл

@ -885,11 +885,6 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
unboxObject(value, scratch);
return scratch;
}
Register extractString(const ValueOperand& value, Register scratch) {
MOZ_ASSERT(scratch != ScratchReg);
unboxString(value, scratch);
return scratch;
}
Register extractSymbol(const ValueOperand& value, Register scratch) {
MOZ_ASSERT(scratch != ScratchReg);
unboxSymbol(value, scratch);

Просмотреть файл

@ -837,10 +837,6 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
unboxNonDouble(value, value.payloadReg(), JSVAL_TYPE_OBJECT, scratch);
return value.payloadReg();
}
Register extractString(const ValueOperand& value, Register scratch) {
unboxNonDouble(value, value.payloadReg(), JSVAL_TYPE_STRING, scratch);
return value.payloadReg();
}
Register extractSymbol(const ValueOperand& value, Register scratch) {
unboxNonDouble(value, value.payloadReg(), JSVAL_TYPE_SYMBOL, scratch);
return value.payloadReg();

Просмотреть файл

@ -40,18 +40,9 @@ using mozilla::BinarySearch;
using mozilla::MakeEnumeratedRange;
using mozilla::PodAssign;
bool
CodeSegment::registerInProcessMap()
{
if (!RegisterCodeSegment(this))
return false;
registered_ = true;
return true;
}
CodeSegment::~CodeSegment()
{
if (registered_)
if (unregisterOnDestroy_)
UnregisterCodeSegment(this);
}
@ -97,6 +88,26 @@ CodeSegment::AllocateCodeBytes(uint32_t codeLength)
return UniqueCodeBytes((uint8_t*)p, FreeCode(roundedCodeLength));
}
bool
CodeSegment::initialize(const CodeTier& codeTier)
{
MOZ_ASSERT(!initialized());
codeTier_ = &codeTier;
MOZ_ASSERT(initialized());
// In the case of tiering, RegisterCodeSegment() immediately makes this code
// segment live to access from other threads executing the containing
// module. So only call once the CodeSegment is fully initialized.
if (!RegisterCodeSegment(this))
return false;
// This bool is only used by the destructor which cannot be called racily
// and so it is not a problem to mutate it after RegisterCodeSegment().
MOZ_ASSERT(!unregisterOnDestroy_);
unregisterOnDestroy_ = true;
return true;
}
const Code&
CodeSegment::code() const
{
@ -107,7 +118,7 @@ CodeSegment::code() const
void
CodeSegment::addSizeOfMisc(MallocSizeOf mallocSizeOf, size_t* code) const
{
*code += RoundupCodeLength(length_);
*code += RoundupCodeLength(length());
}
void
@ -261,13 +272,20 @@ SendCodeRangesToProfiler(const ModuleSegment& ms, const Bytes& bytecode, const M
}
}
ModuleSegment::ModuleSegment(Tier tier,
UniqueCodeBytes codeBytes,
uint32_t codeLength,
const LinkDataTier& linkData)
: CodeSegment(Move(codeBytes), codeLength, CodeSegment::Kind::Module),
tier_(tier),
outOfBoundsCode_(base() + linkData.outOfBoundsOffset),
unalignedAccessCode_(base() + linkData.unalignedAccessOffset),
trapCode_(base() + linkData.trapOffset)
{
}
/* static */ UniqueModuleSegment
ModuleSegment::create(Tier tier,
MacroAssembler& masm,
const ShareableBytes& bytecode,
const LinkDataTier& linkData,
const Metadata& metadata,
const CodeRangeVector& codeRanges)
ModuleSegment::create(Tier tier, MacroAssembler& masm, const LinkDataTier& linkData)
{
uint32_t codeLength = masm.bytesNeeded();
@ -278,16 +296,11 @@ ModuleSegment::create(Tier tier,
// We'll flush the icache after static linking, in initialize().
masm.executableCopy(codeBytes.get(), /* flushICache = */ false);
return create(tier, Move(codeBytes), codeLength, bytecode, linkData, metadata, codeRanges);
return js::MakeUnique<ModuleSegment>(tier, Move(codeBytes), codeLength, linkData);
}
/* static */ UniqueModuleSegment
ModuleSegment::create(Tier tier,
const Bytes& unlinkedBytes,
const ShareableBytes& bytecode,
const LinkDataTier& linkData,
const Metadata& metadata,
const CodeRangeVector& codeRanges)
ModuleSegment::create(Tier tier, const Bytes& unlinkedBytes, const LinkDataTier& linkData)
{
uint32_t codeLength = unlinkedBytes.length();
@ -297,69 +310,35 @@ ModuleSegment::create(Tier tier,
memcpy(codeBytes.get(), unlinkedBytes.begin(), codeLength);
return create(tier, Move(codeBytes), codeLength, bytecode, linkData, metadata, codeRanges);
}
/* static */ UniqueModuleSegment
ModuleSegment::create(Tier tier,
UniqueCodeBytes codeBytes,
uint32_t codeLength,
const ShareableBytes& bytecode,
const LinkDataTier& linkData,
const Metadata& metadata,
const CodeRangeVector& codeRanges)
{
// These should always exist and should never be first in the code segment.
auto ms = js::MakeUnique<ModuleSegment>();
if (!ms)
return nullptr;
if (!ms->initialize(tier, Move(codeBytes), codeLength, bytecode, linkData, metadata, codeRanges))
return nullptr;
return UniqueModuleSegment(ms.release());
return js::MakeUnique<ModuleSegment>(tier, Move(codeBytes), codeLength, linkData);
}
bool
ModuleSegment::initialize(Tier tier,
UniqueCodeBytes codeBytes,
uint32_t codeLength,
ModuleSegment::initialize(const CodeTier& codeTier,
const ShareableBytes& bytecode,
const LinkDataTier& linkData,
const Metadata& metadata,
const CodeRangeVector& codeRanges)
const MetadataTier& metadataTier)
{
MOZ_ASSERT(!bytes_);
tier_ = tier;
bytes_ = Move(codeBytes);
length_ = codeLength;
outOfBoundsCode_ = bytes_.get() + linkData.outOfBoundsOffset;
unalignedAccessCode_ = bytes_.get() + linkData.unalignedAccessOffset;
trapCode_ = bytes_.get() + linkData.trapOffset;
if (!StaticallyLink(*this, linkData))
return false;
ExecutableAllocator::cacheFlush(bytes_.get(), RoundupCodeLength(codeLength));
ExecutableAllocator::cacheFlush(base(), RoundupCodeLength(length()));
// Reprotect the whole region to avoid having separate RW and RX mappings.
if (!ExecutableAllocator::makeExecutable(bytes_.get(), RoundupCodeLength(codeLength)))
if (!ExecutableAllocator::makeExecutable(base(), RoundupCodeLength(length())))
return false;
if (!registerInProcessMap())
return false;
SendCodeRangesToProfiler(*this, bytecode.bytes, metadata, metadataTier.codeRanges);
SendCodeRangesToProfiler(*this, bytecode.bytes, metadata, codeRanges);
return true;
// See comments in CodeSegment::initialize() for why this must be last.
return CodeSegment::initialize(codeTier);
}
size_t
ModuleSegment::serializedSize() const
{
return sizeof(uint32_t) + length_;
return sizeof(uint32_t) + length();
}
void
@ -374,17 +353,16 @@ ModuleSegment::serialize(uint8_t* cursor, const LinkDataTier& linkData) const
{
MOZ_ASSERT(tier() == Tier::Serialized);
cursor = WriteScalar<uint32_t>(cursor, length_);
uint8_t* base = cursor;
cursor = WriteBytes(cursor, bytes_.get(), length_);
StaticallyUnlink(base, linkData);
cursor = WriteScalar<uint32_t>(cursor, length());
uint8_t* serializedBase = cursor;
cursor = WriteBytes(cursor, base(), length());
StaticallyUnlink(serializedBase, linkData);
return cursor;
}
const uint8_t*
ModuleSegment::deserialize(const uint8_t* cursor, const ShareableBytes& bytecode,
const LinkDataTier& linkData, const Metadata& metadata,
const CodeRangeVector& codeRanges)
/* static */ const uint8_t*
ModuleSegment::deserialize(const uint8_t* cursor, const LinkDataTier& linkData,
UniqueModuleSegment* segment)
{
uint32_t length;
cursor = ReadScalar<uint32_t>(cursor, &length);
@ -399,7 +377,8 @@ ModuleSegment::deserialize(const uint8_t* cursor, const ShareableBytes& bytecode
if (!cursor)
return nullptr;
if (!initialize(Tier::Serialized, Move(bytes), length, bytecode, linkData, metadata, codeRanges))
*segment = js::MakeUnique<ModuleSegment>(Tier::Serialized, Move(bytes), length, linkData);
if (!*segment)
return nullptr;
return cursor;
@ -560,17 +539,6 @@ MetadataTier::deserialize(const uint8_t* cursor)
return cursor;
}
bool
LazyStubSegment::initialize(UniqueCodeBytes codeBytes, size_t length)
{
MOZ_ASSERT(bytes_ == nullptr);
bytes_ = Move(codeBytes);
length_ = length;
return registerInProcessMap();
}
UniqueLazyStubSegment
LazyStubSegment::create(const CodeTier& codeTier, size_t length)
{
@ -578,9 +546,10 @@ LazyStubSegment::create(const CodeTier& codeTier, size_t length)
if (!codeBytes)
return nullptr;
auto segment = js::MakeUnique<LazyStubSegment>(codeTier);
if (!segment || !segment->initialize(Move(codeBytes), length))
auto segment = js::MakeUnique<LazyStubSegment>(Move(codeBytes), length);
if (!segment || !segment->initialize(codeTier))
return nullptr;
return segment;
}
@ -588,8 +557,8 @@ bool
LazyStubSegment::hasSpace(size_t bytes) const
{
MOZ_ASSERT(bytes % MPROTECT_PAGE_SIZE == 0);
return bytes <= length_ &&
usedBytes_ <= length_ - bytes;
return bytes <= length() &&
usedBytes_ <= length() - bytes;
}
bool
@ -1021,24 +990,25 @@ CodeTier::serialize(uint8_t* cursor, const LinkDataTier& linkData) const
return cursor;
}
const uint8_t*
CodeTier::deserialize(const uint8_t* cursor, const SharedBytes& bytecode, Metadata& metadata,
const LinkDataTier& linkData)
/* static */ const uint8_t*
CodeTier::deserialize(const uint8_t* cursor, const LinkDataTier& linkData,
UniqueCodeTier* codeTier)
{
metadata_ = js::MakeUnique<MetadataTier>(Tier::Serialized);
if (!metadata_)
auto metadata = js::MakeUnique<MetadataTier>(Tier::Serialized);
if (!metadata)
return nullptr;
cursor = metadata_->deserialize(cursor);
cursor = metadata->deserialize(cursor);
if (!cursor)
return nullptr;
auto segment = Move(js::MakeUnique<ModuleSegment>());
if (!segment)
return nullptr;
cursor = segment->deserialize(cursor, *bytecode, linkData, metadata, metadata_->codeRanges);
UniqueModuleSegment segment;
cursor = ModuleSegment::deserialize(cursor, linkData, &segment);
if (!cursor)
return nullptr;
segment_ = takeOwnership(Move(segment));
*codeTier = js::MakeUnique<CodeTier>(Move(metadata), Move(segment));
if (!*codeTier)
return nullptr;
return cursor;
}
@ -1108,25 +1078,38 @@ JumpTables::init(CompileMode mode, const ModuleSegment& ms, const CodeRangeVecto
return true;
}
Code::Code(UniqueCodeTier codeTier, const Metadata& metadata, JumpTables&& maybeJumpTables)
: tier1_(takeOwnership(Move(codeTier))),
Code::Code(UniqueCodeTier tier1, const Metadata& metadata, JumpTables&& maybeJumpTables)
: tier1_(Move(tier1)),
metadata_(&metadata),
profilingLabels_(mutexid::WasmCodeProfilingLabels, CacheableCharsVector()),
jumpTables_(Move(maybeJumpTables))
{}
bool
Code::initialize(const ShareableBytes& bytecode, const LinkDataTier& linkData)
{
MOZ_ASSERT(!initialized());
if (!tier1_->initialize(*this, bytecode, linkData, *metadata_))
return false;
MOZ_ASSERT(initialized());
return true;
}
Code::Code()
: profilingLabels_(mutexid::WasmCodeProfilingLabels, CacheableCharsVector())
{
}
void
Code::setTier2(UniqueCodeTier tier2) const
bool
Code::setTier2(UniqueCodeTier tier2, const ShareableBytes& bytecode,
const LinkDataTier& linkData) const
{
MOZ_RELEASE_ASSERT(!hasTier2());
MOZ_RELEASE_ASSERT(tier2->tier() == Tier::Ion && tier1_->tier() == Tier::Baseline);
tier2_ = takeOwnership(Move(tier2));
if (!tier2->initialize(*this, bytecode, linkData, *metadata_))
return false;
tier2_ = Move(tier2);
return true;
}
void
@ -1135,6 +1118,7 @@ Code::commitTier2() const
MOZ_RELEASE_ASSERT(!hasTier2());
MOZ_RELEASE_ASSERT(tier2_.get());
hasTier2_ = true;
MOZ_ASSERT(hasTier2());
}
uint32_t
@ -1180,14 +1164,20 @@ Code::codeTier(Tier tier) const
{
switch (tier) {
case Tier::Baseline:
if (tier1_->tier() == Tier::Baseline)
if (tier1_->tier() == Tier::Baseline) {
MOZ_ASSERT(tier1_->initialized());
return *tier1_;
}
MOZ_CRASH("No code segment at this tier");
case Tier::Ion:
if (tier1_->tier() == Tier::Ion)
if (tier1_->tier() == Tier::Ion) {
MOZ_ASSERT(tier1_->initialized());
return *tier1_;
if (hasTier2())
}
if (tier2_) {
MOZ_ASSERT(tier2_->initialized());
return *tier2_;
}
MOZ_CRASH("No code segment at this tier");
default:
MOZ_CRASH();
@ -1370,6 +1360,25 @@ Code::addSizeOfMiscIfNotSeen(MallocSizeOf mallocSizeOf,
codeTier(t).addSizeOfMisc(mallocSizeOf, code, data);
}
bool
CodeTier::initialize(const Code& code,
const ShareableBytes& bytecode,
const LinkDataTier& linkData,
const Metadata& metadata)
{
MOZ_ASSERT(!initialized());
code_ = &code;
MOZ_ASSERT(lazyStubs_.lock()->empty());
// See comments in CodeSegment::initialize() for why this must be last.
if (!segment_->initialize(*this, bytecode, linkData, metadata, *metadata_))
return false;
MOZ_ASSERT(initialized());
return true;
}
size_t
Code::serializedSize() const
{
@ -1378,35 +1387,39 @@ Code::serializedSize() const
}
uint8_t*
Code::serialize(uint8_t* cursor, const LinkDataTier& linkDataTier) const
Code::serialize(uint8_t* cursor, const LinkData& linkData) const
{
MOZ_RELEASE_ASSERT(!metadata().debugEnabled);
cursor = metadata().serialize(cursor);
cursor = codeTier(Tier::Serialized).serialize(cursor, linkDataTier);
cursor = codeTier(Tier::Serialized).serialize(cursor, linkData.tier(Tier::Serialized));
return cursor;
}
const uint8_t*
Code::deserialize(const uint8_t* cursor, const SharedBytes& bytecode,
const LinkDataTier& linkDataTier, Metadata& metadata)
/* static */ const uint8_t*
Code::deserialize(const uint8_t* cursor,
const ShareableBytes& bytecode,
const LinkData& linkData,
Metadata& metadata,
SharedCode* out)
{
cursor = metadata.deserialize(cursor);
if (!cursor)
return nullptr;
auto codeTier = js::MakeUnique<CodeTier>(Tier::Serialized);
if (!codeTier)
return nullptr;
cursor = codeTier->deserialize(cursor, bytecode, metadata, linkDataTier);
UniqueCodeTier codeTier;
cursor = CodeTier::deserialize(cursor, linkData.tier(Tier::Serialized), &codeTier);
if (!cursor)
return nullptr;
tier1_ = takeOwnership(Move(codeTier));
metadata_ = &metadata;
if (!jumpTables_.init(CompileMode::Once, tier1_->segment(), tier1_->metadata().codeRanges))
JumpTables jumpTables;
if (!jumpTables.init(CompileMode::Once, codeTier->segment(), codeTier->metadata().codeRanges))
return nullptr;
MutableCode code = js_new<Code>(Move(codeTier), metadata, Move(jumpTables));
if (!code || !code->initialize(bytecode, linkData.tier(Tier::Serialized)))
return nullptr;
*out = code;
return cursor;
}

Просмотреть файл

@ -34,6 +34,7 @@ namespace wasm {
struct LinkDataTier;
struct MetadataTier;
struct Metadata;
class LinkData;
// ShareableBytes is a reference-counted Vector of bytes.
@ -81,30 +82,30 @@ class CodeSegment
protected:
static UniqueCodeBytes AllocateCodeBytes(uint32_t codeLength);
UniqueCodeBytes bytes_;
uint32_t length_;
// A back reference to the owning code.
const CodeTier* codeTier_;
enum class Kind {
LazyStubs,
Module
} kind_;
};
bool registerInProcessMap();
private:
bool registered_;
public:
explicit CodeSegment(Kind kind = Kind::Module)
: length_(UINT32_MAX),
codeTier_(nullptr),
CodeSegment(UniqueCodeBytes bytes, uint32_t length, Kind kind)
: bytes_(Move(bytes)),
length_(length),
kind_(kind),
registered_(false)
codeTier_(nullptr),
unregisterOnDestroy_(false)
{}
bool initialize(const CodeTier& codeTier);
private:
const UniqueCodeBytes bytes_;
const uint32_t length_;
const Kind kind_;
const CodeTier* codeTier_;
bool unregisterOnDestroy_;
public:
bool initialized() const { return !!codeTier_; }
~CodeSegment();
bool isLazyStubs() const { return kind_ == Kind::LazyStubs; }
@ -125,11 +126,7 @@ class CodeSegment
return pc >= base() && pc < (base() + length_);
}
void initCodeTier(const CodeTier* codeTier) {
MOZ_ASSERT(!codeTier_);
codeTier_ = codeTier;
}
const CodeTier& codeTier() const { return *codeTier_; }
const CodeTier& codeTier() const { MOZ_ASSERT(initialized()); return *codeTier_; }
const Code& code() const;
void addSizeOfMisc(MallocSizeOf mallocSizeOf, size_t* code) const;
@ -138,61 +135,37 @@ class CodeSegment
// A wasm ModuleSegment owns the allocated executable code for a wasm module.
typedef UniquePtr<ModuleSegment> UniqueModuleSegment;
typedef UniquePtr<const ModuleSegment> UniqueConstModuleSegment;
class ModuleSegment : public CodeSegment
{
Tier tier_;
const Tier tier_;
uint8_t* const outOfBoundsCode_;
uint8_t* const unalignedAccessCode_;
uint8_t* const trapCode_;
// These are pointers into code for stubs used for signal-handler
// control-flow transfer.
uint8_t* outOfBoundsCode_;
uint8_t* unalignedAccessCode_;
uint8_t* trapCode_;
bool initialize(Tier tier,
UniqueCodeBytes bytes,
uint32_t codeLength,
const ShareableBytes& bytecode,
const LinkDataTier& linkData,
const Metadata& metadata,
const CodeRangeVector& codeRanges);
static UniqueModuleSegment create(Tier tier,
UniqueCodeBytes bytes,
uint32_t codeLength,
const ShareableBytes& bytecode,
const LinkDataTier& linkData,
const Metadata& metadata,
const CodeRangeVector& codeRanges);
public:
ModuleSegment(const ModuleSegment&) = delete;
void operator=(const ModuleSegment&) = delete;
ModuleSegment()
: CodeSegment(),
tier_(Tier(-1)),
outOfBoundsCode_(nullptr),
unalignedAccessCode_(nullptr),
trapCode_(nullptr)
{}
ModuleSegment(Tier tier,
UniqueCodeBytes codeBytes,
uint32_t codeLength,
const LinkDataTier& linkData);
static UniqueModuleSegment create(Tier tier,
jit::MacroAssembler& masm,
const ShareableBytes& bytecode,
const LinkDataTier& linkData,
const Metadata& metadata,
const CodeRangeVector& codeRanges);
const LinkDataTier& linkData);
static UniqueModuleSegment create(Tier tier,
const Bytes& unlinkedBytes,
const LinkDataTier& linkData);
bool initialize(const CodeTier& codeTier,
const ShareableBytes& bytecode,
const LinkDataTier& linkData,
const Metadata& metadata,
const CodeRangeVector& codeRanges);
const MetadataTier& metadataTier);
Tier tier() const { return tier_; }
// Pointers to stubs to which PC is redirected from the signal-handler.
uint8_t* outOfBoundsCode() const { return outOfBoundsCode_; }
uint8_t* unalignedAccessCode() const { return unalignedAccessCode_; }
uint8_t* trapCode() const { return trapCode_; }
@ -200,10 +173,9 @@ class ModuleSegment : public CodeSegment
// Structured clone support:
size_t serializedSize() const;
uint8_t* serialize(uint8_t* cursor, const LinkDataTier& linkDataTier) const;
const uint8_t* deserialize(const uint8_t* cursor, const ShareableBytes& bytecode,
const LinkDataTier& linkDataTier, const Metadata& metadata,
const CodeRangeVector& codeRanges);
uint8_t* serialize(uint8_t* cursor, const LinkDataTier& linkData) const;
static const uint8_t* deserialize(const uint8_t* cursor, const LinkDataTier& linkData,
UniqueModuleSegment* segment);
const CodeRange* lookupRange(const void* pc) const;
@ -527,6 +499,9 @@ using UniqueMetadataTier = UniquePtr<MetadataTier>;
// isn't (64KiB), a given stub segment can contain entry stubs of many
// functions.
using UniqueLazyStubSegment = UniquePtr<LazyStubSegment>;
using LazyStubSegmentVector = Vector<UniqueLazyStubSegment, 0, SystemAllocPolicy>;
class LazyStubSegment : public CodeSegment
{
CodeRangeVector codeRanges_;
@ -534,17 +509,14 @@ class LazyStubSegment : public CodeSegment
static constexpr size_t MPROTECT_PAGE_SIZE = 4 * 1024;
bool initialize(UniqueCodeBytes codeBytes, size_t length);
public:
explicit LazyStubSegment(const CodeTier& codeTier)
: CodeSegment(CodeSegment::Kind::LazyStubs),
LazyStubSegment(UniqueCodeBytes bytes, size_t length)
: CodeSegment(Move(bytes), length, CodeSegment::Kind::LazyStubs),
usedBytes_(0)
{
initCodeTier(&codeTier);
}
{}
static UniqueLazyStubSegment create(const CodeTier& codeTier, size_t codeLength);
static UniquePtr<LazyStubSegment> create(const CodeTier& codeTier, size_t length);
static size_t AlignBytesNeeded(size_t bytes) { return AlignBytes(bytes, MPROTECT_PAGE_SIZE); }
bool hasSpace(size_t bytes) const;
@ -558,9 +530,6 @@ class LazyStubSegment : public CodeSegment
void addSizeOfMisc(MallocSizeOf mallocSizeOf, size_t* code, size_t* data) const;
};
using UniqueLazyStubSegment = UniquePtr<LazyStubSegment>;
using LazyStubSegmentVector = Vector<UniqueLazyStubSegment, 0, SystemAllocPolicy>;
// LazyFuncExport helps to efficiently lookup a CodeRange from a given function
// index. It is inserted in a vector sorted by function index, to perform
// binary search on it later.
@ -623,23 +592,20 @@ class LazyStubTier
// CodeTier contains all the data related to a given compilation tier. It is
// built during module generation and then immutably stored in a Code.
typedef UniquePtr<CodeTier> UniqueCodeTier;
typedef UniquePtr<const CodeTier> UniqueConstCodeTier;
class CodeTier
{
const Tier tier_;
const Code* code_;
// Serialized information.
UniqueMetadataTier metadata_;
UniqueConstModuleSegment segment_;
const UniqueMetadataTier metadata_;
const UniqueModuleSegment segment_;
// Lazy stubs, not serialized.
ExclusiveData<LazyStubTier> lazyStubs_;
UniqueConstModuleSegment takeOwnership(UniqueModuleSegment segment) const {
segment->initCodeTier(this);
return UniqueConstModuleSegment(segment.release());
}
static const MutexId& mutexForTier(Tier tier) {
if (tier == Tier::Baseline)
return mutexid::WasmLazyStubsTier1;
@ -648,45 +614,35 @@ class CodeTier
}
public:
explicit CodeTier(Tier tier)
: tier_(tier),
code_(nullptr),
metadata_(nullptr),
segment_(nullptr),
lazyStubs_(mutexForTier(tier))
{}
CodeTier(Tier tier, UniqueMetadataTier metadata, UniqueModuleSegment segment)
: tier_(tier),
code_(nullptr),
CodeTier(UniqueMetadataTier metadata, UniqueModuleSegment segment)
: code_(nullptr),
metadata_(Move(metadata)),
segment_(takeOwnership(Move(segment))),
lazyStubs_(mutexForTier(tier))
segment_(Move(segment)),
lazyStubs_(mutexForTier(segment_->tier()))
{}
void initCode(const Code* code) {
MOZ_ASSERT(!code_);
code_ = code;
}
bool initialized() const { return !!code_ && segment_->initialized(); }
Tier tier() const { return tier_; }
bool initialize(const Code& code,
const ShareableBytes& bytecode,
const LinkDataTier& linkData,
const Metadata& metadata);
Tier tier() const { return segment_->tier(); }
const ExclusiveData<LazyStubTier>& lazyStubs() const { return lazyStubs_; }
const MetadataTier& metadata() const { return *metadata_.get(); }
const ModuleSegment& segment() const { return *segment_.get(); }
const Code& code() const { return *code_; }
const Code& code() const { MOZ_ASSERT(initialized()); return *code_; }
const CodeRange* lookupRange(const void* pc) const;
size_t serializedSize() const;
uint8_t* serialize(uint8_t* cursor, const LinkDataTier& linkData) const;
const uint8_t* deserialize(const uint8_t* cursor, const SharedBytes& bytecode,
Metadata& metadata, const LinkDataTier& linkData);
static const uint8_t* deserialize(const uint8_t* cursor, const LinkDataTier& linkData,
UniqueCodeTier* codeTier);
void addSizeOfMisc(MallocSizeOf mallocSizeOf, size_t* code, size_t* data) const;
};
typedef UniquePtr<CodeTier> UniqueCodeTier;
typedef UniquePtr<const CodeTier> UniqueConstCodeTier;
// Jump tables to take tiering into account, when calling either from wasm to
// wasm (through rabaldr) or from jit to wasm (jit entry).
@ -743,23 +699,23 @@ class JumpTables
//
// profilingLabels_ is lazily initialized, but behind a lock.
typedef RefPtr<const Code> SharedCode;
typedef RefPtr<Code> MutableCode;
class Code : public ShareableBase<Code>
{
UniqueConstCodeTier tier1_;
UniqueCodeTier tier1_;
mutable UniqueConstCodeTier tier2_; // Access only when hasTier2() is true
mutable Atomic<bool> hasTier2_;
SharedMetadata metadata_;
ExclusiveData<CacheableCharsVector> profilingLabels_;
JumpTables jumpTables_;
UniqueConstCodeTier takeOwnership(UniqueCodeTier codeTier) const {
codeTier->initCode(this);
return UniqueConstCodeTier(codeTier.release());
}
public:
Code();
Code(UniqueCodeTier tier, const Metadata& metadata, JumpTables&& maybeJumpTables);
Code(UniqueCodeTier tier1, const Metadata& metadata, JumpTables&& maybeJumpTables);
bool initialized() const { return tier1_->initialized(); }
bool initialize(const ShareableBytes& bytecode, const LinkDataTier& linkData);
void setTieringEntry(size_t i, void* target) const { jumpTables_.setTieringEntry(i, target); }
void** tieringJumpTable() const { return jumpTables_.tiering(); }
@ -768,7 +724,8 @@ class Code : public ShareableBase<Code>
void** getAddressOfJitEntry(size_t i) const { return jumpTables_.getAddressOfJitEntry(i); }
uint32_t getFuncIndex(JSFunction* fun) const;
void setTier2(UniqueCodeTier tier2) const;
bool setTier2(UniqueCodeTier tier2, const ShareableBytes& bytecode,
const LinkDataTier& linkData) const;
void commitTier2() const;
bool hasTier2() const { return hasTier2_; }
@ -814,14 +771,14 @@ class Code : public ShareableBase<Code>
// machine code and other parts.
size_t serializedSize() const;
uint8_t* serialize(uint8_t* cursor, const LinkDataTier& linkDataTier) const;
const uint8_t* deserialize(const uint8_t* cursor, const SharedBytes& bytecode,
const LinkDataTier& linkDataTier, Metadata& metadata);
uint8_t* serialize(uint8_t* cursor, const LinkData& linkData) const;
static const uint8_t* deserialize(const uint8_t* cursor,
const ShareableBytes& bytecode,
const LinkData& linkData,
Metadata& metadata,
SharedCode* code);
};
typedef RefPtr<const Code> SharedCode;
typedef RefPtr<Code> MutableCode;
} // namespace wasm
} // namespace js

Просмотреть файл

@ -943,8 +943,7 @@ ModuleGenerator::finish(const ShareableBytes& bytecode)
if (!finishMetadata(bytecode))
return nullptr;
return ModuleSegment::create(tier(), masm_, bytecode, *linkDataTier_, *metadata_,
metadataTier_->codeRanges);
return ModuleSegment::create(tier(), masm_, *linkDataTier_);
}
SharedModule
@ -972,12 +971,12 @@ ModuleGenerator::finishModule(const ShareableBytes& bytecode)
return nullptr;
}
auto codeTier = js::MakeUnique<CodeTier>(tier(), Move(metadataTier_), Move(moduleSegment));
auto codeTier = js::MakeUnique<CodeTier>(Move(metadataTier_), Move(moduleSegment));
if (!codeTier)
return nullptr;
SharedCode code = js_new<Code>(Move(codeTier), *metadata_, Move(jumpTables));
if (!code)
MutableCode code = js_new<Code>(Move(codeTier), *metadata_, Move(jumpTables));
if (!code || !code->initialize(bytecode, *linkDataTier_))
return nullptr;
SharedModule module(js_new<Module>(Move(assumptions_),
@ -1012,7 +1011,7 @@ ModuleGenerator::finishTier2(Module& module)
if (!moduleSegment)
return false;
auto tier2 = js::MakeUnique<CodeTier>(tier(), Move(metadataTier_), Move(moduleSegment));
auto tier2 = js::MakeUnique<CodeTier>(Move(metadataTier_), Move(moduleSegment));
if (!tier2)
return false;

Просмотреть файл

@ -110,26 +110,26 @@ LinkDataTier::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
}
void
LinkData::setTier2(UniqueLinkDataTier linkData) const
LinkData::setTier2(UniqueLinkDataTier tier) const
{
MOZ_RELEASE_ASSERT(linkData->tier == Tier::Ion && linkData1_->tier == Tier::Baseline);
MOZ_RELEASE_ASSERT(!linkData2_.get());
linkData2_ = Move(linkData);
MOZ_RELEASE_ASSERT(tier->tier == Tier::Ion && tier1_->tier == Tier::Baseline);
MOZ_RELEASE_ASSERT(!tier2_.get());
tier2_ = Move(tier);
}
const LinkDataTier&
LinkData::linkData(Tier tier) const
LinkData::tier(Tier tier) const
{
switch (tier) {
case Tier::Baseline:
if (linkData1_->tier == Tier::Baseline)
return *linkData1_;
if (tier1_->tier == Tier::Baseline)
return *tier1_;
MOZ_CRASH("No linkData at this tier");
case Tier::Ion:
if (linkData1_->tier == Tier::Ion)
return *linkData1_;
if (linkData2_)
return *linkData2_;
if (tier1_->tier == Tier::Ion)
return *tier1_;
if (tier2_)
return *tier2_;
MOZ_CRASH("No linkData at this tier");
default:
MOZ_CRASH();
@ -139,24 +139,24 @@ LinkData::linkData(Tier tier) const
size_t
LinkData::serializedSize() const
{
return linkData(Tier::Serialized).serializedSize();
return tier(Tier::Serialized).serializedSize();
}
uint8_t*
LinkData::serialize(uint8_t* cursor) const
{
cursor = linkData(Tier::Serialized).serialize(cursor);
cursor = tier(Tier::Serialized).serialize(cursor);
return cursor;
}
const uint8_t*
LinkData::deserialize(const uint8_t* cursor)
{
MOZ_ASSERT(!linkData1_);
linkData1_ = js::MakeUnique<LinkDataTier>(Tier::Serialized);
if (!linkData1_)
MOZ_ASSERT(!tier1_);
tier1_ = js::MakeUnique<LinkDataTier>(Tier::Serialized);
if (!tier1_)
return nullptr;
cursor = linkData1_->deserialize(cursor);
cursor = tier1_->deserialize(cursor);
return cursor;
}
@ -164,9 +164,9 @@ size_t
LinkData::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
{
size_t sum = 0;
sum += linkData1_->sizeOfExcludingThis(mallocSizeOf);
if (linkData2_)
sum += linkData2_->sizeOfExcludingThis(mallocSizeOf);
sum += tier1_->sizeOfExcludingThis(mallocSizeOf);
if (tier2_)
sum += tier2_->sizeOfExcludingThis(mallocSizeOf);
return sum;
}
@ -243,10 +243,23 @@ Module::notifyCompilationListeners()
}
bool
Module::finishTier2(UniqueLinkDataTier linkData2, UniqueCodeTier tier2, ModuleEnvironment* env2)
Module::finishTier2(UniqueLinkDataTier linkData2, UniqueCodeTier tier2Arg, ModuleEnvironment* env2)
{
MOZ_ASSERT(code().bestTier() == Tier::Baseline && tier2->tier() == Tier::Ion);
MOZ_ASSERT(code().bestTier() == Tier::Baseline && tier2Arg->tier() == Tier::Ion);
// Install the data in the data structures. They will not be visible
// until commitTier2().
if (!code().setTier2(Move(tier2Arg), *bytecode_, *linkData2))
return false;
linkData().setTier2(Move(linkData2));
for (uint32_t i = 0; i < elemSegments_.length(); i++)
elemSegments_[i].setTier2(Move(env2->elemSegments[i].elemCodeRangeIndices(Tier::Ion)));
// Before we can make tier-2 live, we need to compile tier2 versions of any
// extant tier1 lazy stubs (otherwise, tiering would break the assumption
// that any extant exported wasm function has had a lazy entry stub already
// compiled for it).
{
// We need to prevent new tier1 stubs generation until we've committed
// the newer tier2 stubs, otherwise we might not generate one tier2
@ -255,7 +268,7 @@ Module::finishTier2(UniqueLinkDataTier linkData2, UniqueCodeTier tier2, ModuleEn
const MetadataTier& metadataTier1 = metadata(Tier::Baseline);
auto stubs1 = code().codeTier(Tier::Baseline).lazyStubs().lock();
auto stubs2 = tier2->lazyStubs().lock();
auto stubs2 = code().codeTier(Tier::Ion).lazyStubs().lock();
MOZ_ASSERT(stubs2->empty());
@ -272,23 +285,15 @@ Module::finishTier2(UniqueLinkDataTier linkData2, UniqueCodeTier tier2, ModuleEn
}
HasGcTypes gcTypesEnabled = code().metadata().temporaryHasGcTypes;
const CodeTier& tier2 = code().codeTier(Tier::Ion);
Maybe<size_t> stub2Index;
if (!stubs2->createTier2(gcTypesEnabled, funcExportIndices, *tier2, &stub2Index))
if (!stubs2->createTier2(gcTypesEnabled, funcExportIndices, tier2, &stub2Index))
return false;
// Install the data in the data structures. They will not be visible
// yet.
// Now that we can't fail or otherwise abort tier2, make it live.
MOZ_ASSERT(!code().hasTier2());
linkData().setTier2(Move(linkData2));
code().setTier2(Move(tier2));
for (uint32_t i = 0; i < elemSegments_.length(); i++)
elemSegments_[i].setTier2(Move(env2->elemSegments[i].elemCodeRangeIndices(Tier::Ion)));
// Now that all the code and metadata is valid, make tier 2 code
// visible and unblock anyone waiting on it.
code().commitTier2();
// Now tier2 is committed and we can update jump tables entries to
@ -418,7 +423,7 @@ Module::compiledSerialize(uint8_t* compiledBegin, size_t compiledSize) const
cursor = SerializeVector(cursor, exports_);
cursor = SerializePodVector(cursor, dataSegments_);
cursor = SerializeVector(cursor, elemSegments_);
cursor = code_->serialize(cursor, linkData_.linkData(Tier::Serialized));
cursor = code_->serialize(cursor, linkData_);
MOZ_RELEASE_ASSERT(cursor == compiledBegin + compiledSize);
}
@ -481,8 +486,8 @@ Module::deserialize(const uint8_t* bytecodeBegin, size_t bytecodeSize,
if (!cursor)
return nullptr;
MutableCode code = js_new<Code>();
cursor = code->deserialize(cursor, bytecode, linkData.linkData(Tier::Serialized), *metadata);
SharedCode code;
cursor = Code::deserialize(cursor, *bytecode, linkData, *metadata, &code);
if (!cursor)
return nullptr;
@ -1245,12 +1250,7 @@ Module::instantiate(JSContext* cx,
// may patch the pre-linked code at any time.
if (!codeIsBusy_.compareExchange(false, true)) {
Tier tier = Tier::Baseline;
auto segment = ModuleSegment::create(tier,
*unlinkedCodeForDebugging_,
*bytecode_,
linkData(tier),
metadata(),
metadata(tier).codeRanges);
auto segment = ModuleSegment::create(tier, *unlinkedCodeForDebugging_, linkData(tier));
if (!segment) {
ReportOutOfMemory(cx);
return false;
@ -1260,7 +1260,7 @@ Module::instantiate(JSContext* cx,
if (!metadataTier || !metadataTier->clone(metadata(tier)))
return false;
auto codeTier = js::MakeUnique<CodeTier>(tier, Move(metadataTier), Move(segment));
auto codeTier = js::MakeUnique<CodeTier>(Move(metadataTier), Move(segment));
if (!codeTier)
return false;
@ -1268,11 +1268,13 @@ Module::instantiate(JSContext* cx,
if (!jumpTables.init(CompileMode::Once, codeTier->segment(), metadata(tier).codeRanges))
return false;
code = js_new<Code>(Move(codeTier), metadata(), Move(jumpTables));
if (!code) {
MutableCode debugCode = js_new<Code>(Move(codeTier), metadata(), Move(jumpTables));
if (!debugCode || !debugCode->initialize(*bytecode_, linkData(tier))) {
ReportOutOfMemory(cx);
return false;
}
code = debugCode;
}
}

Просмотреть файл

@ -82,15 +82,15 @@ typedef UniquePtr<LinkDataTier> UniqueLinkDataTier;
class LinkData
{
UniqueLinkDataTier linkData1_; // Always present
mutable UniqueLinkDataTier linkData2_; // Access only if hasTier2() is true
UniqueLinkDataTier tier1_; // Always present
mutable UniqueLinkDataTier tier2_; // Access only if hasTier2() is true
public:
LinkData() {}
explicit LinkData(UniqueLinkDataTier linkData) : linkData1_(Move(linkData)) {}
explicit LinkData(UniqueLinkDataTier tier) : tier1_(Move(tier)) {}
void setTier2(UniqueLinkDataTier linkData) const;
const LinkDataTier& linkData(Tier tier) const;
const LinkDataTier& tier(Tier tier) const;
WASM_DECLARE_SERIALIZABLE(LinkData)
};
@ -192,7 +192,7 @@ class Module : public JS::WasmModule
const Metadata& metadata() const { return code_->metadata(); }
const MetadataTier& metadata(Tier t) const { return code_->metadata(t); }
const LinkData& linkData() const { return linkData_; }
const LinkDataTier& linkData(Tier t) const { return linkData_.linkData(t); }
const LinkDataTier& linkData(Tier t) const { return linkData_.tier(t); }
const ImportVector& imports() const { return imports_; }
const ExportVector& exports() const { return exports_; }
const ShareableBytes& bytecode() const { return *bytecode_; }

Просмотреть файл

@ -217,6 +217,7 @@ static ProcessCodeSegmentMap processCodeSegmentMap;
bool
wasm::RegisterCodeSegment(const CodeSegment* cs)
{
MOZ_ASSERT(cs->codeTier().code().initialized());
return processCodeSegmentMap.insert(cs);
}

Просмотреть файл

@ -375,7 +375,7 @@ nsDisplayCanvasBackgroundImage::IsSingleFixedPositionImage(nsDisplayListBuilder*
nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
const nsStyleImageLayers::Layer &layer = mBackgroundStyle->StyleBackground()->mImage.mLayers[mLayer];
if (layer.mAttachment != NS_STYLE_IMAGELAYER_ATTACHMENT_FIXED)
if (layer.mAttachment != StyleImageLayerAttachment::Fixed)
return false;
nsBackgroundLayerState state =

Просмотреть файл

@ -2334,7 +2334,7 @@ nsCSSRendering::GetImageLayerClip(const nsStyleImageLayers::Layer& aLayer,
aClipState->mBGClipArea = clipBorderArea;
if (aForFrame->IsScrollFrame() &&
NS_STYLE_IMAGELAYER_ATTACHMENT_LOCAL == aLayer.mAttachment) {
StyleImageLayerAttachment::Local == aLayer.mAttachment) {
// As of this writing, this is still in discussion in the CSS Working Group
// http://lists.w3.org/Archives/Public/www-style/2013Jul/0250.html
@ -2947,7 +2947,7 @@ nsCSSRendering::ComputeImageLayerPositioningArea(nsPresContext* aPresContext,
LayoutFrameType frameType = aForFrame->Type();
nsIFrame* geometryFrame = aForFrame;
if (MOZ_UNLIKELY(frameType == LayoutFrameType::Scroll &&
NS_STYLE_IMAGELAYER_ATTACHMENT_LOCAL == aLayer.mAttachment)) {
StyleImageLayerAttachment::Local == aLayer.mAttachment)) {
nsIScrollableFrame* scrollableFrame = do_QueryFrame(aForFrame);
positionArea = nsRect(
scrollableFrame->GetScrolledFrame()->GetPosition()
@ -3008,7 +3008,7 @@ nsCSSRendering::ComputeImageLayerPositioningArea(nsPresContext* aPresContext,
}
nsIFrame* attachedToFrame = aForFrame;
if (NS_STYLE_IMAGELAYER_ATTACHMENT_FIXED == aLayer.mAttachment) {
if (StyleImageLayerAttachment::Fixed == aLayer.mAttachment) {
// If it's a fixed background attachment, then the image is placed
// relative to the viewport, which is the area of the root frame
// in a screen context or the page content frame in a print context.
@ -3283,7 +3283,7 @@ nsCSSRendering::PrepareImageLayer(nsPresContext* aPresContext,
// where the background can be drawn to the viewport.
nsRect bgClipRect = aBGClipRect;
if (NS_STYLE_IMAGELAYER_ATTACHMENT_FIXED == aLayer.mAttachment &&
if (StyleImageLayerAttachment::Fixed == aLayer.mAttachment &&
!transformedFixed &&
(aFlags & nsCSSRendering::PAINTBG_TO_WINDOW)) {
bgClipRect = positionArea + aBorderArea.TopLeft();

Просмотреть файл

@ -3501,7 +3501,7 @@ nsDisplayBackgroundImage::GetInitData(nsDisplayListBuilder* aBuilder,
// if it's affected by a transform.
// See https://www.w3.org/Bugs/Public/show_bug.cgi?id=17521.
bool shouldTreatAsFixed =
layer.mAttachment == NS_STYLE_IMAGELAYER_ATTACHMENT_FIXED && !isTransformedFixed;
layer.mAttachment == StyleImageLayerAttachment::Fixed && !isTransformedFixed;
bool shouldFixToViewport = shouldTreatAsFixed && !layer.mImage.IsEmpty();
bool isRasterImage = state.mImageRenderer.IsRasterImage();

Просмотреть файл

@ -173,6 +173,7 @@ rusty-enums = [
"mozilla::StyleUserFocus",
"mozilla::StyleUserSelect",
"mozilla::StyleImageLayerRepeat",
"mozilla::StyleImageLayerAttachment",
"mozilla::StyleBoxDecorationBreak",
"mozilla::StyleRuleInclusion",
"mozilla::StyleGridTrackBreadth",
@ -243,6 +244,7 @@ whitelist-types = [
"mozilla::LookAndFeel",
"mozilla::gfx::Float",
"mozilla::gfx::FontVariation",
"mozilla::StyleImageLayerAttachment",
".*ThreadSafe.*Holder",
"AnonymousContent",
"AudioContext",

Просмотреть файл

@ -447,9 +447,9 @@ const KTableEntry nsCSSProps::kTransformStyleKTable[] = {
};
const KTableEntry nsCSSProps::kImageLayerAttachmentKTable[] = {
{ eCSSKeyword_fixed, NS_STYLE_IMAGELAYER_ATTACHMENT_FIXED },
{ eCSSKeyword_scroll, NS_STYLE_IMAGELAYER_ATTACHMENT_SCROLL },
{ eCSSKeyword_local, NS_STYLE_IMAGELAYER_ATTACHMENT_LOCAL },
{ eCSSKeyword_fixed, StyleImageLayerAttachment::Fixed },
{ eCSSKeyword_scroll, StyleImageLayerAttachment::Scroll },
{ eCSSKeyword_local, StyleImageLayerAttachment::Local },
{ eCSSKeyword_UNKNOWN, -1 }
};

Просмотреть файл

@ -254,9 +254,11 @@ enum class FillMode : uint8_t;
#define NS_STYLE_ANIMATION_PLAY_STATE_PAUSED 1
// See nsStyleImageLayers
#define NS_STYLE_IMAGELAYER_ATTACHMENT_SCROLL 0
#define NS_STYLE_IMAGELAYER_ATTACHMENT_FIXED 1
#define NS_STYLE_IMAGELAYER_ATTACHMENT_LOCAL 2
enum class StyleImageLayerAttachment : uint8_t {
Scroll,
Fixed,
Local
};
// A magic value that we use for our "pretend that background-clip is
// 'padding' when we have a solid border" optimization. This isn't

Просмотреть файл

@ -3111,7 +3111,7 @@ nsStyleImageLayers::Size::operator==(const Size& aOther) const
nsStyleImageLayers::Layer::Layer()
: mClip(StyleGeometryBox::BorderBox)
, mAttachment(NS_STYLE_IMAGELAYER_ATTACHMENT_SCROLL)
, mAttachment(StyleImageLayerAttachment::Scroll)
, mBlendMode(NS_STYLE_BLEND_NORMAL)
, mComposite(NS_STYLE_MASK_COMPOSITE_ADD)
, mMaskMode(NS_STYLE_MASK_MODE_MATCH_SOURCE)
@ -3350,7 +3350,7 @@ nsStyleBackground::HasFixedBackground(nsIFrame* aFrame) const
{
NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, mImage) {
const nsStyleImageLayers::Layer &layer = mImage.mLayers[i];
if (layer.mAttachment == NS_STYLE_IMAGELAYER_ATTACHMENT_FIXED &&
if (layer.mAttachment == StyleImageLayerAttachment::Fixed &&
!layer.mImage.IsEmpty() &&
!nsLayoutUtils::IsTransformed(aFrame)) {
return true;

Просмотреть файл

@ -653,6 +653,7 @@ struct nsStyleImageLayers {
struct Layer {
typedef mozilla::StyleGeometryBox StyleGeometryBox;
typedef mozilla::StyleImageLayerAttachment StyleImageLayerAttachment;
nsStyleImage mImage; // [reset]
mozilla::Position mPosition; // [reset]
@ -660,12 +661,13 @@ struct nsStyleImageLayers {
StyleGeometryBox mClip; // [reset] See nsStyleConsts.h
MOZ_INIT_OUTSIDE_CTOR
StyleGeometryBox mOrigin; // [reset] See nsStyleConsts.h
uint8_t mAttachment; // [reset] See nsStyleConsts.h
StyleImageLayerAttachment mAttachment;
// [reset] See nsStyleConsts.h
// background-only property
// This property is used for background layer
// only. For a mask layer, it should always
// be the initial value, which is
// NS_STYLE_IMAGELAYER_ATTACHMENT_SCROLL.
// StyleImageLayerAttachment::Scroll.
uint8_t mBlendMode; // [reset] See nsStyleConsts.h
// background-only property
// This property is used for background layer

Просмотреть файл

@ -266,7 +266,7 @@ nsStyleBackground::HasLocalBackground() const
NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, mImage) {
const nsStyleImageLayers::Layer& layer = mImage.mLayers[i];
if (!layer.mImage.IsEmpty() &&
layer.mAttachment == NS_STYLE_IMAGELAYER_ATTACHMENT_LOCAL) {
layer.mAttachment == mozilla::StyleImageLayerAttachment::Local) {
return true;
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -122,7 +122,7 @@ android {
}
if (!mozconfig.substs.MOZ_CRASHREPORTER) {
exclude 'org/mozilla/gecko/CrashReporter.java'
exclude 'org/mozilla/gecko/CrashReporterActivity.java'
}
if (!mozconfig.substs.MOZ_NATIVE_DEVICES) {

Просмотреть файл

@ -64,7 +64,7 @@
</issue>
<!-- We fixed all "Registered" lint errors. However the current gradle plugin has a bug where
it ignores @SuppressLint annotations for this check. See CrashReporter class and
it ignores @SuppressLint annotations for this check. See CrashReporterActivity class and
https://code.google.com/p/android/issues/detail?id=204846 -->
<issue id="Registered" severity="warning" />

Просмотреть файл

@ -272,7 +272,7 @@
#include ../services/manifests/FxAccountAndroidManifest_activities.xml.in
#ifdef MOZ_CRASHREPORTER
<activity android:name="org.mozilla.gecko.CrashReporter"
<activity android:name="org.mozilla.gecko.CrashReporterActivity"
android:process="@ANDROID_PACKAGE_NAME@.CrashReporter"
android:label="@string/crash_reporter_title"
android:icon="@drawable/crash_reporter"

Просмотреть файл

@ -28,7 +28,6 @@ import java.security.MessageDigest;
import java.util.zip.GZIPOutputStream;
import org.mozilla.gecko.AppConstants.Versions;
import org.mozilla.gecko.GeckoProfile;
import org.mozilla.gecko.mozglue.GeckoLoader;
import org.mozilla.gecko.mozglue.MinidumpAnalyzer;
import org.mozilla.gecko.telemetry.pingbuilders.TelemetryCrashPingBuilder;
@ -57,7 +56,7 @@ import android.widget.EditText;
// Registered: This activity is only registered in the manifest if MOZ_CRASHREPORTER is set.
// CutPasteId: This lint is not worth fixing. To fix it, cache all the findViewById results.
@SuppressLint("Registered,CutPasteId")
public class CrashReporter extends AppCompatActivity
public class CrashReporterActivity extends AppCompatActivity
{
private static final String LOGTAG = "GeckoCrashReporter";
@ -210,7 +209,7 @@ public class CrashReporter extends AppCompatActivity
final EditText commentsEditText = (EditText) findViewById(R.id.comment);
final EditText emailEditText = (EditText) findViewById(R.id.email);
// Load CrashReporter preferences to avoid redundant user input.
// Load CrashReporterActivity preferences to avoid redundant user input.
SharedPreferences prefs = GeckoSharedPrefs.forCrashReporter(this);
final boolean sendReport = prefs.getBoolean(PREFS_SEND_REPORT, true);
final boolean includeUrl = prefs.getBoolean(PREFS_INCLUDE_URL, false);
@ -271,7 +270,7 @@ public class CrashReporter extends AppCompatActivity
builder.setPositiveButton(R.string.button_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
CrashReporter.this.finish();
CrashReporterActivity.this.finish();
}
});
builder.show();
@ -293,7 +292,7 @@ public class CrashReporter extends AppCompatActivity
public void run() {
sendReport(mPendingMinidumpFile, mExtrasStringMap, mPendingExtrasFile);
}
}, "CrashReporter Thread").start();
}, "CrashReporterActivity Thread").start();
}
private void savePrefs() {

Просмотреть файл

@ -123,7 +123,6 @@ public abstract class GeckoApp extends GeckoActivity
public static final String ACTION_ALERT_CALLBACK = "org.mozilla.gecko.ALERT_CALLBACK";
public static final String ACTION_HOMESCREEN_SHORTCUT = "org.mozilla.gecko.BOOKMARK";
public static final String ACTION_WEBAPP = "org.mozilla.gecko.WEBAPP";
public static final String ACTION_DEBUG = "org.mozilla.gecko.DEBUG";
public static final String ACTION_LAUNCH_SETTINGS = "org.mozilla.gecko.SETTINGS";
public static final String ACTION_LOAD = "org.mozilla.gecko.LOAD";
public static final String ACTION_INIT_PW = "org.mozilla.gecko.INIT_PW";
@ -998,6 +997,18 @@ public abstract class GeckoApp extends GeckoActivity
return;
}
// To prevent races, register startup events before launching the Gecko thread.
EventDispatcher.getInstance().registerGeckoThreadListener(this,
"Gecko:Ready",
null);
EventDispatcher.getInstance().registerUiThreadListener(this,
"Gecko:CorruptAPK",
"Update:Check",
"Update:Download",
"Update:Install",
null);
if (sAlreadyLoaded) {
// This happens when the GeckoApp activity is destroyed by Android
// without killing the entire application (see Bug 769269).
@ -1005,15 +1016,14 @@ public abstract class GeckoApp extends GeckoActivity
// also happen if we're not the first activity to run within a session.
mIsRestoringActivity = true;
Telemetry.addToHistogram("FENNEC_RESTORING_ACTIVITY", 1);
} else {
final String action = intent.getAction();
final String[] args = GeckoApplication.getDefaultGeckoArgs();
final int flags = ACTION_DEBUG.equals(action) ? GeckoThread.FLAG_DEBUGGING : 0;
sAlreadyLoaded = true;
GeckoThread.initMainProcess(/* profile */ null, args,
intent.getExtras(), flags);
if (GeckoApplication.getRuntime() == null) {
GeckoApplication.createRuntime(this, intent);
}
// Speculatively pre-fetch the profile in the background.
ThreadUtils.postToBackgroundThread(new Runnable() {
@ -1030,20 +1040,6 @@ public abstract class GeckoApp extends GeckoActivity
}
}
// To prevent races, register startup events before launching the Gecko thread.
EventDispatcher.getInstance().registerGeckoThreadListener(this,
"Gecko:Ready",
null);
EventDispatcher.getInstance().registerUiThreadListener(this,
"Gecko:CorruptAPK",
"Update:Check",
"Update:Download",
"Update:Install",
null);
GeckoThread.launch();
Bundle stateBundle = IntentUtils.getBundleExtraSafe(getIntent(), EXTRA_STATE_BUNDLE);
if (stateBundle != null) {
// Use the state bundle if it was given as an intent extra. This is
@ -1081,7 +1077,7 @@ public abstract class GeckoApp extends GeckoActivity
if (mLayerView.getSession() != null) {
mLayerView.getSession().close();
}
mLayerView.setSession(session, GeckoRuntime.getDefault(this));
mLayerView.setSession(session, GeckoApplication.getRuntime());
mLayerView.setOverScrollMode(View.OVER_SCROLL_NEVER);
getAppEventDispatcher().registerGeckoThreadListener(this,

Просмотреть файл

@ -13,10 +13,12 @@ import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Process;
import android.os.SystemClock;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.text.TextUtils;
@ -38,6 +40,7 @@ import org.mozilla.gecko.icons.Icons;
import org.mozilla.gecko.lwt.LightweightTheme;
import org.mozilla.gecko.mdns.MulticastDNSManager;
import org.mozilla.gecko.media.AudioFocusAgent;
import org.mozilla.gecko.mozglue.SafeIntent;
import org.mozilla.gecko.notifications.NotificationClient;
import org.mozilla.gecko.notifications.NotificationHelper;
import org.mozilla.gecko.permissions.Permissions;
@ -53,6 +56,8 @@ import org.mozilla.gecko.util.HardwareUtils;
import org.mozilla.gecko.util.PRNGFixes;
import org.mozilla.gecko.util.ShortcutUtils;
import org.mozilla.gecko.util.ThreadUtils;
import org.mozilla.geckoview.GeckoRuntime;
import org.mozilla.geckoview.GeckoRuntimeSettings;
import java.io.ByteArrayOutputStream;
import java.io.File;
@ -65,6 +70,7 @@ import java.util.UUID;
public class GeckoApplication extends Application
implements HapticFeedbackDelegate {
private static final String LOG_TAG = "GeckoApplication";
public static final String ACTION_DEBUG = "org.mozilla.gecko.DEBUG";
private static final String MEDIA_DECODING_PROCESS_CRASH = "MEDIA_DECODING_PROCESS_CRASH";
private boolean mInBackground;
@ -113,7 +119,7 @@ public class GeckoApplication extends Application
"startup (JavaScript) caches.");
return new String[] { "-purgecaches" };
}
return null;
return new String[0];
}
public static String getDefaultUAString() {
@ -210,6 +216,50 @@ public class GeckoApplication extends Application
mInBackground = false;
}
private static GeckoRuntime sGeckoRuntime;
public static GeckoRuntime getRuntime() {
return sGeckoRuntime;
}
public static GeckoRuntime ensureRuntime(@NonNull Context context) {
if (sGeckoRuntime != null) {
return sGeckoRuntime;
}
return createRuntime(context, null);
}
private static GeckoRuntimeSettings.Builder createSettingsBuilder() {
return new GeckoRuntimeSettings.Builder()
.javaCrashReportingEnabled(true)
.nativeCrashReportingEnabled(true)
.arguments(getDefaultGeckoArgs());
}
public static GeckoRuntime createRuntime(@NonNull Context context,
@Nullable SafeIntent intent) {
if (sGeckoRuntime != null) {
throw new IllegalStateException("Already have a GeckoRuntime!");
}
if (context == null) {
throw new IllegalArgumentException("Context must not be null");
}
GeckoRuntimeSettings.Builder builder = createSettingsBuilder();
if (intent != null) {
builder.pauseForDebugger(ACTION_DEBUG.equals(intent.getAction()));
Bundle extras = intent.getExtras();
if (extras != null) {
builder.extras(extras);
}
}
sGeckoRuntime = GeckoRuntime.create(context, builder.build());
return sGeckoRuntime;
}
@Override
public void onCreate() {
Log.i(LOG_TAG, "zerdatime " + SystemClock.elapsedRealtime() +

Просмотреть файл

@ -18,6 +18,7 @@ import android.util.Log;
import java.io.File;
import org.mozilla.gecko.mozglue.SafeIntent;
import org.mozilla.gecko.util.BundleEventListener;
import org.mozilla.gecko.util.GeckoBundle;
import org.mozilla.gecko.util.EventCallback;
@ -166,19 +167,22 @@ public class GeckoService extends Service {
throw new IllegalArgumentException("Intent must specify profile.");
}
if (!GeckoThread.initMainProcessWithProfile(
profileName, profileDir != null ? new File(profileDir) : null,
GeckoApplication.getDefaultGeckoArgs(), intent.getExtras())) {
Log.w(LOGTAG, "Ignoring due to profile mismatch: " +
profileName + " [" + profileDir + ']');
if (GeckoApplication.getRuntime() != null) {
// Gecko has already been initialized, make sure it's using the
// expected profile.
return GeckoThread.canUseProfile(profileName,
profileDir != null ? new File(profileDir) : null);
}
final GeckoProfile profile = GeckoThread.getActiveProfile();
if (profile != null) {
Log.w(LOGTAG, "Current profile is " + profile.getName() +
" [" + profile.getDir().getAbsolutePath() + ']');
}
return false;
String args;
if (profileDir != null) {
args = "-profile " + profileDir;
} else {
args = "-P " + profileName;
}
intent.putExtra(GeckoThread.EXTRA_ARGS, args);
GeckoApplication.createRuntime(this, new SafeIntent(intent));
return true;
}
@ -192,8 +196,6 @@ public class GeckoService extends Service {
return Service.START_NOT_STICKY;
}
GeckoThread.launch();
switch (intent.getAction()) {
case INTENT_ACTION_UPDATE_ADDONS:
// Run the add-on update service. Because the service is automatically invoked

Просмотреть файл

@ -132,7 +132,7 @@ class VirtualPresentation extends CastPresentation {
// Create new GeckoView
view = new GeckoView(getContext());
view.setSession(session, GeckoRuntime.getDefault(getContext()));
view.setSession(session, GeckoApplication.ensureRuntime(getContext()));
view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));

Просмотреть файл

@ -37,6 +37,7 @@ import org.mozilla.gecko.Clipboard;
import org.mozilla.gecko.DoorHangerPopup;
import org.mozilla.gecko.EventDispatcher;
import org.mozilla.gecko.FormAssistPopup;
import org.mozilla.gecko.GeckoApplication;
import org.mozilla.gecko.GeckoSharedPrefs;
import org.mozilla.gecko.preferences.GeckoPreferences;
import org.mozilla.gecko.R;
@ -131,7 +132,7 @@ public class CustomTabsActivity extends AppCompatActivity
mGeckoSession.setProgressDelegate(this);
mGeckoSession.setContentDelegate(this);
mGeckoView.setSession(mGeckoSession, GeckoRuntime.getDefault(this));
mGeckoView.setSession(mGeckoSession, GeckoApplication.ensureRuntime(this));
mPromptService = new PromptService(this, mGeckoView.getEventDispatcher());
mDoorHangerPopup = new DoorHangerPopup(this, mGeckoView.getEventDispatcher());

Просмотреть файл

@ -26,6 +26,7 @@ import org.mozilla.gecko.AppConstants;
import org.mozilla.gecko.BrowserApp;
import org.mozilla.gecko.DoorHangerPopup;
import org.mozilla.gecko.FormAssistPopup;
import org.mozilla.gecko.GeckoApplication;
import org.mozilla.gecko.GeckoScreenOrientation;
import org.mozilla.gecko.GeckoSharedPrefs;
import org.mozilla.gecko.preferences.GeckoPreferences;
@ -97,7 +98,7 @@ public class WebAppActivity extends AppCompatActivity
final GeckoSessionSettings settings = new GeckoSessionSettings();
settings.setBoolean(GeckoSessionSettings.USE_MULTIPROCESS, false);
mGeckoSession = new GeckoSession(settings);
mGeckoView.setSession(mGeckoSession, GeckoRuntime.getDefault(this));
mGeckoView.setSession(mGeckoSession, GeckoApplication.ensureRuntime(this));
mGeckoSession.setNavigationDelegate(this);
mGeckoSession.setContentDelegate(this);

Просмотреть файл

@ -139,6 +139,10 @@ android {
exclude 'org/mozilla/gecko/media/Utils.java'
}
if (!mozconfig.substs.MOZ_CRASHREPORTER) {
exclude 'org/mozilla/gecko/CrashReporterService.java'
}
if (mozconfig.substs.MOZ_WEBRTC) {
srcDir "${topsrcdir}/media/webrtc/trunk/webrtc/base/java/src"
srcDir "${topsrcdir}/media/webrtc/trunk/webrtc/modules/audio_device/android/java/src"

Просмотреть файл

@ -120,6 +120,10 @@ public class TestRunnerActivity extends Activity {
runtimeSettingsBuilder.extras(extras);
}
runtimeSettingsBuilder
.nativeCrashReportingEnabled(true)
.javaCrashReportingEnabled(true);
sRuntime = GeckoRuntime.create(this, runtimeSettingsBuilder.build());
sRuntime.setDelegate(new GeckoRuntime.Delegate() {
@Override

Просмотреть файл

@ -847,7 +847,10 @@ public class GeckoSessionTestRule extends UiThreadTestRule {
final GeckoRuntimeSettings.Builder runtimeSettingsBuilder =
new GeckoRuntimeSettings.Builder();
runtimeSettingsBuilder.arguments(new String[] { "-purgecaches" })
.extras(InstrumentationRegistry.getArguments());
.extras(InstrumentationRegistry.getArguments())
.nativeCrashReportingEnabled(true)
.javaCrashReportingEnabled(true);
sRuntime = GeckoRuntime.create(
InstrumentationRegistry.getTargetContext(),
runtimeSettingsBuilder.build());

Просмотреть файл

@ -1,3 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.mozilla.geckoview">
@ -12,62 +13,88 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
<uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-feature android:name="android.hardware.location" android:required="false"/>
<uses-feature android:name="android.hardware.location.gps" android:required="false"/>
<uses-feature
android:name="android.hardware.location"
android:required="false"/>
<uses-feature
android:name="android.hardware.location.gps"
android:required="false"/>
<uses-feature android:name="android.hardware.touchscreen"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.camera" android:required="false"/>
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
<uses-feature
android:name="android.hardware.camera"
android:required="false"/>
<uses-feature
android:name="android.hardware.camera.autofocus"
android:required="false"/>
<!-- #ifdef MOZ_WEBRTC -->
<!-- TODO preprocess AndroidManifest.xml so that we can
conditionally include WebRTC permissions based on MOZ_WEBRTC. -->
<uses-permission android:name="android.permission.RECORD_AUDIO"/>-->
<uses-feature android:name="android.hardware.audio.low_latency" android:required="false"/>-->
<uses-feature android:name="android.hardware.microphone" android:required="false"/>-->
<uses-feature android:name="android.hardware.camera.any" android:required="false"/>-->
<!--
TODO preprocess AndroidManifest.xml so that we can
conditionally include WebRTC permissions based on MOZ_WEBRTC.
-->
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
-->
<uses-feature
android:name="android.hardware.audio.low_latency"
android:required="false"/>
-->
<uses-feature
android:name="android.hardware.microphone"
android:required="false"/>
-->
<uses-feature
android:name="android.hardware.camera.any"
android:required="false"/>
-->
<!-- #endif -->
<!-- App requires OpenGL ES 2.0 -->
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
<uses-feature
android:glEsVersion="0x00020000"
android:required="true"/>
<application>
<!-- New child services must also be added to the Fennec AndroidManifest.xml.in -->
<service
android:name="org.mozilla.gecko.media.MediaManager"
android:enabled="true"
android:exported="false"
android:process=":media"
android:isolatedProcess="false">
android:isolatedProcess="false"
android:process=":media">
</service>
<service
android:name="org.mozilla.gecko.process.GeckoServiceChildProcess$geckomediaplugin"
android:enabled="true"
android:exported="false"
android:process=":geckomediaplugin"
android:isolatedProcess="false">
android:isolatedProcess="false"
android:process=":geckomediaplugin">
</service>
<service
android:name="org.mozilla.gecko.process.GeckoServiceChildProcess$tab"
android:enabled="true"
android:exported="false"
android:process=":tab"
android:isolatedProcess="false">
android:isolatedProcess="false"
android:process=":tab">
</service>
<service
android:name="org.mozilla.gecko.gfx.SurfaceAllocatorService"
android:enabled="true"
android:exported="false"
android:isolatedProcess="false">
</service>
<service
android:name="org.mozilla.gecko.CrashReporterService"
android:exported="false"
android:process=":crashreporter">
</service>
</application>
</manifest>

Просмотреть файл

@ -11,7 +11,7 @@ import android.os.ParcelFileDescriptor;
interface IChildProcess {
int getPid();
boolean start(in IProcessManager procMan, in String[] args, in Bundle extras,
boolean start(in IProcessManager procMan, in String[] args, in Bundle extras, int flags,
in ParcelFileDescriptor prefsPfd, in ParcelFileDescriptor ipcPfd,
in ParcelFileDescriptor crashReporterPfd,
in ParcelFileDescriptor crashAnnotationPfd);

Просмотреть файл

@ -297,7 +297,7 @@ public class CrashHandler implements Thread.UncaughtExceptionHandler {
final Context context = getAppContext();
final String javaPkg = getJavaPackageName();
final String pkg = getAppPackageName();
final String component = javaPkg + ".CrashReporter";
final String component = javaPkg + ".CrashReporterService";
final String action = javaPkg + ".reportCrash";
final ProcessBuilder pb;
@ -305,8 +305,7 @@ public class CrashHandler implements Thread.UncaughtExceptionHandler {
final Intent intent = new Intent(action);
intent.setComponent(new ComponentName(pkg, component));
intent.putExtra("minidumpPath", dumpFile);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
context.startService(intent);
return true;
}

Просмотреть файл

@ -0,0 +1,373 @@
package org.mozilla.gecko;
import org.mozilla.gecko.mozglue.GeckoLoader;
import org.mozilla.gecko.mozglue.MinidumpAnalyzer;
import org.mozilla.gecko.util.INIParser;
import org.mozilla.gecko.util.INISection;
import org.mozilla.gecko.util.ProxySelector;
import android.app.IntentService;
import android.content.Intent;
import android.os.Build;
import android.util.Log;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.GZIPOutputStream;
public class CrashReporterService extends IntentService {
private static final String LOGTAG = "CrashReporter";
private static final String ACTION_REPORT_CRASH = "org.mozilla.gecko.reportCrash";
private static final String PASSED_MINI_DUMP_KEY = "minidumpPath";
private static final String PASSED_MINI_DUMP_SUCCESS_KEY = "minidumpSuccess";
private static final String MINI_DUMP_PATH_KEY = "upload_file_minidump";
private static final String PAGE_URL_KEY = "URL";
private static final String NOTES_KEY = "Notes";
private static final String SERVER_URL_KEY = "ServerURL";
private static final String CRASH_REPORT_SUFFIX = "/mozilla/Crash Reports/";
private static final String PENDING_SUFFIX = CRASH_REPORT_SUFFIX + "pending";
private static final String SUBMITTED_SUFFIX = CRASH_REPORT_SUFFIX + "submitted";
private File mPendingMinidumpFile;
private File mPendingExtrasFile;
private HashMap<String, String> mExtrasStringMap;
private boolean mMinidumpSucceeded;
public CrashReporterService() {
super("CrashReporterService");
}
@Override
protected void onHandleIntent(Intent intent) {
if (intent == null || !intent.getAction().equals(ACTION_REPORT_CRASH)) {
Log.d(LOGTAG, "Invalid or unknown action");
return;
}
Class<?> reporterActivityCls = getFennecReporterActivity();
if (reporterActivityCls != null) {
intent.setClass(this, reporterActivityCls);
startActivity(intent);
return;
}
submitCrash(intent);
}
private Class<?> getFennecReporterActivity() {
try {
return Class.forName("org.mozilla.gecko.CrashReporterActivity");
} catch (ClassNotFoundException e) {
return null;
}
}
private boolean moveFile(File inFile, File outFile) {
Log.i(LOGTAG, "moving " + inFile + " to " + outFile);
if (inFile.renameTo(outFile))
return true;
try {
outFile.createNewFile();
Log.i(LOGTAG, "couldn't rename minidump file");
// so copy it instead
FileChannel inChannel = new FileInputStream(inFile).getChannel();
FileChannel outChannel = new FileOutputStream(outFile).getChannel();
long transferred = inChannel.transferTo(0, inChannel.size(), outChannel);
inChannel.close();
outChannel.close();
if (transferred > 0)
inFile.delete();
} catch (Exception e) {
Log.e(LOGTAG, "exception while copying minidump file: ", e);
return false;
}
return true;
}
private void submitCrash(Intent intent) {
mMinidumpSucceeded = intent.getBooleanExtra(PASSED_MINI_DUMP_SUCCESS_KEY, false);
if (!mMinidumpSucceeded) {
Log.i(LOGTAG, "Failed to get minidump.");
}
String passedMinidumpPath = intent.getStringExtra(PASSED_MINI_DUMP_KEY);
File passedMinidumpFile = new File(passedMinidumpPath);
File pendingDir = new File(getFilesDir(), PENDING_SUFFIX);
pendingDir.mkdirs();
mPendingMinidumpFile = new File(pendingDir, passedMinidumpFile.getName());
moveFile(passedMinidumpFile, mPendingMinidumpFile);
File extrasFile = new File(passedMinidumpPath.replaceAll("\\.dmp", ".extra"));
mPendingExtrasFile = new File(pendingDir, extrasFile.getName());
moveFile(extrasFile, mPendingExtrasFile);
// Compute the minidump hash and generate the stack traces
computeMinidumpHash(mPendingExtrasFile, mPendingMinidumpFile);
try {
GeckoLoader.loadMozGlue(this);
if (!MinidumpAnalyzer.GenerateStacks(mPendingMinidumpFile.getPath(), /* fullStacks */ false)) {
Log.e(LOGTAG, "Could not generate stacks for this minidump: " + passedMinidumpPath);
}
} catch (UnsatisfiedLinkError e) {
Log.e(LOGTAG, "Could not load libmozglue.so, stacks for this crash won't be generated");
}
// Extract the annotations from the .extra file
mExtrasStringMap = new HashMap<String, String>();
readStringsFromFile(mPendingExtrasFile.getPath(), mExtrasStringMap);
try {
// Find the profile name and path. Since we don't have any other way of getting it within
// this context we extract it from the crash dump path.
final File profileDir = passedMinidumpFile.getParentFile().getParentFile();
final String profileName = getProfileName(profileDir);
if (profileName != null) {
// Extract the crash dump ID and telemetry client ID, we need profile access for the latter.
final String passedMinidumpName = passedMinidumpFile.getName();
// Strip the .dmp suffix from the minidump name to obtain the crash ID.
final String crashId = passedMinidumpName.substring(0, passedMinidumpName.length() - 4);
final GeckoProfile profile = GeckoProfile.get(this, profileName, profileDir);
final String clientId = profile.getClientId();
}
} catch (GeckoProfileDirectories.NoMozillaDirectoryException | IOException e) {
Log.e(LOGTAG, "Cannot send the crash ping: ", e);
}
// Notify GeckoApp that we've crashed, so it can react appropriately during the next start.
try {
File crashFlag = new File(GeckoProfileDirectories.getMozillaDirectory(this), "CRASHED");
crashFlag.createNewFile();
} catch (GeckoProfileDirectories.NoMozillaDirectoryException | IOException e) {
Log.e(LOGTAG, "Cannot set crash flag: ", e);
}
sendReport(mPendingMinidumpFile, mExtrasStringMap, mPendingExtrasFile);
}
private String getProfileName(File profileDir) throws GeckoProfileDirectories.NoMozillaDirectoryException {
final File mozillaDir = GeckoProfileDirectories.getMozillaDirectory(this);
final INIParser parser = GeckoProfileDirectories.getProfilesINI(mozillaDir);
String profileName = null;
if (parser.getSections() != null) {
for (Enumeration<INISection> e = parser.getSections().elements(); e.hasMoreElements(); ) {
final INISection section = e.nextElement();
final String path = section.getStringProperty("Path");
final boolean isRelative = (section.getIntProperty("IsRelative") == 1);
if ((isRelative && path.equals(profileDir.getName())) ||
path.equals(profileDir.getPath())) {
profileName = section.getStringProperty("Name");
break;
}
}
}
return profileName;
}
private void computeMinidumpHash(File extraFile, File minidump) {
try {
FileInputStream stream = new FileInputStream(minidump);
MessageDigest md = MessageDigest.getInstance("SHA-256");
try {
byte[] buffer = new byte[4096];
int readBytes;
while ((readBytes = stream.read(buffer)) != -1) {
md.update(buffer, 0, readBytes);
}
} finally {
stream.close();
}
byte[] digest = md.digest();
StringBuilder hash = new StringBuilder(84);
hash.append("MinidumpSha256Hash=");
for (int i = 0; i < digest.length; i++) {
hash.append(Integer.toHexString((digest[i] & 0xf0) >> 4));
hash.append(Integer.toHexString(digest[i] & 0x0f));
}
hash.append('\n');
FileWriter writer = new FileWriter(extraFile, /* append */ true);
try {
writer.write(hash.toString());
} finally {
writer.close();
}
} catch (Exception e) {
Log.e(LOGTAG, "exception while computing the minidump hash: ", e);
}
}
private boolean readStringsFromFile(String filePath, Map<String, String> stringMap) {
try {
BufferedReader reader = new BufferedReader(new FileReader(filePath));
return readStringsFromReader(reader, stringMap);
} catch (Exception e) {
Log.e(LOGTAG, "exception while reading strings: ", e);
return false;
}
}
private boolean readStringsFromReader(BufferedReader reader, Map<String, String> stringMap) throws IOException {
String line;
while ((line = reader.readLine()) != null) {
int equalsPos = -1;
if ((equalsPos = line.indexOf('=')) != -1) {
String key = line.substring(0, equalsPos);
String val = unescape(line.substring(equalsPos + 1));
stringMap.put(key, val);
}
}
reader.close();
return true;
}
private String generateBoundary() {
// Generate some random numbers to fill out the boundary
int r0 = (int)(Integer.MAX_VALUE * Math.random());
int r1 = (int)(Integer.MAX_VALUE * Math.random());
return String.format("---------------------------%08X%08X", r0, r1);
}
private void sendPart(OutputStream os, String boundary, String name, String data) {
try {
os.write(("--" + boundary + "\r\n" +
"Content-Disposition: form-data; name=\"" + name + "\"\r\n" +
"\r\n" +
data + "\r\n"
).getBytes());
} catch (Exception ex) {
Log.e(LOGTAG, "Exception when sending \"" + name + "\"", ex);
}
}
private void sendFile(OutputStream os, String boundary, String name, File file) throws IOException {
os.write(("--" + boundary + "\r\n" +
"Content-Disposition: form-data; name=\"" + name + "\"; " +
"filename=\"" + file.getName() + "\"\r\n" +
"Content-Type: application/octet-stream\r\n" +
"\r\n"
).getBytes());
FileChannel fc = new FileInputStream(file).getChannel();
fc.transferTo(0, fc.size(), Channels.newChannel(os));
fc.close();
}
private void sendReport(File minidumpFile, Map<String, String> extras, File extrasFile) {
Log.i(LOGTAG, "sendReport: " + minidumpFile.getPath());
String spec = extras.get(SERVER_URL_KEY);
if (spec == null) {
return;
}
try {
final URL url = new URL(URLDecoder.decode(spec, "UTF-8"));
final URI uri = new URI(url.getProtocol(), url.getUserInfo(),
url.getHost(), url.getPort(),
url.getPath(), url.getQuery(), url.getRef());
HttpURLConnection conn = (HttpURLConnection) ProxySelector.openConnectionWithProxy(uri);
conn.setRequestMethod("POST");
String boundary = generateBoundary();
conn.setDoOutput(true);
conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
conn.setRequestProperty("Content-Encoding", "gzip");
OutputStream os = new GZIPOutputStream(conn.getOutputStream());
for (String key : extras.keySet()) {
if (!key.equals(SERVER_URL_KEY) && !key.equals(NOTES_KEY)) {
sendPart(os, boundary, key, extras.get(key));
}
}
StringBuilder sb = new StringBuilder();
sb.append(extras.containsKey(NOTES_KEY) ? extras.get(NOTES_KEY) + "\n" : "");
sb.append(Build.MANUFACTURER).append(' ')
.append(Build.MODEL).append('\n')
.append(Build.FINGERPRINT);
sendPart(os, boundary, NOTES_KEY, sb.toString());
sendPart(os, boundary, "Android_Manufacturer", Build.MANUFACTURER);
sendPart(os, boundary, "Android_Model", Build.MODEL);
sendPart(os, boundary, "Android_Board", Build.BOARD);
sendPart(os, boundary, "Android_Brand", Build.BRAND);
sendPart(os, boundary, "Android_Device", Build.DEVICE);
sendPart(os, boundary, "Android_Display", Build.DISPLAY);
sendPart(os, boundary, "Android_Fingerprint", Build.FINGERPRINT);
sendPart(os, boundary, "Android_CPU_ABI", Build.CPU_ABI);
try {
sendPart(os, boundary, "Android_CPU_ABI2", Build.CPU_ABI2);
sendPart(os, boundary, "Android_Hardware", Build.HARDWARE);
} catch (Exception ex) {
Log.e(LOGTAG, "Exception while sending SDK version 8 keys", ex);
}
sendPart(os, boundary, "Android_Version", Build.VERSION.SDK_INT + " (" + Build.VERSION.CODENAME + ")");
sendPart(os, boundary, PASSED_MINI_DUMP_SUCCESS_KEY, mMinidumpSucceeded ? "True" : "False");
sendFile(os, boundary, MINI_DUMP_PATH_KEY, minidumpFile);
os.write(("\r\n--" + boundary + "--\r\n").getBytes());
os.flush();
os.close();
BufferedReader br = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
HashMap<String, String> responseMap = new HashMap<String, String>();
readStringsFromReader(br, responseMap);
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
File submittedDir = new File(getFilesDir(),
SUBMITTED_SUFFIX);
submittedDir.mkdirs();
minidumpFile.delete();
extrasFile.delete();
String crashid = responseMap.get("CrashID");
File file = new File(submittedDir, crashid + ".txt");
FileOutputStream fos = new FileOutputStream(file);
fos.write("Crash ID: ".getBytes());
fos.write(crashid.getBytes());
fos.close();
Log.i(LOGTAG, "Successfully sent crash report: " + crashid);
} else {
Log.w(LOGTAG, "Received failure HTTP response code from server: " + conn.getResponseCode());
}
} catch (IOException e) {
Log.e(LOGTAG, "exception during send: ", e);
} catch (URISyntaxException e) {
Log.e(LOGTAG, "exception during new URI: ", e);
}
}
private String unescape(String string) {
return string.replaceAll("\\\\\\\\", "\\").replaceAll("\\\\n", "\n").replaceAll("\\\\t", "\t");
}
}

Просмотреть файл

@ -111,7 +111,7 @@ public class GeckoAppShell
// We have static members only.
private GeckoAppShell() { }
private static final CrashHandler CRASH_HANDLER = new CrashHandler() {
private static class GeckoCrashHandler extends CrashHandler {
@Override
protected String getAppPackageName() {
final Context appContext = getAppContext();
@ -174,10 +174,18 @@ public class GeckoAppShell
};
private static String sAppNotes;
private static CrashHandler sCrashHandler;
public static CrashHandler ensureCrashHandling() {
// Crash handling is automatically enabled when GeckoAppShell is loaded.
return CRASH_HANDLER;
public static synchronized CrashHandler ensureCrashHandling() {
if (sCrashHandler == null) {
sCrashHandler = new GeckoCrashHandler();
}
return sCrashHandler;
}
public static synchronized boolean isCrashHandlingEnabled() {
return sCrashHandler != null;
}
@WrapForJNI(exceptionMode = "ignore")
@ -280,8 +288,10 @@ public class GeckoAppShell
}
@WrapForJNI(exceptionMode = "ignore")
private static void handleUncaughtException(Throwable e) {
CRASH_HANDLER.uncaughtException(null, e);
private static synchronized void handleUncaughtException(Throwable e) {
if (sCrashHandler != null) {
sCrashHandler.uncaughtException(null, e);
}
}
private static float getLocationAccuracy(Location location) {

Просмотреть файл

@ -12,6 +12,7 @@ import org.mozilla.gecko.process.GeckoProcessManager;
import org.mozilla.gecko.util.GeckoBundle;
import org.mozilla.gecko.util.FileUtils;
import org.mozilla.gecko.util.ThreadUtils;
import org.mozilla.geckoview.BuildConfig;
import android.content.Context;
import android.content.res.Configuration;
@ -27,10 +28,10 @@ import android.text.TextUtils;
import android.util.Log;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.StringTokenizer;
@ -124,10 +125,12 @@ public class GeckoThread extends Thread {
private static int uiThreadId;
// Main process parameters
public static final int FLAG_DEBUGGING = 1; // Debugging mode.
public static final int FLAG_PRELOAD_CHILD = 2; // Preload child during main thread start.
public static final int FLAG_DEBUGGING = 1 << 0; // Debugging mode.
public static final int FLAG_PRELOAD_CHILD = 1 << 1; // Preload child during main thread start.
public static final int FLAG_ENABLE_NATIVE_CRASHREPORTER = 1 << 2; // Enable native crash reporting
public static final int FLAG_ENABLE_JAVA_CRASHREPORTER = 1 << 3; // Enable java crash reporting
private static final String EXTRA_ARGS = "args";
/* package */ static final String EXTRA_ARGS = "args";
private static final String EXTRA_PREFS_FD = "prefsFd";
private static final String EXTRA_IPC_FD = "ipcFd";
private static final String EXTRA_CRASH_FD = "crashFd";
@ -181,11 +184,14 @@ public class GeckoThread extends Thread {
/* fd */ -1, /* fd */ -1, /* fd */ -1);
}
public static boolean initChildProcess(final String[] args, final Bundle extras,
final int prefsFd, final int ipcFd,
public static boolean initChildProcess(final String[] args,
final Bundle extras,
final int flags,
final int prefsFd,
final int ipcFd,
final int crashFd,
final int crashAnnotationFd) {
return INSTANCE.init(/* profile */ null, args, extras, /* flags */ 0,
return INSTANCE.init(/* profile */ null, args, extras, flags,
prefsFd, ipcFd, crashFd, crashAnnotationFd);
}
@ -377,10 +383,40 @@ public class GeckoThread extends Thread {
if (!INSTANCE.mInitialized) {
return null;
}
return INSTANCE.mExtras;
return new Bundle(INSTANCE.mExtras);
}
}
public static int getActiveFlags() {
synchronized (INSTANCE) {
if (!INSTANCE.mInitialized) {
return 0;
}
return INSTANCE.mFlags;
}
}
private static ArrayList<String> getEnvFromExtras(final Bundle extras) {
if (extras == null) {
return new ArrayList<>();
}
ArrayList<String> result = new ArrayList<>();
if (extras != null) {
String env = extras.getString("env0");
for (int c = 1; env != null; c++) {
if (BuildConfig.DEBUG) {
Log.d(LOGTAG, "env var: " + env);
}
result.add(env);
env = extras.getString("env" + c);
}
}
return result;
}
@Override
public void run() {
Log.i(LOGTAG, "preparing to run Gecko");
@ -442,7 +478,21 @@ public class GeckoThread extends Thread {
Log.i(LOGTAG, "RunGecko - args = " + TextUtils.join(" ", args));
}
GeckoLoader.setupGeckoEnvironment(context, context.getFilesDir().getPath(), mExtras);
final List<String> env = getEnvFromExtras(mExtras);
// In Gecko, the native crash reporter is enabled by default in opt builds, and
// disabled by default in debug builds.
if ((mFlags & FLAG_ENABLE_NATIVE_CRASHREPORTER) == 0 && !BuildConfig.DEBUG_BUILD) {
env.add(0, "MOZ_CRASHREPORTER_DISABLE=1");
} else if ((mFlags & FLAG_ENABLE_NATIVE_CRASHREPORTER) != 0 && BuildConfig.DEBUG_BUILD) {
env.add(0, "MOZ_CRASHREPORTER=1");
}
if ((mFlags & FLAG_ENABLE_JAVA_CRASHREPORTER) != 0) {
GeckoAppShell.ensureCrashHandling();
}
GeckoLoader.setupGeckoEnvironment(context, context.getFilesDir().getPath(), env);
// And go.
GeckoLoader.nativeRun(args,

Просмотреть файл

@ -8,6 +8,7 @@ package org.mozilla.gecko.mozglue;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Collection;
import java.util.Locale;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@ -92,17 +93,9 @@ public final class GeckoLoader {
public synchronized static void setupGeckoEnvironment(final Context context,
final String profilePath,
final Bundle extras) {
// if we have an intent (we're being launched by an activity)
// read in any environmental variables from it here
if (extras != null) {
String env = extras.getString("env0");
Log.d(LOGTAG, "Gecko environment env0: " + env);
for (int c = 1; env != null; c++) {
putenv(env);
env = extras.getString("env" + c);
Log.d(LOGTAG, "env" + c + ": " + env);
}
final Collection<String> env) {
for (final String e : env) {
putenv(e);
}
try {

Просмотреть файл

@ -181,6 +181,11 @@ public final class GeckoProcessManager extends IProcessManager.Stub {
return INSTANCE.start(type, args, prefsFd, ipcFd, crashFd, crashAnnotationFd, /* retry */ false);
}
private int filterFlagsForChild(int flags) {
return flags & (GeckoThread.FLAG_ENABLE_JAVA_CRASHREPORTER |
GeckoThread.FLAG_ENABLE_NATIVE_CRASHREPORTER);
}
private int start(final String type, final String[] args, final int prefsFd,
final int ipcFd, final int crashFd,
final int crashAnnotationFd, final boolean retry) {
@ -205,9 +210,11 @@ public final class GeckoProcessManager extends IProcessManager.Stub {
return 0;
}
final int flags = filterFlagsForChild(GeckoThread.getActiveFlags());
boolean started = false;
try {
started = child.start(this, args, extras, prefsPfd, ipcPfd, crashPfd,
started = child.start(this, args, extras, flags, prefsPfd, ipcPfd, crashPfd,
crashAnnotationPfd);
} catch (final RemoteException e) {
}

Просмотреть файл

@ -24,9 +24,7 @@ import android.os.RemoteException;
import android.util.Log;
public class GeckoServiceChildProcess extends Service {
private static final String LOGTAG = "GeckoServiceChildProcess";
private static IProcessManager sProcessManager;
@WrapForJNI(calledFrom = "gecko")
@ -44,7 +42,6 @@ public class GeckoServiceChildProcess extends Service {
public void onCreate() {
super.onCreate();
GeckoAppShell.ensureCrashHandling();
GeckoAppShell.setApplicationContext(getApplicationContext());
}
@ -63,6 +60,7 @@ public class GeckoServiceChildProcess extends Service {
public boolean start(final IProcessManager procMan,
final String[] args,
final Bundle extras,
final int flags,
final ParcelFileDescriptor prefsPfd,
final ParcelFileDescriptor ipcPfd,
final ParcelFileDescriptor crashReporterPfd,
@ -85,7 +83,7 @@ public class GeckoServiceChildProcess extends Service {
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
if (GeckoThread.initChildProcess(args, extras, prefsFd, ipcFd, crashReporterFd,
if (GeckoThread.initChildProcess(args, extras, flags, prefsFd, ipcFd, crashReporterFd,
crashAnnotationFd)) {
GeckoThread.launch();
}

Просмотреть файл

@ -84,9 +84,23 @@ public final class GeckoRuntime implements Parcelable {
if (DEBUG) {
Log.d(LOGTAG, "init");
}
final int flags = settings.getUseContentProcessHint()
? GeckoThread.FLAG_PRELOAD_CHILD
: 0;
int flags = 0;
if (settings.getUseContentProcessHint()) {
flags |= GeckoThread.FLAG_PRELOAD_CHILD;
}
if (settings.getNativeCrashReportingEnabled()) {
flags |= GeckoThread.FLAG_ENABLE_NATIVE_CRASHREPORTER;
}
if (settings.getJavaCrashReportingEnabled()) {
flags |= GeckoThread.FLAG_ENABLE_JAVA_CRASHREPORTER;
}
if (settings.getPauseForDebuggerEnabled()) {
flags |= GeckoThread.FLAG_DEBUGGING;
}
if (GeckoThread.initMainProcess(/* profile */ null,
settings.getArguments(),
settings.getExtras(),

Просмотреть файл

@ -40,7 +40,9 @@ public final class GeckoRuntimeSettings implements Parcelable {
* Set the content process hint flag.
*
* @param use If true, this will reload the content process for future use.
* Default is false.
* @return This Builder instance.
*/
public @NonNull Builder useContentProcessHint(final boolean use) {
mSettings.mUseContentProcess = use;
@ -79,6 +81,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
* Set whether JavaScript support should be enabled.
*
* @param flag A flag determining whether JavaScript should be enabled.
* Default is true.
* @return This Builder instance.
*/
public @NonNull Builder javaScriptEnabled(final boolean flag) {
@ -101,12 +104,54 @@ public final class GeckoRuntimeSettings implements Parcelable {
* Set whether support for web fonts should be enabled.
*
* @param flag A flag determining whether web fonts should be enabled.
* Default is true.
* @return This Builder instance.
*/
public @NonNull Builder webFontsEnabled(final boolean flag) {
mSettings.mWebFonts.set(flag);
return this;
}
/**
* Set whether crash reporting for native code should be enabled. This will cause
* a SIGSEGV handler to be installed, and any crash encountered there will be
* reported to Mozilla.
*
* @param enabled A flag determining whether native crash reporting should be enabled.
* Defaults to false.
* @return This Builder.
*/
public @NonNull Builder nativeCrashReportingEnabled(final boolean enabled) {
mSettings.mNativeCrashReporting = enabled;
return this;
}
/**
* Set whether crash reporting for Java code should be enabled. This will cause
* a default unhandled exception handler to be installed, and any exceptions encountered
* will automatically reported to Mozilla.
*
* @param enabled A flag determining whether Java crash reporting should be enabled.
* Defaults to false.
* @return This Builder.
*/
public @NonNull Builder javaCrashReportingEnabled(final boolean enabled) {
mSettings.mJavaCrashReporting = enabled;
return this;
}
/**
* Set whether there should be a pause during startup. This is useful if you need to
* wait for a debugger to attach.
*
* @param enabled A flag determining whether there will be a pause early in startup.
* Defaults to false.
* @return This Builder.
*/
public @NonNull Builder pauseForDebugger(boolean enabled) {
mSettings.mDebugPause = enabled;
return this;
}
}
/* package */ GeckoRuntime runtime;
@ -150,6 +195,9 @@ public final class GeckoRuntimeSettings implements Parcelable {
"devtools.debugger.remote-enabled", false);
/* package */ Pref<Boolean> mWebFonts = new Pref<Boolean>(
"browser.display.use_document_fonts", true);
/* package */ boolean mNativeCrashReporting;
/* package */ boolean mJavaCrashReporting;
/* package */ boolean mDebugPause;
private final Pref<?>[] mPrefs = new Pref<?>[] {
mJavaScript, mRemoteDebugging, mWebFonts
@ -180,6 +228,9 @@ public final class GeckoRuntimeSettings implements Parcelable {
final Pref<Object> uncheckedPref = (Pref<Object>) mPrefs[i];
uncheckedPref.set(settings.mPrefs[i].get());
}
mNativeCrashReporting = settings.mNativeCrashReporting;
mJavaCrashReporting = settings.mJavaCrashReporting;
}
/* package */ void flush() {
@ -275,6 +326,31 @@ public final class GeckoRuntimeSettings implements Parcelable {
return this;
}
/**
* Get whether native crash reporting is enabled or not.
*
* @return True if native crash reporting is enabled.
*/
public boolean getNativeCrashReportingEnabled() {
return mNativeCrashReporting;
}
/**
* Get whether Java crash reporting is enabled or not.
*
* @return True if Java crash reporting is enabled.
*/
public boolean getJavaCrashReportingEnabled() {
return mJavaCrashReporting;
}
/**
* Gets whether the pause-for-debugger is enabled or not.
*
* @return True if the pause is enabled.
*/
public boolean getPauseForDebuggerEnabled() { return mDebugPause; }
@Override // Parcelable
public int describeContents() {
return 0;
@ -282,18 +358,22 @@ public final class GeckoRuntimeSettings implements Parcelable {
@Override // Parcelable
public void writeToParcel(Parcel out, int flags) {
out.writeByte((byte) (mUseContentProcess ? 1 : 0));
ParcelableUtils.writeBoolean(out, mUseContentProcess);
out.writeStringArray(mArgs);
mExtras.writeToParcel(out, flags);
for (final Pref<?> pref : mPrefs) {
out.writeValue(pref.get());
}
ParcelableUtils.writeBoolean(out, mNativeCrashReporting);
ParcelableUtils.writeBoolean(out, mJavaCrashReporting);
ParcelableUtils.writeBoolean(out, mDebugPause);
}
// AIDL code may call readFromParcel even though it's not part of Parcelable.
public void readFromParcel(final Parcel source) {
mUseContentProcess = source.readByte() == 1;
mUseContentProcess = ParcelableUtils.readBoolean(source);
mArgs = source.createStringArray();
mExtras.readFromParcel(source);
@ -303,6 +383,10 @@ public final class GeckoRuntimeSettings implements Parcelable {
final Pref<Object> uncheckedPref = (Pref<Object>) pref;
uncheckedPref.set(source.readValue(getClass().getClassLoader()));
}
mNativeCrashReporting = ParcelableUtils.readBoolean(source);
mJavaCrashReporting = ParcelableUtils.readBoolean(source);
mJavaCrashReporting = ParcelableUtils.readBoolean(source);
}
public static final Parcelable.Creator<GeckoRuntimeSettings> CREATOR

Просмотреть файл

@ -0,0 +1,19 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* vim: ts=4 sw=4 expandtab:
* 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.geckoview;
import android.os.Parcel;
class ParcelableUtils {
public static void writeBoolean(Parcel out, boolean val) {
out.writeByte((byte) (val ? 1 : 0));
}
public static boolean readBoolean(Parcel source) {
return source.readByte() == 1;
}
}

Просмотреть файл

@ -67,7 +67,12 @@ public class GeckoViewActivity extends Activity {
if (extras != null) {
runtimeSettingsBuilder.extras(extras);
}
runtimeSettingsBuilder.useContentProcessHint(useMultiprocess);
runtimeSettingsBuilder
.useContentProcessHint(useMultiprocess)
.nativeCrashReportingEnabled(true)
.javaCrashReportingEnabled(true);
sGeckoRuntime = GeckoRuntime.create(this, runtimeSettingsBuilder.build());
}

Просмотреть файл

@ -54,8 +54,8 @@ mozilla::detail::ConditionVariableImpl::notify_all()
void
mozilla::detail::ConditionVariableImpl::wait(MutexImpl& lock)
{
CRITICAL_SECTION* cs = &lock.platformData()->criticalSection;
bool r = SleepConditionVariableCS(&platformData()->cv_, cs, INFINITE);
SRWLOCK* srwlock = &lock.platformData()->lock;
bool r = SleepConditionVariableSRW(&platformData()->cv_, srwlock, INFINITE, 0);
MOZ_RELEASE_ASSERT(r);
}
@ -68,7 +68,7 @@ mozilla::detail::ConditionVariableImpl::wait_for(MutexImpl& lock,
return CVStatus::NoTimeout;
}
CRITICAL_SECTION* cs = &lock.platformData()->criticalSection;
SRWLOCK* srwlock = &lock.platformData()->lock;
// Note that DWORD is unsigned, so we have to be careful to clamp at 0. If
// rel_time is Forever, then ToMilliseconds is +inf, which evaluates as
@ -89,7 +89,7 @@ mozilla::detail::ConditionVariableImpl::wait_for(MutexImpl& lock,
}
}
BOOL r = SleepConditionVariableCS(&platformData()->cv_, cs, msec);
BOOL r = SleepConditionVariableSRW(&platformData()->cv_, srwlock, msec, 0);
if (r)
return CVStatus::NoTimeout;
MOZ_RELEASE_ASSERT(GetLastError() == ERROR_TIMEOUT);

Просмотреть файл

@ -13,7 +13,7 @@
struct mozilla::detail::MutexImpl::PlatformData
{
CRITICAL_SECTION criticalSection;
SRWLOCK lock;
};
#endif // MutexPlatformData_windows_h

Просмотреть файл

@ -14,38 +14,23 @@
mozilla::detail::MutexImpl::MutexImpl()
{
// This number was adopted from NSPR.
const static DWORD LockSpinCount = 1500;
#if defined(RELEASE_OR_BETA)
// Vista and later automatically allocate and subsequently leak a debug info
// object for each critical section that we allocate unless we tell the
// system not to do that.
DWORD flags = CRITICAL_SECTION_NO_DEBUG_INFO;
#else
DWORD flags = 0;
#endif // defined(RELEASE_OR_BETA)
BOOL r = InitializeCriticalSectionEx(&platformData()->criticalSection,
LockSpinCount, flags);
MOZ_RELEASE_ASSERT(r);
InitializeSRWLock(&platformData()->lock);
}
mozilla::detail::MutexImpl::~MutexImpl()
{
DeleteCriticalSection(&platformData()->criticalSection);
}
void
mozilla::detail::MutexImpl::lock()
{
EnterCriticalSection(&platformData()->criticalSection);
AcquireSRWLockExclusive(&platformData()->lock);
}
void
mozilla::detail::MutexImpl::unlock()
{
LeaveCriticalSection(&platformData()->criticalSection);
ReleaseSRWLockExclusive(&platformData()->lock);
}
mozilla::detail::MutexImpl::PlatformData*

Просмотреть файл

@ -298,6 +298,15 @@ nsHostRecord::ResolveComplete()
}
}
if (mTRRUsed && mNativeUsed) {
// both were used, accumulate comparative success
AccumulateCategorical(mNativeSuccess && mTRRSuccess?
Telemetry::LABELS_DNS_TRR_COMPARE::BothWorked :
((mNativeSuccess ? Telemetry::LABELS_DNS_TRR_COMPARE::NativeWorked :
(mTRRSuccess ? Telemetry::LABELS_DNS_TRR_COMPARE::TRRWorked:
Telemetry::LABELS_DNS_TRR_COMPARE::BothFailed))));
}
switch(mResolverMode) {
case MODE_NATIVEONLY:
case MODE_TRROFF:
@ -1686,6 +1695,11 @@ nsHostResolver::CompleteLookup(nsHostRecord* rec, nsresult status, AddrInfo* aNe
TimeDuration age = TimeStamp::NowLoRes() - head->mValidStart;
Telemetry::Accumulate(Telemetry::DNS_CLEANUP_AGE,
static_cast<uint32_t>(age.ToSeconds() / 60));
if (head->CheckExpiration(TimeStamp::Now()) !=
nsHostRecord::EXP_EXPIRED) {
Telemetry::Accumulate(Telemetry::DNS_PREMATURE_EVICTION,
static_cast<uint32_t>(age.ToSeconds() / 60));
}
}
}
}

Просмотреть файл

@ -60,7 +60,7 @@ __FBSDID("$FreeBSD: head/sys/netinet/sctp_crc32.c 310590 2016-12-26 11:06:41Z tu
* non-NULL if the mode argument is equal to CONT or END
* p_buf - the packet buffer where crc computations are being performed
* length - the length of p_buf in bytes
* init_bytes - the number of initial bytes that need to be procesed before
* init_bytes - the number of initial bytes that need to be processed before
* aligning p_buf to multiples of 4 bytes
* mode - can be any of the following: BEGIN, CONT, END, BODY, ALIGN
*

Просмотреть файл

@ -63,12 +63,16 @@ enum class SHA1ModeResult {
// Whether or not we are enforcing one of our CA distrust policies. For context,
// see Bug 1437754 and Bug 1409257.
enum class DistrustedCAPolicy : uint32_t {
Permit = 0,
DistrustSymantecRoots = 1,
DistrustSymantecRootsRegardlessOfDate = 2,
enum DistrustedCAPolicy : uint32_t {
Permit = 0b0000,
DistrustSymantecRoots = 0b0001,
DistrustSymantecRootsRegardlessOfDate = 0b0010,
};
// Bitmask by nsNSSComponent to check for wholly-invalid values; be sure to
// update this to account for new entries in DistrustedCAPolicy.
const uint32_t DistrustedCAPolicyMaxAllowedValueMask = 0b0011;
enum class NetscapeStepUpPolicy : uint32_t;
class PinningTelemetryInfo

Просмотреть файл

@ -877,7 +877,8 @@ NSSCertDBTrustDomain::IsChainValid(const DERArray& certArray, Time time,
// handshake. To determine this, we check mHostname: If it isn't set, this is
// not TLS, so don't run the algorithm.
if (mHostname && CertDNIsInList(root.get(), RootSymantecDNs) &&
mDistrustedCAPolicy != DistrustedCAPolicy::Permit) {
((mDistrustedCAPolicy & DistrustedCAPolicy::DistrustSymantecRoots) ||
(mDistrustedCAPolicy & DistrustedCAPolicy::DistrustSymantecRootsRegardlessOfDate))) {
rootCert = nullptr; // Clear the state for Segment...
nsCOMPtr<nsIX509CertList> intCerts;
@ -893,9 +894,9 @@ NSSCertDBTrustDomain::IsChainValid(const DERArray& certArray, Time time,
// (new Date("2016-06-01T00:00:00Z")).getTime() * 1000
static const PRTime JUNE_1_2016 = 1464739200000000;
PRTime permitAfterDate = 0; // 0 indicates there is no permitAfterDate
if (mDistrustedCAPolicy == DistrustedCAPolicy::DistrustSymantecRoots) {
permitAfterDate = JUNE_1_2016;
PRTime permitAfterDate = JUNE_1_2016;
if (mDistrustedCAPolicy & DistrustedCAPolicy::DistrustSymantecRootsRegardlessOfDate) {
permitAfterDate = 0; // 0 indicates there is no permitAfterDate
}
bool isDistrusted = false;

Просмотреть файл

@ -1688,14 +1688,10 @@ void nsNSSComponent::setValidationOptions(bool isInitialSetting)
static_cast<DistrustedCAPolicy>
(Preferences::GetUint("security.pki.distrust_ca_policy",
static_cast<uint32_t>(defaultCAPolicyMode)));
switch(distrustedCAPolicy) {
case DistrustedCAPolicy::Permit:
case DistrustedCAPolicy::DistrustSymantecRoots:
case DistrustedCAPolicy::DistrustSymantecRootsRegardlessOfDate:
break;
default:
// If distrustedCAPolicy sets any bits larger than the maximum mask, fall back
// to the default.
if (distrustedCAPolicy & ~DistrustedCAPolicyMaxAllowedValueMask) {
distrustedCAPolicy = defaultCAPolicyMode;
break;
}
CertVerifier::OcspDownloadConfig odc;

Просмотреть файл

@ -40,11 +40,11 @@ add_connection_test("symantec-not-whitelisted-before-cutoff.example.com",
null, null);
// Enable the Firefox 63 total distrust; before or after cutoff should now all
// behave the same.
// behave the same. This will be made the default in Bug 1460062.
add_test(function() {
clearSessionCache();
Services.prefs.setIntPref("security.pki.distrust_ca_policy",
/* DistrustedCAPolicy::DistrustSymantecRootsRegardlessOfDate */ 2);
/* DistrustedCAPolicy::DistrustSymantecRootsRegardlessOfDate */ 0b10);
run_next_test();
});
@ -60,7 +60,7 @@ add_connection_test("symantec-not-whitelisted-after-cutoff.example.com",
add_test(function() {
clearSessionCache();
Services.prefs.setIntPref("security.pki.distrust_ca_policy",
/* DistrustedCAPolicy::Permit */ 0);
/* DistrustedCAPolicy::Permit */ 0b00);
run_next_test();
});
@ -96,7 +96,7 @@ add_task(async function() {
// Try with the policy for 60
Services.prefs.setIntPref("security.pki.distrust_ca_policy",
/* DistrustedCAPolicy::DistrustSymantecRoots */ 1);
/* DistrustedCAPolicy::DistrustSymantecRoots */ 0b01);
// (new Date("2018-02-16")).getTime() / 1000
const VALIDATION_TIME = 1518739200;
@ -106,8 +106,23 @@ add_task(async function() {
// Try with the policy for 63
Services.prefs.setIntPref("security.pki.distrust_ca_policy",
/* DistrustedCAPolicy::DistrustSymantecRootsRegardlessOfDate */ 2);
/* DistrustedCAPolicy::DistrustSymantecRootsRegardlessOfDate */ 0b10);
await checkCertErrorGenericAtTime(certDB, whitelistedCert, PRErrorCodeSuccess,
certificateUsageSSLServer, VALIDATION_TIME);
});
// Check invalid policy values; should default to current default
add_test(function() {
clearSessionCache();
Services.prefs.setIntPref("security.pki.distrust_ca_policy",
/* Larger than Max Value */ 0b1111);
run_next_test();
});
add_connection_test("symantec-not-whitelisted-before-cutoff.example.com",
MOZILLA_PKIX_ERROR_ADDITIONAL_POLICY_CONSTRAINT_FAILED,
null, null);
add_connection_test("symantec-not-whitelisted-after-cutoff.example.com",
PRErrorCodeSuccess, null, shouldBeImminentlyDistrusted);

Просмотреть файл

@ -54,7 +54,7 @@ ${helpers.predefined_type(
${helpers.single_keyword("background-attachment",
"scroll fixed" + (" local" if product == "gecko" else ""),
vector=True,
gecko_constant_prefix="NS_STYLE_IMAGELAYER_ATTACHMENT",
gecko_enum_prefix="StyleImageLayerAttachment",
spec="https://drafts.csswg.org/css-backgrounds/#the-background-attachment",
animation_value_type="discrete",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER")}

Просмотреть файл

@ -3231,6 +3231,17 @@
"n_buckets": 50,
"description": "DNS Cache Entry Age at Removal Time (minutes)"
},
"DNS_PREMATURE_EVICTION": {
"record_in_processes": ["main"],
"expires_in_version": "never",
"kind": "exponential",
"high": 1440,
"releaseChannelCollection": "opt-out",
"alert_emails": ["necko@mozilla.com", "dstenberg@mozilla.com"],
"bug_numbers": [1460305],
"n_buckets": 50,
"description": "DNS Cache Entry Age at Removal Time of non-expired entries (minutes)"
},
"DNS_LOOKUP_TIME": {
"record_in_processes": ["main"],
"expires_in_version": "never",
@ -3272,6 +3283,15 @@
"bug_numbers": [1434852],
"description": "DNS: TRR parallel resolve racing results"
},
"DNS_TRR_COMPARE": {
"record_in_processes": ["main"],
"alert_emails": ["necko@mozilla.com", "dstenberg@mozilla.com"],
"expires_in_version": "never",
"kind": "categorical",
"labels": ["BothWorked", "NativeWorked", "TRRWorked", "BothFailed"],
"bug_numbers": [1460589],
"description": "DNS: success distribution when both native and TRR were used"
},
"DNS_TRR_BLACKLISTED": {
"record_in_processes": ["main"],
"expires_in_version": "never",

Просмотреть файл

@ -840,7 +840,7 @@ LaunchCrashReporterActivity(XP_CHAR* aProgramPath, XP_CHAR* aMinidumpPath,
if (androidUserSerial) {
Unused << execlp("/system/bin/am",
"/system/bin/am",
"start",
"startservice",
"--user", androidUserSerial,
"-a", "org.mozilla.gecko.reportCrash",
"-n", aProgramPath,
@ -850,7 +850,7 @@ LaunchCrashReporterActivity(XP_CHAR* aProgramPath, XP_CHAR* aMinidumpPath,
} else {
Unused << execlp("/system/bin/am",
"/system/bin/am",
"start",
"startservice",
"-a", "org.mozilla.gecko.reportCrash",
"-n", aProgramPath,
"--es", "minidumpPath", aMinidumpPath,
@ -1544,10 +1544,10 @@ nsresult SetExceptionHandler(nsIFile* aXREDirectory,
const char* androidPackageName = PR_GetEnv("MOZ_ANDROID_PACKAGE_NAME");
if (androidPackageName != nullptr) {
nsCString package(androidPackageName);
package.AppendLiteral("/org.mozilla.gecko.CrashReporter");
package.AppendLiteral("/org.mozilla.gecko.CrashReporterService");
crashReporterPath = ToNewCString(package);
} else {
nsCString package(ANDROID_PACKAGE_NAME "/org.mozilla.gecko.CrashReporter");
nsCString package(ANDROID_PACKAGE_NAME "/org.mozilla.gecko.CrashReporterService");
crashReporterPath = ToNewCString(package);
}
#endif // !defined(MOZ_WIDGET_ANDROID)

Просмотреть файл

@ -407,6 +407,7 @@ nsAppShell::nsAppShell()
if (!XRE_IsParentProcess()) {
if (jni::IsAvailable()) {
GeckoThreadSupport::Init();
GeckoAppShellSupport::Init();
// Set the corresponding state in GeckoThread.
java::GeckoThread::SetState(java::GeckoThread::State::RUNNING());

Просмотреть файл

@ -3752,7 +3752,7 @@ IMEInputHandler::MaybeDispatchCurrentKeydownEvent(bool aIsProcessedByIME)
MOZ_LOG(gLog, LogLevel::Info,
("%p IMEInputHandler::MaybeDispatchKeydownEvent, aIsProcessedByIME=%s "
"currentKeyEvent={ mKeyEvent(%p)={ type=%s, keyCode=%s (0x%X) } }, "
"aIsProcesedBy=%s, IsDeadKeyComposing()=%s",
"aIsProcessedBy=%s, IsDeadKeyComposing()=%s",
this, TrueOrFalse(aIsProcessedByIME), nativeEvent,
GetNativeKeyEventType(nativeEvent),
GetKeyNameForNativeKeyCode([nativeEvent keyCode]), [nativeEvent keyCode],