Merge last green changeset from inbound to mozilla-central

This commit is contained in:
Matt Brubeck 2012-07-26 13:56:47 -07:00
commit 1f2f2074c4
93 changed files with 1167 additions and 646 deletions

View File

@ -615,7 +615,7 @@ Services.obs.addObserver(function ContentHandler(subject, topic, data) {
}, 'content-handler', false);
(function geolocationStatusTracker() {
gGeolocationActiveCount = 0;
let gGeolocationActiveCount = 0;
Services.obs.addObserver(function(aSubject, aTopic, aData) {
let oldCount = gGeolocationActiveCount;

View File

@ -4681,15 +4681,9 @@ var TabsInTitlebar = {
this._readPref();
Services.prefs.addObserver(this._prefName, this, false);
// Don't trust the initial value of the sizemode attribute; wait for the resize event.
// Don't trust the initial value of the sizemode attribute; wait for
// the resize event (handled in tabbrowser.xml).
this.allowedBy("sizemode", false);
window.addEventListener("resize", function (event) {
if (event.target != window)
return;
let sizemode = document.documentElement.getAttribute("sizemode");
TabsInTitlebar.allowedBy("sizemode",
sizemode == "maximized" || sizemode == "fullscreen");
}, false);
this._initialized = true;
#endif

View File

@ -3092,6 +3092,11 @@
case "resize":
if (aEvent.target != window)
break;
let sizemode = document.documentElement.getAttribute("sizemode");
TabsInTitlebar.allowedBy("sizemode",
sizemode == "maximized" || sizemode == "fullscreen");
var width = this.mTabstrip.boxObject.width;
if (width != this.mTabstripWidth) {
this.adjustTabstrip();
@ -3099,6 +3104,7 @@
this._handleTabSelect();
this.mTabstripWidth = width;
}
this.tabbrowser.updateWindowResizers();
break;
case "mouseout":

View File

@ -1457,7 +1457,7 @@ nsXMLHttpRequest::GetAllResponseHeaders(nsString& aResponseHeaders)
aResponseHeaders.AppendLiteral(";charset=");
AppendASCIItoUTF16(value, aResponseHeaders);
}
aResponseHeaders.Append('\n');
aResponseHeaders.AppendLiteral("\r\n");
}
}
@ -3981,7 +3981,7 @@ nsHeaderVisitor::VisitHeader(const nsACString &header, const nsACString &value)
mHeaders.Append(header);
mHeaders.Append(": ");
mHeaders.Append(value);
mHeaders.Append('\n');
mHeaders.Append("\r\n");
}
return NS_OK;
}

View File

@ -48,7 +48,7 @@ for (i = 0; i < passFiles.length; ++i) {
is(xhr.status, passFiles[i][2], "wrong status");
is(xhr.getResponseHeader("Content-Type"), passFiles[i][3], "wrong content type");
var headers = xhr.getAllResponseHeaders();
ok(/(?:^|\n)Content-Type:\s*([^\n]*)\n/i.test(headers) &&
ok(/(?:^|\n)Content-Type:\s*([^\r\n]*)\r\n/i.test(headers) &&
RegExp.$1 === passFiles[i][3], "wrong response headers");
if (xhr.responseXML) {
is((new XMLSerializer()).serializeToString(xhr.responseXML.documentElement),

View File

@ -93,6 +93,7 @@ using mozilla::plugins::PluginModuleParent;
#ifdef XP_WIN
#include <windows.h>
#include "nsWindowsHelpers.h"
#endif
#ifdef MOZ_WIDGET_ANDROID
@ -281,20 +282,6 @@ static bool GMA9XXGraphics()
}
#endif
#ifdef XP_WIN
static bool
IsVistaOrLater()
{
OSVERSIONINFO info;
ZeroMemory(&info, sizeof(OSVERSIONINFO));
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&info);
return info.dwMajorVersion >= 6;
}
#endif
bool
nsNPAPIPlugin::RunPluginOOP(const nsPluginTag *aPluginTag)
{

View File

@ -218,11 +218,15 @@ nsNPAPIPluginInstance::Destroy()
mPlugin = nsnull;
#if MOZ_WIDGET_ANDROID
if (mContentSurface)
mContentSurface->SetFrameAvailableCallback(nsnull);
mContentTexture = nsnull;
mContentSurface = nsnull;
std::map<void*, VideoInfo*>::iterator it;
for (it = mVideos.begin(); it != mVideos.end(); it++) {
it->second->mSurfaceTexture->SetFrameAvailableCallback(nsnull);
delete it->second;
}
mVideos.clear();
@ -988,11 +992,17 @@ nsSurfaceTexture* nsNPAPIPluginInstance::CreateSurfaceTexture()
if (!surface)
return nsnull;
nsCOMPtr<nsIRunnable> frameCallback = NS_NewRunnableMethod(this, &nsNPAPIPluginInstance::RedrawPlugin);
nsCOMPtr<nsIRunnable> frameCallback = NS_NewRunnableMethod(this, &nsNPAPIPluginInstance::OnSurfaceTextureFrameAvailable);
surface->SetFrameAvailableCallback(frameCallback);
return surface;
}
void nsNPAPIPluginInstance::OnSurfaceTextureFrameAvailable()
{
if (mRunning == RUNNING && mOwner)
RedrawPlugin();
}
void* nsNPAPIPluginInstance::AcquireContentWindow()
{
if (!mContentSurface) {

View File

@ -286,6 +286,7 @@ protected:
nsTArray<nsCOMPtr<PluginEventRunnable>> mPostedEvents;
void PopPostedEvent(PluginEventRunnable* r);
void OnSurfaceTextureFrameAvailable();
PRUint32 mFullScreenOrientation;
bool mWakeLocked;

View File

@ -460,6 +460,7 @@ const GET_RESPONSE_EF_SIZE_BYTES = 15;
// EF path
const EF_PATH_MF_SIM = "3f00";
const EF_PATH_DF_PHONEBOOK = "5f3a";
const EF_PATH_DF_TELECOM = "7f10";
const EF_PATH_DF_GSM = "7f20";

View File

@ -32,7 +32,8 @@ CPPSRCS = \
include $(topsrcdir)/config/rules.mk
INCLUDES += -I../../libeditor/base/src
INCLUDES += \
$(NULL)
_FILES = \
$(srcdir)/res/EditorOverride.css \

View File

@ -567,3 +567,9 @@ nsAuthGSSAPI::Wrap(const void *inToken,
return NS_OK;
}
NS_IMETHODIMP
nsAuthGSSAPI::GetModuleProperties(PRUint32 *flags)
{
*flags = 0;
return NS_OK;
}

View File

@ -149,3 +149,10 @@ nsAuthSASL::Wrap(const void *inToken,
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsAuthSASL::GetModuleProperties(PRUint32 *flags)
{
*flags = 0;
return NS_OK;
}

View File

@ -91,50 +91,6 @@ InitSSPI()
//-----------------------------------------------------------------------------
static nsresult
MakeSN(const char *principal, nsCString &result)
{
nsresult rv;
nsCAutoString buf(principal);
// The service name looks like "protocol@hostname", we need to map
// this to a value that SSPI expects. To be consistent with IE, we
// need to map '@' to '/' and canonicalize the hostname.
PRInt32 index = buf.FindChar('@');
if (index == kNotFound)
return NS_ERROR_UNEXPECTED;
nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv))
return rv;
// This could be expensive if our DNS cache cannot satisfy the request.
// However, we should have at least hit the OS resolver once prior to
// reaching this code, so provided the OS resolver has this information
// cached, we should not have to worry about blocking on this function call
// for very long. NOTE: because we ask for the canonical hostname, we
// might end up requiring extra network activity in cases where the OS
// resolver might not have enough information to satisfy the request from
// its cache. This is not an issue in versions of Windows up to WinXP.
nsCOMPtr<nsIDNSRecord> record;
rv = dns->Resolve(Substring(buf, index + 1),
nsIDNSService::RESOLVE_CANONICAL_NAME,
getter_AddRefs(record));
if (NS_FAILED(rv))
return rv;
nsCAutoString cname;
rv = record->GetCanonicalName(cname);
if (NS_SUCCEEDED(rv)) {
result = StringHead(buf, index) + NS_LITERAL_CSTRING("/") + cname;
LOG(("Using SPN of [%s]\n", result.get()));
}
return rv;
}
//-----------------------------------------------------------------------------
nsAuthSSPI::nsAuthSSPI(pType package)
: mServiceFlags(REQ_DEFAULT)
, mMaxTokenLen(0)
@ -208,23 +164,13 @@ nsAuthSSPI::Init(const char *serviceName,
package = (SEC_WCHAR *) pTypeName[(int)mPackage];
if (mPackage == PACKAGE_TYPE_NTLM) {
// (bug 535193) For NTLM, just use the uri host, do not do canonical host lookups.
// The incoming serviceName is in the format: "protocol@hostname", SSPI expects
// "<service class>/<hostname>", so swap the '@' for a '/'.
mServiceName.Assign(serviceName);
PRInt32 index = mServiceName.FindChar('@');
if (index == kNotFound)
return NS_ERROR_UNEXPECTED;
mServiceName.Replace(index, 1, '/');
}
else {
// Kerberos requires the canonical host, MakeSN takes care of this through a
// DNS lookup.
rv = MakeSN(serviceName, mServiceName);
if (NS_FAILED(rv))
return rv;
}
// The incoming serviceName is in the format: "protocol@hostname", SSPI expects
// "<service class>/<hostname>", so swap the '@' for a '/'.
mServiceName.Assign(serviceName);
PRInt32 index = mServiceName.FindChar('@');
if (index == kNotFound)
return NS_ERROR_UNEXPECTED;
mServiceName.Replace(index, 1, '/');
mServiceFlags = serviceFlags;
@ -653,3 +599,16 @@ nsAuthSSPI::Wrap(const void *inToken,
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsAuthSSPI::GetModuleProperties(PRUint32 *flags)
{
*flags = 0;
// (bug 535193) For NTLM, just use the uri host, do not do canonical host
// lookups. But Kerberos requires the canonical host.
if (mPackage != PACKAGE_TYPE_NTLM)
*flags |= CANONICAL_NAME_REQUIRED;
return NS_OK;
}

View File

@ -282,3 +282,10 @@ nsAuthSambaNTLM::Wrap(const void *inToken,
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsAuthSambaNTLM::GetModuleProperties(PRUint32 *flags)
{
*flags = 0;
return NS_OK;
}

View File

@ -631,11 +631,14 @@ LayerManagerD3D10::VerifyBufferSize()
}
mRTView = nsnull;
if (gfxWindowsPlatform::IsOptimus() ||
gfxWindowsPlatform::IsRunningInWindows8Metro()) {
if (gfxWindowsPlatform::IsOptimus()) {
mSwapChain->ResizeBuffers(1, rect.width, rect.height,
DXGI_FORMAT_B8G8R8A8_UNORM,
0);
} else if (gfxWindowsPlatform::IsRunningInWindows8Metro()) {
mSwapChain->ResizeBuffers(2, rect.width, rect.height,
DXGI_FORMAT_B8G8R8A8_UNORM,
0);
} else {
mSwapChain->ResizeBuffers(1, rect.width, rect.height,
DXGI_FORMAT_B8G8R8A8_UNORM,

View File

@ -44,6 +44,8 @@ public:
bool GetTransformMatrix(gfx3DMatrix& aMatrix);
int ID() { return mID; }
// The callback is guaranteed to be called on the main thread even
// if the upstream callback is received on a different thread
void SetFrameAvailableCallback(nsIRunnable* aRunnable);
// Only should be called by AndroidJNI when we get a

View File

@ -10,6 +10,7 @@
#include "mozilla/dom/battery/Constants.h"
#include <windows.h>
#include "nsWindowsHelpers.h"
using namespace mozilla::dom::battery;
@ -27,18 +28,6 @@ static HPOWERNOTIFY sPowerHandle = nsnull;
static HPOWERNOTIFY sCapacityHandle = nsnull;
static HWND sHWnd = nsnull;
static bool
IsVistaOrLater()
{
OSVERSIONINFO info;
ZeroMemory(&info, sizeof(OSVERSIONINFO));
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&info);
return info.dwMajorVersion >= 6;
}
static void
UpdateHandler(nsITimer* aTimer, void* aClosure) {
NS_ASSERTION(!IsVistaOrLater(),

View File

@ -423,38 +423,47 @@ struct ArenaHeader
* chunk. The latter allows to quickly check if the arena is allocated
* during the conservative GC scanning without searching the arena in the
* list.
*
* We use 8 bits for the allocKind so the compiler can use byte-level memory
* instructions to access it.
*/
size_t allocKind : 8;
/*
* When recursive marking uses too much stack the marking is delayed and
* the corresponding arenas are put into a stack using the following field
* as a linkage. To distinguish the bottom of the stack from the arenas
* not present in the stack we use an extra flag to tag arenas on the
* stack.
* When collecting we sometimes need to keep an auxillary list of arenas,
* for which we use the following fields. This happens for several reasons:
*
* When recursive marking uses too much stack the marking is delayed and the
* corresponding arenas are put into a stack. To distinguish the bottom of
* the stack from the arenas not present in the stack we use the
* markOverflow flag to tag arenas on the stack.
*
* Delayed marking is also used for arenas that we allocate into during an
* incremental GC. In this case, we intend to mark all the objects in the
* arena, and it's faster to do this marking in bulk.
*
* To minimize the ArenaHeader size we record the next delayed marking
* linkage as arenaAddress() >> ArenaShift and pack it with the allocKind
* field and hasDelayedMarking flag. We use 8 bits for the allocKind, not
* ArenaShift - 1, so the compiler can use byte-level memory instructions
* to access it.
* When sweeping we keep track of which arenas have been allocated since the
* end of the mark phase. This allows us to tell whether a pointer to an
* unmarked object is yet to be finalized or has already been reallocated.
* We set the allocatedDuringIncremental flag for this and clear it at the
* end of the sweep phase.
*
* To minimize the ArenaHeader size we record the next linkage as
* arenaAddress() >> ArenaShift and pack it with the allocKind field and the
* flags.
*/
public:
size_t hasDelayedMarking : 1;
size_t allocatedDuringIncremental : 1;
size_t markOverflow : 1;
size_t nextDelayedMarking : JS_BITS_PER_WORD - 8 - 1 - 1 - 1;
size_t auxNextLink : JS_BITS_PER_WORD - 8 - 1 - 1 - 1;
static void staticAsserts() {
/* We must be able to fit the allockind into uint8_t. */
JS_STATIC_ASSERT(FINALIZE_LIMIT <= 255);
/*
* nextDelayedMarkingpacking assumes that ArenaShift has enough bits
* auxNextLink packing assumes that ArenaShift has enough bits
* to cover allocKind and hasDelayedMarking.
*/
JS_STATIC_ASSERT(ArenaShift >= 8 + 1 + 1 + 1);
@ -487,7 +496,7 @@ struct ArenaHeader
markOverflow = 0;
allocatedDuringIncremental = 0;
hasDelayedMarking = 0;
nextDelayedMarking = 0;
auxNextLink = 0;
}
inline uintptr_t arenaAddress() const;
@ -519,6 +528,11 @@ struct ArenaHeader
inline ArenaHeader *getNextDelayedMarking() const;
inline void setNextDelayedMarking(ArenaHeader *aheader);
inline void unsetDelayedMarking();
inline ArenaHeader *getNextAllocDuringSweep() const;
inline void setNextAllocDuringSweep(ArenaHeader *aheader);
inline void unsetAllocDuringSweep();
};
struct Arena
@ -882,15 +896,48 @@ ArenaHeader::setFirstFreeSpan(const FreeSpan *span)
inline ArenaHeader *
ArenaHeader::getNextDelayedMarking() const
{
return &reinterpret_cast<Arena *>(nextDelayedMarking << ArenaShift)->aheader;
JS_ASSERT(hasDelayedMarking);
return &reinterpret_cast<Arena *>(auxNextLink << ArenaShift)->aheader;
}
inline void
ArenaHeader::setNextDelayedMarking(ArenaHeader *aheader)
{
JS_ASSERT(!(uintptr_t(aheader) & ArenaMask));
JS_ASSERT(!auxNextLink && !hasDelayedMarking);
hasDelayedMarking = 1;
nextDelayedMarking = aheader->arenaAddress() >> ArenaShift;
auxNextLink = aheader->arenaAddress() >> ArenaShift;
}
inline void
ArenaHeader::unsetDelayedMarking()
{
JS_ASSERT(hasDelayedMarking);
hasDelayedMarking = 0;
auxNextLink = 0;
}
inline ArenaHeader *
ArenaHeader::getNextAllocDuringSweep() const
{
JS_ASSERT(allocatedDuringIncremental);
return &reinterpret_cast<Arena *>(auxNextLink << ArenaShift)->aheader;
}
inline void
ArenaHeader::setNextAllocDuringSweep(ArenaHeader *aheader)
{
JS_ASSERT(!auxNextLink && !allocatedDuringIncremental);
allocatedDuringIncremental = 1;
auxNextLink = aheader->arenaAddress() >> ArenaShift;
}
inline void
ArenaHeader::unsetAllocDuringSweep()
{
JS_ASSERT(allocatedDuringIncremental);
allocatedDuringIncremental = 0;
auxNextLink = 0;
}
JS_ALWAYS_INLINE void

View File

@ -776,6 +776,11 @@ JSRuntime::JSRuntime()
gcDisableStrictProxyCheckingCount(0),
gcIncrementalState(gc::NO_INCREMENTAL),
gcLastMarkSlice(false),
gcSweepOnBackgroundThread(false),
gcSweepPhase(0),
gcSweepCompartmentIndex(0),
gcSweepKindIndex(0),
gcArenasAllocatedDuringSweep(NULL),
gcInterFrameGC(0),
gcSliceBudget(SliceBudget::Unlimited),
gcIncrementalEnabled(true),

View File

@ -564,6 +564,21 @@ struct JSRuntime : js::RuntimeFriendFields
/* Indicates that the last incremental slice exhausted the mark stack. */
bool gcLastMarkSlice;
/* Whether any sweeping will take place in the separate GC helper thread. */
bool gcSweepOnBackgroundThread;
/*
* Incremental sweep state.
*/
int gcSweepPhase;
ptrdiff_t gcSweepCompartmentIndex;
int gcSweepKindIndex;
/*
* List head of arenas allocated during the sweep phase.
*/
js::gc::ArenaHeader *gcArenasAllocatedDuringSweep;
/*
* Indicates that a GC slice has taken place in the middle of an animation
* frame, rather than at the beginning. In this case, the next slice will be

View File

@ -47,6 +47,7 @@ JSCompartment::JSCompartment(JSRuntime *rt)
needsBarrier_(false),
gcState(NoGCScheduled),
gcPreserveCode(false),
gcStarted(false),
gcBytes(0),
gcTriggerBytes(0),
gcHeapGrowthFactor(3.0),

View File

@ -174,6 +174,7 @@ struct JSCompartment
CompartmentGCState gcState;
bool gcPreserveCode;
bool gcStarted;
public:
bool isCollecting() const {
@ -226,6 +227,19 @@ struct JSCompartment
gcPreserveCode = preserving;
}
bool wasGCStarted() const {
return gcStarted;
}
void setGCStarted(bool started) {
JS_ASSERT(rt->isHeapBusy());
gcStarted = started;
}
bool isGCSweeping() {
return wasGCStarted() && rt->gcIncrementalState == js::gc::SWEEP;
}
size_t gcBytes;
size_t gcTriggerBytes;
size_t gcMaxMallocBytes;

View File

@ -127,7 +127,7 @@ js::PrepareForIncrementalGC(JSRuntime *rt)
return;
for (CompartmentsIter c(rt); !c.done(); c.next()) {
if (c->needsBarrier())
if (c->wasGCStarted())
PrepareCompartmentForGC(c);
}
}

View File

@ -632,6 +632,7 @@ SizeOfJSContext();
D(DEBUG_GC) \
D(DEBUG_MODE_GC) \
D(TRANSPLANT) \
D(RESET) \
\
/* Reasons from Firefox */ \
D(DOM_WINDOW_UTILS) \

View File

@ -200,6 +200,29 @@ const uint32_t Arena::FirstThingOffsets[] = {
#undef OFFSET
/*
* Finalization order for incrementally swept things.
*/
static const AllocKind FinalizePhaseShapes[] = {
FINALIZE_SHAPE,
FINALIZE_BASE_SHAPE,
FINALIZE_TYPE_OBJECT
};
static const AllocKind* FinalizePhases[] = {
FinalizePhaseShapes
};
static const int FinalizePhaseCount = sizeof(FinalizePhases) / sizeof(AllocKind*);
static const int FinalizePhaseLength[] = {
sizeof(FinalizePhaseShapes) / sizeof(AllocKind)
};
static const gcstats::Phase FinalizePhaseStatsPhase[] = {
gcstats::PHASE_SWEEP_SHAPE
};
#ifdef DEBUG
void
ArenaHeader::checkSynchronizedWithFreeList() const
@ -327,46 +350,60 @@ Arena::finalize(FreeOp *fop, AllocKind thingKind, size_t thingSize)
return false;
}
/*
* Insert an arena into the list in appropriate position and update the cursor
* to ensure that any arena before the cursor is full.
*/
void ArenaList::insert(ArenaHeader *a)
{
JS_ASSERT(a);
JS_ASSERT_IF(!head, cursor == &head);
a->next = *cursor;
*cursor = a;
if (!a->hasFreeThings())
cursor = &a->next;
}
template<typename T>
inline void
FinalizeTypedArenas(FreeOp *fop, ArenaLists::ArenaList *al, AllocKind thingKind)
inline bool
FinalizeTypedArenas(FreeOp *fop,
ArenaHeader **src,
ArenaList &dest,
AllocKind thingKind,
SliceBudget &budget)
{
/*
* Release empty arenas and move non-full arenas with some free things into
* a separated list that we append to al after the loop to ensure that any
* arena before al->cursor is full.
* Finalize arenas from src list, releasing empty arenas and inserting the
* others into dest in an appropriate position.
*/
JS_ASSERT_IF(!al->head, al->cursor == &al->head);
ArenaLists::ArenaList available;
ArenaHeader **ap = &al->head;
size_t thingSize = Arena::thingSize(thingKind);
while (ArenaHeader *aheader = *ap) {
while (ArenaHeader *aheader = *src) {
*src = aheader->next;
bool allClear = aheader->getArena()->finalize<T>(fop, thingKind, thingSize);
if (allClear) {
*ap = aheader->next;
if (allClear)
aheader->chunk()->releaseArena(aheader);
} else if (aheader->hasFreeThings()) {
*ap = aheader->next;
*available.cursor = aheader;
available.cursor = &aheader->next;
} else {
ap = &aheader->next;
}
else
dest.insert(aheader);
budget.step(Arena::thingsPerArena(thingSize));
if (budget.isOverBudget())
return false;
}
/* Terminate the available list and append it to al. */
*available.cursor = NULL;
*ap = available.head;
al->cursor = ap;
JS_ASSERT_IF(!al->head, al->cursor == &al->head);
return true;
}
/*
* Finalize the list. On return al->cursor points to the first non-empty arena
* after the al->head.
*/
static void
FinalizeArenas(FreeOp *fop, ArenaLists::ArenaList *al, AllocKind thingKind)
static bool
FinalizeArenas(FreeOp *fop,
ArenaHeader **src,
ArenaList &dest,
AllocKind thingKind,
SliceBudget &budget)
{
switch(thingKind) {
case FINALIZE_OBJECT0:
@ -381,34 +418,28 @@ FinalizeArenas(FreeOp *fop, ArenaLists::ArenaList *al, AllocKind thingKind)
case FINALIZE_OBJECT12_BACKGROUND:
case FINALIZE_OBJECT16:
case FINALIZE_OBJECT16_BACKGROUND:
FinalizeTypedArenas<JSObject>(fop, al, thingKind);
break;
return FinalizeTypedArenas<JSObject>(fop, src, dest, thingKind, budget);
case FINALIZE_SCRIPT:
FinalizeTypedArenas<JSScript>(fop, al, thingKind);
break;
return FinalizeTypedArenas<JSScript>(fop, src, dest, thingKind, budget);
case FINALIZE_SHAPE:
FinalizeTypedArenas<Shape>(fop, al, thingKind);
break;
return FinalizeTypedArenas<Shape>(fop, src, dest, thingKind, budget);
case FINALIZE_BASE_SHAPE:
FinalizeTypedArenas<BaseShape>(fop, al, thingKind);
break;
return FinalizeTypedArenas<BaseShape>(fop, src, dest, thingKind, budget);
case FINALIZE_TYPE_OBJECT:
FinalizeTypedArenas<types::TypeObject>(fop, al, thingKind);
break;
return FinalizeTypedArenas<types::TypeObject>(fop, src, dest, thingKind, budget);
#if JS_HAS_XML_SUPPORT
case FINALIZE_XML:
FinalizeTypedArenas<JSXML>(fop, al, thingKind);
break;
return FinalizeTypedArenas<JSXML>(fop, src, dest, thingKind, budget);
#endif
case FINALIZE_STRING:
FinalizeTypedArenas<JSString>(fop, al, thingKind);
break;
return FinalizeTypedArenas<JSString>(fop, src, dest, thingKind, budget);
case FINALIZE_SHORT_STRING:
FinalizeTypedArenas<JSShortString>(fop, al, thingKind);
break;
return FinalizeTypedArenas<JSShortString>(fop, src, dest, thingKind, budget);
case FINALIZE_EXTERNAL_STRING:
FinalizeTypedArenas<JSExternalString>(fop, al, thingKind);
break;
return FinalizeTypedArenas<JSExternalString>(fop, src, dest, thingKind, budget);
default:
JS_NOT_REACHED("Invalid alloc kind");
return true;
}
}
@ -1436,6 +1467,13 @@ ArenaLists::prepareForIncrementalGC(JSRuntime *rt)
}
}
static inline void
PushArenaAllocatedDuringSweep(JSRuntime *runtime, ArenaHeader *arena)
{
arena->setNextAllocDuringSweep(runtime->gcArenasAllocatedDuringSweep);
runtime->gcArenasAllocatedDuringSweep = arena;
}
inline void *
ArenaLists::allocateFromArena(JSCompartment *comp, AllocKind thingKind)
{
@ -1489,9 +1527,13 @@ ArenaLists::allocateFromArena(JSCompartment *comp, AllocKind thingKind)
*/
freeLists[thingKind] = aheader->getFirstFreeSpan();
aheader->setAsFullyUsed();
if (JS_UNLIKELY(comp->needsBarrier())) {
aheader->allocatedDuringIncremental = true;
comp->rt->gcMarker.delayMarkingArena(aheader);
if (JS_UNLIKELY(comp->wasGCStarted())) {
if (comp->needsBarrier()) {
aheader->allocatedDuringIncremental = true;
comp->rt->gcMarker.delayMarkingArena(aheader);
} else if (comp->isGCSweeping()) {
PushArenaAllocatedDuringSweep(comp->rt, aheader);
}
}
return freeLists[thingKind].infallibleAllocate(Arena::thingSize(thingKind));
}
@ -1518,9 +1560,13 @@ ArenaLists::allocateFromArena(JSCompartment *comp, AllocKind thingKind)
if (!aheader)
return NULL;
if (JS_UNLIKELY(comp->needsBarrier())) {
aheader->allocatedDuringIncremental = true;
comp->rt->gcMarker.delayMarkingArena(aheader);
if (JS_UNLIKELY(comp->wasGCStarted())) {
if (comp->needsBarrier()) {
aheader->allocatedDuringIncremental = true;
comp->rt->gcMarker.delayMarkingArena(aheader);
} else if (comp->isGCSweeping()) {
PushArenaAllocatedDuringSweep(comp->rt, aheader);
}
}
aheader->next = al->head;
if (!al->head) {
@ -1539,14 +1585,31 @@ ArenaLists::allocateFromArena(JSCompartment *comp, AllocKind thingKind)
void
ArenaLists::finalizeNow(FreeOp *fop, AllocKind thingKind)
{
JS_ASSERT(!fop->onBackgroundThread());
JS_ASSERT(backgroundFinalizeState[thingKind] == BFS_DONE ||
backgroundFinalizeState[thingKind] == BFS_JUST_FINISHED);
ArenaHeader *arenas = arenaLists[thingKind].head;
arenaLists[thingKind].clear();
SliceBudget budget;
FinalizeArenas(fop, &arenas, arenaLists[thingKind], thingKind, budget);
JS_ASSERT(!arenas);
}
void
ArenaLists::queueForForegroundSweep(FreeOp *fop, AllocKind thingKind)
{
JS_ASSERT(!fop->onBackgroundThread());
JS_ASSERT(backgroundFinalizeState[thingKind] == BFS_DONE);
FinalizeArenas(fop, &arenaLists[thingKind], thingKind);
JS_ASSERT(!arenaListsToSweep[thingKind]);
arenaListsToSweep[thingKind] = arenaLists[thingKind].head;
arenaLists[thingKind].clear();
}
inline void
ArenaLists::finalizeLater(FreeOp *fop, AllocKind thingKind)
ArenaLists::queueForBackgroundSweep(FreeOp *fop, AllocKind thingKind)
{
JS_ASSERT(thingKind == FINALIZE_OBJECT0_BACKGROUND ||
thingKind == FINALIZE_OBJECT2_BACKGROUND ||
@ -1585,7 +1648,7 @@ ArenaLists::finalizeLater(FreeOp *fop, AllocKind thingKind)
al->clear();
backgroundFinalizeState[thingKind] = BFS_RUN;
} else {
FinalizeArenas(fop, al, thingKind);
finalizeNow(fop, thingKind);
backgroundFinalizeState[thingKind] = BFS_DONE;
}
@ -1605,9 +1668,11 @@ ArenaLists::backgroundFinalize(FreeOp *fop, ArenaHeader *listHead)
JS_ASSERT(listHead);
AllocKind thingKind = listHead->getAllocKind();
JSCompartment *comp = listHead->compartment;
ArenaList finalized;
finalized.head = listHead;
FinalizeArenas(fop, &finalized, thingKind);
SliceBudget budget;
FinalizeArenas(fop, &listHead, finalized, thingKind, budget);
JS_ASSERT(!listHead);
/*
* After we finish the finalization al->cursor must point to the end of
@ -1641,7 +1706,7 @@ ArenaLists::backgroundFinalize(FreeOp *fop, ArenaHeader *listHead)
}
void
ArenaLists::finalizeObjects(FreeOp *fop)
ArenaLists::queueObjectsForSweep(FreeOp *fop)
{
finalizeNow(fop, FINALIZE_OBJECT0);
finalizeNow(fop, FINALIZE_OBJECT2);
@ -1650,12 +1715,12 @@ ArenaLists::finalizeObjects(FreeOp *fop)
finalizeNow(fop, FINALIZE_OBJECT12);
finalizeNow(fop, FINALIZE_OBJECT16);
finalizeLater(fop, FINALIZE_OBJECT0_BACKGROUND);
finalizeLater(fop, FINALIZE_OBJECT2_BACKGROUND);
finalizeLater(fop, FINALIZE_OBJECT4_BACKGROUND);
finalizeLater(fop, FINALIZE_OBJECT8_BACKGROUND);
finalizeLater(fop, FINALIZE_OBJECT12_BACKGROUND);
finalizeLater(fop, FINALIZE_OBJECT16_BACKGROUND);
queueForBackgroundSweep(fop, FINALIZE_OBJECT0_BACKGROUND);
queueForBackgroundSweep(fop, FINALIZE_OBJECT2_BACKGROUND);
queueForBackgroundSweep(fop, FINALIZE_OBJECT4_BACKGROUND);
queueForBackgroundSweep(fop, FINALIZE_OBJECT8_BACKGROUND);
queueForBackgroundSweep(fop, FINALIZE_OBJECT12_BACKGROUND);
queueForBackgroundSweep(fop, FINALIZE_OBJECT16_BACKGROUND);
#if JS_HAS_XML_SUPPORT
finalizeNow(fop, FINALIZE_XML);
@ -1663,26 +1728,26 @@ ArenaLists::finalizeObjects(FreeOp *fop)
}
void
ArenaLists::finalizeStrings(FreeOp *fop)
ArenaLists::queueStringsForSweep(FreeOp *fop)
{
finalizeLater(fop, FINALIZE_SHORT_STRING);
finalizeLater(fop, FINALIZE_STRING);
queueForBackgroundSweep(fop, FINALIZE_SHORT_STRING);
queueForBackgroundSweep(fop, FINALIZE_STRING);
finalizeNow(fop, FINALIZE_EXTERNAL_STRING);
}
void
ArenaLists::finalizeShapes(FreeOp *fop)
ArenaLists::queueScriptsForSweep(FreeOp *fop)
{
finalizeNow(fop, FINALIZE_SHAPE);
finalizeNow(fop, FINALIZE_BASE_SHAPE);
finalizeNow(fop, FINALIZE_TYPE_OBJECT);
finalizeNow(fop, FINALIZE_SCRIPT);
}
void
ArenaLists::finalizeScripts(FreeOp *fop)
ArenaLists::queueShapesForSweep(FreeOp *fop)
{
finalizeNow(fop, FINALIZE_SCRIPT);
queueForForegroundSweep(fop, FINALIZE_SHAPE);
queueForForegroundSweep(fop, FINALIZE_BASE_SHAPE);
queueForForegroundSweep(fop, FINALIZE_TYPE_OBJECT);
}
static void
@ -1923,7 +1988,7 @@ GCMarker::reset()
JS_ASSERT(aheader->hasDelayedMarking);
JS_ASSERT(markLaterArenas);
unmarkedArenaStackTop = aheader->getNextDelayedMarking();
aheader->hasDelayedMarking = 0;
aheader->unsetDelayedMarking();
aheader->markOverflow = 0;
aheader->allocatedDuringIncremental = 0;
markLaterArenas--;
@ -2006,7 +2071,7 @@ GCMarker::markDelayedChildren(SliceBudget &budget)
JS_ASSERT(aheader->hasDelayedMarking);
JS_ASSERT(markLaterArenas);
unmarkedArenaStackTop = aheader->getNextDelayedMarking();
aheader->hasDelayedMarking = 0;
aheader->unsetDelayedMarking();
markLaterArenas--;
markDelayedChildren(aheader);
@ -3042,9 +3107,11 @@ ReleaseObservedTypes(JSRuntime *rt)
}
static void
SweepCompartments(FreeOp *fop, JSGCInvocationKind gckind)
SweepCompartments(FreeOp *fop, gcreason::Reason gcReason)
{
JSRuntime *rt = fop->runtime();
JS_ASSERT_IF(gcReason == gcreason::LAST_CONTEXT, !rt->hasContexts());
JSDestroyCompartmentCallback callback = rt->destroyCompartmentCallback;
/* Skip the atomsCompartment. */
@ -3058,7 +3125,7 @@ SweepCompartments(FreeOp *fop, JSGCInvocationKind gckind)
JSCompartment *compartment = *read++;
if (!compartment->hold && compartment->isCollecting() &&
(compartment->arenas.arenaListsAreEmpty() || !rt->hasContexts()))
(compartment->arenas.arenaListsAreEmpty() || gcReason == gcreason::LAST_CONTEXT))
{
compartment->arenas.checkEmptyFreeLists();
if (callback)
@ -3133,7 +3200,13 @@ BeginMarkPhase(JSRuntime *rt, bool isIncremental)
rt->gcIsFull = true;
for (CompartmentsIter c(rt); !c.done(); c.next()) {
if (!c->isCollecting())
JS_ASSERT(!c->wasGCStarted());
for (unsigned i = 0 ; i < FINALIZE_LIMIT ; ++i)
JS_ASSERT(!c->arenas.arenaListsToSweep[i]);
if (c->isCollecting())
c->setGCStarted(true);
else
rt->gcIsFull = false;
c->setPreservingCode(ShouldPreserveJITCode(c, currentTime));
@ -3384,7 +3457,7 @@ ValidateIncrementalMarking(JSRuntime *rt)
#endif
static void
SweepPhase(JSRuntime *rt, JSGCInvocationKind gckind, bool *startBackgroundSweep)
BeginSweepPhase(JSRuntime *rt)
{
/*
* Sweep phase.
@ -3412,13 +3485,14 @@ SweepPhase(JSRuntime *rt, JSGCInvocationKind gckind, bool *startBackgroundSweep)
isFull = false;
}
*startBackgroundSweep = (rt->hasContexts() && rt->gcHelperThread.prepareForBackgroundSweep());
rt->gcSweepOnBackgroundThread =
(rt->hasContexts() && rt->gcHelperThread.prepareForBackgroundSweep());
/* Purge the ArenaLists before sweeping. */
for (GCCompartmentsIter c(rt); !c.done(); c.next())
c->arenas.purge();
FreeOp fop(rt, *startBackgroundSweep, false);
FreeOp fop(rt, rt->gcSweepOnBackgroundThread, false);
{
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_FINALIZE_START);
@ -3453,37 +3527,82 @@ SweepPhase(JSRuntime *rt, JSGCInvocationKind gckind, bool *startBackgroundSweep)
}
}
{
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_OBJECT);
/*
* Queue all GC things in all compartments for sweeping, either in the
* foreground or on the background thread.
*
* Note that order is important here for the background case.
*
* Objects are finalized immediately but this may change in the future.
*/
for (GCCompartmentsIter c(rt); !c.done(); c.next())
c->arenas.queueObjectsForSweep(&fop);
for (GCCompartmentsIter c(rt); !c.done(); c.next())
c->arenas.queueStringsForSweep(&fop);
for (GCCompartmentsIter c(rt); !c.done(); c.next())
c->arenas.queueScriptsForSweep(&fop);
for (GCCompartmentsIter c(rt); !c.done(); c.next())
c->arenas.queueShapesForSweep(&fop);
/*
* We finalize objects before other GC things to ensure that the object's
* finalizer can access the other things even if they will be freed.
*/
for (GCCompartmentsIter c(rt); !c.done(); c.next())
c->arenas.finalizeObjects(&fop);
}
rt->gcSweepPhase = 0;
rt->gcSweepCompartmentIndex = 0;
rt->gcSweepKindIndex = 0;
{
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_STRING);
for (GCCompartmentsIter c(rt); !c.done(); c.next())
c->arenas.finalizeStrings(&fop);
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_FINALIZE_END);
if (rt->gcFinalizeCallback)
rt->gcFinalizeCallback(&fop, JSFINALIZE_END, !rt->gcIsFull);
}
}
bool
ArenaLists::foregroundFinalize(FreeOp *fop, AllocKind thingKind, SliceBudget &sliceBudget)
{
if (!arenaListsToSweep[thingKind])
return true;
ArenaList &dest = arenaLists[thingKind];
return FinalizeArenas(fop, &arenaListsToSweep[thingKind], dest, thingKind, sliceBudget);
}
static bool
SweepPhase(JSRuntime *rt, SliceBudget &sliceBudget)
{
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP);
FreeOp fop(rt, rt->gcSweepOnBackgroundThread, false);
for (; rt->gcSweepPhase < FinalizePhaseCount ; ++rt->gcSweepPhase) {
gcstats::AutoPhase ap(rt->gcStats, FinalizePhaseStatsPhase[rt->gcSweepPhase]);
ptrdiff_t len = rt->compartments.end() - rt->compartments.begin();
for (; rt->gcSweepCompartmentIndex < len ; ++rt->gcSweepCompartmentIndex) {
JSCompartment *c = rt->compartments.begin()[rt->gcSweepCompartmentIndex];
if (c->wasGCStarted()) {
while (rt->gcSweepKindIndex < FinalizePhaseLength[rt->gcSweepPhase]) {
AllocKind kind = FinalizePhases[rt->gcSweepPhase][rt->gcSweepKindIndex];
if (!c->arenas.foregroundFinalize(&fop, kind, sliceBudget))
return false;
++rt->gcSweepKindIndex;
}
}
rt->gcSweepKindIndex = 0;
}
rt->gcSweepCompartmentIndex = 0;
}
{
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_SCRIPT);
for (GCCompartmentsIter c(rt); !c.done(); c.next())
c->arenas.finalizeScripts(&fop);
}
return true;
}
{
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_SHAPE);
for (GCCompartmentsIter c(rt); !c.done(); c.next())
c->arenas.finalizeShapes(&fop);
}
static void
EndSweepPhase(JSRuntime *rt, JSGCInvocationKind gckind, gcreason::Reason gcReason)
{
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP);
FreeOp fop(rt, rt->gcSweepOnBackgroundThread, false);
#ifdef DEBUG
PropertyTree::dumpShapes(rt);
PropertyTree::dumpShapes(rt);
#endif
{
@ -3504,7 +3623,7 @@ SweepPhase(JSRuntime *rt, JSGCInvocationKind gckind, bool *startBackgroundSweep)
* This removes compartments from rt->compartment, so we do it last to make
* sure we don't miss sweeping any compartments.
*/
SweepCompartments(&fop, gckind);
SweepCompartments(&fop, gcReason);
#ifndef JS_THREADSAFE
/*
@ -3516,14 +3635,24 @@ SweepPhase(JSRuntime *rt, JSGCInvocationKind gckind, bool *startBackgroundSweep)
#endif
}
{
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_FINALIZE_END);
if (rt->gcFinalizeCallback)
rt->gcFinalizeCallback(&fop, JSFINALIZE_END, !isFull);
/*
* Reset the list of arenas marked as being allocated during sweep phase.
*/
while (ArenaHeader *arena = rt->gcArenasAllocatedDuringSweep) {
rt->gcArenasAllocatedDuringSweep = arena->getNextAllocDuringSweep();
arena->unsetAllocDuringSweep();
}
for (CompartmentsIter c(rt); !c.done(); c.next())
for (CompartmentsIter c(rt); !c.done(); c.next()) {
c->setGCLastBytes(c->gcBytes, c->gcMallocAndFreeBytes, gckind);
if (c->wasGCStarted())
c->setGCStarted(false);
JS_ASSERT(!c->wasGCStarted());
for (unsigned i = 0 ; i < FINALIZE_LIMIT ; ++i)
JS_ASSERT(!c->arenas.arenaListsToSweep[i]);
}
rt->gcLastGCTime = PRMJ_Now();
}
@ -3608,17 +3737,38 @@ AutoGCSession::~AutoGCSession()
runtime->resetGCMallocBytes();
}
static void
IncrementalCollectSlice(JSRuntime *rt,
int64_t budget,
gcreason::Reason gcReason,
JSGCInvocationKind gcKind);
static void
ResetIncrementalGC(JSRuntime *rt, const char *reason)
{
if (rt->gcIncrementalState == NO_INCREMENTAL)
return;
for (CompartmentsIter c(rt); !c.done(); c.next())
if (rt->gcIncrementalState == SWEEP) {
/* If we've finished marking then sweep to completion here. */
IncrementalCollectSlice(rt, SliceBudget::Unlimited, gcreason::RESET, GC_NORMAL);
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_WAIT_BACKGROUND_THREAD);
rt->gcHelperThread.waitBackgroundSweepOrAllocEnd();
return;
}
JS_ASSERT(rt->gcIncrementalState == MARK);
for (CompartmentsIter c(rt); !c.done(); c.next()) {
c->setNeedsBarrier(false);
c->setGCStarted(false);
for (unsigned i = 0 ; i < FINALIZE_LIMIT ; ++i)
JS_ASSERT(!c->arenas.arenaListsToSweep[i]);
}
rt->gcMarker.reset();
rt->gcMarker.stop();
rt->gcIncrementalState = NO_INCREMENTAL;
JS_ASSERT(!rt->gcStrictCompartmentChecking);
@ -3648,10 +3798,12 @@ AutoGCSlice::AutoGCSlice(JSRuntime *rt)
for (GCCompartmentsIter c(rt); !c.done(); c.next()) {
/* Clear this early so we don't do any write barriers during GC. */
if (rt->gcIncrementalState == MARK)
if (rt->gcIncrementalState == MARK) {
JS_ASSERT(c->needsBarrier());
c->setNeedsBarrier(false);
else
} else {
JS_ASSERT(!c->needsBarrier());
}
}
}
@ -3662,7 +3814,8 @@ AutoGCSlice::~AutoGCSlice()
c->setNeedsBarrier(true);
c->arenas.prepareForIncrementalGC(runtime);
} else {
JS_ASSERT(runtime->gcIncrementalState == NO_INCREMENTAL);
JS_ASSERT(runtime->gcIncrementalState == NO_INCREMENTAL ||
runtime->gcIncrementalState == SWEEP);
c->setNeedsBarrier(false);
}
}
@ -3685,20 +3838,49 @@ class AutoCopyFreeListToArenas {
};
static void
IncrementalMarkSlice(JSRuntime *rt, int64_t budget, gcreason::Reason reason, bool *shouldSweep)
PushZealSelectedObjects(JSRuntime *rt)
{
#ifdef JS_GC_ZEAL
/* Push selected objects onto the mark stack and clear the list. */
for (JSObject **obj = rt->gcSelectedForMarking.begin();
obj != rt->gcSelectedForMarking.end(); obj++)
{
MarkObjectUnbarriered(&rt->gcMarker, obj, "selected obj");
}
#endif
}
static bool
DrainMarkStack(JSRuntime *rt, SliceBudget &sliceBudget)
{
/* Run a marking slice and return whether the stack is now empty. */
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_MARK);
return rt->gcMarker.drainMarkStack(sliceBudget);
}
static void
IncrementalCollectSlice(JSRuntime *rt,
int64_t budget,
gcreason::Reason reason,
JSGCInvocationKind gckind)
{
AutoCopyFreeListToArenas copy(rt);
AutoGCSlice slice(rt);
gc::State initialState = rt->gcIncrementalState;
*shouldSweep = false;
SliceBudget sliceBudget(budget);
int zeal = 0;
#ifdef JS_GC_ZEAL
if (reason == gcreason::DEBUG_GC) {
// Do the collection type specified by zeal mode only if the collection
// was triggered by RunDebugGC().
/*
* Do the collection type specified by zeal mode only if the collection
* was triggered by RunDebugGC().
*/
zeal = rt->gcZeal();
JS_ASSERT_IF(zeal == ZealIncrementalMarkAllThenFinish ||
zeal == ZealIncrementalRootsThenFinish,
budget == SliceBudget::Unlimited);
}
#endif
@ -3712,51 +3894,88 @@ IncrementalMarkSlice(JSRuntime *rt, int64_t budget, gcreason::Reason reason, boo
rt->gcLastMarkSlice = false;
}
if (rt->gcIncrementalState == MARK_ROOTS) {
switch (rt->gcIncrementalState) {
case MARK_ROOTS:
BeginMarkPhase(rt, isIncremental);
PushZealSelectedObjects(rt);
rt->gcIncrementalState = MARK;
if (zeal == ZealIncrementalRootsThenFinish)
return;
}
break;
if (rt->gcIncrementalState == MARK) {
SliceBudget sliceBudget(budget);
/* fall through */
case MARK: {
/* If we needed delayed marking for gray roots, then collect until done. */
if (!rt->gcMarker.hasBufferedGrayRoots())
sliceBudget.reset();
#ifdef JS_GC_ZEAL
if (!rt->gcSelectedForMarking.empty()) {
for (JSObject **obj = rt->gcSelectedForMarking.begin();
obj != rt->gcSelectedForMarking.end(); obj++)
{
MarkObjectUnbarriered(&rt->gcMarker, obj, "selected obj");
}
bool finished = DrainMarkStack(rt, sliceBudget);
if (!finished)
break;
JS_ASSERT(rt->gcMarker.isDrained());
if (!rt->gcLastMarkSlice &&
((initialState == MARK && budget != SliceBudget::Unlimited) ||
zeal == ZealIncrementalMarkAllThenFinish))
{
/*
* Yield with the aim of starting the sweep in the next
* slice. We will need to mark anything new on the stack
* when we resume, so we stay in MARK state.
*/
rt->gcLastMarkSlice = true;
break;
}
EndMarkPhase(rt, isIncremental);
rt->gcIncrementalState = SWEEP;
/*
* This runs to completion, but we don't continue if the budget is
* now exhasted.
*/
BeginSweepPhase(rt);
if (sliceBudget.isOverBudget())
break;
/*
* Always yield here when running in incremental multi-slice zeal
* mode, so RunDebugGC can reset the slice buget.
*/
if (budget != SliceBudget::Unlimited && zeal == ZealIncrementalMultipleSlices)
break;
/* fall through */
}
case SWEEP: {
#ifdef DEBUG
for (CompartmentsIter c(rt); !c.done(); c.next())
JS_ASSERT(!c->needsBarrier());
#endif
bool finished;
{
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_MARK);
finished = rt->gcMarker.drainMarkStack(sliceBudget);
}
if (finished) {
JS_ASSERT(rt->gcMarker.isDrained());
bool finished = SweepPhase(rt, sliceBudget);
if (!finished)
break;
if (!rt->gcLastMarkSlice &&
((initialState == MARK && budget != SliceBudget::Unlimited) ||
zeal == ZealIncrementalMarkAllThenFinish))
{
rt->gcLastMarkSlice = true;
} else {
EndMarkPhase(rt, isIncremental);
rt->gcIncrementalState = NO_INCREMENTAL;
*shouldSweep = true;
}
}
}
EndSweepPhase(rt, gckind, reason);
if (rt->gcSweepOnBackgroundThread)
rt->gcHelperThread.startBackgroundSweep(gckind == GC_SHRINK);
rt->gcIncrementalState = NO_INCREMENTAL;
break;
}
default:
JS_ASSERT(false);
}
}
class IncrementalSafety
@ -3834,8 +4053,10 @@ BudgetIncrementalGC(JSRuntime *rt, int64_t *budget)
rt->gcStats.nonincremental("malloc bytes trigger");
}
if (c->isCollecting() != c->needsBarrier())
if (rt->gcIncrementalState != NO_INCREMENTAL &&
c->isCollecting() != c->wasGCStarted()) {
reset = true;
}
}
if (reset)
@ -3877,7 +4098,6 @@ GCCycle(JSRuntime *rt, bool incremental, int64_t budget, JSGCInvocationKind gcki
rt->gcHelperThread.waitBackgroundSweepOrAllocEnd();
}
bool startBackgroundSweep = false;
{
if (!incremental) {
/* If non-incremental GC was requested, reset incremental GC. */
@ -3888,23 +4108,8 @@ GCCycle(JSRuntime *rt, bool incremental, int64_t budget, JSGCInvocationKind gcki
BudgetIncrementalGC(rt, &budget);
}
AutoCopyFreeListToArenas copy(rt);
bool shouldSweep;
IncrementalMarkSlice(rt, budget, reason, &shouldSweep);
#ifdef DEBUG
if (rt->gcIncrementalState == NO_INCREMENTAL) {
for (CompartmentsIter c(rt); !c.done(); c.next())
JS_ASSERT(!c->needsBarrier());
}
#endif
if (shouldSweep)
SweepPhase(rt, gckind, &startBackgroundSweep);
IncrementalCollectSlice(rt, budget, reason, gckind);
}
if (startBackgroundSweep)
rt->gcHelperThread.startBackgroundSweep(gckind == GC_SHRINK);
}
#ifdef JS_GC_ZEAL
@ -4270,20 +4475,34 @@ RunDebugGC(JSContext *cx)
type == ZealIncrementalMarkAllThenFinish ||
type == ZealIncrementalMultipleSlices)
{
js::gc::State initialState = rt->gcIncrementalState;
int64_t budget;
if (type == ZealIncrementalMultipleSlices) {
// Start with a small slice limit and double it every slice. This ensure that we get
// multiple slices, and collection runs to completion.
if (rt->gcIncrementalState == NO_INCREMENTAL)
/*
* Start with a small slice limit and double it every slice. This
* ensure that we get multiple slices, and collection runs to
* completion.
*/
if (initialState == NO_INCREMENTAL)
rt->gcIncrementalLimit = rt->gcZealFrequency / 2;
else
rt->gcIncrementalLimit *= 2;
budget = SliceBudget::WorkBudget(rt->gcIncrementalLimit);
} else {
// This triggers incremental GC but is actually ignored by IncrementalMarkSlice.
budget = SliceBudget::Unlimited;
}
Collect(rt, true, budget, GC_NORMAL, gcreason::DEBUG_GC);
/*
* For multi-slice zeal, reset the slice size when we get to the sweep
* phase.
*/
if (type == ZealIncrementalMultipleSlices &&
initialState == MARK && rt->gcIncrementalState == SWEEP)
{
rt->gcIncrementalLimit = rt->gcZealFrequency / 2;
}
} else {
Collect(rt, false, SliceBudget::Unlimited, GC_NORMAL, gcreason::DEBUG_GC);
}

