зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to s-c.
This commit is contained in:
Коммит
9f33dc8380
|
@ -35,47 +35,9 @@ AccEvent::AccEvent(uint32_t aEventType, Accessible* aAccessible,
|
|||
CaptureIsFromUserInput(aIsFromUserInput);
|
||||
}
|
||||
|
||||
AccEvent::AccEvent(uint32_t aEventType, nsINode* aNode,
|
||||
EIsFromUserInput aIsFromUserInput, EEventRule aEventRule) :
|
||||
mEventType(aEventType), mEventRule(aEventRule), mNode(aNode)
|
||||
{
|
||||
CaptureIsFromUserInput(aIsFromUserInput);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AccEvent public methods
|
||||
|
||||
Accessible*
|
||||
AccEvent::GetAccessible()
|
||||
{
|
||||
if (!mAccessible)
|
||||
mAccessible = GetAccessibleForNode();
|
||||
|
||||
return mAccessible;
|
||||
}
|
||||
|
||||
nsINode*
|
||||
AccEvent::GetNode()
|
||||
{
|
||||
if (!mNode && mAccessible)
|
||||
mNode = mAccessible->GetNode();
|
||||
|
||||
return mNode;
|
||||
}
|
||||
|
||||
DocAccessible*
|
||||
AccEvent::GetDocAccessible()
|
||||
{
|
||||
if (mAccessible)
|
||||
return mAccessible->Document();
|
||||
|
||||
nsINode* node = GetNode();
|
||||
if (node)
|
||||
return GetAccService()->GetDocAccessible(node->OwnerDoc());
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
already_AddRefed<nsAccEvent>
|
||||
AccEvent::CreateXPCOMObject()
|
||||
{
|
||||
|
@ -104,56 +66,23 @@ NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AccEvent, Release)
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AccEvent protected methods
|
||||
|
||||
Accessible*
|
||||
AccEvent::GetAccessibleForNode() const
|
||||
{
|
||||
if (mNode) {
|
||||
DocAccessible* document =
|
||||
GetAccService()->GetDocAccessible(mNode->OwnerDoc());
|
||||
if (document)
|
||||
return document->GetAccessible(mNode);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
AccEvent::CaptureIsFromUserInput(EIsFromUserInput aIsFromUserInput)
|
||||
{
|
||||
nsINode *targetNode = GetNode();
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!targetNode) {
|
||||
// XXX: remove this hack during reorganization of 506907. Meanwhile we
|
||||
// want to get rid an assertion for application accessible events which
|
||||
// don't have DOM node (see bug 506206).
|
||||
|
||||
if (mAccessible != static_cast<nsIAccessible*>(ApplicationAcc()))
|
||||
NS_ASSERTION(targetNode, "There should always be a DOM node for an event");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (aIsFromUserInput != eAutoDetect) {
|
||||
mIsFromUserInput = aIsFromUserInput == eFromUserInput ? true : false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!targetNode)
|
||||
return;
|
||||
|
||||
nsIPresShell *presShell = nsCoreUtils::GetPresShellFor(targetNode);
|
||||
if (!presShell) {
|
||||
NS_NOTREACHED("Threre should always be an pres shell for an event");
|
||||
DocAccessible* document = mAccessible->Document();
|
||||
if (!document) {
|
||||
NS_ASSERTION(mAccessible == ApplicationAcc(),
|
||||
"Accessible other than application should always have a doc!");
|
||||
return;
|
||||
}
|
||||
|
||||
nsEventStateManager *esm = presShell->GetPresContext()->EventStateManager();
|
||||
if (!esm) {
|
||||
NS_NOTREACHED("There should always be an ESM for an event");
|
||||
return;
|
||||
}
|
||||
|
||||
mIsFromUserInput = esm->IsHandlingUserInputExternal();
|
||||
mIsFromUserInput =
|
||||
document->PresContext()->EventStateManager()->IsHandlingUserInputExternal();
|
||||
}
|
||||
|
||||
|
||||
|
@ -161,39 +90,6 @@ AccEvent::CaptureIsFromUserInput(EIsFromUserInput aIsFromUserInput)
|
|||
// AccStateChangeEvent
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Note: we pass in eAllowDupes to the base class because we don't currently
|
||||
// support correct state change coalescence (XXX Bug 569356). Also we need to
|
||||
// decide how to coalesce events created via accessible (instead of node).
|
||||
AccStateChangeEvent::
|
||||
AccStateChangeEvent(Accessible* aAccessible, uint64_t aState,
|
||||
bool aIsEnabled, EIsFromUserInput aIsFromUserInput):
|
||||
AccEvent(nsIAccessibleEvent::EVENT_STATE_CHANGE, aAccessible,
|
||||
aIsFromUserInput, eAllowDupes),
|
||||
mState(aState), mIsEnabled(aIsEnabled)
|
||||
{
|
||||
}
|
||||
|
||||
AccStateChangeEvent::
|
||||
AccStateChangeEvent(nsINode* aNode, uint64_t aState, bool aIsEnabled):
|
||||
AccEvent(::nsIAccessibleEvent::EVENT_STATE_CHANGE, aNode,
|
||||
eAutoDetect, eAllowDupes),
|
||||
mState(aState), mIsEnabled(aIsEnabled)
|
||||
{
|
||||
}
|
||||
|
||||
AccStateChangeEvent::
|
||||
AccStateChangeEvent(nsINode* aNode, uint64_t aState) :
|
||||
AccEvent(::nsIAccessibleEvent::EVENT_STATE_CHANGE, aNode,
|
||||
eAutoDetect, eAllowDupes),
|
||||
mState(aState)
|
||||
{
|
||||
// Use GetAccessibleForNode() because we do not want to store an accessible
|
||||
// since it leads to problems with delayed events in the case when
|
||||
// an accessible gets reorder event before delayed event is processed.
|
||||
Accessible* accessible = GetAccessibleForNode();
|
||||
mIsEnabled = accessible && ((accessible->State() & mState) != 0);
|
||||
}
|
||||
|
||||
already_AddRefed<nsAccEvent>
|
||||
AccStateChangeEvent::CreateXPCOMObject()
|
||||
{
|
||||
|
@ -296,20 +192,6 @@ AccShowEvent::
|
|||
// AccCaretMoveEvent
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AccCaretMoveEvent::
|
||||
AccCaretMoveEvent(Accessible* aAccessible, int32_t aCaretOffset) :
|
||||
AccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aAccessible),
|
||||
mCaretOffset(aCaretOffset)
|
||||
{
|
||||
}
|
||||
|
||||
AccCaretMoveEvent::
|
||||
AccCaretMoveEvent(nsINode* aNode) :
|
||||
AccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aNode),
|
||||
mCaretOffset(-1)
|
||||
{
|
||||
}
|
||||
|
||||
already_AddRefed<nsAccEvent>
|
||||
AccCaretMoveEvent::CreateXPCOMObject()
|
||||
{
|
||||
|
|
|
@ -38,17 +38,18 @@ public:
|
|||
// Rule for accessible events.
|
||||
// The rule will be applied when flushing pending events.
|
||||
enum EEventRule {
|
||||
// eAllowDupes : More than one event of the same type is allowed.
|
||||
// This event will always be emitted.
|
||||
eAllowDupes,
|
||||
// eAllowDupes : More than one event of the same type is allowed.
|
||||
// This event will always be emitted. This flag is used for events that
|
||||
// don't support coalescence.
|
||||
eAllowDupes,
|
||||
|
||||
// eCoalesceReorder : For reorder events from the same subtree or the same
|
||||
// node, only the umbrella event on the ancestor will be emitted.
|
||||
eCoalesceReorder,
|
||||
eCoalesceReorder,
|
||||
|
||||
// eCoalesceMutationTextChange : coalesce text change events caused by
|
||||
// tree mutations of the same tree level.
|
||||
eCoalesceMutationTextChange,
|
||||
eCoalesceMutationTextChange,
|
||||
|
||||
// eCoalesceOfSameType : For events of the same type, only the newest event
|
||||
// will be processed.
|
||||
|
@ -59,20 +60,16 @@ public:
|
|||
|
||||
// eRemoveDupes : For repeat events, only the newest event in queue
|
||||
// will be emitted.
|
||||
eRemoveDupes,
|
||||
eRemoveDupes,
|
||||
|
||||
// eDoNotEmit : This event is confirmed as a duplicate, do not emit it.
|
||||
eDoNotEmit
|
||||
eDoNotEmit
|
||||
};
|
||||
|
||||
// Initialize with an nsIAccessible
|
||||
AccEvent(uint32_t aEventType, Accessible* aAccessible,
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect,
|
||||
EEventRule aEventRule = eRemoveDupes);
|
||||
// Initialize with an nsINode
|
||||
AccEvent(uint32_t aEventType, nsINode* aNode,
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect,
|
||||
EEventRule aEventRule = eRemoveDupes);
|
||||
virtual ~AccEvent() {}
|
||||
|
||||
// AccEvent
|
||||
|
@ -80,9 +77,8 @@ public:
|
|||
EEventRule GetEventRule() const { return mEventRule; }
|
||||
bool IsFromUserInput() const { return mIsFromUserInput; }
|
||||
|
||||
Accessible* GetAccessible();
|
||||
DocAccessible* GetDocAccessible();
|
||||
nsINode* GetNode();
|
||||
Accessible* GetAccessible() const { return mAccessible; }
|
||||
DocAccessible* GetDocAccessible() const { return mAccessible->Document(); }
|
||||
|
||||
/**
|
||||
* Create and return an XPCOM object for accessible event object.
|
||||
|
@ -119,10 +115,6 @@ public:
|
|||
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(AccEvent)
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Get an accessible from event target node.
|
||||
*/
|
||||
Accessible* GetAccessibleForNode() const;
|
||||
|
||||
/**
|
||||
* Determine whether the event is from user input by event state manager if
|
||||
|
@ -134,7 +126,6 @@ protected:
|
|||
uint32_t mEventType;
|
||||
EEventRule mEventRule;
|
||||
nsRefPtr<Accessible> mAccessible;
|
||||
nsCOMPtr<nsINode> mNode;
|
||||
|
||||
friend class NotificationController;
|
||||
friend class AccReorderEvent;
|
||||
|
@ -149,11 +140,15 @@ class AccStateChangeEvent: public AccEvent
|
|||
public:
|
||||
AccStateChangeEvent(Accessible* aAccessible, uint64_t aState,
|
||||
bool aIsEnabled,
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect);
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect) :
|
||||
AccEvent(nsIAccessibleEvent::EVENT_STATE_CHANGE, aAccessible,
|
||||
aIsFromUserInput, eAllowDupes),
|
||||
mState(aState), mIsEnabled(aIsEnabled) { }
|
||||
|
||||
AccStateChangeEvent(nsINode* aNode, uint64_t aState, bool aIsEnabled);
|
||||
|
||||
AccStateChangeEvent(nsINode* aNode, uint64_t aState);
|
||||
AccStateChangeEvent(Accessible* aAccessible, uint64_t aState) :
|
||||
AccEvent(::nsIAccessibleEvent::EVENT_STATE_CHANGE, aAccessible,
|
||||
eAutoDetect, eAllowDupes), mState(aState)
|
||||
{ mIsEnabled = (mAccessible->State() & mState) != 0; }
|
||||
|
||||
// AccEvent
|
||||
virtual already_AddRefed<nsAccEvent> CreateXPCOMObject();
|
||||
|
@ -239,6 +234,7 @@ public:
|
|||
bool IsHide() const { return mEventType == nsIAccessibleEvent::EVENT_HIDE; }
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsINode> mNode;
|
||||
nsRefPtr<Accessible> mParent;
|
||||
nsRefPtr<AccTextChangeEvent> mTextChangeEvent;
|
||||
|
||||
|
@ -350,8 +346,10 @@ protected:
|
|||
class AccCaretMoveEvent: public AccEvent
|
||||
{
|
||||
public:
|
||||
AccCaretMoveEvent(Accessible* aAccessible, int32_t aCaretOffset);
|
||||
AccCaretMoveEvent(nsINode* aNode);
|
||||
AccCaretMoveEvent(Accessible* aAccessible) :
|
||||
AccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aAccessible),
|
||||
mCaretOffset(-1) { }
|
||||
virtual ~AccCaretMoveEvent() { }
|
||||
|
||||
// AccEvent
|
||||
virtual already_AddRefed<nsAccEvent> CreateXPCOMObject();
|
||||
|
@ -367,6 +365,8 @@ public:
|
|||
|
||||
private:
|
||||
int32_t mCaretOffset;
|
||||
|
||||
friend class NotificationController;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* 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/. */
|
||||
|
||||
#include "nsAccDocManager.h"
|
||||
#include "DocManager.h"
|
||||
|
||||
#include "Accessible-inl.h"
|
||||
#include "ApplicationAccessible.h"
|
||||
|
@ -33,14 +33,14 @@
|
|||
using namespace mozilla::a11y;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsAccDocManager
|
||||
// DocManager
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsAccDocManager public
|
||||
// DocManager public
|
||||
|
||||
DocAccessible*
|
||||
nsAccDocManager::GetDocAccessible(nsIDocument *aDocument)
|
||||
DocManager::GetDocAccessible(nsIDocument* aDocument)
|
||||
{
|
||||
if (!aDocument)
|
||||
return nullptr;
|
||||
|
@ -56,7 +56,7 @@ nsAccDocManager::GetDocAccessible(nsIDocument *aDocument)
|
|||
}
|
||||
|
||||
Accessible*
|
||||
nsAccDocManager::FindAccessibleInCache(nsINode* aNode) const
|
||||
DocManager::FindAccessibleInCache(nsINode* aNode) const
|
||||
{
|
||||
nsSearchAccessibleInCacheArg arg;
|
||||
arg.mNode = aNode;
|
||||
|
@ -69,7 +69,7 @@ nsAccDocManager::FindAccessibleInCache(nsINode* aNode) const
|
|||
|
||||
#ifdef DEBUG
|
||||
bool
|
||||
nsAccDocManager::IsProcessingRefreshDriverNotification() const
|
||||
DocManager::IsProcessingRefreshDriverNotification() const
|
||||
{
|
||||
bool isDocRefreshing = false;
|
||||
mDocAccessibleCache.EnumerateRead(SearchIfDocIsRefreshing,
|
||||
|
@ -81,10 +81,10 @@ nsAccDocManager::IsProcessingRefreshDriverNotification() const
|
|||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsAccDocManager protected
|
||||
// DocManager protected
|
||||
|
||||
bool
|
||||
nsAccDocManager::Init()
|
||||
DocManager::Init()
|
||||
{
|
||||
mDocAccessibleCache.Init(4);
|
||||
|
||||
|
@ -101,7 +101,7 @@ nsAccDocManager::Init()
|
|||
}
|
||||
|
||||
void
|
||||
nsAccDocManager::Shutdown()
|
||||
DocManager::Shutdown()
|
||||
{
|
||||
nsCOMPtr<nsIWebProgress> progress =
|
||||
do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID);
|
||||
|
@ -115,7 +115,7 @@ nsAccDocManager::Shutdown()
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsISupports
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS3(nsAccDocManager,
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS3(DocManager,
|
||||
nsIWebProgressListener,
|
||||
nsIDOMEventListener,
|
||||
nsISupportsWeakReference)
|
||||
|
@ -124,9 +124,9 @@ NS_IMPL_THREADSAFE_ISUPPORTS3(nsAccDocManager,
|
|||
// nsIWebProgressListener
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAccDocManager::OnStateChange(nsIWebProgress *aWebProgress,
|
||||
nsIRequest *aRequest, uint32_t aStateFlags,
|
||||
nsresult aStatus)
|
||||
DocManager::OnStateChange(nsIWebProgress* aWebProgress,
|
||||
nsIRequest* aRequest, uint32_t aStateFlags,
|
||||
nsresult aStatus)
|
||||
{
|
||||
NS_ASSERTION(aStateFlags & STATE_IS_DOCUMENT, "Other notifications excluded");
|
||||
|
||||
|
@ -203,39 +203,39 @@ nsAccDocManager::OnStateChange(nsIWebProgress *aWebProgress,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAccDocManager::OnProgressChange(nsIWebProgress *aWebProgress,
|
||||
nsIRequest *aRequest,
|
||||
int32_t aCurSelfProgress,
|
||||
int32_t aMaxSelfProgress,
|
||||
int32_t aCurTotalProgress,
|
||||
int32_t aMaxTotalProgress)
|
||||
DocManager::OnProgressChange(nsIWebProgress* aWebProgress,
|
||||
nsIRequest* aRequest,
|
||||
int32_t aCurSelfProgress,
|
||||
int32_t aMaxSelfProgress,
|
||||
int32_t aCurTotalProgress,
|
||||
int32_t aMaxTotalProgress)
|
||||
{
|
||||
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAccDocManager::OnLocationChange(nsIWebProgress *aWebProgress,
|
||||
nsIRequest *aRequest, nsIURI *aLocation,
|
||||
uint32_t aFlags)
|
||||
DocManager::OnLocationChange(nsIWebProgress* aWebProgress,
|
||||
nsIRequest* aRequest, nsIURI* aLocation,
|
||||
uint32_t aFlags)
|
||||
{
|
||||
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAccDocManager::OnStatusChange(nsIWebProgress *aWebProgress,
|
||||
nsIRequest *aRequest, nsresult aStatus,
|
||||
const PRUnichar *aMessage)
|
||||
DocManager::OnStatusChange(nsIWebProgress* aWebProgress,
|
||||
nsIRequest* aRequest, nsresult aStatus,
|
||||
const PRUnichar* aMessage)
|
||||
{
|
||||
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAccDocManager::OnSecurityChange(nsIWebProgress *aWebProgress,
|
||||
nsIRequest *aRequest,
|
||||
uint32_t aState)
|
||||
DocManager::OnSecurityChange(nsIWebProgress* aWebProgress,
|
||||
nsIRequest* aRequest,
|
||||
uint32_t aState)
|
||||
{
|
||||
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
|
||||
return NS_OK;
|
||||
|
@ -245,7 +245,7 @@ nsAccDocManager::OnSecurityChange(nsIWebProgress *aWebProgress,
|
|||
// nsIDOMEventListener
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAccDocManager::HandleEvent(nsIDOMEvent *aEvent)
|
||||
DocManager::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
nsAutoString type;
|
||||
aEvent->GetType(type);
|
||||
|
@ -303,11 +303,11 @@ nsAccDocManager::HandleEvent(nsIDOMEvent *aEvent)
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsAccDocManager private
|
||||
// DocManager private
|
||||
|
||||
void
|
||||
nsAccDocManager::HandleDOMDocumentLoad(nsIDocument *aDocument,
|
||||
uint32_t aLoadEventType)
|
||||
DocManager::HandleDOMDocumentLoad(nsIDocument* aDocument,
|
||||
uint32_t aLoadEventType)
|
||||
{
|
||||
// Document accessible can be created before we were notified the DOM document
|
||||
// was loaded completely. However if it's not created yet then create it.
|
||||
|
@ -322,8 +322,8 @@ nsAccDocManager::HandleDOMDocumentLoad(nsIDocument *aDocument,
|
|||
}
|
||||
|
||||
void
|
||||
nsAccDocManager::AddListeners(nsIDocument *aDocument,
|
||||
bool aAddDOMContentLoadedListener)
|
||||
DocManager::AddListeners(nsIDocument* aDocument,
|
||||
bool aAddDOMContentLoadedListener)
|
||||
{
|
||||
nsPIDOMWindow *window = aDocument->GetWindow();
|
||||
nsIDOMEventTarget *target = window->GetChromeEventHandler();
|
||||
|
@ -347,7 +347,7 @@ nsAccDocManager::AddListeners(nsIDocument *aDocument,
|
|||
}
|
||||
|
||||
DocAccessible*
|
||||
nsAccDocManager::CreateDocOrRootAccessible(nsIDocument* aDocument)
|
||||
DocManager::CreateDocOrRootAccessible(nsIDocument* aDocument)
|
||||
{
|
||||
// Ignore temporary, hiding, resource documents and documents without
|
||||
// docshell.
|
||||
|
@ -400,9 +400,8 @@ nsAccDocManager::CreateDocOrRootAccessible(nsIDocument* aDocument)
|
|||
// the same document.
|
||||
// Note: don't use AccReorderEvent to avoid coalsecense and special reorder
|
||||
// events processing.
|
||||
nsRefPtr<AccEvent> reorderEvent =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_REORDER, ApplicationAcc());
|
||||
docAcc->FireDelayedAccessibleEvent(reorderEvent);
|
||||
docAcc->FireDelayedEvent(nsIAccessibleEvent::EVENT_REORDER,
|
||||
ApplicationAcc());
|
||||
|
||||
} else {
|
||||
parentDocAcc->BindChildDocument(docAcc);
|
||||
|
@ -420,12 +419,12 @@ nsAccDocManager::CreateDocOrRootAccessible(nsIDocument* aDocument)
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsAccDocManager static
|
||||
// DocManager static
|
||||
|
||||
PLDHashOperator
|
||||
nsAccDocManager::GetFirstEntryInDocCache(const nsIDocument* aKey,
|
||||
DocAccessible* aDocAccessible,
|
||||
void* aUserArg)
|
||||
DocManager::GetFirstEntryInDocCache(const nsIDocument* aKey,
|
||||
DocAccessible* aDocAccessible,
|
||||
void* aUserArg)
|
||||
{
|
||||
NS_ASSERTION(aDocAccessible,
|
||||
"No doc accessible for the object in doc accessible cache!");
|
||||
|
@ -435,7 +434,7 @@ nsAccDocManager::GetFirstEntryInDocCache(const nsIDocument* aKey,
|
|||
}
|
||||
|
||||
void
|
||||
nsAccDocManager::ClearDocCache()
|
||||
DocManager::ClearDocCache()
|
||||
{
|
||||
DocAccessible* docAcc = nullptr;
|
||||
while (mDocAccessibleCache.EnumerateRead(GetFirstEntryInDocCache, static_cast<void*>(&docAcc))) {
|
||||
|
@ -445,9 +444,9 @@ nsAccDocManager::ClearDocCache()
|
|||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsAccDocManager::SearchAccessibleInDocCache(const nsIDocument* aKey,
|
||||
DocAccessible* aDocAccessible,
|
||||
void* aUserArg)
|
||||
DocManager::SearchAccessibleInDocCache(const nsIDocument* aKey,
|
||||
DocAccessible* aDocAccessible,
|
||||
void* aUserArg)
|
||||
{
|
||||
NS_ASSERTION(aDocAccessible,
|
||||
"No doc accessible for the object in doc accessible cache!");
|
||||
|
@ -465,9 +464,9 @@ nsAccDocManager::SearchAccessibleInDocCache(const nsIDocument* aKey,
|
|||
|
||||
#ifdef DEBUG
|
||||
PLDHashOperator
|
||||
nsAccDocManager::SearchIfDocIsRefreshing(const nsIDocument* aKey,
|
||||
DocAccessible* aDocAccessible,
|
||||
void* aUserArg)
|
||||
DocManager::SearchIfDocIsRefreshing(const nsIDocument* aKey,
|
||||
DocAccessible* aDocAccessible,
|
||||
void* aUserArg)
|
||||
{
|
||||
NS_ASSERTION(aDocAccessible,
|
||||
"No doc accessible for the object in doc accessible cache!");
|
|
@ -2,8 +2,8 @@
|
|||
* 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/. */
|
||||
|
||||
#ifndef nsAccDocManager_h_
|
||||
#define nsAccDocManager_h_
|
||||
#ifndef mozilla_a11_DocManager_h_
|
||||
#define mozilla_a11_DocManager_h_
|
||||
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
|
@ -19,21 +19,15 @@ namespace a11y {
|
|||
class Accessible;
|
||||
class DocAccessible;
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
/**
|
||||
* Manage the document accessible life cycle.
|
||||
*/
|
||||
class nsAccDocManager : public nsIWebProgressListener,
|
||||
public nsIDOMEventListener,
|
||||
public nsSupportsWeakReference
|
||||
class DocManager : public nsIWebProgressListener,
|
||||
public nsIDOMEventListener,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
typedef mozilla::a11y::Accessible Accessible;
|
||||
typedef mozilla::a11y::DocAccessible DocAccessible;
|
||||
|
||||
virtual ~nsAccDocManager() { }
|
||||
virtual ~DocManager() { }
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIWEBPROGRESSLISTENER
|
||||
|
@ -86,7 +80,7 @@ public:
|
|||
#endif
|
||||
|
||||
protected:
|
||||
nsAccDocManager() { }
|
||||
DocManager() { }
|
||||
|
||||
/**
|
||||
* Initialize the manager.
|
||||
|
@ -99,8 +93,8 @@ protected:
|
|||
void Shutdown();
|
||||
|
||||
private:
|
||||
nsAccDocManager(const nsAccDocManager&);
|
||||
nsAccDocManager& operator =(const nsAccDocManager&);
|
||||
DocManager(const DocManager&);
|
||||
DocManager& operator =(const DocManager&);
|
||||
|
||||
private:
|
||||
/**
|
||||
|
@ -160,4 +154,7 @@ private:
|
|||
DocAccessibleHashtable mDocAccessibleCache;
|
||||
};
|
||||
|
||||
#endif // nsAccDocManager_h_
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_a11_DocManager_h_
|
|
@ -219,7 +219,7 @@ FocusManager::DispatchFocusEvent(DocAccessible* aDocument,
|
|||
nsRefPtr<AccEvent> event =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_FOCUS, aTarget,
|
||||
eAutoDetect, AccEvent::eCoalesceOfSameType);
|
||||
aDocument->FireDelayedAccessibleEvent(event);
|
||||
aDocument->FireDelayedEvent(event);
|
||||
|
||||
#ifdef A11Y_LOG
|
||||
if (logging::IsEnabled(logging::eFocus))
|
||||
|
|
|
@ -471,12 +471,9 @@ logging::DocLoadEventHandled(AccEvent* aEvent)
|
|||
|
||||
MsgBegin(sDocEventTitle, "handled '%s' event", strEventType.get());
|
||||
|
||||
nsINode* node = aEvent->GetNode();
|
||||
if (node->IsNodeOfType(nsINode::eDOCUMENT)) {
|
||||
nsIDocument* documentNode = static_cast<nsIDocument*>(node);
|
||||
DocAccessible* document = aEvent->GetDocAccessible();
|
||||
LogDocInfo(documentNode, document);
|
||||
}
|
||||
DocAccessible* document = aEvent->GetAccessible()->AsDoc();
|
||||
if (document)
|
||||
LogDocInfo(document->DocumentNode(), document);
|
||||
|
||||
MsgEnd();
|
||||
}
|
||||
|
|
|
@ -21,9 +21,9 @@ CPPSRCS = \
|
|||
AccIterator.cpp \
|
||||
Filters.cpp \
|
||||
ARIAStateMap.cpp \
|
||||
DocManager.cpp \
|
||||
FocusManager.cpp \
|
||||
NotificationController.cpp \
|
||||
nsAccDocManager.cpp \
|
||||
nsAccessNode.cpp \
|
||||
nsARIAMap.cpp \
|
||||
nsCoreUtils.cpp \
|
||||
|
@ -48,7 +48,6 @@ endif
|
|||
|
||||
EXPORTS = \
|
||||
AccEvent.h \
|
||||
nsAccDocManager.h \
|
||||
nsAccessibilityService.h \
|
||||
nsAccessNode.h \
|
||||
$(NULL)
|
||||
|
@ -56,6 +55,7 @@ EXPORTS = \
|
|||
EXPORTS_NAMESPACES = mozilla/a11y
|
||||
|
||||
EXPORTS_mozilla/a11y = \
|
||||
DocManager.h \
|
||||
FocusManager.h \
|
||||
AccTypes.h \
|
||||
States.h \
|
||||
|
|
|
@ -385,7 +385,7 @@ NotificationController::CoalesceEvents()
|
|||
AccEvent* accEvent = mEvents[index];
|
||||
if (accEvent->mEventType == tailEvent->mEventType &&
|
||||
accEvent->mEventRule == tailEvent->mEventRule &&
|
||||
accEvent->mNode == tailEvent->mNode) {
|
||||
accEvent->mAccessible == tailEvent->mAccessible) {
|
||||
tailEvent->mEventRule = AccEvent::eDoNotEmit;
|
||||
return;
|
||||
}
|
||||
|
@ -705,12 +705,11 @@ NotificationController::ProcessEventQueue()
|
|||
|
||||
// Dispatch caret moved and text selection change events.
|
||||
if (event->mEventType == nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED) {
|
||||
AccCaretMoveEvent* caretMoveEvent = downcast_accEvent(event);
|
||||
HyperTextAccessible* hyperText = target->AsHyperText();
|
||||
int32_t caretOffset = -1;
|
||||
if (hyperText &&
|
||||
NS_SUCCEEDED(hyperText->GetCaretOffset(&caretOffset))) {
|
||||
nsRefPtr<AccEvent> caretMoveEvent =
|
||||
new AccCaretMoveEvent(hyperText, caretOffset);
|
||||
NS_SUCCEEDED(hyperText->GetCaretOffset(&caretMoveEvent->mCaretOffset))) {
|
||||
|
||||
nsEventShell::FireEvent(caretMoveEvent);
|
||||
|
||||
// There's a selection so fire selection change as well.
|
||||
|
|
|
@ -78,7 +78,7 @@ private:
|
|||
|
||||
Class* mInstance;
|
||||
Callback mCallback;
|
||||
nsCOMPtr<Arg> mArg;
|
||||
nsRefPtr<Arg> mArg;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -82,14 +82,14 @@ TextUpdater::DoUpdate(const nsAString& aNewText, const nsAString& aOldText,
|
|||
// Fire text change event for removal.
|
||||
nsRefPtr<AccEvent> textRemoveEvent =
|
||||
new AccTextChangeEvent(mHyperText, mTextOffset, str1, false);
|
||||
mDocument->FireDelayedAccessibleEvent(textRemoveEvent);
|
||||
mDocument->FireDelayedEvent(textRemoveEvent);
|
||||
}
|
||||
|
||||
if (strLen2 > 0) {
|
||||
// Fire text change event for insertion.
|
||||
nsRefPtr<AccEvent> textInsertEvent =
|
||||
new AccTextChangeEvent(mHyperText, mTextOffset, str2, true);
|
||||
mDocument->FireDelayedAccessibleEvent(textInsertEvent);
|
||||
mDocument->FireDelayedEvent(textInsertEvent);
|
||||
}
|
||||
|
||||
mDocument->MaybeNotifyOfValueChange(mHyperText);
|
||||
|
@ -135,7 +135,7 @@ TextUpdater::DoUpdate(const nsAString& aNewText, const nsAString& aOldText,
|
|||
|
||||
// Fire events.
|
||||
for (int32_t idx = events.Length() - 1; idx >= 0; idx--)
|
||||
mDocument->FireDelayedAccessibleEvent(events[idx]);
|
||||
mDocument->FireDelayedEvent(events[idx]);
|
||||
|
||||
mDocument->MaybeNotifyOfValueChange(mHyperText);
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ ApplicationAccessible* nsAccessibilityService::gApplicationAccessible = nullptr;
|
|||
bool nsAccessibilityService::gIsShutdown = true;
|
||||
|
||||
nsAccessibilityService::nsAccessibilityService() :
|
||||
nsAccDocManager(), FocusManager()
|
||||
DocManager(), FocusManager()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -139,7 +139,7 @@ nsAccessibilityService::~nsAccessibilityService()
|
|||
// nsISupports
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED3(nsAccessibilityService,
|
||||
nsAccDocManager,
|
||||
DocManager,
|
||||
nsIAccessibilityService,
|
||||
nsIAccessibleRetrieval,
|
||||
nsIObserver)
|
||||
|
@ -621,7 +621,7 @@ nsAccessibilityService::GetAccessibleFromCache(nsIDOMNode* aNode,
|
|||
// caches. If we don't find it, and the given node is itself a document, check
|
||||
// our cache of document accessibles (document cache). Note usually shutdown
|
||||
// document accessibles are not stored in the document cache, however an
|
||||
// "unofficially" shutdown document (i.e. not from nsAccDocManager) can still
|
||||
// "unofficially" shutdown document (i.e. not from DocManager) can still
|
||||
// exist in the document cache.
|
||||
Accessible* accessible = FindAccessibleInCache(node);
|
||||
if (!accessible) {
|
||||
|
@ -975,7 +975,7 @@ bool
|
|||
nsAccessibilityService::Init()
|
||||
{
|
||||
// Initialize accessible document manager.
|
||||
if (!nsAccDocManager::Init())
|
||||
if (!DocManager::Init())
|
||||
return false;
|
||||
|
||||
// Add observers.
|
||||
|
@ -1026,7 +1026,7 @@ nsAccessibilityService::Shutdown()
|
|||
}
|
||||
|
||||
// Stop accessible document loader.
|
||||
nsAccDocManager::Shutdown();
|
||||
DocManager::Shutdown();
|
||||
|
||||
// Application is going to be closed, shutdown accessibility and mark
|
||||
// accessibility service as shutdown to prevent calls of its methods.
|
||||
|
|
|
@ -8,8 +8,7 @@
|
|||
|
||||
#include "nsIAccessibilityService.h"
|
||||
|
||||
#include "nsAccDocManager.h"
|
||||
|
||||
#include "mozilla/a11y/DocManager.h"
|
||||
#include "mozilla/a11y/FocusManager.h"
|
||||
|
||||
#include "nsIObserver.h"
|
||||
|
@ -64,12 +63,15 @@ bool ShouldA11yBeEnabled();
|
|||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
class nsAccessibilityService : public nsAccDocManager,
|
||||
class nsAccessibilityService : public mozilla::a11y::DocManager,
|
||||
public mozilla::a11y::FocusManager,
|
||||
public nsIAccessibilityService,
|
||||
public nsIObserver
|
||||
{
|
||||
public:
|
||||
typedef mozilla::a11y::Accessible Accessible;
|
||||
typedef mozilla::a11y::DocAccessible DocAccessible;
|
||||
|
||||
virtual ~nsAccessibilityService();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
|
|
@ -243,10 +243,8 @@ nsCaretAccessible::NormalSelectionChanged(nsISelection* aSelection)
|
|||
mLastCaretOffset = caretOffset;
|
||||
mLastTextAccessible = textAcc;
|
||||
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccCaretMoveEvent(mLastTextAccessible->GetNode());
|
||||
if (event)
|
||||
mLastTextAccessible->Document()->FireDelayedAccessibleEvent(event);
|
||||
nsRefPtr<AccEvent> event = new AccCaretMoveEvent(mLastTextAccessible);
|
||||
mLastTextAccessible->Document()->FireDelayedEvent(event);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -258,15 +256,13 @@ nsCaretAccessible::SpellcheckSelectionChanged(nsISelection* aSelection)
|
|||
// misspelled word). If spellchecking is disabled (for example,
|
||||
// @spellcheck="false" on html:body) then we won't fire any event.
|
||||
|
||||
HyperTextAccessible* textAcc =
|
||||
HyperTextAccessible* hyperText =
|
||||
nsAccUtils::GetTextAccessibleFromSelection(aSelection);
|
||||
if (!textAcc)
|
||||
return;
|
||||
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_TEXT_ATTRIBUTE_CHANGED, textAcc);
|
||||
if (event)
|
||||
textAcc->Document()->FireDelayedAccessibleEvent(event);
|
||||
if (hyperText) {
|
||||
hyperText->Document()->
|
||||
FireDelayedEvent(nsIAccessibleEvent::EVENT_TEXT_ATTRIBUTE_CHANGED,
|
||||
hyperText);
|
||||
}
|
||||
}
|
||||
|
||||
nsIntRect
|
||||
|
|
|
@ -22,7 +22,7 @@ nsEventShell::FireEvent(AccEvent* aEvent)
|
|||
Accessible* accessible = aEvent->GetAccessible();
|
||||
NS_ENSURE_TRUE_VOID(accessible);
|
||||
|
||||
nsINode* node = aEvent->GetNode();
|
||||
nsINode* node = accessible->GetNode();
|
||||
if (node) {
|
||||
sEventTargetNode = node;
|
||||
sEventFromUserInput = aEvent->IsFromUserInput();
|
||||
|
|
|
@ -12,9 +12,31 @@
|
|||
#include "NotificationController.h"
|
||||
#include "States.h"
|
||||
|
||||
#ifdef A11Y_LOG
|
||||
#include "Logging.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
inline void
|
||||
DocAccessible::FireDelayedEvent(AccEvent* aEvent)
|
||||
{
|
||||
#ifdef A11Y_LOG
|
||||
if (logging::IsEnabled(logging::eDocLoad))
|
||||
logging::DocLoadEventFired(aEvent);
|
||||
#endif
|
||||
|
||||
mNotificationController->QueueEvent(aEvent);
|
||||
}
|
||||
|
||||
inline void
|
||||
DocAccessible::FireDelayedEvent(uint32_t aEventType, Accessible* aTarget)
|
||||
{
|
||||
nsRefPtr<AccEvent> event = new AccEvent(aEventType, aTarget);
|
||||
FireDelayedEvent(event);
|
||||
}
|
||||
|
||||
inline void
|
||||
DocAccessible::BindChildDocument(DocAccessible* aDocument)
|
||||
{
|
||||
|
@ -54,20 +76,16 @@ DocAccessible::NotifyOfLoad(uint32_t aLoadEventType)
|
|||
if (HasLoadState(eCompletelyLoaded) && IsLoadEventTarget()) {
|
||||
nsRefPtr<AccEvent> stateEvent =
|
||||
new AccStateChangeEvent(this, states::BUSY, false);
|
||||
FireDelayedAccessibleEvent(stateEvent);
|
||||
FireDelayedEvent(stateEvent);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
DocAccessible::MaybeNotifyOfValueChange(Accessible* aAccessible)
|
||||
{
|
||||
mozilla::a11y::role role = aAccessible->Role();
|
||||
if (role == roles::ENTRY || role == roles::COMBOBOX) {
|
||||
nsRefPtr<AccEvent> valueChangeEvent =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, aAccessible,
|
||||
eAutoDetect, AccEvent::eRemoveDupes);
|
||||
FireDelayedAccessibleEvent(valueChangeEvent);
|
||||
}
|
||||
a11y::role role = aAccessible->Role();
|
||||
if (role == roles::ENTRY || role == roles::COMBOBOX)
|
||||
FireDelayedEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, aAccessible);
|
||||
}
|
||||
|
||||
} // namespace a11y
|
||||
|
|
|
@ -44,10 +44,6 @@
|
|||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
||||
#ifdef A11Y_LOG
|
||||
#include "Logging.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
#include "nsIXULDocument.h"
|
||||
#endif
|
||||
|
@ -100,7 +96,7 @@ DocAccessible::
|
|||
if (!mDocument)
|
||||
return;
|
||||
|
||||
// nsAccDocManager creates document accessible when scrollable frame is
|
||||
// DocManager creates document accessible when scrollable frame is
|
||||
// available already, it should be safe time to add scroll listener.
|
||||
AddScrollListener();
|
||||
|
||||
|
@ -892,7 +888,7 @@ DocAccessible::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
// about this exceptional case.
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(this, states::EDITABLE, true);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
FireDelayedEvent(event);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -987,7 +983,7 @@ DocAccessible::AttributeChanged(nsIDocument* aDocument,
|
|||
|
||||
// Fire accessible events iff there's an accessible, otherwise we consider
|
||||
// the accessible state wasn't changed, i.e. its state is initial state.
|
||||
AttributeChangedImpl(aElement, aNameSpaceID, aAttribute);
|
||||
AttributeChangedImpl(accessible, aNameSpaceID, aAttribute);
|
||||
|
||||
// Update dependent IDs cache. Take care of accessible elements because no
|
||||
// accessible element means either the element is not accessible at all or
|
||||
|
@ -1002,7 +998,8 @@ DocAccessible::AttributeChanged(nsIDocument* aDocument,
|
|||
|
||||
// DocAccessible protected member
|
||||
void
|
||||
DocAccessible::AttributeChangedImpl(nsIContent* aContent, int32_t aNameSpaceID, nsIAtom* aAttribute)
|
||||
DocAccessible::AttributeChangedImpl(Accessible* aAccessible,
|
||||
int32_t aNameSpaceID, nsIAtom* aAttribute)
|
||||
{
|
||||
// Fire accessible event after short timer, because we need to wait for
|
||||
// DOM attribute & resulting layout to actually change. Otherwise,
|
||||
|
@ -1033,14 +1030,12 @@ DocAccessible::AttributeChangedImpl(nsIContent* aContent, int32_t aNameSpaceID,
|
|||
// ARIA's aria-disabled does not affect the disabled state bit.
|
||||
|
||||
nsRefPtr<AccEvent> enabledChangeEvent =
|
||||
new AccStateChangeEvent(aContent, states::ENABLED);
|
||||
|
||||
FireDelayedAccessibleEvent(enabledChangeEvent);
|
||||
new AccStateChangeEvent(aAccessible, states::ENABLED);
|
||||
FireDelayedEvent(enabledChangeEvent);
|
||||
|
||||
nsRefPtr<AccEvent> sensitiveChangeEvent =
|
||||
new AccStateChangeEvent(aContent, states::SENSITIVE);
|
||||
|
||||
FireDelayedAccessibleEvent(sensitiveChangeEvent);
|
||||
new AccStateChangeEvent(aAccessible, states::SENSITIVE);
|
||||
FireDelayedEvent(sensitiveChangeEvent);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1049,7 +1044,7 @@ DocAccessible::AttributeChangedImpl(nsIContent* aContent, int32_t aNameSpaceID,
|
|||
// Check for hyphenated aria-foo property?
|
||||
if (StringBeginsWith(nsDependentAtomString(aAttribute),
|
||||
NS_LITERAL_STRING("aria-"))) {
|
||||
ARIAAttributeChanged(aContent, aAttribute);
|
||||
ARIAAttributeChanged(aAccessible, aAttribute);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1057,75 +1052,69 @@ DocAccessible::AttributeChangedImpl(nsIContent* aContent, int32_t aNameSpaceID,
|
|||
aAttribute == nsGkAtoms::title ||
|
||||
aAttribute == nsGkAtoms::aria_label ||
|
||||
aAttribute == nsGkAtoms::aria_labelledby) {
|
||||
FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE,
|
||||
aContent);
|
||||
FireDelayedEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE, aAccessible);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aAttribute == nsGkAtoms::aria_busy) {
|
||||
bool isOn = aContent->AttrValueIs(aNameSpaceID, aAttribute,
|
||||
nsGkAtoms::_true, eCaseMatters);
|
||||
nsRefPtr<AccEvent> event = new AccStateChangeEvent(aContent, states::BUSY, isOn);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
bool isOn = aAccessible->GetContent()->
|
||||
AttrValueIs(aNameSpaceID, aAttribute, nsGkAtoms::_true, eCaseMatters);
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(aAccessible, states::BUSY, isOn);
|
||||
FireDelayedEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
// ARIA or XUL selection
|
||||
if ((aContent->IsXUL() && aAttribute == nsGkAtoms::selected) ||
|
||||
if ((aAccessible->GetContent()->IsXUL() && aAttribute == nsGkAtoms::selected) ||
|
||||
aAttribute == nsGkAtoms::aria_selected) {
|
||||
Accessible* item = GetAccessible(aContent);
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
Accessible* widget =
|
||||
nsAccUtils::GetSelectableContainer(item, item->State());
|
||||
nsAccUtils::GetSelectableContainer(aAccessible, aAccessible->State());
|
||||
if (widget) {
|
||||
nsIContent* elm = aAccessible->GetContent();
|
||||
AccSelChangeEvent::SelChangeType selChangeType =
|
||||
aContent->AttrValueIs(aNameSpaceID, aAttribute,
|
||||
nsGkAtoms::_true, eCaseMatters) ?
|
||||
elm->AttrValueIs(aNameSpaceID, aAttribute, nsGkAtoms::_true, eCaseMatters) ?
|
||||
AccSelChangeEvent::eSelectionAdd : AccSelChangeEvent::eSelectionRemove;
|
||||
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccSelChangeEvent(widget, item, selChangeType);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
new AccSelChangeEvent(widget, aAccessible, selChangeType);
|
||||
FireDelayedEvent(event);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (aAttribute == nsGkAtoms::contenteditable) {
|
||||
nsRefPtr<AccEvent> editableChangeEvent =
|
||||
new AccStateChangeEvent(aContent, states::EDITABLE);
|
||||
FireDelayedAccessibleEvent(editableChangeEvent);
|
||||
new AccStateChangeEvent(aAccessible, states::EDITABLE);
|
||||
FireDelayedEvent(editableChangeEvent);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aAttribute == nsGkAtoms::value) {
|
||||
Accessible* accessible = GetAccessible(aContent);
|
||||
if(accessible && accessible->IsProgress()) {
|
||||
FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE,
|
||||
aContent);
|
||||
}
|
||||
if (aAccessible->IsProgress())
|
||||
FireDelayedEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, aAccessible);
|
||||
}
|
||||
}
|
||||
|
||||
// DocAccessible protected member
|
||||
void
|
||||
DocAccessible::ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute)
|
||||
DocAccessible::ARIAAttributeChanged(Accessible* aAccessible, nsIAtom* aAttribute)
|
||||
{
|
||||
// Note: For universal/global ARIA states and properties we don't care if
|
||||
// there is an ARIA role present or not.
|
||||
|
||||
if (aAttribute == nsGkAtoms::aria_required) {
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(aContent, states::REQUIRED);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
new AccStateChangeEvent(aAccessible, states::REQUIRED);
|
||||
FireDelayedEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aAttribute == nsGkAtoms::aria_invalid) {
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(aContent, states::INVALID);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
new AccStateChangeEvent(aAccessible, states::INVALID);
|
||||
FireDelayedEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1133,8 +1122,8 @@ DocAccessible::ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute)
|
|||
// to the element with the id that activedescendant points to. Make sure
|
||||
// the tree up to date before processing.
|
||||
if (aAttribute == nsGkAtoms::aria_activedescendant) {
|
||||
mNotificationController->HandleNotification<DocAccessible, nsIContent>
|
||||
(this, &DocAccessible::ARIAActiveDescendantChanged, aContent);
|
||||
mNotificationController->HandleNotification<DocAccessible, Accessible>
|
||||
(this, &DocAccessible::ARIAActiveDescendantChanged, aAccessible);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -1142,8 +1131,8 @@ DocAccessible::ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute)
|
|||
// We treat aria-expanded as a global ARIA state for historical reasons
|
||||
if (aAttribute == nsGkAtoms::aria_expanded) {
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(aContent, states::EXPANDED);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
new AccStateChangeEvent(aAccessible, states::EXPANDED);
|
||||
FireDelayedEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1151,10 +1140,11 @@ DocAccessible::ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute)
|
|||
// change event; at least until native API comes up with a more meaningful event.
|
||||
uint8_t attrFlags = nsAccUtils::GetAttributeCharacteristics(aAttribute);
|
||||
if (!(attrFlags & ATTR_BYPASSOBJ))
|
||||
FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_OBJECT_ATTRIBUTE_CHANGED,
|
||||
aContent);
|
||||
FireDelayedEvent(nsIAccessibleEvent::EVENT_OBJECT_ATTRIBUTE_CHANGED,
|
||||
aAccessible);
|
||||
|
||||
if (!aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::role)) {
|
||||
nsIContent* elm = aAccessible->GetContent();
|
||||
if (!elm->HasAttr(kNameSpaceID_None, nsGkAtoms::role)) {
|
||||
// We don't care about these other ARIA attribute changes unless there is
|
||||
// an ARIA role set for the element
|
||||
// XXX: we should check the role map to see if the changed property is
|
||||
|
@ -1165,29 +1155,26 @@ DocAccessible::ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute)
|
|||
// The following ARIA attributes only take affect when dynamic content role is present
|
||||
if (aAttribute == nsGkAtoms::aria_checked ||
|
||||
aAttribute == nsGkAtoms::aria_pressed) {
|
||||
const uint32_t kState = (aAttribute == nsGkAtoms::aria_checked) ?
|
||||
const uint64_t kState = (aAttribute == nsGkAtoms::aria_checked) ?
|
||||
states::CHECKED : states::PRESSED;
|
||||
nsRefPtr<AccEvent> event = new AccStateChangeEvent(aContent, kState);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
nsRefPtr<AccEvent> event = new AccStateChangeEvent(aAccessible, kState);
|
||||
FireDelayedEvent(event);
|
||||
|
||||
Accessible* accessible = event->GetAccessible();
|
||||
if (accessible) {
|
||||
bool wasMixed = (mARIAAttrOldValue == nsGkAtoms::mixed);
|
||||
bool isMixed = aContent->AttrValueIs(kNameSpaceID_None, aAttribute,
|
||||
nsGkAtoms::mixed, eCaseMatters);
|
||||
if (isMixed != wasMixed) {
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(aContent, states::MIXED, isMixed);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
}
|
||||
bool wasMixed = (mARIAAttrOldValue == nsGkAtoms::mixed);
|
||||
bool isMixed = elm->AttrValueIs(kNameSpaceID_None, aAttribute,
|
||||
nsGkAtoms::mixed, eCaseMatters);
|
||||
if (isMixed != wasMixed) {
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(aAccessible, states::MIXED, isMixed);
|
||||
FireDelayedEvent(event);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (aAttribute == nsGkAtoms::aria_readonly) {
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(aContent, states::READONLY);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
new AccStateChangeEvent(aAccessible, states::READONLY);
|
||||
FireDelayedEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1195,23 +1182,22 @@ DocAccessible::ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute)
|
|||
// when aria-valuenow is changed and aria-valuetext is empty
|
||||
if (aAttribute == nsGkAtoms::aria_valuetext ||
|
||||
(aAttribute == nsGkAtoms::aria_valuenow &&
|
||||
(!aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_valuetext) ||
|
||||
aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::aria_valuetext,
|
||||
nsGkAtoms::_empty, eCaseMatters)))) {
|
||||
FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE,
|
||||
aContent);
|
||||
(!elm->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_valuetext) ||
|
||||
elm->AttrValueIs(kNameSpaceID_None, nsGkAtoms::aria_valuetext,
|
||||
nsGkAtoms::_empty, eCaseMatters)))) {
|
||||
FireDelayedEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, aAccessible);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DocAccessible::ARIAActiveDescendantChanged(nsIContent* aElm)
|
||||
DocAccessible::ARIAActiveDescendantChanged(Accessible* aAccessible)
|
||||
{
|
||||
Accessible* widget = GetAccessible(aElm);
|
||||
if (widget && widget->IsActiveWidget()) {
|
||||
nsIContent* elm = aAccessible->GetContent();
|
||||
if (elm && aAccessible->IsActiveWidget()) {
|
||||
nsAutoString id;
|
||||
if (aElm->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_activedescendant, id)) {
|
||||
dom::Element* activeDescendantElm = aElm->OwnerDoc()->GetElementById(id);
|
||||
if (elm->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_activedescendant, id)) {
|
||||
dom::Element* activeDescendantElm = elm->OwnerDoc()->GetElementById(id);
|
||||
if (activeDescendantElm) {
|
||||
Accessible* activeDescendant = GetAccessible(activeDescendantElm);
|
||||
if (activeDescendant) {
|
||||
|
@ -1240,31 +1226,32 @@ DocAccessible::ContentStateChanged(nsIDocument* aDocument,
|
|||
nsIContent* aContent,
|
||||
nsEventStates aStateMask)
|
||||
{
|
||||
Accessible* accessible = GetAccessible(aContent);
|
||||
if (!accessible)
|
||||
return;
|
||||
|
||||
if (aStateMask.HasState(NS_EVENT_STATE_CHECKED)) {
|
||||
Accessible* item = GetAccessible(aContent);
|
||||
if (item) {
|
||||
Accessible* widget = item->ContainerWidget();
|
||||
if (widget && widget->IsSelect()) {
|
||||
AccSelChangeEvent::SelChangeType selChangeType =
|
||||
aContent->AsElement()->State().HasState(NS_EVENT_STATE_CHECKED) ?
|
||||
AccSelChangeEvent::eSelectionAdd : AccSelChangeEvent::eSelectionRemove;
|
||||
nsRefPtr<AccEvent> event = new AccSelChangeEvent(widget, item,
|
||||
selChangeType);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
}
|
||||
Accessible* widget = accessible->ContainerWidget();
|
||||
if (widget && widget->IsSelect()) {
|
||||
AccSelChangeEvent::SelChangeType selChangeType =
|
||||
aContent->AsElement()->State().HasState(NS_EVENT_STATE_CHECKED) ?
|
||||
AccSelChangeEvent::eSelectionAdd : AccSelChangeEvent::eSelectionRemove;
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccSelChangeEvent(widget, accessible, selChangeType);
|
||||
FireDelayedEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
if (aStateMask.HasState(NS_EVENT_STATE_INVALID)) {
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(aContent, states::INVALID, true);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
new AccStateChangeEvent(accessible, states::INVALID, true);
|
||||
FireDelayedEvent(event);
|
||||
}
|
||||
|
||||
if (aStateMask.HasState(NS_EVENT_STATE_VISITED)) {
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(aContent, states::TRAVERSED, true);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
new AccStateChangeEvent(accessible, states::TRAVERSED, true);
|
||||
FireDelayedEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1542,8 +1529,8 @@ DocAccessible::NotifyOfLoading(bool aIsReloading)
|
|||
// Fire state busy change event. Use delayed event since we don't care
|
||||
// actually if event isn't delivered when the document goes away like a shot.
|
||||
nsRefPtr<AccEvent> stateEvent =
|
||||
new AccStateChangeEvent(mDocument, states::BUSY, true);
|
||||
FireDelayedAccessibleEvent(stateEvent);
|
||||
new AccStateChangeEvent(this, states::BUSY, true);
|
||||
FireDelayedEvent(stateEvent);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1567,7 +1554,7 @@ DocAccessible::DoInitialUpdate()
|
|||
// a problem then consider to keep event processing per tab document.
|
||||
if (!IsRoot()) {
|
||||
nsRefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(Parent());
|
||||
ParentDocument()->FireDelayedAccessibleEvent(reorderEvent);
|
||||
ParentDocument()->FireDelayedEvent(reorderEvent);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1747,36 +1734,6 @@ DocAccessible::UpdateAccessibleOnAttrChange(dom::Element* aElement,
|
|||
return false;
|
||||
}
|
||||
|
||||
// DocAccessible public member
|
||||
nsresult
|
||||
DocAccessible::FireDelayedAccessibleEvent(uint32_t aEventType, nsINode* aNode,
|
||||
AccEvent::EEventRule aAllowDupes,
|
||||
EIsFromUserInput aIsFromUserInput)
|
||||
{
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccEvent(aEventType, aNode, aIsFromUserInput, aAllowDupes);
|
||||
NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
return FireDelayedAccessibleEvent(event);
|
||||
}
|
||||
|
||||
// DocAccessible public member
|
||||
nsresult
|
||||
DocAccessible::FireDelayedAccessibleEvent(AccEvent* aEvent)
|
||||
{
|
||||
NS_ENSURE_ARG(aEvent);
|
||||
|
||||
#ifdef A11Y_LOG
|
||||
if (logging::IsEnabled(logging::eDocLoad))
|
||||
logging::DocLoadEventFired(aEvent);
|
||||
#endif
|
||||
|
||||
if (mNotificationController)
|
||||
mNotificationController->QueueEvent(aEvent);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
DocAccessible::ProcessContentInserted(Accessible* aContainer,
|
||||
const nsTArray<nsCOMPtr<nsIContent> >* aInsertedContent)
|
||||
|
@ -1874,9 +1831,7 @@ DocAccessible::UpdateTree(Accessible* aContainer, nsIContent* aChildNode,
|
|||
Accessible* ancestor = aContainer;
|
||||
while (ancestor) {
|
||||
if (ancestor->ARIARole() == roles::ALERT) {
|
||||
nsRefPtr<AccEvent> alertEvent =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_ALERT, ancestor);
|
||||
FireDelayedAccessibleEvent(alertEvent);
|
||||
FireDelayedEvent(nsIAccessibleEvent::EVENT_ALERT, ancestor);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1892,7 +1847,7 @@ DocAccessible::UpdateTree(Accessible* aContainer, nsIContent* aChildNode,
|
|||
|
||||
// Fire reorder event so the MSAA clients know the children have changed. Also
|
||||
// the event is used internally by MSAA layer.
|
||||
FireDelayedAccessibleEvent(reorderEvent);
|
||||
FireDelayedEvent(reorderEvent);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
@ -1916,11 +1871,8 @@ DocAccessible::UpdateTreeInternal(Accessible* aChild, bool aIsInsert,
|
|||
// the changes before our processing and we may miss some menupopup
|
||||
// events. Now we just want to be consistent in content insertion/removal
|
||||
// handling.
|
||||
if (aChild->ARIARole() == roles::MENUPOPUP) {
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_END, aChild);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
}
|
||||
if (aChild->ARIARole() == roles::MENUPOPUP)
|
||||
FireDelayedEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_END, aChild);
|
||||
}
|
||||
|
||||
// Fire show/hide event.
|
||||
|
@ -1930,23 +1882,19 @@ DocAccessible::UpdateTreeInternal(Accessible* aChild, bool aIsInsert,
|
|||
else
|
||||
event = new AccHideEvent(aChild, node);
|
||||
|
||||
FireDelayedAccessibleEvent(event);
|
||||
FireDelayedEvent(event);
|
||||
aReorderEvent->AddSubMutationEvent(event);
|
||||
|
||||
if (aIsInsert) {
|
||||
roles::Role ariaRole = aChild->ARIARole();
|
||||
if (ariaRole == roles::MENUPOPUP) {
|
||||
// Fire EVENT_MENUPOPUP_START if ARIA menu appears.
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_START, aChild);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
FireDelayedEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_START, aChild);
|
||||
|
||||
} else if (ariaRole == roles::ALERT) {
|
||||
// Fire EVENT_ALERT if ARIA alert appears.
|
||||
updateFlags = eAlertAccessible;
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_ALERT, aChild);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
FireDelayedEvent(nsIAccessibleEvent::EVENT_ALERT, aChild);
|
||||
}
|
||||
|
||||
// If focused node has been shown then it means its frame was recreated
|
||||
|
@ -1996,8 +1944,7 @@ DocAccessible::CacheChildrenInSubtree(Accessible* aRoot)
|
|||
if (aRoot->HasARIARole() && !aRoot->IsDoc()) {
|
||||
a11y::role role = aRoot->ARIARole();
|
||||
if (role == roles::DIALOG || role == roles::DOCUMENT)
|
||||
FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE,
|
||||
aRoot->GetContent());
|
||||
FireDelayedEvent(nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE, aRoot);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include "nsIWeakReference.h"
|
||||
#include "nsIDocShellTreeNode.h"
|
||||
|
||||
class nsAccDocManager;
|
||||
class nsAccessiblePivot;
|
||||
|
||||
class nsIScrollableView;
|
||||
|
@ -34,6 +33,7 @@ const uint32_t kDefaultCacheSize = 256;
|
|||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
class DocManager;
|
||||
class NotificationController;
|
||||
class RelatedAccIterator;
|
||||
template<class Class, class Arg>
|
||||
|
@ -173,22 +173,10 @@ public:
|
|||
{ return mChildDocuments.SafeElementAt(aIndex, nullptr); }
|
||||
|
||||
/**
|
||||
* Non-virtual method to fire a delayed event after a 0 length timeout.
|
||||
*
|
||||
* @param aEventType [in] the nsIAccessibleEvent event type
|
||||
* @param aDOMNode [in] DOM node the accesible event should be fired for
|
||||
* @param aAllowDupes [in] rule to process an event (see EEventRule constants)
|
||||
* Fire accessible event asynchronously.
|
||||
*/
|
||||
nsresult FireDelayedAccessibleEvent(uint32_t aEventType, nsINode *aNode,
|
||||
AccEvent::EEventRule aAllowDupes = AccEvent::eRemoveDupes,
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect);
|
||||
|
||||
/**
|
||||
* Fire accessible event after timeout.
|
||||
*
|
||||
* @param aEvent [in] the event to fire
|
||||
*/
|
||||
nsresult FireDelayedAccessibleEvent(AccEvent* aEvent);
|
||||
void FireDelayedEvent(AccEvent* aEvent);
|
||||
void FireDelayedEvent(uint32_t aEventType, Accessible* aTarget);
|
||||
|
||||
/**
|
||||
* Fire value change event on the given accessible if applicable.
|
||||
|
@ -331,7 +319,7 @@ protected:
|
|||
void NotifyOfLoad(uint32_t aLoadEventType);
|
||||
void NotifyOfLoading(bool aIsReloading);
|
||||
|
||||
friend class ::nsAccDocManager;
|
||||
friend class DocManager;
|
||||
|
||||
/**
|
||||
* Perform initial update (create accessible tree).
|
||||
|
@ -398,27 +386,28 @@ protected:
|
|||
bool UpdateAccessibleOnAttrChange(mozilla::dom::Element* aElement,
|
||||
nsIAtom* aAttribute);
|
||||
|
||||
/**
|
||||
* Fires accessible events when attribute is changed.
|
||||
*
|
||||
* @param aContent - node that attribute is changed for
|
||||
* @param aNameSpaceID - namespace of changed attribute
|
||||
* @param aAttribute - changed attribute
|
||||
*/
|
||||
void AttributeChangedImpl(nsIContent* aContent, int32_t aNameSpaceID, nsIAtom* aAttribute);
|
||||
/**
|
||||
* Fire accessible events when attribute is changed.
|
||||
*
|
||||
* @param aAccessible [in] accessible the DOM attribute is changed for
|
||||
* @param aNameSpaceID [in] namespace of changed attribute
|
||||
* @param aAttribute [in] changed attribute
|
||||
*/
|
||||
void AttributeChangedImpl(Accessible* aAccessible,
|
||||
int32_t aNameSpaceID, nsIAtom* aAttribute);
|
||||
|
||||
/**
|
||||
* Fires accessible events when ARIA attribute is changed.
|
||||
*
|
||||
* @param aContent - node that attribute is changed for
|
||||
* @param aAttribute - changed attribute
|
||||
*/
|
||||
void ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute);
|
||||
/**
|
||||
* Fire accessible events when ARIA attribute is changed.
|
||||
*
|
||||
* @param aAccessible [in] accesislbe the DOM attribute is changed for
|
||||
* @param aAttribute [in] changed attribute
|
||||
*/
|
||||
void ARIAAttributeChanged(Accessible* aAccessible, nsIAtom* aAttribute);
|
||||
|
||||
/**
|
||||
* Process ARIA active-descendant attribute change.
|
||||
*/
|
||||
void ARIAActiveDescendantChanged(nsIContent* aElm);
|
||||
void ARIAActiveDescendantChanged(Accessible* aAccessible);
|
||||
|
||||
/**
|
||||
* Update the accessible tree for inserted content.
|
||||
|
|
|
@ -135,13 +135,13 @@ OuterDocAccessible::Shutdown()
|
|||
void
|
||||
OuterDocAccessible::InvalidateChildren()
|
||||
{
|
||||
// Do not invalidate children because nsAccDocManager is responsible for
|
||||
// Do not invalidate children because DocManager is responsible for
|
||||
// document accessible lifetime when DOM document is created or destroyed. If
|
||||
// DOM document isn't destroyed but its presshell is destroyed (for example,
|
||||
// when DOM node of outerdoc accessible is hidden), then outerdoc accessible
|
||||
// notifies nsAccDocManager about this. If presshell is created for existing
|
||||
// notifies DocManager about this. If presshell is created for existing
|
||||
// DOM document (for example when DOM node of outerdoc accessible is shown)
|
||||
// then allow nsAccDocManager to handle this case since the document
|
||||
// then allow DocManager to handle this case since the document
|
||||
// accessible is created and appended as a child when it's requested.
|
||||
|
||||
SetChildrenFlag(eChildrenUninitialized);
|
||||
|
|
|
@ -311,8 +311,6 @@ RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent)
|
|||
if (!accessible)
|
||||
return;
|
||||
|
||||
nsINode* targetNode = accessible->GetNode();
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
XULTreeAccessible* treeAcc = accessible->AsXULTree();
|
||||
if (treeAcc) {
|
||||
|
@ -383,6 +381,7 @@ RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent)
|
|||
return;
|
||||
}
|
||||
|
||||
nsINode* targetNode = accessible->GetNode();
|
||||
if (treeItemAcc && eventType.EqualsLiteral("select")) {
|
||||
// XXX: We shouldn't be based on DOM select event which doesn't provide us
|
||||
// any context info. We should integrate into nsTreeSelection instead.
|
||||
|
@ -478,10 +477,10 @@ RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent)
|
|||
|
||||
//We don't process 'ValueChange' events for progress meters since we listen
|
||||
//@value attribute change for them.
|
||||
if (!accessible->IsProgress())
|
||||
targetDocument->
|
||||
FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE,
|
||||
targetNode);
|
||||
if (!accessible->IsProgress()) {
|
||||
targetDocument->FireDelayedEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE,
|
||||
accessible);
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_DRAGDROPSTART
|
||||
else if (eventType.EqualsLiteral("mouseover")) {
|
||||
|
@ -677,7 +676,7 @@ RootAccessible::HandlePopupHidingEvent(nsINode* aPopupNode)
|
|||
if (notifyOf & kNotifyOfState) {
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(widget, states::EXPANDED, false);
|
||||
document->FireDelayedAccessibleEvent(event);
|
||||
document->FireDelayedEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsARIAMap.h"
|
||||
#include "DocAccessible.h"
|
||||
#include "DocAccessible-inl.h"
|
||||
#include "Role.h"
|
||||
|
||||
#include "nsIDOMHTMLCollection.h"
|
||||
|
@ -95,7 +95,7 @@ HTMLImageMapAccessible::UpdateChildAreas(bool aDoFireEvents)
|
|||
|
||||
if (aDoFireEvents) {
|
||||
nsRefPtr<AccHideEvent> event = new AccHideEvent(area, area->GetContent());
|
||||
mDoc->FireDelayedAccessibleEvent(event);
|
||||
mDoc->FireDelayedEvent(event);
|
||||
reorderEvent->AddSubMutationEvent(event);
|
||||
doReorderEvent = true;
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ HTMLImageMapAccessible::UpdateChildAreas(bool aDoFireEvents)
|
|||
|
||||
if (aDoFireEvents) {
|
||||
nsRefPtr<AccShowEvent> event = new AccShowEvent(area, areaContent);
|
||||
mDoc->FireDelayedAccessibleEvent(event);
|
||||
mDoc->FireDelayedEvent(event);
|
||||
reorderEvent->AddSubMutationEvent(event);
|
||||
doReorderEvent = true;
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ HTMLImageMapAccessible::UpdateChildAreas(bool aDoFireEvents)
|
|||
|
||||
// Fire reorder event if needed.
|
||||
if (doReorderEvent)
|
||||
mDoc->FireDelayedAccessibleEvent(reorderEvent);
|
||||
mDoc->FireDelayedEvent(reorderEvent);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -50,10 +50,7 @@ var gSimpleTraversalRoles =
|
|||
Ci.nsIAccessibleRole.ROLE_LINK,
|
||||
Ci.nsIAccessibleRole.ROLE_PAGETAB,
|
||||
Ci.nsIAccessibleRole.ROLE_GRAPHIC,
|
||||
// XXX: Find a better solution for ROLE_STATICTEXT.
|
||||
// It allows to filter list bullets but at the same time it
|
||||
// filters CSS generated content too as an unwanted side effect.
|
||||
// Ci.nsIAccessibleRole.ROLE_STATICTEXT,
|
||||
Ci.nsIAccessibleRole.ROLE_STATICTEXT,
|
||||
Ci.nsIAccessibleRole.ROLE_TEXT_LEAF,
|
||||
Ci.nsIAccessibleRole.ROLE_PUSHBUTTON,
|
||||
Ci.nsIAccessibleRole.ROLE_CHECKBUTTON,
|
||||
|
@ -95,6 +92,16 @@ this.TraversalRules = {
|
|||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
else
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
|
||||
case Ci.nsIAccessibleRole.ROLE_STATICTEXT:
|
||||
{
|
||||
let parent = aAccessible.parent;
|
||||
// Ignore prefix static text in list items. They are typically bullets or numbers.
|
||||
if (parent.childCount > 1 && aAccessible.indexInParent == 0 &&
|
||||
parent.role == Ci.nsIAccessibleRole.ROLE_LISTITEM)
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
|
||||
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
}
|
||||
default:
|
||||
// Ignore the subtree, if there is one. So that we don't land on
|
||||
// the same content that was already presented by its parent.
|
||||
|
|
|
@ -45,7 +45,7 @@ nsAccEvent::GetDOMNode(nsIDOMNode** aDOMNode)
|
|||
NS_ENSURE_ARG_POINTER(aDOMNode);
|
||||
*aDOMNode = nullptr;
|
||||
|
||||
nsINode* node = mEvent->GetNode();
|
||||
nsINode* node = mEvent->GetAccessible()->GetNode();
|
||||
if (node)
|
||||
CallQueryInterface(node, aDOMNode);
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "XULTreeAccessible.h"
|
||||
|
||||
#include "DocAccessible-inl.h"
|
||||
#include "nsAccCache.h"
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsCoreUtils.h"
|
||||
|
@ -663,7 +664,7 @@ XULTreeAccessible::TreeViewChanged(nsITreeView* aView)
|
|||
// show/hide events on tree items because it can be expensive to fire them for
|
||||
// each tree item.
|
||||
nsRefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(this);
|
||||
Document()->FireDelayedAccessibleEvent(reorderEvent);
|
||||
Document()->FireDelayedEvent(reorderEvent);
|
||||
|
||||
// Clear cache.
|
||||
ClearCache(mAccessibleCache);
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
|
||||
if (!MAC) { // Mac failure is bug 541093
|
||||
var checker =
|
||||
new eventFromInputChecker(EVENT_TEXT_CARET_MOVED, id, "false", noTargetId);
|
||||
new eventFromInputChecker(EVENT_TEXT_CARET_MOVED, id, "true", noTargetId);
|
||||
gQueue.push(new synthHomeKey(id, checker));
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ include $(DEPTH)/config/autoconf.mk
|
|||
|
||||
MOCHITEST_A11Y_FILES =\
|
||||
dockids.html \
|
||||
$(warning test_applicationacc.xul temporarily disabled, see bug 561508) \
|
||||
$(filter disabled-temporarily--bug-561508, test_applicationacc.xul) \
|
||||
test_aria_globals.html \
|
||||
test_aria_grid.html \
|
||||
test_aria_imgmap.html \
|
||||
|
|
|
@ -584,6 +584,9 @@ pref("network.activity.blipIntervalMilliseconds", 250);
|
|||
|
||||
pref("jsloader.reuseGlobal", true);
|
||||
|
||||
// Enable font inflation for browser tab content.
|
||||
pref("font.size.inflation.minTwips", 120);
|
||||
|
||||
// Enable freeing dirty pages when minimizing memory; this reduces memory
|
||||
// consumption when applications are sent to the background.
|
||||
pref("memory.free_dirty_pages", true);
|
||||
|
|
|
@ -158,6 +158,10 @@ int main(int argc, char* argv[])
|
|||
{
|
||||
char exePath[MAXPATHLEN];
|
||||
|
||||
#if defined(MOZ_X11)
|
||||
putenv("MOZ_USE_OMTC=1");
|
||||
#endif
|
||||
|
||||
nsresult rv = mozilla::BinaryPath::Get(argv[0], exePath);
|
||||
if (NS_FAILED(rv)) {
|
||||
Output("Couldn't calculate the application directory.\n");
|
||||
|
|
|
@ -55,6 +55,9 @@ var func = null;
|
|||
* assertion: optional assertion
|
||||
*/
|
||||
function identityCall(message) {
|
||||
if (options._internal) {
|
||||
message._internal = options._internal;
|
||||
}
|
||||
sendAsyncMessage(kIdentityControllerDoMethod, message);
|
||||
}
|
||||
|
||||
|
@ -78,7 +81,7 @@ function doInternalWatch() {
|
|||
log("doInternalWatch:", options, isLoaded);
|
||||
if (options && isLoaded) {
|
||||
let BrowserID = content.wrappedJSObject.BrowserID;
|
||||
BrowserID.internal.watch(function(aParams) {
|
||||
BrowserID.internal.watch(function(aParams, aInternalParams) {
|
||||
identityCall(aParams);
|
||||
if (aParams.method === "ready") {
|
||||
closeIdentityDialog();
|
||||
|
@ -86,7 +89,7 @@ function doInternalWatch() {
|
|||
},
|
||||
JSON.stringify(options),
|
||||
function(...things) {
|
||||
log("internal: ", things);
|
||||
log("(watch) internal: ", things);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -97,9 +100,13 @@ function doInternalRequest() {
|
|||
if (options && isLoaded) {
|
||||
content.wrappedJSObject.BrowserID.internal.get(
|
||||
options.origin,
|
||||
function(assertion) {
|
||||
function(assertion, internalParams) {
|
||||
internalParams = internalParams || {};
|
||||
if (assertion) {
|
||||
identityCall({method: 'login', assertion: assertion});
|
||||
identityCall({
|
||||
method: 'login',
|
||||
assertion: assertion,
|
||||
_internalParams: internalParams});
|
||||
}
|
||||
closeIdentityDialog();
|
||||
},
|
||||
|
|
|
@ -113,6 +113,10 @@ var shell = {
|
|||
|
||||
// This function submits a crash when we're online.
|
||||
submitCrash: function shell_submitCrash(aCrashID) {
|
||||
if (!Services.io.offline) {
|
||||
this.CrashSubmit.submit(aCrashID);
|
||||
return;
|
||||
}
|
||||
Services.obs.addObserver(function observer(subject, topic, state) {
|
||||
if (state == 'online') {
|
||||
shell.CrashSubmit.submit(aCrashID);
|
||||
|
|
|
@ -60,7 +60,9 @@ function ContentPermissionPrompt() {}
|
|||
ContentPermissionPrompt.prototype = {
|
||||
|
||||
handleExistingPermission: function handleExistingPermission(request) {
|
||||
let result = Services.perms.testExactPermissionFromPrincipal(request.principal, request.type);
|
||||
let access = (request.access && request.access !== "unused") ? request.type + "-" + request.access :
|
||||
request.type;
|
||||
let result = Services.perms.testExactPermissionFromPrincipal(request.principal, access);
|
||||
if (result == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||
request.allow();
|
||||
return true;
|
||||
|
@ -83,6 +85,9 @@ ContentPermissionPrompt.prototype = {
|
|||
if (!content)
|
||||
return;
|
||||
|
||||
let access = (request.access && request.access !== "unused") ? request.type + "-" + request.access :
|
||||
request.type;
|
||||
|
||||
let requestId = this._id++;
|
||||
content.addEventListener("mozContentEvent", function contentEvent(evt) {
|
||||
if (evt.detail.id != requestId)
|
||||
|
@ -92,8 +97,6 @@ ContentPermissionPrompt.prototype = {
|
|||
if (evt.detail.type == "permission-allow") {
|
||||
if (evt.detail.remember) {
|
||||
rememberPermission(request.type, request.principal);
|
||||
Services.perms.addFromPrincipal(request.principal, request.type,
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
}
|
||||
|
||||
request.allow();
|
||||
|
@ -101,7 +104,7 @@ ContentPermissionPrompt.prototype = {
|
|||
}
|
||||
|
||||
if (evt.detail.remember) {
|
||||
Services.perms.addFromPrincipal(request.principal, request.type,
|
||||
Services.perms.addFromPrincipal(request.principal, access,
|
||||
Ci.nsIPermissionManager.DENY_ACTION);
|
||||
}
|
||||
|
||||
|
@ -120,7 +123,7 @@ ContentPermissionPrompt.prototype = {
|
|||
remember: request.remember
|
||||
};
|
||||
|
||||
this._permission = request.type;
|
||||
this._permission = access;
|
||||
this._uri = request.principal.URI.spec;
|
||||
this._origin = request.principal.origin;
|
||||
|
||||
|
|
|
@ -305,7 +305,11 @@ this.SignInToWebsiteController = {
|
|||
break;
|
||||
|
||||
case "login":
|
||||
IdentityService.doLogin(aRpId, message.assertion);
|
||||
if (message._internalParams) {
|
||||
IdentityService.doLogin(aRpId, message.assertion, message._internalParams);
|
||||
} else {
|
||||
IdentityService.doLogin(aRpId, message.assertion);
|
||||
}
|
||||
break;
|
||||
|
||||
case "logout":
|
||||
|
|
|
@ -321,14 +321,6 @@ UpdatePrompt.prototype = {
|
|||
forceUpdateCheck: function UP_forceUpdateCheck() {
|
||||
log("Forcing update check");
|
||||
|
||||
// If we already have an active update available, don't try to
|
||||
// download again, just prompt for install.
|
||||
if (Services.um.activeUpdate) {
|
||||
this.setUpdateStatus("check-complete");
|
||||
this.showApplyPrompt(Services.um.activeUpdate);
|
||||
return;
|
||||
}
|
||||
|
||||
let checker = Cc["@mozilla.org/updates/update-checker;1"]
|
||||
.createInstance(Ci.nsIUpdateChecker);
|
||||
checker.checkForUpdates(this._updateCheckListener, true);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[
|
||||
{
|
||||
"clang_version": "r167750"
|
||||
"clang_version": "r168304"
|
||||
},
|
||||
{
|
||||
"size": 47,
|
||||
|
@ -9,8 +9,8 @@
|
|||
"filename": "setup.sh"
|
||||
},
|
||||
{
|
||||
"size": 56161789,
|
||||
"digest": "43a35be63f9ea1c73a1b22532b5484b131f0c25bdb6a2f39e31c968b6c3477f6640450cc8dab8e17df80f20e367b8cbc0a74986a4eefd7ac9b9adf2b0859e55e",
|
||||
"size": 56144782,
|
||||
"digest": "7e7dd6775d71d074cced8407fac82dc5e161a9034927bd059c84fc06da161da39d32bbd95ac9b6efdf550370fa351361bc476f0b327387dc8d503dc446a776d6",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2"
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ MOZ_OFFICIAL_BRANDING_DIRECTORY=b2g/branding/official
|
|||
|
||||
MOZ_SAFE_BROWSING=
|
||||
MOZ_SERVICES_COMMON=1
|
||||
MOZ_SERVICES_HEALTHREPORT=1
|
||||
MOZ_SERVICES_METRICS=1
|
||||
|
||||
MOZ_WEBSMS_BACKEND=1
|
||||
MOZ_DISABLE_DOMCRYPTO=1
|
||||
|
|
|
@ -54,7 +54,6 @@
|
|||
@BINPATH@/@DLL_PREFIX@xpcom@DLL_SUFFIX@
|
||||
@BINPATH@/@DLL_PREFIX@nspr4@DLL_SUFFIX@
|
||||
@BINPATH@/@DLL_PREFIX@mozalloc@DLL_SUFFIX@
|
||||
@BINPATH@/@DLL_PREFIX@soundtouch@DLL_SUFFIX@
|
||||
#ifdef XP_MACOSX
|
||||
@BINPATH@/XUL
|
||||
#else
|
||||
|
@ -484,6 +483,10 @@
|
|||
@BINPATH@/components/WeaveCrypto.manifest
|
||||
@BINPATH@/components/WeaveCrypto.js
|
||||
#endif
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
@BINPATH@/components/HealthReportComponents.manifest
|
||||
@BINPATH@/components/HealthReportService.js
|
||||
#endif
|
||||
@BINPATH@/components/TelemetryPing.js
|
||||
@BINPATH@/components/TelemetryPing.manifest
|
||||
@BINPATH@/components/Webapps.js
|
||||
|
@ -575,6 +578,9 @@
|
|||
#ifdef MOZ_SERVICES_SYNC
|
||||
@BINPATH@/@PREF_DIR@/services-sync.js
|
||||
#endif
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
@BINPATH@/@PREF_DIR@/healthreport-prefs.js
|
||||
#endif
|
||||
@BINPATH@/greprefs.js
|
||||
@BINPATH@/defaults/autoconfig/platform.js
|
||||
@BINPATH@/defaults/autoconfig/prefcalls.js
|
||||
|
|
|
@ -508,12 +508,13 @@
|
|||
<menu id="menu_socialAmbientMenu">
|
||||
<menupopup id="menu_social-statusarea-popup">
|
||||
<menuitem class="social-statusarea-user menuitem-iconic" pack="start" align="center"
|
||||
observes="socialBroadcaster_userDetails"
|
||||
oncommand="SocialUI.showProfile(); document.getElementById('social-statusarea-popup').hidePopup();">
|
||||
<image class="social-statusarea-user-portrait"
|
||||
observes="socialBroadcaster_userPortrait"/>
|
||||
observes="socialBroadcaster_userDetails"/>
|
||||
<vbox>
|
||||
<label class="social-statusarea-loggedInStatus"
|
||||
observes="socialBroadcaster_loggedInStatus"/>
|
||||
observes="socialBroadcaster_userDetails"/>
|
||||
</vbox>
|
||||
</menuitem>
|
||||
#ifndef XP_WIN
|
||||
|
|
|
@ -113,6 +113,34 @@ var gPluginHandler = {
|
|||
true);
|
||||
},
|
||||
|
||||
// Helper to get the binding handler type from a plugin object
|
||||
_getBindingType : function(plugin) {
|
||||
if (!(plugin instanceof Ci.nsIObjectLoadingContent))
|
||||
return;
|
||||
|
||||
switch (plugin.pluginFallbackType) {
|
||||
case Ci.nsIObjectLoadingContent.PLUGIN_UNSUPPORTED:
|
||||
return "PluginNotFound";
|
||||
case Ci.nsIObjectLoadingContent.PLUGIN_DISABLED:
|
||||
return "PluginDisabled";
|
||||
case Ci.nsIObjectLoadingContent.PLUGIN_BLOCKLISTED:
|
||||
return "PluginBlocklisted";
|
||||
case Ci.nsIObjectLoadingContent.PLUGIN_OUTDATED:
|
||||
return "PluginOutdated";
|
||||
case Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY:
|
||||
return "PluginClickToPlay";
|
||||
case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE:
|
||||
return "PluginVulnerableUpdatable";
|
||||
case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE:
|
||||
return "PluginVulnerableNoUpdate";
|
||||
case Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW:
|
||||
return "PluginPlayPreview";
|
||||
default:
|
||||
// Not all states map to a handler
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
handleEvent : function(event) {
|
||||
let self = gPluginHandler;
|
||||
let plugin = event.target;
|
||||
|
@ -122,10 +150,26 @@ var gPluginHandler = {
|
|||
if (!(plugin instanceof Ci.nsIObjectLoadingContent))
|
||||
return;
|
||||
|
||||
// Force a style flush, so that we ensure our binding is attached.
|
||||
plugin.clientTop;
|
||||
let eventType = event.type;
|
||||
if (eventType == "PluginBindingAttached") {
|
||||
// The plugin binding fires this event when it is created.
|
||||
// As an untrusted event, ensure that this object actually has a binding
|
||||
// and make sure we don't handle it twice
|
||||
let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
|
||||
if (!overlay || overlay._bindingHandled) {
|
||||
return;
|
||||
}
|
||||
overlay._bindingHandled = true;
|
||||
|
||||
switch (event.type) {
|
||||
// Lookup the handler for this binding
|
||||
eventType = self._getBindingType(plugin);
|
||||
if (!eventType) {
|
||||
// Not all bindings have handlers
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (eventType) {
|
||||
case "PluginCrashed":
|
||||
self.pluginInstanceCrashed(plugin, event);
|
||||
break;
|
||||
|
@ -151,7 +195,7 @@ var gPluginHandler = {
|
|||
#ifdef XP_MACOSX
|
||||
case "npapi-carbon-event-model-failure":
|
||||
#endif
|
||||
self.pluginUnavailable(plugin, event.type);
|
||||
self.pluginUnavailable(plugin, eventType);
|
||||
break;
|
||||
|
||||
case "PluginVulnerableUpdatable":
|
||||
|
@ -167,9 +211,9 @@ var gPluginHandler = {
|
|||
let messageString = gNavigatorBundle.getFormattedString("PluginClickToPlay", [pluginName]);
|
||||
let overlayText = doc.getAnonymousElementByAttribute(plugin, "class", "msg msgClickToPlay");
|
||||
overlayText.textContent = messageString;
|
||||
if (event.type == "PluginVulnerableUpdatable" ||
|
||||
event.type == "PluginVulnerableNoUpdate") {
|
||||
let vulnerabilityString = gNavigatorBundle.getString(event.type);
|
||||
if (eventType == "PluginVulnerableUpdatable" ||
|
||||
eventType == "PluginVulnerableNoUpdate") {
|
||||
let vulnerabilityString = gNavigatorBundle.getString(eventType);
|
||||
let vulnerabilityText = doc.getAnonymousElementByAttribute(plugin, "anonid", "vulnerabilityStatus");
|
||||
vulnerabilityText.textContent = vulnerabilityString;
|
||||
}
|
||||
|
@ -186,9 +230,8 @@ var gPluginHandler = {
|
|||
}
|
||||
|
||||
// Hide the in-content UI if it's too big. The crashed plugin handler already did this.
|
||||
if (event.type != "PluginCrashed") {
|
||||
if (eventType != "PluginCrashed") {
|
||||
let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
|
||||
/* overlay might be null, so only operate on it if it exists */
|
||||
if (overlay != null && self.isTooSmall(plugin, overlay))
|
||||
overlay.style.visibility = "hidden";
|
||||
}
|
||||
|
@ -321,7 +364,6 @@ var gPluginHandler = {
|
|||
return;
|
||||
}
|
||||
|
||||
// The overlay is null if the XBL binding is not attached (element is display:none).
|
||||
if (overlay) {
|
||||
overlay.addEventListener("click", function(aEvent) {
|
||||
// Have to check that the target is not the link to update the plugin
|
||||
|
@ -341,11 +383,6 @@ var gPluginHandler = {
|
|||
_handlePlayPreviewEvent: function PH_handlePlayPreviewEvent(aPlugin) {
|
||||
let doc = aPlugin.ownerDocument;
|
||||
let previewContent = doc.getAnonymousElementByAttribute(aPlugin, "class", "previewPluginContent");
|
||||
if (!previewContent) {
|
||||
// the XBL binding is not attached (element is display:none), fallback to click-to-play logic
|
||||
gPluginHandler.stopPlayPreview(aPlugin, false);
|
||||
return;
|
||||
}
|
||||
let iframe = previewContent.getElementsByClassName("previewPluginContentFrame")[0];
|
||||
if (!iframe) {
|
||||
// lazy initialization of the iframe
|
||||
|
@ -754,6 +791,9 @@ var gPluginHandler = {
|
|||
//
|
||||
// Configure the crashed-plugin placeholder.
|
||||
//
|
||||
|
||||
// Force a layout flush so the binding is attached.
|
||||
plugin.clientTop;
|
||||
let doc = plugin.ownerDocument;
|
||||
let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
|
||||
let statusDiv = doc.getAnonymousElementByAttribute(plugin, "class", "submitStatus");
|
||||
|
|
|
@ -252,8 +252,7 @@
|
|||
oncommand="openUILinkIn('https://addons.mozilla.org/firefox/collections/mozilla/webdeveloper/', 'tab');"/>
|
||||
|
||||
<!-- SocialAPI broadcasters -->
|
||||
<broadcaster id="socialBroadcaster_userPortrait"/>
|
||||
<broadcaster id="socialBroadcaster_loggedInStatus"
|
||||
<broadcaster id="socialBroadcaster_userDetails"
|
||||
notLoggedInLabel="&social.notLoggedIn.label;"/>
|
||||
</broadcasterset>
|
||||
|
||||
|
|
|
@ -254,10 +254,7 @@ let SocialChatBar = {
|
|||
}
|
||||
},
|
||||
focus: function SocialChatBar_focus() {
|
||||
if (!this.chatbar.selectedChat)
|
||||
return;
|
||||
let commandDispatcher = gBrowser.ownerDocument.commandDispatcher;
|
||||
commandDispatcher.advanceFocusIntoSubtree(this.chatbar.selectedChat);
|
||||
this.chatbar.focus();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -673,12 +670,19 @@ var SocialToolbar = {
|
|||
// social:profile-changed
|
||||
let profile = Social.provider.profile || {};
|
||||
let userPortrait = profile.portrait || "chrome://global/skin/icons/information-32.png";
|
||||
document.getElementById("socialBroadcaster_userPortrait").setAttribute("src", userPortrait);
|
||||
|
||||
let loggedInStatusBroadcaster = document.getElementById("socialBroadcaster_loggedInStatus");
|
||||
let notLoggedInString = loggedInStatusBroadcaster.getAttribute("notLoggedInLabel");
|
||||
let loggedInStatusValue = profile.userName ? profile.userName : notLoggedInString;
|
||||
loggedInStatusBroadcaster.setAttribute("value", loggedInStatusValue);
|
||||
let userDetailsBroadcaster = document.getElementById("socialBroadcaster_userDetails");
|
||||
let loggedInStatusValue = profile.userName ?
|
||||
profile.userName :
|
||||
userDetailsBroadcaster.getAttribute("notLoggedInLabel");;
|
||||
|
||||
// "image" and "label" are used by Mac's native menus that do not render the menuitem's children
|
||||
// elements. "src" and "value" are used by the image/label children on the other platforms.
|
||||
userDetailsBroadcaster.setAttribute("src", userPortrait);
|
||||
userDetailsBroadcaster.setAttribute("image", userPortrait);
|
||||
|
||||
userDetailsBroadcaster.setAttribute("value", loggedInStatusValue);
|
||||
userDetailsBroadcaster.setAttribute("label", loggedInStatusValue);
|
||||
},
|
||||
|
||||
updateButton: function SocialToolbar_updateButton() {
|
||||
|
|
|
@ -1012,15 +1012,11 @@ var gBrowserInit = {
|
|||
|
||||
gBrowser.addEventListener("DOMUpdatePageReport", gPopupBlockerObserver, false);
|
||||
|
||||
gBrowser.addEventListener("PluginNotFound", gPluginHandler, true);
|
||||
gBrowser.addEventListener("PluginCrashed", gPluginHandler, true);
|
||||
gBrowser.addEventListener("PluginBlocklisted", gPluginHandler, true);
|
||||
gBrowser.addEventListener("PluginOutdated", gPluginHandler, true);
|
||||
gBrowser.addEventListener("PluginDisabled", gPluginHandler, true);
|
||||
gBrowser.addEventListener("PluginClickToPlay", gPluginHandler, true);
|
||||
gBrowser.addEventListener("PluginPlayPreview", gPluginHandler, true);
|
||||
gBrowser.addEventListener("PluginVulnerableUpdatable", gPluginHandler, true);
|
||||
gBrowser.addEventListener("PluginVulnerableNoUpdate", gPluginHandler, true);
|
||||
// Note that the XBL binding is untrusted
|
||||
gBrowser.addEventListener("PluginBindingAttached", gPluginHandler, true, true);
|
||||
gBrowser.addEventListener("PluginCrashed", gPluginHandler, true);
|
||||
gBrowser.addEventListener("PluginOutdated", gPluginHandler, true);
|
||||
|
||||
gBrowser.addEventListener("NewPluginInstalled", gPluginHandler.newPluginInstalled, true);
|
||||
#ifdef XP_MACOSX
|
||||
gBrowser.addEventListener("npapi-carbon-event-model-failure", gPluginHandler, true);
|
||||
|
@ -3540,15 +3536,18 @@ function OpenBrowserWindow(options)
|
|||
var wintype = document.documentElement.getAttribute('windowtype');
|
||||
|
||||
var extraFeatures = "";
|
||||
var forcePrivate = false;
|
||||
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
if (typeof options == "object" &&
|
||||
"private" in options &&
|
||||
options.private) {
|
||||
forcePrivate = typeof options == "object" && "private" in options && options.private;
|
||||
#else
|
||||
forcePrivate = gPrivateBrowsingUI.privateBrowsingEnabled;
|
||||
#endif
|
||||
|
||||
if (forcePrivate) {
|
||||
extraFeatures = ",private";
|
||||
// Force the new window to load about:privatebrowsing instead of the default home page
|
||||
defaultArgs = "about:privatebrowsing";
|
||||
}
|
||||
#endif
|
||||
|
||||
// if and only if the current window is a browser window and it has a document with a character
|
||||
// set, then extract the current charset menu setting from the current document and use it to
|
||||
|
|
|
@ -668,12 +668,13 @@
|
|||
type="menu">
|
||||
<menupopup id="social-statusarea-popup">
|
||||
<menuitem class="social-statusarea-user menuitem-iconic" pack="start" align="center"
|
||||
observes="socialBroadcaster_userDetails"
|
||||
oncommand="SocialUI.showProfile(); document.getElementById('social-statusarea-popup').hidePopup();">
|
||||
<image class="social-statusarea-user-portrait"
|
||||
observes="socialBroadcaster_userPortrait"/>
|
||||
observes="socialBroadcaster_userDetails"/>
|
||||
<vbox>
|
||||
<label class="social-statusarea-loggedInStatus"
|
||||
observes="socialBroadcaster_loggedInStatus"/>
|
||||
observes="socialBroadcaster_userDetails"/>
|
||||
</vbox>
|
||||
</menuitem>
|
||||
#ifndef XP_WIN
|
||||
|
|
|
@ -27,13 +27,20 @@
|
|||
<getter>
|
||||
return this.getAttribute("minimized") == "true";
|
||||
</getter>
|
||||
<setter>
|
||||
<setter><![CDATA[
|
||||
this.isActive = !val;
|
||||
if (val)
|
||||
let parent = this.parentNode;
|
||||
if (val) {
|
||||
this.setAttribute("minimized", "true");
|
||||
else
|
||||
// If this chat is the selected one a new one needs to be selected.
|
||||
if (parent.selectedChat == this)
|
||||
parent._selectAnotherChat();
|
||||
} else {
|
||||
this.removeAttribute("minimized");
|
||||
</setter>
|
||||
// this chat gets selected.
|
||||
parent.selectedChat = this;
|
||||
}
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<property name="isActive">
|
||||
|
@ -123,6 +130,15 @@
|
|||
document.getAnonymousElementByAttribute(this, "anonid", "nub");
|
||||
</field>
|
||||
|
||||
<method name="focus">
|
||||
<body><![CDATA[
|
||||
if (!this.selectedChat)
|
||||
return;
|
||||
let commandDispatcher = gBrowser.ownerDocument.commandDispatcher;
|
||||
commandDispatcher.advanceFocusIntoSubtree(this.selectedChat);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<property name="selectedChat">
|
||||
<getter><![CDATA[
|
||||
return this._selectedChat;
|
||||
|
@ -141,6 +157,7 @@
|
|||
this._selectedChat = val;
|
||||
if (val) {
|
||||
this._selectedChat.setAttribute("selected", "true");
|
||||
this.focus();
|
||||
}
|
||||
}
|
||||
if (val) {
|
||||
|
@ -162,11 +179,11 @@
|
|||
<getter><![CDATA[
|
||||
// A generator yielding all collapsed chatboxes, in the order in
|
||||
// which they should be restored.
|
||||
let child = this.lastChild;
|
||||
let child = this.lastElementChild;
|
||||
while (child) {
|
||||
if (child.collapsed)
|
||||
yield child;
|
||||
child = child.previousSibling;
|
||||
child = child.previousElementSibling;
|
||||
}
|
||||
]]></getter>
|
||||
</property>
|
||||
|
@ -174,11 +191,11 @@
|
|||
<property name="visibleChildren">
|
||||
<getter><![CDATA[
|
||||
// A generator yielding all non-collapsed chatboxes.
|
||||
let child = this.firstChild;
|
||||
let child = this.firstElementChild;
|
||||
while (child) {
|
||||
if (!child.collapsed)
|
||||
yield child;
|
||||
child = child.nextSibling;
|
||||
child = child.nextElementSibling;
|
||||
}
|
||||
]]></getter>
|
||||
</property>
|
||||
|
@ -194,6 +211,26 @@
|
|||
]]></getter>
|
||||
</property>
|
||||
|
||||
<method name="_selectAnotherChat">
|
||||
<body><![CDATA[
|
||||
// Select a different chat (as the currently selected one is no
|
||||
// longer suitable as the selection - maybe it is being minimized or
|
||||
// closed.) We only select non-minimized and non-collapsed chats,
|
||||
// and if none are found, set the selectedChat to null.
|
||||
// It's possible in the future we will track most-recently-selected
|
||||
// chats or similar to find the "best" candidate - for now though
|
||||
// the choice is somewhat arbitrary.
|
||||
for (let other of this.children) {
|
||||
if (other != this.selectedChat && !other.minimized && !other.collapsed) {
|
||||
this.selectedChat = other;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// can't find another - so set no chat as selected.
|
||||
this.selectedChat = null;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="updateTitlebar">
|
||||
<parameter name="aChatbox"/>
|
||||
<body><![CDATA[
|
||||
|
@ -306,7 +343,7 @@
|
|||
<parameter name="aChatbox"/>
|
||||
<body><![CDATA[
|
||||
if (this.selectedChat == aChatbox) {
|
||||
this.selectedChat = aChatbox.previousSibling ? aChatbox.previousSibling : aChatbox.nextSibling
|
||||
this._selectAnotherChat();
|
||||
}
|
||||
this.removeChild(aChatbox);
|
||||
// child might have been collapsed.
|
||||
|
@ -321,8 +358,9 @@
|
|||
|
||||
<method name="removeAll">
|
||||
<body><![CDATA[
|
||||
while (this.firstChild) {
|
||||
this._remove(this.firstChild);
|
||||
this.selectedChat = null;
|
||||
while (this.firstElementChild) {
|
||||
this._remove(this.firstElementChild);
|
||||
}
|
||||
// and the nub/popup must also die.
|
||||
this.nub.collapsed = true;
|
||||
|
@ -396,8 +434,8 @@
|
|||
cb = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "chatbox");
|
||||
if (aMode == "minimized")
|
||||
cb.setAttribute("minimized", "true");
|
||||
this.selectedChat = cb;
|
||||
this.insertBefore(cb, this.firstChild);
|
||||
this.selectedChat = cb;
|
||||
this.initChatBox(cb, aProvider, aURL, aCallback);
|
||||
this.chatboxForURL.set(aURL, Cu.getWeakReference(cb));
|
||||
this.resize();
|
||||
|
|
|
@ -304,7 +304,7 @@ endif
|
|||
ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
_BROWSER_FILES += \
|
||||
browser_private_browsing_window.js \
|
||||
$(warning browser_save_link-perwindowpb.js disabled until bug 722850) \
|
||||
$(filter disabled-until-bug-722850, browser_save_link-perwindowpb.js) \
|
||||
$(NULL)
|
||||
else
|
||||
_BROWSER_FILES += \
|
||||
|
|
|
@ -14,7 +14,7 @@ function test() {
|
|||
var newTab = gBrowser.addTab();
|
||||
gBrowser.selectedTab = newTab;
|
||||
gTestBrowser = gBrowser.selectedBrowser;
|
||||
gTestBrowser.addEventListener("PluginNotFound", pluginNotFound, true);
|
||||
gTestBrowser.addEventListener("PluginBindingAttached", pluginBindingAttached, true, true);
|
||||
var consoleService = Cc["@mozilla.org/consoleservice;1"]
|
||||
.getService(Ci.nsIConsoleService);
|
||||
var errorListener = {
|
||||
|
@ -25,7 +25,7 @@ function test() {
|
|||
};
|
||||
consoleService.registerListener(errorListener);
|
||||
registerCleanupFunction(function() {
|
||||
gTestBrowser.removeEventListener("PluginNotFound", pluginNotFound, true);
|
||||
gTestBrowser.removeEventListener("PluginBindingAttached", pluginBindingAttached, true);
|
||||
consoleService.unregisterListener(errorListener);
|
||||
gBrowser.removeCurrentTab();
|
||||
window.focus();
|
||||
|
@ -33,7 +33,7 @@ function test() {
|
|||
gTestBrowser.contentWindow.location = gHttpTestRoot + "plugin_bug797677.html";
|
||||
}
|
||||
|
||||
function pluginNotFound() {
|
||||
function pluginBindingAttached() {
|
||||
// Let browser-plugins.js handle the PluginNotFound event, then run the test
|
||||
executeSoon(runTest);
|
||||
}
|
||||
|
|
|
@ -64,20 +64,22 @@ function test() {
|
|||
gBrowser.selectedTab = newTab;
|
||||
gTestBrowser = gBrowser.selectedBrowser;
|
||||
gTestBrowser.addEventListener("load", pageLoad, true);
|
||||
gTestBrowser.addEventListener("PluginClickToPlay", handlePluginClickToPlay, true);
|
||||
gTestBrowser.addEventListener("PluginBindingAttached", handleBindingAttached, true, true);
|
||||
prepareTest(test1, gTestRoot + "plugin_unknown.html");
|
||||
}
|
||||
|
||||
function finishTest() {
|
||||
gTestBrowser.removeEventListener("load", pageLoad, true);
|
||||
gTestBrowser.removeEventListener("PluginClickToPlay", handlePluginClickToPlay, true);
|
||||
gTestBrowser.removeEventListener("PluginBindingAttached", handleBindingAttached, true, true);
|
||||
gBrowser.removeCurrentTab();
|
||||
window.focus();
|
||||
finish();
|
||||
}
|
||||
|
||||
function handlePluginClickToPlay() {
|
||||
gClickToPlayPluginActualEvents++;
|
||||
function handleBindingAttached(evt) {
|
||||
evt.target instanceof Ci.nsIObjectLoadingContent;
|
||||
if (evt.target.pluginFallbackType == Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY)
|
||||
gClickToPlayPluginActualEvents++;
|
||||
}
|
||||
|
||||
function pageLoad() {
|
||||
|
@ -657,8 +659,6 @@ function test18e() {
|
|||
ok(objLoadingContent.activated, "Test 18e, Plugin should be activated");
|
||||
|
||||
unregisterFakeBlocklistService();
|
||||
var plugin = getTestPlugin();
|
||||
plugin.clicktoplay = false;
|
||||
Services.perms.removeAll();
|
||||
|
||||
prepareTest(test19a, gTestRoot + "plugin_test.html");
|
||||
|
@ -734,7 +734,7 @@ function test19f() {
|
|||
// "display: block" can be clicked to activate.
|
||||
function test20a() {
|
||||
var clickToPlayNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
|
||||
ok(clickToPlayNotification, "Test 20a, Should have a click-to-play notification");
|
||||
ok(!clickToPlayNotification, "Test 20a, Should not have a click-to-play notification");
|
||||
var doc = gTestBrowser.contentDocument;
|
||||
var plugin = doc.getElementById("plugin");
|
||||
var mainBox = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
|
||||
|
@ -756,6 +756,8 @@ function test20a() {
|
|||
}
|
||||
|
||||
function test20b() {
|
||||
var clickToPlayNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
|
||||
ok(clickToPlayNotification, "Test 20b, Should now have a click-to-play notification");
|
||||
var doc = gTestBrowser.contentDocument;
|
||||
var plugin = doc.getElementById("plugin");
|
||||
var pluginRect = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox").getBoundingClientRect();
|
||||
|
|
|
@ -145,7 +145,7 @@ function test() {
|
|||
gBrowser.selectedTab = newTab;
|
||||
gTestBrowser = gBrowser.selectedBrowser;
|
||||
gTestBrowser.addEventListener("load", pageLoad, true);
|
||||
gTestBrowser.addEventListener("PluginPlayPreview", handlePluginPlayPreview, true);
|
||||
gTestBrowser.addEventListener("PluginBindingAttached", handleBindingAttached, true, true);
|
||||
|
||||
registerPlayPreview('application/x-test', 'about:');
|
||||
prepareTest(test1a, gTestRoot + "plugin_test.html", 1);
|
||||
|
@ -153,14 +153,16 @@ function test() {
|
|||
|
||||
function finishTest() {
|
||||
gTestBrowser.removeEventListener("load", pageLoad, true);
|
||||
gTestBrowser.removeEventListener("PluginPlayPreview", handlePluginPlayPreview, true);
|
||||
gTestBrowser.removeEventListener("PluginBindingAttached", handleBindingAttached, true, true);
|
||||
gBrowser.removeCurrentTab();
|
||||
window.focus();
|
||||
finish();
|
||||
}
|
||||
|
||||
function handlePluginPlayPreview() {
|
||||
gPlayPreviewPluginActualEvents++;
|
||||
function handleBindingAttached(evt) {
|
||||
if (evt.target instanceof Ci.nsIObjectLoadingContent &&
|
||||
evt.target.pluginFallbackType == Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW)
|
||||
gPlayPreviewPluginActualEvents++;
|
||||
}
|
||||
|
||||
function pageLoad() {
|
||||
|
|
|
@ -589,7 +589,5 @@ function getPopupWidth() {
|
|||
|
||||
function closeAllChats() {
|
||||
let chatbar = window.SocialChatBar.chatbar;
|
||||
while (chatbar.selectedChat) {
|
||||
chatbar.selectedChat.close();
|
||||
}
|
||||
chatbar.removeAll();
|
||||
}
|
||||
|
|
|
@ -548,15 +548,17 @@ this.PlacesUIUtils = {
|
|||
aWindow : this._getTopBrowserWin();
|
||||
|
||||
var urls = [];
|
||||
let skipMarking = browserWindow && PrivateBrowsingUtils.isWindowPrivate(browserWindow);
|
||||
for (let item of aItemsToOpen) {
|
||||
if (!PrivateBrowsingUtils.isWindowPrivate(browserWindow)) {
|
||||
if (item.isBookmark)
|
||||
this.markPageAsFollowedBookmark(item.uri);
|
||||
else
|
||||
this.markPageAsTyped(item.uri);
|
||||
urls.push(item.uri);
|
||||
if (skipMarking) {
|
||||
continue;
|
||||
}
|
||||
|
||||
urls.push(item.uri);
|
||||
if (item.isBookmark)
|
||||
this.markPageAsFollowedBookmark(item.uri);
|
||||
else
|
||||
this.markPageAsTyped(item.uri);
|
||||
}
|
||||
|
||||
// whereToOpenLink doesn't return "window" when there's no browser window
|
||||
|
|
|
@ -24,13 +24,13 @@ MOCHITEST_BROWSER_FILES = \
|
|||
browser_library_search.js \
|
||||
browser_history_sidebar_search.js \
|
||||
browser_bookmarksProperties.js \
|
||||
$(warning browser_forgetthissite_single.js temporarily disabled because of very frequent oranges, see bug 551540) \
|
||||
$(filter disabled-for-very-frequent-oranges--bug-551540, browser_forgetthissite_single.js) \
|
||||
browser_library_left_pane_commands.js \
|
||||
browser_drag_bookmarks_on_toolbar.js \
|
||||
browser_library_middleclick.js \
|
||||
browser_library_views_liveupdate.js \
|
||||
browser_views_liveupdate.js \
|
||||
$(warning browser_sidebarpanels_click.js temporarily disabled cause it breaks the treeview, see bug 658744) \
|
||||
$(filter temporarily-disabled-for-breaking-the-treeview--bug-658744, browser_sidebarpanels_click.js) \
|
||||
sidebarpanels_click_test_page.html \
|
||||
browser_library_infoBox.js \
|
||||
browser_markPageAsFollowedLink.js \
|
||||
|
|
|
@ -23,15 +23,13 @@ MOCHITEST_BROWSER_FILES = \
|
|||
browser_privatebrowsing_popupmode.js \
|
||||
browser_privatebrowsing_searchbar.js \
|
||||
browser_privatebrowsing_sslsite_transition.js \
|
||||
$(warning browser_privatebrowsing_transition.js disabled since it no longer makes sense) \
|
||||
$(filter disabled-since-it-no-longer-makes-sense, browser_privatebrowsing_transition.js) \
|
||||
$(filter disabled--bug-564934, browser_privatebrowsing_downloadmonitor.js) \
|
||||
browser_privatebrowsing_urlbarundo.js \
|
||||
browser_privatebrowsing_viewsource.js \
|
||||
staller.sjs \
|
||||
$(NULL)
|
||||
|
||||
# Disabled until bug 564934 is fixed:
|
||||
# browser_privatebrowsing_downloadmonitor.js \
|
||||
|
||||
# Turn off private browsing tests that perma-timeout on Linux.
|
||||
ifneq (Linux,$(OS_ARCH))
|
||||
MOCHITEST_BROWSER_FILES += \
|
||||
|
|
|
@ -25,11 +25,15 @@ MOCHITEST_BROWSER_FILES = \
|
|||
browser_privatebrowsing_geoprompt_page.html \
|
||||
browser_privatebrowsing_lastpbcontextexited.js \
|
||||
browser_privatebrowsing_localStorage.js \
|
||||
browser_privatebrowsing_localStorage_before_after.js \
|
||||
browser_privatebrowsing_localStorage_before_after_page.html \
|
||||
browser_privatebrowsing_localStorage_before_after_page2.html \
|
||||
browser_privatebrowsing_localStorage_page1.html \
|
||||
browser_privatebrowsing_localStorage_page2.html \
|
||||
browser_privatebrowsing_opendir.js \
|
||||
browser_privatebrowsing_openlocation.js \
|
||||
browser_privatebrowsing_openLocationLastURL.js \
|
||||
browser_privatebrowsing_placestitle.js \
|
||||
browser_privatebrowsing_popupblocker.js \
|
||||
browser_privatebrowsing_protocolhandler.js \
|
||||
browser_privatebrowsing_protocolhandler_page.html \
|
||||
|
@ -39,6 +43,7 @@ MOCHITEST_BROWSER_FILES = \
|
|||
browser_privatebrowsing_windowtitle_page.html \
|
||||
browser_privatebrowsing_zoomrestore.js \
|
||||
popup.html \
|
||||
title.sjs \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/* 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/. */
|
||||
|
||||
// Ensure that a storage instance used by both private and public sessions at different times does not
|
||||
// allow any data to leak due to cached values.
|
||||
|
||||
// Step 1: Load browser_privatebrowsing_localStorage_before_after_page.html in a private tab, causing a storage
|
||||
// item to exist. Close the tab.
|
||||
// Step 2: Load the same page in a non-private tab, ensuring that the storage instance reports only one item
|
||||
// existing.
|
||||
|
||||
function test() {
|
||||
// initialization
|
||||
waitForExplicitFinish();
|
||||
let windowsToClose = [];
|
||||
let testURI = "about:blank";
|
||||
let prefix = 'http://mochi.test:8888/browser/browser/components/privatebrowsing/test/browser/perwindow/';
|
||||
|
||||
function doTest(aIsPrivateMode, aWindow, aCallback) {
|
||||
aWindow.gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
|
||||
aWindow.gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
|
||||
|
||||
if (aIsPrivateMode) {
|
||||
// do something when aIsPrivateMode is true
|
||||
is(aWindow.gBrowser.contentWindow.document.title, '1', "localStorage should contain 1 item");
|
||||
} else {
|
||||
// do something when aIsPrivateMode is false
|
||||
is(aWindow.gBrowser.contentWindow.document.title, 'null|0', 'localStorage should contain 0 items');
|
||||
}
|
||||
|
||||
aCallback();
|
||||
}, true);
|
||||
|
||||
aWindow.gBrowser.selectedBrowser.loadURI(testURI);
|
||||
}
|
||||
|
||||
function testOnWindow(aOptions, aCallback) {
|
||||
whenNewWindowLoaded(aOptions, function(aWin) {
|
||||
windowsToClose.push(aWin);
|
||||
// execute should only be called when need, like when you are opening
|
||||
// web pages on the test. If calling executeSoon() is not necesary, then
|
||||
// call whenNewWindowLoaded() instead of testOnWindow() on your test.
|
||||
executeSoon(function() aCallback(aWin));
|
||||
});
|
||||
};
|
||||
|
||||
// this function is called after calling finish() on the test.
|
||||
registerCleanupFunction(function() {
|
||||
windowsToClose.forEach(function(aWin) {
|
||||
aWin.close();
|
||||
});
|
||||
});
|
||||
|
||||
// test first when on private mode
|
||||
testOnWindow({private: true}, function(aWin) {
|
||||
testURI = prefix + 'browser_privatebrowsing_localStorage_before_after_page.html';
|
||||
doTest(true, aWin, function() {
|
||||
// then test when not on private mode
|
||||
testOnWindow({}, function(aWin) {
|
||||
testURI = prefix + 'browser_privatebrowsing_localStorage_before_after_page2.html';
|
||||
doTest(false, aWin, finish);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<script type="text/javascript">
|
||||
localStorage.clear();
|
||||
localStorage.setItem('zzztest', 'zzzvalue');
|
||||
document.title = localStorage.length;
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,10 @@
|
|||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<script type="text/javascript">
|
||||
document.title = localStorage.getItem('zzztest', 'zzzvalue') + '|' + localStorage.length;
|
||||
localStorage.clear();
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,109 @@
|
|||
/* 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/. */
|
||||
|
||||
// This test makes sure that the title of existing history entries does not
|
||||
// change inside a private window.
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
const TEST_URL = "http://mochi.test:8888/browser/browser/components/" +
|
||||
"privatebrowsing/test/browser/perwindow/title.sjs";
|
||||
let cm = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager);
|
||||
|
||||
function waitForCleanup(aCallback) {
|
||||
// delete all cookies
|
||||
cm.removeAll();
|
||||
// delete all history items
|
||||
Services.obs.addObserver(function observeCH(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(observeCH, PlacesUtils.TOPIC_EXPIRATION_FINISHED);
|
||||
aCallback();
|
||||
}, PlacesUtils.TOPIC_EXPIRATION_FINISHED, false);
|
||||
PlacesUtils.bhistory.removeAllPages();
|
||||
}
|
||||
|
||||
let testNumber = 0;
|
||||
let historyObserver = {
|
||||
onTitleChanged: function(aURI, aPageTitle) {
|
||||
if (aURI.spec != TEST_URL)
|
||||
return;
|
||||
switch (++testNumber) {
|
||||
case 1:
|
||||
// The first time that the page is loaded
|
||||
is(aPageTitle, "No Cookie",
|
||||
"The page should be loaded without any cookie for the first time");
|
||||
openTestPage(selectedWin);
|
||||
break;
|
||||
case 2:
|
||||
// The second time that the page is loaded
|
||||
is(aPageTitle, "Cookie",
|
||||
"The page should be loaded with a cookie for the second time");
|
||||
waitForCleanup(function () {
|
||||
openTestPage(selectedWin);
|
||||
});
|
||||
break;
|
||||
case 3:
|
||||
// After clean up
|
||||
is(aPageTitle, "No Cookie",
|
||||
"The page should be loaded without any cookie again");
|
||||
testOnWindow(true, function(win) {
|
||||
whenPageLoad(win, function() {
|
||||
waitForCleanup(finish);
|
||||
});
|
||||
});
|
||||
break;
|
||||
default:
|
||||
// Checks that opening the page in a private window should not fire a
|
||||
// title change.
|
||||
ok(false, "Title changed. Unexpected pass: " + testNumber);
|
||||
}
|
||||
},
|
||||
|
||||
onBeginUpdateBatch: function () {},
|
||||
onEndUpdateBatch: function () {},
|
||||
onVisit: function () {},
|
||||
onBeforeDeleteURI: function () {},
|
||||
onDeleteURI: function () {},
|
||||
onClearHistory: function () {},
|
||||
onPageChanged: function () {},
|
||||
onDeleteVisits: function() {},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsINavHistoryObserver])
|
||||
};
|
||||
PlacesUtils.history.addObserver(historyObserver, false);
|
||||
|
||||
let selectedWin = null;
|
||||
let windowsToClose = [];
|
||||
registerCleanupFunction(function() {
|
||||
PlacesUtils.history.removeObserver(historyObserver);
|
||||
windowsToClose.forEach(function(win) {
|
||||
win.close();
|
||||
});
|
||||
});
|
||||
|
||||
function openTestPage(aWin) {
|
||||
aWin.gBrowser.selectedTab = aWin.gBrowser.addTab(TEST_URL);
|
||||
}
|
||||
|
||||
function whenPageLoad(aWin, aCallback) {
|
||||
aWin.gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
|
||||
aWin.gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
|
||||
aCallback();
|
||||
}, true);
|
||||
aWin.gBrowser.selectedBrowser.loadURI(TEST_URL);
|
||||
}
|
||||
|
||||
function testOnWindow(aPrivate, aCallback) {
|
||||
whenNewWindowLoaded({ private: aPrivate }, function(win) {
|
||||
selectedWin = win;
|
||||
windowsToClose.push(win);
|
||||
executeSoon(function() { aCallback(win) });
|
||||
});
|
||||
}
|
||||
|
||||
waitForCleanup(function() {
|
||||
testOnWindow(false, function(win) {
|
||||
openTestPage(win);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/* 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/. */
|
||||
|
||||
// This provides the tests with a page with different titles based on whether
|
||||
// a cookie is present or not.
|
||||
|
||||
function handleRequest(request, response) {
|
||||
response.setStatusLine(request.httpVersion, 200, "OK");
|
||||
response.setHeader("Content-Type", "text/html", false);
|
||||
|
||||
var cookie = "name=value";
|
||||
var title = "No Cookie";
|
||||
if (request.hasHeader("Cookie") && request.getHeader("Cookie") == cookie)
|
||||
title = "Cookie";
|
||||
else
|
||||
response.setHeader("Set-Cookie", cookie, false);
|
||||
|
||||
response.write("<html><head><title>");
|
||||
response.write(title);
|
||||
response.write("</title><body>test page</body></html>");
|
||||
}
|
|
@ -132,14 +132,11 @@ MOCHITEST_BROWSER_FILES = \
|
|||
browser_739531.js \
|
||||
browser_739531_sample.html \
|
||||
browser_739805.js \
|
||||
$(filter disabled-for-intermittent-failures--bug-766044, browser_459906_empty.html) \
|
||||
$(filter disabled-for-intermittent-failures--bug-766044, browser_459906_sample.html) \
|
||||
$(filter disabled-for-intermittent-failures--bug-765389, browser_461743_sample.html) \
|
||||
$(NULL)
|
||||
|
||||
$(warning browser_459906.js is disabled for intermittent failures. Bug 766044)
|
||||
# browser_459906_empty.html \
|
||||
# browser_459906_sample.html \
|
||||
$(warning browser_461743.js is disabled for intermittent failures. Bug 765389)
|
||||
# browser_461743_sample.html \
|
||||
|
||||
# Disabled on Windows for frequent intermittent failures
|
||||
ifneq ($(OS_ARCH), WINNT)
|
||||
MOCHITEST_FILES += \
|
||||
|
@ -150,8 +147,8 @@ MOCHITEST_FILES += \
|
|||
browser_464620_xd.html \
|
||||
$(NULL)
|
||||
else
|
||||
$(warning browser_464620_a.js is disabled on Windows for intermittent failures. Bug 552424)
|
||||
$(warning browser_464620_b.js is disabled on Windows for intermittent failures. Bug 552424)
|
||||
$(filter disabled-for-intermittent-failures-on-windows--bug-552424, browser_464620_a.js)
|
||||
$(filter disabled-for-intermittent-failures-on-windows--bug-552424, browser_464620_b.js)
|
||||
endif
|
||||
|
||||
ifneq ($(OS_ARCH),Darwin)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[
|
||||
{
|
||||
"clang_version": "r167750"
|
||||
"clang_version": "r168304"
|
||||
},
|
||||
{
|
||||
"size": 47,
|
||||
|
@ -9,8 +9,8 @@
|
|||
"filename": "setup.sh"
|
||||
},
|
||||
{
|
||||
"size": 62553019,
|
||||
"digest": "31dd1ef281d0508bda0c470a29f244f062f42a4c521664dd1833f0f760c4d0cc0a222a8ba23063ad4cf50b678c2ee057519bd480e4a4f6804c3c7fb40f841a92",
|
||||
"size": 62536221,
|
||||
"digest": "a8381234d896ba2eeeef287b948f9d8ffc73bf4d4608ce74002eb666f1ac06d00047fd09b1b8f241c7160561b5dc7a40faf7f8bec94bb7939b9b77ba76af5967",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2"
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[
|
||||
{
|
||||
"clang_version": "r167750"
|
||||
"clang_version": "r168304"
|
||||
},
|
||||
{
|
||||
"size": 47,
|
||||
|
@ -9,8 +9,8 @@
|
|||
"filename": "setup.sh"
|
||||
},
|
||||
{
|
||||
"size": 62858526,
|
||||
"digest": "3c8280e001420eea4c352b05dfffda317ecb9c3be1eb23bda5cb16efebd4fe1b38f752b644acf33c6d34858ae01aa026cbb4c6f319fd6ee8d372517922063ad8",
|
||||
"size": 62877504,
|
||||
"digest": "837884b29c176e652b81e9cdaaeda34cf0bf41b7fe17a7f84ed30269ad7daedc9d72ba0d188b8f1551456f307f2dd72583daf99539e62403c0f2b5a83735658e",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2"
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[
|
||||
{
|
||||
"clang_version": "r167750"
|
||||
"clang_version": "r168304"
|
||||
},
|
||||
{
|
||||
"size": 47,
|
||||
|
@ -9,8 +9,8 @@
|
|||
"filename": "setup.sh"
|
||||
},
|
||||
{
|
||||
"size": 56161789,
|
||||
"digest": "43a35be63f9ea1c73a1b22532b5484b131f0c25bdb6a2f39e31c968b6c3477f6640450cc8dab8e17df80f20e367b8cbc0a74986a4eefd7ac9b9adf2b0859e55e",
|
||||
"size": 56144782,
|
||||
"digest": "7e7dd6775d71d074cced8407fac82dc5e161a9034927bd059c84fc06da161da39d32bbd95ac9b6efdf550370fa351361bc476f0b327387dc8d503dc446a776d6",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2"
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[
|
||||
{
|
||||
"clang_version": "r167750"
|
||||
"clang_version": "r168304"
|
||||
},
|
||||
{
|
||||
"size": 47,
|
||||
|
@ -9,8 +9,8 @@
|
|||
"filename": "setup.sh"
|
||||
},
|
||||
{
|
||||
"size": 56161789,
|
||||
"digest": "43a35be63f9ea1c73a1b22532b5484b131f0c25bdb6a2f39e31c968b6c3477f6640450cc8dab8e17df80f20e367b8cbc0a74986a4eefd7ac9b9adf2b0859e55e",
|
||||
"size": 56144782,
|
||||
"digest": "7e7dd6775d71d074cced8407fac82dc5e161a9034927bd059c84fc06da161da39d32bbd95ac9b6efdf550370fa351361bc476f0b327387dc8d503dc446a776d6",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2"
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ MOZ_SAFE_BROWSING=1
|
|||
MOZ_SERVICES_AITC=1
|
||||
MOZ_SERVICES_COMMON=1
|
||||
MOZ_SERVICES_CRYPTO=1
|
||||
MOZ_SERVICES_METRICS=1
|
||||
MOZ_SERVICES_NOTIFICATIONS=1
|
||||
MOZ_SERVICES_SYNC=1
|
||||
MOZ_APP_VERSION=$FIREFOX_VERSION
|
||||
|
|
|
@ -68,7 +68,7 @@ MOCHITEST_BROWSER_TESTS = \
|
|||
browser_dbg_scripts-searching-popup.js \
|
||||
browser_dbg_pause-resume.js \
|
||||
browser_dbg_update-editor-mode.js \
|
||||
$(warning browser_dbg_select-line.js temporarily disabled due to oranges, see bug 726609) \
|
||||
$(filter temporarily-disabled-due-to-oranges--bug-726609, browser_dbg_select-line.js) \
|
||||
browser_dbg_clean-exit.js \
|
||||
browser_dbg_bug723069_editor-breakpoints.js \
|
||||
browser_dbg_bug723071_editor-breakpoints-pane.js \
|
||||
|
@ -88,11 +88,10 @@ MOCHITEST_BROWSER_TESTS = \
|
|||
browser_dbg_bug737803_editor_actual_location.js \
|
||||
browser_dbg_progress-listener-bug.js \
|
||||
browser_dbg_chrome-debugging.js \
|
||||
$(filter disabled-for-intermittent-failures--bug-753225, browser_dbg_createRemote.js) \
|
||||
head.js \
|
||||
$(NULL)
|
||||
|
||||
$(warning browser_dbg_createRemote.js is disabled for intermittent failures. Bug 753225)
|
||||
|
||||
MOCHITEST_BROWSER_PAGES = \
|
||||
browser_dbg_tab1.html \
|
||||
browser_dbg_tab2.html \
|
||||
|
|
|
@ -23,7 +23,7 @@ _BROWSER_TEST_FILES = \
|
|||
browser_styleeditor_passedinsheet.js \
|
||||
browser_styleeditor_pretty.js \
|
||||
browser_styleeditor_readonly.js \
|
||||
$(warning browser_styleeditor_reopen.js is disabled for intermittent failures. Bug 707891) \
|
||||
$(filter disabled-for-intermittent-failures--bug-707891, browser_styleeditor_reopen.js) \
|
||||
browser_styleeditor_sv_keynav.js \
|
||||
browser_styleeditor_sv_resize.js \
|
||||
four.html \
|
||||
|
|
|
@ -80,17 +80,17 @@ const TESTS = [
|
|||
category: "malformed-xml",
|
||||
matchString: "</html>",
|
||||
},
|
||||
{ // #14
|
||||
{ // #13
|
||||
file: "test-bug-595934-empty-getelementbyid.html",
|
||||
category: "DOM",
|
||||
matchString: "getElementById",
|
||||
},
|
||||
{ // #15
|
||||
{ // #14
|
||||
file: "test-bug-595934-canvas-css.html",
|
||||
category: "CSS Parser",
|
||||
matchString: "foobarCanvasCssParser",
|
||||
},
|
||||
{ // #16
|
||||
{ // #15
|
||||
file: "test-bug-595934-image.html",
|
||||
category: "Image",
|
||||
matchString: "corrupt",
|
||||
|
|
|
@ -54,7 +54,6 @@
|
|||
@BINPATH@/@DLL_PREFIX@gkmedias@DLL_SUFFIX@
|
||||
#endif
|
||||
@BINPATH@/@DLL_PREFIX@mozalloc@DLL_SUFFIX@
|
||||
@BINPATH@/@DLL_PREFIX@soundtouch@DLL_SUFFIX@
|
||||
#ifdef MOZ_SHARED_MOZGLUE
|
||||
@BINPATH@/@DLL_PREFIX@mozglue@DLL_SUFFIX@
|
||||
#endif
|
||||
|
@ -464,6 +463,10 @@
|
|||
@BINPATH@/components/AitcComponents.manifest
|
||||
@BINPATH@/components/Aitc.js
|
||||
#endif
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
@BINPATH@/components/HealthReportComponents.manifest
|
||||
@BINPATH@/components/HealthReportService.js
|
||||
#endif
|
||||
#ifdef MOZ_SERVICES_NOTIFICATIONS
|
||||
@BINPATH@/components/NotificationsComponents.manifest
|
||||
#endif
|
||||
|
@ -571,6 +574,9 @@
|
|||
#ifdef MOZ_SERVICES_SYNC
|
||||
@BINPATH@/@PREF_DIR@/services-sync.js
|
||||
#endif
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
@BINPATH@/@PREF_DIR@/healthreport-prefs.js
|
||||
#endif
|
||||
@BINPATH@/greprefs.js
|
||||
@BINPATH@/defaults/autoconfig/platform.js
|
||||
@BINPATH@/defaults/autoconfig/prefcalls.js
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
/* 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/. */
|
||||
|
||||
|
|
|
@ -978,27 +978,32 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
|
|||
def checkForZombies(self, processLog):
|
||||
""" Look for hung processes """
|
||||
if not os.path.exists(processLog):
|
||||
self.log.info('INFO | automation.py | PID log not found: %s', processLog)
|
||||
else:
|
||||
self.log.info('INFO | automation.py | Reading PID log: %s', processLog)
|
||||
processList = []
|
||||
pidRE = re.compile(r'launched child process (\d+)$')
|
||||
processLogFD = open(processLog)
|
||||
for line in processLogFD:
|
||||
self.log.info(line.rstrip())
|
||||
m = pidRE.search(line)
|
||||
if m:
|
||||
processList.append(int(m.group(1)))
|
||||
processLogFD.close()
|
||||
self.log.info('Automation Error: PID log not found: %s', processLog)
|
||||
# Whilst no hung process was found, the run should still display as a failure
|
||||
return True
|
||||
|
||||
for processPID in processList:
|
||||
self.log.info("INFO | automation.py | Checking for orphan process with PID: %d", processPID)
|
||||
if self.isPidAlive(processPID):
|
||||
self.log.info("TEST-UNEXPECTED-FAIL | automation.py | child process %d still alive after shutdown", processPID)
|
||||
self.killPid(processPID)
|
||||
foundZombie = False
|
||||
self.log.info('INFO | automation.py | Reading PID log: %s', processLog)
|
||||
processList = []
|
||||
pidRE = re.compile(r'launched child process (\d+)$')
|
||||
processLogFD = open(processLog)
|
||||
for line in processLogFD:
|
||||
self.log.info(line.rstrip())
|
||||
m = pidRE.search(line)
|
||||
if m:
|
||||
processList.append(int(m.group(1)))
|
||||
processLogFD.close()
|
||||
|
||||
for processPID in processList:
|
||||
self.log.info("INFO | automation.py | Checking for orphan process with PID: %d", processPID)
|
||||
if self.isPidAlive(processPID):
|
||||
foundZombie = True
|
||||
self.log.info("TEST-UNEXPECTED-FAIL | automation.py | child process %d still alive after shutdown", processPID)
|
||||
self.killPid(processPID)
|
||||
return foundZombie
|
||||
|
||||
def checkForCrashes(self, profileDir, symbolsPath):
|
||||
automationutils.checkForCrashes(os.path.join(profileDir, "minidumps"), symbolsPath, self.lastTestSeen)
|
||||
return automationutils.checkForCrashes(os.path.join(profileDir, "minidumps"), symbolsPath, self.lastTestSeen)
|
||||
|
||||
def runApp(self, testURL, env, app, profileDir, extraArgs,
|
||||
runSSLTunnel = False, utilityPath = None,
|
||||
|
@ -1065,8 +1070,12 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
|
|||
self.log.info("INFO | automation.py | Application ran for: %s", str(datetime.now() - startTime))
|
||||
|
||||
# Do a final check for zombie child processes.
|
||||
self.checkForZombies(processLog)
|
||||
self.checkForCrashes(profileDir, symbolsPath)
|
||||
zombieProcesses = self.checkForZombies(processLog)
|
||||
|
||||
crashed = self.checkForCrashes(profileDir, symbolsPath)
|
||||
|
||||
if crashed or zombieProcesses:
|
||||
status = 1
|
||||
|
||||
if os.path.exists(processLog):
|
||||
os.unlink(processLog)
|
||||
|
|
|
@ -146,7 +146,6 @@ def checkForCrashes(dumpDir, symbolsPath, testName=None):
|
|||
if len(dumps) == 0:
|
||||
return False
|
||||
|
||||
foundCrash = False
|
||||
removeSymbolsPath = False
|
||||
|
||||
# If our symbols are at a remote URL, download them now
|
||||
|
@ -198,12 +197,11 @@ def checkForCrashes(dumpDir, symbolsPath, testName=None):
|
|||
extra = os.path.splitext(d)[0] + ".extra"
|
||||
if os.path.exists(extra):
|
||||
os.remove(extra)
|
||||
foundCrash = True
|
||||
finally:
|
||||
if removeSymbolsPath:
|
||||
shutil.rmtree(symbolsPath)
|
||||
|
||||
return foundCrash
|
||||
return True
|
||||
|
||||
def getFullPath(directory, path):
|
||||
"Get an absolute path relative to 'directory'."
|
||||
|
|
|
@ -99,11 +99,12 @@ class B2GRemoteAutomation(Automation):
|
|||
# is in place.
|
||||
dumpDir = tempfile.mkdtemp()
|
||||
self._devicemanager.getDirectory(self._remoteProfile + '/minidumps/', dumpDir)
|
||||
automationutils.checkForCrashes(dumpDir, symbolsPath, self.lastTestSeen)
|
||||
crashed = automationutils.checkForCrashes(dumpDir, symbolsPath, self.lastTestSeen)
|
||||
try:
|
||||
shutil.rmtree(dumpDir)
|
||||
except:
|
||||
print "WARNING: unable to remove directory: %s" % (dumpDir)
|
||||
return crashed
|
||||
|
||||
def initializeProfile(self, profileDir, extraPrefs = [], useServerLocations = False):
|
||||
# add b2g specific prefs
|
||||
|
|
|
@ -85,21 +85,22 @@ class RemoteAutomation(Automation):
|
|||
|
||||
def checkForCrashes(self, directory, symbolsPath):
|
||||
remoteCrashDir = self._remoteProfile + '/minidumps/'
|
||||
if self._devicemanager.dirExists(remoteCrashDir):
|
||||
dumpDir = tempfile.mkdtemp()
|
||||
self._devicemanager.getDirectory(remoteCrashDir, dumpDir)
|
||||
automationutils.checkForCrashes(dumpDir, symbolsPath,
|
||||
self.lastTestSeen)
|
||||
try:
|
||||
shutil.rmtree(dumpDir)
|
||||
except:
|
||||
print "WARNING: unable to remove directory: %s" % dumpDir
|
||||
else:
|
||||
if not self._devicemanager.dirExists(remoteCrashDir):
|
||||
# As of this writing, the minidumps directory is automatically
|
||||
# created when fennec (first) starts, so its lack of presence
|
||||
# is a hint that something went wrong.
|
||||
print "WARNING: No crash directory (%s) on remote " \
|
||||
"device" % remoteCrashDir
|
||||
print "Automation Error: No crash directory (%s) found on remote device" % remoteCrashDir
|
||||
# Whilst no crash was found, the run should still display as a failure
|
||||
return True
|
||||
dumpDir = tempfile.mkdtemp()
|
||||
self._devicemanager.getDirectory(remoteCrashDir, dumpDir)
|
||||
crashed = automationutils.checkForCrashes(dumpDir, symbolsPath,
|
||||
self.lastTestSeen)
|
||||
try:
|
||||
shutil.rmtree(dumpDir)
|
||||
except:
|
||||
print "WARNING: unable to remove directory: %s" % dumpDir
|
||||
return crashed
|
||||
|
||||
def buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs):
|
||||
# If remote profile is specified, use that instead
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# 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/.
|
||||
|
||||
llvm_revision = "167750"
|
||||
llvm_revision = "168304"
|
||||
moz_version = "moz0"
|
||||
|
||||
##############################################
|
||||
|
|
|
@ -982,7 +982,6 @@ plarenas.h
|
|||
plarena.h
|
||||
plhash.h
|
||||
speex/speex_resampler.h
|
||||
soundtouch/SoundTouch.h
|
||||
#if MOZ_NATIVE_PNG==1
|
||||
png.h
|
||||
#endif
|
||||
|
|
28
configure.in
28
configure.in
|
@ -4193,7 +4193,6 @@ MOZ_OGG=1
|
|||
MOZ_RAW=
|
||||
MOZ_SYDNEYAUDIO=
|
||||
MOZ_SPEEX_RESAMPLER=1
|
||||
MOZ_SOUNDTOUCH=1
|
||||
MOZ_CUBEB=
|
||||
MOZ_VORBIS=
|
||||
MOZ_TREMOR=
|
||||
|
@ -5231,7 +5230,6 @@ dnl enable once PeerConnection lands
|
|||
fi
|
||||
|
||||
AC_SUBST(MOZ_WEBRTC)
|
||||
AC_SUBST(MOZ_WEBRTC_TESTS)
|
||||
AC_SUBST(MOZ_WEBRTC_SIGNALING)
|
||||
AC_SUBST(MOZ_PEERCONNECTION)
|
||||
AC_SUBST(MOZ_WEBRTC_IN_LIBXUL)
|
||||
|
@ -5554,19 +5552,6 @@ if test -n "$MOZ_SPEEX_RESAMPLER"; then
|
|||
AC_DEFINE(MOZ_SPEEX_RESAMPLER)
|
||||
fi
|
||||
|
||||
if test -n "$MOZ_SOUNDTOUCH"; then
|
||||
AC_DEFINE(MOZ_SOUNDTOUCH)
|
||||
fi
|
||||
|
||||
if test -z "$GNU_CC" -a "$OS_ARCH" = "WINNT"; then
|
||||
SOUNDTOUCH_LIBS='$(LIBXUL_DIST)/lib/$(LIB_PREFIX)soundtouch.$(LIB_SUFFIX)'
|
||||
else
|
||||
SOUNDTOUCH_LIBS='-lsoundtouch'
|
||||
fi
|
||||
AC_SUBST(SOUNDTOUCH_CFLAGS)
|
||||
AC_SUBST(SOUNDTOUCH_LIBS)
|
||||
AC_SUBST(SOUNDTOUCH_CONFIG)
|
||||
|
||||
if test -n "$MOZ_CUBEB"; then
|
||||
case "$target" in
|
||||
*-android*|*-linuxandroid*)
|
||||
|
@ -8229,6 +8214,18 @@ if test -n "$MOZ_SERVICES_CRYPTO"; then
|
|||
AC_DEFINE(MOZ_SERVICES_CRYPTO)
|
||||
fi
|
||||
|
||||
dnl Build Firefox Health Reporter Service
|
||||
AC_SUBST(MOZ_SERVICES_HEALTHREPORT)
|
||||
if test -n "$MOZ_SERVICES_HEALTHREPORT"; then
|
||||
AC_DEFINE(MOZ_SERVICES_HEALTHREPORT)
|
||||
fi
|
||||
|
||||
dnl Build Services metrics component
|
||||
AC_SUBST(MOZ_SERVICES_METRICS)
|
||||
if test -n "$MOZ_SERVICES_METRICS"; then
|
||||
AC_DEFINE(MOZ_SERVICES_METRICS)
|
||||
fi
|
||||
|
||||
dnl Build Notifications if required
|
||||
AC_SUBST(MOZ_SERVICES_NOTIFICATIONS)
|
||||
if test -n "$MOZ_SERVICES_NOTIFICATIONS"; then
|
||||
|
@ -8608,7 +8605,6 @@ AC_SUBST(MOZ_APP_EXTRA_LIBS)
|
|||
AC_SUBST(MOZ_MEDIA)
|
||||
AC_SUBST(MOZ_SYDNEYAUDIO)
|
||||
AC_SUBST(MOZ_SPEEX_RESAMPLER)
|
||||
AC_SUBST(MOZ_SOUNDTOUCH)
|
||||
AC_SUBST(MOZ_CUBEB)
|
||||
AC_SUBST(MOZ_WAVE)
|
||||
AC_SUBST(MOZ_VORBIS)
|
||||
|
|
|
@ -107,6 +107,7 @@ NS_CP_ContentTypeName(uint32_t contentType)
|
|||
CASE_RETURN( TYPE_FONT );
|
||||
CASE_RETURN( TYPE_MEDIA );
|
||||
CASE_RETURN( TYPE_WEBSOCKET );
|
||||
CASE_RETURN( TYPE_CSP_REPORT );
|
||||
default:
|
||||
return "<Unknown Type>";
|
||||
}
|
||||
|
|
|
@ -10,6 +10,11 @@
|
|||
interface nsIURI;
|
||||
interface nsIDOMNode;
|
||||
|
||||
/**
|
||||
* The type of nsIContentPolicy::TYPE_*
|
||||
*/
|
||||
typedef unsigned long nsContentPolicyType;
|
||||
|
||||
/**
|
||||
* Interface for content policy mechanism. Implementations of this
|
||||
* interface can be used to control loading of various types of out-of-line
|
||||
|
@ -19,42 +24,62 @@ interface nsIDOMNode;
|
|||
* by launching a dialog to prompt the user for something).
|
||||
*/
|
||||
|
||||
[scriptable,uuid(e590e74f-bac7-4876-8c58-54dde92befb2)]
|
||||
[scriptable,uuid(e48e3024-f302-4a16-b8b6-2034d3a4b279)]
|
||||
interface nsIContentPolicy : nsISupports
|
||||
{
|
||||
const unsigned long TYPE_OTHER = 1;
|
||||
/**
|
||||
* Gecko/Firefox developers: Do not use TYPE_OTHER under any circumstances.
|
||||
*
|
||||
* Extension developers: Whenever it is reasonable, use one of the existing
|
||||
* content types. If none of the existing content types are right for
|
||||
* something you are doing, file a bug in the Core/DOM component that
|
||||
* includes a patch that adds your new content type to the end of the list of
|
||||
* TYPE_* constants here. But, don't start using your new content type until
|
||||
* your patch has been accepted, because it will be uncertain what exact
|
||||
* value and name your new content type will have; in that interim period,
|
||||
* use TYPE_OTHER. In your patch, document your new content type in the style
|
||||
* of the existing ones. In the bug you file, provide a more detailed
|
||||
* description of the new type of content you want Gecko to support, so that
|
||||
* the existing implementations of nsIContentPolicy can be properly modified
|
||||
* to deal with that new type of content.
|
||||
*
|
||||
* Implementations of nsIContentPolicy should treat this the same way they
|
||||
* treat unknown types, because existing users of TYPE_OTHER may be converted
|
||||
* to use new content types.
|
||||
*/
|
||||
const nsContentPolicyType TYPE_OTHER = 1;
|
||||
|
||||
/**
|
||||
* Indicates an executable script (such as JavaScript).
|
||||
*/
|
||||
const unsigned long TYPE_SCRIPT = 2;
|
||||
const nsContentPolicyType TYPE_SCRIPT = 2;
|
||||
|
||||
/**
|
||||
* Indicates an image (e.g., IMG elements).
|
||||
*/
|
||||
const unsigned long TYPE_IMAGE = 3;
|
||||
const nsContentPolicyType TYPE_IMAGE = 3;
|
||||
|
||||
/**
|
||||
* Indicates a stylesheet (e.g., STYLE elements).
|
||||
*/
|
||||
const unsigned long TYPE_STYLESHEET = 4;
|
||||
const nsContentPolicyType TYPE_STYLESHEET = 4;
|
||||
|
||||
/**
|
||||
* Indicates a generic object (plugin-handled content typically falls under
|
||||
* this category).
|
||||
*/
|
||||
const unsigned long TYPE_OBJECT = 5;
|
||||
const nsContentPolicyType TYPE_OBJECT = 5;
|
||||
|
||||
/**
|
||||
* Indicates a document at the top-level (i.e., in a browser).
|
||||
*/
|
||||
const unsigned long TYPE_DOCUMENT = 6;
|
||||
const nsContentPolicyType TYPE_DOCUMENT = 6;
|
||||
|
||||
/**
|
||||
* Indicates a document contained within another document (e.g., IFRAMEs,
|
||||
* FRAMES, and OBJECTs).
|
||||
*/
|
||||
const unsigned long TYPE_SUBDOCUMENT = 7;
|
||||
const nsContentPolicyType TYPE_SUBDOCUMENT = 7;
|
||||
|
||||
/**
|
||||
* Indicates a timed refresh.
|
||||
|
@ -66,51 +91,59 @@ interface nsIContentPolicy : nsISupports
|
|||
* shouldProcess will get this for, e.g., META Refresh elements and HTTP
|
||||
* Refresh headers.
|
||||
*/
|
||||
const unsigned long TYPE_REFRESH = 8;
|
||||
const nsContentPolicyType TYPE_REFRESH = 8;
|
||||
|
||||
/**
|
||||
* Indicates an XBL binding request, triggered either by -moz-binding CSS
|
||||
* property or Document.addBinding method.
|
||||
*/
|
||||
const unsigned long TYPE_XBL = 9;
|
||||
const nsContentPolicyType TYPE_XBL = 9;
|
||||
|
||||
/**
|
||||
* Indicates a ping triggered by a click on <A PING="..."> element.
|
||||
*/
|
||||
const unsigned long TYPE_PING = 10;
|
||||
const nsContentPolicyType TYPE_PING = 10;
|
||||
|
||||
/**
|
||||
* Indicates an XMLHttpRequest. Also used for document.load and for EventSource.
|
||||
*/
|
||||
const unsigned long TYPE_XMLHTTPREQUEST = 11;
|
||||
const unsigned long TYPE_DATAREQUEST = 11; // alias
|
||||
const nsContentPolicyType TYPE_XMLHTTPREQUEST = 11;
|
||||
const nsContentPolicyType TYPE_DATAREQUEST = 11; // alias
|
||||
|
||||
/**
|
||||
* Indicates a request by a plugin.
|
||||
*/
|
||||
const unsigned long TYPE_OBJECT_SUBREQUEST = 12;
|
||||
const nsContentPolicyType TYPE_OBJECT_SUBREQUEST = 12;
|
||||
|
||||
/**
|
||||
* Indicates a DTD loaded by an XML document.
|
||||
*/
|
||||
const unsigned long TYPE_DTD = 13;
|
||||
const nsContentPolicyType TYPE_DTD = 13;
|
||||
|
||||
/**
|
||||
* Indicates a font loaded via @font-face rule.
|
||||
*/
|
||||
const unsigned long TYPE_FONT = 14;
|
||||
const nsContentPolicyType TYPE_FONT = 14;
|
||||
|
||||
/**
|
||||
* Indicates a video or audio load.
|
||||
*/
|
||||
const unsigned long TYPE_MEDIA = 15;
|
||||
const nsContentPolicyType TYPE_MEDIA = 15;
|
||||
|
||||
/**
|
||||
* Indicates a WebSocket load.
|
||||
*/
|
||||
const unsigned long TYPE_WEBSOCKET = 16;
|
||||
const nsContentPolicyType TYPE_WEBSOCKET = 16;
|
||||
|
||||
/* Please update nsContentBlocker when adding new content types. */
|
||||
/**
|
||||
* Indicates a Content Security Policy report.
|
||||
*/
|
||||
const nsContentPolicyType TYPE_CSP_REPORT = 17;
|
||||
|
||||
/* When adding new content types, please update nsContentBlocker,
|
||||
* NS_CP_ContentTypeName, contentScurityPolicy.js, all nsIContentPolicy
|
||||
* implementations, and other things that are not listed here that are
|
||||
* related to nsIContentPolicy. */
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -135,7 +168,7 @@ interface nsIContentPolicy : nsISupports
|
|||
* aRequestOrigin), e.g., if you block an IMAGE because it is served from
|
||||
* goatse.cx (even if you don't necessarily block other types from that
|
||||
* server/domain).
|
||||
*
|
||||
*
|
||||
* NOTE that it is not meant to stop future requests for this server--only the
|
||||
* current request.
|
||||
*/
|
||||
|
@ -213,7 +246,7 @@ interface nsIContentPolicy : nsISupports
|
|||
* up, content showing up doubled, etc. If you need to do any of the things
|
||||
* above, do them off timeout or event.
|
||||
*/
|
||||
short shouldLoad(in unsigned long aContentType,
|
||||
short shouldLoad(in nsContentPolicyType aContentType,
|
||||
in nsIURI aContentLocation,
|
||||
in nsIURI aRequestOrigin,
|
||||
in nsISupports aContext,
|
||||
|
@ -256,7 +289,7 @@ interface nsIContentPolicy : nsISupports
|
|||
* involved is in an inconsistent state. See the note on shouldLoad to see
|
||||
* what this means for implementors of this method.
|
||||
*/
|
||||
short shouldProcess(in unsigned long aContentType,
|
||||
short shouldProcess(in nsContentPolicyType aContentType,
|
||||
in nsIURI aContentLocation,
|
||||
in nsIURI aRequestOrigin,
|
||||
in nsISupports aContext,
|
||||
|
|
|
@ -37,6 +37,8 @@ function ContentSecurityPolicy() {
|
|||
this._policy._allowEval = true;
|
||||
|
||||
this._request = "";
|
||||
this._requestOrigin = "";
|
||||
this._requestPrincipal = "";
|
||||
this._referrer = "";
|
||||
this._docRequest = null;
|
||||
CSPdebug("CSP POLICY INITED TO 'default-src *'");
|
||||
|
@ -73,6 +75,8 @@ function ContentSecurityPolicy() {
|
|||
csp._MAPPINGS[cp.TYPE_XMLHTTPREQUEST] = cspr_sd.XHR_SRC;
|
||||
csp._MAPPINGS[cp.TYPE_WEBSOCKET] = cspr_sd.XHR_SRC;
|
||||
|
||||
/* CSP cannot block CSP reports */
|
||||
csp._MAPPINGS[cp.TYPE_CSP_REPORT] = null;
|
||||
|
||||
/* These must go through the catch-all */
|
||||
csp._MAPPINGS[cp.TYPE_XBL] = cspr_sd.DEFAULT_SRC;
|
||||
|
@ -169,6 +173,11 @@ ContentSecurityPolicy.prototype = {
|
|||
let uri = aChannel.URI.cloneIgnoringRef();
|
||||
uri.userPass = '';
|
||||
this._request = uri.asciiSpec;
|
||||
this._requestOrigin = uri;
|
||||
|
||||
//store a reference to the principal, that can later be used in shouldLoad
|
||||
this._requestPrincipal = Components.classes["@mozilla.org/scriptsecuritymanager;1"].
|
||||
getService(Components.interfaces.nsIScriptSecurityManager).getChannelPrincipal(aChannel);
|
||||
|
||||
if (aChannel.referrer) {
|
||||
let referrer = aChannel.referrer.cloneIgnoringRef();
|
||||
|
@ -202,8 +211,8 @@ ContentSecurityPolicy.prototype = {
|
|||
|
||||
// If there is a policy-uri, fetch the policy, then re-call this function.
|
||||
// (1) parse and create a CSPRep object
|
||||
// Note that we pass the full URI since when it's parsed as 'self' to construct a
|
||||
// CSPSource only the scheme, host, and port are kept.
|
||||
// Note that we pass the full URI since when it's parsed as 'self' to construct a
|
||||
// CSPSource only the scheme, host, and port are kept.
|
||||
var newpolicy = CSPRep.fromString(aPolicy,
|
||||
selfURI,
|
||||
this._docRequest,
|
||||
|
@ -211,7 +220,7 @@ ContentSecurityPolicy.prototype = {
|
|||
|
||||
// (2) Intersect the currently installed CSPRep object with the new one
|
||||
var intersect = this._policy.intersectWith(newpolicy);
|
||||
|
||||
|
||||
// (3) Save the result
|
||||
this._policy = intersect;
|
||||
this._isInitialized = true;
|
||||
|
@ -325,8 +334,9 @@ ContentSecurityPolicy.prototype = {
|
|||
try {
|
||||
var contentPolicy = Cc["@mozilla.org/layout/content-policy;1"]
|
||||
.getService(Ci.nsIContentPolicy);
|
||||
if (contentPolicy.shouldLoad(Ci.nsIContentPolicy.TYPE_OTHER,
|
||||
chan.URI, null, null, null, null)
|
||||
if (contentPolicy.shouldLoad(Ci.nsIContentPolicy.TYPE_CSP_REPORT,
|
||||
chan.URI, this._requestOrigin,
|
||||
null, null, null, this._requestPrincipal)
|
||||
!= Ci.nsIContentPolicy.ACCEPT) {
|
||||
continue; // skip unauthorized URIs
|
||||
}
|
||||
|
@ -378,7 +388,7 @@ ContentSecurityPolicy.prototype = {
|
|||
CSPdebug(" found frame ancestor " + ancestor.asciiSpec);
|
||||
ancestors.push(ancestor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// scan the discovered ancestors
|
||||
let cspContext = CSPRep.SRC_DIRECTIVES.FRAME_ANCESTORS;
|
||||
|
@ -406,11 +416,11 @@ ContentSecurityPolicy.prototype = {
|
|||
* decides whether or not the policy is satisfied.
|
||||
*/
|
||||
shouldLoad:
|
||||
function csp_shouldLoad(aContentType,
|
||||
aContentLocation,
|
||||
aRequestOrigin,
|
||||
aContext,
|
||||
aMimeTypeGuess,
|
||||
function csp_shouldLoad(aContentType,
|
||||
aContentLocation,
|
||||
aRequestOrigin,
|
||||
aContext,
|
||||
aMimeTypeGuess,
|
||||
aOriginalUri) {
|
||||
|
||||
// don't filter chrome stuff
|
||||
|
@ -430,15 +440,15 @@ ContentSecurityPolicy.prototype = {
|
|||
}
|
||||
|
||||
// otherwise, honor the translation
|
||||
// var source = aContentLocation.scheme + "://" + aContentLocation.hostPort;
|
||||
// var source = aContentLocation.scheme + "://" + aContentLocation.hostPort;
|
||||
var res = this._policy.permits(aContentLocation, cspContext)
|
||||
? Ci.nsIContentPolicy.ACCEPT
|
||||
? Ci.nsIContentPolicy.ACCEPT
|
||||
: Ci.nsIContentPolicy.REJECT_SERVER;
|
||||
|
||||
// frame-ancestors is taken care of early on (as this document is loaded)
|
||||
|
||||
// If the result is *NOT* ACCEPT, then send report
|
||||
if (res != Ci.nsIContentPolicy.ACCEPT) {
|
||||
if (res != Ci.nsIContentPolicy.ACCEPT) {
|
||||
CSPdebug("blocking request for " + aContentLocation.asciiSpec);
|
||||
try {
|
||||
let directive = this._policy._directives[cspContext];
|
||||
|
@ -453,7 +463,7 @@ ContentSecurityPolicy.prototype = {
|
|||
|
||||
return (this._reportOnlyMode ? Ci.nsIContentPolicy.ACCEPT : res);
|
||||
},
|
||||
|
||||
|
||||
shouldProcess:
|
||||
function csp_shouldProcess(aContentType,
|
||||
aContentLocation,
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
* 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/. */
|
||||
|
||||
#ifndef mozAutoDocUpdate_h_
|
||||
#define mozAutoDocUpdate_h_
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDocumentObserver.h"
|
||||
|
@ -82,3 +85,5 @@ public:
|
|||
private:
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
* 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/. */
|
||||
|
||||
#ifndef nsCCUncollectableMarker_h_
|
||||
#define nsCCUncollectableMarker_h_
|
||||
|
||||
#include "nsIObserver.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
@ -45,3 +48,5 @@ namespace dom {
|
|||
void TraceBlackJS(JSTracer* aTrc);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -165,59 +165,25 @@ InDocCheckEvent::Run()
|
|||
/**
|
||||
* A task for firing PluginNotFound and PluginBlocklisted DOM Events.
|
||||
*/
|
||||
class nsPluginErrorEvent : public nsRunnable {
|
||||
class nsPluginOutdatedEvent : public nsRunnable {
|
||||
public:
|
||||
nsPluginErrorEvent(nsIContent* aContent,
|
||||
nsObjectLoadingContent::FallbackType aFallbackType)
|
||||
: mContent(aContent),
|
||||
mFallbackType(aFallbackType) {}
|
||||
nsPluginOutdatedEvent(nsIContent* aContent) : mContent(aContent) {}
|
||||
|
||||
~nsPluginErrorEvent() {}
|
||||
~nsPluginOutdatedEvent() {}
|
||||
|
||||
NS_IMETHOD Run();
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIContent> mContent;
|
||||
nsObjectLoadingContent::FallbackType mFallbackType;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginErrorEvent::Run()
|
||||
nsPluginOutdatedEvent::Run()
|
||||
{
|
||||
nsString type;
|
||||
switch (mFallbackType) {
|
||||
case nsObjectLoadingContent::eFallbackVulnerableUpdatable:
|
||||
type = NS_LITERAL_STRING("PluginVulnerableUpdatable");
|
||||
break;
|
||||
case nsObjectLoadingContent::eFallbackVulnerableNoUpdate:
|
||||
type = NS_LITERAL_STRING("PluginVulnerableNoUpdate");
|
||||
break;
|
||||
case nsObjectLoadingContent::eFallbackClickToPlay:
|
||||
type = NS_LITERAL_STRING("PluginClickToPlay");
|
||||
break;
|
||||
case nsObjectLoadingContent::eFallbackPlayPreview:
|
||||
type = NS_LITERAL_STRING("PluginPlayPreview");
|
||||
break;
|
||||
case nsObjectLoadingContent::eFallbackUnsupported:
|
||||
type = NS_LITERAL_STRING("PluginNotFound");
|
||||
break;
|
||||
case nsObjectLoadingContent::eFallbackDisabled:
|
||||
type = NS_LITERAL_STRING("PluginDisabled");
|
||||
break;
|
||||
case nsObjectLoadingContent::eFallbackBlocklisted:
|
||||
type = NS_LITERAL_STRING("PluginBlocklisted");
|
||||
break;
|
||||
case nsObjectLoadingContent::eFallbackOutdated:
|
||||
type = NS_LITERAL_STRING("PluginOutdated");
|
||||
break;
|
||||
default:
|
||||
return NS_OK;
|
||||
}
|
||||
LOG(("OBJLC [%p]: nsPluginErrorEvent firing '%s'",
|
||||
mContent.get(), NS_ConvertUTF16toUTF8(type).get()));
|
||||
LOG(("OBJLC [%p]: nsPluginOutdatedEvent firing", mContent.get()));
|
||||
nsContentUtils::DispatchTrustedEvent(mContent->GetDocument(), mContent,
|
||||
type, true, true);
|
||||
|
||||
NS_LITERAL_STRING("PluginOutdated"),
|
||||
true, true);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -780,8 +746,16 @@ nsObjectLoadingContent::InstantiatePluginInstance()
|
|||
uint32_t blockState = nsIBlocklistService::STATE_NOT_BLOCKED;
|
||||
blocklist->GetPluginBlocklistState(pluginTag, EmptyString(),
|
||||
EmptyString(), &blockState);
|
||||
if (blockState == nsIBlocklistService::STATE_OUTDATED)
|
||||
FirePluginError(eFallbackOutdated);
|
||||
if (blockState == nsIBlocklistService::STATE_OUTDATED) {
|
||||
// Fire plugin outdated event if necessary
|
||||
LOG(("OBJLC [%p]: Dispatching nsPluginOutdatedEvent for content %p\n",
|
||||
this));
|
||||
nsCOMPtr<nsIRunnable> ev = new nsPluginOutdatedEvent(thisContent);
|
||||
nsresult rv = NS_DispatchToCurrentThread(ev);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("failed to dispatch nsPluginOutdatedEvent");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1563,13 +1537,18 @@ nsObjectLoadingContent::LoadObject(bool aNotify,
|
|||
// NOTE LoadFallback can override this in some cases
|
||||
FallbackType fallbackType = eFallbackAlternate;
|
||||
|
||||
if (mType == eType_Null) {
|
||||
// mType can differ with GetTypeOfContent(mContentType) if we support this
|
||||
// type, but the parameters are invalid e.g. a embed tag with type "image/png"
|
||||
// but no URI -- don't show a plugin error or unknown type error in that case.
|
||||
if (mType == eType_Null && GetTypeOfContent(mContentType) == eType_Null) {
|
||||
// See if a disabled or blocked plugin could've handled this
|
||||
nsresult pluginsupport = IsPluginEnabledForType(mContentType);
|
||||
if (pluginsupport == NS_ERROR_PLUGIN_DISABLED) {
|
||||
fallbackType = eFallbackDisabled;
|
||||
} else if (pluginsupport == NS_ERROR_PLUGIN_BLOCKLISTED) {
|
||||
fallbackType = eFallbackBlocklisted;
|
||||
} else {
|
||||
// Completely unknown type
|
||||
fallbackType = eFallbackUnsupported;
|
||||
}
|
||||
}
|
||||
|
@ -1784,6 +1763,9 @@ nsObjectLoadingContent::LoadObject(bool aNotify,
|
|||
|
||||
rv = mFrameLoader->CheckForRecursiveLoad(mURI);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(("OBJLC [%p]: Aborting recursive load", this));
|
||||
mFrameLoader->Destroy();
|
||||
mFrameLoader = nullptr;
|
||||
mType = eType_Null;
|
||||
break;
|
||||
}
|
||||
|
@ -1850,21 +1832,13 @@ nsObjectLoadingContent::LoadObject(bool aNotify,
|
|||
CloseChannel();
|
||||
}
|
||||
|
||||
// Don't notify or send events - we'll handle those ourselves
|
||||
// Don't notify, as LoadFallback doesn't know of our previous state
|
||||
// (so really this is just setting mFallbackType)
|
||||
LoadFallback(fallbackType, false);
|
||||
}
|
||||
|
||||
// Notify of our final state if we haven't already
|
||||
// Notify of our final state
|
||||
NotifyStateChanged(oldType, oldState, false, aNotify);
|
||||
|
||||
if (mType == eType_Null && !mContentType.IsEmpty() &&
|
||||
mFallbackType != eFallbackAlternate) {
|
||||
// if we have a content type and are not showing alternate
|
||||
// content, fire a pluginerror to trigger (we stopped LoadFallback
|
||||
// from doing so above, it doesn't know of our old state)
|
||||
FirePluginError(mFallbackType);
|
||||
}
|
||||
|
||||
//
|
||||
// Pass load on to finalListener if loading with a channel
|
||||
|
@ -2099,23 +2073,6 @@ nsObjectLoadingContent::NotifyStateChanged(ObjectType aOldType,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsObjectLoadingContent::FirePluginError(FallbackType aFallbackType)
|
||||
{
|
||||
nsCOMPtr<nsIContent> thisContent =
|
||||
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||
NS_ASSERTION(thisContent, "must be a content");
|
||||
|
||||
LOG(("OBJLC [%p]: Dispatching nsPluginErrorEvent for content %p\n",
|
||||
this));
|
||||
|
||||
nsCOMPtr<nsIRunnable> ev = new nsPluginErrorEvent(thisContent, aFallbackType);
|
||||
nsresult rv = NS_DispatchToCurrentThread(ev);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("failed to dispatch nsPluginErrorEvent");
|
||||
}
|
||||
}
|
||||
|
||||
nsObjectLoadingContent::ObjectType
|
||||
nsObjectLoadingContent::GetTypeOfContent(const nsCString& aMIMEType)
|
||||
{
|
||||
|
@ -2330,58 +2287,31 @@ nsObjectLoadingContent::LoadFallback(FallbackType aType, bool aNotify) {
|
|||
aType = eFallbackAlternate;
|
||||
}
|
||||
|
||||
/// XXX(johns): This block is just mimicing legacy behavior, not any spec
|
||||
// Check if we have any significant content (excluding param tags) OR a
|
||||
// param named 'pluginUrl'
|
||||
bool hasAlternateContent = false;
|
||||
bool hasPluginUrl = false;
|
||||
if (thisContent->Tag() == nsGkAtoms::object &&
|
||||
(aType == eFallbackUnsupported ||
|
||||
aType == eFallbackDisabled ||
|
||||
aType == eFallbackBlocklisted))
|
||||
{
|
||||
// Show alternate content instead, if it exists
|
||||
for (nsIContent* child = thisContent->GetFirstChild();
|
||||
child; child = child->GetNextSibling())
|
||||
{
|
||||
if (child->IsHTML(nsGkAtoms::param)) {
|
||||
if (child->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
|
||||
NS_LITERAL_STRING("pluginurl"), eIgnoreCase)) {
|
||||
hasPluginUrl = true;
|
||||
}
|
||||
} else if (nsStyleUtil::IsSignificantChild(child, true, false)) {
|
||||
hasAlternateContent = true;
|
||||
child; child = child->GetNextSibling()) {
|
||||
if (!child->IsHTML(nsGkAtoms::param) &&
|
||||
nsStyleUtil::IsSignificantChild(child, true, false)) {
|
||||
aType = eFallbackAlternate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Show alternate content if it exists, unless we have a 'pluginurl' param,
|
||||
// in which case the missing-plugin fallback handler will want to handle
|
||||
// it
|
||||
if (hasAlternateContent && !hasPluginUrl) {
|
||||
LOG(("OBJLC [%p]: Unsupported/disabled/blocked plugin has alternate "
|
||||
"content, showing instead of custom handler", this));
|
||||
aType = eFallbackAlternate;
|
||||
}
|
||||
}
|
||||
|
||||
mType = eType_Null;
|
||||
mFallbackType = aType;
|
||||
|
||||
//
|
||||
// Notify & send events
|
||||
//
|
||||
// Notify
|
||||
if (!aNotify) {
|
||||
return; // done
|
||||
}
|
||||
|
||||
NotifyStateChanged(oldType, oldState, false, true);
|
||||
|
||||
if (mFallbackType != eFallbackCrashed &&
|
||||
mFallbackType != eFallbackAlternate)
|
||||
{
|
||||
// Alternate content doesn't trigger a pluginError, and nsPluginCrashedEvent
|
||||
// is only handled by ::PluginCrashed
|
||||
FirePluginError(mFallbackType);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2578,7 +2508,11 @@ nsObjectLoadingContent::ShouldPlay(FallbackType &aReason)
|
|||
nsRefPtr<nsPluginHost> pluginHost =
|
||||
already_AddRefed<nsPluginHost>(nsPluginHost::GetInst());
|
||||
|
||||
bool isCTP = pluginHost->IsPluginClickToPlayForType(mContentType.get());
|
||||
bool isCTP;
|
||||
nsresult rv = pluginHost->IsPluginClickToPlayForType(mContentType, &isCTP);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isCTP || mActivated) {
|
||||
return true;
|
||||
|
@ -2588,7 +2522,7 @@ nsObjectLoadingContent::ShouldPlay(FallbackType &aReason)
|
|||
aReason = eFallbackClickToPlay;
|
||||
// (if it's click-to-play, it might be because of the blocklist)
|
||||
uint32_t state;
|
||||
nsresult rv = pluginHost->GetBlocklistStateForType(mContentType.get(), &state);
|
||||
rv = pluginHost->GetBlocklistStateForType(mContentType.get(), &state);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
if (state == nsIBlocklistService::STATE_VULNERABLE_UPDATE_AVAILABLE) {
|
||||
aReason = eFallbackVulnerableUpdatable;
|
||||
|
|
|
@ -349,13 +349,6 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
|||
void NotifyStateChanged(ObjectType aOldType, nsEventStates aOldState,
|
||||
bool aSync, bool aNotify);
|
||||
|
||||
/**
|
||||
* Fires the nsPluginErrorEvent. This function doesn't do any checks
|
||||
* whether it should be fired, or whether the given state translates to a
|
||||
* meaningful event
|
||||
*/
|
||||
void FirePluginError(FallbackType aFallbackType);
|
||||
|
||||
/**
|
||||
* Returns a ObjectType value corresponding to the type of content we would
|
||||
* support the given MIME type as, taking capabilities and plugin state
|
||||
|
|
|
@ -375,6 +375,8 @@ nsRange::CharacterDataChanged(nsIDocument* aDocument,
|
|||
nsIContent* aContent,
|
||||
CharacterDataChangeInfo* aInfo)
|
||||
{
|
||||
MOZ_ASSERT(mAssertNextInsertOrAppendIndex == -1,
|
||||
"splitText failed to notify insert/append?");
|
||||
NS_ASSERTION(mIsPositioned, "shouldn't be notified if not positioned");
|
||||
|
||||
nsINode* newRoot = nullptr;
|
||||
|
@ -383,6 +385,35 @@ nsRange::CharacterDataChanged(nsIDocument* aDocument,
|
|||
uint32_t newStartOffset = 0;
|
||||
uint32_t newEndOffset = 0;
|
||||
|
||||
if (aInfo->mDetails &&
|
||||
aInfo->mDetails->mType == CharacterDataChangeInfo::Details::eSplit) {
|
||||
// If the splitted text node is immediately before a range boundary point
|
||||
// that refers to a child index (i.e. its parent is the boundary container)
|
||||
// then we need to increment the corresponding offset to account for the new
|
||||
// text node that will be inserted. If so, we need to prevent the next
|
||||
// ContentInserted or ContentAppended for this range from incrementing it
|
||||
// again (when the new text node is notified).
|
||||
nsINode* parentNode = aContent->GetParentNode();
|
||||
int32_t index = -1;
|
||||
if (parentNode == mEndParent && mEndOffset > 0 &&
|
||||
(index = parentNode->IndexOf(aContent)) + 1 == mEndOffset) {
|
||||
++mEndOffset;
|
||||
mEndOffsetWasIncremented = true;
|
||||
}
|
||||
if (parentNode == mStartParent && mStartOffset > 0 &&
|
||||
(index != -1 ? index : parentNode->IndexOf(aContent)) + 1 == mStartOffset) {
|
||||
++mStartOffset;
|
||||
mStartOffsetWasIncremented = true;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (mStartOffsetWasIncremented || mEndOffsetWasIncremented) {
|
||||
mAssertNextInsertOrAppendIndex =
|
||||
(mStartOffsetWasIncremented ? mStartOffset : mEndOffset) - 1;
|
||||
mAssertNextInsertOrAppendNode = aInfo->mDetails->mNextSibling;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// If the changed node contains our start boundary and the change starts
|
||||
// before the boundary we'll need to adjust the offset.
|
||||
if (aContent == mStartParent &&
|
||||
|
@ -469,7 +500,27 @@ nsRange::CharacterDataChanged(nsIDocument* aDocument,
|
|||
newRoot = IsValidBoundary(newEndNode);
|
||||
}
|
||||
}
|
||||
// When the removed text node's parent is one of our boundary nodes we may
|
||||
// need to adjust the offset to account for the removed node. However,
|
||||
// there will also be a ContentRemoved notification later so the only cases
|
||||
// we need to handle here is when the removed node is the text node after
|
||||
// the boundary. (The m*Offset > 0 check is an optimization - a boundary
|
||||
// point before the first child is never affected by normalize().)
|
||||
nsINode* parentNode = aContent->GetParentNode();
|
||||
if (parentNode == mStartParent && mStartOffset > 0 &&
|
||||
mStartOffset < parentNode->GetChildCount() &&
|
||||
removed == parentNode->GetChildAt(mStartOffset)) {
|
||||
newStartNode = aContent;
|
||||
newStartOffset = aInfo->mChangeStart;
|
||||
}
|
||||
if (parentNode == mEndParent && mEndOffset > 0 &&
|
||||
mEndOffset < parentNode->GetChildCount() &&
|
||||
removed == parentNode->GetChildAt(mEndOffset)) {
|
||||
newEndNode = aContent;
|
||||
newEndOffset = aInfo->mChangeEnd;
|
||||
}
|
||||
}
|
||||
|
||||
if (newStartNode || newEndNode) {
|
||||
if (!newStartNode) {
|
||||
newStartNode = mStartParent;
|
||||
|
@ -504,6 +555,17 @@ nsRange::ContentAppended(nsIDocument* aDocument,
|
|||
child = child->GetNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
if (mStartOffsetWasIncremented || mEndOffsetWasIncremented) {
|
||||
MOZ_ASSERT(mAssertNextInsertOrAppendIndex == aNewIndexInContainer);
|
||||
MOZ_ASSERT(mAssertNextInsertOrAppendNode == aFirstNewContent);
|
||||
MOZ_ASSERT(aFirstNewContent->IsNodeOfType(nsINode::eTEXT));
|
||||
mStartOffsetWasIncremented = mEndOffsetWasIncremented = false;
|
||||
#ifdef DEBUG
|
||||
mAssertNextInsertOrAppendIndex = -1;
|
||||
mAssertNextInsertOrAppendNode = nullptr;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -517,10 +579,12 @@ nsRange::ContentInserted(nsIDocument* aDocument,
|
|||
nsINode* container = NODE_FROM(aContainer, aDocument);
|
||||
|
||||
// Adjust position if a sibling was inserted.
|
||||
if (container == mStartParent && aIndexInContainer < mStartOffset) {
|
||||
if (container == mStartParent && aIndexInContainer < mStartOffset &&
|
||||
!mStartOffsetWasIncremented) {
|
||||
++mStartOffset;
|
||||
}
|
||||
if (container == mEndParent && aIndexInContainer < mEndOffset) {
|
||||
if (container == mEndParent && aIndexInContainer < mEndOffset &&
|
||||
!mEndOffsetWasIncremented) {
|
||||
++mEndOffset;
|
||||
}
|
||||
if (container->IsSelectionDescendant() &&
|
||||
|
@ -528,6 +592,17 @@ nsRange::ContentInserted(nsIDocument* aDocument,
|
|||
MarkDescendants(aChild);
|
||||
aChild->SetDescendantOfCommonAncestorForRangeInSelection();
|
||||
}
|
||||
|
||||
if (mStartOffsetWasIncremented || mEndOffsetWasIncremented) {
|
||||
MOZ_ASSERT(mAssertNextInsertOrAppendIndex == aIndexInContainer);
|
||||
MOZ_ASSERT(mAssertNextInsertOrAppendNode == aChild);
|
||||
MOZ_ASSERT(aChild->IsNodeOfType(nsINode::eTEXT));
|
||||
mStartOffsetWasIncremented = mEndOffsetWasIncremented = false;
|
||||
#ifdef DEBUG
|
||||
mAssertNextInsertOrAppendIndex = -1;
|
||||
mAssertNextInsertOrAppendNode = nullptr;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -538,6 +613,9 @@ nsRange::ContentRemoved(nsIDocument* aDocument,
|
|||
nsIContent* aPreviousSibling)
|
||||
{
|
||||
NS_ASSERTION(mIsPositioned, "shouldn't be notified if not positioned");
|
||||
MOZ_ASSERT(!mStartOffsetWasIncremented && !mEndOffsetWasIncremented &&
|
||||
mAssertNextInsertOrAppendIndex == -1,
|
||||
"splitText failed to notify insert/append?");
|
||||
|
||||
nsINode* container = NODE_FROM(aContainer, aDocument);
|
||||
bool gravitateStart = false;
|
||||
|
@ -581,6 +659,9 @@ nsRange::ContentRemoved(nsIDocument* aDocument,
|
|||
void
|
||||
nsRange::ParentChainChanged(nsIContent *aContent)
|
||||
{
|
||||
MOZ_ASSERT(!mStartOffsetWasIncremented && !mEndOffsetWasIncremented &&
|
||||
mAssertNextInsertOrAppendIndex == -1,
|
||||
"splitText failed to notify insert/append?");
|
||||
NS_ASSERTION(mRoot == aContent, "Wrong ParentChainChanged notification?");
|
||||
nsINode* newRoot = IsValidBoundary(mStartParent);
|
||||
NS_ASSERTION(newRoot, "No valid boundary or root found!");
|
||||
|
|
|
@ -30,6 +30,12 @@ public:
|
|||
, mIsDetached(false)
|
||||
, mMaySpanAnonymousSubtrees(false)
|
||||
, mInSelection(false)
|
||||
, mStartOffsetWasIncremented(false)
|
||||
, mEndOffsetWasIncremented(false)
|
||||
#ifdef DEBUG
|
||||
, mAssertNextInsertOrAppendIndex(-1)
|
||||
, mAssertNextInsertOrAppendNode(nullptr)
|
||||
#endif
|
||||
{}
|
||||
virtual ~nsRange();
|
||||
|
||||
|
@ -229,6 +235,12 @@ protected:
|
|||
bool mIsDetached;
|
||||
bool mMaySpanAnonymousSubtrees;
|
||||
bool mInSelection;
|
||||
bool mStartOffsetWasIncremented;
|
||||
bool mEndOffsetWasIncremented;
|
||||
#ifdef DEBUG
|
||||
int32_t mAssertNextInsertOrAppendIndex;
|
||||
nsINode* mAssertNextInsertOrAppendNode;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* nsRange_h___ */
|
||||
|
|
|
@ -593,6 +593,8 @@ MOCHITEST_FILES_B = \
|
|||
file_bug804395.jar \
|
||||
test_bug804395.html \
|
||||
test_bug809003.html \
|
||||
test_textnode_split_in_selection.html \
|
||||
test_textnode_normalize_in_selection.html \
|
||||
$(NULL)
|
||||
|
||||
# OOP tests don't work on Windows (bug 763081) or native-fennec
|
||||
|
|
|
@ -21,21 +21,10 @@ object:-moz-type-unsupported {
|
|||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
function unknown_plugin_detected(event) {
|
||||
window.parent.unknown_plugin_detected(event);
|
||||
function plugin_binding_attached(event) {
|
||||
window.parent.plugin_binding_attached(event);
|
||||
}
|
||||
|
||||
function blocked_plugin_detected(event) {
|
||||
window.parent.blocked_plugin_detected(event);
|
||||
}
|
||||
|
||||
function disabled_plugin_detected(event) {
|
||||
window.parent.disabled_plugin_detected(event);
|
||||
}
|
||||
|
||||
document.addEventListener("PluginNotFound", unknown_plugin_detected, true);
|
||||
document.addEventListener("PluginDisabled", disabled_plugin_detected, true);
|
||||
document.addEventListener("PluginBlocklisted", blocked_plugin_detected, true);
|
||||
document.addEventListener("PluginBindingAttached", plugin_binding_attached, true, true);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -43,7 +32,7 @@ document.addEventListener("PluginBlocklisted", blocked_plugin_detected, true);
|
|||
<div><embed id="plugin1" style="width: 100px; height: 100px" type="application/x-test"></div>
|
||||
<div><embed id="plugin2" style="width: 100px; height: 100px" src="data:application/x-test,test"></div>
|
||||
|
||||
<!-- So do objects with no content and no pluginurl -->
|
||||
<!-- So do objects with a type/uri and no content -->
|
||||
<div><object id="plugin3" style="width: 100px; height: 100px" type="application/x-test"></object></div>
|
||||
<div><object id="plugin4" style="width: 100px; height: 100px" data="data:application/x-test,test"></object></div>
|
||||
|
||||
|
@ -69,16 +58,6 @@ document.addEventListener("PluginBlocklisted", blocked_plugin_detected, true);
|
|||
|
||||
</object></div>
|
||||
|
||||
<!-- Pluginurl forces the psuedo class and error event regardless of content -->
|
||||
<div><object id="plugin11" style="width: 100px; height: 100px" type="application/x-test">
|
||||
<param name="pluginurl" value="http://foo">
|
||||
<p>Fallback content</p>
|
||||
</object></div>
|
||||
<div><object id="plugin12" style="width: 100px; height: 100px" data="data:application/x-test,test">
|
||||
<param name="pluginurl" value="http://foo">
|
||||
<p>Fallback content</p>
|
||||
</object></div>
|
||||
|
||||
<!-- No errors or psuedo classes for objects with fallback content -->
|
||||
<div><object id="fallback1" style="width: 100px; height: 100px" type="application/x-test">
|
||||
<p>Fallback content</p>
|
||||
|
@ -90,10 +69,20 @@ document.addEventListener("PluginBlocklisted", blocked_plugin_detected, true);
|
|||
<!-- Even other plugins are considered content so no errors dispatched from these
|
||||
objects, but the inner embeds do get processed -->
|
||||
<div><object id="fallback3" style="width: 100px; height: 100px" type="application/x-test">
|
||||
<embed id="plugin13" style="width: 100px; height: 100px" type="application/x-test">
|
||||
<embed id="plugin11" style="width: 100px; height: 100px" type="application/x-test">
|
||||
</object></div>
|
||||
<div><object id="fallback4" style="width: 100px; height: 100px" data="data:application/x-test,test">
|
||||
<embed id="plugin14" style="width: 100px; height: 100px" type="application/x-test">
|
||||
<embed id="plugin12" style="width: 100px; height: 100px" type="application/x-test">
|
||||
</object></div>
|
||||
|
||||
<!-- pluginurl was removed in bug 548133, and should not affect fallback -->
|
||||
<div><object id="plugin13" style="width: 100px; height: 100px" data="data:application/x-test,test">
|
||||
<param name="pluginurl">
|
||||
</object></div>
|
||||
|
||||
<div><object id="fallback5" style="width: 100px; height: 100px" data="data:application/x-test,test">
|
||||
<param name="pluginurl">
|
||||
Fallback content
|
||||
</object></div>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -21,21 +21,10 @@ object:-moz-type-unsupported {
|
|||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
function unknown_plugin_detected(event) {
|
||||
window.parent.unknown_plugin_detected(event);
|
||||
function plugin_binding_attached(event) {
|
||||
window.parent.plugin_binding_attached(event);
|
||||
}
|
||||
|
||||
function blocked_plugin_detected(event) {
|
||||
window.parent.blocked_plugin_detected(event);
|
||||
}
|
||||
|
||||
function disabled_plugin_detected(event) {
|
||||
window.parent.disabled_plugin_detected(event);
|
||||
}
|
||||
|
||||
document.addEventListener("PluginNotFound", unknown_plugin_detected, true);
|
||||
document.addEventListener("PluginDisabled", disabled_plugin_detected, true);
|
||||
document.addEventListener("PluginBlocklisted", blocked_plugin_detected, true);
|
||||
document.addEventListener("PluginBindingAttached", plugin_binding_attached, true, true);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -43,7 +32,7 @@ document.addEventListener("PluginBlocklisted", blocked_plugin_detected, true);
|
|||
<div><embed id="plugin1" style="width: 100px; height: 100px" type="application/x-unknown"></div>
|
||||
<div><embed id="plugin2" style="width: 100px; height: 100px" src="data:application/x-unknown,test"></div>
|
||||
|
||||
<!-- So do objects with no content and no pluginurl -->
|
||||
<!-- So do objects with a type/uri and no content -->
|
||||
<div><object id="plugin3" style="width: 100px; height: 100px" type="application/x-unknown"></object></div>
|
||||
<div><object id="plugin4" style="width: 100px; height: 100px" data="data:application/x-unknown,test"></object></div>
|
||||
|
||||
|
@ -69,16 +58,6 @@ document.addEventListener("PluginBlocklisted", blocked_plugin_detected, true);
|
|||
|
||||
</object></div>
|
||||
|
||||
<!-- Pluginurl forces the psuedo class and error event regardless of content -->
|
||||
<div><object id="plugin11" style="width: 100px; height: 100px" type="application/x-unknown">
|
||||
<param name="pluginurl" value="http://foo">
|
||||
<p>Fallback content</p>
|
||||
</object></div>
|
||||
<div><object id="plugin12" style="width: 100px; height: 100px" data="data:application/x-unknown,test">
|
||||
<param name="pluginurl" value="http://foo">
|
||||
<p>Fallback content</p>
|
||||
</object></div>
|
||||
|
||||
<!-- No errors or psuedo classes for objects with fallback content -->
|
||||
<div><object id="fallback1" style="width: 100px; height: 100px" type="application/x-unknown">
|
||||
<p>Fallback content</p>
|
||||
|
@ -90,10 +69,21 @@ document.addEventListener("PluginBlocklisted", blocked_plugin_detected, true);
|
|||
<!-- Even other plugins are considered content so no errors dispatched from these
|
||||
objects, but the inner embeds do get processed -->
|
||||
<div><object id="fallback3" style="width: 100px; height: 100px" type="application/x-unknown">
|
||||
<embed id="plugin13" style="width: 100px; height: 100px" type="application/x-unknown">
|
||||
<embed id="plugin11" style="width: 100px; height: 100px" type="application/x-unknown">
|
||||
</object></div>
|
||||
<div><object id="fallback4" style="width: 100px; height: 100px" data="data:application/x-unknown,test">
|
||||
<embed id="plugin14" style="width: 100px; height: 100px" type="application/x-unknown">
|
||||
<embed id="plugin12" style="width: 100px; height: 100px" type="application/x-unknown">
|
||||
</object></div>
|
||||
|
||||
<!-- pluginurl was removed in bug 548133, and should not affect fallback -->
|
||||
<div><object id="plugin13" style="width: 100px; height: 100px" type="application/x-unknown">
|
||||
<param name="pluginurl">
|
||||
</object></div>
|
||||
|
||||
<div><object id="fallback5" style="width: 100px; height: 100px" type="applicatin/x-unknown">
|
||||
<param name="pluginurl">
|
||||
Fallback content
|
||||
</object></div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -19,25 +19,30 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=391728
|
|||
<script class="testbody" type="text/javascript">
|
||||
/** Test for Bug 391728 **/
|
||||
// Plugins that should dispatch error events and have the pseudo classes set
|
||||
const PLUGIN_COUNT = 14;
|
||||
const PLUGIN_COUNT = 13;
|
||||
// Plugins that should neither dispatch error events or have the pseudo classes set
|
||||
const FALLBACK_COUNT = 4;
|
||||
const FALLBACK_COUNT = 5;
|
||||
const OBJLC = Components.interfaces.nsIObjectLoadingContent;
|
||||
|
||||
var gNextTest = null;
|
||||
var gUnknown = [];
|
||||
var gBlocked = [];
|
||||
var gDisabled = [];
|
||||
|
||||
function disabled_plugin_detected(event) {
|
||||
gDisabled.push(event.target.id);
|
||||
}
|
||||
|
||||
function blocked_plugin_detected(event) {
|
||||
gBlocked.push(event.target.id);
|
||||
}
|
||||
|
||||
function unknown_plugin_detected(event) {
|
||||
gUnknown.push(event.target.id);
|
||||
function plugin_binding_attached(event) {
|
||||
var plugin = event.target;
|
||||
plugin instanceof OBJLC;
|
||||
switch (SpecialPowers.wrap(plugin).pluginFallbackType) {
|
||||
case OBJLC.PLUGIN_DISABLED:
|
||||
gDisabled.push(plugin.id);
|
||||
break;
|
||||
case OBJLC.PLUGIN_BLOCKLISTED:
|
||||
gBlocked.push(plugin.id);
|
||||
break;
|
||||
case OBJLC.PLUGIN_UNSUPPORTED:
|
||||
gUnknown.push(plugin.id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function init_test() {
|
||||
|
|
|
@ -43,47 +43,36 @@ Embed height=100 (stylesheet width:400px height:400px)
|
|||
|
||||
Object without defined width/height:
|
||||
<object id="object1" type="bogus">
|
||||
<param name="pluginurl" value="http://foo">
|
||||
</object><br>
|
||||
Object width=0 height=0
|
||||
<object id="object2" type="bogus" width="0" height="0">
|
||||
<param name="pluginurl" value="http://foo">
|
||||
</object><br>
|
||||
Object width=100 height=100
|
||||
<object id="object3" type="bogus" width="100" height="100">
|
||||
<param name="pluginurl" value="http://foo">
|
||||
</object><br>
|
||||
Object height=100
|
||||
<object id="object4" type="bogus" height="100">
|
||||
<param name="pluginurl" value="http://foo">
|
||||
</object><br>
|
||||
Object width=100
|
||||
<object id="object5" type="bogus" width="100">
|
||||
<param name="pluginurl" value="http://foo">
|
||||
</object><br>
|
||||
Object width=100xxx height=100
|
||||
<object id="object6" type="bogus" width="100xxx" height="100">
|
||||
<param name="pluginurl" value="http://foo">
|
||||
</object><br>
|
||||
Object width=0100 height=100
|
||||
<object id="object7" type="bogus" width="0100" height="100">
|
||||
<param name="pluginurl" value="http://foo">
|
||||
</object><br>
|
||||
Object width= height=100
|
||||
<object id="object8" type="bogus" width="" height="100">
|
||||
<param name="pluginurl" value="http://foo">
|
||||
</object><br>
|
||||
Object width=100 height=100 style="width:400px"
|
||||
<object id="object9" type="bogus" width="100" height="100" style="width:400px;">
|
||||
<param name="pluginurl" value="http://foo">
|
||||
</object><br>
|
||||
Object height=100 style="width:400px"
|
||||
<object id="object10" type="bogus" height="100" style="width:400px;">
|
||||
<param name="pluginurl" value="http://foo">
|
||||
</object><br>
|
||||
Object height=100 (stylesheet width:400px height:400px)
|
||||
<object id="object11" type="bogus" height="100">
|
||||
<param name="pluginurl" value="http://foo">
|
||||
</object><br>
|
||||
</div>
|
||||
<pre id="test">
|
||||
|
|
|
@ -13,15 +13,19 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=425013
|
|||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=425013">Mozilla Bug 425013</a>
|
||||
<br>
|
||||
|
||||
<script>
|
||||
<script type="text/javascript;version=1.7">
|
||||
var missingPlugins = new Array();
|
||||
var OBJLC = Components.interfaces.nsIObjectLoadingContent;
|
||||
|
||||
function pluginNotFound(event)
|
||||
function pluginBinding(event)
|
||||
{
|
||||
missingPlugins.push(event.target);
|
||||
var plugin = event.target;
|
||||
plugin instanceof OBJLC;
|
||||
if (SpecialPowers.wrap(plugin).pluginFallbackType == OBJLC.PLUGIN_UNSUPPORTED)
|
||||
missingPlugins.push(plugin);
|
||||
}
|
||||
|
||||
document.addEventListener("PluginNotFound", pluginNotFound, false);
|
||||
document.addEventListener("PluginBindingAttached", pluginBinding, true);
|
||||
</script>
|
||||
|
||||
<object type="foo/bar" id="obj1"></object>
|
||||
|
@ -55,14 +59,23 @@ document.addEventListener("PluginNotFound", pluginNotFound, false);
|
|||
<script class="testbody" type="text/javascript">
|
||||
function runtests()
|
||||
{
|
||||
ok(missingPlugins.indexOf(document.getElementById("obj1")) >= 0, "Missing plugin element obj1");
|
||||
ok(missingPlugins.indexOf(document.getElementById("embed1")) >= 0, "Missing plugin element embed1");
|
||||
ok(missingPlugins.indexOf(document.getElementById("embed2")) >= 0, "Missing plugin element embed2");
|
||||
ok(missingPlugins.indexOf(document.getElementById("obj3")) >= 0, "Missing plugin element obj3");
|
||||
// Force layout flush so the binding is attached and the event is fired
|
||||
document.getElementById("obj1").clientTop;
|
||||
document.getElementById("obj3").clientTop;
|
||||
document.getElementById("embed1").clientTop;
|
||||
document.getElementById("embed2").clientTop;
|
||||
|
||||
is(missingPlugins.length, 4, "Wrong number of missing plugins");
|
||||
// Let pending events flush
|
||||
SimpleTest.executeSoon(function () {
|
||||
ok(missingPlugins.indexOf(document.getElementById("obj1")) >= 0, "Missing plugin element obj1");
|
||||
ok(missingPlugins.indexOf(document.getElementById("embed1")) >= 0, "Missing plugin element embed1");
|
||||
ok(missingPlugins.indexOf(document.getElementById("embed2")) >= 0, "Missing plugin element embed2");
|
||||
ok(missingPlugins.indexOf(document.getElementById("obj3")) >= 0, "Missing plugin element obj3");
|
||||
|
||||
SimpleTest.finish();
|
||||
is(missingPlugins.length, 4, "Wrong number of missing plugins");
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
|
|
@ -15,13 +15,17 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=429157
|
|||
|
||||
<script>
|
||||
var missingPlugins = new Array();
|
||||
const OBJLC = Components.interfaces.nsIObjectLoadingContent;
|
||||
|
||||
function pluginNotFound(event)
|
||||
function pluginBindingAttached(event)
|
||||
{
|
||||
missingPlugins.push(event.target);
|
||||
var plugin = event.target;
|
||||
plugin instanceof OBJLC;
|
||||
if (SpecialPowers.wrap(plugin).pluginFallbackType == OBJLC.PLUGIN_UNSUPPORTED)
|
||||
missingPlugins.push(plugin);
|
||||
}
|
||||
|
||||
document.addEventListener("PluginNotFound", pluginNotFound, false);
|
||||
document.addEventListener("PluginBindingAttached", pluginBindingAttached, true);
|
||||
</script>
|
||||
|
||||
<object id="obj1" type="image/png" >ALT image/png</object><br>
|
||||
|
@ -32,9 +36,15 @@ document.addEventListener("PluginNotFound", pluginNotFound, false);
|
|||
<script class="testbody" type="text/javascript">
|
||||
function runtests()
|
||||
{
|
||||
is(missingPlugins.length, 0, "There should be no missing plugins for this page");
|
||||
for (var obj of document.querySelectorAll("object")) {
|
||||
obj.clientTop;
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
SimpleTest.executeSoon(function () {
|
||||
is(missingPlugins.length, 0, "There should be no missing plugins for this page");
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=804784
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 804784</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=804784">Mozilla Bug 804784</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 804784 **/
|
||||
|
||||
var sel = document.getSelection();
|
||||
var flush = true;
|
||||
var dry = true;
|
||||
var run = "";
|
||||
var empty_range;
|
||||
var empty_first_text_range;
|
||||
var empty_last_text_range;
|
||||
var full_range;
|
||||
|
||||
function check(range, expected, test)
|
||||
{
|
||||
is(""+range, expected, test);
|
||||
is(""+empty_range, "", "empty range test after: "+test);
|
||||
is(""+empty_first_text_range, "", "empty first text range test after: "+test);
|
||||
if (empty_last_text_range) is(""+empty_last_text_range, "", "empty last text range test after: "+test);
|
||||
is(""+full_range, full_range.startContainer.textContent, "full range test after: "+test);
|
||||
}
|
||||
|
||||
function newDiv()
|
||||
{
|
||||
var div = document.createElement('div');
|
||||
for (var i = 0; i < arguments.length; ++i) {
|
||||
div.appendChild(document.createTextNode(arguments[i]));
|
||||
}
|
||||
document.body.appendChild(div)
|
||||
empty_range = document.createRange();
|
||||
empty_range.setStart(div,0);
|
||||
empty_range.setEnd(div,0);
|
||||
var firstTextNode = div.childNodes[0];
|
||||
var lastTextNode = div.childNodes[div.childNodes.length - 1];
|
||||
empty_first_text_range = document.createRange();
|
||||
empty_first_text_range.setStart(firstTextNode,0);
|
||||
empty_first_text_range.setEnd(firstTextNode,0);
|
||||
empty_last_text_range = null;
|
||||
if (firstTextNode != lastTextNode) {
|
||||
empty_last_text_range = document.createRange();
|
||||
empty_last_text_range.setStart(lastTextNode,0);
|
||||
empty_last_text_range.setEnd(lastTextNode,0);
|
||||
}
|
||||
full_range = document.createRange();
|
||||
full_range.setStart(div,0);
|
||||
full_range.setEnd(div,div.childNodes.length);
|
||||
return div;
|
||||
}
|
||||
|
||||
function selEnd(div,child,index,s)
|
||||
{
|
||||
var start = div.childNodes[child];
|
||||
var r = document.createRange();
|
||||
sel.addRange(r);
|
||||
r.setStart(start, index);
|
||||
r.setEnd(div, div.childNodes.length);
|
||||
if (!dry) div.normalize();
|
||||
check(r,s,run+" selEnd "+child+","+index);
|
||||
}
|
||||
|
||||
function selStart(div,child,index,s)
|
||||
{
|
||||
if (flush) document.body.getClientRects();
|
||||
var start = div.childNodes[child];
|
||||
var r = document.createRange();
|
||||
sel.addRange(r);
|
||||
r.setStart(div, 0);
|
||||
r.setEnd(start, index);
|
||||
if (!dry) div.normalize();
|
||||
check(r,s,run+" selStart "+child+","+index);
|
||||
}
|
||||
|
||||
function selMiddleStart(div,child,index,s)
|
||||
{
|
||||
if (flush) document.body.getClientRects();
|
||||
var start = div.childNodes[child];
|
||||
var r = document.createRange();
|
||||
sel.addRange(r);
|
||||
r.setStart(div, 1);
|
||||
r.setEnd(start, index);
|
||||
div.normalize();
|
||||
check(r,s,run+" selMiddleStart "+child+","+index);
|
||||
}
|
||||
|
||||
function selMiddleEnd(div,child,index,s)
|
||||
{
|
||||
if (flush) document.body.getClientRects();
|
||||
var start = div.childNodes[child];
|
||||
var r = document.createRange();
|
||||
sel.addRange(r);
|
||||
r.setStart(start, index);
|
||||
r.setEnd(div, 2);
|
||||
if (!dry) div.normalize();
|
||||
check(r,s,run+" selMiddleEnd "+child+","+index);
|
||||
}
|
||||
|
||||
function mergeBefore(div,child,index,s)
|
||||
{
|
||||
if (flush) document.body.getClientRects();
|
||||
var start = div.childNodes[child];
|
||||
var r = document.createRange();
|
||||
sel.addRange(r);
|
||||
r.setStart(div, 1);
|
||||
r.setEnd(start, index);
|
||||
if (!dry) div.normalize();
|
||||
check(r,s,run+" mergeBefore "+child+","+index);
|
||||
}
|
||||
|
||||
function runTests(s)
|
||||
{
|
||||
run = s+":";
|
||||
selEnd(newDiv('111'), 0,0,'111');
|
||||
selEnd(newDiv('111'), 0,1,'11');
|
||||
selEnd(newDiv('111'), 0,2,'1');
|
||||
selEnd(newDiv(''), 0,0,'');
|
||||
selEnd(newDiv('',''), 1,0,'');
|
||||
selEnd(newDiv('','',''), 1,0,'');
|
||||
selEnd(newDiv('111','222'), 0,1,'11222');
|
||||
selEnd(newDiv('111','222'), 0,2,'1222');
|
||||
selEnd(newDiv('111','222'), 1,1,'22');
|
||||
selEnd(newDiv('','222'), 1,2,'2');
|
||||
selEnd(newDiv('111',''), 0,1,'11');
|
||||
selEnd(newDiv('111','222'), 1,2,'2');
|
||||
selEnd(newDiv('111','222','333'), 1,1,'22333');
|
||||
selEnd(newDiv('111','222','333'), 1,2,'2333');
|
||||
selEnd(newDiv('111','','333'), 0,2,'1333');
|
||||
selEnd(newDiv('111','','333'), 1,0,'333');
|
||||
selEnd(newDiv('111','','333'), 2,0,'333');
|
||||
|
||||
selStart(newDiv('111'), 0,0,'');
|
||||
selStart(newDiv('111'), 0,1,'1');
|
||||
selStart(newDiv('111'), 0,2,'11');
|
||||
selStart(newDiv(''), 0,0,'');
|
||||
selStart(newDiv('111','222'), 0,1,'1');
|
||||
selStart(newDiv('111','222'), 0,2,'11');
|
||||
selStart(newDiv('111','222'), 1,1,'1112');
|
||||
selStart(newDiv('111','222'), 1,2,'11122');
|
||||
selStart(newDiv('111',''), 1,0,'111');
|
||||
selStart(newDiv('111',''), 0,2,'11');
|
||||
selStart(newDiv('111','222','333'), 1,1,'1112');
|
||||
selStart(newDiv('111','222','333'), 1,2,'11122');
|
||||
selStart(newDiv('111','222','333'), 1,2,'11122');
|
||||
selStart(newDiv('111','','333'), 1,0,'111');
|
||||
|
||||
selMiddleStart(newDiv('111','222','333'), 1,1,'2');
|
||||
selMiddleStart(newDiv('111','222','333'), 1,2,'22');
|
||||
selMiddleStart(newDiv('111','222','333'), 2,1,'2223');
|
||||
selMiddleStart(newDiv('111','222','333'), 2,2,'22233');
|
||||
selMiddleStart(newDiv('111','','333'), 2,2,'33');
|
||||
selMiddleStart(newDiv('111','222',''), 2,0,'222');
|
||||
|
||||
selMiddleEnd(newDiv('111','222','333'), 0,1,'11222');
|
||||
selMiddleEnd(newDiv('111','222','333'), 0,2,'1222');
|
||||
selMiddleEnd(newDiv('111','222','333'), 1,1,'22');
|
||||
selMiddleEnd(newDiv('111','222','333'), 1,2,'2');
|
||||
selMiddleEnd(newDiv('111','','333'), 1,0,'');
|
||||
selMiddleEnd(newDiv('','222','333'), 0,0,'222');
|
||||
|
||||
mergeBefore(newDiv('111','222'), 1,1,'2');
|
||||
mergeBefore(newDiv('111','222','333'), 1,2,'22');
|
||||
mergeBefore(newDiv('111','222','333'), 2,1,'2223');
|
||||
mergeBefore(newDiv('111','222','333'), 2,2,'22233');
|
||||
mergeBefore(newDiv('111','','333'), 2,0,'');
|
||||
mergeBefore(newDiv('111','','333'), 2,2,'33');
|
||||
}
|
||||
|
||||
function boom()
|
||||
{
|
||||
runTests("dry run"); // this is to verify the result strings without normalize()
|
||||
dry = false;
|
||||
flush = false;
|
||||
runTests("no flush");
|
||||
flush = true;
|
||||
runTests("flush");
|
||||
}
|
||||
|
||||
boom();
|
||||
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,221 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=803924
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 803924</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=803924">Mozilla Bug 803924</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 803924 **/
|
||||
|
||||
var sel = document.getSelection();
|
||||
var flush = true;
|
||||
var dry = true;
|
||||
var run = "";
|
||||
var empty_range;
|
||||
var empty_first_text_range;
|
||||
var empty_last_text_range;
|
||||
var full_range;
|
||||
|
||||
function check(range, expected, test)
|
||||
{
|
||||
is(""+range, expected, test);
|
||||
is(""+empty_range, "", "empty range test after: "+test);
|
||||
is(""+empty_first_text_range, "", "empty first text range test after: "+test);
|
||||
if (empty_last_text_range) is(""+empty_last_text_range, "", "empty last text range test after: "+test);
|
||||
is(""+full_range, full_range.startContainer.textContent, "full range test after: "+test);
|
||||
}
|
||||
|
||||
function newDiv()
|
||||
{
|
||||
var div = document.createElement('div');
|
||||
for (var i = 0; i < arguments.length; ++i) {
|
||||
div.appendChild(document.createTextNode(arguments[i]));
|
||||
}
|
||||
document.body.appendChild(div)
|
||||
empty_range = document.createRange();
|
||||
empty_range.setStart(div,0);
|
||||
empty_range.setEnd(div,0);
|
||||
var firstTextNode = div.childNodes[0];
|
||||
var lastTextNode = div.childNodes[div.childNodes.length - 1];
|
||||
empty_first_text_range = document.createRange();
|
||||
empty_first_text_range.setStart(firstTextNode,0);
|
||||
empty_first_text_range.setEnd(firstTextNode,0);
|
||||
empty_last_text_range = null;
|
||||
if (firstTextNode != lastTextNode) {
|
||||
empty_last_text_range = document.createRange();
|
||||
empty_last_text_range.setStart(lastTextNode,0);
|
||||
empty_last_text_range.setEnd(lastTextNode,0);
|
||||
}
|
||||
full_range = document.createRange();
|
||||
full_range.setStart(div,0);
|
||||
full_range.setEnd(div,div.childNodes.length);
|
||||
return div;
|
||||
}
|
||||
|
||||
function selEnd(div,child,index,split,s)
|
||||
{
|
||||
var start = div.childNodes[child];
|
||||
var r = document.createRange();
|
||||
sel.addRange(r);
|
||||
r.setStart(start, index);
|
||||
r.setEnd(div, div.childNodes.length);
|
||||
if (!dry) start.splitText(split);
|
||||
check(r,s,run+" selEnd "+child+","+index+","+split);
|
||||
}
|
||||
|
||||
function selStart(div,child,index,split,s)
|
||||
{
|
||||
if (flush) document.body.getClientRects();
|
||||
var start = div.childNodes[child];
|
||||
var r = document.createRange();
|
||||
sel.addRange(r);
|
||||
r.setStart(div, 0);
|
||||
r.setEnd(start, index);
|
||||
if (!dry) start.splitText(split);
|
||||
check(r,s,run+" selStart "+child+","+index+","+split);
|
||||
}
|
||||
|
||||
function selMiddleStart(div,child,index,split,s)
|
||||
{
|
||||
if (flush) document.body.getClientRects();
|
||||
var start = div.childNodes[child];
|
||||
var r = document.createRange();
|
||||
sel.addRange(r);
|
||||
r.setStart(div, 1);
|
||||
r.setEnd(start, index);
|
||||
if (!dry) start.splitText(split);
|
||||
check(r,s,run+" selMiddleStart "+child+","+index+","+split);
|
||||
}
|
||||
|
||||
function selMiddleEnd(div,child,index,split,s)
|
||||
{
|
||||
if (flush) document.body.getClientRects();
|
||||
var start = div.childNodes[child];
|
||||
var r = document.createRange();
|
||||
sel.addRange(r);
|
||||
r.setStart(start, index);
|
||||
r.setEnd(div, 2);
|
||||
if (!dry) start.splitText(split);
|
||||
check(r,s,run+" selMiddleEnd "+child+","+index+","+split);
|
||||
}
|
||||
|
||||
function splitBefore(div,child,index,split,s)
|
||||
{
|
||||
if (flush) document.body.getClientRects();
|
||||
var start = div.childNodes[child];
|
||||
var r = document.createRange();
|
||||
sel.addRange(r);
|
||||
r.setStart(div, 1);
|
||||
r.setEnd(start, index);
|
||||
if (!dry) div.childNodes[0].splitText(split);
|
||||
check(r,s,run+" splitBefore "+child+","+index+","+split);
|
||||
}
|
||||
|
||||
function runTests(s)
|
||||
{
|
||||
run = s+":";
|
||||
selEnd(newDiv('111'), 0,0,0,'111');
|
||||
selEnd(newDiv('111'), 0,0,1,'111');
|
||||
selEnd(newDiv('111'), 0,0,3,'111');
|
||||
selEnd(newDiv(''), 0,0,0,'');
|
||||
selEnd(newDiv('111'), 0,1,0,'11');
|
||||
selEnd(newDiv('111'), 0,2,1,'1');
|
||||
selEnd(newDiv('111'), 0,1,3,'11');
|
||||
selEnd(newDiv('111','222'), 0,1,0,'11222');
|
||||
selEnd(newDiv('111','222'), 0,2,1,'1222');
|
||||
selEnd(newDiv('111','222'), 0,1,3,'11222');
|
||||
selEnd(newDiv('111','222'), 1,1,0,'22');
|
||||
selEnd(newDiv('111','222'), 1,2,1,'2');
|
||||
selEnd(newDiv('','222'), 1,1,1,'22');
|
||||
selEnd(newDiv('','222'), 0,0,0,'222');
|
||||
selEnd(newDiv('111',''), 0,1,0,'11');
|
||||
selEnd(newDiv('111','222'), 1,1,3,'22');
|
||||
selEnd(newDiv('111','222','333'), 1,1,0,'22333');
|
||||
selEnd(newDiv('111','222','333'), 1,2,1,'2333');
|
||||
selEnd(newDiv('111','222','333'), 1,1,3,'22333');
|
||||
selEnd(newDiv('111','222',''), 1,1,3,'22');
|
||||
selEnd(newDiv('111','','333'), 0,1,3,'11333');
|
||||
|
||||
selStart(newDiv('111'), 0,0,0,'');
|
||||
selStart(newDiv('111'), 0,0,1,'');
|
||||
selStart(newDiv('111'), 0,0,3,'');
|
||||
selStart(newDiv('111'), 0,1,0,'1');
|
||||
selStart(newDiv('111'), 0,2,1,'11');
|
||||
selStart(newDiv('111'), 0,1,3,'1');
|
||||
selStart(newDiv(''), 0,0,0,'');
|
||||
selStart(newDiv('111','222'), 0,1,0,'1');
|
||||
selStart(newDiv('111','222'), 0,2,1,'11');
|
||||
selStart(newDiv('111','222'), 0,1,3,'1');
|
||||
selStart(newDiv('111','222'), 1,1,0,'1112');
|
||||
selStart(newDiv('111','222'), 1,2,1,'11122');
|
||||
selStart(newDiv('111','222'), 1,1,3,'1112');
|
||||
selStart(newDiv('','222'), 1,1,2,'2');
|
||||
selStart(newDiv('','222'), 0,0,0,'');
|
||||
selStart(newDiv('111',''), 1,0,0,'111');
|
||||
selStart(newDiv('111','222','333'), 1,1,0,'1112');
|
||||
selStart(newDiv('111','222','333'), 1,2,1,'11122');
|
||||
selStart(newDiv('111','222','333'), 1,1,3,'1112');
|
||||
selStart(newDiv('111','','333'), 1,0,0,'111');
|
||||
selStart(newDiv('111','222',''), 1,1,3,'1112');
|
||||
|
||||
selMiddleStart(newDiv('111','222','333'), 1,1,0,'2');
|
||||
selMiddleStart(newDiv('111','222','333'), 1,2,1,'22');
|
||||
selMiddleStart(newDiv('111','222','333'), 1,1,3,'2');
|
||||
selMiddleStart(newDiv('111','222','333'), 2,1,0,'2223');
|
||||
selMiddleStart(newDiv('111','222','333'), 2,2,1,'22233');
|
||||
selMiddleStart(newDiv('111','222','333'), 2,1,3,'2223');
|
||||
selMiddleStart(newDiv('111','','333'), 2,1,2,'3');
|
||||
selMiddleStart(newDiv('111','','333'), 1,0,0,'');
|
||||
|
||||
selMiddleEnd(newDiv('111','222','333'), 0,1,0,'11222');
|
||||
selMiddleEnd(newDiv('111','222','333'), 0,2,1,'1222');
|
||||
selMiddleEnd(newDiv('111','222','333'), 0,1,3,'11222');
|
||||
selMiddleEnd(newDiv('111','222','333'), 1,1,0,'22');
|
||||
selMiddleEnd(newDiv('111','222','333'), 1,2,1,'2');
|
||||
selMiddleEnd(newDiv('111','222','333'), 1,1,3,'22');
|
||||
selMiddleEnd(newDiv('111','','333'), 0,1,2,'11');
|
||||
selMiddleEnd(newDiv('111','','333'), 0,1,3,'11');
|
||||
selMiddleEnd(newDiv('111','','333'), 1,0,0,'');
|
||||
|
||||
splitBefore(newDiv('111','222','333'), 1,1,0,'2');
|
||||
splitBefore(newDiv('111','222','333'), 1,2,1,'22');
|
||||
splitBefore(newDiv('111','222','333'), 1,1,3,'2');
|
||||
splitBefore(newDiv('111','222','333'), 2,1,0,'2223');
|
||||
splitBefore(newDiv('111','222','333'), 2,2,1,'22233');
|
||||
splitBefore(newDiv('111','222','333'), 2,1,3,'2223');
|
||||
splitBefore(newDiv('','222','333'), 1,1,0,'2');
|
||||
splitBefore(newDiv('','','333'), 1,0,0,'');
|
||||
splitBefore(newDiv('','222',''), 2,0,0,'222');
|
||||
splitBefore(newDiv('111','','333'), 2,1,2,'3');
|
||||
}
|
||||
|
||||
function boom()
|
||||
{
|
||||
runTests("dry run"); // this is to verify the result strings without splitText()
|
||||
dry = false;
|
||||
flush = false;
|
||||
runTests("no flush");
|
||||
flush = true;
|
||||
runTests("flush");
|
||||
}
|
||||
|
||||
boom();
|
||||
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -85,100 +85,5 @@ CoerceDouble(jsval v, double* d)
|
|||
return true;
|
||||
}
|
||||
|
||||
template<size_t N>
|
||||
static bool
|
||||
JSValToMatrixElts(JSContext* cx, const jsval& val,
|
||||
double* (&elts)[N], nsresult* rv)
|
||||
{
|
||||
JSObject* obj;
|
||||
uint32_t length;
|
||||
|
||||
if (JSVAL_IS_PRIMITIVE(val) ||
|
||||
!(obj = JSVAL_TO_OBJECT(val)) ||
|
||||
!JS_GetArrayLength(cx, obj, &length) ||
|
||||
N != length) {
|
||||
// Not an array-like thing or wrong size
|
||||
*rv = NS_ERROR_INVALID_ARG;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < N; ++i) {
|
||||
jsval elt;
|
||||
double d;
|
||||
if (!JS_GetElement(cx, obj, i, &elt)) {
|
||||
*rv = NS_ERROR_FAILURE;
|
||||
return false;
|
||||
}
|
||||
if (!CoerceDouble(elt, &d)) {
|
||||
*rv = NS_ERROR_INVALID_ARG;
|
||||
return false;
|
||||
}
|
||||
if (!FloatValidate(d)) {
|
||||
// This is weird, but it's the behavior of SetTransform()
|
||||
*rv = NS_OK;
|
||||
return false;
|
||||
}
|
||||
*elts[i] = d;
|
||||
}
|
||||
|
||||
*rv = NS_OK;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
JSValToMatrix(JSContext* cx, const jsval& val, gfxMatrix* matrix, nsresult* rv)
|
||||
{
|
||||
double* elts[] = { &matrix->xx, &matrix->yx, &matrix->xy, &matrix->yy,
|
||||
&matrix->x0, &matrix->y0 };
|
||||
return JSValToMatrixElts(cx, val, elts, rv);
|
||||
}
|
||||
|
||||
bool
|
||||
JSValToMatrix(JSContext* cx, const jsval& val, Matrix* matrix, nsresult* rv)
|
||||
{
|
||||
gfxMatrix m;
|
||||
if (!JSValToMatrix(cx, val, &m, rv))
|
||||
return false;
|
||||
*matrix = Matrix(Float(m.xx), Float(m.yx), Float(m.xy), Float(m.yy),
|
||||
Float(m.x0), Float(m.y0));
|
||||
return true;
|
||||
}
|
||||
|
||||
template<size_t N>
|
||||
static nsresult
|
||||
MatrixEltsToJSVal(/*const*/ jsval (&elts)[N], JSContext* cx, jsval* val)
|
||||
{
|
||||
JSObject* obj = JS_NewArrayObject(cx, N, elts);
|
||||
if (!obj) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
*val = OBJECT_TO_JSVAL(obj);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
MatrixToJSVal(const gfxMatrix& matrix, JSContext* cx, jsval* val)
|
||||
{
|
||||
jsval elts[] = {
|
||||
DOUBLE_TO_JSVAL(matrix.xx), DOUBLE_TO_JSVAL(matrix.yx),
|
||||
DOUBLE_TO_JSVAL(matrix.xy), DOUBLE_TO_JSVAL(matrix.yy),
|
||||
DOUBLE_TO_JSVAL(matrix.x0), DOUBLE_TO_JSVAL(matrix.y0)
|
||||
};
|
||||
return MatrixEltsToJSVal(elts, cx, val);
|
||||
}
|
||||
|
||||
nsresult
|
||||
MatrixToJSVal(const Matrix& matrix, JSContext* cx, jsval* val)
|
||||
{
|
||||
jsval elts[] = {
|
||||
DOUBLE_TO_JSVAL(matrix._11), DOUBLE_TO_JSVAL(matrix._12),
|
||||
DOUBLE_TO_JSVAL(matrix._21), DOUBLE_TO_JSVAL(matrix._22),
|
||||
DOUBLE_TO_JSVAL(matrix._31), DOUBLE_TO_JSVAL(matrix._32)
|
||||
};
|
||||
return MatrixEltsToJSVal(elts, cx, val);
|
||||
}
|
||||
|
||||
} // namespace CanvasUtils
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -49,18 +49,6 @@ void DoDrawImageSecurityCheck(nsHTMLCanvasElement *aCanvasElement,
|
|||
// succeeded.
|
||||
bool CoerceDouble(jsval v, double* d);
|
||||
|
||||
// Return true iff the conversion succeeded, false otherwise. *rv is
|
||||
// the value to return to script if this returns false.
|
||||
bool JSValToMatrix(JSContext* cx, const jsval& val,
|
||||
gfxMatrix* matrix, nsresult* rv);
|
||||
bool JSValToMatrix(JSContext* cx, const jsval& val,
|
||||
gfx::Matrix* matrix, nsresult* rv);
|
||||
|
||||
nsresult MatrixToJSVal(const gfxMatrix& matrix,
|
||||
JSContext* cx, jsval* val);
|
||||
nsresult MatrixToJSVal(const gfx::Matrix& matrix,
|
||||
JSContext* cx, jsval* val);
|
||||
|
||||
/* Float validation stuff */
|
||||
#define VALIDATE(_f) if (!NS_finite(_f)) return false
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ CPPSRCS += \
|
|||
WebGLExtensionTextureFilterAnisotropic.cpp \
|
||||
WebGLExtensionTextureFloat.cpp \
|
||||
WebGLFramebuffer.cpp \
|
||||
WebGLObjectModel.cpp \
|
||||
WebGLProgram.cpp \
|
||||
WebGLRenderbuffer.cpp \
|
||||
WebGLShader.cpp \
|
||||
|
|
|
@ -3,11 +3,57 @@
|
|||
* 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/. */
|
||||
|
||||
#include "WebGLBuffer.h"
|
||||
#include "WebGLContext.h"
|
||||
#include "mozilla/dom/WebGLRenderingContextBinding.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
WebGLBuffer::WebGLBuffer(WebGLContext *context)
|
||||
: WebGLContextBoundObject(context)
|
||||
, mHasEverBeenBound(false)
|
||||
, mByteLength(0)
|
||||
, mTarget(LOCAL_GL_NONE)
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
mContext->MakeContextCurrent();
|
||||
mContext->gl->fGenBuffers(1, &mGLName);
|
||||
mContext->mBuffers.insertBack(this);
|
||||
}
|
||||
|
||||
WebGLBuffer::~WebGLBuffer() {
|
||||
DeleteOnce();
|
||||
}
|
||||
|
||||
void
|
||||
WebGLBuffer::Delete() {
|
||||
mContext->MakeContextCurrent();
|
||||
mContext->gl->fDeleteBuffers(1, &mGLName);
|
||||
mByteLength = 0;
|
||||
mCache = nullptr;
|
||||
LinkedListElement<WebGLBuffer>::remove(); // remove from mContext->mBuffers
|
||||
}
|
||||
|
||||
void
|
||||
WebGLBuffer::SetTarget(GLenum target) {
|
||||
mTarget = target;
|
||||
if (!mCache && mTarget == LOCAL_GL_ELEMENT_ARRAY_BUFFER)
|
||||
mCache = new WebGLElementArrayCache;
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLBuffer::ElementArrayCacheBufferData(const void* ptr, size_t buffer_size_in_bytes) {
|
||||
if (mTarget == LOCAL_GL_ELEMENT_ARRAY_BUFFER)
|
||||
return mCache->BufferData(ptr, buffer_size_in_bytes);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLBuffer::ElementArrayCacheBufferSubData(size_t pos, const void* ptr, size_t update_size_in_bytes) {
|
||||
if (mTarget == LOCAL_GL_ELEMENT_ARRAY_BUFFER)
|
||||
mCache->BufferSubData(pos, ptr, update_size_in_bytes);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
WebGLBuffer::WrapObject(JSContext *cx, JSObject *scope, bool *triedToWrap) {
|
||||
return dom::WebGLBufferBinding::Wrap(cx, scope, this, triedToWrap);
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef WEBGLBUFFER_H_
|
||||
#define WEBGLBUFFER_H_
|
||||
|
||||
#include "WebGLElementArrayCache.h"
|
||||
#include "WebGLObjectModel.h"
|
||||
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
#include "mozilla/LinkedList.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class WebGLBuffer MOZ_FINAL
|
||||
: public nsISupports
|
||||
, public WebGLRefCountedObject<WebGLBuffer>
|
||||
, public LinkedListElement<WebGLBuffer>
|
||||
, public WebGLContextBoundObject
|
||||
, public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
WebGLBuffer(WebGLContext *context);
|
||||
|
||||
~WebGLBuffer();
|
||||
|
||||
void Delete();
|
||||
|
||||
size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
|
||||
size_t sizeOfCache = mCache ? mCache->SizeOfIncludingThis(aMallocSizeOf) : 0;
|
||||
return aMallocSizeOf(this) + sizeOfCache;
|
||||
}
|
||||
|
||||
bool HasEverBeenBound() { return mHasEverBeenBound; }
|
||||
void SetHasEverBeenBound(bool x) { mHasEverBeenBound = x; }
|
||||
GLuint GLName() const { return mGLName; }
|
||||
GLuint ByteLength() const { return mByteLength; }
|
||||
GLenum Target() const { return mTarget; }
|
||||
|
||||
void SetByteLength(GLuint byteLength) { mByteLength = byteLength; }
|
||||
|
||||
void SetTarget(GLenum target);
|
||||
|
||||
bool ElementArrayCacheBufferData(const void* ptr, size_t buffer_size_in_bytes);
|
||||
|
||||
void ElementArrayCacheBufferSubData(size_t pos, const void* ptr, size_t update_size_in_bytes);
|
||||
|
||||
bool Validate(WebGLenum type, uint32_t max_allowed, size_t first, size_t count) {
|
||||
return mCache->Validate(type, max_allowed, first, count);
|
||||
}
|
||||
|
||||
WebGLContext *GetParentObject() const {
|
||||
return Context();
|
||||
}
|
||||
|
||||
virtual JSObject* WrapObject(JSContext *cx, JSObject *scope, bool *triedToWrap);
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(WebGLBuffer)
|
||||
|
||||
protected:
|
||||
|
||||
WebGLuint mGLName;
|
||||
bool mHasEverBeenBound;
|
||||
GLuint mByteLength;
|
||||
GLenum mTarget;
|
||||
|
||||
nsAutoPtr<WebGLElementArrayCache> mCache;
|
||||
};
|
||||
}
|
||||
#endif //WEBGLBUFFER_H_
|
|
@ -4,6 +4,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "WebGLContext.h"
|
||||
#include "WebGLObjectModel.h"
|
||||
#include "WebGLExtensions.h"
|
||||
#include "WebGLContextUtils.h"
|
||||
|
||||
|
@ -172,6 +173,9 @@ WebGLContext::WebGLContext()
|
|||
mAlreadyWarnedAboutFakeVertexAttrib0 = false;
|
||||
|
||||
mLastUseIndex = 0;
|
||||
|
||||
mMinInUseAttribArrayLengthCached = false;
|
||||
mMinInUseAttribArrayLength = 0;
|
||||
}
|
||||
|
||||
WebGLContext::~WebGLContext()
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
#ifndef WEBGLCONTEXT_H_
|
||||
#define WEBGLCONTEXT_H_
|
||||
|
||||
#include "WebGLElementArrayCache.h"
|
||||
#include "WebGLObjectModel.h"
|
||||
#include "WebGLBuffer.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <vector>
|
||||
|
||||
|
@ -42,8 +46,6 @@
|
|||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
|
||||
#include "WebGLElementArrayCache.h"
|
||||
|
||||
/*
|
||||
* Minimum value constants defined in 6.2 State Tables of OpenGL ES - 2.0.25
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=686732
|
||||
|
@ -62,30 +64,16 @@
|
|||
#define MINVALUE_GL_MAX_RENDERBUFFER_SIZE 1024 // Different from the spec, which sets it to 1 on page 164
|
||||
#define MINVALUE_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 8 // Page 164
|
||||
|
||||
// Manual reflection of WebIDL typedefs
|
||||
typedef uint32_t WebGLenum;
|
||||
typedef uint32_t WebGLbitfield;
|
||||
typedef int32_t WebGLint;
|
||||
typedef int32_t WebGLsizei;
|
||||
typedef int64_t WebGLsizeiptr;
|
||||
typedef int64_t WebGLintptr;
|
||||
typedef uint32_t WebGLuint;
|
||||
typedef float WebGLfloat;
|
||||
typedef float WebGLclampf;
|
||||
typedef bool WebGLboolean;
|
||||
|
||||
class nsIPropertyBag;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class WebGLTexture;
|
||||
class WebGLBuffer;
|
||||
class WebGLProgram;
|
||||
class WebGLShader;
|
||||
class WebGLFramebuffer;
|
||||
class WebGLRenderbuffer;
|
||||
class WebGLUniformLocation;
|
||||
class WebGLContext;
|
||||
class WebGLRenderbuffer;
|
||||
struct WebGLVertexAttribData;
|
||||
class WebGLMemoryPressureObserver;
|
||||
class WebGLRectangleObject;
|
||||
|
@ -163,246 +151,6 @@ inline bool is_pot_assuming_nonnegative(WebGLsizei x)
|
|||
return x && (x & (x-1)) == 0;
|
||||
}
|
||||
|
||||
/* Each WebGL object class WebGLFoo wants to:
|
||||
* - inherit WebGLRefCountedObject<WebGLFoo>
|
||||
* - implement a Delete() method
|
||||
* - have its destructor call DeleteOnce()
|
||||
*
|
||||
* This base class provides two features to WebGL object types:
|
||||
* 1. support for OpenGL object reference counting
|
||||
* 2. support for OpenGL deletion statuses
|
||||
*
|
||||
***** 1. OpenGL object reference counting *****
|
||||
*
|
||||
* WebGL objects such as WebGLTexture's really have two different refcounts:
|
||||
* the XPCOM refcount, that is directly exposed to JavaScript, and the OpenGL
|
||||
* refcount.
|
||||
*
|
||||
* For example, when in JavaScript one does: var newname = existingTexture;
|
||||
* that increments the XPCOM refcount, but doesn't affect the OpenGL refcount.
|
||||
* When one attaches the texture to a framebuffer object, that does increment
|
||||
* its OpenGL refcount (and also its XPCOM refcount, to prevent the regular
|
||||
* XPCOM refcounting mechanism from destroying objects prematurely).
|
||||
*
|
||||
* The actual OpenGL refcount is opaque to us (it's internal to the OpenGL
|
||||
* implementation) but is affects the WebGL semantics that we have to implement:
|
||||
* for example, a WebGLTexture that is attached to a WebGLFramebuffer must not
|
||||
* be actually deleted, even if deleteTexture has been called on it, and even
|
||||
* if JavaScript doesn't have references to it anymore. We can't just rely on
|
||||
* OpenGL to keep alive the underlying OpenGL texture for us, for a variety of
|
||||
* reasons, most importantly: we'd need to know when OpenGL objects are actually
|
||||
* deleted, and OpenGL doesn't notify us about that, so we would have to query
|
||||
* status very often with glIsXxx calls which isn't practical.
|
||||
*
|
||||
* This means that we have to keep track of the OpenGL refcount ourselves,
|
||||
* in addition to the XPCOM refcount.
|
||||
*
|
||||
* This class implements such a refcount, see the mWebGLRefCnt
|
||||
* member. In order to avoid name clashes (with regular XPCOM refcounting)
|
||||
* in the derived class, we prefix members with 'WebGL', whence the names
|
||||
* WebGLAddRef, WebGLRelease, etc.
|
||||
*
|
||||
* In practice, WebGLAddRef and WebGLRelease are only called from the
|
||||
* WebGLRefPtr class.
|
||||
*
|
||||
***** 2. OpenGL deletion statuses *****
|
||||
*
|
||||
* In OpenGL, an object can go through 3 different deletion statuses during its
|
||||
* lifetime, which correspond to the 3 enum values for DeletionStatus in this class:
|
||||
* - the Default status, which it has from its creation to when the
|
||||
* suitable glDeleteXxx function is called on it;
|
||||
* - the DeleteRequested status, which is has from when the suitable glDeleteXxx
|
||||
* function is called on it to when it is no longer referenced by other OpenGL
|
||||
* objects. For example, a texture that is attached to a non-current FBO
|
||||
* will enter that status when glDeleteTexture is called on it. For objects
|
||||
* with that status, GL_DELETE_STATUS queries return true, but glIsXxx
|
||||
* functions still return true.
|
||||
* - the Deleted status, which is the status of objects on which the
|
||||
* suitable glDeleteXxx function has been called, and that are not referenced
|
||||
* by other OpenGL objects.
|
||||
*
|
||||
* This state is stored in the mDeletionStatus member of this class.
|
||||
*
|
||||
* When the GL refcount hits zero, if the status is DeleteRequested then we call
|
||||
* the Delete() method on the derived class and the status becomes Deleted. This is
|
||||
* what the MaybeDelete() function does.
|
||||
*
|
||||
* The DeleteOnce() function implemented here is a helper to ensure that we don't
|
||||
* call Delete() twice on the same object. Since the derived class' destructor
|
||||
* needs to call DeleteOnce() which calls Delete(), we can't allow either to be
|
||||
* virtual. Strictly speaking, we could let them be virtual if the derived class
|
||||
* were final, but that would be impossible to enforce and would lead to strange
|
||||
* bugs if it were subclassed.
|
||||
*
|
||||
* This WebGLRefCountedObject class takes the Derived type
|
||||
* as template parameter, as a means to allow DeleteOnce to call Delete()
|
||||
* on the Derived class, without either method being virtual. This is a common
|
||||
* C++ pattern known as the "curiously recursive template pattern (CRTP)".
|
||||
*/
|
||||
template<typename Derived>
|
||||
class WebGLRefCountedObject
|
||||
{
|
||||
public:
|
||||
enum DeletionStatus { Default, DeleteRequested, Deleted };
|
||||
|
||||
WebGLRefCountedObject()
|
||||
: mDeletionStatus(Default)
|
||||
{ }
|
||||
|
||||
~WebGLRefCountedObject() {
|
||||
NS_ABORT_IF_FALSE(mWebGLRefCnt == 0, "destroying WebGL object still referenced by other WebGL objects");
|
||||
NS_ABORT_IF_FALSE(mDeletionStatus == Deleted, "Derived class destructor must call DeleteOnce()");
|
||||
}
|
||||
|
||||
// called by WebGLRefPtr
|
||||
void WebGLAddRef() {
|
||||
++mWebGLRefCnt;
|
||||
}
|
||||
|
||||
// called by WebGLRefPtr
|
||||
void WebGLRelease() {
|
||||
NS_ABORT_IF_FALSE(mWebGLRefCnt > 0, "releasing WebGL object with WebGL refcnt already zero");
|
||||
--mWebGLRefCnt;
|
||||
MaybeDelete();
|
||||
}
|
||||
|
||||
// this is the function that WebGL.deleteXxx() functions want to call
|
||||
void RequestDelete() {
|
||||
if (mDeletionStatus == Default)
|
||||
mDeletionStatus = DeleteRequested;
|
||||
MaybeDelete();
|
||||
}
|
||||
|
||||
bool IsDeleted() const {
|
||||
return mDeletionStatus == Deleted;
|
||||
}
|
||||
|
||||
bool IsDeleteRequested() const {
|
||||
return mDeletionStatus != Default;
|
||||
}
|
||||
|
||||
void DeleteOnce() {
|
||||
if (mDeletionStatus != Deleted) {
|
||||
static_cast<Derived*>(this)->Delete();
|
||||
mDeletionStatus = Deleted;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void MaybeDelete() {
|
||||
if (mWebGLRefCnt == 0 &&
|
||||
mDeletionStatus == DeleteRequested)
|
||||
{
|
||||
DeleteOnce();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
nsAutoRefCnt mWebGLRefCnt;
|
||||
DeletionStatus mDeletionStatus;
|
||||
};
|
||||
|
||||
/* This WebGLRefPtr class is meant to be used for references between WebGL objects.
|
||||
* For example, a WebGLProgram holds WebGLRefPtr's to the WebGLShader's attached
|
||||
* to it.
|
||||
*
|
||||
* Why the need for a separate refptr class? The only special thing that WebGLRefPtr
|
||||
* does is that it increments and decrements the WebGL refcount of
|
||||
* WebGLRefCountedObject's, in addition to incrementing and decrementing the
|
||||
* usual XPCOM refcount.
|
||||
*
|
||||
* This means that by using a WebGLRefPtr instead of a nsRefPtr, you ensure that
|
||||
* the WebGL refcount is incremented, which means that the object will be kept
|
||||
* alive by this reference even if the matching webgl.deleteXxx() function is
|
||||
* called on it.
|
||||
*/
|
||||
template<typename T>
|
||||
class WebGLRefPtr
|
||||
{
|
||||
public:
|
||||
WebGLRefPtr()
|
||||
: mRawPtr(0)
|
||||
{ }
|
||||
|
||||
WebGLRefPtr(const WebGLRefPtr<T>& aSmartPtr)
|
||||
: mRawPtr(aSmartPtr.mRawPtr)
|
||||
{
|
||||
AddRefOnPtr(mRawPtr);
|
||||
}
|
||||
|
||||
WebGLRefPtr(T *aRawPtr)
|
||||
: mRawPtr(aRawPtr)
|
||||
{
|
||||
AddRefOnPtr(mRawPtr);
|
||||
}
|
||||
|
||||
~WebGLRefPtr() {
|
||||
ReleasePtr(mRawPtr);
|
||||
}
|
||||
|
||||
WebGLRefPtr<T>&
|
||||
operator=(const WebGLRefPtr<T>& rhs)
|
||||
{
|
||||
assign_with_AddRef(rhs.mRawPtr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
WebGLRefPtr<T>&
|
||||
operator=(T* rhs)
|
||||
{
|
||||
assign_with_AddRef(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
T* get() const {
|
||||
return static_cast<T*>(mRawPtr);
|
||||
}
|
||||
|
||||
operator T*() const {
|
||||
return get();
|
||||
}
|
||||
|
||||
T* operator->() const {
|
||||
NS_ABORT_IF_FALSE(mRawPtr != 0, "You can't dereference a NULL WebGLRefPtr with operator->()!");
|
||||
return get();
|
||||
}
|
||||
|
||||
T& operator*() const {
|
||||
NS_ABORT_IF_FALSE(mRawPtr != 0, "You can't dereference a NULL WebGLRefPtr with operator*()!");
|
||||
return *get();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static void AddRefOnPtr(T* rawPtr) {
|
||||
if (rawPtr) {
|
||||
rawPtr->WebGLAddRef();
|
||||
rawPtr->AddRef();
|
||||
}
|
||||
}
|
||||
|
||||
static void ReleasePtr(T* rawPtr) {
|
||||
if (rawPtr) {
|
||||
rawPtr->WebGLRelease(); // must be done first before Release(), as Release() might actually destroy the object
|
||||
rawPtr->Release();
|
||||
}
|
||||
}
|
||||
|
||||
void assign_with_AddRef(T* rawPtr) {
|
||||
AddRefOnPtr(rawPtr);
|
||||
assign_assuming_AddRef(rawPtr);
|
||||
}
|
||||
|
||||
void assign_assuming_AddRef(T* newPtr) {
|
||||
T* oldPtr = mRawPtr;
|
||||
mRawPtr = newPtr;
|
||||
ReleasePtr(oldPtr);
|
||||
}
|
||||
|
||||
protected:
|
||||
T *mRawPtr;
|
||||
};
|
||||
|
||||
// this class is a mixin for GL objects that have dimensions
|
||||
// that we need to track.
|
||||
class WebGLRectangleObject
|
||||
|
@ -1170,11 +918,13 @@ protected:
|
|||
|
||||
// Cache the max number of elements that can be read from bound VBOs
|
||||
// (result of ValidateBuffers).
|
||||
int32_t mMinInUseAttribArrayLength;
|
||||
bool mMinInUseAttribArrayLengthCached;
|
||||
uint32_t mMinInUseAttribArrayLength;
|
||||
|
||||
inline void InvalidateCachedMinInUseAttribArrayLength()
|
||||
{
|
||||
mMinInUseAttribArrayLength = -1;
|
||||
mMinInUseAttribArrayLengthCached = false;
|
||||
mMinInUseAttribArrayLength = 0;
|
||||
}
|
||||
|
||||
// Represents current status, or state, of the context. That is, is it lost
|
||||
|
@ -1220,7 +970,7 @@ protected:
|
|||
nsTArray<WebGLenum> mCompressedTextureFormats;
|
||||
|
||||
bool InitAndValidateGL();
|
||||
bool ValidateBuffers(int32_t *maxAllowedCount, const char *info);
|
||||
bool ValidateBuffers(uint32_t *maxAllowedCount, const char *info);
|
||||
bool ValidateCapabilityEnum(WebGLenum cap, const char *info);
|
||||
bool ValidateBlendEquationEnum(WebGLenum cap, const char *info);
|
||||
bool ValidateBlendFuncDstEnum(WebGLenum mode, const char *info);
|
||||
|
@ -1461,29 +1211,6 @@ ToSupports(WebGLContext* context)
|
|||
return static_cast<nsICanvasRenderingContextInternal*>(context);
|
||||
}
|
||||
|
||||
// This class is a mixin for objects that are tied to a specific
|
||||
// context (which is to say, all of them). They provide initialization
|
||||
// as well as comparison with the current context.
|
||||
class WebGLContextBoundObject
|
||||
{
|
||||
public:
|
||||
WebGLContextBoundObject(WebGLContext *context) {
|
||||
mContext = context;
|
||||
mContextGeneration = context->Generation();
|
||||
}
|
||||
|
||||
bool IsCompatibleWithContext(WebGLContext *other) {
|
||||
return mContext == other &&
|
||||
mContextGeneration == other->Generation();
|
||||
}
|
||||
|
||||
WebGLContext *Context() const { return mContext; }
|
||||
|
||||
protected:
|
||||
WebGLContext *mContext;
|
||||
uint32_t mContextGeneration;
|
||||
};
|
||||
|
||||
struct WebGLVertexAttribData {
|
||||
// note that these initial values are what GL initializes vertex attribs to
|
||||
WebGLVertexAttribData()
|
||||
|
@ -1529,90 +1256,6 @@ struct WebGLVertexAttribData {
|
|||
}
|
||||
};
|
||||
|
||||
class WebGLBuffer MOZ_FINAL
|
||||
: public nsISupports
|
||||
, public WebGLRefCountedObject<WebGLBuffer>
|
||||
, public LinkedListElement<WebGLBuffer>
|
||||
, public WebGLContextBoundObject
|
||||
, public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
WebGLBuffer(WebGLContext *context)
|
||||
: WebGLContextBoundObject(context)
|
||||
, mHasEverBeenBound(false)
|
||||
, mByteLength(0)
|
||||
, mTarget(LOCAL_GL_NONE)
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
mContext->MakeContextCurrent();
|
||||
mContext->gl->fGenBuffers(1, &mGLName);
|
||||
mContext->mBuffers.insertBack(this);
|
||||
}
|
||||
|
||||
~WebGLBuffer() {
|
||||
DeleteOnce();
|
||||
}
|
||||
|
||||
void Delete() {
|
||||
mContext->MakeContextCurrent();
|
||||
mContext->gl->fDeleteBuffers(1, &mGLName);
|
||||
mByteLength = 0;
|
||||
mCache = nullptr;
|
||||
LinkedListElement<WebGLBuffer>::removeFrom(mContext->mBuffers);
|
||||
}
|
||||
|
||||
size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
|
||||
size_t sizeOfCache = mCache ? mCache->SizeOfIncludingThis(aMallocSizeOf) : 0;
|
||||
return aMallocSizeOf(this) + sizeOfCache;
|
||||
}
|
||||
|
||||
bool HasEverBeenBound() { return mHasEverBeenBound; }
|
||||
void SetHasEverBeenBound(bool x) { mHasEverBeenBound = x; }
|
||||
GLuint GLName() const { return mGLName; }
|
||||
GLuint ByteLength() const { return mByteLength; }
|
||||
GLenum Target() const { return mTarget; }
|
||||
|
||||
void SetByteLength(GLuint byteLength) { mByteLength = byteLength; }
|
||||
|
||||
void SetTarget(GLenum target) {
|
||||
mTarget = target;
|
||||
if (!mCache && mTarget == LOCAL_GL_ELEMENT_ARRAY_BUFFER)
|
||||
mCache = new WebGLElementArrayCache;
|
||||
}
|
||||
|
||||
bool ElementArrayCacheBufferData(const void* ptr, size_t buffer_size_in_bytes) {
|
||||
if (mTarget == LOCAL_GL_ELEMENT_ARRAY_BUFFER)
|
||||
return mCache->BufferData(ptr, buffer_size_in_bytes);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ElementArrayCacheBufferSubData(size_t pos, const void* ptr, size_t update_size_in_bytes) {
|
||||
if (mTarget == LOCAL_GL_ELEMENT_ARRAY_BUFFER)
|
||||
mCache->BufferSubData(pos, ptr, update_size_in_bytes);
|
||||
}
|
||||
|
||||
bool Validate(WebGLenum type, uint32_t max_allowed, size_t first, size_t count) {
|
||||
return mCache->Validate(type, max_allowed, first, count);
|
||||
}
|
||||
|
||||
WebGLContext *GetParentObject() const {
|
||||
return Context();
|
||||
}
|
||||
|
||||
virtual JSObject* WrapObject(JSContext *cx, JSObject *scope, bool *triedToWrap);
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(WebGLBuffer)
|
||||
|
||||
protected:
|
||||
|
||||
WebGLuint mGLName;
|
||||
bool mHasEverBeenBound;
|
||||
GLuint mByteLength;
|
||||
GLenum mTarget;
|
||||
|
||||
nsAutoPtr<WebGLElementArrayCache> mCache;
|
||||
};
|
||||
|
||||
// NOTE: When this class is switched to new DOM bindings, update the (then-slow)
|
||||
// WrapObject calls in GetParameter and GetFramebufferAttachmentParameter.
|
||||
|
@ -3465,22 +3108,4 @@ ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
|
|||
aCallback.NoteXPCOMChild(aField.buf);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void
|
||||
ImplCycleCollectionUnlink(mozilla::WebGLRefPtr<T>& aField)
|
||||
{
|
||||
aField = nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void
|
||||
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
|
||||
mozilla::WebGLRefPtr<T>& aField,
|
||||
const char* aName,
|
||||
uint32_t aFlags = 0)
|
||||
{
|
||||
CycleCollectionNoteEdgeName(aCallback, aName, aFlags);
|
||||
aCallback.NoteXPCOMChild(aField);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1418,11 +1418,11 @@ WebGLContext::DrawArrays(GLenum mode, WebGLint first, WebGLsizei count)
|
|||
if (!mCurrentProgram)
|
||||
return;
|
||||
|
||||
int32_t maxAllowedCount = 0;
|
||||
uint32_t maxAllowedCount = 0;
|
||||
if (!ValidateBuffers(&maxAllowedCount, "drawArrays"))
|
||||
return;
|
||||
|
||||
CheckedInt32 checked_firstPlusCount = CheckedInt32(first) + count;
|
||||
CheckedUint32 checked_firstPlusCount = CheckedUint32(first) + count;
|
||||
|
||||
if (!checked_firstPlusCount.isValid())
|
||||
return ErrorInvalidOperation("drawArrays: overflow in first+count");
|
||||
|
@ -1511,13 +1511,13 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type,
|
|||
if (checked_neededByteCount.value() > mBoundElementArrayBuffer->ByteLength())
|
||||
return ErrorInvalidOperation("drawElements: bound element array buffer is too small for given count and offset");
|
||||
|
||||
int32_t maxAllowedCount = 0;
|
||||
uint32_t maxAllowedCount = 0;
|
||||
if (!ValidateBuffers(&maxAllowedCount, "drawElements"))
|
||||
return;
|
||||
return;
|
||||
|
||||
int32_t maxAllowedIndex = NS_MAX(maxAllowedCount - 1, 0);
|
||||
|
||||
if (!mBoundElementArrayBuffer->Validate(type, maxAllowedIndex, first, count)) {
|
||||
if (!maxAllowedCount ||
|
||||
!mBoundElementArrayBuffer->Validate(type, maxAllowedCount - 1, first, count))
|
||||
{
|
||||
return ErrorInvalidOperation(
|
||||
"DrawElements: bound vertex attribute buffers do not have sufficient "
|
||||
"size for given indices from the bound element array");
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче