Merge last green changeset from inbound to mozilla-central
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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":
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -286,6 +286,7 @@ protected:
|
|||
|
||||
nsTArray<nsCOMPtr<PluginEventRunnable>> mPostedEvents;
|
||||
void PopPostedEvent(PluginEventRunnable* r);
|
||||
void OnSurfaceTextureFrameAvailable();
|
||||
|
||||
PRUint32 mFullScreenOrientation;
|
||||
bool mWakeLocked;
|
||||
|
|
|
@ -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";
|
||||
|
||||
|
|
|
@ -32,7 +32,8 @@ CPPSRCS = \
|
|||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
INCLUDES += -I../../libeditor/base/src
|
||||
INCLUDES += \
|
||||
$(NULL)
|
||||
|
||||
_FILES = \
|
||||
$(srcdir)/res/EditorOverride.css \
|
||||
|
|
|
@ -567,3 +567,9 @@ nsAuthGSSAPI::Wrap(const void *inToken,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAuthGSSAPI::GetModuleProperties(PRUint32 *flags)
|
||||
{
|
||||
*flags = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -47,6 +47,7 @@ JSCompartment::JSCompartment(JSRuntime *rt)
|
|||
needsBarrier_(false),
|
||||
gcState(NoGCScheduled),
|
||||
gcPreserveCode(false),
|
||||
gcStarted(false),
|
||||
gcBytes(0),
|
||||
gcTriggerBytes(0),
|
||||
gcHeapGrowthFactor(3.0),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -632,6 +632,7 @@ SizeOfJSContext();
|
|||
D(DEBUG_GC) \
|
||||
D(DEBUG_MODE_GC) \
|
||||
D(TRANSPLANT) \
|
||||
D(RESET) \
|
||||
\
|
||||
/* Reasons from Firefox */ \
|
||||
D(DOM_WINDOW_UTILS) \
|
||||
|
|
557
js/src/jsgc.cpp
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)) +
|
||||
|
|
|
@ -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);
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Двоичные данные
mobile/android/base/resources/drawable-hdpi/sync_fx_icon.png
До Ширина: | Высота: | Размер: 12 KiB |
Двоичные данные
mobile/android/base/resources/drawable-hdpi/sync_ic_launcher.png
До Ширина: | Высота: | Размер: 7.7 KiB |
Двоичные данные
mobile/android/base/resources/drawable-ldpi/sync_fx_icon.png
До Ширина: | Высота: | Размер: 3.8 KiB |
Двоичные данные
mobile/android/base/resources/drawable-ldpi/sync_ic_launcher.png
До Ширина: | Высота: | Размер: 3.2 KiB |
Двоичные данные
mobile/android/base/resources/drawable-mdpi/sync_fx_icon.png
До Ширина: | Высота: | Размер: 5.5 KiB |
Двоичные данные
mobile/android/base/resources/drawable-mdpi/sync_ic_launcher.png
До Ширина: | Высота: | Размер: 4.6 KiB |
Двоичные данные
mobile/android/base/resources/drawable/sync_ic_launcher.png
До Ширина: | Высота: | Размер: 4.6 KiB |
|
@ -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"
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
|
@ -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" />
|
|
@ -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"
|
||||
/>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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@";
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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.");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
});
|
||||
},
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
mobile/android/base/resources/drawable-hdpi/sync_fx_icon.png
|
||||
mobile/android/base/resources/drawable-hdpi/sync_ic_launcher.png
|
|
@ -1,2 +0,0 @@
|
|||
mobile/android/base/resources/drawable-ldpi/sync_fx_icon.png
|
||||
mobile/android/base/resources/drawable-ldpi/sync_ic_launcher.png
|
|
@ -1,2 +0,0 @@
|
|||
mobile/android/base/resources/drawable-mdpi/sync_fx_icon.png
|
||||
mobile/android/base/resources/drawable-mdpi/sync_ic_launcher.png
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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++
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
@ -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
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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@");
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
|