View File

@ -41,6 +41,7 @@ namespace js {
class GCHelperThread;
struct Shape;
struct SliceBudget;
namespace gc {
@ -48,6 +49,7 @@ enum State {
NO_INCREMENTAL,
MARK_ROOTS,
MARK,
SWEEP,
INVALID
};
@ -146,33 +148,35 @@ IsNurseryAllocable(AllocKind kind)
inline JSGCTraceKind
GetGCThingTraceKind(const void *thing);
/*
* ArenaList::head points to the start of the list. Normally cursor points
* to the first arena in the list with some free things and all arenas
* before cursor are fully allocated. However, as the arena currently being
* allocated from is considered full while its list of free spans is moved
* into the freeList, during the GC or cell enumeration, when an
* unallocated freeList is moved back to the arena, we can see an arena
* with some free cells before the cursor. The cursor is an indirect
* pointer to allow for efficient list insertion at the cursor point and
* other list manipulations.
*/
struct ArenaList {
ArenaHeader *head;
ArenaHeader **cursor;
ArenaList() {
clear();
}
void clear() {
head = NULL;
cursor = &head;
}
void insert(ArenaHeader *arena);
};
struct ArenaLists {
/*
* ArenaList::head points to the start of the list. Normally cursor points
* to the first arena in the list with some free things and all arenas
* before cursor are fully allocated. However, as the arena currently being
* allocated from is considered full while its list of free spans is moved
* into the freeList, during the GC or cell enumeration, when an
* unallocated freeList is moved back to the arena, we can see an arena
* with some free cells before the cursor. The cursor is an indirect
* pointer to allow for efficient list insertion at the cursor point and
* other list manipulations.
*/
struct ArenaList {
ArenaHeader *head;
ArenaHeader **cursor;
ArenaList() {
clear();
}
void clear() {
head = NULL;
cursor = &head;
}
};
private:
/*
* For each arena kind its free list is represented as the first span with
@ -211,12 +215,18 @@ struct ArenaLists {
volatile uintptr_t backgroundFinalizeState[FINALIZE_LIMIT];
public:
/* For each arena kind, a list of arenas remaining to be swept. */
ArenaHeader *arenaListsToSweep[FINALIZE_LIMIT];
public:
ArenaLists() {
for (size_t i = 0; i != FINALIZE_LIMIT; ++i)
freeLists[i].initAsEmpty();
for (size_t i = 0; i != FINALIZE_LIMIT; ++i)
backgroundFinalizeState[i] = BFS_DONE;
for (size_t i = 0; i != FINALIZE_LIMIT; ++i)
arenaListsToSweep[i] = NULL;
}
~ArenaLists() {
@ -256,6 +266,10 @@ struct ArenaLists {
return true;
}
bool arenasAreFull(AllocKind thingKind) const {
return !*arenaLists[thingKind].cursor;
}
void unmarkAll() {
for (size_t i = 0; i != FINALIZE_LIMIT; ++i) {
/* The background finalization must have stopped at this point. */
@ -364,16 +378,18 @@ struct ArenaLists {
JS_ASSERT(freeLists[kind].isEmpty());
}
void finalizeObjects(FreeOp *fop);
void finalizeStrings(FreeOp *fop);
void finalizeShapes(FreeOp *fop);
void finalizeScripts(FreeOp *fop);
void queueObjectsForSweep(FreeOp *fop);
void queueStringsForSweep(FreeOp *fop);
void queueShapesForSweep(FreeOp *fop);
void queueScriptsForSweep(FreeOp *fop);
bool foregroundFinalize(FreeOp *fop, AllocKind thingKind, SliceBudget &sliceBudget);
static void backgroundFinalize(FreeOp *fop, ArenaHeader *listHead);
private:
inline void finalizeNow(FreeOp *fop, AllocKind thingKind);
inline void finalizeLater(FreeOp *fop, AllocKind thingKind);
inline void queueForForegroundSweep(FreeOp *fop, AllocKind thingKind);
inline void queueForBackgroundSweep(FreeOp *fop, AllocKind thingKind);
inline void *allocateFromArena(JSCompartment *comp, AllocKind thingKind);
};

View File

@ -418,7 +418,7 @@ NewGCThing(JSContext *cx, js::gc::AllocKind kind, size_t thingSize)
if (!t)
t = js::gc::ArenaLists::refillFreeList(cx, kind);
JS_ASSERT_IF(t && comp->needsBarrier(),
JS_ASSERT_IF(t && comp->wasGCStarted() && comp->needsBarrier(),
static_cast<T *>(t)->arenaHeader()->allocatedDuringIncremental);
#if defined(JSGC_GENERATIONAL) && defined(JS_GC_ZEAL)
@ -445,7 +445,7 @@ TryNewGCThing(JSContext *cx, js::gc::AllocKind kind, size_t thingSize)
#endif
void *t = cx->compartment->arenas.allocateFromFreeList(kind, thingSize);
JS_ASSERT_IF(t && cx->compartment->needsBarrier(),
JS_ASSERT_IF(t && cx->compartment->wasGCStarted() && cx->compartment->needsBarrier(),
static_cast<T *>(t)->arenaHeader()->allocatedDuringIncremental);
#if defined(JSGC_GENERATIONAL) && defined(JS_GC_ZEAL)

View File

@ -102,12 +102,14 @@ void
Shape::removeChild(Shape *child)
{
JS_ASSERT(!child->inDictionary());
JS_ASSERT(child->parent == this);
KidsPointer *kidp = &kids;
if (kidp->isShape()) {
JS_ASSERT(kidp->toShape() == child);
kidp->setNull();
child->parent = NULL;
return;
}
@ -115,6 +117,7 @@ Shape::removeChild(Shape *child)
JS_ASSERT(hash->count() >= 2); /* otherwise kidp->isShape() should be true */
hash->remove(child);
child->parent = NULL;
if (hash->count() == 1) {
/* Convert from HASH form back to SHAPE form. */
@ -126,27 +129,10 @@ Shape::removeChild(Shape *child)
}
}
/*
* We need a read barrier for the shape tree, since these are weak pointers.
*/
static Shape *
ReadBarrier(Shape *shape)
{
#ifdef JSGC_INCREMENTAL
JSCompartment *comp = shape->compartment();
if (comp->needsBarrier()) {
Shape *tmp = shape;
MarkShapeUnbarriered(comp->barrierTracer(), &tmp, "read barrier");
JS_ASSERT(tmp == shape);
}
#endif
return shape;
}
Shape *
PropertyTree::getChild(JSContext *cx, Shape *parent_, uint32_t nfixed, const StackShape &child)
{
Shape *shape;
Shape *shape = NULL;
JS_ASSERT(parent_);
@ -160,17 +146,43 @@ PropertyTree::getChild(JSContext *cx, Shape *parent_, uint32_t nfixed, const Sta
*/
KidsPointer *kidp = &parent_->kids;
if (kidp->isShape()) {
shape = kidp->toShape();
if (shape->matches(child))
return ReadBarrier(shape);
Shape *kid = kidp->toShape();
if (kid->matches(child))
shape = kid;
} else if (kidp->isHash()) {
shape = *kidp->toHash()->lookup(child);
if (shape)
return ReadBarrier(shape);
} else {
/* If kidp->isNull(), we always insert. */
}
#ifdef JSGC_INCREMENTAL
if (shape) {
JSCompartment *comp = shape->compartment();
if (comp->needsBarrier()) {
/*
* We need a read barrier for the shape tree, since these are weak
* pointers.
*/
Shape *tmp = shape;
MarkShapeUnbarriered(comp->barrierTracer(), &tmp, "read barrier");
JS_ASSERT(tmp == shape);
} else if (comp->isGCSweeping() && !shape->isMarked() &&
!shape->arenaHeader()->allocatedDuringIncremental)
{
/*
* The shape we've found is unreachable and due to be finalized, so
* remove our weak reference to it and don't use it.
*/
JS_ASSERT(parent_->isMarked());
parent_->removeChild(shape);
shape = NULL;
}
}
#endif
if (shape)
return shape;
StackShape::AutoRooter childRoot(cx, &child);
RootedShape parent(cx, parent_);
@ -190,6 +202,11 @@ void
Shape::finalize(FreeOp *fop)
{
if (!inDictionary()) {
/*
* Note that due to incremental sweeping, if !parent->isMarked() then
* the parent may point to a new shape allocated in the same cell that
* use to hold our parent.
*/
if (parent && parent->isMarked())
parent->removeChild(this);

View File

@ -1201,7 +1201,7 @@ ScriptSource::createFromSource(JSContext *cx, const jschar *src, uint32_t length
* accessed even if the name was already in the table. At this point old
* scripts pointing to the source may no longer be reachable.
*/
if (cx->runtime->gcIncrementalState == MARK && cx->runtime->gcIsFull)
if (cx->runtime->gcIncrementalState != NO_INCREMENTAL && cx->runtime->gcIsFull)
ss->marked = true;
#endif
@ -1341,7 +1341,7 @@ ScriptSource::performXDR(XDRState<mode> *xdr, ScriptSource **ssp)
cleanup.protect(ss);
#ifdef JSGC_INCREMENTAL
// See comment in ScriptSource::createFromSource.
if (xdr->cx()->runtime->gcIncrementalState == MARK &&
if (xdr->cx()->runtime->gcIncrementalState != NO_INCREMENTAL &&
xdr->cx()->runtime->gcIsFull)
ss->marked = true;
#endif
@ -1409,7 +1409,7 @@ js::SaveScriptFilename(JSContext *cx, const char *filename)
* scripts or exceptions pointing to the filename may no longer be
* reachable.
*/
if (rt->gcIncrementalState == MARK && rt->gcIsFull)
if (rt->gcIncrementalState != NO_INCREMENTAL && rt->gcIsFull)
sfe->marked = true;
#endif

View File

@ -2088,7 +2088,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
bool isPositioned = !isSVG && disp->IsPositioned();
if (isVisuallyAtomic || isPositioned || (!isSVG && disp->IsFloating()) ||
((disp->mClipFlags & NS_STYLE_CLIP_RECT) &&
IsSVGContentWithCSSClip(this)) ||
IsSVGContentWithCSSClip(child)) ||
(aFlags & DISPLAY_CHILD_FORCE_STACKING_CONTEXT)) {
// If you change this, also change IsPseudoStackingContextFromStyle()
pseudoStackingContext = true;

View File

@ -39,27 +39,6 @@ static double FlushToZero(double aVal)
return aVal;
}
/* Helper function to fill in an nscoord with the specified nsCSSValue. */
static nscoord CalcLength(const nsCSSValue &aValue,
nsStyleContext* aContext,
nsPresContext* aPresContext,
bool &aCanStoreInRuleTree)
{
if (aValue.GetUnit() == eCSSUnit_Pixel ||
aValue.GetUnit() == eCSSUnit_Number) {
// Handle this here (even though nsRuleNode::CalcLength handles it
// fine) so that callers are allowed to pass a null style context
// and pres context to SetToTransformFunction if they know (as
// nsStyleAnimation does) that all lengths within the transform
// function have already been computed to pixels and percents.
//
// Raw numbers are treated as being pixels.
return nsPresContext::CSSPixelsToAppUnits(aValue.GetFloatValue());
}
return nsRuleNode::CalcLength(aValue, aContext, aPresContext,
aCanStoreInRuleTree);
}
static float
ProcessTranslatePart(const nsCSSValue& aValue,
nsStyleContext* aContext,
@ -72,6 +51,19 @@ ProcessTranslatePart(const nsCSSValue& aValue,
if (aValue.GetUnit() == eCSSUnit_Percent) {
percent = aValue.GetPercentValue();
} else if (aValue.GetUnit() == eCSSUnit_Pixel ||
aValue.GetUnit() == eCSSUnit_Number) {
// Handle this here (even though nsRuleNode::CalcLength handles it
// fine) so that callers are allowed to pass a null style context
// and pres context to SetToTransformFunction if they know (as
// nsStyleAnimation does) that all lengths within the transform
// function have already been computed to pixels and percents.
//
// Raw numbers are treated as being pixels.
//
// Don't convert to aValue to AppUnits here to avoid precision issues.
return aValue.GetFloatValue() *
(float(nsPresContext::AppUnitsPerCSSPixel()) / aAppUnitsPerMatrixUnit);
} else if (aValue.IsCalcUnit()) {
nsRuleNode::ComputedCalc result =
nsRuleNode::SpecifiedCalcToComputedCalc(aValue, aContext, aPresContext,
@ -79,8 +71,8 @@ ProcessTranslatePart(const nsCSSValue& aValue,
percent = result.mPercent;
offset = result.mLength;
} else {
offset = CalcLength(aValue, aContext, aPresContext,
aCanStoreInRuleTree);
offset = nsRuleNode::CalcLength(aValue, aContext, aPresContext,
aCanStoreInRuleTree);
}
return (percent * NSAppUnitsToFloatPixels(aSize, aAppUnitsPerMatrixUnit)) +

View File

@ -685,3 +685,6 @@ pref("reader.margin_size", 5);
// The default color scheme in reader (light, dark, sepia)
pref("reader.color_scheme", "light");
// Used to show a first-launch tip in reader
pref("reader.has_used_toolbar", false);

View File

@ -16,10 +16,6 @@ DIST_FILES = package-name.txt
include $(topsrcdir)/mobile/android/base/android-sync-files.mk
#These SYNC_ variables could be moved to android-sync/fennec-copy-code.sh
SYNC_RES_XML=res/xml/sync_authenticator.xml
SYNC_PP_RES_XML=res/xml/sync_syncadapter.xml res/xml/sync_options.xml
FENNEC_JAVA_FILES = \
AboutHomeContent.java \
AboutHomeSection.java \
@ -241,6 +237,9 @@ GARBAGE += \
GARBAGE_DIRS += classes res sync db
MOZ_ANDROID_SHARED_ID = "$(ANDROID_PACKAGE_NAME).sharedID"
MOZ_ANDROID_SHARED_ACCOUNT_TYPE = "$(ANDROID_PACKAGE_NAME)_sync"
# Bug 567884 - Need a way to find appropriate icons during packaging
ifeq ($(MOZ_APP_NAME),fennec)
ICON_PATH = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/fennec_48x48.png
@ -248,19 +247,29 @@ ICON_PATH_HDPI = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/fennec_72x72.png
# we released these builds to the public with shared IDs and need to keep them
ifeq (org.mozilla.firefox,$(ANDROID_PACKAGE_NAME))
DEFINES += -DMOZ_ANDROID_SHARED_ID="org.mozilla.firefox.sharedID"
MOZ_ANDROID_SHARED_ID = "org.mozilla.firefox.sharedID"
MOZ_ANDROID_SHARED_ACCOUNT_TYPE = "org.mozilla.firefox_sync"
else ifeq (org.mozilla.firefox_beta,$(ANDROID_PACKAGE_NAME))
DEFINES += -DMOZ_ANDROID_SHARED_ID="org.mozilla.firefox.sharedID"
MOZ_ANDROID_SHARED_ID = "org.mozilla.firefox.sharedID"
MOZ_ANDROID_SHARED_ACCOUNT_TYPE = "org.mozilla.firefox_sync"
else ifeq (org.mozilla.fennec_aurora,$(ANDROID_PACKAGE_NAME))
DEFINES += -DMOZ_ANDROID_SHARED_ID="org.mozilla.fennec.sharedID"
MOZ_ANDROID_SHARED_ID = "org.mozilla.fennec.sharedID"
MOZ_ANDROID_SHARED_ACCOUNT_TYPE = "org.mozilla.fennec_sync"
else ifeq (org.mozilla.fennec,$(ANDROID_PACKAGE_NAME))
DEFINES += -DMOZ_ANDROID_SHARED_ID="org.mozilla.fennec.sharedID"
MOZ_ANDROID_SHARED_ID = "org.mozilla.fennec.sharedID"
MOZ_ANDROID_SHARED_ACCOUNT_TYPE = "org.mozilla.fennec_sync"
endif
else
ICON_PATH = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/icon48.png
ICON_PATH_HDPI = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/icon64.png
DEFINES += -DMOZ_ANDROID_SHARED_ID="$(ANDROID_PACKAGE_NAME).sharedID"
endif
ifdef MOZ_ANDROID_SHARED_ID
DEFINES += -DMOZ_ANDROID_SHARED_ID="$(MOZ_ANDROID_SHARED_ID)"
endif
ifdef MOZ_ANDROID_SHARED_ACCOUNT_TYPE
DEFINES += -DMOZ_ANDROID_SHARED_ACCOUNT_TYPE="$(MOZ_ANDROID_SHARED_ACCOUNT_TYPE)"
endif
RES_LAYOUT = \
@ -1089,10 +1098,10 @@ $(RESOURCES): $(RES_DIRS) $(subst res/,$(srcdir)/resources/,$(RESOURCES))
$(NSINSTALL) $(subst res/,$(srcdir)/resources/,$@) $(dir $@)
R.java: $(MOZ_APP_ICON) $(RESOURCES) $(RES_DRAWABLE) $(RES_DRAWABLE_LDPI) $(RES_DRAWABLE_MDPI) $(RES_DRAWABLE_HDPI) $(PP_RES_XML) res/values/defaults.xml res/drawable/sync_ic_launcher.png res/drawable/icon.png res/drawable-hdpi/icon.png res/values/strings.xml AndroidManifest.xml FORCE
R.java: $(MOZ_APP_ICON) $(RESOURCES) $(RES_DRAWABLE) $(RES_DRAWABLE_LDPI) $(RES_DRAWABLE_MDPI) $(RES_DRAWABLE_HDPI) $(PP_RES_XML) res/values/defaults.xml res/drawable/icon.png res/drawable-hdpi/icon.png res/values/strings.xml AndroidManifest.xml FORCE
$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -S res -J . --custom-package org.mozilla.gecko
gecko.ap_: AndroidManifest.xml res/drawable/sync_ic_launcher.png res/drawable/icon.png res/drawable-hdpi/icon.png $(RESOURCES) $(RES_DRAWABLE) $(RES_DRAWABLE_LDPI) $(RES_DRAWABLE_MDPI) $(RES_DRAWABLE_HDPI) $(PP_RES_XML) res/values/defaults.xml res/values/strings.xml FORCE
gecko.ap_: AndroidManifest.xml res/drawable/icon.png res/drawable-hdpi/icon.png $(RESOURCES) $(RES_DRAWABLE) $(RES_DRAWABLE_LDPI) $(RES_DRAWABLE_MDPI) $(RES_DRAWABLE_HDPI) $(PP_RES_XML) res/values/defaults.xml res/values/strings.xml FORCE
$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -S res -F $@
libs:: classes.dex package-name.txt

View File

@ -23,9 +23,6 @@ class SyncPreference extends Preference {
@Override
protected void onClick() {
// Make sure we use the same account type as our bundled version of Sync!
final String accountType = org.mozilla.gecko.sync.setup.Constants.ACCOUNTTYPE_SYNC;
// Show Sync setup if no accounts exist; otherwise, show account settings.
if (SyncAccounts.syncAccountsExist(mContext)) {
SyncAccounts.openSyncSettings(mContext);

View File

@ -6,14 +6,21 @@ package org.mozilla.gecko;
import android.util.Log;
import android.view.View;
import org.mozilla.gecko.gfx.Layer;
import org.mozilla.gecko.gfx.Layer.RenderContext;
import org.mozilla.gecko.gfx.LayerController;
import org.json.JSONObject;
class TextSelection implements GeckoEventListener {
class TextSelection extends Layer implements GeckoEventListener {
private static final String LOGTAG = "GeckoTextSelection";
private final TextSelectionHandle mStartHandle;
private final TextSelectionHandle mEndHandle;
private float mViewLeft;
private float mViewTop;
private float mViewZoom;
TextSelection(TextSelectionHandle startHandle, TextSelectionHandle endHandle) {
mStartHandle = startHandle;
mEndHandle = endHandle;
@ -41,11 +48,24 @@ class TextSelection implements GeckoEventListener {
public void run() {
mStartHandle.setVisibility(View.VISIBLE);
mEndHandle.setVisibility(View.VISIBLE);
mViewLeft = 0.0f;
mViewTop = 0.0f;
mViewZoom = 0.0f;
LayerController layerController = GeckoApp.mAppContext.getLayerController();
if (layerController != null) {
layerController.getView().addLayer(TextSelection.this);
}
}
});
} else if (event.equals("TextSelection:HideHandles")) {
GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
public void run() {
LayerController layerController = GeckoApp.mAppContext.getLayerController();
if (layerController != null) {
layerController.getView().removeLayer(TextSelection.this);
}
mStartHandle.setVisibility(View.GONE);
mEndHandle.setVisibility(View.GONE);
}
@ -67,4 +87,26 @@ class TextSelection implements GeckoEventListener {
Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
}
}
@Override
public void draw(final RenderContext context) {
// cache the relevant values from the context and bail out if they are the same. we do this
// because this draw function gets called a lot (once per compositor frame) and we want to
// avoid doing a lot of extra work in cases where it's not needed.
if (FloatUtils.fuzzyEquals(mViewLeft, context.viewport.left)
&& FloatUtils.fuzzyEquals(mViewTop, context.viewport.top)
&& FloatUtils.fuzzyEquals(mViewZoom, context.zoomFactor)) {
return;
}
mViewLeft = context.viewport.left;
mViewTop = context.viewport.top;
mViewZoom = context.zoomFactor;
GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
public void run() {
mStartHandle.repositionWithViewport(context.viewport.left, context.viewport.top, context.zoomFactor);
mEndHandle.repositionWithViewport(context.viewport.left, context.viewport.top, context.zoomFactor);
}
});
}
}

View File

@ -13,6 +13,7 @@ import android.view.MotionEvent;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.ImageView;
import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
import org.mozilla.gecko.gfx.LayerController;
import org.json.JSONObject;
@ -28,6 +29,7 @@ class TextSelectionHandle extends ImageView implements View.OnTouchListener {
private int mLeft;
private int mTop;
private PointF mGeckoPoint;
private int mTouchStartX;
private int mTouchStartY;
@ -108,11 +110,18 @@ class TextSelectionHandle extends ImageView implements View.OnTouchListener {
Log.e(LOGTAG, "Can't position handle because layerController is null");
return;
}
PointF geckoPoint = new PointF((float) left, (float) top);
geckoPoint = layerController.convertLayerPointToViewPoint(geckoPoint);
mLeft = Math.round(geckoPoint.x) - (mHandleType.equals(HandleType.START) ? mWidth - mShadow : mShadow);
mTop = Math.round(geckoPoint.y);
mGeckoPoint = new PointF((float) left, (float) top);
ImmutableViewportMetrics metrics = layerController.getViewportMetrics();
repositionWithViewport(metrics.viewportRectLeft, metrics.viewportRectTop, metrics.zoomFactor);
}
void repositionWithViewport(float x, float y, float zoom) {
PointF viewPoint = new PointF((mGeckoPoint.x * zoom) - x,
(mGeckoPoint.y * zoom) - y);
mLeft = Math.round(viewPoint.x) - (mHandleType.equals(HandleType.START) ? mWidth - mShadow : mShadow);
mTop = Math.round(viewPoint.y);
setLayoutPosition();
}

File diff suppressed because one or more lines are too long

View File

@ -300,28 +300,6 @@ public class LayerController {
return layerPoint;
}
/**
* Does the opposite of convertViewPointToLayerPoint.
*/
public PointF convertLayerPointToViewPoint(PointF layerPoint) {
if (mLayerClient == null) {
return null;
}
ImmutableViewportMetrics viewportMetrics = mViewportMetrics;
PointF origin = viewportMetrics.getOrigin();
float zoom = viewportMetrics.zoomFactor;
ViewportMetrics geckoViewport = mLayerClient.getGeckoViewportMetrics();
PointF geckoOrigin = geckoViewport.getOrigin();
float geckoZoom = geckoViewport.getZoomFactor();
PointF viewPoint = new PointF(
((layerPoint.x + (geckoOrigin.x / geckoZoom)) * zoom - origin.x),
((layerPoint.y + (geckoOrigin.y / geckoZoom)) * zoom - origin.y));
return viewPoint;
}
/** Retrieves whether we should show checkerboard checks or not. */
public boolean checkerboardShouldShowChecks() {
return mCheckerboardShouldShowChecks;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

View File

@ -5,17 +5,10 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/SyncLayout" >
<LinearLayout
android:id="@+id/account_top"
style="@style/SyncTop">
<ImageView
style="@style/SyncTopIcon" />
<TextView
style="@style/SyncTextTitle"
<TextView
style="@style/SyncTop"
android:id="@+id/account_top"
android:text="@string/sync_title_connect" />
</LinearLayout>
<ScrollView
android:id="@+id/account_content"
style="@style/SyncLayout"

View File

@ -1,15 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/SyncLayout" >
<LinearLayout
android:id="@+id/redirect_top"
style="@style/SyncTop">
<ImageView
style="@style/SyncTopIcon" />
<TextView
style="@style/SyncTextTitle"
<TextView
style="@style/SyncTop"
android:id="@+id/redirect_top"
android:text="@string/sync_title_redirect_to_set_up_sync" />
</LinearLayout>
<TextView
style="@style/SyncTextItem"
android:layout_below="@id/redirect_top"
@ -22,15 +17,11 @@
android:orientation="horizontal" >
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
style="@style/SyncButton"
android:onClick="redirectToSetupHandler"
android:text="@string/sync_button_set_up_sync" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
<Button
style="@style/SyncButton"
android:onClick="cancelClickHandler"
android:text="@string/sync_button_cancel" />
</LinearLayout>

View File

@ -1,15 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/SyncLayout.Vertical" >
<LinearLayout
android:id="@+id/sendtab_top"
style="@style/SyncTop" >
<ImageView
style="@style/SyncTopIcon" />
<TextView
style="@style/SyncTextTitle"
<TextView
style="@style/SyncTop"
android:id="@+id/sendtab_top"
android:text="@string/sync_title_send_tab" />
</LinearLayout>
<ListView
android:id="@+id/device_list"

View File

@ -6,16 +6,10 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/SyncLayout" >
<LinearLayout
android:id="@+id/setup_top"
style="@style/SyncTop" >
<ImageView
style="@style/SyncTopIcon" />
<TextView
android:id="@+id/setup_title"
style="@style/SyncTextTitle"
<TextView
style="@style/SyncTop"
android:id="@+id/setup_top"
android:text="@string/sync_title_connect" />
</LinearLayout>
<ScrollView
style="@style/SyncLayout"
@ -25,7 +19,7 @@
<LinearLayout
style="@style/SyncLayout.Vertical"
android:layout_height="fill_parent"
android:layout_height="wrap_content"
android:padding="15dp" >
<TextView

View File

@ -5,15 +5,10 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/SyncLayout" >
<LinearLayout
android:id="@+id/failure_top"
style="@style/SyncTop" >
<ImageView
style="@style/SyncTopIcon" />
<TextView
style="@style/SyncTextTitle"
android:text="@string/sync_title_fail" />
</LinearLayout>
style="@style/SyncTop"
android:id="@+id/failure_top"
android:text="@string/sync_title_fail" />
<TextView
android:id="@+id/failure_subtitle1"

View File

@ -5,15 +5,10 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/SyncLayout" >
<LinearLayout
android:id="@+id/waiting_top"
style="@style/SyncTop" >
<ImageView
style="@style/SyncTopIcon" />
<TextView
style="@style/SyncTextTitle"
style="@style/SyncTop"
android:id="@+id/waiting_top"
android:text="@string/sync_title_connect" />
</LinearLayout>
<ProgressBar
android:id="@+id/waiting_content1"

View File

@ -5,21 +5,18 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/SyncLayout" >
<LinearLayout
<TextView
style="@style/SyncTop"
android:id="@+id/internet_top"
style="@style/SyncTop">
<ImageView
style="@style/SyncTopIcon" />
<TextView
style="@style/SyncTextTitle"
android:text="@string/sync_title_fail" />
</LinearLayout>
android:text="@string/sync_title_fail" />
<TextView
style="@style/SyncTextItem"
android:layout_below="@id/internet_top"
android:layout_marginTop="20dp"
android:gravity="center"
android:text="@string/sync_subtitle_nointernet" />
<LinearLayout
style="@style/SyncBottom" >
<Button

View File

@ -5,16 +5,11 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/SyncLayout" >
<LinearLayout
<TextView
style="@style/SyncTop"
android:id="@+id/pair_top"
style="@style/SyncTop" >
<ImageView
style="@style/SyncTopIcon" />
<TextView
android:id="@+id/setup_title"
style="@style/SyncTextTitle"
android:text="@string/sync_title_pair" />
</LinearLayout>
android:text="@string/sync_title_pair" />
<ScrollView
style="@style/SyncLayout"
android:layout_below="@id/pair_top"

View File

@ -6,22 +6,18 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/SyncLayout" >
<LinearLayout
<TextView
style="@style/SyncTop"
android:id="@+id/success_top"
style="@style/SyncTop" >
<ImageView
style="@style/SyncTopIcon"/>
<TextView
style="@style/SyncTextTitle"
android:text="@string/sync_title_success" />
</LinearLayout>
android:text="@string/sync_title_success" />
<TextView
android:id="@+id/setup_success_subtitle"
style="@style/SyncTextItem"
android:gravity="left"
style="@style/SyncTextItem"
android:gravity="left"
android:padding="20dp"
android:layout_below="@id/success_top"
android:text="@string/sync_subtitle_success" />
android:text="@string/sync_subtitle_success" />
<LinearLayout
style="@style/SyncBottom"

View File

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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/. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello… is it me you're looking for?" />
</LinearLayout>

View File

@ -61,15 +61,20 @@
<!-- Theme Styles -->
<style name="SyncTheme" parent="@android:style/Theme.NoTitleBar"/>
<!-- Top title bar: a text view with the Sync icon to the left. -->
<style name="SyncTop">
<item name="android:textAppearance">@android:style/TextAppearance.Large</item>
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:gravity">left</item>
<item name="android:orientation">horizontal</item>
<item name="android:gravity">center_vertical|left</item>
<item name="android:drawableLeft">@drawable/icon</item>
<item name="android:padding">4dp</item>
<item name="android:drawablePadding">4dp</item>
<item name="android:layout_alignParentTop">true</item>
<item name="android:background">@android:drawable/bottom_bar</item>
</style>
<style name="SyncBottom">
<!-- Bottom bar: a horizontal linear layout with buttons in it. -->
<style name="SyncBottom">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_gravity">center</item>
@ -95,11 +100,4 @@
<item name="android:textSize">35sp</item>
<item name="android:text">@string/sync_pin_default</item>
</style>
<style name="SyncTopIcon">
<item name="android:src">@drawable/sync_fx_icon</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:paddingTop">2dp</item>
<item name="android:paddingLeft">4dp</item>
</style>
</resources>

View File

@ -1,11 +1,12 @@
#filter substitution
<?xml version="1.0" encoding="utf-8"?>
<!-- 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/. -->
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="org.mozilla.firefox_sync"
android:icon="@drawable/sync_ic_launcher"
android:smallIcon="@drawable/sync_ic_launcher"
android:accountType="@MOZ_ANDROID_SHARED_ACCOUNT_TYPE@"
android:icon="@drawable/icon"
android:smallIcon="@drawable/icon"
android:label="@string/sync_account_label"
android:accountPreferences="@xml/sync_options" />

View File

@ -6,7 +6,7 @@
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
android:contentAuthority="@ANDROID_PACKAGE_NAME@.db.browser"
android:accountType="org.mozilla.firefox_sync"
android:accountType="@MOZ_ANDROID_SHARED_ACCOUNT_TYPE@"
android:supportsUploading="true"
android:userVisible="true"
/>

View File

@ -241,7 +241,7 @@ public class CommandProcessor {
final NotificationManager notificationManager = (NotificationManager) context.getSystemService(ns);
// Create a Notificiation.
final int icon = R.drawable.sync_ic_launcher;
final int icon = R.drawable.icon;
String notificationTitle = context.getString(R.string.sync_new_tab);
if (title != null) {
notificationTitle = notificationTitle.concat(": " + title);

View File

@ -16,4 +16,6 @@ public class GlobalConstants {
" (" + PRODUCT_NAME + ")";
public static final String BROWSER_INTENT_PACKAGE = "@ANDROID_PACKAGE_NAME@";
public static final String BROWSER_INTENT_CLASS = BROWSER_INTENT_PACKAGE + ".App";
public static final String ACCOUNTTYPE_SYNC = "@MOZ_ANDROID_SHARED_ACCOUNT_TYPE@";
}

View File

@ -41,7 +41,8 @@ public class Logger {
final Set<LogWriter> defaultLogWriters = new LinkedHashSet<LogWriter>();
LogWriter log = new AndroidLogWriter();
LogWriter cache = new AndroidLevelCachingLogWriter(log);
LogWriter single = new SingleTagLogWriter(GLOBAL_LOG_TAG, cache);
final String processedPackage = GlobalConstants.BROWSER_INTENT_PACKAGE.replace("org.mozilla.", "");
LogWriter single = new SingleTagLogWriter(processedPackage, new SingleTagLogWriter(GLOBAL_LOG_TAG, cache));
defaultLogWriters.add(single);
return defaultLogWriters;
}

View File

@ -4,8 +4,6 @@
package org.mozilla.gecko.sync;
import org.mozilla.gecko.R;
import android.app.Activity;
import android.os.Bundle;
@ -17,6 +15,5 @@ public class StubActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sync_stub);
}
}

View File

@ -8,7 +8,6 @@ import android.content.Intent;
public class Constants {
// Constants for Firefox Sync SyncAdapter Accounts.
public static final String ACCOUNTTYPE_SYNC = "org.mozilla.firefox_sync";
public static final String OPTION_SYNCKEY = "option.synckey";
public static final String OPTION_USERNAME = "option.username";
public static final String AUTHTOKEN_TYPE_PLAIN = "auth.plain";

View File

@ -8,6 +8,7 @@ import java.io.File;
import org.mozilla.gecko.db.BrowserContract;
import org.mozilla.gecko.sync.ExtendedJSONObject;
import org.mozilla.gecko.sync.GlobalConstants;
import org.mozilla.gecko.sync.Logger;
import org.mozilla.gecko.sync.SyncConfiguration;
import org.mozilla.gecko.sync.Utils;
@ -50,7 +51,7 @@ public class SyncAccounts {
* Do not call this method from the main thread.
*/
public static boolean syncAccountsExist(Context c) {
final boolean accountsExist = AccountManager.get(c).getAccountsByType(Constants.ACCOUNTTYPE_SYNC).length > 0;
final boolean accountsExist = AccountManager.get(c).getAccountsByType(GlobalConstants.ACCOUNTTYPE_SYNC).length > 0;
if (accountsExist) {
return true;
}
@ -286,13 +287,13 @@ public class SyncAccounts {
Logger.info(LOG_TAG, "Setting explicit server URL: " + serverURL);
}
final Account account = new Account(username, Constants.ACCOUNTTYPE_SYNC);
final Account account = new Account(username, GlobalConstants.ACCOUNTTYPE_SYNC);
final Bundle userbundle = new Bundle();
// Add sync key and server URL.
userbundle.putString(Constants.OPTION_SYNCKEY, syncKey);
userbundle.putString(Constants.OPTION_SERVER, serverURL);
Logger.debug(LOG_TAG, "Adding account for " + Constants.ACCOUNTTYPE_SYNC);
Logger.debug(LOG_TAG, "Adding account for " + GlobalConstants.ACCOUNTTYPE_SYNC);
boolean result = false;
try {
result = accountManager.addAccountExplicitly(account, password, userbundle);

View File

@ -7,6 +7,7 @@ package org.mozilla.gecko.sync.setup;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import org.mozilla.gecko.sync.GlobalConstants;
import org.mozilla.gecko.sync.Logger;
import org.mozilla.gecko.sync.Utils;
import org.mozilla.gecko.sync.config.AccountPickler;
@ -63,7 +64,7 @@ public class SyncAuthenticatorService extends Service {
final Intent intent = new Intent(mContext, SetupSyncActivity.class);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
response);
intent.putExtra("accountType", Constants.ACCOUNTTYPE_SYNC);
intent.putExtra("accountType", GlobalConstants.ACCOUNTTYPE_SYNC);
intent.putExtra(Constants.INTENT_EXTRA_IS_SETUP, true);
final Bundle result = new Bundle();
@ -107,7 +108,7 @@ public class SyncAuthenticatorService extends Service {
final Bundle result = new Bundle();
// This is a Sync account.
result.putString(AccountManager.KEY_ACCOUNT_TYPE, Constants.ACCOUNTTYPE_SYNC);
result.putString(AccountManager.KEY_ACCOUNT_TYPE, GlobalConstants.ACCOUNTTYPE_SYNC);
// Server.
String serverURL = am.getUserData(account, Constants.OPTION_SERVER);

View File

@ -7,6 +7,7 @@ package org.mozilla.gecko.sync.setup.activities;
import java.util.Locale;
import org.mozilla.gecko.R;
import org.mozilla.gecko.sync.GlobalConstants;
import org.mozilla.gecko.sync.Logger;
import org.mozilla.gecko.sync.ThreadPool;
import org.mozilla.gecko.sync.setup.Constants;
@ -264,8 +265,8 @@ public class AccountActivity extends AccountAuthenticatorActivity {
Bundle resultBundle = new Bundle();
resultBundle.putString(AccountManager.KEY_ACCOUNT_NAME, syncAccount.username);
resultBundle.putString(AccountManager.KEY_ACCOUNT_TYPE, Constants.ACCOUNTTYPE_SYNC);
resultBundle.putString(AccountManager.KEY_AUTHTOKEN, Constants.ACCOUNTTYPE_SYNC);
resultBundle.putString(AccountManager.KEY_ACCOUNT_TYPE, GlobalConstants.ACCOUNTTYPE_SYNC);
resultBundle.putString(AccountManager.KEY_AUTHTOKEN, GlobalConstants.ACCOUNTTYPE_SYNC);
setAccountAuthenticatorResult(resultBundle);
setResult(RESULT_OK);

View File

@ -9,6 +9,7 @@ import java.util.List;
import org.mozilla.gecko.R;
import org.mozilla.gecko.sync.CommandProcessor;
import org.mozilla.gecko.sync.CommandRunner;
import org.mozilla.gecko.sync.GlobalConstants;
import org.mozilla.gecko.sync.GlobalSession;
import org.mozilla.gecko.sync.Logger;
import org.mozilla.gecko.sync.repositories.NullCursorException;
@ -87,7 +88,7 @@ public class SendTabActivity extends Activity {
private void redirectIfNoSyncAccount() {
accountManager = AccountManager.get(getApplicationContext());
Account[] accts = accountManager.getAccountsByType(Constants.ACCOUNTTYPE_SYNC);
Account[] accts = accountManager.getAccountsByType(GlobalConstants.ACCOUNTTYPE_SYNC);
// A Sync account exists.
if (accts.length > 0) {

View File

@ -8,6 +8,7 @@ import java.util.HashMap;
import org.json.simple.JSONObject;
import org.mozilla.gecko.R;
import org.mozilla.gecko.sync.GlobalConstants;
import org.mozilla.gecko.sync.Logger;
import org.mozilla.gecko.sync.ThreadPool;
import org.mozilla.gecko.sync.jpake.JPakeClient;
@ -50,9 +51,6 @@ public class SetupSyncActivity extends AccountAuthenticatorActivity {
private LinearLayout pinError;
// UI elements for pairing through PIN generation.
private TextView setupTitleView;
private TextView setupNoDeviceLinkTitleView;
private TextView setupSubtitleView;
private TextView pinTextView1;
private TextView pinTextView2;
private TextView pinTextView3;
@ -102,7 +100,7 @@ public class SetupSyncActivity extends AccountAuthenticatorActivity {
ThreadPool.run(new Runnable() {
@Override
public void run() {
Account[] accts = mAccountManager.getAccountsByType(Constants.ACCOUNTTYPE_SYNC);
Account[] accts = mAccountManager.getAccountsByType(GlobalConstants.ACCOUNTTYPE_SYNC);
finishResume(accts);
}
});
@ -340,7 +338,7 @@ public class SetupSyncActivity extends AccountAuthenticatorActivity {
*/
public void onPaired() {
// Extract Sync account data.
Account[] accts = mAccountManager.getAccountsByType(Constants.ACCOUNTTYPE_SYNC);
Account[] accts = mAccountManager.getAccountsByType(GlobalConstants.ACCOUNTTYPE_SYNC);
if (accts.length == 0) {
// Error, no account present.
Logger.error(LOG_TAG, "No accounts present.");
@ -424,8 +422,8 @@ public class SetupSyncActivity extends AccountAuthenticatorActivity {
if (isSuccess) {
Bundle resultBundle = new Bundle();
resultBundle.putString(AccountManager.KEY_ACCOUNT_NAME, syncAccount.username);
resultBundle.putString(AccountManager.KEY_ACCOUNT_TYPE, Constants.ACCOUNTTYPE_SYNC);
resultBundle.putString(AccountManager.KEY_AUTHTOKEN, Constants.ACCOUNTTYPE_SYNC);
resultBundle.putString(AccountManager.KEY_ACCOUNT_TYPE, GlobalConstants.ACCOUNTTYPE_SYNC);
resultBundle.putString(AccountManager.KEY_AUTHTOKEN, GlobalConstants.ACCOUNTTYPE_SYNC);
setAccountAuthenticatorResult(resultBundle);
}
displayResultAndFinish(isSuccess);
@ -590,23 +588,9 @@ public class SetupSyncActivity extends AccountAuthenticatorActivity {
setContentView(R.layout.sync_setup);
// Set up UI.
setupTitleView = ((TextView) findViewById(R.id.setup_title));
setupSubtitleView = (TextView) findViewById(R.id.setup_subtitle);
setupNoDeviceLinkTitleView = (TextView) findViewById(R.id.link_nodevice);
pinTextView1 = ((TextView) findViewById(R.id.text_pin1));
pinTextView2 = ((TextView) findViewById(R.id.text_pin2));
pinTextView3 = ((TextView) findViewById(R.id.text_pin3));
// UI checks.
if (setupTitleView == null) {
Logger.error(LOG_TAG, "No title view.");
}
if (setupSubtitleView == null) {
Logger.error(LOG_TAG, "No subtitle view.");
}
if (setupNoDeviceLinkTitleView == null) {
Logger.error(LOG_TAG, "No 'no device' link view.");
}
}
});
}

View File

@ -49,7 +49,6 @@ import android.database.sqlite.SQLiteConstraintException;
import android.database.sqlite.SQLiteException;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
public class SyncAdapter extends AbstractThreadedSyncAdapter implements GlobalSessionCallback, ClientsDataDelegate {
private static final String LOG_TAG = "SyncAdapter";
@ -126,32 +125,32 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter implements GlobalSe
setShouldInvalidateAuthToken();
try {
if (e instanceof SQLiteConstraintException) {
Log.e(LOG_TAG, "Constraint exception. Aborting sync.", e);
Logger.error(LOG_TAG, "Constraint exception. Aborting sync.", e);
syncResult.stats.numParseExceptions++; // This is as good as we can do.
return;
}
if (e instanceof SQLiteException) {
Log.e(LOG_TAG, "Couldn't open database (locked?). Aborting sync.", e);
Logger.error(LOG_TAG, "Couldn't open database (locked?). Aborting sync.", e);
syncResult.stats.numIoExceptions++;
return;
}
if (e instanceof OperationCanceledException) {
Log.e(LOG_TAG, "Operation canceled. Aborting sync.", e);
Logger.error(LOG_TAG, "Operation canceled. Aborting sync.", e);
return;
}
if (e instanceof AuthenticatorException) {
syncResult.stats.numParseExceptions++;
Log.e(LOG_TAG, "AuthenticatorException. Aborting sync.", e);
Logger.error(LOG_TAG, "AuthenticatorException. Aborting sync.", e);
return;
}
if (e instanceof IOException) {
syncResult.stats.numIoExceptions++;
Log.e(LOG_TAG, "IOException. Aborting sync.", e);
Logger.error(LOG_TAG, "IOException. Aborting sync.", e);
e.printStackTrace();
return;
}
syncResult.stats.numIoExceptions++;
Log.e(LOG_TAG, "Unknown exception. Aborting sync.", e);
Logger.error(LOG_TAG, "Unknown exception. Aborting sync.", e);
} finally {
notifyMonitor();
}
@ -168,7 +167,7 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter implements GlobalSe
String token;
try {
token = future.getResult().getString(AccountManager.KEY_AUTHTOKEN);
mAccountManager.invalidateAuthToken(Constants.ACCOUNTTYPE_SYNC, token);
mAccountManager.invalidateAuthToken(GlobalConstants.ACCOUNTTYPE_SYNC, token);
} catch (Exception e) {
Logger.error(LOG_TAG, "Couldn't invalidate auth token: " + e);
}
@ -263,7 +262,7 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter implements GlobalSe
this.syncResult = syncResult;
this.localAccount = account;
Log.i(LOG_TAG,
Logger.info(LOG_TAG,
"Syncing account named " + account.name +
" for client named '" + getClientName() +
"' with client guid " + getAccountGUID() +
@ -273,9 +272,9 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter implements GlobalSe
long delay = delayMilliseconds();
if (delay > 0) {
if (thisSyncIsForced) {
Log.i(LOG_TAG, "Forced sync: overruling remaining backoff of " + delay + "ms.");
Logger.info(LOG_TAG, "Forced sync: overruling remaining backoff of " + delay + "ms.");
} else {
Log.i(LOG_TAG, "Not syncing: must wait another " + delay + "ms.");
Logger.info(LOG_TAG, "Not syncing: must wait another " + delay + "ms.");
long remainingSeconds = delay / 1000;
syncResult.delayUntil = remainingSeconds + BACKOFF_PAD_SECONDS;
return;
@ -299,7 +298,7 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter implements GlobalSe
try {
Bundle bundle = future.getResult(60L, TimeUnit.SECONDS);
if (bundle.containsKey("KEY_INTENT")) {
Log.w(LOG_TAG, "KEY_INTENT included in AccountManagerFuture bundle. Problem?");
Logger.warn(LOG_TAG, "KEY_INTENT included in AccountManagerFuture bundle. Problem?");
}
String username = bundle.getString(Constants.OPTION_USERNAME);
String syncKey = bundle.getString(Constants.OPTION_SYNCKEY);
@ -332,14 +331,14 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter implements GlobalSe
// Now catch the individual cases.
if (password == null) {
Log.e(LOG_TAG, "No password: aborting sync.");
Logger.error(LOG_TAG, "No password: aborting sync.");
syncResult.stats.numAuthExceptions++;
notifyMonitor();
return;
}
if (syncKey == null) {
Log.e(LOG_TAG, "No Sync Key: aborting sync.");
Logger.error(LOG_TAG, "No Sync Key: aborting sync.");
syncResult.stats.numAuthExceptions++;
notifyMonitor();
return;
@ -379,11 +378,11 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter implements GlobalSe
syncMonitor.wait();
long interval = getSyncInterval();
long next = System.currentTimeMillis() + interval;
Log.i(LOG_TAG, "Setting minimum next sync time to " + next + " (" + interval + "ms from now).");
Logger.info(LOG_TAG, "Setting minimum next sync time to " + next + " (" + interval + "ms from now).");
extendEarliestNextSync(next);
Log.i(LOG_TAG, "Sync took " + Utils.formatDuration(syncStartTimestamp, System.currentTimeMillis()) + ".");
Logger.info(LOG_TAG, "Sync took " + Utils.formatDuration(syncStartTimestamp, System.currentTimeMillis()) + ".");
} catch (InterruptedException e) {
Log.w(LOG_TAG, "Waiting on sync monitor interrupted.", e);
Logger.warn(LOG_TAG, "Waiting on sync monitor interrupted.", e);
} finally {
// And we're done with HTTP stuff.
stale.shutdown();
@ -489,7 +488,7 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter implements GlobalSe
// Implementing GlobalSession callbacks.
@Override
public void handleError(GlobalSession globalSession, Exception ex) {
Log.i(LOG_TAG, "GlobalSession indicated error. Flagging auth token as invalid, just in case.");
Logger.info(LOG_TAG, "GlobalSession indicated error. Flagging auth token as invalid, just in case.");
setShouldInvalidateAuthToken();
this.updateStats(globalSession, ex);
notifyMonitor();
@ -497,7 +496,7 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter implements GlobalSe
@Override
public void handleAborted(GlobalSession globalSession, String reason) {
Log.w(LOG_TAG, "Sync aborted: " + reason);
Logger.warn(LOG_TAG, "Sync aborted: " + reason);
notifyMonitor();
}
@ -519,7 +518,7 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter implements GlobalSe
@Override
public void handleSuccess(GlobalSession globalSession) {
Log.i(LOG_TAG, "GlobalSession indicated success.");
Logger.info(LOG_TAG, "GlobalSession indicated success.");
Logger.debug(LOG_TAG, "Prefs target: " + globalSession.config.prefsPath);
globalSession.config.persistToPrefs();
notifyMonitor();

View File

@ -205,6 +205,16 @@ let AboutReader = {
return;
this._toolbarElement.classList.toggle("toolbar-hidden");
if (!visible && !this._hasUsedToolbar) {
this._hasUsedToolbar = Services.prefs.getBoolPref("reader.has_used_toolbar");
if (!this._hasUsedToolbar) {
gChromeWin.NativeWindow.toast.show(gStrings.GetStringFromName("aboutReader.toolbarTip"), "short");
Services.prefs.setBoolPref("reader.has_used_toolbar", true);
this._hasUsedToolbar = true;
}
}
},
_toggleToolbarVisibility: function Reader_toggleToolbarVisibility(visible) {

View File

@ -1565,10 +1565,8 @@ var SelectionHandler = {
break;
}
case "after-viewport-change": {
// Update the cache and reposition the handles after the viewport
// changes (e.g. panning, zooming).
// Update the cache after the viewport changes (e.g. panning, zooming).
this.updateCacheForSelection();
this.positionHandles();
break;
}
case "TextSelection:Move": {
@ -1871,13 +1869,15 @@ var SelectionHandler = {
// Translate coordinates to account for selections in sub-frames. We can't cache
// this because the top-level page may have scrolled since selection started.
let offset = this._getViewOffset();
let scrollX = {}, scrollY = {};
this._view.top.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).getScrollXY(false, scrollX, scrollY);
sendMessageToJava({
gecko: {
type: "TextSelection:PositionHandles",
startLeft: this.cache.start.x + offset.x,
startTop: this.cache.start.y + offset.y,
endLeft: this.cache.end.x + offset.x,
endTop: this.cache.end.y + offset.y
startLeft: this.cache.start.x + offset.x + scrollX.value,
startTop: this.cache.start.y + offset.y + scrollY.value,
endLeft: this.cache.end.x + offset.x + scrollX.value,
endTop: this.cache.end.y + offset.y + scrollY.value
}
});
},

View File

@ -11,3 +11,5 @@ aboutReader.marginTitle=Margins
aboutReader.colorSchemeLight=Light
aboutReader.colorSchemeDark=Dark
aboutReader.colorSchemeSepia=Sepia
aboutReader.toolbarTip=Tap the screen to show reader options

View File

@ -1,2 +0,0 @@
mobile/android/base/resources/drawable-hdpi/sync_fx_icon.png
mobile/android/base/resources/drawable-hdpi/sync_ic_launcher.png

View File

@ -1,2 +0,0 @@
mobile/android/base/resources/drawable-ldpi/sync_fx_icon.png
mobile/android/base/resources/drawable-ldpi/sync_ic_launcher.png

View File

@ -1,2 +0,0 @@
mobile/android/base/resources/drawable-mdpi/sync_fx_icon.png
mobile/android/base/resources/drawable-mdpi/sync_ic_launcher.png

View File

@ -1,4 +1,3 @@
mobile/android/base/resources/drawable/desktop.png
mobile/android/base/resources/drawable/mobile.png
mobile/android/base/resources/drawable/pin_background.xml
mobile/android/base/resources/drawable/sync_ic_launcher.png

View File

@ -8,4 +8,3 @@ res/layout/sync_setup_jpake_waiting.xml
res/layout/sync_setup_nointernet.xml
res/layout/sync_setup_pair.xml
res/layout/sync_setup_success.xml
res/layout/sync_stub.xml

View File

@ -1,5 +1,5 @@
<activity
android:icon="@drawable/sync_ic_launcher"
android:icon="@drawable/icon"
android:label="@string/sync_app_name"
android:configChanges="keyboardHidden|orientation|screenSize"
android:windowSoftInputMode="adjustResize|stateHidden"
@ -37,7 +37,7 @@
</receiver>
<activity
android:icon="@drawable/sync_ic_launcher"
android:icon="@drawable/icon"
android:label="@string/sync_app_name"
android:configChanges="orientation"
android:windowSoftInputMode="adjustResize|stateHidden"

View File

@ -4,7 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
[uuid(6e35dbc0-49ef-4e2c-b1ea-b72ec64450a2)]
[uuid(fb82a326-1311-4c45-b5b3-84eb883d4b70)]
interface nsIAuthModule : nsISupports
{
/**
@ -116,6 +116,13 @@ interface nsIAuthModule : nsISupports
in unsigned long aInTokenLength,
out voidPtr aOutToken,
out unsigned long aOutTokenLength);
/* Flags defining various properties of the auth module. */
readonly attribute unsigned long moduleProperties;
/* The service name in Init() is required to be the Canonical DNS
name for that host */
const unsigned long CANONICAL_NAME_REQUIRED = (1<<0);
};
%{C++

View File

@ -179,8 +179,16 @@ nsDeleteDir::TimerCallback(nsITimer *aTimer, void *arg)
dirList = static_cast<nsCOMArray<nsIFile> *>(arg);
bool shuttingDown = false;
for (PRInt32 i = 0; i < dirList->Count() && !shuttingDown; i++) {
gInstance->RemoveDir((*dirList)[i], &shuttingDown);
// Intentional extra braces to control variable sope.
{
// Low IO priority can only be set when running in the context of the
// current thread. So this shouldn't be moved to where we set the priority
// of the Cache deleter thread using the nsThread's NSPR priority constants.
nsAutoLowPriorityIO autoLowPriority;
for (PRInt32 i = 0; i < dirList->Count() && !shuttingDown; i++) {
gInstance->RemoveDir((*dirList)[i], &shuttingDown);
}
}
{

View File

@ -4219,6 +4219,19 @@ NS_IMETHODIMP nsHttpChannel::OnAuthCancelled(bool userCancel)
return NS_OK;
}
NS_IMETHODIMP nsHttpChannel::GetAsciiHostForAuth(nsACString &host)
{
if (mAuthProvider)
return mAuthProvider->GetAsciiHostForAuth(host);
nsresult rv;
nsCOMPtr<nsIURI> uri;
rv = GetURI(getter_AddRefs(uri));
if (NS_FAILED(rv))
return rv;
return uri->GetAsciiHost(host);
}
//-----------------------------------------------------------------------------
// nsHttpChannel::nsISupports
//-----------------------------------------------------------------------------

View File

@ -82,6 +82,7 @@ public:
NS_IMETHOD SetWWWCredentials(const nsACString & aCredentials);
NS_IMETHOD OnAuthAvailable();
NS_IMETHOD OnAuthCancelled(bool userCancel);
NS_IMETHOD GetAsciiHostForAuth(nsACString &aHost);
// Functions we implement from nsIHttpAuthenticableChannel but are
// declared in HttpBaseChannel must be implemented in this class. We
// just call the HttpBaseChannel:: impls.

View File

@ -16,6 +16,10 @@
#include "nsAuthInformationHolder.h"
#include "nsIStringBundle.h"
#include "nsIPrompt.h"
#include "nsIAuthModule.h"
#include "nsIDNSService.h"
#include "nsNetCID.h"
#include "nsIDNSRecord.h"
nsHttpChannelAuthProvider::nsHttpChannelAuthProvider()
: mAuthChannel(nsnull)
@ -25,6 +29,7 @@ nsHttpChannelAuthProvider::nsHttpChannelAuthProvider()
, mTriedProxyAuth(false)
, mTriedHostAuth(false)
, mSuppressDefensiveAuth(false)
, mResolvedHost(0)
{
// grab a reference to the handler to ensure that it doesn't go away.
nsHttpHandler *handler = gHttpHandler;
@ -75,6 +80,9 @@ nsHttpChannelAuthProvider::ProcessAuthentication(PRUint32 httpStatus,
this, mAuthChannel, httpStatus, SSLConnectFailed));
NS_ASSERTION(mAuthChannel, "Channel not initialized");
mCanonicalizedHost.Truncate();
mResolvedHost = 0;
nsCOMPtr<nsIProxyInfo> proxyInfo;
nsresult rv = mAuthChannel->GetProxyInfo(getter_AddRefs(proxyInfo));
@ -224,6 +232,10 @@ nsHttpChannelAuthProvider::Cancel(nsresult status)
mAsyncPromptAuthCancelable->Cancel(status);
mAsyncPromptAuthCancelable = nsnull;
}
if (mDNSQuery) {
mDNSQuery->Cancel(status);
mDNSQuery = nsnull;
}
return NS_OK;
}
@ -236,6 +248,10 @@ nsHttpChannelAuthProvider::Disconnect(nsresult status)
mAsyncPromptAuthCancelable->Cancel(status);
mAsyncPromptAuthCancelable = nsnull;
}
if (mDNSQuery) {
mDNSQuery->Cancel(status);
mDNSQuery = nsnull;
}
NS_IF_RELEASE(mProxyAuthContinuationState);
NS_IF_RELEASE(mAuthContinuationState);
@ -426,6 +442,58 @@ nsHttpChannelAuthProvider::PrepareForAuthentication(bool proxyAuth)
return NS_OK;
}
bool
nsHttpChannelAuthProvider::AuthModuleRequiresCanonicalName(nsISupports *state)
{
if (mResolvedHost || !state)
return false;
nsCOMPtr<nsIAuthModule> module = do_QueryInterface(state);
if (!module)
return false;
PRUint32 flags;
if (NS_FAILED(module->GetModuleProperties(&flags)))
return false;
if (!(flags & nsIAuthModule::CANONICAL_NAME_REQUIRED))
return false;
LOG(("nsHttpChannelAuthProvider::AuthModuleRequiresCanoncialName "
"this=%p\n", this));
return true;
}
nsresult
nsHttpChannelAuthProvider::ResolveHost()
{
mResolvedHost = 1;
nsresult rv;
static NS_DEFINE_CID(kDNSServiceCID, NS_DNSSERVICE_CID);
nsCOMPtr<nsIDNSService> dns = do_GetService(kDNSServiceCID, &rv);
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIURI> uri;
rv = mAuthChannel->GetURI(getter_AddRefs(uri));
if (NS_FAILED(rv))
return rv;
nsCAutoString host;
rv = uri->GetAsciiHost(host);
if (NS_FAILED(rv))
return rv;
LOG(("nsHttpChannelAuthProvider::ResolveHost() this=%p "
"looking up canoncial of %s\n", this, host.get()));
nsRefPtr<DNSCallback> dnsCallback = new DNSCallback(this);
rv = dns->AsyncResolve(host,
nsIDNSService::RESOLVE_CANONICAL_NAME,
dnsCallback, NS_GetCurrentThread(),
getter_AddRefs(mDNSQuery));
return rv;
}
nsresult
nsHttpChannelAuthProvider::GetCredentials(const char *challenges,
bool proxyAuth,
@ -714,6 +782,13 @@ nsHttpChannelAuthProvider::GetCredentialsForChallenge(const char *challenge,
}
}
if (AuthModuleRequiresCanonicalName(*continuationState)) {
nsresult rv = ResolveHost();
if (NS_SUCCEEDED(rv))
return NS_ERROR_IN_PROGRESS;
return rv;
}
//
// get credentials for the given user:pass
//
@ -979,9 +1054,18 @@ NS_IMETHODIMP nsHttpChannelAuthProvider::OnAuthAvailable(nsISupports *aContext,
nsAuthInformationHolder* holder =
static_cast<nsAuthInformationHolder*>(aAuthInfo);
ident->Set(holder->Domain().get(),
holder->User().get(),
holder->Password().get());
if (holder) {
ident->Set(holder->Domain().get(),
holder->User().get(),
holder->Password().get());
}
if (AuthModuleRequiresCanonicalName(*continuationState)) {
rv = ResolveHost();
if (NS_FAILED(rv))
OnAuthCancelled(aContext, true);
return NS_OK;
}
nsCAutoString unused;
nsCOMPtr<nsIHttpAuthenticator> auth;
@ -1273,5 +1357,54 @@ nsHttpChannelAuthProvider::GetCurrentPath(nsACString &path)
return rv;
}
nsresult
nsHttpChannelAuthProvider::GetAsciiHostForAuth(nsACString &host)
{
if (!mCanonicalizedHost.IsEmpty()) {
LOG(("nsHttpChannelAuthProvider::GetAsciiHostForAuth"
" this=%p host is %s\n", this, mCanonicalizedHost.get()));
host = mCanonicalizedHost;
return NS_OK;
}
// fallback
nsresult rv;
nsCOMPtr<nsIURI> uri;
rv = mAuthChannel->GetURI(getter_AddRefs(uri));
if (NS_FAILED(rv))
return rv;
return uri->GetAsciiHost(host);
}
NS_IMETHODIMP
nsHttpChannelAuthProvider::DNSCallback::OnLookupComplete(nsICancelable *request,
nsIDNSRecord *record,
nsresult rv)
{
nsCString cname;
mAuthProvider->SetDNSQuery(nsnull);
LOG(("nsHttpChannelAuthProvider::OnLookupComplete this=%p "
"rv=%X\n", mAuthProvider.get(), rv));
if (NS_SUCCEEDED(rv))
rv = record->GetCanonicalName(cname);
if (NS_SUCCEEDED(rv)) {
LOG(("nsHttpChannelAuthProvider::OnLookupComplete this=%p "
"resolved to %s\n", mAuthProvider.get(), cname.get()));
mAuthProvider->SetCanonicalizedHost(cname);
mAuthProvider->OnAuthAvailable(nsnull, nsnull);
}
else {
LOG(("nsHttpChannelAuthProvider::OnLookupComplete this=%p "
"GetCanonicalName failed\n", mAuthProvider.get()));
mAuthProvider->OnAuthCancelled(nsnull, false);
}
return NS_OK;
}
NS_IMPL_ISUPPORTS3(nsHttpChannelAuthProvider, nsICancelable,
nsIHttpChannelAuthProvider, nsIAuthPromptCallback)
NS_IMPL_THREADSAFE_ISUPPORTS1(nsHttpChannelAuthProvider::DNSCallback,
nsIDNSListener)

View File

@ -16,6 +16,7 @@
#include "nsIURI.h"
#include "nsHttpAuthCache.h"
#include "nsProxyInfo.h"
#include "nsIDNSListener.h"
class nsIHttpAuthenticator;
@ -56,6 +57,9 @@ private:
nsIHttpAuthenticator **auth);
void ParseRealm(const char *challenge, nsACString &realm);
void GetIdentityFromURI(PRUint32 authFlags, nsHttpAuthIdentity&);
bool AuthModuleRequiresCanonicalName(nsISupports *state);
nsresult ResolveHost();
/**
* Following three methods return NS_ERROR_IN_PROGRESS when
* nsIAuthPrompt2.asyncPromptAuth method is called. This result indicates
@ -105,12 +109,16 @@ private:
*/
nsresult ProcessSTSHeader();
void SetDNSQuery(nsICancelable *aQuery) { mDNSQuery = aQuery; }
void SetCanonicalizedHost(nsACString &aHost) { mCanonicalizedHost = aHost; }
private:
nsIHttpAuthenticableChannel *mAuthChannel; // weak ref
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsProxyInfo> mProxyInfo;
nsCString mHost;
nsCString mCanonicalizedHost;
PRInt32 mPort;
bool mUsingSSL;
@ -140,6 +148,22 @@ private:
PRUint32 mTriedProxyAuth : 1;
PRUint32 mTriedHostAuth : 1;
PRUint32 mSuppressDefensiveAuth : 1;
PRUint32 mResolvedHost : 1;
// define a separate threadsafe class for use with the DNS callback
class DNSCallback : public nsIDNSListener
{
NS_DECL_ISUPPORTS
NS_DECL_NSIDNSLISTENER
DNSCallback(nsHttpChannelAuthProvider *authProvider)
: mAuthProvider(authProvider)
{ }
private:
nsRefPtr<nsHttpChannelAuthProvider> mAuthProvider;
};
nsCOMPtr<nsICancelable> mDNSQuery;
};
#endif // nsHttpChannelAuthProvider_h__

View File

@ -351,12 +351,8 @@ nsHttpNTLMAuth::GenerateCredentials(nsIHttpAuthenticableChannel *authChannel,
// initial challenge
if (PL_strcasecmp(challenge, "NTLM") == 0) {
// NTLM service name format is 'HTTP@host' for both http and https
nsCOMPtr<nsIURI> uri;
rv = authChannel->GetURI(getter_AddRefs(uri));
if (NS_FAILED(rv))
return rv;
nsCAutoString serviceName, host;
rv = uri->GetAsciiHost(host);
rv = authChannel->GetAsciiHostForAuth(host);
if (NS_FAILED(rv))
return rv;
serviceName.AppendLiteral("HTTP@");

View File

@ -10,7 +10,7 @@ interface nsILoadGroup;
interface nsIURI;
interface nsIInterfaceRequestor;
[scriptable, uuid(701093ac-5c7f-429c-99e3-423b041fccb4)]
[scriptable, uuid(ea5f7698-c4e4-48fd-aa54-6fdcf1dc349b)]
interface nsIHttpAuthenticableChannel : nsIProxiedChannel
{
/**
@ -71,6 +71,11 @@ interface nsIHttpAuthenticableChannel : nsIProxiedChannel
*/
readonly attribute ACString WWWChallenges;
/**
* The host portion of the URI, possibly canonicalized
*/
readonly attribute ACString asciiHostForAuth;
/**
* Sets the Proxy-Authorization request header. An empty string
* will clear it.

View File

@ -25,7 +25,7 @@ interface nsIHttpAuthenticableChannel;
* called.
*/
[scriptable, uuid(c68f3def-c7c8-4ee8-861c-eef49a48b702)]
[scriptable, uuid(1b74d211-8980-42d4-b0ce-caafa73f4a0f)]
interface nsIHttpChannelAuthProvider : nsICancelable
{
/**
@ -42,13 +42,11 @@ interface nsIHttpChannelAuthProvider : nsICancelable
* the http status received.
* @param sslConnectFailed
* if the last ssl tunnel connection attempt was or not successful.
* @param callback
* the callback to be called when it returns NS_ERROR_IN_PROGRESS.
* The implementation must hold a weak reference.
*
* @returns NS_OK if the credentials were got and set successfully.
* NS_ERROR_IN_PROGRESS if the credentials are going to be asked to
* the user. The channel reference must be
* the user or other blocking event such as DNS
* is incurred. The channel reference must be
* alive until the feedback from
* nsIHttpAuthenticableChannel's methods or
* until disconnect be called.
@ -68,8 +66,13 @@ interface nsIHttpChannelAuthProvider : nsICancelable
void checkForSuperfluousAuth();
/**
* Cancel pending user auth prompts and release the callback and channel
* weak references.
* Cancel pending user auth prompts and release the channel
* weak reference.
*/
void disconnect(in nsresult status);
/**
* The host portion of the URI, possibly canonicalized
*/
readonly attribute ACString asciiHostForAuth;
};

View File

@ -831,6 +831,13 @@ nsNTLMAuthModule::Wrap(const void *inToken,
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsNTLMAuthModule::GetModuleProperties(PRUint32 *flags)
{
*flags = 0;
return NS_OK;
}
//-----------------------------------------------------------------------------
// DES support code

View File

@ -19,6 +19,7 @@
#include "prlog.h"
#include "nsWindowsDllInterceptor.h"
#include "nsWindowsHelpers.h"
using namespace mozilla;
@ -155,18 +156,6 @@ private:
void* mRealView;
};
bool
IsVistaOrLater()
{
OSVERSIONINFO info;
ZeroMemory(&info, sizeof(OSVERSIONINFO));
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&info);
return info.dwMajorVersion >= 6;
}
bool
CheckASLR(const wchar_t* path)
{

View File

@ -1949,19 +1949,19 @@ public:
NS_IMETHOD_(void) DescribeRefCountedNode(nsrefcnt refcount,
size_t objsz,
const char *objname) {};
const char *objname) {}
NS_IMETHOD_(void) DescribeGCedNode(bool ismarked,
size_t objsz,
const char *objname) {};
NS_IMETHOD_(void) NoteXPCOMRoot(nsISupports *root) {};
NS_IMETHOD_(void) NoteJSRoot(void *root) {};
const char *objname) {}
NS_IMETHOD_(void) NoteXPCOMRoot(nsISupports *root) {}
NS_IMETHOD_(void) NoteJSRoot(void *root) {}
NS_IMETHOD_(void) NoteNativeRoot(void *root,
nsCycleCollectionParticipant *helper) {};
NS_IMETHOD_(void) NoteNextEdgeName(const char* name) {};
NS_IMETHOD_(void) NoteWeakMapping(void *map, void *key, void *val) {};
nsCycleCollectionParticipant *helper) {}
NS_IMETHOD_(void) NoteNextEdgeName(const char* name) {}
NS_IMETHOD_(void) NoteWeakMapping(void *map, void *key, void *val) {}
bool MayHaveChild() {
return mMayHaveChild;
};
}
private:
bool mMayHaveChild;
};
@ -1975,7 +1975,7 @@ ChildFinder::NoteXPCOMChild(nsISupports *child)
ToParticipant(child, &cp);
if (cp && !cp->CanSkip(child, true))
mMayHaveChild = true;
};
}
NS_IMETHODIMP_(void)
ChildFinder::NoteNativeChild(void *child,
@ -1983,7 +1983,7 @@ ChildFinder::NoteNativeChild(void *child,
{
if (child)
mMayHaveChild = true;
};
}
NS_IMETHODIMP_(void)
ChildFinder::NoteJSChild(void *child)
@ -1991,7 +1991,7 @@ ChildFinder::NoteJSChild(void *child)
if (child && xpc_GCThingIsGrayCCThing(child)) {
mMayHaveChild = true;
}
};
}
static bool
AddPurpleRoot(GCGraphBuilder &builder, nsISupports *root)

View File

@ -5,6 +5,7 @@
#ifndef nsWindowsHelpers_h
#define nsWindowsHelpers_h
#include <windows.h>
#include "nsAutoRef.h"
#include "nscore.h"
@ -82,4 +83,17 @@ typedef nsAutoRef<HKEY> nsAutoRegKey;
typedef nsAutoRef<SC_HANDLE> nsAutoServiceHandle;
typedef nsAutoRef<HANDLE> nsAutoHandle;
namespace
{
bool
IsVistaOrLater()
{
OSVERSIONINFO info;
ZeroMemory(&info, sizeof(OSVERSIONINFO));
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&info);
return info.dwMajorVersion >= 6;
}
}
#endif

View File

@ -17,6 +17,9 @@
#ifdef XP_WIN
#include <windows.h>
#include "nsWindowsHelpers.h"
#elif defined(XP_MACOSX)
#include <sys/resource.h>
#endif
#include <pratom.h>
@ -289,3 +292,36 @@ nsThreadPoolNaming::SetThreadPoolName(const nsACString & aPoolName,
PR_SetCurrentThreadName(name.BeginReading());
}
}
// nsAutoLowPriorityIO
nsAutoLowPriorityIO::nsAutoLowPriorityIO()
{
#if defined(XP_WIN)
lowIOPrioritySet = IsVistaOrLater() &&
SetThreadPriority(GetCurrentThread(),
THREAD_MODE_BACKGROUND_BEGIN);
#elif defined(XP_MACOSX)
oldPriority = getiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_THREAD);
lowIOPrioritySet = oldPriority != -1 &&
setiopolicy_np(IOPOL_TYPE_DISK,
IOPOL_SCOPE_THREAD,
IOPOL_THROTTLE) != -1;
#else
lowIOPrioritySet = false;
#endif
}
nsAutoLowPriorityIO::~nsAutoLowPriorityIO()
{
#if defined(XP_WIN)
if (NS_LIKELY(lowIOPrioritySet)) {
// On Windows the old thread priority is automatically restored
SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_END);
}
#elif defined(XP_MACOSX)
if (NS_LIKELY(lowIOPrioritySet)) {
setiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_THREAD, oldPriority);
}
#endif
}

View File

@ -494,4 +494,25 @@ private:
void operator=(const nsThreadPoolNaming &) MOZ_DELETE;
};
/**
* Thread priority in most operating systems affect scheduling, not IO. This
* helper is used to set the current thread to low IO priority for the lifetime
* of the created object. You can only use this low priority IO setting within
* the context of the current thread.
*/
class NS_STACK_CLASS nsAutoLowPriorityIO
{
public:
nsAutoLowPriorityIO();
~nsAutoLowPriorityIO();
private:
bool lowIOPrioritySet;
#if defined(XP_MACOSX)
int oldPriority;
#endif
};
#endif // nsThreadUtils_h__