This commit is contained in:
Richard Newman 2012-11-21 09:37:58 -08:00
Родитель da2eaf1742 1e5820e470
Коммит 9f33dc8380
494 изменённых файлов: 12491 добавлений и 4733 удалений

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

@ -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

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

@ -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");

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше