Merge with m-c

This commit is contained in:
Doug Turner 2010-03-18 21:53:17 -07:00
commit 4956b23fb3
48 changed files with 2333 additions and 2101 deletions

View File

@ -740,27 +740,49 @@ PRUint32 nsARIAMap::gWAIUnivAttrMapLength = NS_ARRAY_LENGTH(nsARIAMap::gWAIUnivA
////////////////////////////////////////////////////////////////////////////////
// nsStateMapEntry
nsStateMapEntry:: nsStateMapEntry(nsIAtom **aAttrName, eStateValueType aType,
PRUint32 aPermanentState,
PRUint32 aTrueState, PRUint32 aTrueExtraState,
PRUint32 aFalseState, PRUint32 aFalseExtraState,
PRBool aDefinedIfAbsent) :
attributeName(aAttrName), isToken(PR_TRUE), permanentState(aPermanentState)
nsStateMapEntry::nsStateMapEntry() :
mAttributeName(nsnull),
mIsToken(PR_FALSE),
mPermanentState(0),
mValue1(nsnull),
mState1(0),
mExtraState1(0),
mValue2(nsnull),
mState2(0),
mExtraState2(0),
mValue3(nsnull),
mState3(0),
mExtraState3(0),
mDefaultState(0),
mDefaultExtraState(0),
mDefinedIfAbsent(PR_FALSE)
{}
nsStateMapEntry::nsStateMapEntry(nsIAtom **aAttrName, eStateValueType aType,
PRUint32 aPermanentState,
PRUint32 aTrueState, PRUint32 aTrueExtraState,
PRUint32 aFalseState, PRUint32 aFalseExtraState,
PRBool aDefinedIfAbsent) :
mAttributeName(aAttrName),
mIsToken(PR_TRUE),
mPermanentState(aPermanentState),
mValue1("false"),
mState1(aFalseState),
mExtraState1(aFalseExtraState),
mValue2(nsnull),
mState2(0),
mExtraState2(0),
mValue3(nsnull),
mState3(0),
mExtraState3(0),
mDefaultState(aTrueState),
mDefaultExtraState(aTrueExtraState),
mDefinedIfAbsent(aDefinedIfAbsent)
{
value1 = "false";
state1 = aFalseState;
extraState1 = aFalseExtraState;
if (aType == kMixedType) {
value2 = "mixed";
state2 = nsIAccessibleStates::STATE_MIXED;
extraState2 = 0;
mValue2 = "mixed";
mState2 = nsIAccessibleStates::STATE_MIXED;
}
defaultState = aTrueState;
defaultExtraState = aTrueExtraState;
definedIfAbsent = aDefinedIfAbsent;
}
nsStateMapEntry::nsStateMapEntry(nsIAtom **aAttrName,
@ -770,11 +792,11 @@ nsStateMapEntry::nsStateMapEntry(nsIAtom **aAttrName,
PRUint32 aState2, PRUint32 aExtraState2,
const char *aValue3,
PRUint32 aState3, PRUint32 aExtraState3) :
attributeName(aAttrName), isToken(PR_FALSE), permanentState(0),
value1(aValue1), state1(aState1), extraState1(aExtraState1),
value2(aValue2), state2(aState2), extraState2(aExtraState2),
value3(aValue3), state3(aState3), extraState3(aExtraState3),
defaultState(0), defaultExtraState(0), definedIfAbsent(PR_FALSE)
mAttributeName(aAttrName), mIsToken(PR_FALSE), mPermanentState(0),
mValue1(aValue1), mState1(aState1), mExtraState1(aExtraState1),
mValue2(aValue2), mState2(aState2), mExtraState2(aExtraState2),
mValue3(aValue3), mState3(aState3), mExtraState3(aExtraState3),
mDefaultState(0), mDefaultExtraState(0), mDefinedIfAbsent(PR_FALSE)
{
}
@ -786,15 +808,15 @@ nsStateMapEntry::nsStateMapEntry(nsIAtom **aAttrName,
PRUint32 aState2, PRUint32 aExtraState2,
const char *aValue3,
PRUint32 aState3, PRUint32 aExtraState3) :
attributeName(aAttrName), isToken(PR_TRUE), permanentState(0),
value1(aValue1), state1(aState1), extraState1(aExtraState1),
value2(aValue2), state2(aState2), extraState2(aExtraState2),
value3(aValue3), state3(aState3), extraState3(aExtraState3),
defaultState(0), defaultExtraState(0), definedIfAbsent(PR_TRUE)
mAttributeName(aAttrName), mIsToken(PR_TRUE), mPermanentState(0),
mValue1(aValue1), mState1(aState1), mExtraState1(aExtraState1),
mValue2(aValue2), mState2(aState2), mExtraState2(aExtraState2),
mValue3(aValue3), mState3(aState3), mExtraState3(aExtraState3),
mDefaultState(0), mDefaultExtraState(0), mDefinedIfAbsent(PR_TRUE)
{
if (aDefaultStateRule == eUseFirstState) {
defaultState = aState1;
defaultExtraState = aExtraState1;
mDefaultState = aState1;
mDefaultExtraState = aExtraState1;
}
}
@ -809,17 +831,17 @@ nsStateMapEntry::MapToStates(nsIContent *aContent,
const nsStateMapEntry& entry = nsARIAMap::gWAIStateMap[aStateMapEntryID];
if (entry.isToken) {
if (entry.mIsToken) {
// If attribute is considered as defined when it's absent then let's act
// attribute value is "false" supposedly.
PRBool hasAttr = aContent->HasAttr(kNameSpaceID_None, *entry.attributeName);
if (entry.definedIfAbsent && !hasAttr) {
if (entry.permanentState)
*aState |= entry.permanentState;
if (entry.state1)
*aState |= entry.state1;
if (aExtraState && entry.extraState1)
*aExtraState |= entry.extraState1;
PRBool hasAttr = aContent->HasAttr(kNameSpaceID_None, *entry.mAttributeName);
if (entry.mDefinedIfAbsent && !hasAttr) {
if (entry.mPermanentState)
*aState |= entry.mPermanentState;
if (entry.mState1)
*aState |= entry.mState1;
if (aExtraState && entry.mExtraState1)
*aExtraState |= entry.mExtraState1;
return PR_TRUE;
}
@ -832,66 +854,66 @@ nsStateMapEntry::MapToStates(nsIContent *aContent,
// attribute, for example: aria-label="" or aria-label="undefined", we will
// bail out and not explore a state mapping, which is safe.
if (!hasAttr ||
aContent->AttrValueIs(kNameSpaceID_None, *entry.attributeName,
aContent->AttrValueIs(kNameSpaceID_None, *entry.mAttributeName,
nsAccessibilityAtoms::_empty, eCaseMatters) ||
aContent->AttrValueIs(kNameSpaceID_None, *entry.attributeName,
aContent->AttrValueIs(kNameSpaceID_None, *entry.mAttributeName,
nsAccessibilityAtoms::_undefined, eCaseMatters)) {
if (entry.permanentState)
*aState &= ~entry.permanentState;
if (entry.mPermanentState)
*aState &= ~entry.mPermanentState;
return PR_TRUE;
}
if (entry.permanentState)
*aState |= entry.permanentState;
if (entry.mPermanentState)
*aState |= entry.mPermanentState;
}
nsAutoString attrValue;
if (!aContent->GetAttr(kNameSpaceID_None, *entry.attributeName, attrValue))
if (!aContent->GetAttr(kNameSpaceID_None, *entry.mAttributeName, attrValue))
return PR_TRUE;
// Apply states for matched value. If no values was matched then apply default
// states.
PRBool applyDefaultStates = PR_TRUE;
if (entry.value1) {
if (attrValue.EqualsASCII(entry.value1)) {
if (entry.mValue1) {
if (attrValue.EqualsASCII(entry.mValue1)) {
applyDefaultStates = PR_FALSE;
if (entry.state1)
*aState |= entry.state1;
if (entry.mState1)
*aState |= entry.mState1;
if (aExtraState && entry.extraState1)
*aExtraState |= entry.extraState1;
if (aExtraState && entry.mExtraState1)
*aExtraState |= entry.mExtraState1;
} else if (entry.value2) {
if (attrValue.EqualsASCII(entry.value2)) {
} else if (entry.mValue2) {
if (attrValue.EqualsASCII(entry.mValue2)) {
applyDefaultStates = PR_FALSE;
if (entry.state2)
*aState |= entry.state2;
if (entry.mState2)
*aState |= entry.mState2;
if (aExtraState && entry.extraState2)
*aExtraState |= entry.extraState2;
if (aExtraState && entry.mExtraState2)
*aExtraState |= entry.mExtraState2;
} else if (entry.value3) {
if (attrValue.EqualsASCII(entry.value3)) {
} else if (entry.mValue3) {
if (attrValue.EqualsASCII(entry.mValue3)) {
applyDefaultStates = PR_FALSE;
if (entry.state3)
*aState |= entry.state3;
if (entry.mState3)
*aState |= entry.mState3;
if (aExtraState && entry.extraState3)
*aExtraState |= entry.extraState3;
if (aExtraState && entry.mExtraState3)
*aExtraState |= entry.mExtraState3;
}
}
}
}
if (applyDefaultStates) {
if (entry.defaultState)
*aState |= entry.defaultState;
if (entry.defaultExtraState && aExtraState)
*aExtraState |= entry.defaultExtraState;
if (entry.mDefaultState)
*aState |= entry.mDefaultState;
if (entry.mDefaultExtraState && aExtraState)
*aExtraState |= entry.mDefaultExtraState;
}
return PR_TRUE;

View File

@ -194,7 +194,7 @@ public:
/**
* Used to create stub.
*/
nsStateMapEntry() {}
nsStateMapEntry();
/**
* Used for ARIA attributes having boolean or mixed values.
@ -240,33 +240,33 @@ public:
private:
// ARIA attribute name
nsIAtom** attributeName;
nsIAtom** mAttributeName;
// Indicates if attribute is token (can be undefined)
PRBool isToken;
PRBool mIsToken;
// State applied always if attribute is defined
PRUint32 permanentState;
PRUint32 mPermanentState;
// States applied if attribute value is matched to the stored value
const char* value1;
PRUint32 state1;
PRUint32 extraState1;
const char* mValue1;
PRUint32 mState1;
PRUint32 mExtraState1;
const char* value2;
PRUint32 state2;
PRUint32 extraState2;
const char* mValue2;
PRUint32 mState2;
PRUint32 mExtraState2;
const char* value3;
PRUint32 state3;
PRUint32 extraState3;
const char* mValue3;
PRUint32 mState3;
PRUint32 mExtraState3;
// States applied if no stored values above are matched
PRUint32 defaultState;
PRUint32 defaultExtraState;
PRUint32 mDefaultState;
PRUint32 mDefaultExtraState;
// Permanent and false states are applied if attribute is absent
PRBool definedIfAbsent;
PRBool mDefinedIfAbsent;
};

View File

@ -315,7 +315,8 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsXFormsSelectableAccessible,
nsXFormsSelectableAccessible::
nsXFormsSelectableAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell) :
nsXFormsEditableAccessible(aNode, aShell)
nsXFormsEditableAccessible(aNode, aShell),
mIsSelect1Element(nsnull)
{
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
if (!content)

View File

@ -1214,13 +1214,14 @@ nsXULTreeItemAccessible::Shutdown()
nsresult
nsXULTreeItemAccessible::GetRoleInternal(PRUint32 *aRole)
{
nsCOMPtr<nsITreeColumn> column =
nsCoreUtils::GetFirstSensibleColumn(mTree);
nsCOMPtr<nsITreeColumns> columns;
mTree->GetColumns(getter_AddRefs(columns));
NS_ENSURE_STATE(columns);
PRBool isPrimary = PR_FALSE;
column->GetPrimary(&isPrimary);
nsCOMPtr<nsITreeColumn> primaryColumn;
columns->GetPrimaryColumn(getter_AddRefs(primaryColumn));
*aRole = isPrimary ?
*aRole = primaryColumn ?
nsIAccessibleRole::ROLE_OUTLINEITEM :
nsIAccessibleRole::ROLE_LISTITEM;

View File

@ -1341,13 +1341,6 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) {
// Initialize the downloads monitor panel listener
DownloadMonitorPanel.init();
if (Win7Features) {
let tempScope = {};
Cu.import("resource://gre/modules/DownloadTaskbarProgress.jsm",
tempScope);
tempScope.DownloadTaskbarProgress.onBrowserWindowLoad(window);
}
}, 10000);
// Delayed initialization of PlacesDBUtils.

View File

@ -1360,7 +1360,7 @@ protected:
#ifdef MOZ_SMIL
// SMIL Animation Controller, lazily-initialized in GetAnimationController
nsAutoPtr<nsSMILAnimationController> mAnimationController;
nsRefPtr<nsSMILAnimationController> mAnimationController;
#endif // MOZ_SMIL
// Table of element properties for this document.

View File

@ -54,12 +54,7 @@ INPUT(popupText1): blur \n\
setPrefAndDoTest(eventLogForNewWindow,'Body',2); // 2 = open new window as window
}
if (navigator.platform.indexOf("Lin") == -1 && navigator.platform.indexOf("SunOS") == -1) {
SimpleTest.waitForExplicitFinish(); // the finish() call is in bug299673.js
addLoadEvent(doTest);
} else {
todo(false, "Please write a better test for bug 299673 that also works on Linux");
}
todo(false, "Please write a test for bug 299673 that actually works");
</script>
</pre>

View File

@ -53,12 +53,7 @@ INPUT(popupText1): blur \n\
}
if (navigator.platform.indexOf("Lin") == -1) {
SimpleTest.waitForExplicitFinish(); // the finish() call is in bug299673.js
addLoadEvent(doTest);
} else {
todo(false, "Please write a better test for bug 299673 that also works on Linux");
}
todo(false, "Please write a test for bug 299673 that actually works");
</script>
</pre>

View File

@ -1537,27 +1537,35 @@ nsHTMLInputElement::Click()
return rv;
}
nsIPresShell *shell = doc->GetPrimaryShell();
nsCOMPtr<nsIPresShell> shell = doc->GetPrimaryShell();
nsCOMPtr<nsPresContext> context = nsnull;
if (shell) {
nsCOMPtr<nsPresContext> context = shell->GetPresContext();
context = shell->GetPresContext();
}
if (context) {
// Click() is never called from native code, but it may be
// called from chrome JS. Mark this event trusted if Click()
// is called from chrome code.
nsMouseEvent event(nsContentUtils::IsCallerChrome(),
NS_MOUSE_CLICK, nsnull, nsMouseEvent::eReal);
nsEventStatus status = nsEventStatus_eIgnore;
SET_BOOLBIT(mBitField, BF_HANDLING_CLICK, PR_TRUE);
nsEventDispatcher::Dispatch(static_cast<nsIContent*>(this), context,
&event, nsnull, &status);
SET_BOOLBIT(mBitField, BF_HANDLING_CLICK, PR_FALSE);
if (!context) {
doc->FlushPendingNotifications(Flush_Frames);
shell = doc->GetPrimaryShell();
if (shell) {
context = shell->GetPresContext();
}
}
if (context) {
// Click() is never called from native code, but it may be
// called from chrome JS. Mark this event trusted if Click()
// is called from chrome code.
nsMouseEvent event(nsContentUtils::IsCallerChrome(),
NS_MOUSE_CLICK, nsnull, nsMouseEvent::eReal);
nsEventStatus status = nsEventStatus_eIgnore;
SET_BOOLBIT(mBitField, BF_HANDLING_CLICK, PR_TRUE);
nsEventDispatcher::Dispatch(static_cast<nsIContent*>(this), context,
&event, nsnull, &status);
SET_BOOLBIT(mBitField, BF_HANDLING_CLICK, PR_FALSE);
}
}
return NS_OK;

View File

@ -62,6 +62,20 @@
//
const PRUint32 nsSMILAnimationController::kTimerInterval = 22;
// Helper method
static nsRefreshDriver*
GetRefreshDriverForDoc(nsIDocument* aDoc)
{
nsIPresShell* shell = aDoc->GetPrimaryShell();
if (!shell) {
return nsnull;
}
nsPresContext* context = shell->GetPresContext();
return context ? context->RefreshDriver() : nsnull;
}
//----------------------------------------------------------------------
// ctors, dtors, factory methods
@ -75,10 +89,8 @@ nsSMILAnimationController::nsSMILAnimationController()
nsSMILAnimationController::~nsSMILAnimationController()
{
if (mTimer) {
mTimer->Cancel();
mTimer = nsnull;
}
StopSampling(GetRefreshDriverForDoc(mDocument));
mTimer = nsnull;
NS_ASSERTION(mAnimationElementTable.Count() == 0,
"Animation controller shouldn't be tracking any animation"
@ -125,7 +137,7 @@ nsSMILAnimationController::Pause(PRUint32 aType)
nsSMILTimeContainer::Pause(aType);
if (mPauseState) {
StopTimer();
StopSampling(GetRefreshDriverForDoc(mDocument));
}
}
@ -137,7 +149,8 @@ nsSMILAnimationController::Resume(PRUint32 aType)
nsSMILTimeContainer::Resume(aType);
if (wasPaused && !mPauseState && mChildContainerTable.Count()) {
StartTimer();
Sample(); // Run the first sample manually
StartSampling(GetRefreshDriverForDoc(mDocument));
}
}
@ -148,6 +161,22 @@ nsSMILAnimationController::GetParentTime() const
return PR_Now() / PR_USEC_PER_MSEC;
}
//----------------------------------------------------------------------
// nsARefreshObserver methods:
NS_IMPL_ADDREF(nsSMILAnimationController)
NS_IMPL_RELEASE(nsSMILAnimationController)
// nsRefreshDriver Callback function
// XXXdholbert NOTE: This function isn't used yet
void
nsSMILAnimationController::WillRefresh(mozilla::TimeStamp aTime)
{
// XXXdholbert Eventually we should be sampling based on aTime. For now,
// though, we keep track of the time on our own, and we just use
// nsRefreshDriver for scheduling samples.
Sample();
}
//----------------------------------------------------------------------
// Animation element registration methods:
@ -226,14 +255,11 @@ nsSMILAnimationController::Notify(nsITimer* timer, void* aClosure)
}
nsresult
nsSMILAnimationController::StartTimer()
nsSMILAnimationController::StartSampling(nsRefreshDriver* aRefreshDriver)
{
NS_ENSURE_TRUE(mTimer, NS_ERROR_FAILURE);
NS_ASSERTION(mPauseState == 0, "Starting timer but controller is paused");
// Run the first sample manually
Sample();
//
// XXX Make this self-tuning. Sounds like control theory to me and not
// something I'm familiar with.
@ -245,7 +271,7 @@ nsSMILAnimationController::StartTimer()
}
nsresult
nsSMILAnimationController::StopTimer()
nsSMILAnimationController::StopSampling(nsRefreshDriver* aRefreshDriver)
{
NS_ENSURE_TRUE(mTimer, NS_ERROR_FAILURE);
@ -668,7 +694,8 @@ nsSMILAnimationController::AddChild(nsSMILTimeContainer& aChild)
NS_ENSURE_TRUE(key,NS_ERROR_OUT_OF_MEMORY);
if (!mPauseState && mChildContainerTable.Count() == 1) {
StartTimer();
Sample(); // Run the first sample manually
StartSampling(GetRefreshDriverForDoc(mDocument));
}
return NS_OK;
@ -680,6 +707,6 @@ nsSMILAnimationController::RemoveChild(nsSMILTimeContainer& aChild)
mChildContainerTable.RemoveEntry(&aChild);
if (!mPauseState && mChildContainerTable.Count() == 0) {
StopTimer();
StopSampling(GetRefreshDriverForDoc(mDocument));
}
}

View File

@ -48,6 +48,7 @@
#include "nsSMILTimeContainer.h"
#include "nsSMILCompositorTable.h"
#include "nsSMILMilestone.h"
#include "nsRefreshDriver.h"
struct nsSMILTargetIdentifier;
class nsISMILAnimationElement;
@ -66,7 +67,8 @@ class nsIDocument;
// a compound document. These time containers can be paused individually or
// here, at the document level.
//
class nsSMILAnimationController : public nsSMILTimeContainer
class nsSMILAnimationController : public nsSMILTimeContainer,
public nsARefreshObserver
{
public:
nsSMILAnimationController();
@ -77,6 +79,12 @@ public:
virtual void Resume(PRUint32 aType);
virtual nsSMILTime GetParentTime() const;
// nsARefreshObserver
NS_IMETHOD_(nsrefcnt) AddRef();
NS_IMETHOD_(nsrefcnt) Release();
virtual void WillRefresh(mozilla::TimeStamp aTime);
// Methods for registering and enumerating animation elements
void RegisterAnimationElement(nsISMILAnimationElement* aAnimationElement);
void UnregisterAnimationElement(nsISMILAnimationElement* aAnimationElement);
@ -102,6 +110,10 @@ public:
void Traverse(nsCycleCollectionTraversalCallback* aCallback);
void Unlink();
// Methods for controlling whether we're sampling
nsresult StartSampling(nsRefreshDriver* aRefreshDriver);
nsresult StopSampling(nsRefreshDriver* aRefreshDriver);
protected:
// Typedefs
typedef nsPtrHashKey<nsSMILTimeContainer> TimeContainerPtrKey;
@ -138,8 +150,6 @@ protected:
// Timer-related implementation helpers
static void Notify(nsITimer* aTimer, void* aClosure);
nsresult StartTimer();
nsresult StopTimer();
// Sample-related callbacks and implementation helpers
virtual void DoSample();
@ -165,6 +175,9 @@ protected:
virtual void RemoveChild(nsSMILTimeContainer& aChild);
// Members
nsAutoRefCnt mRefCnt;
NS_DECL_OWNINGTHREAD
static const PRUint32 kTimerInterval;
nsCOMPtr<nsITimer> mTimer;
AnimationElementHashtable mAnimationElementTable;

View File

@ -259,7 +259,7 @@ PluginModuleParent::ActorDestroy(ActorDestroyReason why)
switch (why) {
case AbnormalShutdown: {
nsCOMPtr<nsIFile> dump;
if (GetMinidump(getter_AddRefs(dump))) {
if (TakeMinidump(getter_AddRefs(dump))) {
WriteExtraDataForMinidump(dump);
if (NS_SUCCEEDED(dump->GetLeafName(mDumpID))) {
mDumpID.Replace(mDumpID.Length() - 4, 4,
@ -295,6 +295,15 @@ PluginModuleParent::NotifyPluginCrashed()
// MessageLoop owns this
mPluginCrashedTask = NULL;
if (!OkToCleanup()) {
// there's still plugin code on the C++ stack. try again
mPluginCrashedTask = NewRunnableMethod(
this, &PluginModuleParent::NotifyPluginCrashed);
MessageLoop::current()->PostDelayedTask(
FROM_HERE, mPluginCrashedTask, 10);
return;
}
if (mPlugin)
mPlugin->PluginCrashed(mDumpID);
}

View File

@ -121,7 +121,7 @@ typedef struct {
cairo_bool_t supports_porter_duff;
#if defined(Q_WS_X11) && defined(CAIRO_HAS_XLIB_XRENDER_SURFACE)
#if defined(CAIRO_HAS_XLIB_XRENDER_SURFACE)
/* temporary, so that we can share the xlib surface's glyphs code */
bool xlib_has_clipping;
cairo_surface_t *xlib_equiv;
@ -438,7 +438,7 @@ _cairo_qpainter_surface_finish (void *abstract_surface)
if (qs->image_equiv)
cairo_surface_destroy ((cairo_surface_t*) qs->image_equiv);
#if defined(Q_WS_X11) && defined(CAIRO_HAS_XLIB_XRENDER_SURFACE)
#if defined(CAIRO_HAS_XLIB_XRENDER_SURFACE)
if (qs->xlib_equiv)
cairo_surface_destroy (qs->xlib_equiv);
#endif
@ -1365,7 +1365,7 @@ _cairo_qpainter_surface_show_glyphs (void *abstract_surface,
Q_UNUSED(extends);
cairo_qpainter_surface_t *qs = (cairo_qpainter_surface_t *) abstract_surface;
#if defined(Q_WS_X11) && defined(CAIRO_HAS_XLIB_XRENDER_SURFACE)
#if defined(CAIRO_HAS_XLIB_XRENDER_SURFACE)
/* If we have an equivalent X surface, let the xlib surface handle this
* until we figure out how to do this natively with Qt.
*/
@ -1587,7 +1587,7 @@ static const cairo_surface_backend_t cairo_qpainter_surface_backend = {
NULL, /* show_text_glyphs */
};
#if defined(Q_WS_X11) && defined(CAIRO_HAS_XLIB_XRENDER_SURFACE)
#if defined(CAIRO_HAS_XLIB_XRENDER_SURFACE)
void
_cairo_qpainter_create_xlib_surface (cairo_qpainter_surface_t *qs)
{
@ -1661,7 +1661,7 @@ cairo_qpainter_surface_create (QPainter *painter)
qs->window = painter->window();
#if defined(Q_WS_X11) && defined(CAIRO_HAS_XLIB_XRENDER_SURFACE)
#if defined(CAIRO_HAS_XLIB_XRENDER_SURFACE)
_cairo_qpainter_create_xlib_surface (qs);
#endif
@ -1748,7 +1748,7 @@ cairo_qpainter_surface_create_with_qpixmap (cairo_content_t content,
qs->window = QRect(0, 0, width, height);
#if defined(Q_WS_X11) && defined(CAIRO_HAS_XLIB_XRENDER_SURFACE)
#if defined(CAIRO_HAS_XLIB_XRENDER_SURFACE)
_cairo_qpainter_create_xlib_surface (qs);
#endif

View File

@ -27,7 +27,12 @@ Message::Message()
InitLoggingVariables();
}
#if !defined(CHROMIUM_MOZILLA_BUILD)
Message::Message(int32 routing_id, uint16 type, PriorityValue priority)
#else
Message::Message(int32 routing_id, uint16 type, PriorityValue priority,
const char* const name)
#endif
: Pickle(sizeof(Header)) {
header()->routing = routing_id;
header()->type = type;
@ -39,8 +44,10 @@ Message::Message(int32 routing_id, uint16 type, PriorityValue priority)
header()->rpc_remote_stack_depth_guess = static_cast<size_t>(-1);
header()->rpc_local_stack_depth = static_cast<size_t>(-1);
header()->seqno = 0;
#endif
InitLoggingVariables(name);
#else
InitLoggingVariables();
#endif
}
Message::Message(const char* data, int data_len) : Pickle(data, data_len) {
@ -48,13 +55,22 @@ Message::Message(const char* data, int data_len) : Pickle(data, data_len) {
}
Message::Message(const Message& other) : Pickle(other) {
#if !defined(CHROMIUM_MOZILLA_BUILD)
InitLoggingVariables();
#else
InitLoggingVariables(other.name_);
#endif
#if defined(OS_POSIX)
file_descriptor_set_ = other.file_descriptor_set_;
#endif
}
#if !defined(CHROMIUM_MOZILLA_BUILD)
void Message::InitLoggingVariables() {
#else
void Message::InitLoggingVariables(const char* const name) {
name_ = name;
#endif
#ifdef IPC_MESSAGE_LOG_ENABLED
received_time_ = 0;
dont_log_ = false;
@ -64,6 +80,9 @@ void Message::InitLoggingVariables() {
Message& Message::operator=(const Message& other) {
*static_cast<Pickle*>(this) = other;
#if defined(CHROMIUM_MOZILLA_BUILD)
InitLoggingVariables(other.name_);
#endif
#if defined(OS_POSIX)
file_descriptor_set_ = other.file_descriptor_set_;
#endif

View File

@ -62,7 +62,12 @@ class Message : public Pickle {
// Initialize a message with a user-defined type, priority value, and
// destination WebView ID.
#if !defined(CHROMIUM_MOZILLA_BUILD)
Message(int32 routing_id, uint16 type, PriorityValue priority);
#else
Message(int32 routing_id, uint16 type, PriorityValue priority,
const char* const name="???");
#endif
// Initializes a message from a const block of data. The data is not copied;
// instead the data is merely referenced by this message. Only const methods
@ -166,6 +171,14 @@ class Message : public Pickle {
void set_seqno(int32 seqno) {
header()->seqno = seqno;
}
const char* const name() const {
return name_;
}
void set_name(const char* const name) {
name_ = name;
}
#endif
template<class T>
@ -296,7 +309,11 @@ class Message : public Pickle {
return headerT<Header>();
}
#if !defined(CHROMIUM_MOZILLA_BUILD)
void InitLoggingVariables();
#else
void InitLoggingVariables(const char* const name="???");
#endif
#if defined(OS_POSIX)
// The set of file descriptors associated with this message.
@ -314,6 +331,10 @@ class Message : public Pickle {
}
#endif
#if defined(CHROMIUM_MOZILLA_BUILD)
const char* name_;
#endif
#ifdef IPC_MESSAGE_LOG_ENABLED
// Used for logging.
mutable int64 received_time_;

View File

@ -444,11 +444,18 @@ AsyncChannel::OnChannelError()
MutexAutoLock lock(mMutex);
// NB: this can race with the `Goodbye' event being processed by
// the worker thread
if (ChannelClosing != mChannelState)
mChannelState = ChannelError;
PostErrorNotifyTask();
}
void
AsyncChannel::PostErrorNotifyTask()
{
AssertIOThread();
mMutex.AssertCurrentThreadOwns();
NS_ASSERTION(!mChannelErrorTask, "OnChannelError called twice?");
// This must be the last code that runs on this thread!

View File

@ -175,6 +175,7 @@ protected:
void OnChannelOpened();
void OnSend(Message* aMsg);
void OnCloseChannel();
void PostErrorNotifyTask();
// Return true if |msg| is a special message targeted at the IO
// thread, in which case it shouldn't be delivered to the worker.

View File

@ -96,8 +96,7 @@ RPCChannel::RPCChannel(RPCListener* aListener)
mOutOfTurnReplies(),
mDeferred(),
mRemoteStackDepthGuess(0),
mBlockedOnParent(false),
mCxxStackFrames(0)
mBlockedOnParent(false)
{
MOZ_COUNT_CTOR(RPCChannel);
@ -109,7 +108,7 @@ RPCChannel::RPCChannel(RPCListener* aListener)
RPCChannel::~RPCChannel()
{
MOZ_COUNT_DTOR(RPCChannel);
RPC_ASSERT(0 == mCxxStackFrames, "mismatched CxxStackFrame ctor/dtors");
RPC_ASSERT(mCxxStackFrames.empty(), "mismatched CxxStackFrame ctor/dtors");
}
void
@ -142,14 +141,16 @@ RPCChannel::EventOccurred()
bool
RPCChannel::Send(Message* msg)
{
CxxStackFrame f(*this);
Message copy = *msg;
CxxStackFrame f(*this, OUT_MESSAGE, &copy);
return AsyncChannel::Send(msg);
}
bool
RPCChannel::Send(Message* msg, Message* reply)
{
CxxStackFrame f(*this);
Message copy = *msg;
CxxStackFrame f(*this, OUT_MESSAGE, &copy);
return SyncChannel::Send(msg, reply);
}
@ -162,7 +163,8 @@ RPCChannel::Call(Message* msg, Message* reply)
"violation of sync handler invariant");
RPC_ASSERT(msg->is_rpc(), "can only Call() RPC messages here");
CxxStackFrame f(*this);
Message copy = *msg;
CxxStackFrame f(*this, OUT_MESSAGE, &copy);
MutexAutoLock lock(mMutex);
@ -227,7 +229,10 @@ RPCChannel::Call(Message* msg, Message* reply)
if (!recvd.is_sync() && !recvd.is_rpc()) {
MutexAutoUnlock unlock(mMutex);
CxxStackFrame f(*this, IN_MESSAGE, &recvd);
AsyncChannel::OnDispatchMessage(recvd);
continue;
}
@ -235,7 +240,10 @@ RPCChannel::Call(Message* msg, Message* reply)
RPC_ASSERT(mPending.empty(),
"other side should have been blocked");
MutexAutoUnlock unlock(mMutex);
CxxStackFrame f(*this, IN_MESSAGE, &recvd);
SyncChannel::OnDispatchMessage(recvd);
continue;
}
@ -271,14 +279,6 @@ RPCChannel::Call(Message* msg, Message* reply)
}
if (0 == StackDepth()) {
// we may have received new messages while waiting for
// our reply. because we were awaiting a reply,
// StackDepth > 0, and the IO thread didn't enqueue
// OnMaybeDequeueOne() events for us. so to avoid
// "losing" the new messages, we do that now.
EnqueuePendingMessages();
RPC_ASSERT(
mOutOfTurnReplies.empty(),
"still have pending replies with no pending out-calls",
@ -296,6 +296,7 @@ RPCChannel::Call(Message* msg, Message* reply)
{
MutexAutoUnlock unlock(mMutex);
// someone called in to us from the other side. handle the call
CxxStackFrame f(*this, IN_MESSAGE, &recvd);
Incall(recvd, stackDepth);
// FIXME/cjones: error handling
}
@ -332,6 +333,8 @@ RPCChannel::MaybeProcessDeferredIncall()
MutexAutoUnlock unlock(mMutex);
fprintf(stderr, " (processing deferred in-call)\n");
CxxStackFrame f(*this, IN_MESSAGE, &call);
Incall(call, stackDepth);
}
@ -364,6 +367,22 @@ RPCChannel::OnMaybeDequeueOne()
AssertWorkerThread();
mMutex.AssertNotCurrentThreadOwns();
if (IsOnCxxStack())
// We're running in a nested event loop, and there's
// RPCChannel code below us on the stack. We don't want to
// dispatch this new message here because the assumptions made
// by the code below us on the stack have changed. Just
// bailing here isn't enough, however, because we also have to
// ensure that the messages received in this nested loop
// aren't "lost". We might be running in this nested context
// above a non-interruptable handler; these are async
// in/out-msg, sync in/out-msg, and rpc in-call. So, we still
// bail here, but ensure that at each exit point, we fix up
// the IO thread's invariant. Luckily, since we already track
// the C++ stack, we know when these exit points are hit:
// ExitedCxxStack().
return;
Message recvd;
{
MutexAutoLock lock(mMutex);
@ -383,7 +402,8 @@ RPCChannel::OnMaybeDequeueOne()
mPending.pop();
}
CxxStackFrame f(*this);
RPC_ASSERT(!IsOnCxxStack(), "RPCChannel code not on C++ stack");
CxxStackFrame f(*this, IN_MESSAGE, &recvd);
if (recvd.is_rpc())
return Incall(recvd, 0);
@ -554,6 +574,8 @@ RPCChannel::BlockOnParent()
mPending.pop();
MutexAutoUnlock unlock(mMutex);
CxxStackFrame f(*this, IN_MESSAGE, &recvd);
if (recvd.is_rpc()) {
// stack depth must be 0 here
Incall(recvd, 0);
@ -581,6 +603,17 @@ RPCChannel::UnblockFromParent()
mBlockedOnParent = false;
}
void
RPCChannel::ExitedCxxStack()
{
Listener()->OnExitedCxxStack();
{
MutexAutoLock lock(mMutex);
// see long comment in OnMaybeDequeueOne()
EnqueuePendingMessages();
}
}
void
RPCChannel::DebugAbort(const char* file, int line, const char* cond,
const char* why,
@ -594,8 +627,7 @@ RPCChannel::DebugAbort(const char* file, int line, const char* cond,
why,
type, reply ? "reply" : "");
// technically we need the mutex for this, but we're dying anyway
fprintf(stderr, " local RPC stack size: %lu\n",
mStack.size());
DumpRPCStack(stderr, " ");
fprintf(stderr, " remote RPC stack guess: %lu\n",
mRemoteStackDepthGuess);
fprintf(stderr, " deferred stack size: %lu\n",
@ -615,6 +647,28 @@ RPCChannel::DebugAbort(const char* file, int line, const char* cond,
NS_RUNTIMEABORT(why);
}
void
RPCChannel::DumpRPCStack(FILE* outfile, const char* const pfx)
{
NS_WARN_IF_FALSE(MessageLoop::current() != mWorkerLoop,
"The worker thread had better be paused in a debugger!");
if (!outfile)
outfile = stdout;
fprintf(outfile, "%sRPCChannel 'backtrace':\n", pfx);
// print a python-style backtrace, first frame to last
for (PRUint32 i = 0; i < mCxxStackFrames.size(); ++i) {
int32 id;
const char* dir, *sems, *name;
mCxxStackFrames[i].Describe(&id, &dir, &sems, &name);
fprintf(outfile, "%s[(%u) %s %s %s(actor=%d) ]\n", pfx,
i, dir, sems, name, id);
}
}
//
// The methods below run in the context of the IO thread, and can proxy
// back to the methods above
@ -654,20 +708,16 @@ RPCChannel::OnChannelError()
{
AssertIOThread();
{
MutexAutoLock lock(mMutex);
MutexAutoLock lock(mMutex);
// NB: this can race with the `Goodbye' event being processed by
// the worker thread
if (ChannelClosing != mChannelState)
mChannelState = ChannelError;
if (ChannelClosing != mChannelState)
mChannelState = ChannelError;
// skip SyncChannel::OnError(); we subsume its duties
if (AwaitingSyncReply() || 0 < StackDepth())
NotifyWorkerThread();
}
// skip SyncChannel::OnError(); we subsume its duties
if (AwaitingSyncReply() || 0 < StackDepth())
NotifyWorkerThread();
AsyncChannel::OnChannelError();
PostErrorNotifyTask();
}
} // namespace ipc

View File

@ -39,9 +39,12 @@
#ifndef ipc_glue_RPCChannel_h
#define ipc_glue_RPCChannel_h 1
#include <stdio.h>
// FIXME/cjones probably shouldn't depend on STL
#include <queue>
#include <stack>
#include <vector>
#include "base/basictypes.h"
@ -140,7 +143,7 @@ public:
// Return true iff this has code on the C++ stack.
bool IsOnCxxStack() const {
return 0 < mCxxStackFrames;
return !mCxxStackFrames.empty();
}
NS_OVERRIDE
@ -183,7 +186,7 @@ protected:
NS_OVERRIDE
virtual bool ShouldDeferNotifyMaybeError() {
return 0 < mCxxStackFrames;
return IsOnCxxStack();
}
bool EventOccurred();
@ -207,25 +210,44 @@ protected:
Listener()->OnEnteredCxxStack();
}
void ExitedCxxStack()
{
Listener()->OnExitedCxxStack();
}
void ExitedCxxStack();
enum Direction { IN_MESSAGE, OUT_MESSAGE };
struct RPCFrame {
RPCFrame(Direction direction, const Message* msg) :
mDirection(direction), mMsg(msg)
{ }
void Describe(int32* id, const char** dir, const char** sems,
const char** name)
const
{
*id = mMsg->routing_id();
*dir = (IN_MESSAGE == mDirection) ? "in" : "out";
*sems = mMsg->is_rpc() ? "rpc" : mMsg->is_sync() ? "sync" : "async";
*name = mMsg->name();
}
Direction mDirection;
const Message* mMsg;
};
class NS_STACK_CLASS CxxStackFrame
{
public:
CxxStackFrame(RPCChannel& that) : mThat(that) {
NS_ABORT_IF_FALSE(0 <= mThat.mCxxStackFrames,
"mismatched CxxStackFrame ctor/dtor");
CxxStackFrame(RPCChannel& that, Direction direction,
const Message* msg) : mThat(that) {
mThat.AssertWorkerThread();
if (0 == mThat.mCxxStackFrames++)
if (mThat.mCxxStackFrames.empty())
mThat.EnteredCxxStack();
mThat.mCxxStackFrames.push_back(RPCFrame(direction, msg));
}
~CxxStackFrame() {
bool exitingStack = (0 == --mThat.mCxxStackFrames);
mThat.mCxxStackFrames.pop_back();
bool exitingStack = mThat.mCxxStackFrames.empty();
// mListener could have gone away if Close() was called while
// RPCChannel code was still on the stack
@ -255,6 +277,10 @@ protected:
const char* why,
const char* type="rpc", bool reply=false);
// This method is only safe to call on the worker thread, or in a
// debugger with all threads paused. |outfile| defaults to stdout.
void DumpRPCStack(FILE* outfile=NULL, const char* const pfx="");
//
// Queue of all incoming messages, except for replies to sync
// messages, which are delivered directly to the SyncChannel
@ -350,15 +376,15 @@ protected:
// True iff the parent has put us in a |BlockChild()| state.
bool mBlockedOnParent;
// Approximation of number of Sync/RPCChannel-code frames on the
// C++ stack. It can only be interpreted as the implication
// Approximation of Sync/RPCChannel-code frames on the C++ stack.
// It can only be interpreted as the implication
//
// mCxxStackDepth > 0 => RPCChannel code on C++ stack
// !mCxxStackFrames.empty() => RPCChannel code on C++ stack
//
// This member is only accessed on the worker thread, and so is
// not protected by mMutex. It is managed exclusively by the
// helper |class CxxStackFrame|.
int mCxxStackFrames;
std::vector<RPCFrame> mCxxStackFrames;
private:

View File

@ -213,19 +213,15 @@ SyncChannel::OnChannelError()
{
AssertIOThread();
{
MutexAutoLock lock(mMutex);
MutexAutoLock lock(mMutex);
// NB: this can race with the `Goodbye' event being processed by
// the worker thread
if (ChannelClosing != mChannelState)
mChannelState = ChannelError;
if (ChannelClosing != mChannelState)
mChannelState = ChannelError;
if (AwaitingSyncReply())
NotifyWorkerThread();
}
if (AwaitingSyncReply())
NotifyWorkerThread();
AsyncChannel::OnChannelError();
PostErrorNotifyTask();
}
//

View File

@ -617,6 +617,7 @@ class ExprCall(Node):
def __init__(self, func, args=[ ]):
assert hasattr(func, 'accept')
assert isinstance(args, list)
for arg in args: assert not isinstance(arg, str)
Node.__init__(self)
self.func = func

View File

@ -1160,12 +1160,17 @@ class MessageDecl(ipdl.ast.MessageDecl):
def msgClass(self):
return 'Msg_%s'% (self.decl.progname)
def prettyMsgName(self, pfx=''):
return pfx + self.msgClass()
def pqMsgClass(self):
return '%s::%s'% (self.namespace, self.msgClass())
def msgCast(self, msgexpr):
return ExprCast(msgexpr, Type(self.pqMsgClass(), const=1, ptr=1),
static=1)
return ExprCast(msgexpr, self.msgCxxType(const=1, ptr=1), static=1)
def msgCxxType(self, const=0, ref=0, ptr=0):
return Type(self.pqMsgClass(), const=const, ref=ref, ptr=ptr)
def msgId(self): return self.msgClass()+ '__ID'
def pqMsgId(self):
@ -1185,6 +1190,9 @@ class MessageDecl(ipdl.ast.MessageDecl):
def pqReplyId(self):
return '%s::%s'% (self.namespace, self.replyId())
def prettyReplyName(self, pfx=''):
return pfx + self.replyClass()
def actorDecl(self):
return self.params[0]
@ -1645,7 +1653,8 @@ child actors.'''
pipetypes=1)
ns.addstmts([
_generateMessageClass(md.msgClass(), md.msgId(),
paramsIn, paramsOut, typedefs),
paramsIn, paramsOut, typedefs,
md.prettyMsgName(p.name+'::')),
Whitespace.NL ])
if md.hasReply():
returnsIn = md.makeCxxParams(paramsems=None, returnsems='in',
@ -1655,14 +1664,15 @@ child actors.'''
ns.addstmts([
_generateMessageClass(
md.replyClass(), md.replyId(), returnsIn, returnsOut,
typedefs),
typedefs, md.prettyReplyName(p.name+'::')),
Whitespace.NL ])
ns.addstmts([ Whitespace.NL, Whitespace.NL ])
##--------------------------------------------------
def _generateMessageClass(clsname, msgid, inparams, outparams, typedefs):
def _generateMessageClass(clsname, msgid, inparams, outparams, typedefs,
prettyName):
cls = Class(name=clsname, inherits=[ Inherit(Type('IPC::Message')) ])
cls.addstmt(Label.PRIVATE)
cls.addstmts(typedefs)
@ -1681,7 +1691,8 @@ def _generateMessageClass(clsname, msgid, inparams, outparams, typedefs):
memberinits=[ExprMemberInit(ExprVar('IPC::Message'),
[ ExprVar('MSG_ROUTING_NONE'),
ExprVar('ID'),
ExprVar('PRIORITY_NORMAL') ]) ])
ExprVar('PRIORITY_NORMAL'),
ExprLiteral.String(prettyName) ]) ])
ctor.addstmts([
StmtExpr(ExprCall(ExprVar('IPC::WriteParam'),
args=[ ExprVar.THIS, ExprVar(p.name) ]))
@ -2950,14 +2961,14 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
dumpvar = ExprVar('aDump')
getdump = MethodDefn(MethodDecl(
'GetMinidump',
'TakeMinidump',
params=[ Decl(Type('nsIFile', ptrptr=1), dumpvar.name) ],
ret=Type.BOOL,
const=1))
getdump.addstmts([
CppDirective('ifdef', 'MOZ_CRASHREPORTER'),
StmtReturn(ExprCall(
ExprVar('XRE_GetMinidumpForChild'),
ExprVar('XRE_TakeMinidumpForChild'),
args=[ ExprCall(otherpidvar), dumpvar ])),
CppDirective('else'),
StmtReturn(ExprLiteral.FALSE),
@ -3854,6 +3865,15 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
vars = [ ]
readvars = [ ]
stmts = [
# this is kind of naughty, but the only two other options
# are serializing the message name (yuk) or making the
# IPDL|*Channel abstraction leak more
StmtExpr(ExprCall(
ExprSelect(
ExprCast(msgvar, Type('Message', ref=1), const=1),
'.', 'set_name'),
args=[ ExprLiteral.String(md.prettyMsgName(self.protocol.name
+'::')) ])),
self.logMessage(md, md.msgCast(ExprAddrOf(msgvar)),
'Received '),
Whitespace.NL

View File

@ -58,23 +58,24 @@ FORCE_STATIC_LIB = 1
EXPORT_LIBRARY = 1
IPDLTESTS = \
TestSanity \
TestRPCErrorCleanup \
TestCrashCleanup \
TestStackHooks \
TestSyncWakeup \
TestLatency \
TestRPCRaces \
TestRacyRPCReplies \
TestRPCShutdownRace \
TestHangs \
TestArrays \
TestBlockChild \
TestManyChildAllocs \
TestCrashCleanup \
TestDesc \
TestHangs \
TestLatency \
TestManyChildAllocs \
TestMultiMgrs \
TestNestedLoops \
TestRPCErrorCleanup \
TestRPCRaces \
TestRPCShutdownRace \
TestRacyRPCReplies \
TestSanity \
TestShmem \
TestShutdown \
TestArrays \
TestStackHooks \
TestSyncWakeup \
$(NULL)
IPDLTESTSRCS = $(addsuffix .cpp,$(IPDLTESTS))

View File

@ -0,0 +1,34 @@
namespace mozilla {
namespace _ipdltest {
rpc protocol PTestNestedLoops {
child:
async Start();
rpc R();
__delete__();
parent:
async Nonce();
state START:
send Start goto RACE;
state RACE:
recv Nonce goto RACE1;
call R goto RACE2;
state RACE1:
call R goto DEAD;
state RACE2:
recv Nonce goto DEAD;
state DEAD:
send __delete__;
};
} // namespace mozilla
} // namespace _ipdltest

View File

@ -0,0 +1,106 @@
#include "base/basictypes.h"
#include "nsThreadUtils.h"
#include "TestNestedLoops.h"
#include "IPDLUnitTests.h" // fail etc.
template<>
struct RunnableMethodTraits<mozilla::_ipdltest::TestNestedLoopsParent>
{
static void RetainCallee(mozilla::_ipdltest::TestNestedLoopsParent* obj) { }
static void ReleaseCallee(mozilla::_ipdltest::TestNestedLoopsParent* obj) { }
};
namespace mozilla {
namespace _ipdltest {
//-----------------------------------------------------------------------------
// parent
TestNestedLoopsParent::TestNestedLoopsParent() : mBreakNestedLoop(false)
{
MOZ_COUNT_CTOR(TestNestedLoopsParent);
}
TestNestedLoopsParent::~TestNestedLoopsParent()
{
MOZ_COUNT_DTOR(TestNestedLoopsParent);
}
void
TestNestedLoopsParent::Main()
{
if (!SendStart())
fail("sending Start");
// sigh ... spin for a while to let Nonce arrive
puts(" (sleeping to wait for nonce ... sorry)");
PR_Sleep(5000);
// while waiting for the reply to R, we'll receive Nonce
if (!CallR())
fail("calling R");
Close();
}
bool
TestNestedLoopsParent::RecvNonce()
{
// if we have an OnMaybeDequeueOne waiting for us (we may not, due
// to the inherent race condition in this test, then this event
// must be ordered after it in the queue
MessageLoop::current()->PostTask(
FROM_HERE,
NewRunnableMethod(this, &TestNestedLoopsParent::BreakNestedLoop));
// sigh ... spin for a while to let the reply to R arrive
puts(" (sleeping to wait for reply to R ... sorry)");
PR_Sleep(5000);
// sigh ... we have no idea when code might do this
do {
if (!NS_ProcessNextEvent(nsnull, PR_FALSE))
fail("expected at least one pending event");
} while (!mBreakNestedLoop);
return true;
}
void
TestNestedLoopsParent::BreakNestedLoop()
{
mBreakNestedLoop = true;
}
//-----------------------------------------------------------------------------
// child
TestNestedLoopsChild::TestNestedLoopsChild()
{
MOZ_COUNT_CTOR(TestNestedLoopsChild);
}
TestNestedLoopsChild::~TestNestedLoopsChild()
{
MOZ_COUNT_DTOR(TestNestedLoopsChild);
}
bool
TestNestedLoopsChild::RecvStart()
{
if (!SendNonce())
fail("sending Nonce");
return true;
}
bool
TestNestedLoopsChild::AnswerR()
{
return true;
}
} // namespace _ipdltest
} // namespace mozilla

View File

@ -0,0 +1,69 @@
#ifndef mozilla__ipdltest_TestNestedLoops_h
#define mozilla__ipdltest_TestNestedLoops_h 1
#include "mozilla/_ipdltest/IPDLUnitTests.h"
#include "mozilla/_ipdltest/PTestNestedLoopsParent.h"
#include "mozilla/_ipdltest/PTestNestedLoopsChild.h"
namespace mozilla {
namespace _ipdltest {
class TestNestedLoopsParent :
public PTestNestedLoopsParent
{
public:
TestNestedLoopsParent();
virtual ~TestNestedLoopsParent();
void Main();
protected:
NS_OVERRIDE
virtual bool RecvNonce();
void BreakNestedLoop();
NS_OVERRIDE
virtual void ActorDestroy(ActorDestroyReason why)
{
if (NormalShutdown != why)
fail("unexpected destruction!");
passed("ok");
QuitParent();
}
bool mBreakNestedLoop;
};
class TestNestedLoopsChild :
public PTestNestedLoopsChild
{
public:
TestNestedLoopsChild();
virtual ~TestNestedLoopsChild();
protected:
NS_OVERRIDE
virtual bool RecvStart();
NS_OVERRIDE
virtual bool AnswerR();
NS_OVERRIDE
virtual void ActorDestroy(ActorDestroyReason why)
{
if (NormalShutdown != why)
fail("unexpected destruction!");
QuitChild();
}
};
} // namespace _ipdltest
} // namespace mozilla
#endif // ifndef mozilla__ipdltest_TestNestedLoops_h

View File

@ -14,6 +14,7 @@ IPDLSRCS = \
PTestMultiMgrsLeft.ipdl \
PTestMultiMgrsRight.ipdl \
PTestMultiMgrsBottom.ipdl \
PTestNestedLoops.ipdl \
PTestRacyRPCReplies.ipdl \
PTestRPCErrorCleanup.ipdl \
PTestRPCRaces.ipdl \

View File

@ -48,7 +48,8 @@
*/
const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished";
const MAX_WAIT_SECONDS = 3;
const MAX_WAIT_SECONDS = 4;
const INTERVAL_CUSHION = 2;
let os = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
@ -107,7 +108,8 @@ function run_next_test() {
};
os.addObserver(gCurrentTest.observer, TOPIC_EXPIRATION_FINISHED, false);
setInterval(gCurrentTest.interval);
let waitSeconds = Math.min(MAX_WAIT_SECONDS, gCurrentTest.interval + 1);
let waitSeconds = Math.min(MAX_WAIT_SECONDS,
gCurrentTest.interval + INTERVAL_CUSHION);
do_timeout(waitSeconds * 1000, check_result);
}
else {

View File

@ -1418,13 +1418,22 @@ SetRemoteExceptionHandler()
bool
GetMinidumpForChild(PRUint32 childPid, nsIFile** dump)
TakeMinidumpForChild(PRUint32 childPid, nsIFile** dump)
{
if (!GetEnabled())
return false;
MutexAutoLock lock(*dumpMapLock);
return pidToMinidump->Get(childPid, dump);
nsCOMPtr<nsIFile> d;
bool found = pidToMinidump->Get(childPid, getter_AddRefs(d));
if (found)
pidToMinidump->Remove(childPid);
*dump = NULL;
d.swap(*dump);
return found;
}
bool

View File

@ -77,8 +77,9 @@ nsresult SetSubmitReports(PRBool aSubmitReport);
// Out-of-process crash reporter API.
// Return true iff a dump was found for |childPid|, and return the
// path in |dump|.
bool GetMinidumpForChild(PRUint32 childPid, nsIFile** dump NS_OUTPARAM);
// path in |dump|. The caller owns the last reference to |dump| if it
// is non-NULL.
bool TakeMinidumpForChild(PRUint32 childPid, nsIFile** dump NS_OUTPARAM);
# if defined(XP_WIN32)
// Parent-side API for children

View File

@ -1,376 +0,0 @@
/* -*- Mode: JavaScript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=2 sts=2 et filetype=javascript
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Windows Download Taskbar Progress.
*
* The Initial Developer of the Original Code is
* Siddharth Agarwal <sid.bugzilla@gmail.com>
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
let EXPORTED_SYMBOLS = [
"DownloadTaskbarProgress",
];
////////////////////////////////////////////////////////////////////////////////
//// Constants
const Cc = Components.classes;
const Ci = Components.interfaces;
const kTaskbarID = "@mozilla.org/windows-taskbar;1";
////////////////////////////////////////////////////////////////////////////////
//// DownloadTaskbarProgress Object
const DownloadTaskbarProgress =
{
/**
* Called when a browser window appears. This has an effect only when we
* don't already have an active window.
*
* @param aWindow
* The browser window that we'll potentially use to display the
* progress.
*/
onBrowserWindowLoad: function DTP_onBrowserWindowLoad(aWindow)
{
if (!DownloadTaskbarProgressUpdater) {
return;
}
if (!DownloadTaskbarProgressUpdater._activeTaskbarProgress) {
DownloadTaskbarProgressUpdater._setActiveWindow(aWindow, false);
}
},
/**
* Called when the download window appears. The download window will take
* over as the active window.
*/
onDownloadWindowLoad: function DTP_onDownloadWindowLoad(aWindow)
{
if (!DownloadTaskbarProgressUpdater) {
return;
}
DownloadTaskbarProgressUpdater._setActiveWindow(aWindow, true);
},
/**
* Getters for internal DownloadTaskbarProgressUpdater values
*/
get activeTaskbarProgress() {
if (!DownloadTaskbarProgressUpdater) {
return null;
}
return DownloadTaskbarProgressUpdater._activeTaskbarProgress;
},
get activeWindowIsDownloadWindow() {
if (!DownloadTaskbarProgressUpdater) {
return null;
}
return DownloadTaskbarProgressUpdater._activeWindowIsDownloadWindow;
},
get taskbarState() {
if (!DownloadTaskbarProgressUpdater) {
return null;
}
return DownloadTaskbarProgressUpdater._taskbarState;
},
};
////////////////////////////////////////////////////////////////////////////////
//// DownloadTaskbarProgressUpdater Object
var DownloadTaskbarProgressUpdater =
{
/// Reference to the taskbar.
_taskbar: null,
/// Reference to the download manager.
_dm: null,
/**
* Initialize and register ourselves as a download progress listener.
*/
_init: function DTPU_init()
{
if (!(kTaskbarID in Cc)) {
// This means that the component isn't available
DownloadTaskbarProgressUpdater = null;
return;
}
this._taskbar = Cc[kTaskbarID].getService(Ci.nsIWinTaskbar);
if (!this._taskbar.available) {
// The Windows version is probably too old
DownloadTaskbarProgressUpdater = null;
return;
}
this._dm = Cc["@mozilla.org/download-manager;1"].
getService(Ci.nsIDownloadManager);
this._dm.addListener(this);
this._updateStatus();
// onBrowserWindowLoad/onDownloadWindowLoad are going to set the active
// window, so don't do it here.
},
/**
* This holds a reference to the taskbar progress for the window we're
* working with. This window would preferably be download window, but can be
* another window if it isn't open.
*/
_activeTaskbarProgress: null,
/// Whether the active window is the download window
_activeWindowIsDownloadWindow: false,
/**
* Sets the active window, and whether it's the download window. This takes
* care of clearing out the previous active window's taskbar item, updating
* the taskbar, and setting an onunload listener.
*
* @param aWindow
* The window to set as active.
* @param aIsDownloadWindow
* Whether this window is a download window.
*/
_setActiveWindow: function DTPU_setActiveWindow(aWindow, aIsDownloadWindow)
{
// Clear out the taskbar for the old active window. (If there was no active
// window, this is a no-op.)
this._clearTaskbar();
this._activeWindowIsDownloadWindow = aIsDownloadWindow;
if (aWindow) {
// Get the taskbar progress for this window
let docShell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIWebNavigation).
QueryInterface(Ci.nsIDocShellTreeItem).treeOwner.
QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIXULWindow).docShell;
let taskbarProgress = this._taskbar.getTaskbarProgress(docShell);
this._activeTaskbarProgress = taskbarProgress;
this._updateTaskbar();
// _onActiveWindowUnload is idempotent, so we don't need to check whether
// we've already set this before or not.
aWindow.addEventListener("unload", function () {
DownloadTaskbarProgressUpdater._onActiveWindowUnload(taskbarProgress);
}, false);
}
else {
this._activeTaskbarProgress = null;
}
},
/// Current state displayed on the active window's taskbar item
_taskbarState: Ci.nsITaskbarProgress.STATE_NO_PROGRESS,
_totalSize: 0,
_totalTransferred: 0,
/**
* Update the active window's taskbar indicator with the current state. There
* are two cases here:
* 1. If the active window is the download window, then we always update
* the taskbar indicator.
* 2. If the active window isn't the download window, then we update only if
* the status is Normal, i.e. one or more downloads are currently
* progressing. If we aren't, then we clear the indicator.
*/
_updateTaskbar: function DTPU_updateTaskbar()
{
if (!this._activeTaskbarProgress) {
return;
}
// If the active window is not the download manager window, set the state
// only if it is Normal
if (this._activeWindowIsDownloadWindow ||
(this._taskbarState == Ci.nsITaskbarProgress.STATE_NORMAL)) {
this._activeTaskbarProgress.setProgressState(this._taskbarState,
this._totalTransferred,
this._totalSize);
}
// Clear any state otherwise
else {
this._clearTaskbar();
}
},
/**
* Clear taskbar state. This is needed:
* - to transfer the indicator off a window before transferring it onto
* another one
* - whenever we don't want to show it for a non-download window.
*/
_clearTaskbar: function DTPU_clearTaskbar()
{
if (this._activeTaskbarProgress) {
this._activeTaskbarProgress.setProgressState(
Ci.nsITaskbarProgress.STATE_NO_PROGRESS
);
}
},
/**
* Update this._taskbarState, this._totalSize and this._totalTransferred.
* This is called when the download manager is initialized or when the
* progress or state of a download changes.
* We compute the number of active and paused downloads, and the total size
* and total amount already transferred across whichever downloads we have
* the data for.
* - If there are no active downloads, then we don't want to show any
* progress.
* - If the number of active downloads is equal to the number of paused
* downloads, then we show a paused indicator if we know the size of at
* least one download, and no indicator if we don't.
* - If the number of active downloads is more than the number of paused
* downloads, then we show a "normal" indicator if we know the size of at
* least one download, and an indeterminate indicator if we don't.
*/
_updateStatus: function DTPU_updateStatus()
{
let numActive = this._dm.activeDownloadCount;
let totalSize = 0, totalTransferred = 0;
if (numActive == 0) {
this._taskbarState = Ci.nsITaskbarProgress.STATE_NO_PROGRESS;
}
else {
let numPaused = 0;
// Enumerate all active downloads
let downloads = this._dm.activeDownloads;
while (downloads.hasMoreElements()) {
let download = downloads.getNext().QueryInterface(Ci.nsIDownload);
// Only set values if we actually know the download size
if (download.percentComplete < 100 && download.size > 0) {
totalSize += download.size;
totalTransferred += download.amountTransferred;
}
// We might need to display a paused state, so track this
if (download.state == this._dm.DOWNLOAD_PAUSED) {
numPaused++;
}
}
// If all downloads are paused, show the progress as paused, unless we
// don't have any information about sizes, in which case we don't
// display anything
if (numActive == numPaused) {
if (totalSize == 0) {
this._taskbarState = Ci.nsITaskbarProgress.STATE_NO_PROGRESS;
totalTransferred = 0;
}
else {
this._taskbarState = Ci.nsITaskbarProgress.STATE_PAUSED;
}
}
// If at least one download is not paused, and we don't have any
// information about download sizes, display an indeterminate indicator
else if (totalSize == 0) {
this._taskbarState = Ci.nsITaskbarProgress.STATE_INDETERMINATE;
totalTransferred = 0;
}
// Otherwise display a normal progress bar
else {
this._taskbarState = Ci.nsITaskbarProgress.STATE_NORMAL;
}
}
this._totalSize = totalSize;
this._totalTransferred = totalTransferred;
},
/**
* Called when a window that at one point has been an active window is
* closed. If this window is currently the active window, we need to look for
* another window and make that our active window.
*
* This function is idempotent, so multiple calls for the same window are not
* a problem.
*
* @param aTaskbarProgress
* The taskbar progress for the window that is being unloaded.
*/
_onActiveWindowUnload: function DTPU_onActiveWindowUnload(aTaskbarProgress)
{
if (this._activeTaskbarProgress == aTaskbarProgress) {
let windowMediator = Cc["@mozilla.org/appshell/window-mediator;1"].
getService(Ci.nsIWindowMediator);
let windows = windowMediator.getEnumerator(null);
let newActiveWindow = null;
if (windows.hasMoreElements()) {
newActiveWindow = windows.getNext().QueryInterface(Ci.nsIDOMWindow);
}
// We aren't ever going to reach this point while the download manager is
// open, so it's safe to assume false for the second operand
this._setActiveWindow(newActiveWindow, false);
}
},
//////////////////////////////////////////////////////////////////////////////
//// nsIDownloadProgressListener
/**
* Update status if a download's progress has changed.
*/
onProgressChange: function DTPU_onProgressChange()
{
this._updateStatus();
this._updateTaskbar();
},
/**
* Update status if a download's state has changed.
*/
onDownloadStateChange: function DTPU_onDownloadStateChange()
{
this._updateStatus();
this._updateTaskbar();
},
onSecurityChange: function() { },
onStateChange: function() { },
};
////////////////////////////////////////////////////////////////////////////////
//// Initialization
DownloadTaskbarProgressUpdater._init();

View File

@ -51,12 +51,6 @@ EXTRA_JS_MODULES = \
DownloadUtils.jsm \
$(NULL)
ifeq ($(OS_ARCH),WINNT)
EXTRA_JS_MODULES += \
DownloadTaskbarProgress.jsm \
$(NULL)
endif
ifdef ENABLE_TESTS
DIRS += tests
endif

View File

@ -484,14 +484,6 @@ function Startup()
e.preventDefault();
}
}, false);
#ifdef XP_WIN
#ifndef WINCE
let tempScope = {};
Cu.import("resource://gre/modules/DownloadTaskbarProgress.jsm", tempScope);
tempScope.DownloadTaskbarProgress.onDownloadWindowLoad(window);
#endif
#endif
}
function Shutdown()

View File

@ -82,18 +82,5 @@ _CHROME_FILES += \
$(NULL)
endif
ifeq ($(OS_ARCH),WINNT)
_CHROME_FILES += \
test_taskbarprogress_downloadstates.xul \
$(NULL)
_BROWSER_FILES = \
browser_taskbarprogress_service.js \
$(NULL)
libs:: $(_BROWSER_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
endif
libs:: $(_CHROME_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)

View File

@ -1,147 +0,0 @@
const Cc = Components.classes;
const Ci = Components.interfaces;
const kTaskbarID = "@mozilla.org/windows-taskbar;1";
const DOWNLOAD_MANAGER_URL = "chrome://mozapps/content/downloads/downloads.xul";
const DLMGR_UI_DONE = "download-manager-ui-done";
let DownloadTaskbarProgress, TaskbarService, observerService, wwatch;
let gGen = null;
function test() {
gGen = doTest();
gGen.next();
}
function continueTest() {
gGen.next();
}
function doTest() {
let isWin7OrHigher = false;
try {
let version = Cc["@mozilla.org/system-info;1"]
.getService(Ci.nsIPropertyBag2)
.getProperty("version");
isWin7OrHigher = (parseFloat(version) >= 6.1);
} catch (ex) { }
is(!!Win7Features, isWin7OrHigher, "Win7Features available when it should be");
if (!isWin7OrHigher) {
return;
}
waitForExplicitFinish();
let tempScope = {};
Cu.import("resource://gre/modules/DownloadTaskbarProgress.jsm", tempScope);
DownloadTaskbarProgress = tempScope.DownloadTaskbarProgress;
TaskbarService = Cc[kTaskbarID].getService(Ci.nsIWinTaskbar);
observerService = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
wwatch = Cc["@mozilla.org/embedcomp/window-watcher;1"].
getService(Ci.nsIWindowWatcher);
isnot(DownloadTaskbarProgress, null, "Download taskbar progress service exists");
is(TaskbarService.available, true, "Taskbar Service is available");
//Manually call onBrowserWindowLoad because this is delayed in 10sec
DownloadTaskbarProgress.onBrowserWindowLoad(window);
is(DownloadTaskbarProgress.activeWindowIsDownloadWindow, false,
"DownloadTaskbarProgress window is not the Download window");
checkActiveTaskbar(false, window);
openDownloadManager(continueTest);
yield;
let DMWindow = Cc["@mozilla.org/appshell/window-mediator;1"].
getService(Ci.nsIWindowMediator).
getMostRecentWindow("Download:Manager");
ok(DMWindow, "Download Manager window was opened");
checkActiveTaskbar(true, DMWindow);
DMWindow.close();
setTimeout(continueTest, 100);
yield;
checkActiveTaskbar(false, window);
let browserWindow = openBrowserWindow(continueTest);
yield;
ok(browserWindow, "Browser window was opened");
DownloadTaskbarProgress.onBrowserWindowLoad(browserWindow);
// The owner window should not have changed, since our
// original window still exists
checkActiveTaskbar(false, window);
browserWindow.close();
finish();
}
function checkActiveTaskbar(isDownloadManager, ownerWindow) {
isnot(DownloadTaskbarProgress.activeTaskbarProgress, null, "DownloadTaskbarProgress has an active taskbar");
is(DownloadTaskbarProgress.activeWindowIsDownloadWindow, isDownloadManager,
"The active taskbar progress " + (isDownloadManager ? "is" : "is not") + " the Download Manager");
if (ownerWindow) {
let ownerWindowDocShell = ownerWindow.QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIWebNavigation).
QueryInterface(Ci.nsIDocShellTreeItem).treeOwner.
QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIXULWindow).docShell;
let windowTaskbarProgress = TaskbarService.getTaskbarProgress(ownerWindowDocShell);
is(DownloadTaskbarProgress.activeTaskbarProgress, windowTaskbarProgress,
"DownloadTaskbarProgress has the expected taskbar as active");
}
}
function openBrowserWindow(callback) {
let blank = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
blank.data = "about:blank";
browserWindow = wwatch.openWindow(null, "chrome://browser/content/",
"_blank", "chrome,dialog=no", blank);
let helperFunc = function() {
callback();
browserWindow.removeEventListener("load", helperFunc, false);
}
browserWindow.addEventListener("load", helperFunc, false);
return browserWindow;
}
function openDownloadManager(callback) {
let testObs = {
observe: function(aSubject, aTopic, aData) {
if (aTopic != DLMGR_UI_DONE) {
return;
}
callback();
observerService.removeObserver(testObs, DLMGR_UI_DONE);
}
};
observerService.addObserver(testObs, DLMGR_UI_DONE, false);
Cc["@mozilla.org/download-manager-ui;1"].
getService(Ci.nsIDownloadManagerUI).show();
}

View File

@ -1,276 +0,0 @@
<?xml version="1.0"?>
<!--
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Windows Download Taskbar Progress.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Felipe Gomes <felipc@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/**
* This tests that the Windows 7 Taskbar Progress is correctly updated when
* the download state changes.
*/
-->
<window title="Win7 Taskbar Progress"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="test();">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"/>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
<script type="application/javascript"
src="chrome://mochikit/content/chrome/toolkit/mozapps/downloads/tests/chrome/utils.js"/>
<script type="application/javascript">
<![CDATA[
const kTaskbarID = "@mozilla.org/windows-taskbar;1";
const DOWNLOAD_MANAGER_URL = "chrome://mozapps/content/downloads/downloads.xul";
const DLMGR_UI_DONE = "download-manager-ui-done";
const Cu = Components.utils;
const nsITP = Ci.nsITaskbarProgress;
let DownloadTaskbarProgress, dm;
let downloadA, downloadB, gGen;
let testState = {
activeDownloadCount: 0,
pausedDownloadCount: 0,
regularStateTested: false,
pausedStateTested: false,
noDownloadsStateTested: false
}
function continueTest() {
setTimeout(function() {
gGen.next();
}, 10);
}
function downloadListener()
{
this.wasPaused = false;
}
downloadListener.prototype = {
onStateChange: function(a, b, c, d, e) {
checkCorrectState();
},
onDownloadStateChange: function(aState, aDownload)
{
if (aDownload.state == Ci.nsIDownloadManager.DOWNLOAD_PAUSED) {
testState.pausedDownloadCount++;
testState.activeDownloadCount--;
if (aDownload == downloadB) {
continueTest();
}
}
if (aDownload.state == Ci.nsIDownloadManager.DOWNLOAD_FINISHED) {
testState.activeDownloadCount--;
aDownload.targetFile.remove(false);
setTimeout(function(){
//Check when download finishes too
checkCorrectState();
if(testState.activeDownloadCount == 0) {
finishTest();
}
},10);
}
if (aDownload.state == Ci.nsIDownloadManager.DOWNLOAD_DOWNLOADING) {
//when DownloadB is added, begin pausing phase
if (aDownload == downloadB && !this.wasPaused) {
this.wasPaused = true;
continueTest();
}
}
},
onProgressChange: function(a, b, c, d, e, f, g) { },
onSecurityChange: function(a, b, c, d) { }
};
function testSteps() {
// Step 1 - Add downloads
testState.activeDownloadCount++;
downloadA = addDownload();
testState.activeDownloadCount++;
downloadB = addDownload();
yield;
// Step 2 - Pause downloads
dm.pauseDownload(downloadA.id);
continueTest();
yield;
dm.pauseDownload(downloadB.id);
yield;
// Step 3 - Resume downloads
testState.activeDownloadCount++;
testState.pausedDownloadCount--;
dm.resumeDownload(downloadA.id);
testState.activeDownloadCount++;
testState.pausedDownloadCount--;
dm.resumeDownload(downloadB.id);
yield;
}
function finishTest() {
ok(testState.regularStateTested, "Tests went through regular download state");
ok(testState.pausedStateTested, "Tests went through paused download state");
ok(testState.noDownloadsStateTested, "Tests went through finished downloads state");
dm.removeListener(downloadListener);
SimpleTest.finish();
}
function checkCorrectState() {
if(testState.activeDownloadCount < 0 || testState.pausedDownloadCount < 0) {
ok(false, "There shouldn't be negative download counts");
SimpleTest.finish();
}
let taskbarState = DownloadTaskbarProgress.taskbarState;
if (testState.activeDownloadCount) {
//There's at least one active download
ok(taskbarState == nsITP.STATE_NORMAL || taskbarState == nsITP.STATE_INDETERMINATE, "Correct downloading state");
testState.regularStateTested = true;
} else if (testState.pausedDownloadCount) {
//There are no active downloads but there are paused ones
ok(taskbarState == nsITP.STATE_PAUSED, "Correct paused state");
testState.pausedStateTested = true;
} else {
//No more downloads
ok(taskbarState == nsITP.STATE_NO_PROGRESS, "Correct finished downloads state");
testState.noDownloadsStateTested = true;
}
}
function test() {
SimpleTest.waitForExplicitFinish();
testSetup();
}
function testSetup()
{
//Test setup
let dmui = getDMUI();
if (!dmui) {
todo(false, "skip test for toolkit download manager UI");
return;
}
let isWin7OrHigher = false;
try {
let version = Cc["@mozilla.org/system-info;1"]
.getService(Ci.nsIPropertyBag2)
.getProperty("version");
isWin7OrHigher = (parseFloat(version) >= 6.1);
} catch (ex) { }
if (!isWin7OrHigher) {
return;
}
let tempScope = {};
Cu.import("resource://gre/modules/DownloadTaskbarProgress.jsm", tempScope);
Cu.import("resource://gre/modules/Services.jsm");
DownloadTaskbarProgress = tempScope.DownloadTaskbarProgress;
let TaskbarService = Cc[kTaskbarID].getService(Ci.nsIWinTaskbar);
isnot(DownloadTaskbarProgress, null, "Download taskbar progress service exists");
is(TaskbarService.available, true, "Taskbar Service is available");
dm = Cc["@mozilla.org/download-manager;1"].
getService(Ci.nsIDownloadManager);
// First, we clear out the database
dm.DBConnection.executeSimpleSQL("DELETE FROM moz_downloads");
// See if the DM is already open, and if it is, close it!
let win = Services.wm.getMostRecentWindow("Download:Manager");
if (win) {
win.close();
}
let os = Services.obs;
const DLMGR_UI_DONE = "download-manager-ui-done";
gGen = testSteps();
dm.addListener(new downloadListener());
let testObs = {
observe: function(aSubject, aTopic, aData)
{
if (aTopic != DLMGR_UI_DONE) {
return;
}
os.removeObserver(testObs, DLMGR_UI_DONE);
continueTest();
}
};
// Register with the observer service
os.addObserver(testObs, DLMGR_UI_DONE, false);
// Show the Download Manager UI
dmui.show();
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display:none;"></div>
<pre id="test"></pre>
</body>
</window>

View File

@ -266,9 +266,9 @@ static MessageLoop* sIOMessageLoop;
// IPDL wants access to this crashreporter interface, and
// crashreporter is built in such a way to make that awkward
PRBool
XRE_GetMinidumpForChild(PRUint32 aChildPid, nsIFile** aDump)
XRE_TakeMinidumpForChild(PRUint32 aChildPid, nsIFile** aDump)
{
return CrashReporter::GetMinidumpForChild(aChildPid, aDump);
return CrashReporter::TakeMinidumpForChild(aChildPid, aDump);
}
PRBool

View File

@ -79,6 +79,7 @@ CPPSRCS = \
nsImageToPixbuf.cpp \
nsAccessibilityHelper.cpp \
nsAccelerometerUnix.cpp \
nsGtkIMModule.cpp \
$(NULL)
ifdef MOZ_X11
@ -152,7 +153,6 @@ CXXFLAGS += $(MOZ_GCONF_CFLAGS)
endif
endif
DEFINES += -DUSE_XIM
DEFINES += -DCAIRO_GFX
ifdef MOZ_ENABLE_POSTSCRIPT

View File

@ -51,7 +51,6 @@
#ifdef PR_LOGGING
PRLogModuleInfo *gWidgetLog = nsnull;
PRLogModuleInfo *gWidgetFocusLog = nsnull;
PRLogModuleInfo *gWidgetIMLog = nsnull;
PRLogModuleInfo *gWidgetDragLog = nsnull;
PRLogModuleInfo *gWidgetDrawLog = nsnull;
#endif
@ -89,8 +88,6 @@ nsAppShell::Init()
gWidgetLog = PR_NewLogModule("Widget");
if (!gWidgetFocusLog)
gWidgetFocusLog = PR_NewLogModule("WidgetFocus");
if (!gWidgetIMLog)
gWidgetIMLog = PR_NewLogModule("WidgetIM");
if (!gWidgetDragLog)
gWidgetDragLog = PR_NewLogModule("WidgetDrag");
if (!gWidgetDrawLog)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,282 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim:expandtab:shiftwidth=4:tabstop=4:
*/
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Christopher Blizzard
* <blizzard@mozilla.org>. Portions created by the Initial Developer
* are Copyright (C) 2001 the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Masayuki Nakano <masayuki@d-toybox.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef __nsGtkIMModule_h__
#define __nsGtkIMModule_h__
#include <gdk/gdk.h>
#include <gtk/gtk.h>
#include "nsString.h"
#include "nsAutoPtr.h"
#include "nsTArray.h"
#include "nsGUIEvent.h"
// If software keyboard is needed in password field and uses GTK2 IM module
// for inputting characters, we need to enable IME in password field too.
#ifdef MOZ_PLATFORM_MAEMO
#define NS_IME_ENABLED_ON_PASSWORD_FIELD 1
#endif
class nsWindow;
class nsGtkIMModule
{
public:
nsrefcnt AddRef()
{
NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "mRefCnt is negative");
++mRefCnt;
NS_LOG_ADDREF(this, mRefCnt, "nsGtkIMModule", sizeof(*this));
return mRefCnt;
}
nsrefcnt Release()
{
NS_PRECONDITION(mRefCnt != 0, "mRefCnt is alrady zero");
--mRefCnt;
NS_LOG_RELEASE(this, mRefCnt, "nsGtkIMModule");
if (mRefCnt == 0) {
mRefCnt = 1; /* stabilize */
NS_DELETEXPCOM(this);
return 0;
}
return mRefCnt;
}
protected:
nsAutoRefCnt mRefCnt;
public:
// aOwnerWindow is a pointer of the owner window. When aOwnerWindow is
// destroyed, the related IME contexts are released (i.e., IME cannot be
// used with the instance after that).
nsGtkIMModule(nsWindow* aOwnerWindow);
~nsGtkIMModule();
// OnFocusWindow is a notification that aWindow is going to be focused.
void OnFocusWindow(nsWindow* aWindow);
// OnBlurWindow is a notification that aWindow is going to be unfocused.
void OnBlurWindow(nsWindow* aWindow);
// OnDestroyWindow is a notification that aWindow is going to be destroyed.
void OnDestroyWindow(nsWindow* aWindow);
// OnFocusChangeInGecko is a notification that an editor gets focus.
void OnFocusChangeInGecko(PRBool aFocus);
// OnKeyEvent is called when aWindow gets a native key press event or a
// native key release event. If this returns TRUE, the key event was
// filtered by IME. Otherwise, this returns FALSE.
// NOTE: When the keypress event starts composition, this returns TRUE but
// this dispatches keydown event before compositionstart event.
PRBool OnKeyEvent(nsWindow* aWindow, GdkEventKey* aEvent);
// IME related nsIWidget methods.
nsresult ResetInputState(nsWindow* aCaller);
nsresult SetIMEEnabled(nsWindow* aCaller, PRUint32 aState);
nsresult GetIMEEnabled(PRUint32* aState);
nsresult CancelIMEComposition(nsWindow* aCaller);
// If a software keyboard has been opened, this returns TRUE.
// Otherwise, FALSE.
static PRBool IsVirtualKeyboardOpened();
protected:
// Owner of an instance of this class. This should be top level window.
// The owner window must release the contexts when it's destroyed because
// the IME contexts need the native window. If OnDestroyWindow() is called
// with the owner window, it'll release IME contexts. Otherwise, it'll
// just clean up any existing composition if it's related to the destroying
// child window.
nsWindow* mOwnerWindow;
// A last focused window in this class's context.
nsWindow* mLastFocusedWindow;
// Actual context. This is used for handling the user's input.
GtkIMContext *mContext;
#ifndef NS_IME_ENABLED_ON_PASSWORD_FIELD
// mSimpleContext is used for the password field and
// the |ime-mode: disabled;| editors. These editors disable IME.
// But dead keys should work. Fortunately, the simple IM context of
// GTK2 support only them.
GtkIMContext *mSimpleContext;
#endif // NS_IME_ENABLED_ON_PASSWORD_FIELD
// mDummyContext is a dummy context and will be used in Focus()
// when the state of mEnabled means disabled. This context's IME state is
// always "closed", so it closes IME forcedly.
GtkIMContext *mDummyContext;
// IME enabled state in this window. The values is nsIWidget::IME_STATUS_*.
// Use following helper methods if you don't need the detail of the status.
PRUint32 mEnabled;
// mCompositionStart is the start offset of the composition string in the
// current content. When <textarea> or <input> have focus, it means offset
// from the first character of them. When a HTML editor has focus, it
// means offset from the first character of the root element of the editor.
PRUint32 mCompositionStart;
// mCompositionString is the current composing string. Even if this is
// empty, we can be composing. See mIsComposing.
nsString mCompositionString;
// OnKeyEvent() temporarily sets mProcessingKeyEvent to the given native
// event.
GdkEventKey* mProcessingKeyEvent;
// mIsComposing is set to TRUE when we dispatch the composition start
// event. And it's set to FALSE when we dispatches the composition end
// event. Note that mCompositionString can be empty string even if this is
// TRUE.
PRPackedBool mIsComposing;
// mIsIMFocused is set to TRUE when we call gtk_im_context_focus_in(). And
// it's set to FALSE when we call gtk_im_context_focus_out().
PRPackedBool mIsIMFocused;
// mFilterKeyEvent is used by OnKeyEvent(). If the commit event should
// be processed as simple key event, this is set to TRUE by the commit
// handler.
PRPackedBool mFilterKeyEvent;
// When mIgnoreNativeCompositionEvent is TRUE, all native composition
// should be ignored except that the compositon should be restarted in
// another content (nsIContent). Don't refer this value directly, use
// ShouldIgnoreNativeCompositionEvent().
PRPackedBool mIgnoreNativeCompositionEvent;
// sLastFocusedModule is a pointer to the last focused instance of this
// class. When a instance is destroyed and sLastFocusedModule refers it,
// this is cleared. So, this refers valid pointer always.
static nsGtkIMModule* sLastFocusedModule;
// Callback methods for native IME events. These methods should call
// the related instance methods simply.
static void OnCommitCompositionCallback(GtkIMContext *aContext,
const gchar *aString,
nsGtkIMModule* aModule);
static void OnChangeCompositionCallback(GtkIMContext *aContext,
nsGtkIMModule* aModule);
static void OnStartCompositionCallback(GtkIMContext *aContext,
nsGtkIMModule* aModule);
static void OnEndCompositionCallback(GtkIMContext *aContext,
nsGtkIMModule* aModule);
// The instance methods for the native IME events.
void OnCommitCompositionNative(GtkIMContext *aContext,
const gchar *aString);
void OnChangeCompositionNative(GtkIMContext *aContext);
void OnStartCompositionNative(GtkIMContext *aContext);
void OnEndCompositionNative(GtkIMContext *aContext);
// GetContext() returns current IM context which is chosen by the enabled
// state. So, this means *current* IM context.
GtkIMContext* GetContext();
// "Enabled" means the users can use all IMEs.
// I.e., the focus is in the normal editors.
PRBool IsEnabled();
// "Editable" means the users can input characters. They may be not able to
// use IMEs but they can use dead keys.
// I.e., the focus is in the normal editors or the password editors or
// the |ime-mode: disabled;| editors.
PRBool IsEditable();
// If the owner window and IM context have been destroyed, returns TRUE.
PRBool IsDestroyed() { return !mOwnerWindow; }
// Sets focus to the instance of this class.
void Focus();
// Steals focus from the instance of this class.
void Blur();
// Initializes the instance.
void Init();
// Reset the current composition of IME. All native composition events
// during this processing are ignored.
void ResetIME();
// Gets the current composition string by the native APIs.
void GetCompositionString(nsAString &aCompositionString);
// Generates our text range list from current composition string.
void SetTextRangeList(nsTArray<nsTextRange> &aTextRangeList);
// Sets the offset's cursor position to IME.
void SetCursorPosition(PRUint32 aTargetOffset);
// Queries the current selection offset of the window.
PRUint32 GetSelectionOffset(nsWindow* aWindow);
// Initializes the GUI event.
void InitEvent(nsGUIEvent& aEvent);
// Called before destroying the context to work around some platform bugs.
void PrepareToDestroyContext(GtkIMContext *aContext);
PRBool ShouldIgnoreNativeCompositionEvent();
/**
* WARNING:
* Following methods dispatch gecko events. Then, the focused widget
* can be destroyed, and also it can be stolen focus. If they returns
* FALSE, callers cannot continue the composition.
* - CommitCompositionBy
* - DispatchCompositionStart
* - DispatchCompositionEnd
* - DispatchTextEvent
*/
// Commits the current composition by the aString.
PRBool CommitCompositionBy(const nsAString& aString);
// Dispatches a composition start event or a composition end event.
PRBool DispatchCompositionStart();
PRBool DispatchCompositionEnd();
// Dispatches a text event. If aCheckAttr is TRUE, dispatches a committed
// text event. Otherwise, dispatches a composing text event.
PRBool DispatchTextEvent(PRBool aCheckAttr);
};
#endif // __nsGtkIMModule_h__

File diff suppressed because it is too large Load Diff

View File

@ -81,15 +81,15 @@
#include "prlog.h"
#include "nsTArray.h"
#include "nsGtkIMModule.h"
extern PRLogModuleInfo *gWidgetLog;
extern PRLogModuleInfo *gWidgetFocusLog;
extern PRLogModuleInfo *gWidgetIMLog;
extern PRLogModuleInfo *gWidgetDragLog;
extern PRLogModuleInfo *gWidgetDrawLog;
#define LOG(args) PR_LOG(gWidgetLog, 4, args)
#define LOGFOCUS(args) PR_LOG(gWidgetFocusLog, 4, args)
#define LOGIM(args) PR_LOG(gWidgetIMLog, 4, args)
#define LOGDRAG(args) PR_LOG(gWidgetDragLog, 4, args)
#define LOGDRAW(args) PR_LOG(gWidgetDrawLog, 4, args)
@ -97,7 +97,6 @@ extern PRLogModuleInfo *gWidgetDrawLog;
#define LOG(args)
#define LOGFOCUS(args)
#define LOGIM(args)
#define LOGDRAG(args)
#define LOGDRAW(args)
@ -310,91 +309,22 @@ public:
NS_IMETHOD BeginResizeDrag (nsGUIEvent* aEvent, PRInt32 aHorizontal, PRInt32 aVertical);
#ifdef USE_XIM
void IMEInitData (void);
void IMEReleaseData (void);
void IMEDestroyContext (void);
void IMESetFocus (void);
void IMELoseFocus (void);
void IMEComposeStart (void);
void IMEComposeText (const PRUnichar *aText,
const PRInt32 aLen,
const gchar *aPreeditString,
const gint aCursorPos,
const PangoAttrList *aFeedback);
void IMEComposeEnd (void);
GtkIMContext* IMEGetContext (void);
// "Enabled" means the users can use all IMEs.
// I.e., the focus is in the normal editors.
PRBool IMEIsEnabledState (void);
// "Editable" means the users can input characters. They may be not able to
// use IMEs but they can use dead keys.
// I.e., the forcus is in the normal editors or the password editors or
// the |ime-mode: disabled;| editors.
PRBool IMEIsEditableState(void);
nsWindow* IMEComposingWindow(void);
void IMECreateContext (void);
PRBool IMEFilterEvent (GdkEventKey *aEvent);
void IMESetCursorPosition(const nsTextEventReply& aReply);
MozContainer* GetMozContainer() { return mContainer; }
GdkWindow* GetGdkWindow() { return mGdkWindow; }
PRBool IsDestroyed() { return mIsDestroyed; }
/*
* |mIMEData| has all IME data for the window and its children widgets.
* Only stand-alone windows and child windows embedded in non-Mozilla GTK
* containers own IME contexts.
* But this is referred from all children after the widget gets focus.
* The children refers to its owning window's object.
*/
struct nsIMEData {
// Actual context. This is used for handling the user's input.
GtkIMContext *mContext;
// mSimpleContext is used for the password field and
// the |ime-mode: disabled;| editors. These editors disable IME.
// But dead keys should work. Fortunately, the simple IM context of
// GTK2 support only them.
GtkIMContext *mSimpleContext;
// mDummyContext is a dummy context and will be used in IMESetFocus()
// when mEnabled is false. This mDummyContext IM state is always
// "off", so it works to switch conversion mode to OFF on IM status
// window.
GtkIMContext *mDummyContext;
// This mComposingWindow is set in IMEComposeStart(), when user starts
// composition, then unset in IMEComposeEnd() when user ends the
// composition. We will keep the widget where the actual composition is
// started. During the composition, we may get some events like
// ResetInputStateInternal() and CancelIMECompositionInternal() by
// changing input focus, we will use the original widget of
// mComposingWindow to commit or reset the composition.
nsWindow *mComposingWindow;
// Owner of this struct.
// The owner window must release the contexts at destroying.
nsWindow *mOwner;
// The reference counter. When this will be zero by the decrement,
// the decrementer must free the instance.
PRUint32 mRefCount;
// IME enabled state in this window.
PRUint32 mEnabled;
nsIMEData(nsWindow* aOwner) {
mContext = nsnull;
mSimpleContext = nsnull;
mDummyContext = nsnull;
mComposingWindow = nsnull;
mOwner = aOwner;
mRefCount = 1;
mEnabled = nsIWidget::IME_STATUS_ENABLED;
}
};
nsIMEData *mIMEData;
// If this dispatched the keydown event actually, this returns TRUE,
// otherwise, FALSE.
PRBool DispatchKeyDownEvent(GdkEventKey *aEvent,
PRBool *aIsCancelled);
NS_IMETHOD ResetInputState();
NS_IMETHOD SetIMEOpenState(PRBool aState);
NS_IMETHOD GetIMEOpenState(PRBool* aState);
NS_IMETHOD SetIMEEnabled(PRUint32 aState);
NS_IMETHOD GetIMEEnabled(PRUint32* aState);
NS_IMETHOD CancelIMEComposition();
NS_IMETHOD OnIMEFocusChange(PRBool aFocus);
NS_IMETHOD GetToggledKeyState(PRUint32 aKeyCode, PRBool* aLEDState);
#endif
void ResizeTransparencyBitmap(PRInt32 aNewWidth, PRInt32 aNewHeight);
void ApplyTransparencyBitmap();
virtual void SetTransparencyMode(nsTransparencyMode aMode);
@ -568,6 +498,20 @@ private:
*flag &= ~mask;
}
/**
* |mIMModule| takes all IME related stuff.
*
* This is owned by the top-level nsWindow or the topmost child
* nsWindow embedded in a non-Gecko widget.
*
* The instance is created when the top level widget is created. And when
* the widget is destroyed, it's released. All child windows refer its
* ancestor widget's instance. So, one set of IM contexts is created for
* all windows in a hierarchy. If the children are released after the top
* level window is released, the children still have a valid pointer,
* however, IME doesn't work at that time.
*/
nsRefPtr<nsGtkIMModule> mIMModule;
};
class nsChildWindow : public nsWindow {

View File

@ -65,7 +65,7 @@ ifdef MOZ_ENABLE_GTK2
CFLAGS += $(MOZ_GTK2_CFLAGS)
endif
DEFINES += -D_IMPL_GTKXTBIN_API -DUSE_XIM
DEFINES += -D_IMPL_GTKXTBIN_API
ifeq ($(OS_ARCH), OpenVMS)
DEFINES += -DGENERIC_MOTIF_REDEFINES

View File

@ -37,15 +37,13 @@
*
* ***** END LICENSE BLOCK ***** */
#include <QX11Info>
#include "nsIdleServiceQt.h"
#include "nsIServiceManager.h"
#include "nsDebug.h"
#include "prlink.h"
#ifdef Q_WS_X11
#include <QX11Info>
typedef PRBool (*_XScreenSaverQueryExtension_fn)(Display* dpy, int* event_base,
int* error_base);
@ -134,27 +132,3 @@ nsIdleServiceQt::GetIdleTime(PRUint32 *aTimeDiff)
return NS_ERROR_FAILURE;
}
#else
NS_IMPL_ISUPPORTS1(nsIdleServiceQt, nsIIdleService)
nsIdleServiceQt::nsIdleServiceQt()
{
}
static void Initialize()
{
}
nsIdleServiceQt::~nsIdleServiceQt()
{
}
NS_IMETHODIMP
nsIdleServiceQt::GetIdleTime(PRUint32 *aTimeDiff)
{
return NS_ERROR_FAILURE;
}
#endif

View File

@ -160,12 +160,10 @@ static const nsModuleComponentInfo components[] =
NS_BIDIKEYBOARD_CID,
"@mozilla.org/widget/bidikeyboard;1",
nsBidiKeyboardConstructor },
#ifdef Q_WS_X11
{ "Qt Idle Service",
NS_IDLE_SERVICE_CID,
"@mozilla.org/widget/idleservice;1",
nsIdleServiceQtConstructor },
#endif
{ "Qt Sound",
NS_SOUND_CID,
"@mozilla.org/sound;1",

View File

@ -550,6 +550,10 @@ nsWindow::SetSizeMode(PRInt32 aMode)
widget->showMinimized();
break;
case nsSizeMode_Fullscreen:
// Some versions of Qt (4.6.x) crash in XSetInputFocus due to
// unsynchronized window activation. Sync here to avoid such
// cases.
XSync(QX11Info().display(), False);
widget->showFullScreen();
break;
@ -767,14 +771,12 @@ nsWindow::GetNativeData(PRUint32 aDataType)
return SetupPluginPort();
break;
#ifdef Q_WS_X11
case NS_NATIVE_DISPLAY:
{
QWidget *widget = GetViewWidget();
return widget ? widget->x11Info().display() : nsnull;
}
break;
#endif
case NS_NATIVE_GRAPHIC: {
NS_ASSERTION(nsnull != mToolkit, "NULL toolkit, unable to get a GC");
@ -1772,7 +1774,6 @@ nsWindow::SetWindowClass(const nsAString &xulWinType)
nsXPIDLString brandName;
GetBrandName(brandName);
#ifdef Q_WS_X11
XClassHint *class_hint = XAllocClassHint();
if (!class_hint)
return NS_ERROR_OUT_OF_MEMORY;
@ -1814,7 +1815,6 @@ nsWindow::SetWindowClass(const nsAString &xulWinType)
nsMemory::Free(class_hint->res_class);
nsMemory::Free(class_hint->res_name);
XFree(class_hint);
#endif
return NS_OK;
}
@ -1931,12 +1931,10 @@ nsWindow::MakeFullScreen(PRBool aFullScreen)
mLastSizeMode = mSizeMode;
mSizeMode = nsSizeMode_Fullscreen;
#ifdef Q_WS_X11
// Some versions of Qt (4.6.x) crash in XSetInputFocus due to
// unsynchronized window activation. Sync here to avoid such
// cases.
XSync(QX11Info().display(), False);
#endif
widget->showFullScreen();
}
else {
@ -1992,11 +1990,9 @@ nsWindow::HideWindowChrome(PRBool aShouldHide)
// and flush the queue here so that we don't end up with a BadWindow
// error later when this happens (when the persistence timer fires
// and GetWindowPos is called)
#ifdef Q_WS_X11
QWidget *widget = GetViewWidget();
NS_ENSURE_TRUE(widget, NS_ERROR_FAILURE);
XSync(widget->x11Info().display(), False);
#endif
return NS_OK;
}

View File

@ -452,7 +452,7 @@ XRE_API(GeckoProcessType,
#if defined(MOZ_CRASHREPORTER)
// Used in the "master" parent process hosting the crash server
XRE_API(PRBool,
XRE_GetMinidumpForChild, (PRUint32 aChildPid, nsIFile** aDump))
XRE_TakeMinidumpForChild, (PRUint32 aChildPid, nsIFile** aDump))
// Used in child processes.
XRE_API(PRBool,