--- a/accessible/src/base/NotificationController.cpp
+++ b/accessible/src/base/NotificationController.cpp
@@ -50,17 +50,17 @@
////////////////////////////////////////////////////////////////////////////////
// NotificationCollector
////////////////////////////////////////////////////////////////////////////////
NotificationController::NotificationController(nsDocAccessible* aDocument,
nsIPresShell* aPresShell) :
mObservingState(eNotObservingRefresh), mDocument(aDocument),
- mPresShell(aPresShell), mTreeConstructedState(eTreeConstructionPending)
+ mPresShell(aPresShell)
{
mTextHash.Init();
// Schedule initial accessible tree construction.
ScheduleProcessing();
}
NotificationController::~NotificationController()
@@ -149,20 +149,16 @@ NotificationController::ScheduleChildDoc
ScheduleProcessing();
}
void
NotificationController::ScheduleContentInsertion(nsAccessible* aContainer,
nsIContent* aStartChildNode,
nsIContent* aEndChildNode)
{
- // Ignore content insertions until we constructed accessible tree.
- if (mTreeConstructedState == eTreeConstructionPending)
- return;
-
nsRefPtr<ContentInsertion> insertion = new ContentInsertion(mDocument,
aContainer);
if (insertion && insertion->InitChildList(aStartChildNode, aEndChildNode) &&
mContentInsertions.AppendElement(insertion)) {
ScheduleProcessing();
}
}
@@ -202,29 +198,28 @@ NotificationController::WillRefresh(mozi
if (!mDocument)
return;
// Any generic notifications should be queued if we're processing content
// insertions or generic notifications.
mObservingState = eRefreshProcessingForUpdate;
// Initial accessible tree construction.
- if (mTreeConstructedState == eTreeConstructionPending) {
+ if (!mDocument->HasLoadState(nsDocAccessible::eTreeConstructed)) {
// If document is not bound to parent at this point then the document is not
// ready yet (process notifications later).
if (!mDocument->IsBoundToParent())
return;
#ifdef DEBUG_NOTIFICATIONS
printf("\ninitial tree created, document: %p, document node: %p\n",
mDocument.get(), mDocument->GetDocumentNode());
#endif
- mTreeConstructedState = eTreeConstructed;
- mDocument->NotifyOfInitialUpdate();
+ mDocument->DoInitialUpdate();
NS_ASSERTION(mContentInsertions.Length() == 0,
"Pending content insertions while initial accessible tree isn't created!");
}
// Process content inserted notifications to update the tree. Process other
// notifications like DOM events and then flush event queue. If any new
// notifications are queued during this processing then they will be processed
@@ -245,18 +240,18 @@ NotificationController::WillRefresh(mozi
return;
}
// Process rendered text change notifications.
mTextHash.EnumerateEntries(TextEnumerator, mDocument);
mTextHash.Clear();
// Bind hanging child documents.
- PRUint32 childDocCount = mHangingChildDocuments.Length();
- for (PRUint32 idx = 0; idx < childDocCount; idx++) {
+ PRUint32 hangingDocCnt = mHangingChildDocuments.Length();
+ for (PRUint32 idx = 0; idx < hangingDocCnt; idx++) {
nsDocAccessible* childDoc = mHangingChildDocuments[idx];
nsIContent* ownerContent = mDocument->GetDocumentNode()->
FindContentForSubDocument(childDoc->GetDocumentNode());
if (ownerContent) {
nsAccessible* outerDocAcc = mDocument->GetAccessible(ownerContent);
if (outerDocAcc && outerDocAcc->AppendChild(childDoc)) {
if (mDocument->AppendChildDocument(childDoc))
@@ -266,16 +261,35 @@ NotificationController::WillRefresh(mozi
}
// Failed to bind the child document, destroy it.
childDoc->Shutdown();
}
}
mHangingChildDocuments.Clear();
+ // If the document is ready and all its subdocuments are completely loaded
+ // then process the document load.
+ if (mDocument->HasLoadState(nsDocAccessible::eReady) &&
+ !mDocument->HasLoadState(nsDocAccessible::eCompletelyLoaded) &&
+ hangingDocCnt == 0) {
+ PRUint32 childDocCnt = mDocument->ChildDocumentCount(), childDocIdx = 0;
+ for (; childDocIdx < childDocCnt; childDocIdx++) {
+ nsDocAccessible* childDoc = mDocument->GetChildDocumentAt(childDocIdx);
+ if (!childDoc->HasLoadState(nsDocAccessible::eCompletelyLoaded))
+ break;
+ }
+
+ if (childDocIdx == childDocCnt) {
+ mDocument->ProcessLoad();
+ if (!mDocument)
+ return;
+ }
+ }
+
// Process only currently queued generic notifications.
nsTArray < nsRefPtr<Notification> > notifications;
notifications.SwapElements(mNotifications);
PRUint32 notificationCount = notifications.Length();
for (PRUint32 idx = 0; idx < notificationCount; idx++) {
notifications[idx]->Process();
if (!mDocument)
@@ -305,20 +319,22 @@ NotificationController::WillRefresh(mozi
if (showOrHideEvent->mTextChangeEvent)
mDocument->ProcessPendingEvent(showOrHideEvent->mTextChangeEvent);
}
}
if (!mDocument)
return;
}
- // Stop further processing if there are no newly queued insertions,
- // notifications or events.
+ // Stop further processing if there are no new notifications of any kind or
+ // events and document load is processed.
if (mContentInsertions.Length() == 0 && mNotifications.Length() == 0 &&
- mEvents.Length() == 0 &&
+ mEvents.Length() == 0 && mTextHash.Count() == 0 &&
+ mHangingChildDocuments.Length() == 0 &&
+ mDocument->HasLoadState(nsDocAccessible::eCompletelyLoaded) &&
mPresShell->RemoveRefreshObserver(this, Flush_Display)) {
mObservingState = eNotObservingRefresh;
}
}
////////////////////////////////////////////////////////////////////////////////
// NotificationController: event queue
--- a/accessible/src/base/NotificationController.h
+++ b/accessible/src/base/NotificationController.h
@@ -123,24 +123,16 @@ public:
virtual ~NotificationController();
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(NotificationController)
/**
- * Return true when tree is constructed.
- */
- inline bool IsTreeConstructed()
- {
- return mTreeConstructedState == eTreeConstructed;
- }
-
- /**
* Shutdown the notification controller.
*/
void Shutdown();
/**
* Put an accessible event into the queue to process it later.
*/
void QueueEvent(AccEvent* aEvent);
@@ -150,21 +142,18 @@ public:
*/
void ScheduleChildDocBinding(nsDocAccessible* aDocument);
/**
* Schedule the accessible tree update because of rendered text changes.
*/
inline void ScheduleTextUpdate(nsIContent* aTextNode)
{
- // Ignore the notification if initial tree construction hasn't been done yet.
- if (mTreeConstructedState != eTreeConstructionPending &&
- mTextHash.PutEntry(aTextNode)) {
+ if (mTextHash.PutEntry(aTextNode))
ScheduleProcessing();
- }
}
/**
* Pend accessible tree update for content insertion.
*/
void ScheduleContentInsertion(nsAccessible* aContainer,
nsIContent* aStartChildNode,
nsIContent* aEndChildNode);
@@ -295,27 +284,16 @@ private:
nsRefPtr<nsDocAccessible> mDocument;
/**
* The presshell of the document accessible.
*/
nsIPresShell* mPresShell;
/**
- * Indicate whether initial construction of the document's accessible tree
- * performed or pending. When the document accessible is created then
- * we construct its initial accessible tree.
- */
- enum eTreeConstructedState {
- eTreeConstructed,
- eTreeConstructionPending
- };
- eTreeConstructedState mTreeConstructedState;
-
- /**
* Child documents that needs to be bound to the tree.
*/
nsTArray<nsRefPtr<nsDocAccessible> > mHangingChildDocuments;
/**
* Storage for content inserted notification information.
*/
class ContentInsertion
--- a/accessible/src/base/nsAccDocManager.cpp
+++ b/accessible/src/base/nsAccDocManager.cpp
@@ -185,53 +185,35 @@ nsAccDocManager::OnStateChange(nsIWebPro
HandleDOMDocumentLoad(document, eventType);
return NS_OK;
}
// Document loading was started.
NS_LOG_ACCDOCLOAD("start document loading", aWebProgress, aRequest,
aStateFlags)
- if (!IsEventTargetDocument(document))
- return NS_OK;
-
nsDocAccessible* docAcc = mDocAccessibleCache.GetWeak(document);
if (!docAcc)
return NS_OK;
nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(DOMWindow));
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(webNav));
NS_ENSURE_STATE(docShell);
- // Fire reload and state busy events on existing document accessible while
- // event from user input flag can be calculated properly and accessible
- // is alive. When new document gets loaded then this one is destroyed.
+ bool isReloading = false;
PRUint32 loadType;
docShell->GetLoadType(&loadType);
if (loadType == LOAD_RELOAD_NORMAL ||
loadType == LOAD_RELOAD_BYPASS_CACHE ||
loadType == LOAD_RELOAD_BYPASS_PROXY ||
loadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE) {
-
- // Fire reload event.
- nsRefPtr<AccEvent> reloadEvent =
- new AccEvent(nsIAccessibleEvent::EVENT_DOCUMENT_RELOAD, docAcc);
- nsEventShell::FireEvent(reloadEvent);
+ isReloading = true;
}
- // Mark the document accessible as loading, if it stays alive then we'll mark
- // it as loaded when we receive proper notification.
- docAcc->MarkAsLoading();
-
- // 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(document, states::BUSY, PR_TRUE);
- docAcc->FireDelayedAccessibleEvent(stateEvent);
-
+ docAcc->NotifyOfLoading(isReloading);
return NS_OK;
}
NS_IMETHODIMP
nsAccDocManager::OnProgressChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest,
PRInt32 aCurSelfProgress,
PRInt32 aMaxSelfProgress,
@@ -333,64 +315,17 @@ nsAccDocManager::HandleDOMDocumentLoad(n
// was loaded completely. However if it's not created yet then create it.
nsDocAccessible* docAcc = mDocAccessibleCache.GetWeak(aDocument);
if (!docAcc) {
docAcc = CreateDocOrRootAccessible(aDocument);
if (!docAcc)
return;
}
- // Mark the document as loaded to drop off the busy state flag on it.
- docAcc->MarkAsLoaded();
-
- // Do not fire document complete/stop events for root chrome document
- // accessibles and for frame/iframe documents because
- // a) screen readers start working on focus event in the case of root chrome
- // documents
- // b) document load event on sub documents causes screen readers to act is if
- // entire page is reloaded.
- if (!IsEventTargetDocument(aDocument))
- return;
-
- // Fire complete/load stopped if the load event type is given.
- if (aLoadEventType) {
- nsRefPtr<AccEvent> loadEvent = new AccEvent(aLoadEventType, aDocument);
- docAcc->FireDelayedAccessibleEvent(loadEvent);
- }
-
- // Fire busy state change event.
- nsRefPtr<AccEvent> stateEvent =
- new AccStateChangeEvent(aDocument, states::BUSY, PR_FALSE);
- docAcc->FireDelayedAccessibleEvent(stateEvent);
-}
-
-PRBool
-nsAccDocManager::IsEventTargetDocument(nsIDocument *aDocument) const
-{
- nsCOMPtr<nsISupports> container = aDocument->GetContainer();
- nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
- do_QueryInterface(container);
- NS_ASSERTION(docShellTreeItem, "No document shell for document!");
-
- nsCOMPtr<nsIDocShellTreeItem> parentTreeItem;
- docShellTreeItem->GetParent(getter_AddRefs(parentTreeItem));
-
- // It's not a root document.
- if (parentTreeItem) {
- nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
- docShellTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
-
- // It's not a sub document, i.e. a frame or iframe.
- return (sameTypeRoot == docShellTreeItem);
- }
-
- // It's not chrome root document.
- PRInt32 contentType;
- docShellTreeItem->GetItemType(&contentType);
- return (contentType == nsIDocShellTreeItem::typeContent);
+ docAcc->NotifyOfLoad(aLoadEventType);
}
void
nsAccDocManager::AddListeners(nsIDocument *aDocument,
PRBool aAddDOMContentLoadedListener)
{
nsPIDOMWindow *window = aDocument->GetWindow();
nsIDOMEventTarget *target = window->GetChromeEventHandler();
--- a/accessible/src/base/nsAccDocManager.h
+++ b/accessible/src/base/nsAccDocManager.h
@@ -116,34 +116,16 @@ private:
* @param aDocument [in] loaded DOM document
* @param aLoadEventType [in] specifies the event type to fire load event,
* if 0 then no event is fired
*/
void HandleDOMDocumentLoad(nsIDocument *aDocument,
PRUint32 aLoadEventType);
/**
- * Return true if accessibility events accompanying document accessible
- * loading should be fired.
- *
- * The rules are: do not fire events for root chrome document accessibles and
- * for sub document accessibles (like HTML frame of iframe) of the loading
- * document accessible.
- *
- * XXX: in general AT expect events for document accessible loading into
- * tabbrowser, events from other document accessibles may break AT. We need to
- * figure out what AT wants to know about loading page (for example, some of
- * them have separate processing of iframe documents on the page and therefore
- * they need a way to distinguish sub documents from page document). Ideally
- * we should make events firing for any loaded document and provide additional
- * info AT are needing.
- */
- PRBool IsEventTargetDocument(nsIDocument *aDocument) const;
-
- /**
* Add 'pagehide' and 'DOMContentLoaded' event listeners.
*/
void AddListeners(nsIDocument *aDocument, PRBool aAddPageShowListener);
/**
* Create document or root accessible.
*/
nsDocAccessible *CreateDocOrRootAccessible(nsIDocument *aDocument);
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -100,17 +100,18 @@ static const PRUint32 kRelationAttrsLen
////////////////////////////////////////////////////////////////////////////////
// Constructor/desctructor
nsDocAccessible::
nsDocAccessible(nsIDocument *aDocument, nsIContent *aRootContent,
nsIWeakReference *aShell) :
nsHyperTextAccessibleWrap(aRootContent, aShell),
- mDocument(aDocument), mScrollPositionChangedTicks(0), mIsLoaded(PR_FALSE)
+ mDocument(aDocument), mScrollPositionChangedTicks(0),
+ mLoadState(eTreeConstructionPending), mLoadEventType(0)
{
mFlags |= eDocAccessible;
mDependentIDsHash.Init();
// XXX aaronl should we use an algorithm for the initial cache size?
mAccessibleCache.Init(kDefaultCacheSize);
mNodeToAccessibleMap.Init(kDefaultCacheSize);
@@ -304,21 +305,26 @@ nsDocAccessible::NativeState()
// XXX Need to invent better check to see if doc is focusable,
// which it should be if it is scrollable. A XUL document could be focusable.
// See bug 376803.
state |= states::FOCUSABLE;
if (gLastFocusedNode == mDocument)
state |= states::FOCUSED;
}
- // Expose state busy until the document is loaded or tree is constructed.
- if (!mIsLoaded || !mNotificationController->IsTreeConstructed()) {
- state |= states::BUSY | states::STALE;
- }
-
+ // Expose stale state until the document is ready (DOM is loaded and tree is
+ // constructed).
+ if (!HasLoadState(eReady))
+ state |= states::STALE;
+
+ // Expose state busy until the document and all its subdocuments is completely
+ // loaded.
+ if (!HasLoadState(eCompletelyLoaded))
+ state |= states::BUSY;
+
nsIFrame* frame = GetFrame();
if (!frame || !nsCoreUtils::CheckVisibilityInParentChain(frame)) {
state |= states::INVISIBLE | states::OFFSCREEN;
}
nsCOMPtr<nsIEditor> editor;
GetAssociatedEditor(getter_AddRefs(editor));
state |= editor ? states::EDITABLE : states::READONLY;
@@ -600,17 +606,17 @@ nsDocAccessible::Init()
mNotificationController = new NotificationController(this, shell);
if (!mNotificationController)
return PR_FALSE;
// Mark the document accessible as loaded if its DOM document was loaded at
// this point (this can happen because a11y is started late or DOM document
// having no container was loaded.
if (mDocument->GetReadyStateEnum() == nsIDocument::READYSTATE_COMPLETE)
- mIsLoaded = PR_TRUE;
+ mLoadState |= eDOMLoaded;
AddEventListeners();
return PR_TRUE;
}
void
nsDocAccessible::Shutdown()
{
@@ -1371,18 +1377,19 @@ nsDocAccessible::UnbindFromDocument(nsAc
mAccessibleCache.Remove(uniqueID);
}
void
nsDocAccessible::ContentInserted(nsIContent* aContainerNode,
nsIContent* aStartChildNode,
nsIContent* aEndChildNode)
{
- /// Pend tree update on content insertion until layout.
- if (mNotificationController) {
+ // Ignore content insertions until we constructed accessible tree. Otherwise
+ // schedule tree update on content insertion after layout.
+ if (mNotificationController && HasLoadState(eTreeConstructed)) {
// Update the whole tree of this document accessible when the container is
// null (document element is inserted or removed).
nsAccessible* container = aContainerNode ?
GetAccessibleOrContainer(aContainerNode) : this;
mNotificationController->ScheduleContentInsertion(container,
aStartChildNode,
aEndChildNode);
@@ -1462,18 +1469,46 @@ nsDocAccessible::CacheChildren()
nsAccessible* child = nsnull;
while ((child = walker.NextChild()) && AppendChild(child));
}
////////////////////////////////////////////////////////////////////////////////
// Protected members
void
-nsDocAccessible::NotifyOfInitialUpdate()
+nsDocAccessible::NotifyOfLoading(bool aIsReloading)
{
+ // Mark the document accessible as loading, if it stays alive then we'll mark
+ // it as loaded when we receive proper notification.
+ mLoadState &= ~eDOMLoaded;
+
+ if (!IsLoadEventTarget())
+ return;
+
+ if (aIsReloading) {
+ // Fire reload and state busy events on existing document accessible while
+ // event from user input flag can be calculated properly and accessible
+ // is alive. When new document gets loaded then this one is destroyed.
+ nsRefPtr<AccEvent> reloadEvent =
+ new AccEvent(nsIAccessibleEvent::EVENT_DOCUMENT_RELOAD, this);
+ nsEventShell::FireEvent(reloadEvent);
+ }
+
+ // 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, PR_TRUE);
+ FireDelayedAccessibleEvent(stateEvent);
+}
+
+void
+nsDocAccessible::DoInitialUpdate()
+{
+ mLoadState |= eTreeConstructed;
+
// The content element may be changed before the initial update and then we
// miss the notification (since content tree change notifications are ignored
// prior to initial update). Make sure the content element is valid.
nsIContent* contentElm = nsCoreUtils::GetRoleContent(mDocument);
if (contentElm && mContent != contentElm)
mContent = contentElm;
// Build initial tree.
@@ -1487,16 +1522,44 @@ nsDocAccessible::NotifyOfInitialUpdate()
nsRefPtr<AccEvent> reorderEvent =
new AccEvent(nsIAccessibleEvent::EVENT_REORDER, Parent(), eAutoDetect,
AccEvent::eCoalesceFromSameSubtree);
ParentDocument()->FireDelayedAccessibleEvent(reorderEvent);
}
}
void
+nsDocAccessible::ProcessLoad()
+{
+ mLoadState |= eCompletelyLoaded;
+
+ // Do not fire document complete/stop events for root chrome document
+ // accessibles and for frame/iframe documents because
+ // a) screen readers start working on focus event in the case of root chrome
+ // documents
+ // b) document load event on sub documents causes screen readers to act is if
+ // entire page is reloaded.
+ if (!IsLoadEventTarget())
+ return;
+
+ // Fire complete/load stopped if the load event type is given.
+ if (mLoadEventType) {
+ nsRefPtr<AccEvent> loadEvent = new AccEvent(mLoadEventType, this);
+ nsEventShell::FireEvent(loadEvent);
+
+ mLoadEventType = 0;
+ }
+
+ // Fire busy state change event.
+ nsRefPtr<AccEvent> stateEvent =
+ new AccStateChangeEvent(this, states::BUSY, PR_FALSE);
+ nsEventShell::FireEvent(stateEvent);
+}
+
+void
nsDocAccessible::AddDependentIDsFor(nsAccessible* aRelProvider,
nsIAtom* aRelAttr)
{
for (PRUint32 idx = 0; idx < kRelationAttrsLen; idx++) {
nsIAtom* relAttr = *kRelationAttrs[idx];
if (aRelAttr && aRelAttr != relAttr)
continue;
@@ -1959,8 +2022,35 @@ nsDocAccessible::ShutdownChildrenInSubtr
jdx++;
}
ShutdownChildrenInSubtree(child);
}
UnbindFromDocument(aAccessible);
}
+
+bool
+nsDocAccessible::IsLoadEventTarget() const
+{
+ nsCOMPtr<nsISupports> container = mDocument->GetContainer();
+ nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
+ do_QueryInterface(container);
+ NS_ASSERTION(docShellTreeItem, "No document shell for document!");
+
+ nsCOMPtr<nsIDocShellTreeItem> parentTreeItem;
+ docShellTreeItem->GetParent(getter_AddRefs(parentTreeItem));
+
+ // It's not a root document.
+ if (parentTreeItem) {
+ nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
+ docShellTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
+
+ // It's not a sub document, i.e. a frame or iframe.
+ return (sameTypeRoot == docShellTreeItem);
+ }
+
+ // It's not chrome root document.
+ PRInt32 contentType;
+ docShellTreeItem->GetItemType(&contentType);
+ return (contentType == nsIDocShellTreeItem::typeContent);
+}
+
--- a/accessible/src/base/nsDocAccessible.h
+++ b/accessible/src/base/nsDocAccessible.h
@@ -129,29 +129,44 @@ public:
// nsDocAccessible
/**
* Return true if associated DOM document was loaded and isn't unloading.
*/
PRBool IsContentLoaded() const
{
+ // eDOMLoaded flag check is used for error pages as workaround to make this
+ // method return correct result since error pages do not receive 'pageshow'
+ // event and as consequence nsIDocument::IsShowing() returns false.
return mDocument && mDocument->IsVisible() &&
- (mDocument->IsShowing() || mIsLoaded);
+ (mDocument->IsShowing() || HasLoadState(eDOMLoaded));
}
/**
- * Marks this document as loaded or loading, used to expose busy state.
- * The loaded flag has special meaning for error pages and used as workaround
- * to make IsContentLoaded() return correct result since these pages do not
- * receive pageshow event and as consequence nsIDocument::IsShowing() returns
- * false.
+ * Document load states.
*/
- void MarkAsLoaded() { mIsLoaded = PR_TRUE; }
- void MarkAsLoading() { mIsLoaded = PR_FALSE; }
+ enum LoadState {
+ // initial tree construction is pending
+ eTreeConstructionPending = 0,
+ // initial tree construction done
+ eTreeConstructed = 1,
+ // DOM document is loaded.
+ eDOMLoaded = 1 << 1,
+ // document is ready
+ eReady = eTreeConstructed | eDOMLoaded,
+ // document and all its subdocuments are ready
+ eCompletelyLoaded = eReady | 1 << 2
+ };
+
+ /**
+ * Return true if the document has given document state.
+ */
+ bool HasLoadState(LoadState aState) const
+ { return (mLoadState & aState) == aState; }
/**
* Return a native window handler or pointer depending on platform.
*/
virtual void* GetNativeWindow() const;
/**
* Return the parent document.
@@ -321,17 +336,18 @@ public:
/**
* Updates accessible tree when rendered text is changed.
*/
inline void UpdateText(nsIContent* aTextNode)
{
NS_ASSERTION(mNotificationController, "The document was shut down!");
- if (mNotificationController)
+ // Ignore the notification if initial tree construction hasn't been done yet.
+ if (mNotificationController && HasLoadState(eTreeConstructed))
mNotificationController->ScheduleTextUpdate(aTextNode);
}
/**
* Recreate an accessible, results in hide/show events pair.
*/
void RecreateAccessible(nsIContent* aContent);
@@ -341,20 +357,39 @@ protected:
virtual void CacheChildren();
// nsDocAccessible
virtual void GetBoundsRect(nsRect& aRect, nsIFrame** aRelativeFrame);
virtual nsresult AddEventListeners();
virtual nsresult RemoveEventListeners();
/**
- * Notify this document that was bound to the accessible document tree.
+ * Marks this document as loaded or loading.
+ */
+ inline void NotifyOfLoad(PRUint32 aLoadEventType)
+ {
+ mLoadState |= eDOMLoaded;
+ mLoadEventType = aLoadEventType;
+ }
+
+ void NotifyOfLoading(bool aIsReloading);
+
+ friend class nsAccDocManager;
+
+ /**
+ * Perform initial update (create accessible tree).
* Can be overridden by wrappers to prepare initialization work.
*/
- virtual void NotifyOfInitialUpdate();
+ virtual void DoInitialUpdate();
+
+ /**
+ * Process document load notification, fire document load and state busy
+ * events if applicable.
+ */
+ void ProcessLoad();
void AddScrollListener();
void RemoveScrollListener();
/**
* Append the given document accessible to this document's child document
* accessibles.
*/
@@ -479,40 +514,63 @@ protected:
* Shutdown any cached accessible in the subtree.
*
* @param aAccessible [in] the root of the subrtee to invalidate accessible
* child/parent refs in
*/
void ShutdownChildrenInSubtree(nsAccessible *aAccessible);
/**
+ * Return true if accessibility events accompanying document accessible
+ * loading should be fired.
+ *
+ * The rules are: do not fire events for root chrome document accessibles and
+ * for sub document accessibles (like HTML frame of iframe) of the loading
+ * document accessible.
+ *
+ * XXX: in general AT expect events for document accessible loading into
+ * tabbrowser, events from other document accessibles may break AT. We need to
+ * figure out what AT wants to know about loading page (for example, some of
+ * them have separate processing of iframe documents on the page and therefore
+ * they need a way to distinguish sub documents from page document). Ideally
+ * we should make events firing for any loaded document and provide additional
+ * info AT are needing.
+ */
+ bool IsLoadEventTarget() const;
+
+ /**
* Used to fire scrolling end event after page scroll.
*
* @param aTimer [in] the timer object
* @param aClosure [in] the document accessible where scrolling happens
*/
static void ScrollTimerCallback(nsITimer* aTimer, void* aClosure);
+protected:
+
/**
* Cache of accessibles within this document accessible.
*/
nsAccessibleHashtable mAccessibleCache;
nsDataHashtable<nsPtrHashKey<const nsINode>, nsAccessible*>
mNodeToAccessibleMap;
nsCOMPtr<nsIDocument> mDocument;
nsCOMPtr<nsITimer> mScrollWatchTimer;
PRUint16 mScrollPositionChangedTicks; // Used for tracking scroll events
-protected:
+ /**
+ * Bit mask of document load states (@see LoadState).
+ */
+ PRUint32 mLoadState;
/**
- * Specifies if the document was loaded, used for error pages only.
+ * Type of document load event fired after the document is loaded completely.
*/
- PRPackedBool mIsLoaded;
+ PRUint32 mLoadEventType;
static PRUint64 gLastFocusedAccessiblesState;
nsTArray<nsRefPtr<nsDocAccessible> > mChildDocuments;
/**
* A storage class for pairing content with one of its relation attributes.
*/
--- a/accessible/src/base/nsRootAccessible.h
+++ b/accessible/src/base/nsRootAccessible.h
@@ -44,18 +44,17 @@
#include "nsIAccessibleDocument.h"
#ifdef MOZ_XUL
#include "nsXULTreeAccessible.h"
#endif
#include "nsHashtable.h"
#include "nsCaretAccessible.h"
#include "nsIDocument.h"
-#include "nsIDOMFocusListener.h"
-#include "nsIDOMFormListener.h"
+#include "nsIDOMEventListener.h"
#define NS_ROOTACCESSIBLE_IMPL_CID \
{ /* eaba2cf0-21b1-4e2b-b711-d3a89dcd5e1a */ \
0xeaba2cf0, \
0x21b1, \
0x4e2b, \
{ 0xb7, 0x11, 0xd3, 0xa8, 0x9d, 0xcd, 0x5e, 0x1a } \
}
--- a/accessible/src/msaa/nsDocAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsDocAccessibleWrap.cpp
@@ -263,19 +263,19 @@ nsDocAccessibleWrap::GetNativeWindow() c
{
return mHWND ? mHWND : nsDocAccessible::GetNativeWindow();
}
////////////////////////////////////////////////////////////////////////////////
// nsDocAccessible protected
void
-nsDocAccessibleWrap::NotifyOfInitialUpdate()
+nsDocAccessibleWrap::DoInitialUpdate()
{
- nsDocAccessible::NotifyOfInitialUpdate();
+ nsDocAccessible::DoInitialUpdate();
if (nsWinUtils::IsWindowEmulationStarted()) {
// Create window for tab document.
if (nsCoreUtils::IsTabDocument(mDocument)) {
mozilla::dom::TabChild* tabChild =
mozilla::dom::GetTabChildFrom(mDocument->GetShell());
nsRootAccessible* rootDocument = RootAccessible();
--- a/accessible/src/msaa/nsDocAccessibleWrap.h
+++ b/accessible/src/msaa/nsDocAccessibleWrap.h
@@ -92,15 +92,15 @@ public:
// nsAccessNode
virtual void Shutdown();
// nsDocAccessible
virtual void* GetNativeWindow() const;
protected:
// nsDocAccessible
- virtual void NotifyOfInitialUpdate();
+ virtual void DoInitialUpdate();
protected:
void* mHWND;
};
#endif
--- a/accessible/tests/mochitest/relations/test_tabbrowser.xul
+++ b/accessible/tests/mochitest/relations/test_tabbrowser.xul
@@ -60,17 +60,17 @@
var target = aEvent.accessible;
if (target.role == ROLE_INTERNAL_FRAME &&
target.parent.parent == getAccessible(this.tabBrowser.mTabBox.tabpanels)) {
this.reorderCnt++;
}
if (this.reorderCnt == docURIs.length) {
unregisterA11yEventListener(EVENT_REORDER, this);
- testAccTree();
+ testRelations();
}
},
tabBrowser: tabBrowser,
reorderCnt: 0
};
registerA11yEventListener(EVENT_REORDER, handler);
--- a/browser/base/content/browser-context.inc
+++ b/browser/base/content/browser-context.inc
@@ -31,16 +31,17 @@
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
+ <menuseparator id="page-menu-separator"/>
<menuitem id="spell-no-suggestions"
disabled="true"
label="&spellNoSuggestions.label;"/>
<menuitem id="spell-add-to-dictionary"
label="&spellAddToDictionary.label;"
accesskey="&spellAddToDictionary.accesskey;"
oncommand="InlineSpellCheckerUI.addToDictionary();"/>
<menuseparator id="spell-suggestions-separator"/>
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -211,16 +211,22 @@ XPCOMUtils.defineLazyGetter(this, "Win7F
});
#ifdef MOZ_CRASHREPORTER
XPCOMUtils.defineLazyServiceGetter(this, "gCrashReporter",
"@mozilla.org/xre/app-info;1",
"nsICrashReporter");
#endif
+XPCOMUtils.defineLazyGetter(this, "PageMenu", function() {
+ let tmp = {};
+ Cu.import("resource://gre/modules/PageMenu.jsm", tmp);
+ return new tmp.PageMenu();
+});
+
/**
* We can avoid adding multiple load event listeners and save some time by adding
* one listener that calls all real handlers.
*/
function pageShowEventHandlers(event) {
// Filter out events that are not about the document load we are interested in
if (event.originalTarget == content.document) {
charsetLoadListener(event);
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -268,20 +268,20 @@
accesskey="&fullScreenAutohide.accesskey;"
oncommand="FullScreen.setAutohide();"/>
<menuseparator/>
<menuitem label="&fullScreenExit.label;"
accesskey="&fullScreenExit.accesskey;"
oncommand="BrowserFullScreen();"/>
</menupopup>
- <menupopup id="contentAreaContextMenu"
+ <menupopup id="contentAreaContextMenu" pagemenu="start"
onpopupshowing="if (event.target != this)
return true;
- gContextMenu = new nsContextMenu(this, gBrowser);
+ gContextMenu = new nsContextMenu(this, gBrowser, event.shiftKey);
if (gContextMenu.shouldDisplay)
updateEditUIVisibility();
return gContextMenu.shouldDisplay;"
onpopuphiding="if (event.target == this) { gContextMenu = null; updateEditUIVisibility(); }">
#include browser-context.inc
</menupopup>
<menupopup id="placesContext"/>
@@ -1004,17 +1004,17 @@
<svg:circle cx="-0.35" cy="0.5" r="0.58"/>
</svg:mask>
</svg:svg>
#endif
#ifdef XP_MACOSX
<svg:svg height="0">
<svg:mask id="pinstripe-keyhole-forward-mask" maskContentUnits="objectBoundingBox">
<svg:rect x="0" y="0" width="1" height="1" fill="white"/>
- <svg:circle cx="-0.46" cy="0.48" r="0.65"/>
+ <svg:circle cx="-0.41" cy="0.5" r="0.65"/>
</svg:mask>
<svg:mask id="pinstripe-tab-ontop-left-curve-mask" maskContentUnits="userSpaceOnUse">
<svg:circle cx="9" cy="3" r="3" fill="white"/>
<svg:rect x="9" y="0" width="3" height="3" fill="white"/>
<svg:rect x="6" y="3" width="6" height="19" fill="white"/>
<svg:rect x="1" y="17" width="5" height="5" fill="white"/>
<svg:circle cx="1" cy="17" r="5"/>
<svg:rect x="0" y="22" width="12" height="1" fill="white"/>
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -56,55 +56,66 @@
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
-function nsContextMenu(aXulMenu, aBrowser) {
+function nsContextMenu(aXulMenu, aBrowser, aIsShift) {
this.shouldDisplay = true;
- this.initMenu(aBrowser);
+ this.initMenu(aBrowser, aXulMenu, aIsShift);
}
// Prototype for nsContextMenu "class."
nsContextMenu.prototype = {
- initMenu: function CM_initMenu(aBrowser) {
+ initMenu: function CM_initMenu(aBrowser, aXulMenu, aIsShift) {
// Get contextual info.
this.setTarget(document.popupNode, document.popupRangeParent,
document.popupRangeOffset);
if (!this.shouldDisplay)
return;
this.browser = aBrowser;
+
+ this.hasPageMenu = false;
+ if (!aIsShift) {
+ this.hasPageMenu = PageMenu.init(this.target, aXulMenu);
+ }
+
this.isFrameImage = document.getElementById("isFrameImage");
this.ellipsis = "\u2026";
try {
this.ellipsis = gPrefService.getComplexValue("intl.ellipsis",
Ci.nsIPrefLocalizedString).data;
} catch (e) { }
this.isTextSelected = this.isTextSelection();
this.isContentSelected = this.isContentSelection();
// Initialize (disable/remove) menu items.
this.initItems();
},
initItems: function CM_initItems() {
+ this.initPageMenuSeparator();
this.initOpenItems();
this.initNavigationItems();
this.initViewItems();
this.initMiscItems();
this.initSpellingItems();
this.initSaveItems();
this.initClipboardItems();
this.initMediaPlayerItems();
},
+ initPageMenuSeparator: function CM_initPageMenuSeparator() {
+ this.showItem("page-menu-separator", this.hasPageMenu);
+ },
+
initOpenItems: function CM_initOpenItems() {
var isMailtoInternal = false;
if (this.onMailtoLink) {
var mailtoHandler = Cc["@mozilla.org/uriloader/external-protocol-service;1"].
getService(Ci.nsIExternalProtocolService).
getProtocolHandlerInfo("mailto");
isMailtoInternal = (!mailtoHandler.alwaysAskBeforeHandling &&
mailtoHandler.preferredAction == Ci.nsIHandlerInfo.useHelperApp &&
--- a/browser/base/content/test/subtst_contextmenu.html
+++ b/browser/base/content/test/subtst_contextmenu.html
@@ -16,11 +16,45 @@ Browser context menu subtest.
<video id="test-video-bad" src="bogus.duh" width="100" height="100" style="background-color: orange"></video>
<video id="test-video-bad2" width="100" height="100" style="background-color: yellow">
<source src="bogus.duh" type="video/durrrr;">
</video>
<iframe id="test-iframe" width="98" height="98" style="border: 1px solid black"></iframe>
<textarea id="test-textarea">chssseesbbbie</textarea> <!-- a weird word which generates only one suggestion -->
<div id="test-contenteditable" contenteditable="true">chssseefsbbbie</div> <!-- a more weird word which generates no suggestions -->
<input id="test-input-spellcheck" type="text" spellcheck="true" autofocus value="prodkjfgigrty"> <!-- this one also generates one suggestion -->
+<div contextmenu="myMenu">
+ <p id="test-pagemenu" hopeless="true">I've got a context menu!</p>
+ <menu id="myMenu" type="context">
+ <menuitem label="Plain item" onclick="document.getElementById('test-pagemenu').removeAttribute('hopeless');"></menuitem>
+ <menuitem label="Disabled item" disabled></menuitem>
+ <menu>
+ <menuitem type="checkbox" label="Checkbox" checked></menuitem>
+ </menu>
+ <menu>
+ <menuitem type="radio" label="Radio1" checked></menuitem>
+ <menuitem type="radio" label="Radio2"></menuitem>
+ <menuitem type="radio" label="Radio3"></menuitem>
+ </menu>
+ <menu>
+ <menuitem label="Item w/ icon" icon="favicon.ico"></menuitem>
+ <menuitem label="Item w/ bad icon" icon="data://www.mozilla.org/favicon.ico"></menuitem>
+ </menu>
+ <menu label="Submenu">
+ <menuitem type="radio" label="Radio1" radiogroup="rg"></menuitem>
+ <menuitem type="radio" label="Radio2" checked radiogroup="rg"></menuitem>
+ <menuitem type="radio" label="Radio3" radiogroup="rg"></menuitem>
+ <menu>
+ <menuitem type="checkbox" label="Checkbox"></menuitem>
+ </menu>
+ </menu>
+ <menu hidden>
+ <menuitem label="Bogus item"></menuitem>
+ </menu>
+ <menu>
+ </menu>
+ <menuitem label="Hidden item" hidden></menuitem>
+ <menuitem></menuitem>
+ </menu>
+</div>
</body>
</html>
--- a/browser/base/content/test/test_contextmenu.html
+++ b/browser/base/content/test/test_contextmenu.html
@@ -19,21 +19,21 @@ Browser context menu tests.
/** Test for Login Manager: multiple login autocomplete. **/
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
const Cc = Components.classes;
const Ci = Components.interfaces;
-function openContextMenuFor(element) {
+function openContextMenuFor(element, shiftkey) {
// Context menu should be closed before we open it again.
is(contextMenu.state, "closed", "checking if popup is closed");
- var eventDetails = { type : "contextmenu", button : 2 };
+ var eventDetails = { type : "contextmenu", button : 2, shiftKey : shiftkey };
synthesizeMouse(element, 2, 2, eventDetails, element.ownerDocument.defaultView);
}
function closeContextMenu() {
contextMenu.hidePopup();
}
function executeCopyCommand(command, expectedValue)
@@ -45,113 +45,171 @@ function executeCopyCommand(command, exp
// The easiest way to check the clipboard is to paste the contents into a
// textbox
input.focus();
input.value = "";
input.controllers.getControllerForCommand("cmd_paste").doCommand("cmd_paste");
is(input.value, expectedValue, "paste for command " + command);
}
-function getVisibleMenuItems(aMenu) {
+function invokeItemAction(ident)
+{
+ var item = contextMenu.getElementsByAttribute("ident", ident)[0];
+ ok(item, "Got generated XUL menu item");
+ item.doCommand();
+ is(pagemenu.hasAttribute("hopeless"), false, "attribute got removed");
+}
+
+function getVisibleMenuItems(aMenu, aData) {
var items = [];
var accessKeys = {};
for (var i = 0; i < aMenu.childNodes.length; i++) {
var item = aMenu.childNodes[i];
if (item.hidden)
continue;
var key = item.accessKey;
if (key)
key = key.toLowerCase();
+ var isGenerated = item.hasAttribute("generated");
+
if (item.nodeName == "menuitem") {
var isSpellSuggestion = item.className == "spell-suggestion";
if (isSpellSuggestion) {
is(item.id, "", "child menuitem #" + i + " is a spelling suggestion");
+ } else if (isGenerated) {
+ is(item.id, "", "child menuitem #" + i + " is a generated item");
} else {
ok(item.id, "child menuitem #" + i + " has an ID");
}
var label = item.getAttribute("label");
ok(label.length, "menuitem " + item.id + " has a label");
if (isSpellSuggestion) {
is(key, "", "Spell suggestions shouldn't have an access key");
items.push("*" + label);
+ } else if (isGenerated) {
+ items.push("+" + label);
} else if (item.id.indexOf("spell-check-dictionary-") != 0 &&
item.id != "spell-no-suggestions") {
ok(key, "menuitem " + item.id + " has an access key");
if (accessKeys[key])
ok(false, "menuitem " + item.id + " has same accesskey as " + accessKeys[key]);
else
accessKeys[key] = item.id;
}
- if (!isSpellSuggestion) {
+ if (!isSpellSuggestion && !isGenerated) {
items.push(item.id);
}
- items.push(!item.disabled);
+ if (isGenerated) {
+ var p = {};
+ p.type = item.getAttribute("type");
+ p.icon = item.getAttribute("image");
+ p.checked = item.hasAttribute("checked");
+ p.disabled = item.hasAttribute("disabled");
+ items.push(p);
+ } else {
+ items.push(!item.disabled);
+ }
} else if (item.nodeName == "menuseparator") {
ok(true, "--- seperator id is " + item.id);
items.push("---");
items.push(null);
} else if (item.nodeName == "menu") {
+ if (isGenerated) {
+ item.id = "generated-submenu-" + aData.generatedSubmenuId++;
+ }
ok(item.id, "child menu #" + i + " has an ID");
- ok(key, "menu has an access key");
- if (accessKeys[key])
- ok(false, "menu " + item.id + " has same accesskey as " + accessKeys[key]);
- else
- accessKeys[key] = item.id;
+ if (!isGenerated) {
+ ok(key, "menu has an access key");
+ if (accessKeys[key])
+ ok(false, "menu " + item.id + " has same accesskey as " + accessKeys[key]);
+ else
+ accessKeys[key] = item.id;
+ }
items.push(item.id);
items.push(!item.disabled);
// Add a dummy item to that the indexes in checkMenu are the same
// for expectedItems and actualItems.
items.push([]);
items.push(null);
} else {
ok(false, "child #" + i + " of menu ID " + aMenu.id +
" has an unknown type (" + item.nodeName + ")");
}
}
return items;
}
function checkContextMenu(expectedItems) {
is(contextMenu.state, "open", "checking if popup is open");
- checkMenu(contextMenu, expectedItems);
+ var data = { generatedSubmenuId: 1 };
+ checkMenu(contextMenu, expectedItems, data);
}
/*
* checkMenu - checks to see if the specified <menupopup> contains the
* expected items and state.
* expectedItems is a array of (1) item IDs and (2) a boolean specifying if
* the item is enabled or not (or null to ignore it). Submenus can be checked
* by providing a nested array entry after the expected <menu> ID.
* For example: ["blah", true, // item enabled
* "submenu", null, // submenu
* ["sub1", true, // submenu contents
* "sub2", false], null, // submenu contents
* "lol", false] // item disabled
*
*/
-function checkMenu(menu, expectedItems) {
- var actualItems = getVisibleMenuItems(menu);
+function checkMenu(menu, expectedItems, data) {
+ var actualItems = getVisibleMenuItems(menu, data);
//ok(false, "Items are: " + actualItems);
for (var i = 0; i < expectedItems.length; i+=2) {
var actualItem = actualItems[i];
var actualEnabled = actualItems[i + 1];
var expectedItem = expectedItems[i];
var expectedEnabled = expectedItems[i + 1];
if (expectedItem instanceof Array) {
ok(true, "Checking submenu...");
var menuID = expectedItems[i - 2]; // The last item was the menu ID.
var submenu = menu.getElementsByAttribute("id", menuID)[0];
ok(submenu && submenu.nodeName == "menu", "got expected submenu element");
- checkMenu(submenu.menupopup, expectedItem);
+ checkMenu(submenu.menupopup, expectedItem, data);
} else {
is(actualItem, expectedItem,
"checking item #" + i/2 + " (" + expectedItem + ") name");
- if (expectedEnabled != null)
+
+ if (typeof expectedEnabled == "object" && expectedEnabled != null ||
+ typeof actualEnabled == "object" && actualEnabled != null) {
+
+ ok(!(actualEnabled == null), "actualEnabled is not null");
+ ok(!(expectedEnabled == null), "expectedEnabled is not null");
+ is(typeof actualEnabled, typeof expectedEnabled, "checking types");
+
+ if (typeof actualEnabled != typeof expectedEnabled ||
+ actualEnabled == null || expectedEnabled == null)
+ continue;
+
+ is(actualEnabled.type, expectedEnabled.type,
+ "checking item #" + i/2 + " (" + expectedItem + ") type attr value");
+ var icon = actualEnabled.icon;
+ if (icon) {
+ var tmp = "";
+ var j = icon.length - 1;
+ while (j && icon[j] != "/") {
+ tmp = icon[j--] + tmp;
+ }
+ icon = tmp;
+ }
+ is(icon, expectedEnabled.icon,
+ "checking item #" + i/2 + " (" + expectedItem + ") icon attr value");
+ is(actualEnabled.checked, expectedEnabled.checked,
+ "checking item #" + i/2 + " (" + expectedItem + ") has checked attr");
+ is(actualEnabled.disabled, expectedEnabled.disabled,
+ "checking item #" + i/2 + " (" + expectedItem + ") has disabled attr");
+ } else if (expectedEnabled != null)
is(actualEnabled, expectedEnabled,
"checking item #" + i/2 + " (" + expectedItem + ") enabled state");
}
}
// Could find unexpected extra items at the end...
is(actualItems.length, expectedItems.length, "checking expected number of menu entries");
}
@@ -403,19 +461,80 @@ function runTest(testNum) {
["spell-check-dictionary-en-US", true,
"---", null,
"spell-add-dictionaries", true], null]);
closeContextMenu();
openContextMenuFor(link); // Invoke context menu for next test.
break;
- case 15:
+ case 15:
executeCopyCommand("cmd_copyLink", "http://mozilla.com/");
closeContextMenu();
+ openContextMenuFor(pagemenu); // Invoke context menu for next test.
+ break;
+
+ case 16:
+ // Context menu for element with assigned content context menu
+ checkContextMenu(["+Plain item", {type: "", icon: "", checked: false, disabled: false},
+ "+Disabled item", {type: "", icon: "", checked: false, disabled: true},
+ "---", null,
+ "+Checkbox", {type: "checkbox", icon: "", checked: true, disabled: false},
+ "---", null,
+ "+Radio1", {type: "checkbox", icon: "", checked: true, disabled: false},
+ "+Radio2", {type: "checkbox", icon: "", checked: false, disabled: false},
+ "+Radio3", {type: "checkbox", icon: "", checked: false, disabled: false},
+ "---", null,
+ "+Item w/ icon", {type: "", icon: "favicon.ico", checked: false, disabled: false},
+ "+Item w/ bad icon", {type: "", icon: "", checked: false, disabled: false},
+ "---", null,
+ "generated-submenu-1", true,
+ ["+Radio1", {type: "checkbox", icon: "", checked: false, disabled: false},
+ "+Radio2", {type: "checkbox", icon: "", checked: true, disabled: false},
+ "+Radio3", {type: "checkbox", icon: "", checked: false, disabled: false},
+ "---", null,
+ "+Checkbox", {type: "checkbox", icon: "", checked: false, disabled: false}], null,
+ "---", null,
+ "context-back", false,
+ "context-forward", false,
+ "context-reload", true,
+ "context-stop", false,
+ "---", null,
+ "context-bookmarkpage", true,
+ "context-savepage", true,
+ "context-sendpage", true,
+ "---", null,
+ "context-viewbgimage", false,
+ "context-selectall", true,
+ "---", null,
+ "context-viewsource", true,
+ "context-viewinfo", true]);
+
+ invokeItemAction("0");
+ closeContextMenu();
+ openContextMenuFor(pagemenu, true); // Invoke context menu for next test.
+ break;
+
+ case 17:
+ // Context menu for element with assigned content context menu
+ // The shift key should bypass content context menu processing
+ checkContextMenu(["context-back", false,
+ "context-forward", false,
+ "context-reload", true,
+ "context-stop", false,
+ "---", null,
+ "context-bookmarkpage", true,
+ "context-savepage", true,
+ "context-sendpage", true,
+ "---", null,
+ "context-viewbgimage", false,
+ "context-selectall", true,
+ "---", null,
+ "context-viewsource", true,
+ "context-viewinfo", true]);
subwindow.close();
SimpleTest.finish();
return;
/*
* Other things that would be nice to test:
* - selected text
@@ -432,17 +551,17 @@ function runTest(testNum) {
}
}
var testNum = 1;
var subwindow, chromeWin, contextMenu;
var text, link, mailto, input, img, canvas, video_ok, video_bad, video_bad2,
- iframe, textarea, contenteditable, inputspell;
+ iframe, textarea, contenteditable, inputspell, pagemenu;
function startTest() {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
chromeWin = subwindow
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.rootTreeItem
@@ -465,16 +584,17 @@ function startTest() {
canvas = subwindow.document.getElementById("test-canvas");
video_ok = subwindow.document.getElementById("test-video-ok");
video_bad = subwindow.document.getElementById("test-video-bad");
video_bad2 = subwindow.document.getElementById("test-video-bad2");
iframe = subwindow.document.getElementById("test-iframe");
textarea = subwindow.document.getElementById("test-textarea");
contenteditable = subwindow.document.getElementById("test-contenteditable");
inputspell = subwindow.document.getElementById("test-input-spellcheck");
+ pagemenu = subwindow.document.getElementById("test-pagemenu");
contextMenu.addEventListener("popupshown", function() { runTest(++testNum); }, false);
runTest(1);
}
// We open this in a separate window, because the Mochitests run inside a frame.
// The frame causes an extra menu item, and prevents running the test
// standalone (ie, clicking the test name in the Mochitest window) to see
--- a/browser/base/content/web-panels.xul
+++ b/browser/base/content/web-panels.xul
@@ -75,20 +75,20 @@
oncommand="getPanelBrowser().webNavigation.goForward();"
disabled="true"/>
<command id="Browser:Stop" oncommand="PanelBrowserStop();"/>
<command id="Browser:Reload" oncommand="PanelBrowserReload();"/>
</commandset>
<popupset id="mainPopupSet">
<tooltip id="aHTMLTooltip" onpopupshowing="return FillInHTMLTooltip(document.tooltipNode);"/>
- <menupopup id="contentAreaContextMenu"
+ <menupopup id="contentAreaContextMenu" pagemenu="start"
onpopupshowing="if (event.target != this)
return true;
- gContextMenu = new nsContextMenu(this, getPanelBrowser());
+ gContextMenu = new nsContextMenu(this, getPanelBrowser(), event.shiftKey);
if (gContextMenu.shouldDisplay)
document.popupNode = this.triggerNode;
return gContextMenu.shouldDisplay;"
onpopuphiding="if (event.target == this)
gContextMenu = null;">
#include browser-context.inc
</menupopup>
</popupset>
--- a/browser/components/migration/src/nsSeamonkeyProfileMigrator.cpp
+++ b/browser/components/migration/src/nsSeamonkeyProfileMigrator.cpp
@@ -56,17 +56,16 @@
#define FILE_NAME_BOOKMARKS NS_LITERAL_STRING("bookmarks.html")
#define FILE_NAME_COOKIES NS_LITERAL_STRING("cookies.txt")
#define FILE_NAME_SITEPERM_OLD NS_LITERAL_STRING("cookperm.txt")
#define FILE_NAME_SITEPERM_NEW NS_LITERAL_STRING("hostperm.1")
#define FILE_NAME_CERT8DB NS_LITERAL_STRING("cert8.db")
#define FILE_NAME_KEY3DB NS_LITERAL_STRING("key3.db")
#define FILE_NAME_SECMODDB NS_LITERAL_STRING("secmod.db")
-#define FILE_NAME_HISTORY NS_LITERAL_STRING("history.dat")
#define FILE_NAME_MIMETYPES NS_LITERAL_STRING("mimeTypes.rdf")
#define FILE_NAME_DOWNLOADS NS_LITERAL_STRING("downloads.rdf")
#define FILE_NAME_PREFS NS_LITERAL_STRING("prefs.js")
#define FILE_NAME_USER_PREFS NS_LITERAL_STRING("user.js")
#define FILE_NAME_USERCONTENT NS_LITERAL_STRING("userContent.css")
#define DIR_NAME_CHROME NS_LITERAL_STRING("chrome")
NS_IMPL_ISUPPORTS1(nsSeamonkeyProfileMigrator, nsIBrowserProfileMigrator)
@@ -95,17 +94,16 @@ nsSeamonkeyProfileMigrator::Migrate(PRUi
}
if (!mSourceProfile)
GetSourceProfile(aProfile);
NOTIFY_OBSERVERS(MIGRATION_STARTED, nsnull);
COPY_DATA(CopyPreferences, aReplace, nsIBrowserProfileMigrator::SETTINGS);
COPY_DATA(CopyCookies, aReplace, nsIBrowserProfileMigrator::COOKIES);
- COPY_DATA(CopyHistory, aReplace, nsIBrowserProfileMigrator::HISTORY);
COPY_DATA(CopyPasswords, aReplace, nsIBrowserProfileMigrator::PASSWORDS);
COPY_DATA(CopyOtherData, aReplace, nsIBrowserProfileMigrator::OTHERDATA);
// Need to do startup before trying to copy bookmarks, since bookmarks
// import requires a profile. Can't do it earlier because services might
// end up creating the files we try to copy above.
if (aStartup) {
rv = aStartup->DoStartup();
@@ -146,19 +144,16 @@ nsSeamonkeyProfileMigrator::GetMigrateDa
nsIBrowserProfileMigrator::SETTINGS,
PR_TRUE },
{ ToNewUnicode(FILE_NAME_USER_PREFS),
nsIBrowserProfileMigrator::SETTINGS,
PR_TRUE },
{ ToNewUnicode(FILE_NAME_COOKIES),
nsIBrowserProfileMigrator::COOKIES,
PR_FALSE },
- { ToNewUnicode(FILE_NAME_HISTORY),
- nsIBrowserProfileMigrator::HISTORY,
- PR_TRUE },
{ ToNewUnicode(FILE_NAME_BOOKMARKS),
nsIBrowserProfileMigrator::BOOKMARKS,
PR_FALSE },
{ ToNewUnicode(FILE_NAME_DOWNLOADS),
nsIBrowserProfileMigrator::OTHERDATA,
PR_TRUE },
{ ToNewUnicode(FILE_NAME_MIMETYPES),
nsIBrowserProfileMigrator::OTHERDATA,
@@ -639,22 +634,16 @@ nsSeamonkeyProfileMigrator::CopyCookies(
seamonkeyCookiesFile->Append(FILE_NAME_COOKIES);
rv = ImportNetscapeCookies(seamonkeyCookiesFile);
}
return rv;
}
nsresult
-nsSeamonkeyProfileMigrator::CopyHistory(PRBool aReplace)
-{
- return aReplace ? CopyFile(FILE_NAME_HISTORY, FILE_NAME_HISTORY) : NS_OK;
-}
-
-nsresult
nsSeamonkeyProfileMigrator::CopyPasswords(PRBool aReplace)
{
nsresult rv;
nsCString signonsFileName;
GetSignonFileName(aReplace, getter_Copies(signonsFileName));
if (signonsFileName.IsEmpty())
--- a/browser/components/migration/src/nsSeamonkeyProfileMigrator.h
+++ b/browser/components/migration/src/nsSeamonkeyProfileMigrator.h
@@ -86,17 +86,16 @@ protected:
void ReadFontsBranch(nsIPrefService* aPrefService,
nsTArray<FontPref>* aPrefs);
void WriteFontsBranch(nsIPrefService* aPrefService,
nsTArray<FontPref>* aPrefs);
nsresult CopyUserContentSheet();
nsresult CopyCookies(PRBool aReplace);
- nsresult CopyHistory(PRBool aReplace);
nsresult CopyPasswords(PRBool aReplace);
nsresult LocateSignonsFile(char** aResult);
nsresult CopyBookmarks(PRBool aReplace);
nsresult CopyOtherData(PRBool aReplace);
private:
nsCOMPtr<nsISupportsArray> mProfileNames;
nsCOMPtr<nsISupportsArray> mProfileLocations;
--- a/browser/components/privatebrowsing/test/unit/head_privatebrowsing.js
+++ b/browser/components/privatebrowsing/test/unit/head_privatebrowsing.js
@@ -42,17 +42,16 @@ const Cu = Components.utils;
const kPrivateBrowsingNotification = "private-browsing";
const kPrivateBrowsingCancelVoteNotification = "private-browsing-cancel-vote";
const kPrivateBrowsingTransitionCompleteNotification = "private-browsing-transition-complete";
const kEnter = "enter";
const kExit = "exit";
const NS_APP_USER_PROFILE_50_DIR = "ProfD";
-const NS_APP_HISTORY_50_FILE = "UHist";
function LOG(aMsg) {
aMsg = ("*** PRIVATEBROWSING TESTS: " + aMsg);
Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService).
logStringMessage(aMsg);
print(aMsg);
}
@@ -60,36 +59,16 @@ function uri(spec) {
return Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService).
newURI(spec, null, null);
}
var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
var profileDir = do_get_profile();
-var provider = {
- getFile: function(prop, persistent) {
- persistent.value = true;
- if (prop == NS_APP_HISTORY_50_FILE) {
- var histFile = profileDir.clone();
- histFile.append("history.dat");
- return histFile;
- }
- throw Cr.NS_ERROR_FAILURE;
- },
- QueryInterface: function(iid) {
- if (iid.equals(Ci.nsIDirectoryServiceProvider) ||
- iid.equals(Ci.nsISupports)) {
- return this;
- }
- throw Cr.NS_ERROR_NO_INTERFACE;
- }
-};
-dirSvc.QueryInterface(Ci.nsIDirectoryService).registerProvider(provider);
-
// Do not attempt to restore any session since we don't have any windows
Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch).
setBoolPref("browser.privatebrowsing.keep_current_session", true);
/**
* Removes any files that could make our tests fail.
*/
--- a/browser/components/sessionstore/src/nsSessionStore.js
+++ b/browser/components/sessionstore/src/nsSessionStore.js
@@ -1867,19 +1867,17 @@ SessionStoreService.prototype = {
// We can stop doing base64 encoding once our serialization into JSON
// is guaranteed to handle all chars in strings, including embedded
// nulls.
entry.owner_b64 = btoa(String.fromCharCode.apply(null, ownerBytes));
}
catch (ex) { debug(ex); }
}
- if (aEntry.docIdentifier) {
- entry.docIdentifier = aEntry.docIdentifier;
- }
+ entry.docIdentifier = aEntry.BFCacheEntry.ID;
if (aEntry.stateData != null) {
entry.structuredCloneState = aEntry.stateData.getDataAsBase64();
entry.structuredCloneVersion = aEntry.stateData.formatVersion;
}
if (!(aEntry instanceof Ci.nsISHContainer)) {
return entry;
@@ -2977,17 +2975,16 @@ SessionStoreService.prototype = {
getEntryAtIndex(activeIndex, false).
QueryInterface(Ci.nsISHEntry);
// restore those aspects of the currently active documents which are not
// preserved in the plain history entries (mainly scroll state and text data)
browser.__SS_restore_data = tabData.entries[activeIndex] || {};
browser.__SS_restore_pageStyle = tabData.pageStyle || "";
browser.__SS_restore_tab = aTab;
- browser.__SS_restore_docIdentifier = curSHEntry.docIdentifier;
didStartLoad = true;
try {
// In order to work around certain issues in session history, we need to
// force session history to update its internal index and call reload
// instead of gotoIndex. See bug 597315.
browser.webNavigation.sessionHistory.getEntryAtIndex(activeIndex, true);
browser.webNavigation.sessionHistory.reloadCurrentEntry();
@@ -3130,34 +3127,26 @@ SessionStoreService.prototype = {
var postdata = atob(aEntry.postdata_b64);
var stream = Cc["@mozilla.org/io/string-input-stream;1"].
createInstance(Ci.nsIStringInputStream);
stream.setData(postdata, postdata.length);
shEntry.postData = stream;
}
if (aEntry.docIdentifier) {
- // Get a new document identifier for this entry to ensure that history
- // entries after a session restore are considered to have different
- // documents from the history entries before the session restore.
- // Document identifiers are 64-bit ints, so JS will loose precision and
- // start assigning all entries the same doc identifier if these ever get
- // large enough.
- //
- // It's a potential security issue if document identifiers aren't
- // globally unique, but shEntry.setUniqueDocIdentifier() below guarantees
- // that we won't re-use a doc identifier within a given instance of the
- // application.
- let ident = aDocIdentMap[aEntry.docIdentifier];
- if (!ident) {
- shEntry.setUniqueDocIdentifier();
- aDocIdentMap[aEntry.docIdentifier] = shEntry.docIdentifier;
+ // If we have a serialized document identifier, try to find an SHEntry
+ // which matches that doc identifier and adopt that SHEntry's
+ // BFCacheEntry. If we don't find a match, insert shEntry as the match
+ // for the document identifier.
+ let matchingEntry = aDocIdentMap[aEntry.docIdentifier];
+ if (!matchingEntry) {
+ aDocIdentMap[aEntry.docIdentifier] = shEntry;
}
else {
- shEntry.docIdentifier = ident;
+ shEntry.adoptBFCacheEntry(matchingEntry);
}
}
if (aEntry.owner_b64) {
var ownerInput = Cc["@mozilla.org/io/string-input-stream;1"].
createInstance(Ci.nsIStringInputStream);
var binaryData = atob(aEntry.owner_b64);
ownerInput.setData(binaryData, binaryData.length);
@@ -3283,29 +3272,22 @@ SessionStoreService.prototype = {
// don't restore text data and scrolling state if the user has navigated
// away before the loading completed (except for in-page navigation)
if (hasExpectedURL(aEvent.originalTarget, aBrowser.__SS_restore_data.url)) {
var content = aEvent.originalTarget.defaultView;
restoreTextDataAndScrolling(content, aBrowser.__SS_restore_data, "");
aBrowser.markupDocumentViewer.authorStyleDisabled = selectedPageStyle == "_nostyle";
}
- if (aBrowser.__SS_restore_docIdentifier) {
- let sh = aBrowser.webNavigation.sessionHistory;
- sh.getEntryAtIndex(sh.index, false).QueryInterface(Ci.nsISHEntry).
- docIdentifier = aBrowser.__SS_restore_docIdentifier;
- }
-
// notify the tabbrowser that this document has been completely restored
this._sendTabRestoredNotification(aBrowser.__SS_restore_tab);
delete aBrowser.__SS_restore_data;
delete aBrowser.__SS_restore_pageStyle;
delete aBrowser.__SS_restore_tab;
- delete aBrowser.__SS_restore_docIdentifier;
},
/**
* Restore visibility and dimension features to a window
* @param aWindow
* Window reference
* @param aWinData
* Object containing session data for the window
--- a/browser/components/sessionstore/test/browser/browser_500328.js
+++ b/browser/components/sessionstore/test/browser/browser_500328.js
@@ -111,23 +111,23 @@ function test() {
tabBrowser.loadURI("http://example.com", null, null);
tabBrowser.addEventListener("load", function(aEvent) {
tabBrowser.removeEventListener("load", arguments.callee, true);
// After these push/replaceState calls, the window should have three
// history entries:
- // testURL (state object: null) <-- oldest
- // testURL (state object: {obj1:1})
- // page2 (state object: {obj3:/^a$/}) <-- newest
+ // testURL (state object: null) <-- oldest
+ // testURL (state object: {obj1:1})
+ // testURL?page2 (state object: {obj3:/^a$/}) <-- newest
let contentWindow = tab.linkedBrowser.contentWindow;
let history = contentWindow.history;
history.pushState({obj1:1}, "title-obj1");
- history.pushState({obj2:2}, "title-obj2", "page2");
+ history.pushState({obj2:2}, "title-obj2", "?page2");
history.replaceState({obj3:/^a$/}, "title-obj3");
let state = ss.getTabState(tab);
gBrowser.removeTab(tab);
// Restore the state into a new tab. Things don't work well when we
// restore into the old tab, but that's not a real use case anyway.
let tab2 = gBrowser.addTab("about:blank");
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -251,16 +251,17 @@
@BINPATH@/components/xpcom_system.xpt
@BINPATH@/components/xpcom_components.xpt
@BINPATH@/components/xpcom_ds.xpt
@BINPATH@/components/xpcom_io.xpt
@BINPATH@/components/xpcom_threads.xpt
@BINPATH@/components/xpcom_xpti.xpt
@BINPATH@/components/xpconnect.xpt
@BINPATH@/components/xulapp.xpt
+@BINPATH@/components/xul.xpt
@BINPATH@/components/xuldoc.xpt
@BINPATH@/components/xultmpl.xpt
@BINPATH@/components/zipwriter.xpt
@BINPATH@/components/telemetry.xpt
; JavaScript components
@BINPATH@/components/ConsoleAPI.manifest
@BINPATH@/components/ConsoleAPI.js
--- a/browser/installer/removed-files.in
+++ b/browser/installer/removed-files.in
@@ -221,16 +221,17 @@ extensions/testpilot@labs.mozilla.com/sk
extensions/testpilot@labs.mozilla.com/skin/win/feedback.css
extensions/testpilot@labs.mozilla.com/skin/win/notification-tail-down.png
extensions/testpilot@labs.mozilla.com/skin/win/notification-tail-up.png
extensions/testpilot@labs.mozilla.com/tests/test_data_store.js
greprefs/all.js
greprefs/security-prefs.js
greprefs/xpinstall.js
install.rdf
+modules/ISO8601DateUtils.jsm
modules/JSON.jsm
mozilla-runtime@BIN_SUFFIX@
old-homepage-default.properties
README.txt
res/arrow.gif
res/arrowd.gif
res/broken-image.gif
res/broken-image.png
@@ -936,17 +937,16 @@ xpicleanup@BIN_SUFFIX@
#ifdef XP_WIN
modules/DownloadTaskbarProgress.jsm
#endif
modules/DownloadUtils.jsm
modules/FileUtils.jsm
modules/Geometry.jsm
modules/HUDService.jsm
modules/InlineSpellChecker.jsm
- modules/ISO8601DateUtils.jsm
modules/LightweightThemeConsumer.jsm
modules/LightweightThemeManager.jsm
modules/Microformats.js
modules/NetUtil.jsm
modules/NetworkPrioritizer.jsm
modules/openLocationLastURL.jsm
modules/PerfMeasurement.jsm
modules/PlacesDBUtils.jsm
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a65aa30ebae6c314bccd897862be400e27c7afab
GIT binary patch
literal 6479
zc$`&p1yB@F+b%62jijWMG%M2GDX@TaNeU}0-LSwS9nv7(DJjz3uz++oEYclI{(Rqm
z=gz&)%sKBnbIzH0&lBMqY6`g6l-Ni}NVrOhvYJRp$gr1Q6cg=bmlBZ9c_~<qiux`{
zNUw?ivyhQ~W{@KxQ6MYHN@;s89vNd9Y3a^F6oE_4+RJ*~cvyy*wJe7|^X~{Gr6frs
zHyeMumFAQ5x`oX8+ZS(XE`5keS`-e8S<K0_voA;e<DT(HSS|9yl}pK{hGaNqSJp{u
z%8yn??k)u1)ZWSc$}=L6`y_Mu>fuD}W_2Jg5A*-xsiSLlPVH=M*hhXeR?WOZ1}cNf
zH(L=?-(#beLwYY$G*hHrUG5}0@D`3Ml2uopCf-$2_|BT9_W2&>P9sPWZn5-R&(HpT
zG(`A1y~&x{7;I2skxuLw>D2zlN>^aWef!Qyq(yj3lv<n|A&!5jBc{qbo+xDG(rBIX
zrHF-=uT{Y69L9I&;mWzIVZ$ZRVi(GFe<WcuD>%Jp@Z*@C*dT?fg(_C4q6Ys-AR*iG
zps~kop4$KCuqxpq?e>Zz#wzYTR4Z8TkdiDW<EY$v`0^joPIdpsBqKvKI;1&L3(CFq
zJ2cvdPTD?vw8x^~MSa2^o<aEgw;Nz}$77yv4k`F6<Cq4b;-oybHGTN4U0ccRfA0V0
zdYB0u22;Nm`Erx%u^ifXenoyhqcTD!igPLIfVKYJ+jKN`?L9(sw(`dKCdSuMWZh{_
zP@UV}Cz0O^2|W7GZ`Y&jQgRRZM5`#v#=+5Uq8NUOHI_YytH}KqjxFud<h6X(PvdB3
zrf6{C!pMx7AfeTei)24vI9@v9pMG|^{=IDv*JK@|l|NJ{@v5iLe$?=I@c{K5fjAn#
zChRCCjcP4slpt2TPN>r5?PXU4=Gnlj<yR{)Sf{2kd?raEjktRydjva+CwQV`V`=;U
zo(c)1HG<clcC;0=^vTqSrQb8q6O?Sv){LJ?LWe~BJaONwrma=e@32dpBHdH9S&NGu
z;OBzx+2l1}e{X8oUDYu~-)Okfy2SAGZgkYEjFa|UOs~s)tkKTp!0NgN(4nK5bEDfa
zDylCDnvOf=i6hSgpb-`!0%-1UcZD>e`bgcw%-nU4Cyfgf%kAa2_G)r!eL=d$&wDsA
zRJ;<N@{oTfVUM4CMRqR%D-OqzL~E#ImA+6qc(s>BTsCI+Pj4s)>JnX^HhI>W$kKH`
zk$^k?jnaWh`cucm;hF9vnwyZoikd0=K|*z)*|!~}Lndy=c55;byFb^Ob1LF`2p$3p
znY6k3*Dj)a$i4|KxE*V#RO*Z0(^PtnKEsZr5NAd8JXN;#h%<eB6x*NVJ4TIq1=vVW
zKcK3gRI2>xb=b3^sl4AG4(cRPCf*ZOh(6z`=CYcPbsJ0)A=78{ZZDkQ%bk{|R0|cI
zN)TiO?fuZ0p$c<@FVw=6=^fq(V3RPEe(y<=FhN)}!V~<Bm-+9zG!}A<(h8HM5E^N;
zjZUeTigv<jR)5(7Q?*ic-r@YlT_WhOSPYl<i>4Iu3o=!ptMHp}&FZ4l<12RPqj3>q
zAt%D6@^){r#Dm~Hd!2R7<RK&P!m@8oG!melAic1n;S&!JJmEO!0FgDGX-9jWlwA$I
zjWkE=P7+F7tvlZ8zrmRP9|7prlc{^~e4N=!v=u`)Zsye-l><cSQ$<)v+VjGsuF0Sn
zZHRsJ5lSl)JPdwNcG`u;K!<IvAw8<y4fu-)BV(pOt4l0$wPuBCpeh72!~`x=jsc$t
z?$$?zVbi1)ojUDWQC<pPrrt)kw%(C3mYJPWIL8YqVBJBh6YE>LdNjtFx*8;K%;|v)
zHS;U&k6c*Gy*O6?-bM?BxXgC@EODfIP-aYDBrLuOLD5=*cKW<6&x-ih|F2&^g5Z-~
zWTgyNB1d!OQ-LYjbFL(LNvp1>uD`n4^D;YC2@V>BA>sN*OyVb&+;w`Z1GKJ<dW}KO
zDlk8dP8aWyGM%UWwgffiUJ9-aCnW<PCh94cm_mBZD{OCOs)JEFDpC~h6;qGZqt+$+
zhJTW&;eijH*85+cHweOHu`r%}^gq!KQ0$}i#KR|f<5J&gx`a|FOeiyDg?bYun(@vm
zHArHD{%WdV{=I>408oXBaP3dpiK6PGbnI7Zeus0>3VICJRm$d=ZZ&n5M8yU&$Y$%M
zO>lK(U7^m|9b+xdx`p025-`6l=CcE&zN=nB_ST8+<cdPCQ8JH6swp81{3*Wf-Z_>6
zZH8cm_Jx{-^e>cQ^>5H2GX*i&the1tXJE4nz4=QU<Na3f>z)BKWkkpuMGGbDWT}ta
z2K{oXfCNL7UKvIk&h8putnIQ*Giav2rceiELst)85eAL|;{atPfomJH9T|ITD)?iM
zKF`i@M-VW(lFPj&=#S%J!RHPgo$K)vZn?Co3Zp9!A!R|%r`@r}Z`aabx(HT%DhpL7
znA@AxE0mN`VY><(GYYw?wT5PO^**Nw%M<A{XijdD96;<O$$3UVdWyz%{8jGRRJ*L8
zwg3WJKH<$vHLPY@)+rD4=^#SvZe(14nA?LW!+-bNh75I2Ek#}&;kc3VO9d#4KC4pA
z0!qdYDaY)NK{d?w!O<Gl@6A+7<gQhvM+=DE`6%secTT!Uf?ubno{QIlzu;uv6npzm
z@r{Fy?^i4n`BZh3cKwJ#?K!F3H|C{%rgz8bza9?JS*5w+*dQ-=`@Z@Y$4B@{oCIS2
ziHKLHbXL(4j=P2|z)-BSOo9t8wB?txvj#9JN`-I3C_JlLf8^!aCZZX>uwKtaF2aFo
zi4h;@0Sz>@P=&o`Zg>OZ3#lU|EYo8WEozUE&EMb!jYP*y&{+$eeu>!b-|px6j>gs=
zn4}Rbwi`|qq07$R9{2TN6T(iVLL@&fDX3TWJv6)f)IsnTBmk0?F=w<S()!>=+siYj
z<f$74jfzR_L%GK3FEXzQ2FVAqM&c<1HeN+Krw)EzQ~c!f_lSGqQcko|Amt-Ed7+NF
z$nBPEc6wwFt>Y2>tr2EBb)>tbp*EW)?``r8Mb8nQ_ef|KZaE37hi<EF3~3f$?z};f
zeeewXyulq227Uw0j){zSUeC|~VaoNtU|4-|T$U#f)+TKRK6PnA^XOJmIDxzAnj5}u
zOZ8gQwpm*~+(@-sTdraLHRDyvug|3iH^Yf{7@3`)VoM?A1`qy4cKm<eK^YTzRl6^z
z4bsZ`PM&{Z7g5^vmTcz8X^~&P(XS-;i0BwpdOO%HI`#Q=xu7y!0mA!s8zX)cCcIv?
zw7ThmSZ~)Oz@wm`47Y*1(Vp5_6q8p)QByUIwPl3$ynf!k#BvGRq<09g8jHB>zwB3(
z!}*k9L0#FYr4m|xt49U$B+mb0o#Qo$7CD3Ysq<rN`tZ4W9$hADg7$&;#Itgm&)$4s
zbB#}Ms!3ZQtTi@fzk#85o4?0nvT&tQyMzyrXlKAc>N=++_*22jQ+?C=alE*=(BD2I
zZ(M$1fyJ=kN1vWH>8#6M*Y<duuH$&fJd-m4W*Nfxm>ExQUWcgjG8NweqsfJ;meIX9
zpq<g(#anK%ot*GE&Gc7FK-;^%wPo*czr7zNcH~tOdwt@Hq2z5+2Sdb&IZd7<#Y4c8
zLv{1dxD}>Ctd8h%AR4vRi280Vj&NUZD%uu(fg7SW_B<EqoW6$<z?*0nZADwprI1bo
zu85nBUO7IiRtxsgwuF#wOJylz0A)}p8gxiufFB$^_5|goV%a6i(hNh=lVwbiX$!=O
zRh%}UVPT?9^*V7KCa@R75m&Q&*V*SGx`V&Aa_pATwf$e^-c8D*u&R71Gtf*{K2^)(
zzmfeoYNJN##vyEYHn*^tp%DD5xILjv_gI^u4U-d)KOrzAtrYTp2NTdl`YtGV9g=0(
zc<MTj$~~4aAge<YzL*?m&KdQ}mhd!x9%Md2A|vDGbn%PWgMTcA%?-NqP4URDL34S}
zxQDmNkj9$@+eSdV4tLuQuEF@zDVEqwXqSGZ+^seX=Wlq$?&mRH&7uvQ-V7SCiPXuF
zjxb`9Ta}OPOm!c~#4@AS1{;5+=<pOg)j6v`Rnwv_uPaf~Q~0emkT?-p7yr=urRVQK
zY)h{{Vq`ivc!?4A(pH*WdlAC;m0%0Q@AR$_q2*4EnS;N8-tyRSZXq^5n6Ewa-`!2s
zfFN});5MTqEOX-NL@B_qk@cUn5u=f)2B{49x!scUPRU~$W8A5E?-{U)l&^t^tCw5y
z``OmM$fhjh8E_r^^Y>QZDtVP+-(+FeNfva#kfmNNXaI6!M7cUK!A|0wrqA$NMA;#=
zAuH=n4a5B>x62$^)rY9dyc}s6)mG!w$Wn{Ui)oKxCScB5S=LN@i_Cre^Mtt%i}SVH
z8THyq)=Y@Ku`jT4lwn48&$UUxx0IhDtGMc2Vs6+f&pyYU*+w1oJjyK%6|pGwfwner
zLB;1{WG?(^TRg3$I9oJOoOF!VAJ?A`+4`G?ard{uEm2EkpTUVGf)QjNl?s3r)%C}q
zpQ8)&>YK0qRa+vCZykuY<?x288%88}*s^g?$2sHJfu?)n6jZw=<8qp>r&I|YunP|7
zfr~x%e=(ZXB@b(UM!YV{(lrv)f$}~P7ioEV0ZDt;Zmcui&wCzx(9@f~Qp`xaHM|iJ
zaRS2UHB3u}1HY=-!6hk_X|%3I;liPy`kmYRU+8RY(Xf^Q-N3-uHB!#Eih0yH2XXzr
zkt`0$(qoc_A4jZo-|&<2GqZjGBrTi*-7|_I=@7%;CkhL$;k@-tBQ3T)1%*hj@Oq-P
zn`S45r<aEYrZ>~T16!Zl;gwu%dYk|XUBk2y%6B77P89}ApKdxb8u)fCf9@;tMFj$0
zB^Q-D8#+UdAPWx7Cgr_*$wX=1g(DyBWLU?>10z>he8Bh=s%FC}$QUg#XX_{y`|#0&
z_Y@o$^{^B6CWCCe+4;ybGmCwV?NVO!dC-vJwI?rs3D*~z{cuYEW?js$+}+c4CO7Bo
zUjKa1jj!4AO3;|NyaKM*x67=XR++6T!0D#xrYNeuh(6Iv#qQJUf@7xU4lRg9jAP{*
znS-D~*|1lbF-Ix}GrmGx;*>n%`m$K!htzhpX&aevlu4lf)#ex1TRcjTa)b32MK3rm
z+0NkT7dLQ6nsPuskcthsZRTk&n)l=nIy1v6Dg0e!^_`y6mezdkqDhb#W_Q7LfxR7y
z;KVw}+3hnPM?J8|E6r=HX#|#~M(?eo<OtPD5Dv5tJ|$WUt)~4NeXJMu?le4~N#}(4
zo!qkAOGsP~i9dMNSq<s-X)Ip+oOMaXWip84O~-Yfr8f3H^X@Gu#-FWV_%d!PrO@yV
z{R9!31=7Y(Fl)J9iSX#O8JW$=XMUvC$vQN0;|--E^6u%#e}%iqyD^zNVa3uh)B0tP
zjKnWVOx;-Y>i2_)i_Fzv?jWyC1kX&9{0PCL+(;4J28cg`j4T2x-m7CknsaGnTRF1`
zXBGIOz8`POq37BZki`d7DB|d(Z^Ya|%w78RhZ!n;r8i&3|L4YjD4#AQ0|fWObKT|B
z5k+2TDC68!t+&~<kYh!=bQfAiRKH}I6I8gk-kPsMcYRG=jcstUo!xP{sSAqWDjzJA
zEzy^!6`lw0infC81WbC^QK)XLVmU18O(tPohPX3Q2H?Ow`0UZLOmz81!5m<i#<scg
zMSw}+xJ=yEjA$!war%)F9~jo*a=nAk|8M(n1knbWhq?cD)>cg;XZ>P5PxN<X2xvQZ
zx?+3L3RPgll)GUCIWdFE8Q`njQ#}{f4cDMKb11U@E`#Ox_P{Fd3~y6~=tvEhd{%f_
zV%BTNv7cb=4{e_kNaP@a6oOYf=G0pbs!7jczrRgytlABM`k2pWzVNvW*52V5#}tTP
zu)0U?8Yg$Pa))&LSM>cffW{nll*9{Au^!}$;WX9afHW{vxPpqMmfWUXM~@3Y&6uId
zQ6ipvxn?<NwchgFow8x~<HW?&<pERUTwu=QA?Rk-&adL^zAyGT#YGwlDtvtO^V1t2
zd<3SJb3edDjp}lW_u-)<X0=M06f21IpJj`CB$}V^lZ%cY;#}qksq{?htMULU^r7g2
z5-Bq1Pc2B0DP8sJ*2;#Eu{*)Hd(^|NJmlT2tx1yLYG2r_zKdQaN{V(T<xzy4uCa2;
zUG<7a9$h_%jD2mNSP5EMERh6F8oPWp`r$3?)p!?N>doD(S2|ixL`s1>>B?#g2`;xh
z+={=<H`e6eX-_Vup%`Tg0)5CyRQl}TkS+5<lnKzuV=6s=VIieSMf{#$YYycZ5c#J&
ze}7rtD2C)cdzyP3bl$At>Z*A-Yna9j|CeVexre~N8(T78eLNR1P=a>7nLk3mWOuzo
z%YU=A*rGD6$hP#1Hn`C-hczomH#Vwy)XaJW*=w+{@Wz_R{aY>t;p07G6O-o^i(i|c
zljoZg*mr`2`j{z|@vlGN?+e3R){_G2yGZjbr%ldikJe$gKdiLdoIIVaE)o`IRIie$
zJVtoLQc&?=^#QA9IV=qQ{I%~<{yzj|lUtNvC9;!9_vHt#&!8zo=H^3c^Q|}PWD_k>
z!v|R06LD>2QBX#@L!7sFsRU>Ix4Q80{l9iNt-pEt9?lSHr;{kNz-!u8E<Ae<aLmcS
zNHKi>YB=H}BXZylPt2x7-J@ySx3b6bo3x`h*^~$<3rN|wg(7BE;<|-@T^20C<Ue1+
zg@%TPzt!7p?+<03yH9a;2fAtfA?di<d7jJ`=#Xl%r80QSMjg`)+&P<*n29^HUK<r(
zVPVS@tV2Uf4kF>x*LH?rnvD{&B@DM;9u<O1MeW9xc9D<q!<9>hqM*X0rfhQN*R*Rr
z@2rO=;`2Go$7q<Mn30jYIsm5U_*v+;Q@V+X&eC@iZ$^riX*pZHiPzWlU2O(<#vK08
z1D3!*bZx17PEJ5wsZ)Uv7A6N&p`_%%7%ASs)sTh$@oNMLkhdh@^9hR4NnT!RQa%l!
zqhrqTi;9*iQ+zV5R#Rc=hIDK^K|(-he06R?PtOg;gkNSbeI&1~d8M#)pT_Et8xrbG
zskZe_i2|$&tX7iG*!Wt6urDxPwdDSenVuOrkO`2iOxq|?AZ@NDX)gD0gz;%qh1$e<
zPsck+sSv=ffU0{vRsKhFA1lM2HaDv}$=^GvvG#==W^1aWVN%gpmu%df)6~Plgkj`>
zJWe;xDE7Ala;gDh_wRjNoqw_3i`@@WzRY)C`K@#57n12C>e_mmZ1jMDr*zwhGRS6n
zxj+9$gJCI>g>JHw$Bo8QY$OdC@TvToz?_Ick8<|5gOj5mRt4`*%t+3%6OC(rH+6Cb
zxR_dhO>SCsYm}C<OJqyH-PPSyxdG#Zv6qpq`eXlka_qmR$9=Mcef;sI-#Jf7H(*|F
zJkf@1q7AJpr*PHm)ZO;nA=QMNZ!ICIAEZ@LP*l3G1suPXhV`{L+|-!Xw5;g1rAKtK
z#C|p53G48hKSf97Z@xeK?0z1Ej2wtwDnyF)-nDcY660Trw7x(3xNF4b<YpVGUh$C~
z=#MB`3QZco&)mwhiak$hIn_>RjaQH~1A5G2s554kIQp`J@sycOgf^((9%cLMZ<TvJ
zd3L16Auu$f)E|J*)?PJ9GpA5@QB5aoK3pqolju3Y8isNEl7Z80XG*?InWBw^0S)NG
z0vU2(U#Sp=jp$oflYvbz=)uzJG{avwMr(SF?l&Xd|G{llK<@)R-R%Oh#gpo2T(*I`
z#UuU!M9*Eu->wV@%kEr6m~tG!?sYlIN6yC-i7r9|I=eelB?y;vZ)!{bGz)ao!N>E;
zM}$*ctzBIR>qxVh01!+}j>F#Oz7DB`^4oYMi>IhHW?#_ROQg20%%3<8jAol|TP{!B
zER7}_^3-p_|1&@}6%TwoD&9?|o?xi=0nyjcVP^icomKVSO@>zw0GaMpwIJkO|Jn&8
z1t`I2QBYowr98CO)oYZ6BYHG&ES~hpxLWjIdsU=Lg!CE>_de)*tEi}+&oQB)k)rlL
zc$Jltdj3q6!0Ag(mDuzEZLsRVXsH3ZYa{IhYunwu4^E{~;NkXad8IHVNi!ugSoT%V
z!EXTMtGV*agJZY)>SU4&1qE24z`%ar1BGG3<^N_Q5CEB7HLZ$9)ZM=1Vn1fcdHmNU
zn-<wc=+Ur_F?De?f>+JJ?f(hHot^oU-iW4pC3Ok<GpE!4rU7O!INAR&w5Twf`f|_1
z3U&KeeRV3yg^iuQ<dFp*``LThu?R%Ix++%xLk;1A8H{#_=D)5)ebLNNkv3(!!2tBq
z>YZDP91W^j^gT?l6s@SGM30E1cz8S1Fa7sdwmblc`E|Kzg^Do8@*8b#KM2#sreu@}
zjMmRw$6qEPjTvn9;&(<k{)=&P!V$!^AS>E?l9nVtdJF(0tJV58C~%eC_rK@gOJ77v
z(@XPtad-}C@(N5$VB$SI_TNq!D6(S&?i=nG{UQFpvNnpSm_HE^Jg8C|{Kq@%Hj1BK
d>N-pRGx9SwcSo+_#tqU7l;qT8E2YhX{s$_Ls#O30
--- a/browser/themes/pinstripe/browser/browser.css
+++ b/browser/themes/pinstripe/browser/browser.css
@@ -83,18 +83,18 @@
}
#nav-bar {
padding-bottom: 4px !important;
}
#PersonalToolbar {
-moz-appearance: none;
- margin-top: -1px; /* overlay the bottom border of the toolbar above us */
- padding-top: 0 !important;
+ margin-top: -2px; /* overlay the bottom border of the toolbar above us */
+ padding-top: 1px !important;
background-color: -moz-mac-chrome-active;
border-bottom: 1px solid rgba(0, 0, 0, 0.57);
}
#navigator-toolbox[tabsontop="true"] > #nav-bar,
#navigator-toolbox[tabsontop="true"]:not([customizing]) > #nav-bar[collapsed="true"] + toolbar,
#navigator-toolbox[tabsontop="true"]:not([customizing]) > #nav-bar[collapsed="true"] + #customToolbars + #PersonalToolbar {
-moz-appearance: none;
@@ -288,31 +288,32 @@ toolbarbutton.bookmark-item > menupopup
/* ----- PRIMARY TOOLBAR BUTTONS ----- */
.toolbarbutton-1:not([type="menu-button"]),
.toolbarbutton-1 > .toolbarbutton-menubutton-button,
.toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker,
#restore-button {
-moz-box-orient: vertical;
- padding: 0 3px;
+ -moz-appearance: toolbarbutton;
height: 22px;
- border: 1px solid @toolbarbuttonBorderColor@;
- border-radius: @toolbarbuttonCornerRadius@;
- box-shadow: 0 1px rgba(255, 255, 255, 0.2);
- background: @toolbarbuttonBackground@;
- background-origin: border-box;
+ padding: 0;
+ border: 0;
}
.toolbarbutton-1:not([type="menu-button"]):-moz-lwtheme,
.toolbarbutton-1 > .toolbarbutton-menubutton-button:-moz-lwtheme,
.toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker:-moz-lwtheme,
#restore-button:-moz-lwtheme {
- border-color: rgba(0, 0, 0, 0.4);
- background-image: -moz-linear-gradient(rgba(255,255,255,0.5), rgba(255,255,255,0.2) 50%, rgba(255,255,255,0.1) 50%, rgba(255,255,255,0.2));
+ -moz-appearance: none;
+ padding: 0 3px;
+ border: 1px solid rgba(0, 0, 0, 0.4);
+ border-radius: @toolbarbuttonCornerRadius@;
+ background: -moz-linear-gradient(rgba(255,255,255,0.5), rgba(255,255,255,0.2) 50%, rgba(255,255,255,0.1) 50%, rgba(255,255,255,0.2)) repeat-x;
+ background-origin: border-box;
box-shadow: inset 0 1px rgba(255,255,255,0.3), 0 1px rgba(255,255,255,0.2);
}
.toolbarbutton-1:not([type="menu-button"]):-moz-lwtheme-darktext,
.toolbarbutton-1 > .toolbarbutton-menubutton-button:-moz-lwtheme-darktext,
.toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker:-moz-lwtheme-darktext,
#restore-button:-moz-lwtheme-darktext {
background-image: -moz-linear-gradient(rgba(255,255,255,0.3), rgba(50,50,50,0.2) 50%, rgba(0,0,0,0.2) 50%, rgba(0,0,0,0.13));
@@ -332,16 +333,17 @@ toolbarbutton.bookmark-item > menupopup
margin: 0 4px;
list-style-image: url("chrome://browser/skin/Toolbar.png");
}
toolbar:not([mode="icons"]) .toolbarbutton-1:not([type="menu-button"]),
toolbar:not([mode="icons"]) .toolbarbutton-1 > .toolbarbutton-menubutton-button,
toolbar:not([mode="icons"]) .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker,
toolbar:not([mode="icons"]) #restore-button {
+ -moz-appearance: none;
padding: 0;
height: auto;
border: none;
box-shadow: none;
background: none;
}
.toolbarbutton-1:not([type="menu-button"]),
@@ -403,137 +405,132 @@ toolbar:not([mode="icons"]) .toolbarbutt
opacity: .7;
}
.toolbarbutton-1 > .toolbarbutton-text,
.toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-text {
margin: 2px 0 0;
}
-toolbar[mode="icons"] .toolbarbutton-1:not([type="menu-button"]):not([disabled="true"]):active:hover:not(:-moz-lwtheme),
-toolbar[mode="icons"] .toolbarbutton-1:not([type="menu-button"])[open="true"]:not(:-moz-lwtheme),
-toolbar[mode="icons"] .toolbarbutton-1:not([disabled="true"]) > .toolbarbutton-menubutton-button:active:hover:not(:-moz-lwtheme),
-toolbar[mode="icons"] .toolbarbutton-1[open="true"] > .toolbarbutton-menubutton-dropmarker:not(:-moz-lwtheme),
-toolbar[mode="icons"] #restore-button:not([disabled="true"]):active:hover:not(:-moz-lwtheme) {
- background: @toolbarbuttonPressedBackgroundColor@;
- text-shadow: @loweredShadow@;
- box-shadow: @toolbarbuttonPressedInnerShadow@, @loweredShadow@;
-}
-
toolbar[mode="icons"] .toolbarbutton-1:not([type="menu-button"]):not([disabled="true"]):active:hover:-moz-lwtheme,
toolbar[mode="icons"] .toolbarbutton-1:not([type="menu-button"])[open="true"]:-moz-lwtheme,
toolbar[mode="icons"] .toolbarbutton-1:not([disabled="true"]) > .toolbarbutton-menubutton-button:active:hover:-moz-lwtheme,
toolbar[mode="icons"] .toolbarbutton-1[open="true"] > .toolbarbutton-menubutton-dropmarker:-moz-lwtheme,
toolbar[mode="icons"] #restore-button:not([disabled="true"]):active:hover:-moz-lwtheme {
text-shadow: @loweredShadow@;
background-color: rgba(0,0,0,0.2);
box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), 0 1px rgba(255,255,255,0.2);
}
-toolbar[mode="icons"] .toolbarbutton-1:not([type="menu-button"]):not(#fullscreen-button)[checked="true"]:not(:-moz-lwtheme) {
- background: #606060;
- box-shadow: inset #2A2A2A 0 3px 3.5px, @loweredShadow@;
-}
-
toolbar[mode="icons"] .toolbarbutton-1:not([type="menu-button"]):not(#fullscreen-button)[checked="true"]:-moz-lwtheme {
background-color: rgba(0,0,0,0.4);
box-shadow: inset 0 2px 5px rgba(0,0,0,0.7), 0 1px rgba(255,255,255,0.2);
}
-toolbar[mode="icons"] .toolbarbutton-1:not([type="menu-button"]):not(#fullscreen-button)[checked="true"]:not([disabled="true"]):active:hover:not(:-moz-lwtheme) {
- background: #4E4E4E;
- box-shadow: inset #1c1c1c 0 3px 3.5px;
-}
-
toolbar[mode="icons"] .toolbarbutton-1:not([type="menu-button"]):not(#fullscreen-button)[checked="true"]:not([disabled="true"]):active:hover:-moz-lwtheme {
background-color: rgba(0, 0, 0, 0.6);
box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.8), 0 1px rgba(255, 255, 255, 0.2);
}
-toolbar[mode="icons"] .toolbarbutton-1:not([type="menu-button"]):-moz-window-inactive:not(:-moz-lwtheme),
-toolbar[mode="icons"] .toolbarbutton-1 > .toolbarbutton-menubutton-button:-moz-window-inactive:not(:-moz-lwtheme),
-toolbar[mode="icons"] .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker:-moz-window-inactive:not(:-moz-lwtheme),
-toolbar[mode="icons"] #restore-button:-moz-window-inactive:not(:-moz-lwtheme) {
- border-color: @toolbarbuttonInactiveBorderColor@;
- background-image: @toolbarbuttonInactiveBackgroundImage@;
-}
-
-toolbar[mode="icons"] .toolbarbutton-1:not([type="menu-button"]):not(#fullscreen-button)[checked="true"]:-moz-window-inactive {
- background: #8E8E8E;
- box-shadow: inset rgba(0, 0, 0, 0.5) 0 3px 3.5px, @loweredShadow@;
-}
-
toolbar[mode="icons"] .toolbarbutton-1 > menupopup {
margin-top: 1px;
}
#navigator-toolbox > toolbar {
/* force iconsize="small" on these toolbars */
counter-reset: smallicons;
}
/* unified back/forward button */
#unified-back-forward-button {
-moz-box-align: center;
}
#back-button,
-toolbar:not([mode="icons"]) #forward-button:-moz-locale-dir(rtl) {
+#forward-button:-moz-locale-dir(rtl),
+toolbar[mode="icons"] #back-button:-moz-locale-dir(rtl):-moz-lwtheme {
-moz-image-region: rect(0, 40px, 20px, 20px);
}
#forward-button,
-toolbar:not([mode="icons"]) #back-button:-moz-locale-dir(rtl) {
+#back-button:-moz-locale-dir(rtl),
+#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #forward-button:-moz-locale-dir(rtl),
+toolbar[mode="icons"] #forward-button:-moz-locale-dir(rtl):-moz-lwtheme {
-moz-image-region: rect(0, 60px, 20px, 40px);
}
+#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button:-moz-locale-dir(rtl),
+#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #forward-button:-moz-locale-dir(rtl),
+toolbar[mode="icons"] #back-button:-moz-locale-dir(rtl):-moz-lwtheme,
+toolbar[mode="icons"] #forward-button:-moz-locale-dir(rtl):-moz-lwtheme {
+ -moz-transform: scaleX(-1);
+}
+
#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button {
- -moz-margin-end: -5px;
+ -moz-appearance: none;
+ -moz-margin-end: -7px;
position: relative;
z-index: 1;
-moz-image-region: rect(0, 20px, 20px, 0);
width: 30px;
height: 30px;
padding: 4px 5px 4px 3px;
border-radius: 10000px;
}
-toolbar[mode="icons"] #back-button:-moz-locale-dir(rtl),
-toolbar[mode="icons"] #forward-button:-moz-locale-dir(rtl) {
- -moz-transform: scaleX(-1);
+#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button:not(:-moz-lwtheme) {
+ height: 31px;
+ padding: 4px 5px 5px 3px;
+ margin-bottom: -1px;
+ background: url(chrome://browser/skin/keyhole-circle.png) 0 0 no-repeat;
+}
+
+#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button:-moz-window-inactive:not(:-moz-lwtheme) {
+ background-position: -60px 0;
+}
+
+#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button:not([disabled="true"]):active:hover:not(:-moz-lwtheme),
+#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button[open="true"]:not(:-moz-lwtheme) {
+ background-position: -30px 0;
}
toolbar[mode="icons"] #forward-button {
-moz-margin-start: 0;
}
+#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #forward-button > .toolbarbutton-icon {
+ /* shift the icon away from the back button */
+ margin-left: 3px;
+ margin-right: -1px;
+}
+
#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #forward-button {
- /* 1px to the right */
- padding-left: 4px;
- padding-right: 2px;
-}
-
-#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #forward-button:-moz-lwtheme {
mask: url(chrome://browser/content/browser.xul#pinstripe-keyhole-forward-mask);
}
#navigator-toolbox[iconsize="small"][mode="icons"] > #nav-bar #forward-button {
width: 27px;
+}
+
+#navigator-toolbox[iconsize="small"][mode="icons"] > #nav-bar #forward-button:-moz-lwtheme {
padding-left: 2px;
}
-toolbar[mode="icons"] #forward-button {
+toolbar[mode="icons"] #forward-button:-moz-lwtheme {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
#navigator-toolbox[iconsize="small"][mode="icons"] > #nav-bar #back-button {
-moz-margin-end: 0;
width: 26px;
+}
+
+#navigator-toolbox[iconsize="small"][mode="icons"] > #nav-bar #back-button:-moz-lwtheme {
padding-right: 2px;
border-right-width: 0;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.unified-nav-back[_moz-menuactive]:-moz-locale-dir(ltr),
.unified-nav-forward[_moz-menuactive]:-moz-locale-dir(rtl) {
@@ -1771,44 +1768,45 @@ toolbarbutton.chevron > .toolbarbutton-m
}
#TabsToolbar {
-moz-appearance: none;
height: 26px;
background-repeat: repeat-x;
}
-#TabsToolbar:not(:-moz-lwtheme) {
- background-color: -moz-mac-chrome-active;
-}
-
-#TabsToolbar:not(:-moz-lwtheme):-moz-window-inactive {
- background-color: -moz-mac-chrome-inactive;
-}
-
#TabsToolbar[tabsontop="false"] {
- margin-top: -1px;
+ margin-top: -2px;
padding-top: 2px;
}
+/* For tabs-on-top, only fill the bottom 2px with the chrome background
+ * color, so that the borders in tabbar-top-bg-*.png can mix with it.
+ * In the top 24px the unified toolbar (from the ::before above) will show.
+ */
#TabsToolbar[tabsontop="true"]:not(:-moz-lwtheme) {
padding-bottom: 2px;
- background-image: url(chrome://browser/skin/tabbrowser/tabbar-top-bg-active.png) ;
+ background: url(chrome://browser/skin/tabbrowser/tabbar-top-bg-active.png),
+ -moz-linear-gradient(bottom, -moz-mac-chrome-active 2px, transparent 2px);
}
#TabsToolbar[tabsontop="true"]:not(:-moz-lwtheme):-moz-window-inactive {
- background-image: url(chrome://browser/skin/tabbrowser/tabbar-top-bg-inactive.png);
-}
-
+ background: url(chrome://browser/skin/tabbrowser/tabbar-top-bg-inactive.png),
+ -moz-linear-gradient(bottom, -moz-mac-chrome-inactive 2px, transparent 2px);
+}
+
+/* In tabs-on-bottom mode, fill the whole toolbar with the chrome
+ * background color.
+ */
#TabsToolbar[tabsontop="false"]:not(:-moz-lwtheme) {
- background-image: url(chrome://browser/skin/tabbrowser/tabbar-bottom-bg-active.png);
+ background: url(chrome://browser/skin/tabbrowser/tabbar-bottom-bg-active.png) -moz-mac-chrome-active;
}
#TabsToolbar[tabsontop="false"]:not(:-moz-lwtheme):-moz-window-inactive {
- background-image: url(chrome://browser/skin/tabbrowser/tabbar-bottom-bg-inactive.png);
+ background: url(chrome://browser/skin/tabbrowser/tabbar-bottom-bg-inactive.png) -moz-mac-chrome-inactive;
}
#tabbrowser-tabs {
-moz-box-align: stretch;
height: 26px;
}
#tabbrowser-tabs[tabsontop="true"] > .tabbrowser-arrowscrollbox > .arrowscrollbox-scrollbox:not(:-moz-lwtheme) {
@@ -1950,21 +1948,22 @@ toolbarbutton.chevron > .toolbarbutton-m
/**
* Tabstrip & add-on bar toolbar buttons
*/
:-moz-any(#TabsToolbar, #addon-bar) .toolbarbutton-1,
:-moz-any(#TabsToolbar, #addon-bar) .toolbarbutton-1 > .toolbarbutton-menubutton-button,
:-moz-any(#TabsToolbar, #addon-bar) .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
- margin: 0;
- padding: 0;
- border: none;
- border-radius: 0;
+ -moz-appearance: none;
/* !important flags needed because of bug 561154: */
+ margin: 0 !important;
+ padding: 0 !important;
+ border: none !important;
+ border-radius: 0 !important;
background: none !important;
box-shadow: none !important;
}
:-moz-any(#TabsToolbar, #addon-bar) .toolbarbutton-1:not([type="menu-button"]),
:-moz-any(#TabsToolbar, #addon-bar) .toolbarbutton-1 > .toolbarbutton-menubutton-button,
:-moz-any(#TabsToolbar, #addon-bar) .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
margin: 0;
--- a/browser/themes/pinstripe/browser/jar.mn
+++ b/browser/themes/pinstripe/browser/jar.mn
@@ -37,16 +37,17 @@ browser.jar:
skin/classic/browser/reload-stop-go.png
skin/classic/browser/searchbar-dropmarker.png
skin/classic/browser/searchbar.css
skin/classic/browser/Search.png
skin/classic/browser/section_collapsed.png
skin/classic/browser/section_collapsed-rtl.png
skin/classic/browser/section_expanded.png
skin/classic/browser/Secure-Glyph-White.png
+ skin/classic/browser/keyhole-circle.png
skin/classic/browser/Toolbar.png
skin/classic/browser/toolbarbutton-dropmarker.png
skin/classic/browser/urlbar-arrow.png
skin/classic/browser/urlbar-popup-blocked.png
skin/classic/browser/feeds/subscribe.css (feeds/subscribe.css)
skin/classic/browser/feeds/subscribe-ui.css (feeds/subscribe-ui.css)
skin/classic/browser/feeds/feedIcon.png (feeds/feedIcon.png)
skin/classic/browser/feeds/feedIcon16.png (feeds/feedIcon16.png)
@@ -129,8 +130,13 @@ browser.jar:
skin/classic/browser/sync-bg.png
skin/classic/browser/sync-desktopIcon.png
skin/classic/browser/sync-mobileIcon.png
skin/classic/browser/sync-notification-24.png
skin/classic/browser/syncSetup.css
skin/classic/browser/syncCommon.css
skin/classic/browser/syncQuota.css
#endif
+ skin/classic/browser/lion/keyhole-circle.png (keyhole-circle-lion.png)
+ skin/classic/browser/lion/Toolbar.png (Toolbar-lion.png)
+
+% override chrome://browser/skin/keyhole-circle.png chrome://browser/skin/lion/keyhole-circle.png os=Darwin osversion>=10.7
+% override chrome://browser/skin/Toolbar.png chrome://browser/skin/lion/Toolbar.png os=Darwin osversion>=10.7
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f164d498c351e2541fadcbfb9b1e7a8334a7e581
GIT binary patch
literal 2261
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c3ecea0315f6f42b06dc2fe869d6d0461fef0930
GIT binary patch
literal 2262
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
--- a/browser/themes/pinstripe/browser/places/organizer.css
+++ b/browser/themes/pinstripe/browser/places/organizer.css
@@ -75,43 +75,19 @@
min-width: 1px;
width: 1px;
background-image: none !important;
}
#placesToolbar > toolbarbutton {
list-style-image: url("chrome://browser/skin/places/toolbar.png");
margin: 4px 4px 5px;
- padding: 1px 3px;
- border: 1px solid @toolbarbuttonBorderColor@;
- border-radius: @toolbarbuttonCornerRadius@;
- box-shadow: @loweredShadow@;
- background: @toolbarbuttonBackground@;
- background-origin: border-box;
-}
-
-#placesToolbar > toolbarbutton:not([disabled="true"]):active:hover,
-#placesToolbar > toolbarbutton[open="true"] {
- background: @toolbarbuttonPressedBackgroundColor@;
- text-shadow: @loweredShadow@;
- box-shadow: @toolbarbuttonPressedInnerShadow@, @loweredShadow@;
-}
-
-#placesToolbar > toolbarbutton:-moz-focusring {
- border-color: @toolbarbuttonFocusedBorderColorAqua@;
- box-shadow: @focusRingShadow@;
-}
-
-#placesToolbar > toolbarbutton:-moz-system-metric(mac-graphite-theme):-moz-focusring {
- border-color: @toolbarbuttonFocusedBorderColorGraphite@;
-}
-
-#placesToolbar > toolbarbutton:-moz-window-inactive {
- border-color: @toolbarbuttonInactiveBorderColor@;
- background-image: @toolbarbuttonInactiveBackgroundImage@;
+ padding: 0;
+ height: 22px;
+ -moz-appearance: toolbarbutton;
}
#placesToolbar > toolbarbutton[disabled="true"] > .toolbarbutton-icon {
opacity: 0.5;
}
#placesToolbar > toolbarbutton > .toolbarbutton-icon {
margin: 1px 4px;
@@ -131,27 +107,22 @@
#placesToolbar > toolbarbutton > menupopup {
margin-top: 1px;
}
/* back and forward button */
#back-button:-moz-locale-dir(ltr),
#forward-button:-moz-locale-dir(rtl) {
-moz-image-region: rect(0px, 16px, 16px, 0px);
- border-top-right-radius: 0;
- border-bottom-right-radius: 0;
margin-right: 0;
- border-right: 0;
}
#forward-button:-moz-locale-dir(ltr),
#back-button:-moz-locale-dir(rtl) {
-moz-image-region: rect(0px, 32px, 16px, 16px);
- border-top-left-radius: 0;
- border-bottom-left-radius: 0;
margin-left: 0;
}
#back-button > .toolbarbutton-icon {
-moz-margin-start: 3px !important;
-moz-margin-end: 2px !important;
}
index 0e7f271a5d67058ca678b238595523806ba72ec4..fc7b3497d55e5b665e0308ccab26cae7598887fd
GIT binary patch
literal 121
zc%17D@N?(olHy`uVBq!ia0vp^B0wy~!3HF^H`mkxDF;s%$B>F!Z_jMxWKa+}av|7J
zAZLxtRo1(&kK8lr{lL7wH)nB@#9@hJA6`!LsOK^EVO_=*+`RIzNy01x-6?N<t-@Z;
VS4xWCe+Ot5gQu&X%Q~loCIFS#DhU7p
index 0c7a196de516f54cbd1ab19b06d46236c43ad206..c47147cbddb44e5f154c31d372b0de49c44de4db
GIT binary patch
literal 118
zc%17D@N?(olHy`uVBq!ia0vp^B0wy~!3HF^H`mkxDO*n$$B>F!Z!aF?WKiI7zPLhR
zM<DyFb$y{P`Ti@Zd|3BiC{*;6BfD(Lg@f@;dl@gcWFFj-XtkolBPhPslYjZ~i)+6v
S?3xBNh{4m<&t;ucLK6TKjwz%7
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -138,22 +138,19 @@ MOZ_UPDATE_CHANNEL = @MOZ_UPDATE_CHANNEL
MOZ_UPDATE_PACKAGING = @MOZ_UPDATE_PACKAGING@
MOZ_DISABLE_PARENTAL_CONTROLS = @MOZ_DISABLE_PARENTAL_CONTROLS@
NS_ENABLE_TSF = @NS_ENABLE_TSF@
MOZ_SPELLCHECK = @MOZ_SPELLCHECK@
MOZ_PROFILELOCKING = @MOZ_PROFILELOCKING@
MOZ_FEEDS = @MOZ_FEEDS@
MOZ_TOOLKIT_SEARCH = @MOZ_TOOLKIT_SEARCH@
MOZ_PLACES = @MOZ_PLACES@
-MOZ_STORAGE = @MOZ_STORAGE@
MOZ_SAFE_BROWSING = @MOZ_SAFE_BROWSING@
MOZ_URL_CLASSIFIER = @MOZ_URL_CLASSIFIER@
MOZ_ZIPWRITER = @MOZ_ZIPWRITER@
-MOZ_MORK = @MOZ_MORK@
-MOZ_MORKREADER = @MOZ_MORKREADER@
MOZ_OGG = @MOZ_OGG@
MOZ_RAW = @MOZ_RAW@
MOZ_SYDNEYAUDIO = @MOZ_SYDNEYAUDIO@
MOZ_WAVE = @MOZ_WAVE@
MOZ_MEDIA = @MOZ_MEDIA@
MOZ_VORBIS = @MOZ_VORBIS@
MOZ_TREMOR = @MOZ_TREMOR@
MOZ_WEBM = @MOZ_WEBM@
--- a/configure.in
+++ b/configure.in
@@ -3887,73 +3887,16 @@ elif test "x$ac_cv___va_copy" = "xyes";
AC_DEFINE(HAVE_VA_COPY)
fi
if test "x$ac_cv_va_val_copy" = "xno"; then
AC_DEFINE(HAVE_VA_LIST_AS_ARRAY)
fi
AC_MSG_RESULT($ac_cv_va_val_copy)
-dnl Check for dll-challenged libc's.
-dnl This check is apparently only needed for Linux.
-case "$target" in
- *-linux*)
- dnl ===================================================================
- _curdir=`pwd`
- export _curdir
- rm -rf conftest* _conftest
- mkdir _conftest
- cat >> conftest.C <<\EOF
-#include <stdio.h>
-#include <link.h>
-#include <dlfcn.h>
-#ifdef _dl_loaded
-void __dump_link_map(void) {
- struct link_map *map = _dl_loaded;
- while (NULL != map) {printf("0x%08x %s\n", map->l_addr, map->l_name); map = map->l_next;}
-}
-int main() {
- dlopen("./conftest1.so",RTLD_LAZY);
- dlopen("./../_conftest/conftest1.so",RTLD_LAZY);
- dlopen("CURDIR/_conftest/conftest1.so",RTLD_LAZY);
- dlopen("CURDIR/_conftest/../_conftest/conftest1.so",RTLD_LAZY);
- __dump_link_map();
-}
-#else
-/* _dl_loaded isn't defined, so this should be either a libc5 (glibc1) system, or a glibc2 system that doesn't have the multiple load bug (i.e., RH6.0).*/
-int main() { printf("./conftest1.so\n"); }
-#endif
-EOF
-
- $PERL -p -i -e "s/CURDIR/\$ENV{_curdir}/g;" conftest.C
-
- cat >> conftest1.C <<\EOF
-#include <stdio.h>
-void foo(void) {printf("foo in dll called\n");}
-EOF
- ${CXX-g++} -fPIC -c -g conftest1.C
- ${CXX-g++} -shared -Wl,-h -Wl,conftest1.so -o conftest1.so conftest1.o
- ${CXX-g++} -g conftest.C -o conftest -ldl
- cp -f conftest1.so conftest _conftest
- cd _conftest
- if test `./conftest | grep conftest1.so | wc -l` -gt 1
- then
- echo
- echo "*** Your libc has a bug that can result in loading the same dynamic"
- echo "*** library multiple times. This bug is known to be fixed in glibc-2.0.7-32"
- echo "*** or later. However, if you choose not to upgrade, the only effect"
- echo "*** will be excessive memory usage at runtime."
- echo
- fi
- cd ${_curdir}
- rm -rf conftest* _conftest
- dnl ===================================================================
- ;;
-esac
-
dnl ===================================================================
dnl ========================================================
dnl Put your C++ language/feature checks below
dnl ========================================================
AC_LANG_CPLUSPLUS
ARM_ABI_PREFIX=
HAVE_GCC3_ABI=
@@ -4626,21 +4569,16 @@ if test "$SYSTEM_JPEG" = 1; then
#include <sys/types.h>
#include <jpeglib.h> ],
[ #if JPEG_LIB_VERSION < $MOZJPEG
#error "Insufficient JPEG library version ($MOZJPEG required)."
#endif ],
SYSTEM_JPEG=1,
[SYSTEM_JPEG= JPEG_CFLAGS= JPEG_LIBS=])
fi
-
-MOZ_LIBJPEG_TURBO=
-if test -z "$SYSTEM_JPEG"; then
- MOZ_LIBJPEG_TURBO=1
-fi
CFLAGS=$_SAVE_CFLAGS
LDFLAGS=$_SAVE_LDFLAGS
LIBS=$_SAVE_LIBS
if test -n "${JPEG_DIR}" -a -d "${JPEG_DIR}" -a "$SYSTEM_JPEG" = 1; then
JPEG_CFLAGS="-I${JPEG_DIR}/include"
JPEG_LIBS="-L${JPEG_DIR}/lib ${JPEG_LIBS}"
fi
@@ -4816,18 +4754,16 @@ dnl ====================================
MOZ_ARG_HEADER(Application)
ENABLE_TESTS=1
MOZ_BRANDING_DIRECTORY=
MOZ_OFFICIAL_BRANDING=
MOZ_FEEDS=1
MOZ_INSTALLER=1
MOZ_JSDEBUGGER=1
-MOZ_MORK=
-MOZ_MORKREADER=
MOZ_AUTH_EXTENSION=1
MOZ_OGG=1
MOZ_RAW=
MOZ_SYDNEYAUDIO=
MOZ_VORBIS=
MOZ_TREMOR=
MOZ_WAVE=1
MOZ_MEDIA=
@@ -4849,17 +4785,16 @@ MOZ_PLACES=1
MOZ_PREF_EXTENSIONS=1
MOZ_PROFILELOCKING=1
MOZ_PSM=1
MOZ_RDF=1
MOZ_REFLOW_PERF=
MOZ_SAFE_BROWSING=
MOZ_HELP_VIEWER=
MOZ_SPELLCHECK=1
-MOZ_STORAGE=1
MOZ_SVG_DLISTS=
MOZ_TOOLKIT_SEARCH=1
MOZ_UI_LOCALE=en-US
MOZ_UNIVERSALCHARDET=1
MOZ_URL_CLASSIFIER=
MOZ_XSLT_STANDALONE=
MOZ_XTF=1
MOZ_XUL=1
@@ -6251,22 +6186,30 @@ MOZ_ARG_WITH_STRING(crashreporter-enable
if test -z "$MOZ_CRASHREPORTER_ENABLE_PERCENT"; then
MOZ_CRASHREPORTER_ENABLE_PERCENT=100
fi
AC_DEFINE_UNQUOTED(MOZ_CRASHREPORTER_ENABLE_PERCENT, $MOZ_CRASHREPORTER_ENABLE_PERCENT)
dnl ========================================================
dnl = libjpeg-turbo configuration
dnl ========================================================
+MOZ_LIBJPEG_TURBO=
+if test -z "$SYSTEM_JPEG"; then
+ MOZ_LIBJPEG_TURBO=1
+fi
MOZ_ARG_DISABLE_BOOL(libjpeg_turbo,
[ --disable-libjpeg-turbo Disable optimized jpeg decoding routines],
MOZ_LIBJPEG_TURBO=,
MOZ_LIBJPEG_TURBO=1)
+if test "$SYSTEM_JPEG" = 1 -a "$MOZ_LIBJPEG_TURBO" = 1; then
+ AC_MSG_ERROR([cannot use --with-system-jpeg with --enable-libjpeg-turbo.])
+fi
+
dnl Detect if we can use yasm to compile libjpeg-turbo's optimized assembly
dnl files.
if test -n "$MOZ_LIBJPEG_TURBO"; then
dnl Do we support libjpeg-turbo on this platform?
case "$OS_ARCH:$OS_TEST" in
Linux:x86|Linux:i?86)
@@ -6601,28 +6544,16 @@ if test -n "$MOZ_FEEDS"; then
AC_DEFINE(MOZ_FEEDS)
else
if test "$MOZ_BUILD_APP" = "browser"; then
AC_MSG_ERROR([Cannot build Firefox with --disable-feeds.])
fi
fi
dnl ========================================================
-dnl = Enable mozStorage
-dnl ========================================================
-dnl Implicitly enabled by default if building calendar or places
-MOZ_ARG_ENABLE_BOOL(storage,
-[ --enable-storage Enable mozStorage module and related components],
- MOZ_STORAGE=1,
- MOZ_STORAGE= )
-if test -n "$MOZ_STORAGE"; then
- AC_DEFINE(MOZ_STORAGE)
-fi
-
-dnl ========================================================
dnl Check for sqlite
dnl ========================================================
MOZ_NATIVE_SQLITE=
MOZ_ARG_ENABLE_BOOL(system-sqlite,
[ --enable-system-sqlite Use system sqlite (located with pkgconfig)],
MOZ_NATIVE_SQLITE=1,
MOZ_NATIVE_SQLITE= )
@@ -8883,28 +8814,16 @@ MOZ_ARG_DISABLE_BOOL(ctypes,
AC_SUBST(BUILD_CTYPES)
if test "$BUILD_CTYPES"; then
AC_DEFINE(BUILD_CTYPES)
fi
dnl NECKO_ configuration options are not global
_NON_GLOBAL_ACDEFINES="$_NON_GLOBAL_ACDEFINES NECKO_"
-dnl Only build Mork if it's required
-AC_SUBST(MOZ_MORK)
-if test "$MOZ_MORK"; then
- AC_DEFINE(MOZ_MORK)
-fi
-
-dnl Build the lightweight Mork reader if required
-AC_SUBST(MOZ_MORKREADER)
-if test "$MOZ_MORKREADER"; then
- AC_DEFINE(MOZ_MORKREADER)
-fi
-
dnl Build Places if required
if test "$MOZ_PLACES"; then
AC_DEFINE(MOZ_PLACES)
fi
dnl Build Sync Services if required
AC_SUBST(MOZ_SERVICES_SYNC)
if test -n "$MOZ_SERVICES_SYNC"; then
@@ -8974,17 +8893,16 @@ AC_SUBST(MOZ_JPROF)
AC_SUBST(MOZ_SHARK)
AC_SUBST(MOZ_CALLGRIND)
AC_SUBST(MOZ_VTUNE)
AC_SUBST(MOZ_ETW)
AC_SUBST(MOZ_PROFILING)
AC_SUBST(MOZ_QUANTIFY)
AC_SUBST(LIBICONV)
AC_SUBST(MOZ_PLACES)
-AC_SUBST(MOZ_STORAGE)
AC_SUBST(MOZ_TOOLKIT_SEARCH)
AC_SUBST(MOZ_FEEDS)
AC_SUBST(NS_PRINTING)
AC_SUBST(MOZ_WEBGL)
AC_SUBST(MOZ_HELP_VIEWER)
AC_SUBST(JAVA)
AC_SUBST(JAVAC)
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -64,16 +64,17 @@
#ifdef MOZ_SMIL
#include "nsSMILAnimationController.h"
#endif // MOZ_SMIL
#include "nsIScriptGlobalObject.h"
#include "nsIDocumentEncoder.h"
#include "nsIAnimationFrameListener.h"
#include "nsEventStates.h"
#include "nsIStructuredCloneContainer.h"
+#include "nsIBFCacheEntry.h"
#include "nsDOMMemoryReporter.h"
class nsIContent;
class nsPresContext;
class nsIPresShell;
class nsIDocShell;
class nsStyleSet;
class nsIStyleSheet;
@@ -120,19 +121,19 @@ class Loader;
namespace dom {
class Link;
class Element;
} // namespace dom
} // namespace mozilla
-#define NS_IDOCUMENT_IID \
-{ 0xfac563fb, 0x2b6a, 0x4ac8, \
- { 0x85, 0xf7, 0xd5, 0x14, 0x4b, 0x3e, 0xce, 0x78 } }
+#define NS_IDOCUMENT_IID \
+{ 0x455e4d79, 0x756b, 0x4f73, \
+ { 0x95, 0xea, 0x3f, 0xf6, 0x0c, 0x6a, 0x8c, 0xa6 } }
// Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
// Document states
// RTL locale: specific to the XUL localedir attribute
#define NS_DOCUMENT_STATE_RTL_LOCALE NS_DEFINE_EVENT_STATE_MACRO(0)
@@ -475,21 +476,25 @@ public:
nsIPresShell** aInstancePtrResult) = 0;
virtual void DeleteShell() = 0;
nsIPresShell* GetShell() const
{
return GetBFCacheEntry() ? nsnull : mPresShell;
}
- void SetBFCacheEntry(nsISHEntry* aSHEntry) {
- mSHEntry = aSHEntry;
+ void SetBFCacheEntry(nsIBFCacheEntry* aEntry)
+ {
+ mBFCacheEntry = aEntry;
}
- nsISHEntry* GetBFCacheEntry() const { return mSHEntry; }
+ nsIBFCacheEntry* GetBFCacheEntry() const
+ {
+ return mBFCacheEntry;
+ }
/**
* Return the parent document of this document. Will return null
* unless this document is within a compound document and has a
* parent. Note that this parent chain may cross chrome boundaries.
*/
nsIDocument *GetParentDocument() const
{
@@ -1321,16 +1326,20 @@ public:
* Unsuppress event handling.
* @param aFireEvents If PR_TRUE, delayed events (focus/blur) will be fired
* asynchronously.
*/
virtual void UnsuppressEventHandlingAndFireEvents(PRBool aFireEvents) = 0;
PRUint32 EventHandlingSuppressed() const { return mEventsSuppressed; }
+ bool IsEventHandlingEnabled() {
+ return !EventHandlingSuppressed() && mScriptGlobalObject;
+ }
+
/**
* Increment the number of external scripts being evaluated.
*/
void BeginEvaluatingExternalScript() { ++mExternalScriptsBeingEvaluated; }
/**
* Decrement the number of external scripts being evaluated.
*/
@@ -1733,19 +1742,19 @@ protected:
// Weak reference to mScriptGlobalObject QI:d to nsPIDOMWindow,
// updated on every set of mSecriptGlobalObject.
nsPIDOMWindow *mWindow;
nsCOMPtr<nsIDocumentEncoder> mCachedEncoder;
AnimationListenerList mAnimationFrameListeners;
- // The session history entry in which we're currently bf-cached. Non-null
- // if and only if we're currently in the bfcache.
- nsISHEntry* mSHEntry;
+ // This object allows us to evict ourself from the back/forward cache. The
+ // pointer is non-null iff we're currently in the bfcache.
+ nsIBFCacheEntry *mBFCacheEntry;
// Our base target.
nsString mBaseTarget;
nsCOMPtr<nsIStructuredCloneContainer> mStateObjectContainer;
nsCOMPtr<nsIVariant> mStateObjectCached;
};
--- a/content/base/public/nsIDroppedLinkHandler.idl
+++ b/content/base/public/nsIDroppedLinkHandler.idl
@@ -46,17 +46,17 @@ interface nsIDroppedLinkHandler : nsISup
* Determines if a link being dragged can be dropped and returns true if so.
* aEvent should be a dragenter or dragover event.
*
* If aAllowSameDocument is false, drops are only allowed if the document
* of the source of the drag is different from the destination. This check
* includes any parent, sibling and child frames in the same content tree.
* If true, the source is not checked.
*/
- boolean canDropLink(in nsIDOMDragEvent aEvent, in PRBool aAllowSameDocument);
+ boolean canDropLink(in nsIDOMDragEvent aEvent, in boolean aAllowSameDocument);
/**
* Given a drop event aEvent, determines the link being dragged and returns
* it. If a uri is returned the caller can, for instance, load it. If null
* is returned, there is no valid link to be dropped. A
* NS_ERROR_DOM_SECURITY_ERR error will be thrown and the event cancelled if
* the receiving target should not load the uri for security reasons. This
* will occur if the source of the drag initiated a link for dragging that
--- a/content/base/public/nsISelection2.idl
+++ b/content/base/public/nsISelection2.idl
@@ -58,24 +58,24 @@ interface nsISelection2 : nsISelection
readonly attribute short type;
/**
* Return array of ranges intersecting with the given DOM interval.
*/
void GetRangesForInterval(
in nsIDOMNode beginNode, in PRInt32 beginOffset,
in nsIDOMNode endNode, in PRInt32 endOffset,
- in PRBool allowAdjacent,
+ in boolean allowAdjacent,
out PRUint32 resultCount,
[retval, array, size_is(resultCount)] out nsIDOMRange results);
[noscript] void GetRangesForIntervalCOMArray(
in nsIDOMNode beginNode, in PRInt32 beginOffset,
in nsIDOMNode endNode, in PRInt32 endOffset,
- in PRBool allowAdjacent,
+ in boolean allowAdjacent,
in RangeArray results);
/**
* Scrolls a region of the selection, so that it is visible in
* the scrolled view.
*
* @param aRegion - the region inside the selection to scroll into view
* (see selection region constants defined in
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -487,182 +487,24 @@ nsContentUtils::InitImgLoader()
}
PRBool
nsContentUtils::InitializeEventTable() {
NS_ASSERTION(!sAtomEventTable, "EventTable already initialized!");
NS_ASSERTION(!sStringEventTable, "EventTable already initialized!");
static const EventNameMapping eventArray[] = {
- { nsGkAtoms::onmousedown, NS_MOUSE_BUTTON_DOWN, EventNameType_All, NS_MOUSE_EVENT },
- { nsGkAtoms::onmouseup, NS_MOUSE_BUTTON_UP, EventNameType_All, NS_MOUSE_EVENT },
- { nsGkAtoms::onclick, NS_MOUSE_CLICK, EventNameType_All, NS_MOUSE_EVENT },
- { nsGkAtoms::ondblclick, NS_MOUSE_DOUBLECLICK, EventNameType_HTMLXUL, NS_MOUSE_EVENT },
- { nsGkAtoms::onmouseover, NS_MOUSE_ENTER_SYNTH, EventNameType_All, NS_MOUSE_EVENT },
- { nsGkAtoms::onmouseout, NS_MOUSE_EXIT_SYNTH, EventNameType_All, NS_MOUSE_EVENT },
- { nsGkAtoms::onMozMouseHittest, NS_MOUSE_MOZHITTEST, EventNameType_None, NS_MOUSE_EVENT },
- { nsGkAtoms::onmousemove, NS_MOUSE_MOVE, EventNameType_All, NS_MOUSE_EVENT },
- { nsGkAtoms::oncontextmenu, NS_CONTEXTMENU, EventNameType_HTMLXUL, NS_MOUSE_EVENT },
-
- { nsGkAtoms::onkeydown, NS_KEY_DOWN, EventNameType_HTMLXUL, NS_KEY_EVENT },
- { nsGkAtoms::onkeyup, NS_KEY_UP, EventNameType_HTMLXUL, NS_KEY_EVENT },
- { nsGkAtoms::onkeypress, NS_KEY_PRESS, EventNameType_HTMLXUL, NS_KEY_EVENT },
-
- { nsGkAtoms::onfocus, NS_FOCUS_CONTENT, EventNameType_HTMLXUL, NS_FOCUS_EVENT },
- { nsGkAtoms::onblur, NS_BLUR_CONTENT, EventNameType_HTMLXUL, NS_FOCUS_EVENT },
-
- { nsGkAtoms::onoffline, NS_OFFLINE, EventNameType_HTMLXUL, NS_EVENT },
- { nsGkAtoms::ononline, NS_ONLINE, EventNameType_HTMLXUL, NS_EVENT },
- { nsGkAtoms::onsubmit, NS_FORM_SUBMIT, EventNameType_HTMLXUL, NS_EVENT },
- { nsGkAtoms::onreset, NS_FORM_RESET, EventNameType_HTMLXUL, NS_EVENT },
- { nsGkAtoms::onchange, NS_FORM_CHANGE, EventNameType_HTMLXUL, NS_EVENT },
- { nsGkAtoms::onselect, NS_FORM_SELECTED, EventNameType_HTMLXUL, NS_EVENT },
- { nsGkAtoms::oninvalid, NS_FORM_INVALID, EventNameType_HTMLXUL, NS_EVENT },
- { nsGkAtoms::onload, NS_LOAD, EventNameType_All, NS_EVENT },
- { nsGkAtoms::onpopstate, NS_POPSTATE, EventNameType_HTMLXUL, NS_EVENT_NULL },
- { nsGkAtoms::onunload, NS_PAGE_UNLOAD,
- (EventNameType_HTMLXUL | EventNameType_SVGSVG), NS_EVENT },
- { nsGkAtoms::onhashchange, NS_HASHCHANGE, EventNameType_HTMLXUL, NS_EVENT },
- { nsGkAtoms::onreadystatechange, NS_READYSTATECHANGE, EventNameType_HTMLXUL },
- { nsGkAtoms::onbeforeunload, NS_BEFORE_PAGE_UNLOAD, EventNameType_HTMLXUL, NS_EVENT },
- { nsGkAtoms::onabort, NS_IMAGE_ABORT,
- (EventNameType_HTMLXUL | EventNameType_SVGSVG), NS_EVENT },
- { nsGkAtoms::onerror, NS_LOAD_ERROR,
- (EventNameType_HTMLXUL | EventNameType_SVGSVG), NS_EVENT },
- { nsGkAtoms::onbeforescriptexecute, NS_BEFORE_SCRIPT_EXECUTE, EventNameType_HTMLXUL, NS_EVENT },
- { nsGkAtoms::onafterscriptexecute, NS_AFTER_SCRIPT_EXECUTE, EventNameType_HTMLXUL, NS_EVENT },
-
- { nsGkAtoms::onDOMAttrModified, NS_MUTATION_ATTRMODIFIED, EventNameType_HTMLXUL, NS_MUTATION_EVENT },
- { nsGkAtoms::onDOMCharacterDataModified, NS_MUTATION_CHARACTERDATAMODIFIED, EventNameType_HTMLXUL, NS_MUTATION_EVENT },
- { nsGkAtoms::onDOMNodeInserted, NS_MUTATION_NODEINSERTED, EventNameType_HTMLXUL, NS_MUTATION_EVENT },
- { nsGkAtoms::onDOMNodeRemoved, NS_MUTATION_NODEREMOVED, EventNameType_HTMLXUL, NS_MUTATION_EVENT },
- { nsGkAtoms::onDOMNodeInsertedIntoDocument, NS_MUTATION_NODEINSERTEDINTODOCUMENT, EventNameType_HTMLXUL, NS_MUTATION_EVENT },
- { nsGkAtoms::onDOMNodeRemovedFromDocument, NS_MUTATION_NODEREMOVEDFROMDOCUMENT, EventNameType_HTMLXUL, NS_MUTATION_EVENT },
- { nsGkAtoms::onDOMSubtreeModified, NS_MUTATION_SUBTREEMODIFIED, EventNameType_HTMLXUL, NS_MUTATION_EVENT },
-
- { nsGkAtoms::onDOMActivate, NS_UI_ACTIVATE, EventNameType_HTMLXUL, NS_UI_EVENT },
- { nsGkAtoms::onDOMFocusIn, NS_UI_FOCUSIN, EventNameType_HTMLXUL, NS_UI_EVENT },
- { nsGkAtoms::onDOMFocusOut, NS_UI_FOCUSOUT, EventNameType_HTMLXUL, NS_UI_EVENT },
- { nsGkAtoms::oninput, NS_FORM_INPUT, EventNameType_HTMLXUL, NS_UI_EVENT },
-
- { nsGkAtoms::onDOMMouseScroll, NS_MOUSE_SCROLL, EventNameType_HTMLXUL, NS_MOUSE_SCROLL_EVENT },
- { nsGkAtoms::onMozMousePixelScroll, NS_MOUSE_PIXEL_SCROLL, EventNameType_HTMLXUL, NS_MOUSE_SCROLL_EVENT },
-
- { nsGkAtoms::onpageshow, NS_PAGE_SHOW, EventNameType_HTML, NS_EVENT },
- { nsGkAtoms::onpagehide, NS_PAGE_HIDE, EventNameType_HTML, NS_EVENT },
- { nsGkAtoms::onMozBeforeResize, NS_BEFORERESIZE_EVENT, EventNameType_None, NS_EVENT },
- { nsGkAtoms::onresize, NS_RESIZE_EVENT,
- (EventNameType_HTMLXUL | EventNameType_SVGSVG), NS_EVENT },
- { nsGkAtoms::onscroll, NS_SCROLL_EVENT,
- (EventNameType_HTMLXUL | EventNameType_SVGSVG), NS_EVENT_NULL },
- { nsGkAtoms::oncopy, NS_COPY, EventNameType_HTMLXUL, NS_EVENT },
- { nsGkAtoms::oncut, NS_CUT, EventNameType_HTMLXUL, NS_EVENT },
- { nsGkAtoms::onpaste, NS_PASTE, EventNameType_HTMLXUL, NS_EVENT },
- { nsGkAtoms::onopen, NS_OPEN, EventNameType_None, NS_EVENT },
- { nsGkAtoms::onmessage, NS_MESSAGE, EventNameType_None, NS_EVENT },
- // XUL specific events
- { nsGkAtoms::ontext, NS_TEXT_TEXT, EventNameType_XUL, NS_EVENT_NULL },
-
- { nsGkAtoms::oncompositionstart, NS_COMPOSITION_START, EventNameType_XUL, NS_COMPOSITION_EVENT },
- { nsGkAtoms::oncompositionend, NS_COMPOSITION_END, EventNameType_XUL, NS_COMPOSITION_EVENT },
-
- { nsGkAtoms::oncommand, NS_XUL_COMMAND, EventNameType_XUL, NS_INPUT_EVENT },
-
- { nsGkAtoms::onclose, NS_XUL_CLOSE, EventNameType_XUL, NS_EVENT_NULL},
- { nsGkAtoms::onpopupshowing, NS_XUL_POPUP_SHOWING, EventNameType_XUL, NS_EVENT_NULL},
- { nsGkAtoms::onpopupshown, NS_XUL_POPUP_SHOWN, EventNameType_XUL, NS_EVENT_NULL},
- { nsGkAtoms::onpopuphiding, NS_XUL_POPUP_HIDING, EventNameType_XUL, NS_EVENT_NULL},
- { nsGkAtoms::onpopuphidden, NS_XUL_POPUP_HIDDEN, EventNameType_XUL, NS_EVENT_NULL},
- { nsGkAtoms::onbroadcast, NS_XUL_BROADCAST, EventNameType_XUL, NS_EVENT_NULL},
- { nsGkAtoms::oncommandupdate, NS_XUL_COMMAND_UPDATE, EventNameType_XUL, NS_EVENT_NULL},
-
- { nsGkAtoms::ondragenter, NS_DRAGDROP_ENTER, EventNameType_HTMLXUL, NS_DRAG_EVENT },
- { nsGkAtoms::ondragover, NS_DRAGDROP_OVER_SYNTH, EventNameType_HTMLXUL, NS_DRAG_EVENT },
- { nsGkAtoms::ondragexit, NS_DRAGDROP_EXIT_SYNTH, EventNameType_XUL, NS_DRAG_EVENT },
- { nsGkAtoms::ondragdrop, NS_DRAGDROP_DRAGDROP, EventNameType_XUL, NS_DRAG_EVENT },
- { nsGkAtoms::ondraggesture, NS_DRAGDROP_GESTURE, EventNameType_XUL, NS_DRAG_EVENT },
- { nsGkAtoms::ondrag, NS_DRAGDROP_DRAG, EventNameType_HTMLXUL, NS_DRAG_EVENT },
- { nsGkAtoms::ondragend, NS_DRAGDROP_END, EventNameType_HTMLXUL, NS_DRAG_EVENT },
- { nsGkAtoms::ondragstart, NS_DRAGDROP_START, EventNameType_HTMLXUL, NS_DRAG_EVENT },
- { nsGkAtoms::ondragleave, NS_DRAGDROP_LEAVE_SYNTH, EventNameType_HTMLXUL, NS_DRAG_EVENT },
- { nsGkAtoms::ondrop, NS_DRAGDROP_DROP, EventNameType_HTMLXUL, NS_DRAG_EVENT },
-
- { nsGkAtoms::onoverflow, NS_SCROLLPORT_OVERFLOW, EventNameType_XUL, NS_EVENT_NULL},
- { nsGkAtoms::onunderflow, NS_SCROLLPORT_UNDERFLOW, EventNameType_XUL, NS_EVENT_NULL},
- { nsGkAtoms::onSVGLoad, NS_SVG_LOAD, EventNameType_None, NS_SVG_EVENT },
- { nsGkAtoms::onSVGUnload, NS_SVG_UNLOAD, EventNameType_None, NS_SVG_EVENT },
- { nsGkAtoms::onSVGAbort, NS_SVG_ABORT, EventNameType_None, NS_SVG_EVENT },
- { nsGkAtoms::onSVGError, NS_SVG_ERROR, EventNameType_None, NS_SVG_EVENT },
- { nsGkAtoms::onSVGResize, NS_SVG_RESIZE, EventNameType_None, NS_SVG_EVENT },
- { nsGkAtoms::onSVGScroll, NS_SVG_SCROLL, EventNameType_None, NS_SVG_EVENT },
-
- { nsGkAtoms::onSVGZoom, NS_SVG_ZOOM, EventNameType_None, NS_SVGZOOM_EVENT },
-
- // This is a bit hackish, but SVG's event names are weird.
- { nsGkAtoms::onzoom, NS_SVG_ZOOM, EventNameType_SVGSVG, NS_EVENT_NULL },
-#ifdef MOZ_SMIL
- { nsGkAtoms::onbegin, NS_SMIL_BEGIN, EventNameType_SMIL, NS_EVENT_NULL },
- { nsGkAtoms::onbeginEvent, NS_SMIL_BEGIN, EventNameType_None, NS_SMIL_TIME_EVENT },
- { nsGkAtoms::onend, NS_SMIL_END, EventNameType_SMIL, NS_EVENT_NULL },
- { nsGkAtoms::onendEvent, NS_SMIL_END, EventNameType_None, NS_SMIL_TIME_EVENT },
- { nsGkAtoms::onrepeat, NS_SMIL_REPEAT, EventNameType_SMIL, NS_EVENT_NULL },
- { nsGkAtoms::onrepeatEvent, NS_SMIL_REPEAT, EventNameType_None, NS_SMIL_TIME_EVENT },
-#endif // MOZ_SMIL
-#ifdef MOZ_MEDIA
- { nsGkAtoms::onloadstart, NS_LOADSTART, EventNameType_HTML, NS_EVENT_NULL },
- { nsGkAtoms::onprogress, NS_PROGRESS, EventNameType_HTML, NS_EVENT_NULL },
- { nsGkAtoms::onsuspend, NS_SUSPEND, EventNameType_HTML, NS_EVENT_NULL },
- { nsGkAtoms::onemptied, NS_EMPTIED, EventNameType_HTML, NS_EVENT_NULL },
- { nsGkAtoms::onstalled, NS_STALLED, EventNameType_HTML, NS_EVENT_NULL },
- { nsGkAtoms::onplay, NS_PLAY, EventNameType_HTML, NS_EVENT_NULL },
- { nsGkAtoms::onpause, NS_PAUSE, EventNameType_HTML, NS_EVENT_NULL },
- { nsGkAtoms::onloadedmetadata, NS_LOADEDMETADATA, EventNameType_HTML, NS_EVENT_NULL },
- { nsGkAtoms::onloadeddata, NS_LOADEDDATA, EventNameType_HTML, NS_EVENT_NULL },
- { nsGkAtoms::onwaiting, NS_WAITING, EventNameType_HTML, NS_EVENT_NULL },
- { nsGkAtoms::onplaying, NS_PLAYING, EventNameType_HTML, NS_EVENT_NULL },
- { nsGkAtoms::oncanplay, NS_CANPLAY, EventNameType_HTML, NS_EVENT_NULL },
- { nsGkAtoms::oncanplaythrough, NS_CANPLAYTHROUGH, EventNameType_HTML, NS_EVENT_NULL },
- { nsGkAtoms::onseeking, NS_SEEKING, EventNameType_HTML, NS_EVENT_NULL },
- { nsGkAtoms::onseeked, NS_SEEKED, EventNameType_HTML, NS_EVENT_NULL },
- { nsGkAtoms::ontimeupdate, NS_TIMEUPDATE, EventNameType_HTML, NS_EVENT_NULL },
- { nsGkAtoms::onended, NS_ENDED, EventNameType_HTML, NS_EVENT_NULL },
- { nsGkAtoms::onratechange, NS_RATECHANGE, EventNameType_HTML, NS_EVENT_NULL },
- { nsGkAtoms::ondurationchange, NS_DURATIONCHANGE, EventNameType_HTML, NS_EVENT_NULL },
- { nsGkAtoms::onvolumechange, NS_VOLUMECHANGE, EventNameType_HTML, NS_EVENT_NULL },
- { nsGkAtoms::onMozAudioAvailable, NS_MOZAUDIOAVAILABLE, EventNameType_None, NS_EVENT_NULL },
-#endif // MOZ_MEDIA
- { nsGkAtoms::onMozAfterPaint, NS_AFTERPAINT, EventNameType_None, NS_EVENT },
- { nsGkAtoms::onMozBeforePaint, NS_BEFOREPAINT, EventNameType_None, NS_EVENT_NULL },
-
- { nsGkAtoms::onMozScrolledAreaChanged, NS_SCROLLEDAREACHANGED, EventNameType_None, NS_SCROLLAREA_EVENT },
-
- // Simple gesture events
- { nsGkAtoms::onMozSwipeGesture, NS_SIMPLE_GESTURE_SWIPE, EventNameType_None, NS_SIMPLE_GESTURE_EVENT },
- { nsGkAtoms::onMozMagnifyGestureStart, NS_SIMPLE_GESTURE_MAGNIFY_START, EventNameType_None, NS_SIMPLE_GESTURE_EVENT },
- { nsGkAtoms::onMozMagnifyGestureUpdate, NS_SIMPLE_GESTURE_MAGNIFY_UPDATE, EventNameType_None, NS_SIMPLE_GESTURE_EVENT },
- { nsGkAtoms::onMozMagnifyGesture, NS_SIMPLE_GESTURE_MAGNIFY, EventNameType_None, NS_SIMPLE_GESTURE_EVENT },
- { nsGkAtoms::onMozRotateGestureStart, NS_SIMPLE_GESTURE_ROTATE_START, EventNameType_None, NS_SIMPLE_GESTURE_EVENT },
- { nsGkAtoms::onMozRotateGestureUpdate, NS_SIMPLE_GESTURE_ROTATE_UPDATE, EventNameType_None, NS_SIMPLE_GESTURE_EVENT },
- { nsGkAtoms::onMozRotateGesture, NS_SIMPLE_GESTURE_ROTATE, EventNameType_None, NS_SIMPLE_GESTURE_EVENT },
- { nsGkAtoms::onMozTapGesture, NS_SIMPLE_GESTURE_TAP, EventNameType_None, NS_SIMPLE_GESTURE_EVENT },
- { nsGkAtoms::onMozPressTapGesture, NS_SIMPLE_GESTURE_PRESSTAP, EventNameType_None, NS_SIMPLE_GESTURE_EVENT },
-
- { nsGkAtoms::onMozTouchDown, NS_MOZTOUCH_DOWN, EventNameType_None, NS_MOZTOUCH_EVENT },
- { nsGkAtoms::onMozTouchMove, NS_MOZTOUCH_MOVE, EventNameType_None, NS_MOZTOUCH_EVENT },
- { nsGkAtoms::onMozTouchUp, NS_MOZTOUCH_UP, EventNameType_None, NS_MOZTOUCH_EVENT },
-
- { nsGkAtoms::ondevicemotion, NS_DEVICE_MOTION, EventNameType_None, NS_EVENT },
- { nsGkAtoms::ondeviceorientation, NS_DEVICE_ORIENTATION, EventNameType_None, NS_EVENT },
-
- { nsGkAtoms::ontransitionend, NS_TRANSITION_END, EventNameType_None, NS_TRANSITION_EVENT },
- { nsGkAtoms::onanimationstart, NS_ANIMATION_START, EventNameType_None, NS_ANIMATION_EVENT },
- { nsGkAtoms::onanimationend, NS_ANIMATION_END, EventNameType_None, NS_ANIMATION_EVENT },
- { nsGkAtoms::onanimationiteration, NS_ANIMATION_ITERATION, EventNameType_None, NS_ANIMATION_EVENT },
- { nsGkAtoms::onbeforeprint, NS_BEFOREPRINT, EventNameType_HTMLXUL, NS_EVENT },
- { nsGkAtoms::onafterprint, NS_AFTERPRINT, EventNameType_HTMLXUL, NS_EVENT }
+#define EVENT(name_, _id, _type, _struct) \
+ { nsGkAtoms::on##name_, _id, _type, _struct },
+#define WINDOW_ONLY_EVENT EVENT
+#define NON_IDL_EVENT EVENT
+#include "nsEventNameList.h"
+#undef WINDOW_ONLY_EVENT
+#undef EVENT
+ nsnull
};
sAtomEventTable = new nsDataHashtable<nsISupportsHashKey, EventNameMapping>;
sStringEventTable = new nsDataHashtable<nsStringHashKey, EventNameMapping>;
sUserDefinedEvents = new nsCOMArray<nsIAtom>(64);
if (!sAtomEventTable || !sStringEventTable || !sUserDefinedEvents ||
!sAtomEventTable->Init(int(NS_ARRAY_LENGTH(eventArray) / 0.75) + 1) ||
@@ -671,17 +513,18 @@ nsContentUtils::InitializeEventTable() {
sAtomEventTable = nsnull;
delete sStringEventTable;
sStringEventTable = nsnull;
delete sUserDefinedEvents;
sUserDefinedEvents = nsnull;
return PR_FALSE;
}
- for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(eventArray); ++i) {
+ // Subtract one from the length because of the trailing null
+ for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(eventArray) - 1; ++i) {
if (!sAtomEventTable->Put(eventArray[i].mAtom, eventArray[i]) ||
!sStringEventTable->Put(Substring(nsDependentAtomString(eventArray[i].mAtom), 2),
eventArray[i])) {
delete sAtomEventTable;
sAtomEventTable = nsnull;
delete sStringEventTable;
sStringEventTable = nsnull;
return PR_FALSE;
@@ -693,24 +536,26 @@ nsContentUtils::InitializeEventTable() {
void
nsContentUtils::InitializeTouchEventTable()
{
static PRBool sEventTableInitialized = PR_FALSE;
if (!sEventTableInitialized && sAtomEventTable && sStringEventTable) {
sEventTableInitialized = PR_TRUE;
static const EventNameMapping touchEventArray[] = {
- { nsGkAtoms::ontouchstart, NS_USER_DEFINED_EVENT, EventNameType_All, NS_INPUT_EVENT },
- { nsGkAtoms::ontouchend, NS_USER_DEFINED_EVENT, EventNameType_All, NS_INPUT_EVENT },
- { nsGkAtoms::ontouchmove, NS_USER_DEFINED_EVENT, EventNameType_All, NS_INPUT_EVENT },
- { nsGkAtoms::ontouchenter, NS_USER_DEFINED_EVENT, EventNameType_All, NS_INPUT_EVENT },
- { nsGkAtoms::ontouchleave, NS_USER_DEFINED_EVENT, EventNameType_All, NS_INPUT_EVENT },
- { nsGkAtoms::ontouchcancel, NS_USER_DEFINED_EVENT, EventNameType_All, NS_INPUT_EVENT }
+#define EVENT(name_, _id, _type, _struct)
+#define TOUCH_EVENT(name_, _id, _type, _struct) \
+ { nsGkAtoms::on##name_, _id, _type, _struct },
+#include "nsEventNameList.h"
+#undef TOUCH_EVENT
+#undef EVENT
+ nsnull
};
- for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(touchEventArray); ++i) {
+ // Subtract one from the length because of the trailing null
+ for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(touchEventArray) - 1; ++i) {
if (!sAtomEventTable->Put(touchEventArray[i].mAtom, touchEventArray[i]) ||
!sStringEventTable->Put(Substring(nsDependentAtomString(touchEventArray[i].mAtom), 2),
touchEventArray[i])) {
delete sAtomEventTable;
sAtomEventTable = nsnull;
delete sStringEventTable;
sStringEventTable = nsnull;
return;
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -3191,28 +3191,31 @@ nsDocument::doCreateShell(nsPresContext*
rv = shell->Init(this, aContext, aViewManager, aStyleSet, aCompatMode);
NS_ENSURE_SUCCESS(rv, rv);
// Note: we don't hold a ref to the shell (it holds a ref to us)
mPresShell = shell;
mExternalResourceMap.ShowViewers();
- if (mScriptGlobalObject) {
- RescheduleAnimationFrameNotifications();
- }
+ MaybeRescheduleAnimationFrameNotifications();
shell.swap(*aInstancePtrResult);
return NS_OK;
}
void
-nsDocument::RescheduleAnimationFrameNotifications()
-{
+nsDocument::MaybeRescheduleAnimationFrameNotifications()
+{
+ if (!mPresShell || !IsEventHandlingEnabled()) {
+ // bail out for now, until one of those conditions changes
+ return;
+ }
+
nsRefreshDriver* rd = mPresShell->GetPresContext()->RefreshDriver();
if (mHavePendingPaint) {
rd->ScheduleBeforePaintEvent(this);
}
if (!mAnimationFrameListeners.IsEmpty()) {
rd->ScheduleAnimationFrameListeners(this);
}
}
@@ -3223,17 +3226,17 @@ nsIDocument::TakeAnimationFrameListeners
aListeners.AppendElements(mAnimationFrameListeners);
mAnimationFrameListeners.Clear();
}
void
nsDocument::DeleteShell()
{
mExternalResourceMap.HideViewers();
- if (mScriptGlobalObject) {
+ if (IsEventHandlingEnabled()) {
RevokeAnimationFrameNotifications();
}
mPresShell = nsnull;
}
void
nsDocument::RevokeAnimationFrameNotifications()
{
@@ -3771,17 +3774,17 @@ nsDocument::SetScriptGlobalObject(nsIScr
"Clearing window pointer while animations are unpaused");
#endif // MOZ_SMIL
if (mScriptGlobalObject && !aScriptGlobalObject) {
// We're detaching from the window. We need to grab a pointer to
// our layout history state now.
mLayoutHistoryState = GetLayoutHistoryState();
- if (mPresShell) {
+ if (mPresShell && !EventHandlingSuppressed()) {
RevokeAnimationFrameNotifications();
}
// Also make sure to remove our onload blocker now if we haven't done it yet
if (mOnloadBlockCount != 0) {
nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
if (loadGroup) {
loadGroup->RemoveRequest(mOnloadBlocker, nsnull, NS_OK);
@@ -3832,19 +3835,17 @@ nsDocument::SetScriptGlobalObject(nsIScr
"Unexpected container or script global?");
#endif
PRBool allowDNSPrefetch;
docShell->GetAllowDNSPrefetch(&allowDNSPrefetch);
mAllowDNSPrefetch = allowDNSPrefetch;
}
}
- if (mPresShell) {
- RescheduleAnimationFrameNotifications();
- }
+ MaybeRescheduleAnimationFrameNotifications();
}
// Remember the pointer to our window (or lack there of), to avoid
// having to QI every time it's asked for.
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mScriptGlobalObject);
mWindow = window;
}
@@ -7643,16 +7644,20 @@ SuppressEventHandlingInDocument(nsIDocum
{
aDocument->SuppressEventHandling(*static_cast<PRUint32*>(aData));
return PR_TRUE;
}
void
nsDocument::SuppressEventHandling(PRUint32 aIncrease)
{
+ if (mEventsSuppressed == 0 && aIncrease != 0 && mPresShell &&
+ mScriptGlobalObject) {
+ RevokeAnimationFrameNotifications();
+ }
mEventsSuppressed += aIncrease;
EnumerateSubDocuments(SuppressEventHandlingInDocument, &aIncrease);
}
static void
FireOrClearDelayedEvents(nsTArray<nsCOMPtr<nsIDocument> >& aDocuments,
PRBool aFireEvents)
{
@@ -7802,23 +7807,18 @@ GetAndUnsuppressSubDocuments(nsIDocument
docs->AppendElement(aDocument);
aDocument->EnumerateSubDocuments(GetAndUnsuppressSubDocuments, docs);
return PR_TRUE;
}
void
nsDocument::UnsuppressEventHandlingAndFireEvents(PRBool aFireEvents)
{
- if (mEventsSuppressed > 0) {
- --mEventsSuppressed;
- }
-
nsTArray<nsCOMPtr<nsIDocument> > documents;
- documents.AppendElement(this);
- EnumerateSubDocuments(GetAndUnsuppressSubDocuments, &documents);
+ GetAndUnsuppressSubDocuments(this, &documents);
if (aFireEvents) {
NS_DispatchToCurrentThread(new nsDelayedEventDispatcher(documents));
} else {
FireOrClearDelayedEvents(documents, PR_FALSE);
}
}
@@ -8037,30 +8037,31 @@ nsIDocument::CreateStaticClone(nsISuppor
}
void
nsIDocument::ScheduleBeforePaintEvent(nsIAnimationFrameListener* aListener)
{
if (aListener) {
PRBool alreadyRegistered = !mAnimationFrameListeners.IsEmpty();
if (mAnimationFrameListeners.AppendElement(aListener) &&
- !alreadyRegistered && mPresShell) {
+ !alreadyRegistered && mPresShell && IsEventHandlingEnabled()) {
mPresShell->GetPresContext()->RefreshDriver()->
ScheduleAnimationFrameListeners(this);
}
return;
}
if (!mHavePendingPaint) {
// We don't want to use GetShell() here, because we want to schedule the
// paint even if we're frozen. Either we'll get unfrozen and then the
// event will fire, or we'll quietly go away at some point.
mHavePendingPaint =
!mPresShell ||
+ !IsEventHandlingEnabled() ||
mPresShell->GetPresContext()->RefreshDriver()->
ScheduleBeforePaintEvent(this);
}
}
nsresult
nsDocument::GetStateObject(nsIVariant** aState)
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -860,17 +860,20 @@ public:
#endif // MOZ_SMIL
void SetImagesNeedAnimating(PRBool aAnimating);
virtual void SuppressEventHandling(PRUint32 aIncrease);
virtual void UnsuppressEventHandlingAndFireEvents(PRBool aFireEvents);
- void DecreaseEventSuppression() { --mEventsSuppressed; }
+ void DecreaseEventSuppression() {
+ --mEventsSuppressed;
+ MaybeRescheduleAnimationFrameNotifications();
+ }
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsDocument,
nsIDocument)
void DoNotifyPossibleTitleChange();
nsExternalResourceMap& ExternalResourceMap()
{
@@ -1144,18 +1147,19 @@ private:
// Just like EnableStyleSheetsForSet, but doesn't check whether
// aSheetSet is null and allows the caller to control whether to set
// aSheetSet as the preferred set in the CSSLoader.
void EnableStyleSheetsForSetInternal(const nsAString& aSheetSet,
PRBool aUpdateCSSLoader);
// Revoke any pending notifications due to mozRequestAnimationFrame calls
void RevokeAnimationFrameNotifications();
- // Reschedule any notifications we need to handle mozRequestAnimationFrame
- void RescheduleAnimationFrameNotifications();
+ // Reschedule any notifications we need to handle
+ // mozRequestAnimationFrame, if it's OK to do so.
+ void MaybeRescheduleAnimationFrameNotifications();
// These are not implemented and not supported.
nsDocument(const nsDocument& aOther);
nsDocument& operator=(const nsDocument& aOther);
nsCOMPtr<nsISupports> mXPathEvaluatorTearoff;
// The layout history state that should be used by nodes in this
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -244,17 +244,17 @@ nsFrameMessageManager::SendSyncMessage()
NS_ENSURE_SUCCESS(rv, rv);
JSAutoRequest ar(ctx);
PRUint32 len = retval.Length();
JSObject* dataArray = JS_NewArrayObject(ctx, len, NULL);
NS_ENSURE_TRUE(dataArray, NS_ERROR_OUT_OF_MEMORY);
for (PRUint32 i = 0; i < len; ++i) {
- if (!retval[i].Length())
+ if (retval[i].IsEmpty())
continue;
jsval ret = JSVAL_VOID;
if (!JS_ParseJSON(ctx, (jschar*)retval[i].get(),
(uint32)retval[i].Length(), &ret)) {
return NS_ERROR_UNEXPECTED;
}
NS_ENSURE_TRUE(JS_SetElement(ctx, dataArray, i, &ret), NS_ERROR_OUT_OF_MEMORY);
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -1122,36 +1122,16 @@ nsINode::DispatchDOMEvent(nsEvent* aEven
nsIDOMEvent* aDOMEvent,
nsPresContext* aPresContext,
nsEventStatus* aEventStatus)
{
return nsEventDispatcher::DispatchDOMEvent(this, aEvent, aDOMEvent,
aPresContext, aEventStatus);
}
-nsresult
-nsINode::AddEventListenerByIID(nsIDOMEventListener *aListener,
- const nsIID& aIID)
-{
- nsEventListenerManager* elm = GetListenerManager(PR_TRUE);
- NS_ENSURE_STATE(elm);
- return elm->AddEventListenerByIID(aListener, aIID, NS_EVENT_FLAG_BUBBLE);
-}
-
-nsresult
-nsINode::RemoveEventListenerByIID(nsIDOMEventListener *aListener,
- const nsIID& aIID)
-{
- nsEventListenerManager* elm = GetListenerManager(PR_FALSE);
- if (elm) {
- elm->RemoveEventListenerByIID(aListener, aIID, NS_EVENT_FLAG_BUBBLE);
- }
- return NS_OK;
-}
-
nsEventListenerManager*
nsINode::GetListenerManager(PRBool aCreateIfNotFound)
{
return nsContentUtils::GetListenerManager(this, aCreateIfNotFound);
}
nsIScriptContext*
nsINode::GetContextForEventHandlers(nsresult* aRv)
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -562,16 +562,17 @@ GK_ATOM(mediaType, "media-type")
GK_ATOM(member, "member")
GK_ATOM(menu, "menu")
GK_ATOM(menubar, "menubar")
GK_ATOM(menubutton, "menubutton")
GK_ATOM(menuButton, "menu-button")
GK_ATOM(menuitem, "menuitem")
GK_ATOM(menulist, "menulist")
GK_ATOM(menupopup, "menupopup")
+GK_ATOM(menuseparator, "menuseparator")
GK_ATOM(message, "message")
GK_ATOM(meta, "meta")
GK_ATOM(meter, "meter")
GK_ATOM(method, "method")
GK_ATOM(middle, "middle")
GK_ATOM(min, "min")
GK_ATOM(minheight, "minheight")
GK_ATOM(minimum_scale, "minimum-scale")
@@ -718,16 +719,17 @@ GK_ATOM(onpopupshown, "onpopupshown")
GK_ATOM(onreadystatechange, "onreadystatechange")
GK_ATOM(onRequest, "onRequest")
GK_ATOM(onreset, "onreset")
GK_ATOM(onMozBeforeResize, "onMozBeforeResize")
GK_ATOM(onresize, "onresize")
GK_ATOM(onscroll, "onscroll")
GK_ATOM(onselect, "onselect")
GK_ATOM(onset, "onset")
+GK_ATOM(onshow, "onshow")
GK_ATOM(onsubmit, "onsubmit")
GK_ATOM(ontext, "ontext")
GK_ATOM(ontouchstart, "ontouchstart")
GK_ATOM(ontouchend, "ontouchend")
GK_ATOM(ontouchmove, "ontouchmove")
GK_ATOM(ontouchenter, "ontouchenter")
GK_ATOM(ontouchleave, "ontouchleave")
GK_ATOM(ontouchcancel, "ontouchcancel")
--- a/content/base/src/nsWebSocket.cpp
+++ b/content/base/src/nsWebSocket.cpp
@@ -377,16 +377,18 @@ nsWebSocketEstablishedConnection::Close(
return NS_OK;
// Disconnect() can release this object, so we keep a
// reference until the end of the method
nsRefPtr<nsWebSocketEstablishedConnection> kungfuDeathGrip = this;
if (mOwner->mReadyState == nsIMozWebSocket::CONNECTING) {
mOwner->SetReadyState(nsIMozWebSocket::CLOSED);
+ mWebSocketChannel->Close(mOwner->mClientReasonCode,
+ mOwner->mClientReason);
Disconnect();
return NS_OK;
}
mOwner->SetReadyState(nsIMozWebSocket::CLOSING);
if (mStatus == CONN_CLOSED) {
mOwner->SetReadyState(nsIMozWebSocket::CLOSED);
@@ -1489,17 +1491,17 @@ nsWebSocketEstablishedConnection::IsPend
NS_IMETHODIMP
nsWebSocketEstablishedConnection::GetStatus(nsresult *aStatus)
{
*aStatus = NS_OK;
return NS_OK;
}
-// probably means window went away or stop button pressed
+// Window closed, stop/reload button pressed, user navigated away from page, etc.
NS_IMETHODIMP
nsWebSocketEstablishedConnection::Cancel(nsresult aStatus)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
if (!mOwner) {
return NS_OK;
}
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -496,16 +496,18 @@ include $(topsrcdir)/config/rules.mk
accesscontrol.resource^headers^ \
invalid_accesscontrol.resource \
invalid_accesscontrol.resource^headers^ \
somedatas.resource \
somedatas.resource^headers^ \
delayedServerEvents.sjs \
test_bug664916.html \
test_bug666604.html \
+ test_bug675121.html \
+ file_bug675121.sjs \
$(NULL)
_CHROME_FILES = \
test_bug357450.js \
$(NULL)
# This test fails on the Mac for some reason
ifneq (,$(filter gtk2 windows,$(MOZ_WIDGET_TOOLKIT)))
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_bug675121.sjs
@@ -0,0 +1,15 @@
+var timer;
+
+function handleRequest(request, response)
+{
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "text/plain", false);
+ response.write("Responded");
+ response.processAsync();
+ timer = Components.classes["@mozilla.org/timer;1"]
+ .createInstance(Components.interfaces.nsITimer);
+ timer.initWithCallback(function() {
+ response.finish();
+ // 50ms certainly be enough for one refresh driver firing to happen!
+ }, 50, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
+}
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug675121.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=675121
+-->
+<head>
+ <title>Test for Bug 675121</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <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=675121">Mozilla Bug 675121</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 675121 **/
+var callbackFired = false;
+var xhrInProgress = false;
+function f() {
+ callbackFired = true;
+ if (!xhrInProgress) {
+ SimpleTest.finish();
+ }
+}
+
+window.mozRequestAnimationFrame(f);
+var xhr = new XMLHttpRequest();
+xhr.open("GET", "file_bug675121.sjs", false);
+xhrInProgress = true;
+xhr.send();
+xhrInProgress = false;
+is(xhr.responseText, "Responded", "Should have a response by now");
+is(callbackFired, false, "Callback should not fire during sync XHR");
+
+if (!callbackFired) {
+ SimpleTest.waitForExplicitFinish();
+}
+</script>
+</pre>
+</body>
+</html>
--- a/content/canvas/src/CanvasUtils.h
+++ b/content/canvas/src/CanvasUtils.h
@@ -157,17 +157,17 @@ JSValToDashArray(JSContext* cx, const js
// Not an array-like thing
return NS_ERROR_INVALID_ARG;
} else if (length > MAX_NUM_DASHES) {
// Too many dashes in the pattern
return NS_ERROR_ILLEGAL_VALUE;
}
bool haveNonzeroElement = false;
- for (jsint i = 0; i < jsint(length); ++i) {
+ for (uint32 i = 0; i < length; ++i) {
jsval elt;
double d;
if (!JS_GetElement(cx, obj, i, &elt)) {
return NS_ERROR_FAILURE;
}
if (!(CoerceDouble(elt, &d) &&
FloatValidate(d) &&
d >= 0.0)) {
--- a/content/events/public/Makefile.in
+++ b/content/events/public/Makefile.in
@@ -48,16 +48,17 @@ XPIDL_MODULE = content_events
EXPORTS = \
nsMutationEvent.h \
nsIPrivateDOMEvent.h \
nsIPrivateTextEvent.h \
nsIPrivateTextRange.h \
nsPLDOMEvent.h \
nsEventDispatcher.h \
nsEventStates.h \
+ nsEventNameList.h \
$(NULL)
XPIDLSRCS = \
nsIEventListenerService.idl \
$(NULL)
include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/content/events/public/nsEventNameList.h
@@ -0,0 +1,751 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Boris Zbarsky <bzbarsky@mit.edu>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * This file contains the list of event names that are exposed via IDL
+ * on various objects. It is designed to be used as inline input to
+ * various consumers through the magic of C preprocessing.
+ *
+ * Each entry consists of 4 pieces of information:
+ * 1) The name of the event
+ * 2) The event ID (see nsGUIEvent.h)
+ * 3) The event type (see the EventNameType enum in nsContentUtils.h)
+ * 4) The event struct type for this event.
+ * Items 2-4 might be empty strings for events for which they don't make sense.
+ *
+ * Event names that are exposed as content attributes on HTML elements
+ * and as IDL attributes on Elements, Documents and Windows and have
+ * no forwarding behavior should be enclosed in the EVENT macro.
+ *
+ * Event names that are exposed as content attributes on HTML elements
+ * and as IDL attributes on Elements, Documents and Windows and are
+ * forwarded from <body> and <frameset> to the Window should be
+ * enclosed in the FORWARDED_EVENT macro. If this macro is not
+ * defined, it will be defined to be equivalent to EVENT.
+ *
+ * Event names that are exposed as IDL attributes on Windows only
+ * should be enclosed in the WINDOW_ONLY_EVENT macro. If this macro
+ * is not defined, it will be defined to the empty string.
+ *
+ * Event names that are exposed as content and IDL attributes on
+ * <body> and <frameset>, which forward them to the Window, and are
+ * exposed as IDL attributes on the Window should be enclosed in the
+ * WINDOW_EVENT macro. If this macro is not defined, it will be
+ * defined to be equivalent to WINDOW_ONLY_EVENT.
+ *
+ * Touch-specific event names should be enclosed in TOUCH_EVENT. They
+ * are otherwise equivalent to those enclosed in EVENT. If
+ * TOUCH_EVENT is not defined, it will be defined to the empty string.
+ *
+ * Event names that are not exposed as IDL attributes at all should be
+ * enclosed in NON_IDL_EVENT. If NON_IDL_EVENT is not defined, it
+ * will be defined to the empty string.
+ */
+
+#ifdef DEFINED_FORWARDED_EVENT
+#error "Don't define DEFINED_FORWARDED_EVENT"
+#endif /* DEFINED_FORWARDED_EVENT */
+
+#ifndef FORWARDED_EVENT
+#define FORWARDED_EVENT EVENT
+#define DEFINED_FORWARDED_EVENT
+#endif /* FORWARDED_EVENT */
+
+#ifdef DEFINED_WINDOW_ONLY_EVENT
+#error "Don't define DEFINED_WINDOW_ONLY_EVENT"
+#endif /* DEFINED_WINDOW_ONLY_EVENT */
+
+#ifndef WINDOW_ONLY_EVENT
+#define WINDOW_ONLY_EVENT(_name, _id, _type, _struct)
+#define DEFINED_WINDOW_ONLY_EVENT
+#endif /* WINDOW_ONLY_EVENT */
+
+#ifdef DEFINED_WINDOW_EVENT
+#error "Don't define DEFINED_WINDOW_EVENT"
+#endif /* DEFINED_WINDOW_EVENT */
+
+#ifndef WINDOW_EVENT
+#define WINDOW_EVENT WINDOW_ONLY_EVENT
+#define DEFINED_WINDOW_EVENT
+#endif /* WINDOW_EVENT */
+
+#ifdef DEFINED_TOUCH_EVENT
+#error "Don't define DEFINED_TOUCH_EVENT"
+#endif /* DEFINED_TOUCH_EVENT */
+
+#ifndef TOUCH_EVENT
+#define TOUCH_EVENT(_name, _id, _type, _struct)
+#define DEFINED_TOUCH_EVENT
+#endif /* TOUCH_EVENT */
+
+#ifdef DEFINED_NON_IDL_EVENT
+#error "Don't define DEFINED_NON_IDL_EVENT"
+#endif /* DEFINED_NON_IDL_EVENT */
+
+#ifndef NON_IDL_EVENT
+#define NON_IDL_EVENT(_name, _id, _type, _struct)
+#define DEFINED_NON_IDL_EVENT
+#endif /* NON_IDL_EVENT */
+
+EVENT(abort,
+ NS_IMAGE_ABORT,
+ (EventNameType_HTMLXUL | EventNameType_SVGSVG),
+ NS_EVENT)
+EVENT(canplay,
+ NS_CANPLAY,
+ EventNameType_HTML,
+ NS_EVENT_NULL)
+EVENT(canplaythrough,
+ NS_CANPLAYTHROUGH,
+ EventNameType_HTML,
+ NS_EVENT_NULL )
+EVENT(change,
+ NS_FORM_CHANGE,
+ EventNameType_HTMLXUL,
+ NS_EVENT )
+EVENT(click,
+ NS_MOUSE_CLICK,
+ EventNameType_All,
+ NS_MOUSE_EVENT)
+EVENT(contextmenu,
+ NS_CONTEXTMENU,
+ EventNameType_HTMLXUL,
+ NS_MOUSE_EVENT)
+// Not supported yet
+// EVENT(cuechange)
+EVENT(dblclick,
+ NS_MOUSE_DOUBLECLICK,
+ EventNameType_HTMLXUL,
+ NS_MOUSE_EVENT)
+EVENT(drag,
+ NS_DRAGDROP_DRAG,
+ EventNameType_HTMLXUL,
+ NS_DRAG_EVENT)
+EVENT(dragend,
+ NS_DRAGDROP_END,
+ EventNameType_HTMLXUL,
+ NS_DRAG_EVENT)
+EVENT(dragenter,
+ NS_DRAGDROP_ENTER,
+ EventNameType_HTMLXUL,
+ NS_DRAG_EVENT)
+EVENT(dragleave,
+ NS_DRAGDROP_LEAVE_SYNTH,
+ EventNameType_HTMLXUL,
+ NS_DRAG_EVENT)
+EVENT(dragover,
+ NS_DRAGDROP_OVER_SYNTH,
+ EventNameType_HTMLXUL,
+ NS_DRAG_EVENT)
+EVENT(dragstart,
+ NS_DRAGDROP_START,
+ EventNameType_HTMLXUL,
+ NS_DRAG_EVENT)
+EVENT(drop,
+ NS_DRAGDROP_DROP,
+ EventNameType_HTMLXUL,
+ NS_DRAG_EVENT)
+EVENT(durationchange,
+ NS_DURATIONCHANGE,
+ EventNameType_HTML,
+ NS_EVENT_NULL)
+EVENT(emptied,
+ NS_EMPTIED,
+ EventNameType_HTML,
+ NS_EVENT_NULL)
+EVENT(ended,
+ NS_ENDED,
+ EventNameType_HTML,
+ NS_EVENT_NULL)
+EVENT(input,
+ NS_FORM_INPUT,
+ EventNameType_HTMLXUL,
+ NS_UI_EVENT)
+EVENT(invalid,
+ NS_FORM_INVALID,
+ EventNameType_HTMLXUL,
+ NS_EVENT)
+EVENT(keydown,
+ NS_KEY_DOWN,
+ EventNameType_HTMLXUL,
+ NS_KEY_EVENT)
+EVENT(keypress,
+ NS_KEY_PRESS,
+ EventNameType_HTMLXUL,
+ NS_KEY_EVENT)
+EVENT(keyup,
+ NS_KEY_UP,
+ EventNameType_HTMLXUL,
+ NS_KEY_EVENT)
+EVENT(loadeddata,
+ NS_LOADEDDATA,
+ EventNameType_HTML,
+ NS_EVENT_NULL)
+EVENT(loadedmetadata,
+ NS_LOADEDMETADATA,
+ EventNameType_HTML,
+ NS_EVENT_NULL)
+EVENT(loadstart,
+ NS_LOADSTART,
+ EventNameType_HTML,
+ NS_EVENT_NULL)
+EVENT(mousedown,
+ NS_MOUSE_BUTTON_DOWN,
+ EventNameType_All,
+ NS_MOUSE_EVENT)
+EVENT(mousemove,
+ NS_MOUSE_MOVE,
+ EventNameType_All,
+ NS_MOUSE_EVENT)
+EVENT(mouseout,
+ NS_MOUSE_EXIT_SYNTH,
+ EventNameType_All,
+ NS_MOUSE_EVENT)
+EVENT(mouseover,
+ NS_MOUSE_ENTER_SYNTH,
+ EventNameType_All,
+ NS_MOUSE_EVENT)
+EVENT(mouseup,
+ NS_MOUSE_BUTTON_UP,
+ EventNameType_All,
+ NS_MOUSE_EVENT)
+// Not supported yet; probably never because "wheel" is a better idea.
+// EVENT(mousewheel)
+EVENT(pause,
+ NS_PAUSE,
+ EventNameType_HTML,
+ NS_EVENT_NULL)
+EVENT(play,
+ NS_PLAY,
+ EventNameType_HTML,
+ NS_EVENT_NULL)
+EVENT(playing,
+ NS_PLAYING,
+ EventNameType_HTML,
+ NS_EVENT_NULL)
+EVENT(progress,
+ NS_PROGRESS,
+ EventNameType_HTML,
+ NS_EVENT_NULL)
+EVENT(ratechange,
+ NS_RATECHANGE,
+ EventNameType_HTML,
+ NS_EVENT_NULL)
+EVENT(readystatechange,
+ NS_READYSTATECHANGE,
+ EventNameType_HTMLXUL,
+ NS_EVENT_NULL)
+EVENT(reset,
+ NS_FORM_RESET,
+ EventNameType_HTMLXUL,
+ NS_EVENT)
+EVENT(seeked,
+ NS_SEEKED,
+ EventNameType_HTML,
+ NS_EVENT_NULL)
+EVENT(seeking,
+ NS_SEEKING,
+ EventNameType_HTML,
+ NS_EVENT_NULL)
+EVENT(select,
+ NS_FORM_SELECTED,
+ EventNameType_HTMLXUL,
+ NS_EVENT)
+EVENT(show,
+ NS_SHOW_EVENT,
+ EventNameType_HTML,
+ NS_EVENT)
+EVENT(stalled,
+ NS_STALLED,
+ EventNameType_HTML,
+ NS_EVENT_NULL)
+EVENT(submit,
+ NS_FORM_SUBMIT,
+ EventNameType_HTMLXUL,
+ NS_EVENT)
+EVENT(suspend,
+ NS_SUSPEND,
+ EventNameType_HTML,
+ NS_EVENT_NULL)
+EVENT(timeupdate,
+ NS_TIMEUPDATE,
+ EventNameType_HTML,
+ NS_EVENT_NULL)
+EVENT(volumechange,
+ NS_VOLUMECHANGE,
+ EventNameType_HTML,
+ NS_EVENT_NULL)
+EVENT(waiting,
+ NS_WAITING,
+ EventNameType_HTML,
+ NS_EVENT_NULL)
+// Gecko-specific extensions that apply to elements
+EVENT(copy,
+ NS_COPY,
+ EventNameType_HTMLXUL,
+ NS_EVENT)
+EVENT(cut,
+ NS_CUT,
+ EventNameType_HTMLXUL,
+ NS_EVENT)
+EVENT(paste,
+ NS_PASTE,
+ EventNameType_HTMLXUL,
+ NS_EVENT)
+EVENT(beforescriptexecute,
+ NS_BEFORE_SCRIPT_EXECUTE,
+ EventNameType_HTMLXUL,
+ NS_EVENT)
+EVENT(afterscriptexecute,
+ NS_AFTER_SCRIPT_EXECUTE,
+ EventNameType_HTMLXUL,
+ NS_EVENT)
+
+FORWARDED_EVENT(blur,
+ NS_BLUR_CONTENT,
+ EventNameType_HTMLXUL,
+ NS_FOCUS_EVENT)
+FORWARDED_EVENT(error,
+ NS_LOAD_ERROR,
+ (EventNameType_HTMLXUL | EventNameType_SVGSVG),
+ NS_EVENT)
+FORWARDED_EVENT(focus,
+ NS_FOCUS_CONTENT,
+ EventNameType_HTMLXUL,
+ NS_FOCUS_EVENT)
+FORWARDED_EVENT(load,
+ NS_LOAD,
+ EventNameType_All,
+ NS_EVENT)
+FORWARDED_EVENT(scroll,
+ NS_SCROLL_EVENT,
+ (EventNameType_HTMLXUL | EventNameType_SVGSVG),
+ NS_EVENT_NULL)
+
+WINDOW_EVENT(afterprint,
+ NS_AFTERPRINT,
+ EventNameType_HTMLXUL,
+ NS_EVENT)
+WINDOW_EVENT(beforeprint,
+ NS_BEFOREPRINT,
+ EventNameType_HTMLXUL,
+ NS_EVENT)
+WINDOW_EVENT(beforeunload,
+ NS_BEFORE_PAGE_UNLOAD,
+ EventNameType_HTMLXUL,
+ NS_EVENT)
+WINDOW_EVENT(hashchange,
+ NS_HASHCHANGE,
+ EventNameType_HTMLXUL,
+ NS_EVENT)
+WINDOW_EVENT(message,
+ NS_MESSAGE,
+ EventNameType_None,
+ NS_EVENT)
+WINDOW_EVENT(offline,
+ NS_OFFLINE,
+ EventNameType_HTMLXUL,
+ NS_EVENT)
+WINDOW_EVENT(online,
+ NS_ONLINE,
+ EventNameType_HTMLXUL,
+ NS_EVENT)
+WINDOW_EVENT(pagehide,
+ NS_PAGE_HIDE,
+ EventNameType_HTML,
+ NS_EVENT)
+WINDOW_EVENT(pageshow,
+ NS_PAGE_SHOW,
+ EventNameType_HTML,
+ NS_EVENT)
+WINDOW_EVENT(popstate,
+ NS_POPSTATE,
+ EventNameType_HTMLXUL,
+ NS_EVENT_NULL)
+// Not supported yet
+// WINDOW_EVENT(redo)
+WINDOW_EVENT(resize,
+ NS_RESIZE_EVENT,
+ (EventNameType_HTMLXUL | EventNameType_SVGSVG),
+ NS_EVENT)
+// Not supported yet
+// WINDOW_EVENT(storage)
+// Not supported yet
+// WINDOW_EVENT(undo)
+WINDOW_EVENT(unload,
+ NS_PAGE_UNLOAD,
+ (EventNameType_HTMLXUL | EventNameType_SVGSVG),
+ NS_EVENT)
+
+WINDOW_ONLY_EVENT(devicemotion,
+ NS_DEVICE_MOTION,
+ EventNameType_None,
+ NS_EVENT)
+WINDOW_ONLY_EVENT(deviceorientation,
+ NS_DEVICE_ORIENTATION,
+ EventNameType_None,
+ NS_EVENT)
+
+TOUCH_EVENT(touchstart,
+ NS_USER_DEFINED_EVENT,
+ EventNameType_All,
+ NS_INPUT_EVENT)
+TOUCH_EVENT(touchend,
+ NS_USER_DEFINED_EVENT,
+ EventNameType_All,
+ NS_INPUT_EVENT)
+TOUCH_EVENT(touchmove,
+ NS_USER_DEFINED_EVENT,
+ EventNameType_All,
+ NS_INPUT_EVENT )
+TOUCH_EVENT(touchenter,
+ NS_USER_DEFINED_EVENT,
+ EventNameType_All,
+ NS_INPUT_EVENT )
+TOUCH_EVENT(touchleave,
+ NS_USER_DEFINED_EVENT,
+ EventNameType_All,
+ NS_INPUT_EVENT)
+TOUCH_EVENT(touchcancel,
+ NS_USER_DEFINED_EVENT,
+ EventNameType_All,
+ NS_INPUT_EVENT)
+
+NON_IDL_EVENT(MozMouseHittest,
+ NS_MOUSE_MOZHITTEST,
+ EventNameType_None,
+ NS_MOUSE_EVENT)
+
+NON_IDL_EVENT(DOMAttrModified,
+ NS_MUTATION_ATTRMODIFIED,
+ EventNameType_HTMLXUL,
+ NS_MUTATION_EVENT)
+NON_IDL_EVENT(DOMCharacterDataModified,
+ NS_MUTATION_CHARACTERDATAMODIFIED,
+ EventNameType_HTMLXUL,
+ NS_MUTATION_EVENT)
+NON_IDL_EVENT(DOMNodeInserted,
+ NS_MUTATION_NODEINSERTED,
+ EventNameType_HTMLXUL,
+ NS_MUTATION_EVENT)
+NON_IDL_EVENT(DOMNodeRemoved,
+ NS_MUTATION_NODEREMOVED,
+ EventNameType_HTMLXUL,
+ NS_MUTATION_EVENT)
+NON_IDL_EVENT(DOMNodeInsertedIntoDocument,
+ NS_MUTATION_NODEINSERTEDINTODOCUMENT,
+ EventNameType_HTMLXUL,
+ NS_MUTATION_EVENT)
+NON_IDL_EVENT(DOMNodeRemovedFromDocument,
+ NS_MUTATION_NODEREMOVEDFROMDOCUMENT,
+ EventNameType_HTMLXUL,
+ NS_MUTATION_EVENT)
+NON_IDL_EVENT(DOMSubtreeModified,
+ NS_MUTATION_SUBTREEMODIFIED,
+ EventNameType_HTMLXUL,
+ NS_MUTATION_EVENT)
+
+NON_IDL_EVENT(DOMActivate,
+ NS_UI_ACTIVATE,
+ EventNameType_HTMLXUL,
+ NS_UI_EVENT)
+NON_IDL_EVENT(DOMFocusIn,
+ NS_UI_FOCUSIN,
+ EventNameType_HTMLXUL,
+ NS_UI_EVENT)
+NON_IDL_EVENT(DOMFocusOut,
+ NS_UI_FOCUSOUT,
+ EventNameType_HTMLXUL,
+ NS_UI_EVENT)
+
+NON_IDL_EVENT(DOMMouseScroll,
+ NS_MOUSE_SCROLL,
+ EventNameType_HTMLXUL,
+ NS_MOUSE_SCROLL_EVENT)
+NON_IDL_EVENT(MozMousePixelScroll,
+ NS_MOUSE_PIXEL_SCROLL,
+ EventNameType_HTMLXUL,
+ NS_MOUSE_SCROLL_EVENT)
+
+NON_IDL_EVENT(MozBeforeResize,
+ NS_BEFORERESIZE_EVENT,
+ EventNameType_None,
+ NS_EVENT)
+NON_IDL_EVENT(open,
+ NS_OPEN,
+ EventNameType_None,
+ NS_EVENT)
+
+// Events that only have on* attributes on XUL elements
+NON_IDL_EVENT(text,
+ NS_TEXT_TEXT,
+ EventNameType_XUL,
+ NS_EVENT_NULL)
+NON_IDL_EVENT(compositionstart,
+ NS_COMPOSITION_START,
+ EventNameType_XUL,
+ NS_COMPOSITION_EVENT)
+NON_IDL_EVENT(compositionend,
+ NS_COMPOSITION_END,
+ EventNameType_XUL,
+ NS_COMPOSITION_EVENT)
+NON_IDL_EVENT(command,
+ NS_XUL_COMMAND,
+ EventNameType_XUL,
+ NS_INPUT_EVENT)
+NON_IDL_EVENT(close,
+ NS_XUL_CLOSE,
+ EventNameType_XUL,
+ NS_EVENT_NULL)
+NON_IDL_EVENT(popupshowing,
+ NS_XUL_POPUP_SHOWING,
+ EventNameType_XUL,
+ NS_EVENT_NULL)
+NON_IDL_EVENT(popupshown,
+ NS_XUL_POPUP_SHOWN,
+ EventNameType_XUL,
+ NS_EVENT_NULL)
+NON_IDL_EVENT(popuphiding,
+ NS_XUL_POPUP_HIDING,
+ EventNameType_XUL,
+ NS_EVENT_NULL)
+NON_IDL_EVENT(popuphidden,
+ NS_XUL_POPUP_HIDDEN,
+ EventNameType_XUL,
+ NS_EVENT_NULL)
+NON_IDL_EVENT(broadcast,
+ NS_XUL_BROADCAST,
+ EventNameType_XUL,
+ NS_EVENT_NULL)
+NON_IDL_EVENT(commandupdate,
+ NS_XUL_COMMAND_UPDATE,
+ EventNameType_XUL,
+ NS_EVENT_NULL)
+NON_IDL_EVENT(dragexit,
+ NS_DRAGDROP_EXIT_SYNTH,
+ EventNameType_XUL,
+ NS_DRAG_EVENT)
+NON_IDL_EVENT(dragdrop,
+ NS_DRAGDROP_DRAGDROP,
+ EventNameType_XUL,
+ NS_DRAG_EVENT)
+NON_IDL_EVENT(draggesture,
+ NS_DRAGDROP_GESTURE,
+ EventNameType_XUL,
+ NS_DRAG_EVENT)
+NON_IDL_EVENT(overflow,
+ NS_SCROLLPORT_OVERFLOW,
+ EventNameType_XUL,
+ NS_EVENT_NULL)
+NON_IDL_EVENT(underflow,
+ NS_SCROLLPORT_UNDERFLOW,
+ EventNameType_XUL,
+ NS_EVENT_NULL)
+
+// Various SVG events
+NON_IDL_EVENT(SVGLoad,
+ NS_SVG_LOAD,
+ EventNameType_None,
+ NS_SVG_EVENT)
+NON_IDL_EVENT(SVGUnload,
+ NS_SVG_UNLOAD,
+ EventNameType_None,
+ NS_SVG_EVENT)
+NON_IDL_EVENT(SVGAbort,
+ NS_SVG_ABORT,
+ EventNameType_None,
+ NS_SVG_EVENT)
+NON_IDL_EVENT(SVGError,
+ NS_SVG_ERROR,
+ EventNameType_None,
+ NS_SVG_EVENT)
+NON_IDL_EVENT(SVGResize,
+ NS_SVG_RESIZE,
+ EventNameType_None,
+ NS_SVG_EVENT)
+NON_IDL_EVENT(SVGScroll,
+ NS_SVG_SCROLL,
+ EventNameType_None,
+ NS_SVG_EVENT)
+
+NON_IDL_EVENT(SVGZoom,
+ NS_SVG_ZOOM,
+ EventNameType_None,
+ NS_SVGZOOM_EVENT)
+// This is a bit hackish, but SVG's event names are weird.
+NON_IDL_EVENT(zoom,
+ NS_SVG_ZOOM,
+ EventNameType_SVGSVG,
+ NS_EVENT_NULL)
+#ifdef MOZ_SMIL
+NON_IDL_EVENT(begin,
+ NS_SMIL_BEGIN,
+ EventNameType_SMIL,
+ NS_EVENT_NULL)
+NON_IDL_EVENT(beginEvent,
+ NS_SMIL_BEGIN,
+ EventNameType_None,
+ NS_SMIL_TIME_EVENT)
+NON_IDL_EVENT(end,
+ NS_SMIL_END,
+ EventNameType_SMIL,
+ NS_EVENT_NULL)
+NON_IDL_EVENT(endEvent,
+ NS_SMIL_END,
+ EventNameType_None,
+ NS_SMIL_TIME_EVENT)
+NON_IDL_EVENT(repeat,
+ NS_SMIL_REPEAT,
+ EventNameType_SMIL,
+ NS_EVENT_NULL)
+NON_IDL_EVENT(repeatEvent,
+ NS_SMIL_REPEAT,
+ EventNameType_None,
+ NS_SMIL_TIME_EVENT)
+#endif // MOZ_SMIL
+
+NON_IDL_EVENT(MozAudioAvailable,
+ NS_MOZAUDIOAVAILABLE,
+ EventNameType_None,
+ NS_EVENT_NULL)
+NON_IDL_EVENT(MozAfterPaint,
+ NS_AFTERPAINT,
+ EventNameType_None,
+ NS_EVENT)
+NON_IDL_EVENT(MozBeforePaint,
+ NS_BEFOREPAINT,
+ EventNameType_None,
+ NS_EVENT_NULL)
+
+NON_IDL_EVENT(MozScrolledAreaChanged,
+ NS_SCROLLEDAREACHANGED,
+ EventNameType_None,
+ NS_SCROLLAREA_EVENT)
+
+// Simple gesture events
+NON_IDL_EVENT(MozSwipeGesture,
+ NS_SIMPLE_GESTURE_SWIPE,
+ EventNameType_None,
+ NS_SIMPLE_GESTURE_EVENT)
+NON_IDL_EVENT(MozMagnifyGestureStart,
+ NS_SIMPLE_GESTURE_MAGNIFY_START,
+ EventNameType_None,
+ NS_SIMPLE_GESTURE_EVENT)
+NON_IDL_EVENT(MozMagnifyGestureUpdate,
+ NS_SIMPLE_GESTURE_MAGNIFY_UPDATE,
+ EventNameType_None,
+ NS_SIMPLE_GESTURE_EVENT)
+NON_IDL_EVENT(MozMagnifyGesture,
+ NS_SIMPLE_GESTURE_MAGNIFY,
+ EventNameType_None,
+ NS_SIMPLE_GESTURE_EVENT)
+NON_IDL_EVENT(MozRotateGestureStart,
+ NS_SIMPLE_GESTURE_ROTATE_START,
+ EventNameType_None,
+ NS_SIMPLE_GESTURE_EVENT)
+NON_IDL_EVENT(MozRotateGestureUpdate,
+ NS_SIMPLE_GESTURE_ROTATE_UPDATE,
+ EventNameType_None,
+ NS_SIMPLE_GESTURE_EVENT)
+NON_IDL_EVENT(MozRotateGesture,
+ NS_SIMPLE_GESTURE_ROTATE,
+ EventNameType_None,
+ NS_SIMPLE_GESTURE_EVENT)
+NON_IDL_EVENT(MozTapGesture,
+ NS_SIMPLE_GESTURE_TAP,
+ EventNameType_None,
+ NS_SIMPLE_GESTURE_EVENT)
+NON_IDL_EVENT(MozPressTapGesture,
+ NS_SIMPLE_GESTURE_PRESSTAP,
+ EventNameType_None,
+ NS_SIMPLE_GESTURE_EVENT)
+
+NON_IDL_EVENT(MozTouchDown,
+ NS_MOZTOUCH_DOWN,
+ EventNameType_None,
+ NS_MOZTOUCH_EVENT)
+NON_IDL_EVENT(MozTouchMove,
+ NS_MOZTOUCH_MOVE,
+ EventNameType_None,
+ NS_MOZTOUCH_EVENT)
+NON_IDL_EVENT(MozTouchUp,
+ NS_MOZTOUCH_UP,
+ EventNameType_None,
+ NS_MOZTOUCH_EVENT)
+
+NON_IDL_EVENT(transitionend,
+ NS_TRANSITION_END,
+ EventNameType_None,
+ NS_TRANSITION_EVENT)
+NON_IDL_EVENT(animationstart,
+ NS_ANIMATION_START,
+ EventNameType_None,
+ NS_ANIMATION_EVENT)
+NON_IDL_EVENT(animationend,
+ NS_ANIMATION_END,
+ EventNameType_None,
+ NS_ANIMATION_EVENT)
+NON_IDL_EVENT(animationiteration,
+ NS_ANIMATION_ITERATION,
+ EventNameType_None,
+ NS_ANIMATION_EVENT)
+
+#ifdef DEFINED_FORWARDED_EVENT
+#undef DEFINED_FORWARDED_EVENT
+#undef FORWARDED_EVENT
+#endif /* DEFINED_FORWARDED_EVENT */
+
+#ifdef DEFINED_WINDOW_EVENT
+#undef DEFINED_WINDOW_EVENT
+#undef WINDOW_EVENT
+#endif /* DEFINED_WINDOW_EVENT */
+
+#ifdef DEFINED_WINDOW_ONLY_EVENT
+#undef DEFINED_WINDOW_ONLY_EVENT
+#undef WINDOW_ONLY_EVENT
+#endif /* DEFINED_WINDOW_ONLY_EVENT */
+
+#ifdef DEFINED_TOUCH_EVENT
+#undef DEFINED_TOUCH_EVENT
+#undef TOUCH_EVENT
+#endif /* DEFINED_TOUCH_EVENT */
+
+#ifdef DEFINED_NON_IDL_EVENT
+#undef DEFINED_NON_IDL_EVENT
+#undef NON_IDL_EVENT
+#endif /* DEFINED_NON_IDL_EVENT */
+
--- a/content/events/src/nsDOMEvent.cpp
+++ b/content/events/src/nsDOMEvent.cpp
@@ -72,17 +72,17 @@ static const char* const sEventNames[] =
"dragenter", "dragover", "dragexit", "dragdrop", "draggesture",
"drag", "dragend", "dragstart", "dragleave", "drop", "resize",
"scroll", "overflow", "underflow", "overflowchanged",
"DOMSubtreeModified", "DOMNodeInserted", "DOMNodeRemoved",
"DOMNodeRemovedFromDocument", "DOMNodeInsertedIntoDocument",
"DOMAttrModified", "DOMCharacterDataModified",
"DOMActivate", "DOMFocusIn", "DOMFocusOut",
"pageshow", "pagehide", "DOMMouseScroll", "MozMousePixelScroll",
- "offline", "online", "copy", "cut", "paste", "open", "message",
+ "offline", "online", "copy", "cut", "paste", "open", "message", "show",
"SVGLoad", "SVGUnload", "SVGAbort", "SVGError", "SVGResize", "SVGScroll",
"SVGZoom",
#ifdef MOZ_SMIL
"beginEvent", "endEvent", "repeatEvent",
#endif // MOZ_SMIL
#ifdef MOZ_MEDIA
"loadstart", "progress", "suspend", "emptied", "stalled", "play", "pause",
"loadedmetadata", "loadeddata", "waiting", "playing", "canplay",
@@ -1252,16 +1252,18 @@ const char* nsDOMEvent::GetEventName(PRU
case NS_CUT:
return sEventNames[eDOMEvents_cut];
case NS_PASTE:
return sEventNames[eDOMEvents_paste];
case NS_OPEN:
return sEventNames[eDOMEvents_open];
case NS_MESSAGE:
return sEventNames[eDOMEvents_message];
+ case NS_SHOW_EVENT:
+ return sEventNames[eDOMEvents_show];
case NS_SVG_LOAD:
return sEventNames[eDOMEvents_SVGLoad];
case NS_SVG_UNLOAD:
return sEventNames[eDOMEvents_SVGUnload];
case NS_SVG_ABORT:
return sEventNames[eDOMEvents_SVGAbort];
case NS_SVG_ERROR:
return sEventNames[eDOMEvents_SVGError];
--- a/content/events/src/nsDOMEvent.h
+++ b/content/events/src/nsDOMEvent.h
@@ -133,16 +133,17 @@ public:
eDOMEvents_MozMousePixelScroll,
eDOMEvents_offline,
eDOMEvents_online,
eDOMEvents_copy,
eDOMEvents_cut,
eDOMEvents_paste,
eDOMEvents_open,
eDOMEvents_message,
+ eDOMEvents_show,
eDOMEvents_SVGLoad,
eDOMEvents_SVGUnload,
eDOMEvents_SVGAbort,
eDOMEvents_SVGError,
eDOMEvents_SVGResize,
eDOMEvents_SVGScroll,
eDOMEvents_SVGZoom,
#ifdef MOZ_SMIL
--- a/content/events/src/nsDOMEventTargetHelper.cpp
+++ b/content/events/src/nsDOMEventTargetHelper.cpp
@@ -201,36 +201,16 @@ nsDOMEventTargetHelper::GetListenerManag
{
if (!mListenerManager && aCreateIfNotFound) {
mListenerManager = new nsEventListenerManager(this);
}
return mListenerManager;
}
-nsresult
-nsDOMEventTargetHelper::AddEventListenerByIID(nsIDOMEventListener *aListener,
- const nsIID& aIID)
-{
- nsEventListenerManager* elm = GetListenerManager(PR_TRUE);
- NS_ENSURE_STATE(elm);
- return elm->AddEventListenerByIID(aListener, aIID, NS_EVENT_FLAG_BUBBLE);
-}
-
-nsresult
-nsDOMEventTargetHelper::RemoveEventListenerByIID(nsIDOMEventListener *aListener,
- const nsIID& aIID)
-{
- nsEventListenerManager* elm = GetListenerManager(PR_FALSE);
- if (elm) {
- elm->RemoveEventListenerByIID(aListener, aIID, NS_EVENT_FLAG_BUBBLE);
- }
- return NS_OK;
-}
-
nsIScriptContext*
nsDOMEventTargetHelper::GetContextForEventHandlers(nsresult* aRv)
{
*aRv = CheckInnerWindowCorrectness();
if (NS_FAILED(*aRv)) {
return nsnull;
}
return mScriptContext;
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -37,26 +37,16 @@
#include "nsISupports.h"
#include "nsGUIEvent.h"
#include "nsDOMEvent.h"
#include "nsEventListenerManager.h"
#include "nsCaret.h"
#include "nsIDOMNSEvent.h"
#include "nsIDOMEventListener.h"
-#include "nsIDOMMouseListener.h"
-#include "nsIDOMMouseMotionListener.h"
-#include "nsIDOMContextMenuListener.h"
-#include "nsIDOMKeyListener.h"
-#include "nsIDOMFocusListener.h"
-#include "nsIDOMFormListener.h"
-#include "nsIDOMLoadListener.h"
-#include "nsIDOMTextListener.h"
-#include "nsIDOMCompositionListener.h"
-#include "nsIDOMUIListener.h"
#include "nsITextControlFrame.h"
#include "nsGkAtoms.h"
#include "nsPIDOMWindow.h"
#include "nsIPrivateDOMEvent.h"
#include "nsIJSEventListener.h"
#include "prmem.h"
#include "nsIScriptGlobalObject.h"
#include "nsIScriptRuntime.h"
@@ -90,23 +80,19 @@
#include "nsCOMArray.h"
#include "nsEventListenerService.h"
#include "nsDOMEvent.h"
#include "nsIContentSecurityPolicy.h"
using namespace mozilla::dom;
#define EVENT_TYPE_EQUALS( ls, type, userType ) \
- (ls->mEventType && ls->mEventType == type && \
+ (ls->mEventType == type && \
(ls->mEventType != NS_USER_DEFINED_EVENT || ls->mTypeAtom == userType))
-#define EVENT_TYPE_DATA_EQUALS( type1, type2 ) \
- (type1 && type2 && type1->iid && type2->iid && \
- type1->iid->Equals(*(type2->iid)))
-
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
static const PRUint32 kAllMutationBits =
NS_EVENT_BITS_MUTATION_SUBTREEMODIFIED |
NS_EVENT_BITS_MUTATION_NODEINSERTED |
NS_EVENT_BITS_MUTATION_NODEREMOVED |
NS_EVENT_BITS_MUTATION_NODEREMOVEDFROMDOCUMENT |
@@ -133,147 +119,16 @@ MutationBitForEventType(PRUint32 aEventT
case NS_MUTATION_CHARACTERDATAMODIFIED:
return NS_EVENT_BITS_MUTATION_CHARACTERDATAMODIFIED;
default:
break;
}
return 0;
}
-typedef
-NS_STDCALL_FUNCPROTO(nsresult,
- GenericHandler,
- nsIDOMEventListener, HandleEvent,
- (nsIDOMEvent*));
-
-/*
- * Things here are not as they appear. Namely, |ifaceListener| below is
- * not really a pointer to the nsIDOMEventListener interface, and aMethod is
- * not really a pointer-to-member for nsIDOMEventListener. They both
- * actually refer to the event-type-specific listener interface. The casting
- * magic allows us to use a single dispatch method. This relies on the
- * assumption that nsIDOMEventListener and the event type listener interfaces
- * have the same object layout and will therefore have compatible
- * pointer-to-member implementations.
- */
-
-static nsresult DispatchToInterface(nsIDOMEvent* aEvent,
- nsIDOMEventListener* aListener,
- GenericHandler aMethod,
- const nsIID& aIID)
-{
- nsIDOMEventListener* ifaceListener = nsnull;
- nsresult rv = NS_OK;
- aListener->QueryInterface(aIID, (void**) &ifaceListener);
- NS_WARN_IF_FALSE(ifaceListener,
- "DispatchToInterface couldn't QI to the right interface");
- if (ifaceListener) {
- rv = (ifaceListener->*aMethod)(aEvent);
- NS_RELEASE(ifaceListener);
- }
- return rv;
-}
-
-struct EventDispatchData
-{
- PRUint32 message;
- GenericHandler method;
-};
-
-struct EventTypeData
-{
- const EventDispatchData* events;
- int numEvents;
- const nsIID* iid;
-};
-
-#define HANDLER(x) reinterpret_cast<GenericHandler>(x)
-
-static const EventDispatchData sMouseEvents[] = {
- { NS_MOUSE_BUTTON_DOWN, HANDLER(&nsIDOMMouseListener::MouseDown) },
- { NS_MOUSE_BUTTON_UP, HANDLER(&nsIDOMMouseListener::MouseUp) },
- { NS_MOUSE_CLICK, HANDLER(&nsIDOMMouseListener::MouseClick) },
- { NS_MOUSE_DOUBLECLICK, HANDLER(&nsIDOMMouseListener::MouseDblClick) },
- { NS_MOUSE_ENTER_SYNTH, HANDLER(&nsIDOMMouseListener::MouseOver) },
- { NS_MOUSE_EXIT_SYNTH, HANDLER(&nsIDOMMouseListener::MouseOut) }
-};
-
-static const EventDispatchData sMouseMotionEvents[] = {
- { NS_MOUSE_MOVE, HANDLER(&nsIDOMMouseMotionListener::MouseMove) }
-};
-
-static const EventDispatchData sContextMenuEvents[] = {
- { NS_CONTEXTMENU, HANDLER(&nsIDOMContextMenuListener::ContextMenu) }
-};
-
-static const EventDispatchData sCompositionEvents[] = {
- { NS_COMPOSITION_START,
- HANDLER(&nsIDOMCompositionListener::HandleStartComposition) },
- { NS_COMPOSITION_END,
- HANDLER(&nsIDOMCompositionListener::HandleEndComposition) }
-};
-
-static const EventDispatchData sTextEvents[] = {
- { NS_TEXT_TEXT, HANDLER(&nsIDOMTextListener::HandleText) }
-};
-
-static const EventDispatchData sKeyEvents[] = {
- { NS_KEY_UP, HANDLER(&nsIDOMKeyListener::KeyUp) },
- { NS_KEY_DOWN, HANDLER(&nsIDOMKeyListener::KeyDown) },
- { NS_KEY_PRESS, HANDLER(&nsIDOMKeyListener::KeyPress) }
-};
-
-static const EventDispatchData sFocusEvents[] = {
- { NS_FOCUS_CONTENT, HANDLER(&nsIDOMFocusListener::Focus) },
- { NS_BLUR_CONTENT, HANDLER(&nsIDOMFocusListener::Blur) }
-};
-
-static const EventDispatchData sFormEvents[] = {
- { NS_FORM_SUBMIT, HANDLER(&nsIDOMFormListener::Submit) },
- { NS_FORM_RESET, HANDLER(&nsIDOMFormListener::Reset) },
- { NS_FORM_CHANGE, HANDLER(&nsIDOMFormListener::Change) },
- { NS_FORM_SELECTED, HANDLER(&nsIDOMFormListener::Select) },
- { NS_FORM_INPUT, HANDLER(&nsIDOMFormListener::Input) }
-};
-
-static const EventDispatchData sLoadEvents[] = {
- { NS_LOAD, HANDLER(&nsIDOMLoadListener::Load) },
- { NS_PAGE_UNLOAD, HANDLER(&nsIDOMLoadListener::Unload) },
- { NS_LOAD_ERROR, HANDLER(&nsIDOMLoadListener::Error) },
- { NS_BEFORE_PAGE_UNLOAD, HANDLER(&nsIDOMLoadListener::BeforeUnload) }
-};
-
-static const EventDispatchData sUIEvents[] = {
- { NS_UI_ACTIVATE, HANDLER(&nsIDOMUIListener::Activate) },
- { NS_UI_FOCUSIN, HANDLER(&nsIDOMUIListener::FocusIn) },
- { NS_UI_FOCUSOUT, HANDLER(&nsIDOMUIListener::FocusOut) }
-};
-
-#define IMPL_EVENTTYPEDATA(type) \
-{ \
- s##type##Events, \
- NS_ARRAY_LENGTH(s##type##Events), \
- &NS_GET_IID(nsIDOM##type##Listener) \
-}
-
-// IMPORTANT: indices match up with eEventArrayType_ enum values
-
-static const EventTypeData sEventTypes[] = {
- IMPL_EVENTTYPEDATA(Mouse),
- IMPL_EVENTTYPEDATA(MouseMotion),
- IMPL_EVENTTYPEDATA(ContextMenu),
- IMPL_EVENTTYPEDATA(Key),
- IMPL_EVENTTYPEDATA(Load),
- IMPL_EVENTTYPEDATA(Focus),
- IMPL_EVENTTYPEDATA(Form),
- IMPL_EVENTTYPEDATA(Text),
- IMPL_EVENTTYPEDATA(Composition),
- IMPL_EVENTTYPEDATA(UI)
-};
-
PRUint32 nsEventListenerManager::sCreatedCount = 0;
nsEventListenerManager::nsEventListenerManager(nsISupports* aTarget) :
mMayHavePaintEventListener(PR_FALSE),
mMayHaveMutationListeners(PR_FALSE),
mMayHaveCapturingListeners(PR_FALSE),
mMayHaveSystemGroupListeners(PR_FALSE),
mMayHaveAudioAvailableEventListener(PR_FALSE),
@@ -328,43 +183,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsEventListenerManager)
tmp->Disconnect();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-const EventTypeData*
-nsEventListenerManager::GetTypeDataForIID(const nsIID& aIID)
-{
- for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(sEventTypes); ++i) {
- if (aIID.Equals(*(sEventTypes[i].iid))) {
- return &sEventTypes[i];
- }
- }
- return nsnull;
-}
-
-const EventTypeData*
-nsEventListenerManager::GetTypeDataForEventName(nsIAtom* aName)
-{
- PRUint32 event = nsContentUtils::GetEventId(aName);
- if (event != NS_USER_DEFINED_EVENT) {
- for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(sEventTypes); ++i) {
- for (PRInt32 j = 0; j < sEventTypes[i].numEvents; ++j) {
- if (event == sEventTypes[i].events[j].message) {
- return &sEventTypes[i];
- }
- }
- }
- }
- return nsnull;
-}
-
nsPIDOMWindow*
nsEventListenerManager::GetInnerWindowForTarget()
{
nsCOMPtr<nsINode> node = do_QueryInterface(mTarget);
if (node) {
// XXX sXBL/XBL2 issue -- do we really want the owner here? What
// if that's the XBL document?
nsIDocument* document = node->GetOwnerDoc();
@@ -380,62 +208,42 @@ nsEventListenerManager::GetInnerWindowFo
return nsnull;
}
nsresult
nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener,
PRUint32 aType,
nsIAtom* aTypeAtom,
- const EventTypeData* aTypeData,
PRInt32 aFlags)
{
NS_ENSURE_TRUE(aListener, NS_ERROR_FAILURE);
- NS_ENSURE_TRUE(aType || aTypeData, NS_ERROR_FAILURE);
+ NS_ENSURE_TRUE(aType, NS_ERROR_FAILURE);
nsRefPtr<nsIDOMEventListener> kungFuDeathGrip = aListener;
- if (!aTypeData) {
- // If we don't have type data, we can try to QI listener to the right
- // interface and set mTypeData only if QI succeeds. This way we can save
- // calls to DispatchToInterface (in HandleEvent) in those cases when QI
- // would fail.
- // @see also DispatchToInterface()
- const EventTypeData* td = GetTypeDataForEventName(aTypeAtom);
- if (td && td->iid) {
- nsIDOMEventListener* ifaceListener = nsnull;
- aListener->QueryInterface(*(td->iid), (void**) &ifaceListener);
- if (ifaceListener) {
- aTypeData = td;
- NS_RELEASE(ifaceListener);
- }
- }
- }
-
nsListenerStruct* ls;
PRUint32 count = mListeners.Length();
for (PRUint32 i = 0; i < count; i++) {
ls = &mListeners.ElementAt(i);
if (ls->mListener == aListener && ls->mFlags == aFlags &&
- (EVENT_TYPE_EQUALS(ls, aType, aTypeAtom) ||
- EVENT_TYPE_DATA_EQUALS(aTypeData, ls->mTypeData))) {
+ EVENT_TYPE_EQUALS(ls, aType, aTypeAtom)) {
return NS_OK;
}
}
mNoListenerForEvent = NS_EVENT_TYPE_NULL;
mNoListenerForEventAtom = nsnull;
ls = mListeners.AppendElement();
ls->mListener = aListener;
ls->mEventType = aType;
ls->mTypeAtom = aTypeAtom;
ls->mFlags = aFlags;
ls->mHandlerIsString = PR_FALSE;
- ls->mTypeData = aTypeData;
if (aFlags & NS_EVENT_FLAG_SYSTEM_EVENT) {
mMayHaveSystemGroupListeners = PR_TRUE;
}
if (aFlags & NS_EVENT_FLAG_CAPTURE) {
mMayHaveCapturingListeners = PR_TRUE;
}
@@ -486,90 +294,69 @@ nsEventListenerManager::AddEventListener
return NS_OK;
}
void
nsEventListenerManager::RemoveEventListener(nsIDOMEventListener *aListener,
PRUint32 aType,
nsIAtom* aUserType,
- const EventTypeData* aTypeData,
PRInt32 aFlags)
{
- if (!aListener || !(aType || aTypeData)) {
+ if (!aListener || !aType) {
return;
}
nsListenerStruct* ls;
aFlags &= ~NS_PRIV_EVENT_UNTRUSTED_PERMITTED;
PRUint32 count = mListeners.Length();
for (PRUint32 i = 0; i < count; ++i) {
ls = &mListeners.ElementAt(i);
if (ls->mListener == aListener &&
((ls->mFlags & ~NS_PRIV_EVENT_UNTRUSTED_PERMITTED) == aFlags) &&
- (EVENT_TYPE_EQUALS(ls, aType, aUserType) ||
- (!(ls->mEventType) &&
- EVENT_TYPE_DATA_EQUALS(ls->mTypeData, aTypeData)))) {
+ EVENT_TYPE_EQUALS(ls, aType, aUserType)) {
nsRefPtr<nsEventListenerManager> kungFuDeathGrip = this;
mListeners.RemoveElementAt(i);
mNoListenerForEvent = NS_EVENT_TYPE_NULL;
mNoListenerForEventAtom = nsnull;
break;
}
}
}
-nsresult
-nsEventListenerManager::AddEventListenerByIID(nsIDOMEventListener *aListener,
- const nsIID& aIID,
- PRInt32 aFlags)
-{
- return AddEventListener(aListener, NS_EVENT_TYPE_NULL, nsnull,
- GetTypeDataForIID(aIID), aFlags);
-}
-
-void
-nsEventListenerManager::RemoveEventListenerByIID(nsIDOMEventListener *aListener,
- const nsIID& aIID,
- PRInt32 aFlags)
+static inline PRBool
+ListenerCanHandle(nsListenerStruct* aLs, nsEvent* aEvent)
{
- RemoveEventListener(aListener, NS_EVENT_TYPE_NULL, nsnull,
- GetTypeDataForIID(aIID), aFlags);
-}
-
-PRBool
-nsEventListenerManager::ListenerCanHandle(nsListenerStruct* aLs,
- nsEvent* aEvent)
-{
- if (aEvent->message == NS_USER_DEFINED_EVENT) {
- // We don't want to check aLs->mEventType here, bug 276846.
- return (aEvent->userType && aLs->mTypeAtom == aEvent->userType);
- }
- return (aLs->mEventType == aEvent->message);
+ // This is slightly different from EVENT_TYPE_EQUALS in that it returns
+ // true even when aEvent->message == NS_USER_DEFINED_EVENT and
+ // aLs=>mEventType != NS_USER_DEFINED_EVENT as long as the atoms are the same
+ return aEvent->message == NS_USER_DEFINED_EVENT ?
+ (aLs->mTypeAtom == aEvent->userType) :
+ (aLs->mEventType == aEvent->message);
}
nsresult
nsEventListenerManager::AddEventListenerByType(nsIDOMEventListener *aListener,
const nsAString& aType,
PRInt32 aFlags)
{
nsCOMPtr<nsIAtom> atom = do_GetAtom(NS_LITERAL_STRING("on") + aType);
PRUint32 type = nsContentUtils::GetEventId(atom);
- return AddEventListener(aListener, type, atom, nsnull, aFlags);
+ return AddEventListener(aListener, type, atom, aFlags);
}
void
nsEventListenerManager::RemoveEventListenerByType(nsIDOMEventListener *aListener,
const nsAString& aType,
PRInt32 aFlags)
{
nsCOMPtr<nsIAtom> atom = do_GetAtom(NS_LITERAL_STRING("on") + aType);
PRUint32 type = nsContentUtils::GetEventId(atom);
- RemoveEventListener(aListener, type, atom, nsnull, aFlags);
+ RemoveEventListener(aListener, type, atom, aFlags);
}
nsListenerStruct*
nsEventListenerManager::FindJSEventListener(PRUint32 aEventType,
nsIAtom* aTypeAtom)
{
// Run through the listeners for this type and see if a script
// listener is registered
@@ -598,17 +385,17 @@ nsEventListenerManager::SetJSEventListen
if (!ls) {
// If we didn't find a script listener or no listeners existed
// create and add a new one.
nsCOMPtr<nsIDOMEventListener> scriptListener;
rv = NS_NewJSEventListener(aContext, aScopeObject, mTarget, aName,
getter_AddRefs(scriptListener));
if (NS_SUCCEEDED(rv)) {
- AddEventListener(scriptListener, eventType, aName, nsnull,
+ AddEventListener(scriptListener, eventType, aName,
NS_EVENT_FLAG_BUBBLE | NS_PRIV_EVENT_FLAG_SCRIPT);
ls = FindJSEventListener(eventType, aName);
}
}
if (NS_SUCCEEDED(rv) && ls) {
// Set flag to indicate possible need for compilation later
@@ -1073,20 +860,16 @@ nsEventListenerManager::HandleEventSubTy
if (NS_SUCCEEDED(result)) {
// nsIDOMEvent::currentTarget is set in nsEventDispatcher.
result = aListener->HandleEvent(aDOMEvent);
}
return result;
}
-static PRUint32 sLatestEventType = 0;
-static const EventTypeData* sLatestEventTypeData = nsnull;
-static const EventDispatchData* sLatestEventDispData = nsnull;
-
/**
* Causes a check for event listeners and processing by them if they exist.
* @param an event listener
*/
void
nsEventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
nsEvent* aEvent,
@@ -1096,89 +879,49 @@ nsEventListenerManager::HandleEventInter
nsEventStatus* aEventStatus,
nsCxPusher* aPusher)
{
//Set the value of the internal PreventDefault flag properly based on aEventStatus
if (*aEventStatus == nsEventStatus_eConsumeNoDefault) {
aEvent->flags |= NS_EVENT_FLAG_NO_DEFAULT;
}
- const EventTypeData* typeData = nsnull;
- const EventDispatchData* dispData = nsnull;
- if (aEvent->message != NS_USER_DEFINED_EVENT) {
- // Check if this is the same type of event as what a listener manager
- // handled last time.
- if (aEvent->message == sLatestEventType) {
- typeData = sLatestEventTypeData;
- dispData = sLatestEventDispData;
- goto found;
- }
- for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(sEventTypes); ++i) {
- typeData = &sEventTypes[i];
- for (PRInt32 j = 0; j < typeData->numEvents; ++j) {
- dispData = &(typeData->events[j]);
- if (aEvent->message == dispData->message) {
- sLatestEventType = aEvent->message;
- sLatestEventTypeData = typeData;
- sLatestEventDispData = dispData;
- goto found;
- }
- }
- typeData = nsnull;
- dispData = nsnull;
- }
- }
-
-found:
-
nsAutoTObserverArray<nsListenerStruct, 2>::EndLimitedIterator iter(mListeners);
nsAutoPopupStatePusher popupStatePusher(nsDOMEvent::GetEventPopupControlState(aEvent));
PRBool hasListener = PR_FALSE;
while (iter.HasMore()) {
nsListenerStruct* ls = &iter.GetNext();
- PRBool useTypeInterface =
- EVENT_TYPE_DATA_EQUALS(ls->mTypeData, typeData);
- PRBool useGenericInterface =
- (!useTypeInterface && ListenerCanHandle(ls, aEvent));
- // Don't fire the listener if it's been removed.
// Check that the phase is same in event and event listener.
// Handle only trusted events, except when listener permits untrusted events.
- if (useTypeInterface || useGenericInterface) {
- if (ls->mListener) {
- hasListener = PR_TRUE;
- // XXX The (mFlags & aFlags) test here seems fragile. Shouldn't we
- // specifically only test the capture/bubble flags.
- if ((ls->mFlags & aFlags & ~NS_EVENT_FLAG_SYSTEM_EVENT) &&
- (ls->mFlags & NS_EVENT_FLAG_SYSTEM_EVENT) ==
- (aFlags & NS_EVENT_FLAG_SYSTEM_EVENT) &&
- (NS_IS_TRUSTED_EVENT(aEvent) ||
- ls->mFlags & NS_PRIV_EVENT_UNTRUSTED_PERMITTED)) {
- if (!*aDOMEvent) {
- nsEventDispatcher::CreateEvent(aPresContext, aEvent,
- EmptyString(), aDOMEvent);
- }
- if (*aDOMEvent) {
+ if (ListenerCanHandle(ls, aEvent)) {
+ hasListener = PR_TRUE;
+ // XXX The (mFlags & aFlags) test here seems fragile. Shouldn't we
+ // specifically only test the capture/bubble flags.
+ if ((ls->mFlags & aFlags & ~NS_EVENT_FLAG_SYSTEM_EVENT) &&
+ (ls->mFlags & NS_EVENT_FLAG_SYSTEM_EVENT) ==
+ (aFlags & NS_EVENT_FLAG_SYSTEM_EVENT) &&
+ (NS_IS_TRUSTED_EVENT(aEvent) ||
+ ls->mFlags & NS_PRIV_EVENT_UNTRUSTED_PERMITTED)) {
+ if (!*aDOMEvent) {
+ nsEventDispatcher::CreateEvent(aPresContext, aEvent,
+ EmptyString(), aDOMEvent);
+ }
+ if (*aDOMEvent) {
+ if (!aEvent->currentTarget) {
+ aEvent->currentTarget = aCurrentTarget->GetTargetForDOMEvent();
if (!aEvent->currentTarget) {
- aEvent->currentTarget = aCurrentTarget->GetTargetForDOMEvent();
- if (!aEvent->currentTarget) {
- break;
- }
+ break;
}
- nsRefPtr<nsIDOMEventListener> kungFuDeathGrip = ls->mListener;
- if (useTypeInterface) {
- aPusher->Pop();
- DispatchToInterface(*aDOMEvent, ls->mListener,
- dispData->method, *typeData->iid);
- } else if (useGenericInterface &&
- aPusher->RePush(aCurrentTarget)) {
- if (NS_FAILED(HandleEventSubType(ls, ls->mListener, *aDOMEvent,
- aCurrentTarget, aFlags,
- aPusher))) {
- aEvent->flags |= NS_EVENT_FLAG_EXCEPTION_THROWN;
- }
+ }
+ nsRefPtr<nsIDOMEventListener> kungFuDeathGrip = ls->mListener;
+ if (aPusher->RePush(aCurrentTarget)) {
+ if (NS_FAILED(HandleEventSubType(ls, ls->mListener, *aDOMEvent,
+ aCurrentTarget, aFlags,
+ aPusher))) {
+ aEvent->flags |= NS_EVENT_FLAG_EXCEPTION_THROWN;
}
}
}
}
}
}
aEvent->currentTarget = nsnull;
@@ -1262,40 +1005,21 @@ nsEventListenerManager::MutationListener
}
return bits;
}
PRBool
nsEventListenerManager::HasListenersFor(const nsAString& aEventName)
{
nsCOMPtr<nsIAtom> atom = do_GetAtom(NS_LITERAL_STRING("on") + aEventName);
- PRUint32 type = nsContentUtils::GetEventId(atom);
-
- const EventTypeData* typeData = nsnull;
- const EventDispatchData* dispData = nsnull;
- if (type != NS_USER_DEFINED_EVENT) {
- for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(sEventTypes); ++i) {
- typeData = &sEventTypes[i];
- for (PRInt32 j = 0; j < typeData->numEvents; ++j) {
- dispData = &(typeData->events[j]);
- if (type == dispData->message) {
- goto found;
- }
- }
- typeData = nsnull;
- dispData = nsnull;
- }
- }
-found:
PRUint32 count = mListeners.Length();
for (PRUint32 i = 0; i < count; ++i) {
nsListenerStruct* ls = &mListeners.ElementAt(i);
- if (ls->mTypeAtom == atom ||
- EVENT_TYPE_DATA_EQUALS(ls->mTypeData, typeData)) {
+ if (ls->mTypeAtom == atom) {
return PR_TRUE;
}
}
return PR_FALSE;
}
PRBool
nsEventListenerManager::HasListeners()
@@ -1324,64 +1048,32 @@ nsEventListenerManager::GetListenerInfo(
jslistener->GetEventScope(),
jslistener->GetEventTarget(),
ls.mTypeAtom,
const_cast<nsListenerStruct*>(&ls),
mTarget,
PR_TRUE);
}
}
- if (ls.mTypeData) {
- // Handle special event listener interfaces, like nsIDOMFocusListener.
- for (PRInt32 j = 0; j < ls.mTypeData->numEvents; ++j) {
- const EventDispatchData* dispData = &(ls.mTypeData->events[j]);
- const char* eventName = nsDOMEvent::GetEventName(dispData->message);
- if (eventName) {
- NS_ConvertASCIItoUTF16 eventType(eventName);
- nsRefPtr<nsEventListenerInfo> info =
- new nsEventListenerInfo(eventType, ls.mListener, capturing,
- allowsUntrusted, systemGroup);
- NS_ENSURE_TRUE(info, NS_ERROR_OUT_OF_MEMORY);
- aList->AppendObject(info);
- }
- }
- } else if (ls.mEventType == NS_USER_DEFINED_EVENT) {
- // Handle user defined event types.
- if (ls.mTypeAtom) {
- const nsDependentSubstring& eventType =
- Substring(nsDependentAtomString(ls.mTypeAtom), 2);
- nsRefPtr<nsEventListenerInfo> info =
- new nsEventListenerInfo(eventType, ls.mListener, capturing,
- allowsUntrusted, systemGroup);
- NS_ENSURE_TRUE(info, NS_ERROR_OUT_OF_MEMORY);
- aList->AppendObject(info);
- }
- } else {
- // Handle normal events.
- const char* eventName = nsDOMEvent::GetEventName(ls.mEventType);
- if (eventName) {
- NS_ConvertASCIItoUTF16 eventType(eventName);
- nsRefPtr<nsEventListenerInfo> info =
- new nsEventListenerInfo(eventType, ls.mListener, capturing,
- allowsUntrusted, systemGroup);
- NS_ENSURE_TRUE(info, NS_ERROR_OUT_OF_MEMORY);
- aList->AppendObject(info);
- }
- }
+ const nsDependentSubstring& eventType =
+ Substring(nsDependentAtomString(ls.mTypeAtom), 2);
+ nsRefPtr<nsEventListenerInfo> info =
+ new nsEventListenerInfo(eventType, ls.mListener, capturing,
+ allowsUntrusted, systemGroup);
+ NS_ENSURE_TRUE(info, NS_ERROR_OUT_OF_MEMORY);
+ aList->AppendObject(info);
}
return NS_OK;
}
PRBool
nsEventListenerManager::HasUnloadListeners()
{
PRUint32 count = mListeners.Length();
for (PRUint32 i = 0; i < count; ++i) {
nsListenerStruct* ls = &mListeners.ElementAt(i);
if (ls->mEventType == NS_PAGE_UNLOAD ||
- ls->mEventType == NS_BEFORE_PAGE_UNLOAD ||
- (ls->mTypeData && ls->mTypeData->iid &&
- ls->mTypeData->iid->Equals(NS_GET_IID(nsIDOMLoadListener)))) {
+ ls->mEventType == NS_BEFORE_PAGE_UNLOAD) {
return PR_TRUE;
}
}
return PR_FALSE;
}
--- a/content/events/src/nsEventListenerManager.h
+++ b/content/events/src/nsEventListenerManager.h
@@ -62,17 +62,16 @@ class nsCxPusher;
class nsIEventListenerInfo;
typedef struct {
nsRefPtr<nsIDOMEventListener> mListener;
PRUint32 mEventType;
nsCOMPtr<nsIAtom> mTypeAtom;
PRUint16 mFlags;
PRBool mHandlerIsString;
- const EventTypeData* mTypeData;
} nsListenerStruct;
/*
* Event listener manager
*/
class nsEventListenerManager
{
@@ -92,20 +91,16 @@ public:
void RemoveEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
PRBool aUseCapture);
/**
* Sets events listeners of all types.
* @param an event listener
*/
- nsresult AddEventListenerByIID(nsIDOMEventListener *aListener,
- const nsIID& aIID, PRInt32 aFlags);
- void RemoveEventListenerByIID(nsIDOMEventListener *aListener,
- const nsIID& aIID, PRInt32 aFlags);
nsresult AddEventListenerByType(nsIDOMEventListener *aListener,
const nsAString& type,
PRInt32 aFlags);
void RemoveEventListenerByType(nsIDOMEventListener *aListener,
const nsAString& type,
PRInt32 aFlags);
nsresult AddScriptEventListener(nsIAtom *aName,
const nsAString& aFunc,
@@ -213,27 +208,24 @@ protected:
nsListenerStruct* FindJSEventListener(PRUint32 aEventType, nsIAtom* aTypeAtom);
nsresult SetJSEventListener(nsIScriptContext *aContext,
void *aScopeGlobal,
nsIAtom* aName, PRBool aIsString,
PRBool aPermitUntrustedEvents);
nsresult AddEventListener(nsIDOMEventListener *aListener,
PRUint32 aType,
nsIAtom* aTypeAtom,
- const EventTypeData* aTypeData,
PRInt32 aFlags);
void RemoveEventListener(nsIDOMEventListener *aListener,
PRUint32 aType,
nsIAtom* aUserType,
- const EventTypeData* aTypeData,
PRInt32 aFlags);
void RemoveAllListeners();
const EventTypeData* GetTypeDataForIID(const nsIID& aIID);
const EventTypeData* GetTypeDataForEventName(nsIAtom* aName);
- PRBool ListenerCanHandle(nsListenerStruct* aLs, nsEvent* aEvent);
nsPIDOMWindow* GetInnerWindowForTarget();
PRUint32 mMayHavePaintEventListener : 1;
PRUint32 mMayHaveMutationListeners : 1;
PRUint32 mMayHaveCapturingListeners : 1;
PRUint32 mMayHaveSystemGroupListeners : 1;
PRUint32 mMayHaveAudioAvailableEventListener : 1;
PRUint32 mMayHaveTouchEventListener : 1;
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -136,16 +136,20 @@
#include "mozilla/Services.h"
#include "mozAutoDocUpdate.h"
#include "nsHTMLLabelElement.h"
#include "mozilla/Preferences.h"
#ifdef XP_MACOSX
#import <ApplicationServices/ApplicationServices.h>
+
+#ifdef MOZ_WIDGET_COCOA
+#include "nsCocoaFeatures.h"
+#endif
#endif
using namespace mozilla;
using namespace mozilla::dom;
//#define DEBUG_DOCSHELL_FOCUS
#define NS_USER_INTERACTION_INTERVAL 5000 // ms
@@ -368,25 +372,30 @@ public:
// Be careful, UpdateTransaction may fire a DOM event, therefore, the target
// frame might be destroyed in the event handler.
static PRBool UpdateTransaction(PRInt32 aNumLines,
PRBool aScrollHorizontal);
static void EndTransaction();
static void OnEvent(nsEvent* aEvent);
static void Shutdown();
static PRUint32 GetTimeoutTime();
+ static PRUint32 GetGestureTimeoutTime();
static PRInt32 AccelerateWheelDelta(PRInt32 aScrollLines,
PRBool aIsHorizontal, PRBool aAllowScrollSpeedOverride,
nsIScrollableFrame::ScrollUnit *aScrollQuantity,
PRBool aLimitToMaxOnePageScroll = PR_TRUE);
static PRBool IsAccelerationEnabled();
enum {
kScrollSeriesTimeout = 80
};
+#ifdef MOZ_WIDGET_COCOA
+ static PRBool GetGestureTriggered();
+ static void SetGestureTriggered();
+#endif
protected:
static nsIntPoint GetScreenPoint(nsGUIEvent* aEvent);
static void OnFailToScrollTarget();
static void OnTimeout(nsITimer *aTimer, void *aClosure);
static void SetTimeout();
static PRUint32 GetIgnoreMoveDelayTime();
static PRInt32 GetAccelerationStart();
static PRInt32 GetAccelerationFactor();
@@ -397,23 +406,29 @@ protected:
PRBool aIsHorizontal,
nsIScrollableFrame::ScrollUnit *aScrollQuantity);
static nsWeakFrame sTargetFrame;
static PRUint32 sTime; // in milliseconds
static PRUint32 sMouseMoved; // in milliseconds
static nsITimer* sTimer;
static PRInt32 sScrollSeriesCounter;
+#ifdef MOZ_WIDGET_COCOA
+ static PRUint32 sGestureTriggered; // in milliseconds
+#endif
};
nsWeakFrame nsMouseWheelTransaction::sTargetFrame(nsnull);
PRUint32 nsMouseWheelTransaction::sTime = 0;
PRUint32 nsMouseWheelTransaction::sMouseMoved = 0;
nsITimer* nsMouseWheelTransaction::sTimer = nsnull;
PRInt32 nsMouseWheelTransaction::sScrollSeriesCounter = 0;
+#ifdef MOZ_WIDGET_COCOA
+PRUint32 nsMouseWheelTransaction::sGestureTriggered = 0;
+#endif
static PRBool
OutOfTime(PRUint32 aBaseTime, PRUint32 aThreshold)
{
PRUint32 now = PR_IntervalToMilliseconds(PR_IntervalNow());
return (now - aBaseTime > aThreshold);
}
@@ -482,18 +497,39 @@ nsMouseWheelTransaction::UpdateTransacti
void
nsMouseWheelTransaction::EndTransaction()
{
if (sTimer)
sTimer->Cancel();
sTargetFrame = nsnull;
sScrollSeriesCounter = 0;
+#ifdef MOZ_WIDGET_COCOA
+ sGestureTriggered = 0;
+#endif
}
+#ifdef MOZ_WIDGET_COCOA
+void
+nsMouseWheelTransaction::SetGestureTriggered() {
+ sGestureTriggered = PR_IntervalToMilliseconds(PR_IntervalNow());
+}
+
+PRBool
+nsMouseWheelTransaction::GetGestureTriggered() {
+ if (sGestureTriggered != 0 &&
+ OutOfTime(sGestureTriggered, GetGestureTimeoutTime())) {
+ // Start accepting new gestures
+ sGestureTriggered = 0;
+ }
+
+ return sGestureTriggered != 0;
+}
+#endif
+
void
nsMouseWheelTransaction::OnEvent(nsEvent* aEvent)
{
if (!sTargetFrame)
return;
if (OutOfTime(sTime, GetTimeoutTime())) {
// Even if the scroll event which is handled after timeout, but onTimeout
@@ -630,16 +666,22 @@ nsIntPoint
nsMouseWheelTransaction::GetScreenPoint(nsGUIEvent* aEvent)
{
NS_ASSERTION(aEvent, "aEvent is null");
NS_ASSERTION(aEvent->widget, "aEvent-widget is null");
return aEvent->refPoint + aEvent->widget->WidgetToScreenOffset();
}
PRUint32
+nsMouseWheelTransaction::GetGestureTimeoutTime()
+{
+ return Preferences::GetUint("mousewheel.transaction.gesturetimeout", 300);
+}
+
+PRUint32
nsMouseWheelTransaction::GetTimeoutTime()
{
return Preferences::GetUint("mousewheel.transaction.timeout", 1500);
}
PRUint32
nsMouseWheelTransaction::GetIgnoreMoveDelayTime()
{
@@ -2792,16 +2834,32 @@ nsEventStateManager::DoScrollText(nsIFra
passToParent = PR_TRUE;
nsMouseWheelTransaction::EndTransaction();
}
}
}
}
}
+#ifdef MOZ_WIDGET_COCOA
+ // On lion scroll will trigger back/forward at the edge of the page
+ if (isHorizontal && passToParent && nsCocoaFeatures::OnLionOrLater()) {
+ if (!nsMouseWheelTransaction::GetGestureTriggered()) {
+ if (numLines > 4 || numLines < -4) {
+ DoScrollHistory(-numLines);
+ nsMouseWheelTransaction::SetGestureTriggered();
+ return NS_OK;
+ }
+ } else {
+ // Extend the gesture in progress
+ nsMouseWheelTransaction::SetGestureTriggered();
+ }
+ }
+#endif
+
if (!passToParent && frameToScroll) {
if (aScrollQuantity == nsIScrollableFrame::LINES) {
// When this is called for querying the scroll target information,
// we shouldn't limit the scrolling amount to less one page.
// Otherwise, we shouldn't scroll more one page at once.
numLines =
nsMouseWheelTransaction::AccelerateWheelDelta(numLines, isHorizontal,
aAllowScrollSpeedOverride,
--- a/content/html/content/public/Makefile.in
+++ b/content/html/content/public/Makefile.in
@@ -43,16 +43,18 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = content
XPIDL_MODULE = content_html
XPIDLSRCS = \
nsIFormSubmitObserver.idl \
nsIPhonetic.idl \
+ nsIHTMLMenu.idl \
+ nsIMenuBuilder.idl \
$(NULL)
EXPORTS = \
nsIConstraintValidation.h \
nsIFormControl.h \
nsIForm.h \
nsIFormProcessor.h \
nsILink.h \
new file mode 100644
--- /dev/null
+++ b/content/html/content/public/nsIHTMLMenu.idl
@@ -0,0 +1,73 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsIMenuBuilder;
+
+/**
+ * A private interface.
+ * All methods throw NS_ERROR_DOM_SECURITY_ERR if the caller is not chrome.
+ */
+
+[scriptable, uuid(d3d068d8-e223-4228-ba39-4d6df21ba616)]
+interface nsIHTMLMenu : nsISupports
+{
+ /**
+ * Creates and dispatches a trusted event named "show".
+ * The event is not cancelable and does not bubble.
+ * See http://www.whatwg.org/specs/web-apps/current-work/multipage/interactive-elements.html#context-menus
+ */
+ void sendShowEvent();
+
+ /**
+ * Creates a native menu builder. The builder type is dependent on menu type.
+ * Currently, it returns nsXULContextMenuBuilder for context menus.
+ * Toolbar menus are not yet supported (the method returns null).
+ */
+ nsIMenuBuilder createBuilder();
+
+ /*
+ * Builds a menu by iterating over menu children.
+ * See http://www.whatwg.org/specs/web-apps/current-work/multipage/interactive-elements.html#building-menus-and-toolbars
+ * The caller can use a native builder by calling createBuilder() or provide
+ * a custom builder that implements the nsIMenuBuilder interface.
+ * A custom builder can be used for example to build native context menus
+ * that are not defined using <menupopup>.
+ */
+ void build(in nsIMenuBuilder aBuilder);
+
+};
new file mode 100644
--- /dev/null
+++ b/content/html/content/public/nsIMenuBuilder.idl
@@ -0,0 +1,83 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsIDOMHTMLMenuItemElement;
+
+/**
+ * An interface used to construct native toolbar or context menus from <menu>
+ */
+
+[scriptable, uuid(12724737-f7db-43b4-94ab-708a7b86e115)]
+interface nsIMenuBuilder : nsISupports
+{
+
+ /**
+ * Create the top level menu or a submenu. The implementation should create
+ * a new context for this menu, so all subsequent methods will add new items
+ * to this newly created menu.
+ */
+ void openContainer(in DOMString aLabel);
+
+ /**
+ * Add a new menu item. All menu item details can be obtained from
+ * the element. This method is not called for hidden elements or elements
+ * with no or empty label. The icon should be loaded only if aCanLoadIcon
+ * is true.
+ */
+ void addItemFor(in nsIDOMHTMLMenuItemElement aElement,
+ in boolean aCanLoadIcon);
+
+ /**
+ * Create a new separator.
+ */
+ void addSeparator();
+
+ /**
+ * Remove last added separator.
+ * Sometimes it's needed to remove last added separator, otherwise it's not
+ * possible to implement the postprocessing in one pass.
+ * See http://www.whatwg.org/specs/web-apps/current-work/multipage/interactive-elements.html#building-menus-and-toolbars
+ */
+ void undoAddSeparator();
+
+ /**
+ * Set the context to the parent menu.
+ */
+ void closeContainer();
+
+};
--- a/content/html/content/src/Makefile.in
+++ b/content/html/content/src/Makefile.in
@@ -77,16 +77,18 @@ CPPSRCS = \
nsHTMLIFrameElement.cpp \
nsHTMLImageElement.cpp \
nsHTMLInputElement.cpp \
nsHTMLLIElement.cpp \
nsHTMLLabelElement.cpp \
nsHTMLLegendElement.cpp \
nsHTMLLinkElement.cpp \
nsHTMLMapElement.cpp \
+ nsHTMLMenuElement.cpp \
+ nsHTMLMenuItemElement.cpp \
nsHTMLMetaElement.cpp \
nsHTMLModElement.cpp \
nsHTMLObjectElement.cpp \
nsHTMLOListElement.cpp \
nsHTMLSharedObjectElement.cpp \
nsHTMLOptionElement.cpp \
nsHTMLOptGroupElement.cpp \
nsHTMLOutputElement.cpp \
@@ -129,16 +131,17 @@ FORCE_STATIC_LIB = 1
include $(topsrcdir)/config/rules.mk
include $(topsrcdir)/ipc/chromium/chromium-config.mk
INCLUDES += \
-I$(srcdir)/../../../base/src \
-I$(srcdir)/../../../events/src \
-I$(srcdir)/../../../xbl/src \
+ -I$(srcdir)/../../../xul/content/src \
-I$(srcdir)/../../../../layout/forms \
-I$(srcdir)/../../../../layout/style \
-I$(srcdir)/../../../../layout/tables \
-I$(srcdir)/../../../../layout/xul/base/src \
-I$(srcdir)/../../../../layout/generic \
-I$(srcdir)/../../../../dom/base \
-I$(srcdir)/../../../../editor/libeditor/base \
-I$(srcdir)/../../../../editor/libeditor/text \
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -45,16 +45,17 @@
#include "mozilla/css/StyleRule.h"
#include "nsIDocument.h"
#include "nsIDocumentEncoder.h"
#include "nsIDOMHTMLBodyElement.h"
#include "nsIDOMHTMLDocument.h"
#include "nsIDOMAttr.h"
#include "nsIDOMDocumentFragment.h"
#include "nsIDOMNSHTMLElement.h"
+#include "nsIDOMHTMLMenuElement.h"
#include "nsIDOMElementCSSInlineStyle.h"
#include "nsIDOMWindow.h"
#include "nsIDOMDocument.h"
#include "nsEventListenerManager.h"
#include "nsMappedAttributes.h"
#include "nsHTMLStyleSheet.h"
#include "nsIHTMLDocument.h"
#include "nsILink.h"
@@ -110,16 +111,17 @@
#include "nsEventDispatcher.h"
#include "nsLayoutUtils.h"
#include "nsContentCreatorFunctions.h"
#include "mozAutoDocUpdate.h"
#include "nsHtml5Module.h"
#include "nsITextControlElement.h"
#include "mozilla/dom/Element.h"
#include "nsHTMLFieldSetElement.h"
+#include "nsHTMLMenuElement.h"
#include "mozilla/Preferences.h"
using namespace mozilla;
using namespace mozilla::dom;
#include "nsThreadUtils.h"
@@ -2446,16 +2448,38 @@ nsGenericHTMLElement::GetIsContentEditab
}
}
}
*aContentEditable = PR_FALSE;
return NS_OK;
}
+nsresult
+nsGenericHTMLElement::GetContextMenu(nsIDOMHTMLMenuElement** aContextMenu)
+{
+ *aContextMenu = nsnull;
+
+ nsAutoString value;
+ GetAttr(kNameSpaceID_None, nsGkAtoms::contextmenu, value);
+
+ if (value.IsEmpty()) {
+ return NS_OK;
+ }
+
+ nsIDocument* doc = GetCurrentDoc();
+ if (doc) {
+ nsRefPtr<nsHTMLMenuElement> element =
+ nsHTMLMenuElement::FromContent(doc->GetElementById(value));
+ element.forget(aContextMenu);
+ }
+
+ return NS_OK;
+}
+
//----------------------------------------------------------------------
NS_IMPL_INT_ATTR(nsGenericHTMLFrameElement, TabIndex, tabindex)
nsGenericHTMLFormElement::nsGenericHTMLFormElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo)
, mForm(nsnull)
, mFieldSet(nsnull)
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -61,16 +61,17 @@ class nsIFormControlFrame;
class nsIForm;
class nsPresState;
class nsILayoutHistoryState;
class nsIEditor;
struct nsRect;
struct nsSize;
class nsHTMLFormElement;
class nsIDOMDOMStringMap;
+class nsIDOMHTMLMenuElement;
typedef nsMappedAttributeElement nsGenericHTMLElementBase;
/**
* A common superclass for HTML elements
*/
class nsGenericHTMLElement : public nsGenericHTMLElementBase
{
@@ -156,16 +157,17 @@ public:
NS_IMETHOD SetAccessKey(const nsAString& aAccessKey);
NS_IMETHOD GetAccessKeyLabel(nsAString& aLabel);
nsresult GetContentEditable(nsAString& aContentEditable);
nsresult GetIsContentEditable(PRBool* aContentEditable);
nsresult SetContentEditable(const nsAString &aContentEditable);
nsresult GetDataset(nsIDOMDOMStringMap** aDataset);
// Callback for destructor of of dataset to ensure to null out weak pointer.
nsresult ClearDataset();
+ nsresult GetContextMenu(nsIDOMHTMLMenuElement** aContextMenu);
// Implementation for nsIContent
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE);
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
@@ -528,16 +530,21 @@ public:
/**
* Returns the current disabled state of the element.
*/
virtual bool IsDisabled() const {
return HasAttr(kNameSpaceID_None, nsGkAtoms::disabled);
}
+ PRBool IsHidden() const
+ {
+ return HasAttr(kNameSpaceID_None, nsGkAtoms::hidden);
+ }
+
protected:
/**
* Add/remove this element to the documents name cache
*/
void AddToNameTable(nsIAtom* aName) {
NS_ASSERTION(HasName(), "Node doesn't have name?");
nsIDocument* doc = GetCurrentDoc();
if (doc && !IsInAnonymousSubtree()) {
@@ -1466,32 +1473,32 @@ protected:
NS_INTERFACE_TABLE_ENTRY(_class, _i5) \
NS_INTERFACE_TABLE_ENTRY(_class, _i6) \
NS_INTERFACE_TABLE_ENTRY(_class, _i7) \
NS_INTERFACE_TABLE_ENTRY(_class, _i8) \
NS_INTERFACE_TABLE_ENTRY(_class, _i9) \
NS_INTERFACE_TABLE_ENTRY(_class, _i10) \
NS_OFFSET_AND_INTERFACE_TABLE_END
-/* Use this macro to declare functions that forward the behavior of this interface to another object.
- This macro doesn't forward Focus or Click because sometimes elements will want to override them. */
-#define NS_FORWARD_NSIDOMHTMLELEMENT_NOFOCUSCLICK(_to) \
- NS_SCRIPTABLE NS_IMETHOD GetId(nsAString & aId) { return _to GetId(aId); } \
- NS_SCRIPTABLE NS_IMETHOD SetId(const nsAString & aId) { return _to SetId(aId); } \
- NS_SCRIPTABLE NS_IMETHOD GetTitle(nsAString & aTitle) { return _to GetTitle(aTitle); } \
- NS_SCRIPTABLE NS_IMETHOD SetTitle(const nsAString & aTitle) { return _to SetTitle(aTitle); } \
- NS_SCRIPTABLE NS_IMETHOD GetLang(nsAString & aLang) { return _to GetLang(aLang); } \
- NS_SCRIPTABLE NS_IMETHOD SetLang(const nsAString & aLang) { return _to SetLang(aLang); } \
- NS_SCRIPTABLE NS_IMETHOD GetDir(nsAString & aDir) { return _to GetDir(aDir); } \
- NS_SCRIPTABLE NS_IMETHOD SetDir(const nsAString & aDir) { return _to SetDir(aDir); } \
- NS_SCRIPTABLE NS_IMETHOD GetClassName(nsAString & aClassName) { return _to GetClassName(aClassName); } \
- NS_SCRIPTABLE NS_IMETHOD SetClassName(const nsAString & aClassName) { return _to SetClassName(aClassName); } \
- NS_SCRIPTABLE NS_IMETHOD GetAccessKey(nsAString & aAccessKey) { return _to GetAccessKey(aAccessKey); } \
- NS_SCRIPTABLE NS_IMETHOD SetAccessKey(const nsAString & aAccessKey) { return _to SetAccessKey(aAccessKey); } \
- NS_SCRIPTABLE NS_IMETHOD GetAccessKeyLabel(nsAString & aLabel) { return _to GetAccessKeyLabel(aLabel); } \
+/* Use this macro to declare functions that forward the behavior of this interface to another object.
+ This macro doesn't forward Focus or Click because sometimes elements will want to override them. */
+#define NS_FORWARD_NSIDOMHTMLELEMENT_NOFOCUSCLICK(_to) \
+ NS_SCRIPTABLE NS_IMETHOD GetId(nsAString & aId) { return _to GetId(aId); } \
+ NS_SCRIPTABLE NS_IMETHOD SetId(const nsAString & aId) { return _to SetId(aId); } \
+ NS_SCRIPTABLE NS_IMETHOD GetTitle(nsAString & aTitle) { return _to GetTitle(aTitle); } \
+ NS_SCRIPTABLE NS_IMETHOD SetTitle(const nsAString & aTitle) { return _to SetTitle(aTitle); } \
+ NS_SCRIPTABLE NS_IMETHOD GetLang(nsAString & aLang) { return _to GetLang(aLang); } \
+ NS_SCRIPTABLE NS_IMETHOD SetLang(const nsAString & aLang) { return _to SetLang(aLang); } \
+ NS_SCRIPTABLE NS_IMETHOD GetDir(nsAString & aDir) { return _to GetDir(aDir); } \
+ NS_SCRIPTABLE NS_IMETHOD SetDir(const nsAString & aDir) { return _to SetDir(aDir); } \
+ NS_SCRIPTABLE NS_IMETHOD GetClassName(nsAString & aClassName) { return _to GetClassName(aClassName); } \
+ NS_SCRIPTABLE NS_IMETHOD SetClassName(const nsAString & aClassName) { return _to SetClassName(aClassName); } \
+ NS_SCRIPTABLE NS_IMETHOD GetAccessKey(nsAString & aAccessKey) { return _to GetAccessKey(aAccessKey); } \
+ NS_SCRIPTABLE NS_IMETHOD SetAccessKey(const nsAString & aAccessKey) { return _to SetAccessKey(aAccessKey); } \
+ NS_SCRIPTABLE NS_IMETHOD GetAccessKeyLabel(nsAString & aLabel) { return _to GetAccessKeyLabel(aLabel); } \
NS_SCRIPTABLE NS_IMETHOD Blur(void) { return _to Blur(); }
/**
* A macro to declare the NS_NewHTMLXXXElement() functions.
*/
#define NS_DECLARE_NS_NEW_HTML_ELEMENT(_elementName) \
nsGenericHTMLElement* \
NS_NewHTML##_elementName##Element(already_AddRefed<nsINodeInfo> aNodeInfo, \
@@ -1558,16 +1565,18 @@ NS_DECLARE_NS_NEW_HTML_ELEMENT_AS_SHARED
NS_DECLARE_NS_NEW_HTML_ELEMENT(IFrame)
NS_DECLARE_NS_NEW_HTML_ELEMENT(Image)
NS_DECLARE_NS_NEW_HTML_ELEMENT(Input)
NS_DECLARE_NS_NEW_HTML_ELEMENT(LI)
NS_DECLARE_NS_NEW_HTML_ELEMENT(Label)
NS_DECLARE_NS_NEW_HTML_ELEMENT(Legend)
NS_DECLARE_NS_NEW_HTML_ELEMENT(Link)
NS_DECLARE_NS_NEW_HTML_ELEMENT(Map)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Menu)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(MenuItem)
NS_DECLARE_NS_NEW_HTML_ELEMENT(Meta)
NS_DECLARE_NS_NEW_HTML_ELEMENT(Object)
NS_DECLARE_NS_NEW_HTML_ELEMENT(OptGroup)
NS_DECLARE_NS_NEW_HTML_ELEMENT(Option)
NS_DECLARE_NS_NEW_HTML_ELEMENT(Output)
NS_DECLARE_NS_NEW_HTML_ELEMENT(Paragraph)
NS_DECLARE_NS_NEW_HTML_ELEMENT(Pre)
NS_DECLARE_NS_NEW_HTML_ELEMENT(Progress)
new file mode 100644
--- /dev/null
+++ b/content/html/content/src/nsHTMLMenuElement.cpp
@@ -0,0 +1,289 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIDOMNSHTMLElement.h"
+#include "nsIDOMHTMLMenuItemElement.h"
+#include "nsXULContextMenuBuilder.h"
+#include "nsGUIEvent.h"
+#include "nsEventDispatcher.h"
+#include "nsHTMLMenuItemElement.h"
+#include "nsHTMLMenuElement.h"
+
+enum MenuType
+{
+ MENU_TYPE_CONTEXT = 1,
+ MENU_TYPE_TOOLBAR,
+ MENU_TYPE_LIST
+};
+
+static const nsAttrValue::EnumTable kMenuTypeTable[] = {
+ { "context", MENU_TYPE_CONTEXT },
+ { "toolbar", MENU_TYPE_TOOLBAR },
+ { "list", MENU_TYPE_LIST },
+ { 0 }
+};
+
+static const nsAttrValue::EnumTable* kMenuDefaultType =
+ &kMenuTypeTable[2];
+
+enum SeparatorType
+{
+ ST_TRUE_INIT = -1,
+ ST_FALSE = 0,
+ ST_TRUE = 1
+};
+
+NS_IMPL_NS_NEW_HTML_ELEMENT(Menu)
+
+
+nsHTMLMenuElement::nsHTMLMenuElement(already_AddRefed<nsINodeInfo> aNodeInfo)
+ : nsGenericHTMLElement(aNodeInfo), mType(MENU_TYPE_LIST)
+{
+}
+
+nsHTMLMenuElement::~nsHTMLMenuElement()
+{
+}
+
+
+NS_IMPL_ADDREF_INHERITED(nsHTMLMenuElement, nsGenericElement)
+NS_IMPL_RELEASE_INHERITED(nsHTMLMenuElement, nsGenericElement)
+
+
+DOMCI_NODE_DATA(HTMLMenuElement, nsHTMLMenuElement)
+
+// QueryInterface implementation for nsHTMLMenuElement
+NS_INTERFACE_TABLE_HEAD(nsHTMLMenuElement)
+ NS_HTML_CONTENT_INTERFACE_TABLE2(nsHTMLMenuElement,
+ nsIDOMHTMLMenuElement,
+ nsIHTMLMenu)
+ NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLMenuElement,
+ nsGenericHTMLElement)
+NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLMenuElement)
+
+NS_IMPL_ELEMENT_CLONE(nsHTMLMenuElement)
+
+NS_IMPL_BOOL_ATTR(nsHTMLMenuElement, Compact, compact)
+NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLMenuElement, Type, type,
+ kMenuDefaultType->tag)
+NS_IMPL_STRING_ATTR(nsHTMLMenuElement, Label, label)
+
+
+NS_IMETHODIMP
+nsHTMLMenuElement::SendShowEvent()
+{
+ NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_DOM_SECURITY_ERR);
+
+ nsCOMPtr<nsIDocument> document = GetCurrentDoc();
+ if (!document) {
+ return NS_ERROR_FAILURE;
+ }
+
+ nsEvent event(PR_TRUE, NS_SHOW_EVENT);
+ event.flags |= NS_EVENT_FLAG_CANT_CANCEL | NS_EVENT_FLAG_CANT_BUBBLE;
+
+ nsCOMPtr<nsIPresShell> shell = document->GetShell();
+ if (!shell) {
+ return NS_ERROR_FAILURE;
+ }
+
+ nsRefPtr<nsPresContext> presContext = shell->GetPresContext();
+ nsEventStatus status = nsEventStatus_eIgnore;
+ nsEventDispatcher::Dispatch(static_cast<nsIContent*>(this), presContext,
+ &event, nsnull, &status);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsHTMLMenuElement::CreateBuilder(nsIMenuBuilder** _retval)
+{
+ NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_DOM_SECURITY_ERR);
+
+ *_retval = nsnull;
+
+ if (mType == MENU_TYPE_CONTEXT) {
+ NS_ADDREF(*_retval = new nsXULContextMenuBuilder());
+ }
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsHTMLMenuElement::Build(nsIMenuBuilder* aBuilder)
+{
+ NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_DOM_SECURITY_ERR);
+
+ if (!aBuilder) {
+ return NS_OK;
+ }
+
+ BuildSubmenu(EmptyString(), this, aBuilder);
+
+ return NS_OK;
+}
+
+
+PRBool
+nsHTMLMenuElement::ParseAttribute(PRInt32 aNamespaceID,
+ nsIAtom* aAttribute,
+ const nsAString& aValue,
+ nsAttrValue& aResult)
+{
+ if (aNamespaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::type) {
+ PRBool success = aResult.ParseEnumValue(aValue, kMenuTypeTable,
+ PR_FALSE);
+ if (success) {
+ mType = aResult.GetEnumValue();
+ } else {
+ mType = kMenuDefaultType->value;
+ }
+
+ return success;
+ }
+
+ return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
+ aResult);
+}
+
+void
+nsHTMLMenuElement::BuildSubmenu(const nsAString& aLabel,
+ nsIContent* aContent,
+ nsIMenuBuilder* aBuilder)
+{
+ aBuilder->OpenContainer(aLabel);
+
+ PRInt8 separator = ST_TRUE_INIT;
+ TraverseContent(aContent, aBuilder, separator);
+
+ if (separator == ST_TRUE) {
+ aBuilder->UndoAddSeparator();
+ }
+
+ aBuilder->CloseContainer();
+}
+
+// static
+PRBool
+nsHTMLMenuElement::CanLoadIcon(nsIContent* aContent, const nsAString& aIcon)
+{
+ if (aIcon.IsEmpty()) {
+ return PR_FALSE;
+ }
+
+ nsIDocument* doc = aContent->GetOwnerDoc();
+ if (!doc) {
+ return PR_FALSE;
+ }
+
+ nsCOMPtr<nsIURI> baseURI = aContent->GetBaseURI();
+ nsCOMPtr<nsIURI> uri;
+ nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(uri), aIcon, doc,
+ baseURI);
+
+ if (!uri) {
+ return PR_FALSE;
+ }
+
+ return nsContentUtils::CanLoadImage(uri, aContent, doc,
+ aContent->NodePrincipal());
+}
+
+void
+nsHTMLMenuElement::TraverseContent(nsIContent* aContent,
+ nsIMenuBuilder* aBuilder,
+ PRInt8& aSeparator)
+{
+ nsCOMPtr<nsIContent> child;
+ for (child = aContent->GetFirstChild(); child;
+ child = child->GetNextSibling()) {
+ nsGenericHTMLElement* element = nsGenericHTMLElement::FromContent(child);
+ if (!element) {
+ continue;
+ }
+
+ nsIAtom* tag = child->Tag();
+
+ if (tag == nsGkAtoms::menuitem) {
+ nsHTMLMenuItemElement* menuitem =
+ nsHTMLMenuItemElement::FromContent(child);
+
+ if (menuitem->IsHidden()) {
+ continue;
+ }
+
+ nsAutoString label;
+ menuitem->GetLabel(label);
+ if (label.IsEmpty()) {
+ continue;
+ }
+
+ nsAutoString icon;
+ menuitem->GetIcon(icon);
+
+ aBuilder->AddItemFor(menuitem, CanLoadIcon(child, icon));
+
+ aSeparator = ST_FALSE;
+ } else if (tag == nsGkAtoms::menu && !element->IsHidden()) {
+ if (child->HasAttr(kNameSpaceID_None, nsGkAtoms::label)) {
+ nsAutoString label;
+ child->GetAttr(kNameSpaceID_None, nsGkAtoms::label, label);
+
+ BuildSubmenu(label, child, aBuilder);
+
+ aSeparator = ST_FALSE;
+ } else {
+ AddSeparator(aBuilder, aSeparator);
+
+ TraverseContent(child, aBuilder, aSeparator);
+
+ AddSeparator(aBuilder, aSeparator);
+ }
+ }
+ }
+}
+
+inline void
+nsHTMLMenuElement::AddSeparator(nsIMenuBuilder* aBuilder, PRInt8& aSeparator)
+{
+ if (aSeparator) {
+ return;
+ }
+
+ aBuilder->AddSeparator();
+ aSeparator = ST_TRUE;
+}
new file mode 100644
--- /dev/null
+++ b/content/html/content/src/nsHTMLMenuElement.h
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIDOMHTMLMenuElement.h"
+#include "nsIHTMLMenu.h"
+#include "nsGenericHTMLElement.h"
+#include "nsIDOMNSHTMLElement.h"
+
+class nsHTMLMenuElement : public nsGenericHTMLElement,
+ public nsIDOMHTMLMenuElement,
+ public nsIHTMLMenu
+{
+public:
+ nsHTMLMenuElement(already_AddRefed<nsINodeInfo> aNodeInfo);
+ virtual ~nsHTMLMenuElement();
+
+ /** Typesafe, non-refcounting cast from nsIContent. Cheaper than QI. **/
+ static nsHTMLMenuElement* FromContent(nsIContent* aContent)
+ {
+ if (aContent && aContent->IsHTML(nsGkAtoms::menu))
+ return static_cast<nsHTMLMenuElement*>(aContent);
+ return nsnull;
+ }
+
+ // nsISupports
+ NS_DECL_ISUPPORTS_INHERITED
+
+ // nsIDOMNode
+ NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
+
+ // nsIDOMElement
+ NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
+
+ // nsIDOMHTMLElement
+ NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
+
+ // nsIDOMHTMLMenuElement
+ NS_DECL_NSIDOMHTMLMENUELEMENT
+
+ // nsIHTMLMenu
+ NS_DECL_NSIHTMLMENU
+
+ virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
+ nsIAtom* aAttribute,
+ const nsAString& aValue,
+ nsAttrValue& aResult);
+
+ virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+
+ virtual nsXPCClassInfo* GetClassInfo();
+
+ PRUint8 GetType() const { return mType; }
+
+protected:
+ static PRBool CanLoadIcon(nsIContent* aContent, const nsAString& aIcon);
+
+ void BuildSubmenu(const nsAString& aLabel,
+ nsIContent* aContent,
+ nsIMenuBuilder* aBuilder);
+
+ void TraverseContent(nsIContent* aContent,
+ nsIMenuBuilder* aBuilder,
+ PRInt8& aSeparator);
+
+ void AddSeparator(nsIMenuBuilder* aBuilder, PRInt8& aSeparator);
+
+ PRUint8 mType;
+};
new file mode 100644
--- /dev/null
+++ b/content/html/content/src/nsHTMLMenuItemElement.cpp
@@ -0,0 +1,514 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsGUIEvent.h"
+#include "nsEventDispatcher.h"
+#include "nsHTMLMenuItemElement.h"
+
+using namespace mozilla::dom;
+
+// First bits are needed for the menuitem type.
+#define NS_CHECKED_IS_TOGGLED (1 << 2)
+#define NS_ORIGINAL_CHECKED_VALUE (1 << 3)
+#define NS_MENUITEM_TYPE(bits) ((bits) & ~( \
+ NS_CHECKED_IS_TOGGLED | NS_ORIGINAL_CHECKED_VALUE))
+
+enum CmdType
+{
+ CMD_TYPE_MENUITEM = 1,
+ CMD_TYPE_CHECKBOX,
+ CMD_TYPE_RADIO
+};
+
+static const nsAttrValue::EnumTable kMenuItemTypeTable[] = {
+ { "menuitem", CMD_TYPE_MENUITEM },
+ { "checkbox", CMD_TYPE_CHECKBOX },
+ { "radio", CMD_TYPE_RADIO },
+ { 0 }
+};
+
+static const nsAttrValue::EnumTable* kMenuItemDefaultType =
+ &kMenuItemTypeTable[0];
+
+// A base class inherited by all radio visitors.
+class Visitor
+{
+public:
+ Visitor() { }
+ virtual ~Visitor() { }
+
+ /**
+ * Visit a node in the tree. This is meant to be called on all radios in a
+ * group, sequentially. If the method returns false then the iteration is
+ * stopped.
+ */
+ virtual PRBool Visit(nsHTMLMenuItemElement* aMenuItem) = 0;
+};
+
+// Find the selected radio, see GetSelectedRadio().
+class GetCheckedVisitor : public Visitor
+{
+public:
+ GetCheckedVisitor(nsHTMLMenuItemElement** aResult)
+ : mResult(aResult)
+ { }
+ virtual PRBool Visit(nsHTMLMenuItemElement* aMenuItem)
+ {
+ if (aMenuItem->IsChecked()) {
+ *mResult = aMenuItem;
+ return PR_FALSE;
+ }
+ return PR_TRUE;
+ }
+protected:
+ nsHTMLMenuItemElement** mResult;
+};
+
+// Deselect all radios except the one passed to the constructor.
+class ClearCheckedVisitor : public Visitor
+{
+public:
+ ClearCheckedVisitor(nsHTMLMenuItemElement* aExcludeMenuItem)
+ : mExcludeMenuItem(aExcludeMenuItem)
+ { }
+ virtual PRBool Visit(nsHTMLMenuItemElement* aMenuItem)
+ {
+ if (aMenuItem != mExcludeMenuItem && aMenuItem->IsChecked()) {
+ aMenuItem->ClearChecked();
+ }
+ return PR_TRUE;
+ }
+protected:
+ nsHTMLMenuItemElement* mExcludeMenuItem;
+};
+
+// Get current value of the checked dirty flag. The same value is stored on all
+// radios in the group, so we need to check only the first one.
+class GetCheckedDirtyVisitor : public Visitor
+{
+public:
+ GetCheckedDirtyVisitor(PRBool* aCheckedDirty,
+ nsHTMLMenuItemElement* aExcludeMenuItem)
+ : mCheckedDirty(aCheckedDirty),
+ mExcludeMenuItem(aExcludeMenuItem)
+ { }
+ virtual PRBool Visit(nsHTMLMenuItemElement* aMenuItem)
+ {
+ if (aMenuItem == mExcludeMenuItem) {
+ return PR_TRUE;
+ }
+ *mCheckedDirty = aMenuItem->IsCheckedDirty();
+ return PR_FALSE;
+ }
+protected:
+ PRBool* mCheckedDirty;
+ nsHTMLMenuItemElement* mExcludeMenuItem;
+};
+
+// Set checked dirty to true on all radios in the group.
+class SetCheckedDirtyVisitor : public Visitor
+{
+public:
+ SetCheckedDirtyVisitor()
+ { }
+ virtual PRBool Visit(nsHTMLMenuItemElement* aMenuItem)
+ {
+ aMenuItem->SetCheckedDirty();
+ return PR_TRUE;
+ }
+};
+
+// A helper visitor that is used to combine two operations (visitors) to avoid
+// iterating over radios twice.
+class CombinedVisitor : public Visitor
+{
+public:
+ CombinedVisitor(Visitor* aVisitor1, Visitor* aVisitor2)
+ : mVisitor1(aVisitor1), mVisitor2(aVisitor2),
+ mContinue1(PR_TRUE), mContinue2(PR_TRUE)
+ { }
+ virtual PRBool Visit(nsHTMLMenuItemElement* aMenuItem)
+ {
+ if (mContinue1) {
+ mContinue1 = mVisitor1->Visit(aMenuItem);
+ }
+ if (mContinue2) {
+ mContinue2 = mVisitor2->Visit(aMenuItem);
+ }
+ return mContinue1 || mContinue2;
+ }
+protected:
+ Visitor* mVisitor1;
+ Visitor* mVisitor2;
+ PRPackedBool mContinue1;
+ PRPackedBool mContinue2;
+};
+
+
+NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(MenuItem)
+
+nsHTMLMenuItemElement::nsHTMLMenuItemElement(
+ already_AddRefed<nsINodeInfo> aNodeInfo, FromParser aFromParser)
+ : nsGenericHTMLElement(aNodeInfo),
+ mType(kMenuItemDefaultType->value),
+ mParserCreating(false),
+ mShouldInitChecked(false),
+ mCheckedDirty(false),
+ mChecked(false)
+{
+ mParserCreating = aFromParser;
+}
+
+nsHTMLMenuItemElement::~nsHTMLMenuItemElement()
+{
+}
+
+
+NS_IMPL_ADDREF_INHERITED(nsHTMLMenuItemElement, nsGenericElement)
+NS_IMPL_RELEASE_INHERITED(nsHTMLMenuItemElement, nsGenericElement)
+
+
+DOMCI_NODE_DATA(HTMLMenuItemElement, nsHTMLMenuItemElement)
+
+// QueryInterface implementation for nsHTMLMenuItemElement
+NS_INTERFACE_TABLE_HEAD(nsHTMLMenuItemElement)
+ NS_HTML_CONTENT_INTERFACE_TABLE2(nsHTMLMenuItemElement,
+ nsIDOMHTMLCommandElement,
+ nsIDOMHTMLMenuItemElement)
+ NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLMenuItemElement,
+ nsGenericHTMLElement)
+NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLMenuItemElement)
+
+//NS_IMPL_ELEMENT_CLONE(nsHTMLMenuItemElement)
+nsresult
+nsHTMLMenuItemElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
+{
+ *aResult = nsnull;
+ nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
+ nsHTMLMenuItemElement *it = new nsHTMLMenuItemElement(ni.forget(),
+ NOT_FROM_PARSER);
+ if (!it) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ nsCOMPtr<nsINode> kungFuDeathGrip = it;
+ nsresult rv = CopyInnerTo(it);
+ if (NS_SUCCEEDED(rv)) {
+ switch (mType) {
+ case CMD_TYPE_CHECKBOX:
+ case CMD_TYPE_RADIO:
+ if (mCheckedDirty) {
+ // We no longer have our original checked state. Set our
+ // checked state on the clone.
+ it->mCheckedDirty = true;
+ it->mChecked = mChecked;
+ }
+ break;
+ }
+
+ kungFuDeathGrip.swap(*aResult);
+ }
+
+ return rv;
+}
+
+
+NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLMenuItemElement, Type, type,
+ kMenuItemDefaultType->tag)
+NS_IMPL_STRING_ATTR(nsHTMLMenuItemElement, Label, label)
+NS_IMPL_URI_ATTR(nsHTMLMenuItemElement, Icon, icon)
+NS_IMPL_BOOL_ATTR(nsHTMLMenuItemElement, Disabled, disabled)
+NS_IMPL_BOOL_ATTR(nsHTMLMenuItemElement, DefaultChecked, checked)
+//NS_IMPL_BOOL_ATTR(nsHTMLMenuItemElement, Checked, checked)
+NS_IMPL_STRING_ATTR(nsHTMLMenuItemElement, Radiogroup, radiogroup)
+
+NS_IMETHODIMP
+nsHTMLMenuItemElement::GetChecked(PRBool* aChecked)
+{
+ *aChecked = mChecked;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsHTMLMenuItemElement::SetChecked(PRBool aChecked)
+{
+ PRBool checkedChanged = mChecked != aChecked;
+
+ mChecked = aChecked;
+
+ if (mType == CMD_TYPE_RADIO) {
+ if (checkedChanged) {
+ if (mCheckedDirty) {
+ ClearCheckedVisitor visitor(this);
+ WalkRadioGroup(&visitor);
+ } else {
+ ClearCheckedVisitor visitor1(this);
+ SetCheckedDirtyVisitor visitor2;
+ CombinedVisitor visitor(&visitor1, &visitor2);
+ WalkRadioGroup(&visitor);
+ }
+ } else if (!mCheckedDirty) {
+ SetCheckedDirtyVisitor visitor;
+ WalkRadioGroup(&visitor);
+ }
+ } else {
+ mCheckedDirty = true;
+ }
+
+ return NS_OK;
+}
+
+nsresult
+nsHTMLMenuItemElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
+{
+ if (aVisitor.mEvent->message == NS_MOUSE_CLICK) {
+
+ PRBool originalCheckedValue = PR_FALSE;
+ switch (mType) {
+ case CMD_TYPE_CHECKBOX:
+ originalCheckedValue = mChecked;
+ SetChecked(!originalCheckedValue);
+ aVisitor.mItemFlags |= NS_CHECKED_IS_TOGGLED;
+ break;
+ case CMD_TYPE_RADIO:
+ nsCOMPtr<nsIDOMHTMLMenuItemElement> selectedRadio = GetSelectedRadio();
+ aVisitor.mItemData = selectedRadio;
+
+ originalCheckedValue = mChecked;
+ if (!originalCheckedValue) {
+ SetChecked(PR_TRUE);
+ aVisitor.mItemFlags |= NS_CHECKED_IS_TOGGLED;
+ }
+ break;
+ }
+
+ if (originalCheckedValue) {
+ aVisitor.mItemFlags |= NS_ORIGINAL_CHECKED_VALUE;
+ }
+
+ // We must cache type because mType may change during JS event.
+ aVisitor.mItemFlags |= mType;
+ }
+
+ return nsGenericHTMLElement::PreHandleEvent(aVisitor);
+}
+
+nsresult
+nsHTMLMenuItemElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
+{
+ // Check to see if the event was cancelled.
+ if (aVisitor.mEvent->message == NS_MOUSE_CLICK &&
+ aVisitor.mItemFlags & NS_CHECKED_IS_TOGGLED &&
+ aVisitor.mEventStatus == nsEventStatus_eConsumeNoDefault) {
+ PRBool originalCheckedValue =
+ !!(aVisitor.mItemFlags & NS_ORIGINAL_CHECKED_VALUE);
+ PRUint8 oldType = NS_MENUITEM_TYPE(aVisitor.mItemFlags);
+
+ nsCOMPtr<nsIDOMHTMLMenuItemElement> selectedRadio =
+ do_QueryInterface(aVisitor.mItemData);
+ if (selectedRadio) {
+ selectedRadio->SetChecked(PR_TRUE);
+ if (mType != CMD_TYPE_RADIO) {
+ SetChecked(PR_FALSE);
+ }
+ } else if (oldType == CMD_TYPE_CHECKBOX) {
+ SetChecked(originalCheckedValue);
+ }
+ }
+
+ return NS_OK;
+}
+
+nsresult
+nsHTMLMenuItemElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+ nsIContent* aBindingParent,
+ PRBool aCompileEventHandlers)
+{
+ nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
+ aBindingParent,
+ aCompileEventHandlers);
+
+ if (NS_SUCCEEDED(rv) && aDocument && mType == CMD_TYPE_RADIO) {
+ AddedToRadioGroup();
+ }
+
+ return rv;
+}
+
+PRBool
+nsHTMLMenuItemElement::ParseAttribute(PRInt32 aNamespaceID,
+ nsIAtom* aAttribute,
+ const nsAString& aValue,
+ nsAttrValue& aResult)
+{
+ if (aNamespaceID == kNameSpaceID_None) {
+ if (aAttribute == nsGkAtoms::type) {
+ PRBool success = aResult.ParseEnumValue(aValue, kMenuItemTypeTable,
+ PR_FALSE);
+ if (success) {
+ mType = aResult.GetEnumValue();
+ } else {
+ mType = kMenuItemDefaultType->value;
+ }
+
+ return success;
+ }
+
+ if (aAttribute == nsGkAtoms::radiogroup) {
+ aResult.ParseAtom(aValue);
+ return PR_TRUE;
+ }
+ }
+
+ return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
+ aResult);
+}
+
+void
+nsHTMLMenuItemElement::DoneCreatingElement()
+{
+ mParserCreating = false;
+
+ if (mShouldInitChecked) {
+ InitChecked();
+ mShouldInitChecked = false;
+ }
+}
+
+nsresult
+nsHTMLMenuItemElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
+ const nsAString* aValue, PRBool aNotify)
+{
+ if (aNameSpaceID == kNameSpaceID_None) {
+ if ((aName == nsGkAtoms::radiogroup || aName == nsGkAtoms::type) &&
+ mType == CMD_TYPE_RADIO &&
+ !mParserCreating) {
+ if (IsInDoc() && GetParent()) {
+ AddedToRadioGroup();
+ }
+ }
+
+ // Checked must be set no matter what type of menuitem it is, since
+ // GetChecked() must reflect the new value
+ if (aName == nsGkAtoms::checked &&
+ !mCheckedDirty) {
+ if (mParserCreating) {
+ mShouldInitChecked = true;
+ } else {
+ InitChecked();
+ }
+ }
+ }
+
+ return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
+ aNotify);
+}
+
+void
+nsHTMLMenuItemElement::WalkRadioGroup(Visitor* aVisitor)
+{
+ nsIContent* parent = GetParent();
+ if (!parent) {
+ aVisitor->Visit(this);
+ return;
+ }
+
+ nsAttrInfo info1(GetAttrInfo(kNameSpaceID_None,
+ nsGkAtoms::radiogroup));
+ PRBool info1Empty = !info1.mValue || info1.mValue->IsEmptyString();
+
+ for (nsIContent* cur = parent->GetFirstChild();
+ cur;
+ cur = cur->GetNextSibling()) {
+ nsHTMLMenuItemElement* menuitem = nsHTMLMenuItemElement::FromContent(cur);
+
+ if (!menuitem || menuitem->GetType() != CMD_TYPE_RADIO) {
+ continue;
+ }
+
+ nsAttrInfo info2(menuitem->GetAttrInfo(kNameSpaceID_None,
+ nsGkAtoms::radiogroup));
+ PRBool info2Empty = !info2.mValue || info2.mValue->IsEmptyString();
+
+ if (info1Empty != info2Empty ||
+ info1.mValue && info2.mValue && !info1.mValue->Equals(*info2.mValue)) {
+ continue;
+ }
+
+ if (!aVisitor->Visit(menuitem)) {
+ break;
+ }
+ }
+}
+
+nsHTMLMenuItemElement*
+nsHTMLMenuItemElement::GetSelectedRadio()
+{
+ nsHTMLMenuItemElement* result = nsnull;
+
+ GetCheckedVisitor visitor(&result);
+ WalkRadioGroup(&visitor);
+
+ return result;
+}
+
+void
+nsHTMLMenuItemElement::AddedToRadioGroup()
+{
+ PRBool checkedDirty = mCheckedDirty;
+ if (mChecked) {
+ ClearCheckedVisitor visitor1(this);
+ GetCheckedDirtyVisitor visitor2(&checkedDirty, this);
+ CombinedVisitor visitor(&visitor1, &visitor2);
+ WalkRadioGroup(&visitor);
+ } else {
+ GetCheckedDirtyVisitor visitor(&checkedDirty, this);
+ WalkRadioGroup(&visitor);
+ }
+ mCheckedDirty = checkedDirty;
+}
+
+void
+nsHTMLMenuItemElement::InitChecked()
+{
+ PRBool defaultChecked;
+ GetDefaultChecked(&defaultChecked);
+ mChecked = defaultChecked;
+ if (mType == CMD_TYPE_RADIO) {
+ ClearCheckedVisitor visitor(this);
+ WalkRadioGroup(&visitor);
+ }
+}
new file mode 100644
--- /dev/null
+++ b/content/html/content/src/nsHTMLMenuItemElement.h
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIDOMHTMLMenuItemElement.h"
+#include "nsGenericHTMLElement.h"
+
+class Visitor;
+
+class nsHTMLMenuItemElement : public nsGenericHTMLElement,
+ public nsIDOMHTMLMenuItemElement
+{
+public:
+ nsHTMLMenuItemElement(already_AddRefed<nsINodeInfo> aNodeInfo,
+ mozilla::dom::FromParser aFromParser);
+ virtual ~nsHTMLMenuItemElement();
+
+ /** Typesafe, non-refcounting cast from nsIContent. Cheaper than QI. **/
+ static nsHTMLMenuItemElement* FromContent(nsIContent* aContent)
+ {
+ if (aContent && aContent->IsHTML(nsGkAtoms::menuitem)) {
+ return static_cast<nsHTMLMenuItemElement*>(aContent);
+ }
+ return nsnull;
+ }
+
+ // nsISupports
+ NS_DECL_ISUPPORTS_INHERITED
+
+ // nsIDOMNode
+ NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
+
+ // nsIDOMElement
+ NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
+
+ // nsIDOMHTMLElement
+ NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
+
+ // nsIDOMHTMLCommandElement
+ NS_DECL_NSIDOMHTMLCOMMANDELEMENT
+
+ // nsIDOMHTMLMenuItemElement
+ NS_DECL_NSIDOMHTMLMENUITEMELEMENT
+
+ virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
+ virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
+
+ virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+ nsIContent* aBindingParent,
+ PRBool aCompileEventHandlers);
+
+ virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
+ nsIAtom* aAttribute,
+ const nsAString& aValue,
+ nsAttrValue& aResult);
+
+ virtual void DoneCreatingElement();
+
+ virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+
+ virtual nsXPCClassInfo* GetClassInfo();
+
+ PRUint8 GetType() const { return mType; }
+
+ /**
+ * Syntax sugar to make it easier to check for checked and checked dirty
+ */
+ PRBool IsChecked() const { return mChecked; }
+ PRBool IsCheckedDirty() const { return mCheckedDirty; }
+
+protected:
+ virtual nsresult AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
+ const nsAString* aValue, PRBool aNotify);
+
+ void WalkRadioGroup(Visitor* aVisitor);
+
+ nsHTMLMenuItemElement* GetSelectedRadio();
+
+ void AddedToRadioGroup();
+
+ void InitChecked();
+
+ friend class ClearCheckedVisitor;
+ friend class SetCheckedDirtyVisitor;
+
+ void ClearChecked() { mChecked = false; }
+ void SetCheckedDirty() { mCheckedDirty = true; }
+
+private:
+ PRUint8 mType : 2;
+ bool mParserCreating : 1;
+ bool mShouldInitChecked : 1;
+ bool mCheckedDirty : 1;
+ bool mChecked : 1;
+};
--- a/content/html/content/src/nsHTMLSelectElement.cpp
+++ b/content/html/content/src/nsHTMLSelectElement.cpp
@@ -355,22 +355,16 @@ nsHTMLSelectElement::RemoveOptionsFromLi
UpdateState(aNotify);
}
}
return NS_OK;
}
-static PRBool IsOptGroup(nsIContent *aContent)
-{
- return (aContent->NodeInfo()->Equals(nsGkAtoms::optgroup) &&
- aContent->IsHTML());
-}
-
// If the document is such that recursing over these options gets us
// deeper than four levels, there is something terribly wrong with the
// world.
nsresult
nsHTMLSelectElement::InsertOptionsIntoListRecurse(nsIContent* aOptions,
PRInt32* aInsertIndex,
PRInt32 aDepth)
{
@@ -389,17 +383,17 @@ nsHTMLSelectElement::InsertOptionsIntoLi
// If it's at the top level, then we just found out there are non-options
// at the top level, which will throw off the insert count
if (aDepth == 0) {
mNonOptionChildren++;
}
// Recurse down into optgroups
- if (IsOptGroup(aOptions)) {
+ if (aOptions->IsHTML(nsGkAtoms::optgroup)) {
mOptGroupCount++;
PRUint32 numChildren = aOptions->GetChildCount();
for (PRUint32 i = 0; i < numChildren; ++i) {
nsresult rv = InsertOptionsIntoListRecurse(aOptions->GetChildAt(i),
aInsertIndex, aDepth+1);
NS_ENSURE_SUCCESS(rv, rv);
}
@@ -433,17 +427,17 @@ nsHTMLSelectElement::RemoveOptionsFromLi
}
// Yay, one less artifact at the top level.
if (aDepth == 0) {
mNonOptionChildren--;
}
// Recurse down deeper for options
- if (mOptGroupCount && IsOptGroup(aOptions)) {
+ if (mOptGroupCount && aOptions->IsHTML(nsGkAtoms::optgroup)) {
mOptGroupCount--;
PRUint32 numChildren = aOptions->GetChildCount();
for (PRUint32 i = 0; i < numChildren; ++i) {
nsresult rv = RemoveOptionsFromListRecurse(aOptions->GetChildAt(i),
aRemoveIndex,
aNumRemoved,
aDepth + 1);
@@ -1868,25 +1862,25 @@ void nsHTMLSelectElement::DispatchConten
}
}
}
}
static void
AddOptionsRecurse(nsIContent* aRoot, nsHTMLOptionCollection* aArray)
{
- nsIContent* child;
- for(PRUint32 i = 0; (child = aRoot->GetChildAt(i)); ++i) {
- nsHTMLOptionElement *opt = nsHTMLOptionElement::FromContent(child);
+ for (nsIContent* cur = aRoot->GetFirstChild();
+ cur;
+ cur = cur->GetNextSibling()) {
+ nsHTMLOptionElement* opt = nsHTMLOptionElement::FromContent(cur);
if (opt) {
// If we fail here, then at least we've tried our best
aArray->AppendOption(opt);
- }
- else if (IsOptGroup(child)) {
- AddOptionsRecurse(child, aArray);
+ } else if (cur->IsHTML(nsGkAtoms::optgroup)) {
+ AddOptionsRecurse(cur, aArray);
}
}
}
void
nsHTMLSelectElement::RebuildOptionsArray(PRBool aNotify)
{
mOptions->Clear();
@@ -1964,25 +1958,25 @@ nsHTMLSelectElement::GetValidationMessag
}
#ifdef DEBUG
static void
VerifyOptionsRecurse(nsIContent* aRoot, PRInt32& aIndex,
nsHTMLOptionCollection* aArray)
{
- nsIContent* child;
- for(PRUint32 i = 0; (child = aRoot->GetChildAt(i)); ++i) {
- nsCOMPtr<nsIDOMHTMLOptionElement> opt = do_QueryInterface(child);
+ for (nsIContent* cur = aRoot->GetFirstChild();
+ cur;
+ cur = cur->GetNextSibling()) {
+ nsCOMPtr<nsIDOMHTMLOptionElement> opt = do_QueryInterface(cur);
if (opt) {
NS_ASSERTION(opt == aArray->ItemAsOption(aIndex++),
"Options collection broken");
- }
- else if (IsOptGroup(child)) {
- VerifyOptionsRecurse(child, aIndex, aArray);
+ } else if (cur->IsHTML(nsGkAtoms::optgroup)) {
+ VerifyOptionsRecurse(cur, aIndex, aArray);
}
}
}
void
nsHTMLSelectElement::VerifyOptionsArray()
{
PRInt32 aIndex = 0;
--- a/content/html/content/src/nsHTMLSharedElement.cpp
+++ b/content/html/content/src/nsHTMLSharedElement.cpp
@@ -33,17 +33,16 @@
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsIDOMHTMLParamElement.h"
#include "nsIDOMHTMLBaseElement.h"
#include "nsIDOMHTMLDirectoryElement.h"
-#include "nsIDOMHTMLMenuElement.h"
#include "nsIDOMHTMLQuoteElement.h"
#include "nsIDOMHTMLHeadElement.h"
#include "nsIDOMHTMLHtmlElement.h"
#include "nsGenericHTMLElement.h"
#include "nsGkAtoms.h"
#include "nsStyleConsts.h"
#include "nsRuleData.h"
#include "nsMappedAttributes.h"
@@ -54,17 +53,16 @@
// XXX nav4 has type= start= (same as OL/UL)
extern nsAttrValue::EnumTable kListTypeTable[];
class nsHTMLSharedElement : public nsGenericHTMLElement,
public nsIDOMHTMLParamElement,
public nsIDOMHTMLBaseElement,
public nsIDOMHTMLDirectoryElement,
- public nsIDOMHTMLMenuElement,
public nsIDOMHTMLQuoteElement,
public nsIDOMHTMLHeadElement,
public nsIDOMHTMLHtmlElement
{
public:
nsHTMLSharedElement(already_AddRefed<nsINodeInfo> aNodeInfo);
virtual ~nsHTMLSharedElement();
@@ -84,19 +82,16 @@ public:
NS_DECL_NSIDOMHTMLPARAMELEMENT
// nsIDOMHTMLBaseElement
NS_DECL_NSIDOMHTMLBASEELEMENT
// nsIDOMHTMLDirectoryElement
NS_DECL_NSIDOMHTMLDIRECTORYELEMENT
- // nsIDOMHTMLMenuElement
- // Same as directoryelement
-
// nsIDOMHTMLQuoteElement
NS_DECL_NSIDOMHTMLQUOTEELEMENT
// nsIDOMHTMLHeadElement
NS_DECL_NSIDOMHTMLHEADELEMENT
// nsIDOMHTMLHtmlElement
NS_DECL_NSIDOMHTMLHTMLELEMENT
@@ -152,36 +147,32 @@ nsHTMLSharedElement::~nsHTMLSharedElemen
NS_IMPL_ADDREF_INHERITED(nsHTMLSharedElement, nsGenericElement)
NS_IMPL_RELEASE_INHERITED(nsHTMLSharedElement, nsGenericElement)
DOMCI_DATA(HTMLParamElement, nsHTMLSharedElement)
DOMCI_DATA(HTMLBaseElement, nsHTMLSharedElement)
DOMCI_DATA(HTMLDirectoryElement, nsHTMLSharedElement)
-DOMCI_DATA(HTMLMenuElement, nsHTMLSharedElement)
DOMCI_DATA(HTMLQuoteElement, nsHTMLSharedElement)
DOMCI_DATA(HTMLHeadElement, nsHTMLSharedElement)
DOMCI_DATA(HTMLHtmlElement, nsHTMLSharedElement)
nsIClassInfo*
nsHTMLSharedElement::GetClassInfoInternal()
{
if (mNodeInfo->Equals(nsGkAtoms::param)) {
return NS_GetDOMClassInfoInstance(eDOMClassInfo_HTMLParamElement_id);
}
if (mNodeInfo->Equals(nsGkAtoms::base)) {
return NS_GetDOMClassInfoInstance(eDOMClassInfo_HTMLBaseElement_id);
}
if (mNodeInfo->Equals(nsGkAtoms::dir)) {
return NS_GetDOMClassInfoInstance(eDOMClassInfo_HTMLDirectoryElement_id);
}
- if (mNodeInfo->Equals(nsGkAtoms::menu)) {
- return NS_GetDOMClassInfoInstance(eDOMClassInfo_HTMLMenuElement_id);
- }
if (mNodeInfo->Equals(nsGkAtoms::q)) {
return NS_GetDOMClassInfoInstance(eDOMClassInfo_HTMLQuoteElement_id);
}
if (mNodeInfo->Equals(nsGkAtoms::blockquote)) {
return NS_GetDOMClassInfoInstance(eDOMClassInfo_HTMLQuoteElement_id);
}
if (mNodeInfo->Equals(nsGkAtoms::head)) {
return NS_GetDOMClassInfoInstance(eDOMClassInfo_HTMLHeadElement_id);
@@ -198,17 +189,16 @@ NS_INTERFACE_TABLE_HEAD(nsHTMLSharedElem
nsIDOMHTMLParamElement)
NS_OFFSET_AND_INTERFACE_TABLE_END
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE_AMBIGUOUS(nsHTMLSharedElement,
nsGenericHTMLElement,
nsIDOMHTMLParamElement)
NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLParamElement, param)
NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLBaseElement, base)
NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLDirectoryElement, dir)
- NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLMenuElement, menu)
NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLQuoteElement, q)
NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLQuoteElement, blockquote)
NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLHeadElement, head)
NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLHtmlElement, html)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_GETTER(GetClassInfoInternal)
NS_HTML_CONTENT_INTERFACE_MAP_END
@@ -219,19 +209,16 @@ NS_IMPL_ELEMENT_CLONE(nsHTMLSharedElemen
NS_IMPL_STRING_ATTR(nsHTMLSharedElement, Name, name)
NS_IMPL_STRING_ATTR(nsHTMLSharedElement, Type, type)
NS_IMPL_STRING_ATTR(nsHTMLSharedElement, Value, value)
NS_IMPL_STRING_ATTR(nsHTMLSharedElement, ValueType, valuetype)
// nsIDOMHTMLDirectoryElement
NS_IMPL_BOOL_ATTR(nsHTMLSharedElement, Compact, compact)
-// nsIDOMHTMLMenuElement
-//NS_IMPL_BOOL_ATTR(nsHTMLSharedElement, Compact, compact)
-
// nsIDOMHTMLQuoteElement
NS_IMPL_URI_ATTR(nsHTMLSharedElement, Cite, cite)
// nsIDOMHTMLHeadElement
// Empty
// nsIDOMHTMLHtmlElement
NS_IMPL_STRING_ATTR(nsHTMLSharedElement, Version, version)
@@ -270,32 +257,31 @@ nsHTMLSharedElement::SetHref(const nsASt
PRBool
nsHTMLSharedElement::ParseAttribute(PRInt32 aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult)
{
if (aNamespaceID == kNameSpaceID_None &&
- (mNodeInfo->Equals(nsGkAtoms::dir) ||
- mNodeInfo->Equals(nsGkAtoms::menu))) {
+ mNodeInfo->Equals(nsGkAtoms::dir)) {
if (aAttribute == nsGkAtoms::type) {
return aResult.ParseEnumValue(aValue, kListTypeTable, PR_FALSE);
}
if (aAttribute == nsGkAtoms::start) {
return aResult.ParseIntWithBounds(aValue, 1);
}
}
return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
aResult);
}
static void
-DirectoryMenuMapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+DirectoryMapAttributesIntoRule(const nsMappedAttributes* aAttributes,
nsRuleData* aData)
{
if (aData->mSIDs & NS_STYLE_INHERIT_BIT(List)) {
nsCSSValue* listStyleType = aData->ValueForListStyleType();
if (listStyleType->GetUnit() == eCSSUnit_Null) {
// type: enum
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::type);
if (value) {
@@ -481,14 +467,14 @@ nsHTMLSharedElement::UnbindFromTree(PRBo
SetBaseTargetUsingFirstBaseWithTarget(doc, nsnull);
}
}
}
nsMapRuleToAttributesFunc
nsHTMLSharedElement::GetAttributeMappingFunction() const
{
- if (mNodeInfo->Equals(nsGkAtoms::dir) || mNodeInfo->Equals(nsGkAtoms::menu)) {
- return &DirectoryMenuMapAttributesIntoRule;
+ if (mNodeInfo->Equals(nsGkAtoms::dir)) {
+ return &DirectoryMapAttributesIntoRule;
}
return nsGenericHTMLElement::GetAttributeMappingFunction();
}
--- a/content/html/content/src/nsTextEditorState.cpp
+++ b/content/html/content/src/nsTextEditorState.cpp
@@ -31,16 +31,18 @@
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
+#include "nsTextEditorState.h"
+
#include "nsCOMPtr.h"
#include "nsIPresShell.h"
#include "nsIView.h"
#include "nsCaret.h"
#include "nsEditorCID.h"
#include "nsLayoutCID.h"
#include "nsITextControlFrame.h"
#include "nsIPlaintextEditor.h"
@@ -60,18 +62,16 @@
#include "nsIDocumentEncoder.h"
#include "nsISelectionPrivate.h"
#include "nsPIDOMWindow.h"
#include "nsServiceManagerUtils.h"
#include "nsIEditor.h"
#include "nsTextEditRules.h"
#include "nsEventListenerManager.h"
-#include "nsTextEditorState.h"
-
using namespace mozilla::dom;
static NS_DEFINE_CID(kTextEditorCID, NS_TEXTEDITOR_CID);
static nsINativeKeyBindings *sNativeInputBindings = nsnull;
static nsINativeKeyBindings *sNativeTextAreaBindings = nsnull;
class RestoreSelectionState : public nsRunnable {
--- a/content/html/content/src/nsTextEditorState.h
+++ b/content/html/content/src/nsTextEditorState.h
@@ -35,16 +35,17 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsTextEditorState_h__
#define nsTextEditorState_h__
#include "nsAutoPtr.h"
+#include "nsString.h"
#include "nsITextControlElement.h"
#include "nsITextControlFrame.h"
#include "nsCycleCollectionParticipant.h"
class nsTextInputListener;
class nsTextControlFrame;
class nsTextInputSelectionImpl;
class nsAnonDivObserver;
--- a/content/html/content/test/Makefile.in
+++ b/content/html/content/test/Makefile.in
@@ -141,17 +141,16 @@ include $(topsrcdir)/config/rules.mk
test_bug406596.html \
test_bug408231.html \
test_bug417760.html \
file_bug417760.png \
test_formSubmission.html \
test_formSubmission2.html \
file_formSubmission_text.txt \
file_formSubmission_img.jpg \
- test_bug418756.html \
test_bug421640.html \
test_bug424698.html \
test_bug428135.xhtml \
test_bug430351.html \
test_bug430392.html \
bug441930_iframe.html \
test_bug441930.html \
test_bug442801.html \
@@ -275,12 +274,14 @@ include $(topsrcdir)/config/rules.mk
test_bug659743.xml \
test_bug660663.html \
test_bug664299.html \
test_bug666200.html \
test_bug666666.html \
test_bug674558.html \
test_bug583533.html \
test_restore_from_parser_fragment.html \
+ test_bug617528.html \
+ test_checked.html \
$(NULL)
libs:: $(_TEST_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/test_bug617528.html
@@ -0,0 +1,74 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=617528
+-->
+<head>
+ <title>Test for Bug 617528</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <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=617528">Mozilla Bug 617528</a>
+<p id="display"></p>
+<div id="content">
+ <menu>
+ <menuitem id="checkbox" type="checkbox" label="Checkbox" checked></menuitem>
+ <menuitem id="radio1" type="radio" label="Radio1" checked></menuitem>
+ <menuitem id="radio2" type="radio" label="Radio2"></menuitem>
+ </menu>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 617528 **/
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function() {
+ function click(element, preventDefault, checked) {
+ function handleClick(event) {
+ is(this.checked, checked,
+ "checking .checked (" + this.id + ")");
+ if (preventDefault)
+ event.preventDefault();
+ }
+ element.addEventListener("click", handleClick);
+ element.click();
+ element.removeEventListener("click", handleClick);
+ }
+
+ function verify(elements, data) {
+ for (var i = 0; i < elements.length; i++) {
+ var element = elements[i];
+ is(element.checked, data[i*2],
+ "checking .checked (" + element.id + ")");
+ is(element.defaultChecked, data[i*2+1],
+ 'checking .defaultChecked (' + element.id + ")");
+ }
+ }
+
+ var checkbox = document.getElementById("checkbox");
+ click(checkbox, false, false);
+ verify([checkbox], [false, true]);
+
+ click(checkbox, true, true);
+ verify([checkbox], [false, true]);
+
+ var radio1 = document.getElementById("radio1");
+ var radio2 = document.getElementById("radio2");
+ click(radio2, false, true);
+ verify([radio1, radio2], [false, true,
+ true, false]);
+
+ click(radio1, true, true);
+ verify([radio1, radio2], [false, true,
+ true, false]);
+
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
rename from content/html/content/test/test_bug418756.html
rename to content/html/content/test/test_checked.html
--- a/content/html/content/test/test_bug418756.html
+++ b/content/html/content/test/test_checked.html
@@ -1,32 +1,47 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=418756
+https://bugzilla.mozilla.org/show_bug.cgi?id=617528
-->
<head>
- <title>Test for Bug 418756</title>
+ <title>Test for Bug 418756 and 617528</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/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=418756">Mozilla Bug 418756</a>
+Mozilla bug
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=418756">418756</a>
+and
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=617528">617528</a>
<p id="display"></p>
<div id="content">
<form id="f1">
</form>
<form id="f2">
</form>
+ <menu id="m1">
+ </menu>
+ <menu id="m2">
+ </menu>
</div>
<pre id="test">
<script class="testbody" type="text/javascript; version=1.7">
-/** Test for Bug 418756 **/
+/** Test for Bug 418756 and 617528 **/
+let group1;
+let group2;
+let group3;
+
+let tags = ["input", "menuitem"];
+for each (let tag in tags) {
+
function bounce(node) {
let n = node.nextSibling;
let p = node.parentNode;
p.removeChild(node);
p.insertBefore(node, n);
}
let createdNodes = [];
@@ -45,23 +60,23 @@ let typeMapper = {
'c': 'checkbox',
'r': 'radio'
};
let id = 0;
// type can be 'c' for 'checkbox' and 'r' for 'radio'
function createNode(type, name, checked) {
- let node = document.createElement("input");
+ let node = document.createElement(tag);
node.setAttribute("type", typeMapper[type]);
if (checked) {
node.setAttribute("checked", "checked");
}
node.setAttribute("id", type + (++id));
- node.setAttribute("name", name);
+ node.setAttribute(tag == "input" ? "name" : "radiogroup", name);
createdNodes.push(node);
return node;
}
let types = ['c', 'r'];
// First make sure that setting .checked makes .defaultChecked changes no
// longer affect .checked.
@@ -92,45 +107,45 @@ for each (let type in types) {
}
cleanup();
// Now check that bouncing a control that's the only one of its kind has no
// effect
for each (let type in types) {
let n = createNode(type, 'test1', true);
- $("f1").appendChild(n);
+ $(tag == "input" ? "f1" : "m1").appendChild(n);
n.checked = false;
n.defaultChecked = false;
bounce(n);
n.defaultChecked = true;
is(n.checked, false, "We set .checked on this " + typeMapper[type]);
}
cleanup();
// Now check that playing with a single radio in a group affects all
// other radios in the group (but not radios not in that group)
-let group1 = [ createNode('r', 'g1', false),
- createNode('r', 'g1', false),
- createNode('r', 'g1', false) ];
-let group2 = [ createNode('r', 'g2', false),
- createNode('r', 'g2', false),
- createNode('r', 'g2', false) ];
-let group3 = [ createNode('r', 'g1', false),
- createNode('r', 'g1', false),
- createNode('r', 'g1', false) ];
+group1 = [ createNode('r', 'g1', false),
+ createNode('r', 'g1', false),
+ createNode('r', 'g1', false) ];
+group2 = [ createNode('r', 'g2', false),
+ createNode('r', 'g2', false),
+ createNode('r', 'g2', false) ];
+group3 = [ createNode('r', 'g1', false),
+ createNode('r', 'g1', false),
+ createNode('r', 'g1', false) ];
for each (let g in group1) {
- $("f1").appendChild(g);
+ $(tag == "input" ? "f1" : "m1").appendChild(g);
}
for each (let g in group2) {
- $("f1").appendChild(g);
+ $(tag == "input" ? "f1" : "m1").appendChild(g);
}
for each (let g in group3) {
- $("f2").appendChild(g);
+ $(tag == "input" ? "f2" : "m2").appendChild(g);
}
for each (let n in [1, 2, 3]) {
for each (let g in window["group"+n]) {
is(g.defaultChecked, false,
"group" + n + "[" + window["group"+n].indexOf(g) +
"] defaultChecked wrong pass 1");
is(g.checked, false,
@@ -330,13 +345,15 @@ for each (let n in [1, 2, 3]) {
group1.indexOf(g) == 0)) ||
(n == 2 && group2.indexOf(g) == 0),
"group" + n + "[" + window["group"+n].indexOf(g) +
"] checked wrong pass 15");
}
}
cleanup();
+
+}
</script>
</pre>
</body>
</html>
--- a/content/html/document/src/nsHTMLContentSink.cpp
+++ b/content/html/document/src/nsHTMLContentSink.cpp
@@ -1016,17 +1016,20 @@ SinkContext::AddLeaf(const nsIParserNode
// Bug 40072: Don't evaluate METAs after FRAMESET.
if (!mSink->mInsideNoXXXTag && !mSink->mFrameset) {
rv = mSink->ProcessMETATag(content);
}
break;
case eHTMLTag_input:
content->DoneCreatingElement();
-
+ break;
+
+ case eHTMLTag_menuitem:
+ content->DoneCreatingElement();
break;
default:
break;
}
}
break;
--- a/content/xbl/src/nsXBLBinding.cpp
+++ b/content/xbl/src/nsXBLBinding.cpp
@@ -68,23 +68,17 @@
#include "nsXBLService.h"
#include "nsXBLInsertionPoint.h"
#include "nsIXPConnect.h"
#include "nsIScriptContext.h"
#include "nsCRT.h"
// Event listeners
#include "nsEventListenerManager.h"
-#include "nsIDOMMouseListener.h"
-#include "nsIDOMMouseMotionListener.h"
-#include "nsIDOMLoadListener.h"
-#include "nsIDOMFocusListener.h"
-#include "nsIDOMKeyListener.h"
-#include "nsIDOMFormListener.h"
-#include "nsIDOMContextMenuListener.h"
+#include "nsIDOMEventListener.h"
#include "nsAttrName.h"
#include "nsGkAtoms.h"
#include "nsIDOMAttr.h"
#include "nsIDOMNamedNodeMap.h"
#include "nsXBLPrototypeHandler.h"
--- a/content/xml/document/src/nsXMLContentSink.cpp
+++ b/content/xml/document/src/nsXMLContentSink.cpp
@@ -1065,17 +1065,18 @@ nsXMLContentSink::HandleStartElement(con
parent->AppendChildTo(content, PR_FALSE);
}
}
// Some HTML nodes need DoneCreatingElement() called to initialize
// properly (eg form state restoration).
if (nodeInfo->NamespaceID() == kNameSpaceID_XHTML) {
if (nodeInfo->NameAtom() == nsGkAtoms::input ||
- nodeInfo->NameAtom() == nsGkAtoms::button) {
+ nodeInfo->NameAtom() == nsGkAtoms::button ||
+ nodeInfo->NameAtom() == nsGkAtoms::menuitem) {
content->DoneCreatingElement();
} else if (nodeInfo->NameAtom() == nsGkAtoms::head && !mCurrentHead) {
mCurrentHead = content;
}
}
if (IsMonolithicContainer(nodeInfo)) {
mInMonolithicContainer++;
--- a/content/xslt/src/xslt/txMozillaXMLOutput.cpp
+++ b/content/xslt/src/xslt/txMozillaXMLOutput.cpp
@@ -338,17 +338,18 @@ txMozillaXMLOutput::endElement()
// Else, add this script element to the array of loading scripts.
if (rv == NS_ERROR_HTMLPARSER_BLOCK) {
nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(element);
rv = mNotifier->AddScriptElement(sele);
NS_ENSURE_SUCCESS(rv, rv);
}
} else if (ns == kNameSpaceID_XHTML &&
(localName == nsGkAtoms::input ||
- localName == nsGkAtoms::button)) {
+ localName == nsGkAtoms::button ||
+ localName == nsGkAtoms::menuitem)) {
element->DoneCreatingElement();
}
}
if (mCreatingNewDocument) {
// Handle all sorts of stylesheets
nsCOMPtr<nsIStyleSheetLinkingElement> ssle =
do_QueryInterface(mCurrentNode);
--- a/content/xul/content/Makefile.in
+++ b/content/xul/content/Makefile.in
@@ -38,16 +38,16 @@
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = xul
-PARALLEL_DIRS = src
+PARALLEL_DIRS = public src
ifdef ENABLE_TESTS
PARALLEL_DIRS += test
endif
include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/content/xul/content/public/Makefile.in
@@ -0,0 +1,51 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla code.
+#
+# The Initial Developer of the Original Code is Mozilla Foundation
+# Portions created by the Initial Developer are Copyright (C) 2011
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xul
+
+ifdef MOZ_XUL
+XPIDLSRCS = \
+ nsIXULContextMenuBuilder.idl \
+ $(NULL)
+endif
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/content/xul/content/public/nsIXULContextMenuBuilder.idl
@@ -0,0 +1,73 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsIDOMDocumentFragment;
+
+/**
+ * An interface for initialization of XUL context menu builder
+ * and for triggering of menuitem actions with assigned identifiers.
+ */
+
+[scriptable, uuid(f0c35053-14cc-4e23-a9db-f9a68fae8375)]
+interface nsIXULContextMenuBuilder : nsISupports
+{
+
+ /**
+ * Initialize builder before building.
+ *
+ * @param aDocumentFragment the fragment that will be used to append top
+ * level elements
+ *
+ * @param aGeneratedAttrName the name of the attribute that will be used
+ * to mark elements as generated.
+ *
+ * @param aIdentAttrName the name of the attribute that will be used for
+ * menuitem identification.
+ */
+ void init(in nsIDOMDocumentFragment aDocumentFragment,
+ in AString aGeneratedAttrName,
+ in AString aIdentAttrName);
+
+ /**
+ * Invoke the action of the menuitem with assigned identifier aIdent.
+ *
+ * @param aIdent the menuitem identifier
+ */
+ void click(in DOMString aIdent);
+
+};
--- a/content/xul/content/src/Makefile.in
+++ b/content/xul/content/src/Makefile.in
@@ -49,16 +49,17 @@ LIBRARY_NAME = gkconxulcon_s
LIBXUL_LIBRARY = 1
endif
ifdef MOZ_XUL
CPPSRCS += \
nsXULElement.cpp \
nsXULPopupListener.cpp \
+ nsXULContextMenuBuilder.cpp \
$(NULL)
endif
# we don't want the shared lib, but we want to force the creation of a
# static lib.
FORCE_STATIC_LIB = 1
include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/content/xul/content/src/nsXULContextMenuBuilder.cpp
@@ -0,0 +1,268 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsContentCreatorFunctions.h"
+#include "nsIDOMHTMLElement.h"
+#include "nsIDOMHTMLMenuItemElement.h"
+#include "nsXULContextMenuBuilder.h"
+
+
+nsXULContextMenuBuilder::nsXULContextMenuBuilder()
+ : mCurrentIdent(0)
+{
+}
+
+nsXULContextMenuBuilder::~nsXULContextMenuBuilder()
+{
+}
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULContextMenuBuilder)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULContextMenuBuilder)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFragment)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocument)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCurrentNode)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mElements)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULContextMenuBuilder)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFragment)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocument)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCurrentNode)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mElements)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXULContextMenuBuilder)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXULContextMenuBuilder)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULContextMenuBuilder)
+ NS_INTERFACE_MAP_ENTRY(nsIMenuBuilder)
+ NS_INTERFACE_MAP_ENTRY(nsIXULContextMenuBuilder)
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMenuBuilder)
+NS_INTERFACE_MAP_END
+
+
+NS_IMETHODIMP
+nsXULContextMenuBuilder::OpenContainer(const nsAString& aLabel)
+{
+ if (!mFragment) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+
+ if (!mCurrentNode) {
+ mCurrentNode = mFragment;
+ } else {
+ nsCOMPtr<nsIContent> menu;
+ nsresult rv = CreateElement(nsGkAtoms::menu, getter_AddRefs(menu));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ menu->SetAttr(kNameSpaceID_None, nsGkAtoms::label, aLabel, PR_FALSE);
+
+ nsCOMPtr<nsIContent> menuPopup;
+ rv = CreateElement(nsGkAtoms::menupopup, getter_AddRefs(menuPopup));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = menu->AppendChildTo(menuPopup, PR_FALSE);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = mCurrentNode->AppendChildTo(menu, PR_FALSE);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ mCurrentNode = menuPopup;
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULContextMenuBuilder::AddItemFor(nsIDOMHTMLMenuItemElement* aElement,
+ PRBool aCanLoadIcon)
+{
+ if (!mFragment) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+
+ nsCOMPtr<nsIContent> menuitem;
+ nsresult rv = CreateElement(nsGkAtoms::menuitem, getter_AddRefs(menuitem));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoString type;
+ aElement->GetType(type);
+ if (type.EqualsLiteral("checkbox") || type.EqualsLiteral("radio")) {
+ // The menu is only temporary, so we don't need to handle
+ // the radio type precisely.
+ menuitem->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
+ NS_LITERAL_STRING("checkbox"), PR_FALSE);
+ PRBool checked;
+ aElement->GetChecked(&checked);
+ if (checked) {
+ menuitem->SetAttr(kNameSpaceID_None, nsGkAtoms::checked,
+ NS_LITERAL_STRING("true"), PR_FALSE);
+ }
+ }
+
+ nsAutoString label;
+ aElement->GetLabel(label);
+ menuitem->SetAttr(kNameSpaceID_None, nsGkAtoms::label, label, PR_FALSE);
+
+ nsAutoString icon;
+ aElement->GetIcon(icon);
+ if (!icon.IsEmpty()) {
+ menuitem->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
+ NS_LITERAL_STRING("menuitem-iconic"), PR_FALSE);
+ if (aCanLoadIcon) {
+ menuitem->SetAttr(kNameSpaceID_None, nsGkAtoms::image, icon, PR_FALSE);
+ }
+ }
+
+ PRBool disabled;
+ aElement->GetDisabled(&disabled);
+ if (disabled) {
+ menuitem->SetAttr(kNameSpaceID_None, nsGkAtoms::disabled,
+ NS_LITERAL_STRING("true"), PR_FALSE);
+ }
+
+ nsAutoString ident;
+ ident.AppendInt(mCurrentIdent++);
+
+ menuitem->SetAttr(kNameSpaceID_None, mIdentAttr, ident, PR_FALSE);
+
+ rv = mCurrentNode->AppendChildTo(menuitem, PR_FALSE);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ mElements.AppendObject(aElement);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULContextMenuBuilder::AddSeparator()
+{
+ if (!mFragment) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+
+ nsCOMPtr<nsIContent> menuseparator;
+ nsresult rv = CreateElement(nsGkAtoms::menuseparator,
+ getter_AddRefs(menuseparator));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return mCurrentNode->AppendChildTo(menuseparator, PR_FALSE);
+}
+
+NS_IMETHODIMP
+nsXULContextMenuBuilder::UndoAddSeparator()
+{
+ if (!mFragment) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+
+ PRUint32 count = mCurrentNode->GetChildCount();
+ if (!count ||
+ mCurrentNode->GetChildAt(count - 1)->Tag() != nsGkAtoms::menuseparator) {
+ return NS_OK;
+ }
+
+ return mCurrentNode->RemoveChildAt(count - 1, PR_FALSE);
+}
+
+NS_IMETHODIMP
+nsXULContextMenuBuilder::CloseContainer()
+{
+ if (!mFragment) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+
+ if (mCurrentNode == mFragment) {
+ mCurrentNode = nsnull;
+ } else {
+ nsIContent* parent = mCurrentNode->GetParent();
+ mCurrentNode = parent->GetParent();
+ }
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsXULContextMenuBuilder::Init(nsIDOMDocumentFragment* aDocumentFragment,
+ const nsAString& aGeneratedAttrName,
+ const nsAString& aIdentAttrName)
+{
+ NS_ENSURE_ARG_POINTER(aDocumentFragment);
+
+ mFragment = do_QueryInterface(aDocumentFragment);
+ mDocument = mFragment->GetOwnerDocument();
+ mGeneratedAttr = do_GetAtom(aGeneratedAttrName);
+ mIdentAttr = do_GetAtom(aIdentAttrName);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULContextMenuBuilder::Click(const nsAString& aIdent)
+{
+ PRInt32 rv;
+ PRInt32 idx = nsString(aIdent).ToInteger(&rv);
+ if (NS_SUCCEEDED(rv)) {
+ nsCOMPtr<nsIDOMHTMLElement> element = mElements.SafeObjectAt(idx);
+ if (element) {
+ element->Click();
+ }
+ }
+
+ return NS_OK;
+}
+
+nsresult
+nsXULContextMenuBuilder::CreateElement(nsIAtom* aTag, nsIContent** aResult)
+{
+ *aResult = nsnull;
+
+ nsCOMPtr<nsINodeInfo> nodeInfo = mDocument->NodeInfoManager()->GetNodeInfo(
+ aTag, nsnull, kNameSpaceID_XUL, nsIDOMNode::ELEMENT_NODE);
+ NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
+
+ nsresult rv = NS_NewElement(aResult, kNameSpaceID_XUL, nodeInfo.forget(),
+ mozilla::dom::NOT_FROM_PARSER);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ (*aResult)->SetAttr(kNameSpaceID_None, mGeneratedAttr, EmptyString(),
+ PR_FALSE);
+
+ return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/content/xul/content/src/nsXULContextMenuBuilder.h
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsCOMPtr.h"
+#include "nsCOMArray.h"
+#include "nsIContent.h"
+#include "nsIMenuBuilder.h"
+#include "nsIXULContextMenuBuilder.h"
+#include "nsIDOMDocumentFragment.h"
+#include "nsCycleCollectionParticipant.h"
+
+class nsXULContextMenuBuilder : public nsIMenuBuilder,
+ public nsIXULContextMenuBuilder
+{
+public:
+ nsXULContextMenuBuilder();
+ virtual ~nsXULContextMenuBuilder();
+
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXULContextMenuBuilder,
+ nsIMenuBuilder)
+ NS_DECL_NSIMENUBUILDER
+
+ NS_DECL_NSIXULCONTEXTMENUBUILDER
+
+protected:
+ nsresult CreateElement(nsIAtom* aTag, nsIContent** aResult);
+
+ nsCOMPtr<nsIContent> mFragment;
+ nsCOMPtr<nsIDocument> mDocument;
+ nsCOMPtr<nsIAtom> mGeneratedAttr;
+ nsCOMPtr<nsIAtom> mIdentAttr;
+
+ nsCOMPtr<nsIContent> mCurrentNode;
+ PRInt32 mCurrentIdent;
+
+ nsCOMArray<nsIDOMHTMLElement> mElements;
+};
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -61,23 +61,16 @@
#include "nsIDOMEvent.h"
#include "nsIPrivateDOMEvent.h"
#include "nsHashtable.h"
#include "nsIAtom.h"
#include "nsIBaseWindow.h"
#include "nsIDOMAttr.h"
#include "nsIDOMDocument.h"
#include "nsIDOMElement.h"
-#include "nsIDOMMouseListener.h"
-#include "nsIDOMMouseMotionListener.h"
-#include "nsIDOMLoadListener.h"
-#include "nsIDOMFocusListener.h"
-#include "nsIDOMKeyListener.h"
-#include "nsIDOMFormListener.h"
-#include "nsIDOMContextMenuListener.h"
#include "nsIDOMEventListener.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMXULCommandDispatcher.h"
#include "nsIDOMXULElement.h"
#include "nsIDOMElementCSSInlineStyle.h"
#include "nsIDOMXULSelectCntrlItemEl.h"
#include "nsIDocument.h"
#include "nsEventListenerManager.h"
--- a/content/xul/document/src/nsXULCommandDispatcher.h
+++ b/content/xul/document/src/nsXULCommandDispatcher.h
@@ -43,17 +43,16 @@
*/
#ifndef nsXULCommandDispatcher_h__
#define nsXULCommandDispatcher_h__
#include "nsCOMPtr.h"
#include "nsIDOMXULCommandDispatcher.h"
-#include "nsIDOMFocusListener.h"
#include "nsWeakReference.h"
#include "nsIDOMNode.h"
#include "nsString.h"
#include "nsCycleCollectionParticipant.h"
class nsIDOMElement;
class nsPIWindowRoot;
--- a/db/Makefile.in
+++ b/db/Makefile.in
@@ -37,19 +37,9 @@
DEPTH = ..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
-ifndef NSS_DISABLE_DBM
-ifdef MOZ_MORK
-PARALLEL_DIRS = mdb mork
-endif
-endif
-
-ifdef MOZ_MORKREADER
-PARALLEL_DIRS += morkreader
-endif
-
include $(topsrcdir)/config/rules.mk
deleted file mode 100644
--- a/db/README.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<html>
-<!-- ***** BEGIN LICENSE BLOCK *****
- - Version: MPL 1.1/GPL 2.0/LGPL 2.1
- -
- - The contents of this file are subject to the Mozilla Public License Version
- - 1.1 (the "License"); you may not use this file except in compliance with
- - the License. You may obtain a copy of the License at
- - http://www.mozilla.org/MPL/
- -
- - Software distributed under the License is distributed on an "AS IS" basis,
- - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- - for the specific language governing rights and limitations under the
- - License.
- -
- - The Original Code is mozilla.org code.
- -
- - The Initial Developer of the Original Code is
- - Netscape Communications Corporation.
- - Portions created by the Initial Developer are Copyright (C) 1998-1999
- - the Initial Developer. All Rights Reserved.
- -
- - Contributor(s):
- - Daniel Howard
- -
- - Alternatively, the contents of this file may be used under the terms of
- - either the GNU General Public License Version 2 or later (the "GPL"), or
- - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- - in which case the provisions of the GPL or the LGPL are applicable instead
- - of those above. If you wish to allow use of your version of this file only
- - under the terms of either the GPL or the LGPL, and not to allow others to
- - use your version of this file under the terms of the MPL, indicate your
- - decision by deleting the provisions above and replace them with the notice
- - and other provisions required by the GPL or the LGPL. If you do not delete
- - the provisions above, a recipient may use your version of this file under
- - the terms of any one of the MPL, the GPL or the LGPL.
- -
- - ***** END LICENSE BLOCK ***** -->
-<body>
-<h1>
-<span CLASS=LXRSHORTDESC>
-mdb/Mork general-purpose database<p>
-</span>
-</h1>
-<span CLASS=LXRLONGDESC>
-db contains C++ code for the mdb/Mork database which is a low-level,
-general-purpose and cross-platform file library. It is used to store
-mail box data, news data and global history data.
-</span>
-</body>
-</html>
deleted file mode 100644
--- a/db/mdb/Makefile.in
+++ /dev/null
@@ -1,48 +0,0 @@
-#
-# ***** BEGIN LICENSE BLOCK *****
-# Version: MPL 1.1/GPL 2.0/LGPL 2.1
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-# http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Original Code is mozilla.org code.
-#
-# The Initial Developer of the Original Code is
-# Netscape Communications Corporation.
-# Portions created by the Initial Developer are Copyright (C) 1998
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either of the GNU General Public License Version 2 or later (the "GPL"),
-# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-
-DEPTH = ../..
-topsrcdir = @top_srcdir@
-srcdir = @srcdir@
-VPATH = @srcdir@
-
-include $(DEPTH)/config/autoconf.mk
-
-DIRS = public
-
-include $(topsrcdir)/config/rules.mk
-
deleted file mode 100644
--- a/db/mdb/public/Makefile.in
+++ /dev/null
@@ -1,51 +0,0 @@
-#
-# ***** BEGIN LICENSE BLOCK *****
-# Version: MPL 1.1/GPL 2.0/LGPL 2.1
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-# http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Original Code is mozilla.org code.
-#
-# The Initial Developer of the Original Code is
-# Netscape Communications Corporation.
-# Portions created by the Initial Developer are Copyright (C) 1999
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either of the GNU General Public License Version 2 or later (the "GPL"),
-# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-
-DEPTH = ../../..
-topsrcdir = @top_srcdir@
-srcdir = @srcdir@
-VPATH = @srcdir@
-
-include $(DEPTH)/config/autoconf.mk
-
-MODULE = mork
-XPIDL_MODULE = msgmdb
-
-EXPORTS = mdb.h
-
-include $(topsrcdir)/config/rules.mk
-
deleted file mode 100644
--- a/db/mdb/public/mdb.h
+++ /dev/null
@@ -1,2569 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1999
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Blake Ross (blake@blakeross.com)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef _MDB_
-#define _MDB_ 1
-
-#include "nscore.h"
-#include "nsISupports.h"
-//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
-
-// { %%%%% begin scalar typedefs %%%%%
-typedef unsigned char mdb_u1; // make sure this is one byte
-typedef unsigned short mdb_u2; // make sure this is two bytes
-typedef short mdb_i2; // make sure this is two bytes
-typedef PRUint32 mdb_u4; // make sure this is four bytes
-typedef PRInt32 mdb_i4; // make sure this is four bytes
-typedef PRWord mdb_ip; // make sure sizeof(mdb_ip) == sizeof(void*)
-
-typedef mdb_u1 mdb_bool; // unsigned byte with zero=false, nonzero=true
-
-/* canonical boolean constants provided only for code clarity: */
-#define mdbBool_kTrue ((mdb_bool) 1) /* actually any nonzero means true */
-#define mdbBool_kFalse ((mdb_bool) 0) /* only zero means false */
-
-typedef mdb_u4 mdb_id; // unsigned object identity in a scope
-typedef mdb_id mdb_rid; // unsigned row identity inside scope
-typedef mdb_id mdb_tid; // unsigned table identity inside scope
-typedef mdb_u4 mdb_token; // unsigned token for atomized string
-typedef mdb_token mdb_scope; // token used to id scope for rows
-typedef mdb_token mdb_kind; // token used to id kind for tables
-typedef mdb_token mdb_column; // token used to id columns for rows
-typedef mdb_token mdb_cscode; // token used to id charset names
-typedef mdb_u4 mdb_seed; // unsigned collection change counter
-typedef mdb_u4 mdb_count; // unsigned collection member count
-typedef mdb_u4 mdb_size; // unsigned physical media size
-typedef mdb_u4 mdb_fill; // unsigned logical content size
-typedef mdb_u4 mdb_more; // more available bytes for larger buffer
-
-#define mdbId_kNone ((mdb_id) -1) /* never a valid Mork object ID */
-
-typedef mdb_u4 mdb_percent; // 0..100, with values >100 same as 100
-
-typedef mdb_u1 mdb_priority; // 0..9, for a total of ten different values
-
-// temporary substitute for NS_RESULT, for mdb.h standalone compilation:
-typedef nsresult mdb_err; // equivalent to NS_RESULT
-
-// sequence position is signed; negative is useful to mean "before first":
-typedef mdb_i4 mdb_pos; // signed zero-based ordinal collection position
-
-#define mdbPos_kBeforeFirst ((mdb_pos) -1) /* any negative is before zero */
-
-// order is also signed, so we can use three states for comparison order:
-typedef mdb_i4 mdb_order; // neg:lessthan, zero:equalto, pos:greaterthan
-
-typedef mdb_order (* mdbAny_Order)(const void* inA, const void* inB,
- const void* inClosure);
-
-// } %%%%% end scalar typedefs %%%%%
-
-// { %%%%% begin C structs %%%%%
-
-#ifndef mdbScopeStringSet_typedef
-typedef struct mdbScopeStringSet mdbScopeStringSet;
-#define mdbScopeStringSet_typedef 1
-#endif
-
-/*| mdbScopeStringSet: a set of null-terminated C strings that enumerate some
-**| names of row scopes, so that row scopes intended for use by an application
-**| can be declared by an app when trying to open or create a database file.
-**| (We use strings and not tokens because we cannot know the tokens for any
-**| particular db without having first opened the db.) The goal is to inform
-**| a db runtime that scopes not appearing in this list can be given relatively
-**| short shrift in runtime representation, with the expectation that other
-**| scopes will not actually be used. However, a db should still be prepared
-**| to handle accessing row scopes not in this list, rather than raising errors.
-**| But it could be quite expensive to access a row scope not on the list.
-**| Note a zero count for the string set means no such string set is being
-**| specified, and that a db should handle all row scopes efficiently.
-**| (It does NOT mean an app plans to use no content whatsoever.)
-|*/
-#ifndef mdbScopeStringSet_struct
-#define mdbScopeStringSet_struct 1
-struct mdbScopeStringSet { // vector of scopes for use in db opening policy
- // when mScopeStringSet_Count is zero, this means no scope constraints
- mdb_count mScopeStringSet_Count; // number of strings in vector below
- const char** mScopeStringSet_Strings; // null-ended ascii scope strings
-};
-#endif /*mdbScopeStringSet_struct*/
-
-#ifndef mdbOpenPolicy_typedef
-typedef struct mdbOpenPolicy mdbOpenPolicy;
-#define mdbOpenPolicy_typedef 1
-#endif
-
-#ifndef mdbOpenPolicy_struct
-#define mdbOpenPolicy_struct 1
-struct mdbOpenPolicy { // policies affecting db usage for ports and stores
- mdbScopeStringSet mOpenPolicy_ScopePlan; // predeclare scope usage plan
- mdb_bool mOpenPolicy_MaxLazy; // nonzero: do least work
- mdb_bool mOpenPolicy_MinMemory; // nonzero: use least memory
-};
-#endif /*mdbOpenPolicy_struct*/
-
-#ifndef mdbTokenSet_typedef
-typedef struct mdbTokenSet mdbTokenSet;
-#define mdbTokenSet_typedef 1
-#endif
-
-#ifndef mdbTokenSet_struct
-#define mdbTokenSet_struct 1
-struct mdbTokenSet { // array for a set of tokens, and actual slots used
- mdb_count mTokenSet_Count; // number of token slots in the array
- mdb_fill mTokenSet_Fill; // the subset of count slots actually used
- mdb_more mTokenSet_More; // more tokens available for bigger array
- mdb_token* mTokenSet_Tokens; // array of count mdb_token instances
-};
-#endif /*mdbTokenSet_struct*/
-
-#ifndef mdbUsagePolicy_typedef
-typedef struct mdbUsagePolicy mdbUsagePolicy;
-#define mdbUsagePolicy_typedef 1
-#endif
-
-/*| mdbUsagePolicy: another version of mdbOpenPolicy which uses tokens instead
-**| of scope strings, because usage policies can be constructed for use with a
-**| db that is already open, while an open policy must be constructed before a
-**| db has yet been opened.
-|*/
-#ifndef mdbUsagePolicy_struct
-#define mdbUsagePolicy_struct 1
-struct mdbUsagePolicy { // policies affecting db usage for ports and stores
- mdbTokenSet mUsagePolicy_ScopePlan; // current scope usage plan
- mdb_bool mUsagePolicy_MaxLazy; // nonzero: do least work
- mdb_bool mUsagePolicy_MinMemory; // nonzero: use least memory
-};
-#endif /*mdbUsagePolicy_struct*/
-
-#ifndef mdbOid_typedef
-typedef struct mdbOid mdbOid;
-#define mdbOid_typedef 1
-#endif
-
-#ifndef mdbOid_struct
-#define mdbOid_struct 1
-struct mdbOid { // identity of some row or table inside a database
- mdb_scope mOid_Scope; // scope token for an id's namespace
- mdb_id mOid_Id; // identity of object inside scope namespace
-};
-#endif /*mdbOid_struct*/
-
-#ifndef mdbRange_typedef
-typedef struct mdbRange mdbRange;
-#define mdbRange_typedef 1
-#endif
-
-#ifndef mdbRange_struct
-#define mdbRange_struct 1
-struct mdbRange { // range of row positions in a table
- mdb_pos mRange_FirstPos; // position of first row
- mdb_pos mRange_LastPos; // position of last row
-};
-#endif /*mdbRange_struct*/
-
-#ifndef mdbColumnSet_typedef
-typedef struct mdbColumnSet mdbColumnSet;
-#define mdbColumnSet_typedef 1
-#endif
-
-#ifndef mdbColumnSet_struct
-#define mdbColumnSet_struct 1
-struct mdbColumnSet { // array of column tokens (just the same as mdbTokenSet)
- mdb_count mColumnSet_Count; // number of columns
- mdb_column* mColumnSet_Columns; // count mdb_column instances
-};
-#endif /*mdbColumnSet_struct*/
-
-#ifndef mdbYarn_typedef
-typedef struct mdbYarn mdbYarn;
-#define mdbYarn_typedef 1
-#endif
-
-#ifdef MDB_BEGIN_C_LINKAGE_define
-#define MDB_BEGIN_C_LINKAGE_define 1
-#define MDB_BEGIN_C_LINKAGE extern "C" {
-#define MDB_END_C_LINKAGE }
-#endif /*MDB_BEGIN_C_LINKAGE_define*/
-
-/*| mdbYarn_mGrow: an abstract API for growing the size of a mdbYarn
-**| instance. With respect to a specific API that requires a caller
-**| to supply a string (mdbYarn) that a callee fills with content
-**| that might exceed the specified size, mdbYarn_mGrow is a caller-
-**| supplied means of letting a callee attempt to increase the string
-**| size to become large enough to receive all content available.
-**|
-**|| Grow(): a method for requesting that a yarn instance be made
-**| larger in size. Note that such requests need not be honored, and
-**| need not be honored in full if only partial size growth is desired.
-**| (Note that no nsIMdbEnv instance is passed as argument, although one
-**| might be needed in some circumstances. So if an nsIMdbEnv is needed,
-**| a reference to one might be held inside a mdbYarn member slot.)
-**|
-**|| self: a yarn instance to be grown. Presumably this yarn is
-**| the instance which holds the mYarn_Grow method pointer. Yarn
-**| instancesshould only be passed to grow methods which they were
-**| specifically designed to fit, as indicated by the mYarn_Grow slot.
-**|
-**|| inNewSize: the new desired value for slot mYarn_Size in self.
-**| If mYarn_Size is already this big, then nothing should be done.
-**| If inNewSize is larger than seems feasible or desirable to honor,
-**| then any size restriction policy can be used to grow to some size
-**| greater than mYarn_Size. (Grow() might even grow to a size
-**| greater than inNewSize in order to make the increase in size seem
-**| worthwhile, rather than growing in many smaller steps over time.)
-|*/
-typedef void (* mdbYarn_mGrow)(mdbYarn* self, mdb_size inNewSize);
-// mdbYarn_mGrow methods must be declared with C linkage in C++
-
-/*| mdbYarn: a variable length "string" of arbitrary binary bytes,
-**| whose length is mYarn_Fill, inside a buffer mYarn_Buf that has
-**| at most mYarn_Size byte of physical space.
-**|
-**|| mYarn_Buf: a pointer to space containing content. This slot
-**| might never be nil when mYarn_Size is nonzero, but checks for nil
-**| are recommended anyway.
-**| (Implementations of mdbYarn_mGrow methods should take care to
-**| ensure the existence of a replacement before dropping old Bufs.)
-**| Content in Buf can be anything in any format, but the mYarn_Form
-**| implies the actual format by some caller-to-callee convention.
-**| mYarn_Form==0 implies US-ASCII iso-8859-1 Latin1 string content.
-**|
-**|| mYarn_Size: the physical size of Buf in bytes. Note that if one
-**| intends to terminate a string with a null byte, that it must not
-**| be written at or after mYarn_Buf[mYarn_Size] because this is after
-**| the last byte in the physical buffer space. Size can be zero,
-**| which means the string has no content whatsoever; note that when
-**| Size is zero, this is a suitable reason for Buf==nil as well.
-**|
-**|| mYarn_Fill: the logical content in Buf in bytes, where Fill must
-**| never exceed mYarn_Size. Note that yarn strings might not have a
-**| terminating null byte (since they might not even be C strings), but
-**| when they do, such terminating nulls are considered part of content
-**| and therefore Fill will count such null bytes. So an "empty" C
-**| string will have Fill==1, because content includes one null byte.
-**| Fill does not mean "length" when applied to C strings for this
-**| reason. However, clients using yarns to hold C strings can infer
-**| that length is equal to Fill-1 (but should take care to handle the
-**| case where Fill==0). To be paranoid, one can always copy to a
-**| destination with size exceeding Fill, and place a redundant null
-**| byte in the Fill position when this simplifies matters.
-**|
-**|| mYarn_Form: a designation of content format within mYarn_Buf.
-**| The semantics of this slot are the least well defined, since the
-**| actual meaning is context dependent, to the extent that callers
-**| and callees must agree on format encoding conventions when such
-**| are not standardized in many computing contexts. However, in the
-**| context of a specific mdb database, mYarn_Form is a token for an
-**| atomized string in that database that typically names a preferred
-**| mime type charset designation. If and when mdbYarn is used for
-**| other purposes away from the mdb interface, folks can use another
-**| convention system for encoding content formats. However, in all
-**| contexts is it useful to maintain the convention that Form==0
-**| implies Buf contains US-ASCII iso-8859-1 Latin1 string content.
-**|
-**|| mYarn_Grow: either a mdbYarn_mGrow method, or else nil. When
-**| a mdbYarn_mGrow method is provided, this method can be used to
-**| request a yarn buf size increase. A caller who constructs the
-**| original mdbYarn instance decides whether a grow method is necessary
-**| or desirable, and uses only grow methods suitable for the buffering
-**| nature of a specific mdbYarn instance. (For example, Buf might be a
-**| staticly allocated string space which switches to something heap-based
-**| when grown, and subsequent calls to grow the yarn must distinguish the
-**| original static string from heap allocated space, etc.) Note that the
-**| method stored in mYarn_Grow can change, and this might be a common way
-**| to track memory managent changes in policy for mYarn_Buf.
-|*/
-#ifndef mdbYarn_struct
-#define mdbYarn_struct 1
-struct mdbYarn { // buffer with caller space allocation semantics
- void* mYarn_Buf; // space for holding any binary content
- mdb_fill mYarn_Fill; // logical content in Buf in bytes
- mdb_size mYarn_Size; // physical size of Buf in bytes
- mdb_more mYarn_More; // more available bytes if Buf is bigger
- mdb_cscode mYarn_Form; // charset format encoding
- mdbYarn_mGrow mYarn_Grow; // optional method to grow mYarn_Buf
-
- // Subclasses might add further slots after mYarn_Grow in order to
- // maintain bookkeeping needs, such as state info about mYarn_Buf.
-};
-#endif /*mdbYarn_struct*/
-
-// } %%%%% end C structs %%%%%
-
-// { %%%%% begin class forward defines %%%%%
-class nsIMdbEnv;
-class nsIMdbObject;
-class nsIMdbErrorHook;
-class nsIMdbCompare;
-class nsIMdbThumb;
-class nsIMdbFactory;
-class nsIMdbFile;
-class nsIMdbPort;
-class nsIMdbStore;
-class nsIMdbCursor;
-class nsIMdbPortTableCursor;
-class nsIMdbCollection;
-class nsIMdbTable;
-class nsIMdbTableRowCursor;
-class nsIMdbRow;
-class nsIMdbRowCellCursor;
-class nsIMdbBlob;
-class nsIMdbCell;
-class nsIMdbSorting;
-// } %%%%% end class forward defines %%%%%
-
-
-// { %%%%% begin C++ abstract class interfaces %%%%%
-
-/*| nsIMdbObject: base class for all message db class interfaces
-**|
-**|| factory: all nsIMdbObjects from the same code suite have the same factory
-**|
-**|| refcounting: both strong and weak references, to ensure strong refs are
-**| acyclic, while weak refs can cause cycles. CloseMdbObject() is
-**| called when (strong) use counts hit zero, but clients can call this close
-**| method early for some reason, if absolutely necessary even though it will
-**| thwart the other uses of the same object. Note that implementations must
-**| cope with close methods being called arbitrary numbers of times. The COM
-**| calls to AddRef() and release ref map directly to strong use ref calls,
-**| but the total ref count for COM objects is the sum of weak & strong refs.
-|*/
-
-#define NS_IMDBOBJECT_IID_STR "5533ea4b-14c3-4bef-ac60-22f9e9a49084"
-
-#define NS_IMDBOBJECT_IID \
-{0x5533ea4b, 0x14c3, 0x4bef, \
-{ 0xac, 0x60, 0x22, 0xf9, 0xe9, 0xa4, 0x90, 0x84}}
-
-class nsIMdbObject : public nsISupports { // msg db base class
-public:
-
- NS_DECLARE_STATIC_IID_ACCESSOR(NS_IMDBOBJECT_IID)
-// { ===== begin nsIMdbObject methods =====
-
- // { ----- begin attribute methods -----
- NS_IMETHOD IsFrozenMdbObject(nsIMdbEnv* ev, mdb_bool* outIsReadonly) = 0;
- // same as nsIMdbPort::GetIsPortReadonly() when this object is inside a port.
- // } ----- end attribute methods -----
-
- // { ----- begin factory methods -----
- NS_IMETHOD GetMdbFactory(nsIMdbEnv* ev, nsIMdbFactory** acqFactory) = 0;
- // } ----- end factory methods -----
-
- // { ----- begin ref counting for well-behaved cyclic graphs -----
- NS_IMETHOD GetWeakRefCount(nsIMdbEnv* ev, // weak refs
- mdb_count* outCount) = 0;
- NS_IMETHOD GetStrongRefCount(nsIMdbEnv* ev, // strong refs
- mdb_count* outCount) = 0;
-
- NS_IMETHOD AddWeakRef(nsIMdbEnv* ev) = 0;
- NS_IMETHOD AddStrongRef(nsIMdbEnv* ev) = 0;
-
- NS_IMETHOD CutWeakRef(nsIMdbEnv* ev) = 0;
- NS_IMETHOD CutStrongRef(nsIMdbEnv* ev) = 0;
-
- NS_IMETHOD CloseMdbObject(nsIMdbEnv* ev) = 0; // called at strong refs zero
- NS_IMETHOD IsOpenMdbObject(nsIMdbEnv* ev, mdb_bool* outOpen) = 0;
- // } ----- end ref counting -----
-
-// } ===== end nsIMdbObject methods =====
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(nsIMdbObject, NS_IMDBOBJECT_IID)
-
-/*| nsIMdbErrorHook: a base class for clients of this API to subclass, in order
-**| to provide a callback installable in nsIMdbEnv for error notifications. If
-**| apps that subclass nsIMdbErrorHook wish to maintain a reference to the env
-**| that contains the hook, then this should be a weak ref to avoid cycles.
-**|
-**|| OnError: when nsIMdbEnv has an error condition that causes the total count
-**| of errors to increase, then nsIMdbEnv should call OnError() to report the
-**| error in some fashion when an instance of nsIMdbErrorHook is installed. The
-**| variety of string flavors is currently due to the uncertainty here in the
-**| nsIMdbBlob and nsIMdbCell interfaces. (Note that overloading by using the
-**| same method name is not necessary here, and potentially less clear.)
-|*/
-class nsIMdbErrorHook : public nsISupports{ // env callback handler to report errors
-public:
-
-// { ===== begin error methods =====
- NS_IMETHOD OnErrorString(nsIMdbEnv* ev, const char* inAscii) = 0;
- NS_IMETHOD OnErrorYarn(nsIMdbEnv* ev, const mdbYarn* inYarn) = 0;
-// } ===== end error methods =====
-
-// { ===== begin warning methods =====
- NS_IMETHOD OnWarningString(nsIMdbEnv* ev, const char* inAscii) = 0;
- NS_IMETHOD OnWarningYarn(nsIMdbEnv* ev, const mdbYarn* inYarn) = 0;
-// } ===== end warning methods =====
-
-// { ===== begin abort hint methods =====
- NS_IMETHOD OnAbortHintString(nsIMdbEnv* ev, const char* inAscii) = 0;
- NS_IMETHOD OnAbortHintYarn(nsIMdbEnv* ev, const mdbYarn* inYarn) = 0;
-// } ===== end abort hint methods =====
-};
-
-/*| nsIMdbCompare: a caller-supplied yarn comparison interface. When two yarns
-**| are compared to each other with Order(), this method should return a signed
-**| long integer denoting relation R between the 1st and 2nd yarn instances
-**| such that (First R Second), where negative is less than, zero is equal to,
-**| and positive is greater than. Note that both yarns are readonly, and the
-**| Order() method should make no attempt to modify the yarn content.
-|*/
-class nsIMdbCompare { // caller-supplied yarn comparison
-public:
-
-// { ===== begin nsIMdbCompare methods =====
- NS_IMETHOD Order(nsIMdbEnv* ev, // compare first to second yarn
- const mdbYarn* inFirst, // first yarn in comparison
- const mdbYarn* inSecond, // second yarn in comparison
- mdb_order* outOrder) = 0; // negative="<", zero="=", positive=">"
-
- NS_IMETHOD AddStrongRef(nsIMdbEnv* ev) = 0; // does nothing
- NS_IMETHOD CutStrongRef(nsIMdbEnv* ev) = 0; // does nothing
-// } ===== end nsIMdbCompare methods =====
-
-};
-
-/*| nsIMdbHeap: abstract memory allocation interface.
-**|
-**|| Alloc: return a block at least inSize bytes in size with alignment
-**| suitable for any native type (such as long integers). When no such
-**| block can be allocated, failure is indicated by a null address in
-**| addition to reporting an error in the environment.
-**|
-**|| Free: deallocate a block allocated or resized earlier by the same
-**| heap instance. If the inBlock parameter is nil, the heap should do
-**| nothing (and crashing is strongly discouraged).
-|*/
-class nsIMdbHeap { // caller-supplied memory management interface
-public:
-// { ===== begin nsIMdbHeap methods =====
- NS_IMETHOD Alloc(nsIMdbEnv* ev, // allocate a piece of memory
- mdb_size inSize, // requested byte size of new memory block
- void** outBlock) = 0; // memory block of inSize bytes, or nil
-
- NS_IMETHOD Free(nsIMdbEnv* ev, // free block from Alloc or Resize()
- void* ioBlock) = 0; // block to be destroyed/deallocated
-
- NS_IMETHOD HeapAddStrongRef(nsIMdbEnv* ev) = 0;
- NS_IMETHOD HeapCutStrongRef(nsIMdbEnv* ev) = 0;
-
-// } ===== end nsIMdbHeap methods =====
-};
-
-/*| nsIMdbCPlusHeap: Alloc() with global ::new(), Free() with global ::delete().
-**| Resize() is done by ::new() followed by ::delete().
-|*/
-class nsIMdbCPlusHeap { // caller-supplied memory management interface
-public:
-// { ===== begin nsIMdbHeap methods =====
- NS_IMETHOD Alloc(nsIMdbEnv* ev, // allocate a piece of memory
- mdb_size inSize, // requested size of new memory block
- void** outBlock); // memory block of inSize bytes, or nil
-
- NS_IMETHOD Free(nsIMdbEnv* ev, // free block allocated earlier by Alloc()
- void* inBlock);
-
- NS_IMETHOD HeapAddStrongRef(nsIMdbEnv* ev);
- NS_IMETHOD HeapCutStrongRef(nsIMdbEnv* ev);
-// } ===== end nsIMdbHeap methods =====
-};
-
-/*| nsIMdbThumb:
-|*/
-
-
-#define NS_IMDBTHUMB_IID_STR "6d3ad7c1-a809-4e74-8577-49fa9a4562fa"
-
-#define NS_IMDBTHUMB_IID \
-{0x6d3ad7c1, 0xa809, 0x4e74, \
-{ 0x85, 0x77, 0x49, 0xfa, 0x9a, 0x45, 0x62, 0xfa}}
-
-
-class nsIMdbThumb : public nsISupports { // closure for repeating incremental method
-public:
- NS_DECLARE_STATIC_IID_ACCESSOR(NS_IMDBTHUMB_IID)
-
-// { ===== begin nsIMdbThumb methods =====
- NS_IMETHOD GetProgress(nsIMdbEnv* ev,
- mdb_count* outTotal, // total somethings to do in operation
- mdb_count* outCurrent, // subportion of total completed so far
- mdb_bool* outDone, // is operation finished?
- mdb_bool* outBroken // is operation irreparably dead and broken?
- ) = 0;
-
- NS_IMETHOD DoMore(nsIMdbEnv* ev,
- mdb_count* outTotal, // total somethings to do in operation
- mdb_count* outCurrent, // subportion of total completed so far
- mdb_bool* outDone, // is operation finished?
- mdb_bool* outBroken // is operation irreparably dead and broken?
- ) = 0;
-
- NS_IMETHOD CancelAndBreakThumb( // cancel pending operation
- nsIMdbEnv* ev) = 0;
-// } ===== end nsIMdbThumb methods =====
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(nsIMdbThumb, NS_IMDBTHUMB_IID)
-
-/*| nsIMdbEnv: a context parameter used when calling most abstract db methods.
-**| The main purpose of such an object is to permit a database implementation
-**| to avoid the use of globals to share information between various parts of
-**| the implementation behind the abstract db interface. An environment acts
-**| like a session object for a given calling thread, and callers should use
-**| at least one different nsIMdbEnv instance for each thread calling the API.
-**| While the database implementation might not be threaded, it is highly
-**| desirable that the db be thread-safe if calling threads use distinct
-**| instances of nsIMdbEnv. Callers can stop at one nsIMdbEnv per thread, or they
-**| might decide to make on nsIMdbEnv instance for every nsIMdbPort opened, so that
-**| error information is segregated by database instance. Callers create
-**| instances of nsIMdbEnv by calling the MakeEnv() method in nsIMdbFactory.
-**|
-**|| tracing: an environment might support some kind of tracing, and this
-**| boolean attribute permits such activity to be enabled or disabled.
-**|
-**|| errors: when a call to the abstract db interface returns, a caller might
-**| check the number of outstanding errors to see whether the operation did
-**| actually succeed. Each nsIMdbEnv should have all its errors cleared by a
-**| call to ClearErrors() before making each call to the abstract db API,
-**| because outstanding errors might disable further database actions. (This
-**| is not done inside the db interface, because the db cannot in general know
-**| when a call originates from inside or outside -- only the app knows this.)
-**|
-**|| error hook: callers can install an instance of nsIMdbErrorHook to receive
-**| error notifications whenever the error count increases. The hook can
-**| be uninstalled by passing a null pointer.
-**|
-|*/
-
-#define NS_IMDBENV_IID_STR "a765e46b-efb6-41e6-b75b-c5d6bd710594"
-
-#define NS_IMDBENV_IID \
-{0xa765e46b, 0xefb6, 0x41e6, \
-{ 0xb7, 0x5b, 0xc5, 0xd6, 0xbd, 0x71, 0x05, 0x94}}
-
-class nsIMdbEnv : public nsISupports { // db specific context parameter
-public:
-
- NS_DECLARE_STATIC_IID_ACCESSOR(NS_IMDBENV_IID)
-// { ===== begin nsIMdbEnv methods =====
-
- // { ----- begin attribute methods -----
- NS_IMETHOD GetErrorCount(mdb_count* outCount,
- mdb_bool* outShouldAbort) = 0;
- NS_IMETHOD GetWarningCount(mdb_count* outCount,
- mdb_bool* outShouldAbort) = 0;
-
- NS_IMETHOD GetEnvBeVerbose(mdb_bool* outBeVerbose) = 0;
- NS_IMETHOD SetEnvBeVerbose(mdb_bool inBeVerbose) = 0;
-
- NS_IMETHOD GetDoTrace(mdb_bool* outDoTrace) = 0;
- NS_IMETHOD SetDoTrace(mdb_bool inDoTrace) = 0;
-
- NS_IMETHOD GetAutoClear(mdb_bool* outAutoClear) = 0;
- NS_IMETHOD SetAutoClear(mdb_bool inAutoClear) = 0;
-
- NS_IMETHOD GetErrorHook(nsIMdbErrorHook** acqErrorHook) = 0;
- NS_IMETHOD SetErrorHook(
- nsIMdbErrorHook* ioErrorHook) = 0; // becomes referenced
-
- NS_IMETHOD GetHeap(nsIMdbHeap** acqHeap) = 0;
- NS_IMETHOD SetHeap(
- nsIMdbHeap* ioHeap) = 0; // becomes referenced
- // } ----- end attribute methods -----
-
- NS_IMETHOD ClearErrors() = 0; // clear errors beore re-entering db API
- NS_IMETHOD ClearWarnings() = 0; // clear warnings
- NS_IMETHOD ClearErrorsAndWarnings() = 0; // clear both errors & warnings
-// } ===== end nsIMdbEnv methods =====
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(nsIMdbEnv, NS_IMDBENV_IID)
-
-/*| nsIMdbFactory: the main entry points to the abstract db interface. A DLL
-**| that supports this mdb interface need only have a single exported method
-**| that will return an instance of nsIMdbFactory, so that further methods in
-**| the suite can be accessed from objects returned by nsIMdbFactory methods.
-**|
-**|| mdbYarn: note all nsIMdbFactory subclasses must guarantee null
-**| termination of all strings written into mdbYarn instances, as long as
-**| mYarn_Size and mYarn_Buf are nonzero. Even truncated string values must
-**| be null terminated. This is more strict behavior than mdbYarn requires,
-**| but it is part of the nsIMdbFactory interface.
-**|
-**|| envs: an environment instance is required as per-thread context for
-**| most of the db method calls, so nsIMdbFactory creates such instances.
-**|
-**|| rows: callers must be able to create row instances that are independent
-**| of storage space that is part of the db content graph. Many interfaces
-**| for data exchange have strictly copy semantics, so that a row instance
-**| has no specific identity inside the db content model, and the text in
-**| cells are an independenty copy of unexposed content inside the db model.
-**| Callers are expected to maintain one or more row instances as a buffer
-**| for staging cell content copied into or out of a table inside the db.
-**| Callers are urged to use an instance of nsIMdbRow created by the nsIMdbFactory
-**| code suite, because reading and writing might be much more efficient than
-**| when using a hand-rolled nsIMdbRow subclass with no relation to the suite.
-**|
-**|| ports: a port is a readonly interface to a specific database file. Most
-**| of the methods to access a db file are suitable for a readonly interface,
-**| so a port is the basic minimum for accessing content. This makes it
-**| possible to read other external formats for import purposes, without
-**| needing the code or competence necessary to write every such format. So
-**| we can write generic import code just once, as long as every format can
-**| show a face based on nsIMdbPort. (However, same suite import can be faster.)
-**| Given a file name and the first 512 bytes of a file, a factory can say if
-**| a port can be opened by this factory. Presumably an app maintains chains
-**| of factories for different suites, and asks each in turn about opening a
-**| a prospective file for reading (as a port) or writing (as a store). I'm
-**| not ready to tackle issues of format fidelity and factory chain ordering.
-**|
-**|| stores: a store is a mutable interface to a specific database file, and
-**| includes the port interface plus any methods particular to writing, which
-**| are few in number. Presumably the set of files that can be opened as
-**| stores is a subset of the set of files that can be opened as ports. A
-**| new store can be created with CreateNewFileStore() by supplying a new
-**| file name which does not yet exist (callers are always responsible for
-**| destroying any existing files before calling this method).
-|*/
-
-#define NS_IMDBFACTORY_IID_STR "2b80395c-b91e-4990-b1a7-023e99ab14e9"
-
-#define NS_IMDBFACTORY_IID \
-{0xf04aa4ab, 0x1fe, 0x4115, \
-{ 0xa4, 0xa5, 0x68, 0x19, 0xdf, 0xf1, 0x10, 0x3d}}
-
-
-class nsIMdbFactory : public nsISupports { // suite entry points
-public:
-
- NS_DECLARE_STATIC_IID_ACCESSOR(NS_IMDBFACTORY_IID)
-// { ===== begin nsIMdbFactory methods =====
-
- // { ----- begin file methods -----
- NS_IMETHOD OpenOldFile(nsIMdbEnv* ev, nsIMdbHeap* ioHeap,
- const char* inFilePath,
- mdb_bool inFrozen, nsIMdbFile** acqFile) = 0;
- // Choose some subclass of nsIMdbFile to instantiate, in order to read
- // (and write if not frozen) the file known by inFilePath. The file
- // returned should be open and ready for use, and presumably positioned
- // at the first byte position of the file. The exact manner in which
- // files must be opened is considered a subclass specific detail, and
- // other portions or Mork source code don't want to know how it's done.
-
- NS_IMETHOD CreateNewFile(nsIMdbEnv* ev, nsIMdbHeap* ioHeap,
- const char* inFilePath,
- nsIMdbFile** acqFile) = 0;
- // Choose some subclass of nsIMdbFile to instantiate, in order to read
- // (and write if not frozen) the file known by inFilePath. The file
- // returned should be created and ready for use, and presumably positioned
- // at the first byte position of the file. The exact manner in which
- // files must be opened is considered a subclass specific detail, and
- // other portions or Mork source code don't want to know how it's done.
- // } ----- end file methods -----
-
- // { ----- begin env methods -----
- NS_IMETHOD MakeEnv(nsIMdbHeap* ioHeap, nsIMdbEnv** acqEnv) = 0; // acquire new env
- // ioHeap can be nil, causing a MakeHeap() style heap instance to be used
- // } ----- end env methods -----
-
- // { ----- begin heap methods -----
- NS_IMETHOD MakeHeap(nsIMdbEnv* ev, nsIMdbHeap** acqHeap) = 0; // acquire new heap
- // } ----- end heap methods -----
-
- // { ----- begin compare methods -----
- NS_IMETHOD MakeCompare(nsIMdbEnv* ev, nsIMdbCompare** acqCompare) = 0; // ASCII
- // } ----- end compare methods -----
-
- // { ----- begin row methods -----
- NS_IMETHOD MakeRow(nsIMdbEnv* ev, nsIMdbHeap* ioHeap, nsIMdbRow** acqRow) = 0; // new row
- // ioHeap can be nil, causing the heap associated with ev to be used
- // } ----- end row methods -----
-
- // { ----- begin port methods -----
- NS_IMETHOD CanOpenFilePort(
- nsIMdbEnv* ev, // context
- // const char* inFilePath, // the file to investigate
- // const mdbYarn* inFirst512Bytes,
- nsIMdbFile* ioFile, // db abstract file interface
- mdb_bool* outCanOpen, // whether OpenFilePort() might succeed
- mdbYarn* outFormatVersion) = 0; // informal file format description
-
- NS_IMETHOD OpenFilePort(
- nsIMdbEnv* ev, // context
- nsIMdbHeap* ioHeap, // can be nil to cause ev's heap attribute to be used
- // const char* inFilePath, // the file to open for readonly import
- nsIMdbFile* ioFile, // db abstract file interface
- const mdbOpenPolicy* inOpenPolicy, // runtime policies for using db
- nsIMdbThumb** acqThumb) = 0; // acquire thumb for incremental port open
- // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and
- // then call nsIMdbFactory::ThumbToOpenPort() to get the port instance.
-
- NS_IMETHOD ThumbToOpenPort( // redeeming a completed thumb from OpenFilePort()
- nsIMdbEnv* ev, // context
- nsIMdbThumb* ioThumb, // thumb from OpenFilePort() with done status
- nsIMdbPort** acqPort) = 0; // acquire new port object
- // } ----- end port methods -----
-
- // { ----- begin store methods -----
- NS_IMETHOD CanOpenFileStore(
- nsIMdbEnv* ev, // context
- // const char* inFilePath, // the file to investigate
- // const mdbYarn* inFirst512Bytes,
- nsIMdbFile* ioFile, // db abstract file interface
- mdb_bool* outCanOpenAsStore, // whether OpenFileStore() might succeed
- mdb_bool* outCanOpenAsPort, // whether OpenFilePort() might succeed
- mdbYarn* outFormatVersion) = 0; // informal file format description
-
- NS_IMETHOD OpenFileStore( // open an existing database
- nsIMdbEnv* ev, // context
- nsIMdbHeap* ioHeap, // can be nil to cause ev's heap attribute to be used
- // const char* inFilePath, // the file to open for general db usage
- nsIMdbFile* ioFile, // db abstract file interface
- const mdbOpenPolicy* inOpenPolicy, // runtime policies for using db
- nsIMdbThumb** acqThumb) = 0; // acquire thumb for incremental store open
- // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and
- // then call nsIMdbFactory::ThumbToOpenStore() to get the store instance.
-
- NS_IMETHOD
- ThumbToOpenStore( // redeem completed thumb from OpenFileStore()
- nsIMdbEnv* ev, // context
- nsIMdbThumb* ioThumb, // thumb from OpenFileStore() with done status
- nsIMdbStore** acqStore) = 0; // acquire new db store object
-
- NS_IMETHOD CreateNewFileStore( // create a new db with minimal content
- nsIMdbEnv* ev, // context
- nsIMdbHeap* ioHeap, // can be nil to cause ev's heap attribute to be used
- // const char* inFilePath, // name of file which should not yet exist
- nsIMdbFile* ioFile, // db abstract file interface
- const mdbOpenPolicy* inOpenPolicy, // runtime policies for using db
- nsIMdbStore** acqStore) = 0; // acquire new db store object
- // } ----- end store methods -----
-
-// } ===== end nsIMdbFactory methods =====
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(nsIMdbFactory, NS_IMDBFACTORY_IID)
-
-extern "C" nsIMdbFactory* MakeMdbFactory();
-
-/*| nsIMdbFile: abstract file interface resembling the original morkFile
-**| abstract interface (which was in turn modeled on the file interface
-**| from public domain IronDoc). The design of this file interface is
-**| complicated by the fact that some DB's will not find this interface
-**| adequate for all runtime requirements (even though this file API is
-**| enough to implement text-based DB's like Mork). For this reason,
-**| more methods have been added to let a DB library force the file to
-**| become closed so the DB can reopen the file in some other manner.
-**| Folks are encouraged to suggest ways to tune this interface to suit
-**| DB's that cannot manage to pull their maneuvers even given this API.
-**|
-**|| Tell: get the current i/o position in file
-**|
-**|| Seek: change the current i/o position in file
-**|
-**|| Eof: return file's total length in bytes
-**|
-**|| Read: input inSize bytes into outBuf, returning actual transfer size
-**|
-**|| Get: read starting at specific file offset (e.g. Seek(); Read();)
-**|
-**|| Write: output inSize bytes from inBuf, returning actual transfer size
-**|
-**|| Put: write starting at specific file offset (e.g. Seek(); Write();)
-**|
-**|| Flush: if written bytes are buffered, push them to final destination
-**|
-**|| Path: get file path in some string representation. This is intended
-**| either to support the display of file name in a user presentation, or
-**| to support the closing and reopening of the file when the DB needs more
-**| exotic file access than is presented by the nsIMdbFile interface.
-**|
-**|| Steal: tell this file to close any associated i/o stream in the file
-**| system, because the file ioThief intends to reopen the file in order
-**| to provide the MDB implementation with more exotic file access than is
-**| offered by the nsIMdbFile alone. Presumably the thief knows enough
-**| from Path() in order to know which file to reopen. If Steal() is
-**| successful, this file should probably delegate all future calls to
-**| the nsIMdbFile interface down to the thief files, so that even after
-**| the file has been stolen, it can still be read, written, or forcibly
-**| closed (by a call to CloseMdbObject()).
-**|
-**|| Thief: acquire and return thief passed to an earlier call to Steal().
-|*/
-
-#define NS_IMDBFILE_IID_STR "f04aa4ab-1fe7-4115-a4a5-6819dff1103d"
-
-#define NS_IMDBFILE_IID \
-{0xf04aa4ab, 0x1fe, 0x4115, \
-{ 0xa4, 0xa5, 0x68, 0x19, 0xdf, 0xf1, 0x10, 0x3d}}
-
-class nsIMdbFile : public nsISupports { // minimal file interface
-public:
-
- NS_DECLARE_STATIC_IID_ACCESSOR(NS_IMDBFILE_IID)
-// { ===== begin nsIMdbFile methods =====
-
- // { ----- begin pos methods -----
- NS_IMETHOD Tell(nsIMdbEnv* ev, mdb_pos* outPos) const = 0;
- NS_IMETHOD Seek(nsIMdbEnv* ev, mdb_pos inPos, mdb_pos *outPos) = 0;
- NS_IMETHOD Eof(nsIMdbEnv* ev, mdb_pos* outPos) = 0;
- // } ----- end pos methods -----
-
- // { ----- begin read methods -----
- NS_IMETHOD Read(nsIMdbEnv* ev, void* outBuf, mdb_size inSize,
- mdb_size* outActualSize) = 0;
- NS_IMETHOD Get(nsIMdbEnv* ev, void* outBuf, mdb_size inSize,
- mdb_pos inPos, mdb_size* outActualSize) = 0;
- // } ----- end read methods -----
-
- // { ----- begin write methods -----
- NS_IMETHOD Write(nsIMdbEnv* ev, const void* inBuf, mdb_size inSize,
- mdb_size* outActualSize) = 0;
- NS_IMETHOD Put(nsIMdbEnv* ev, const void* inBuf, mdb_size inSize,
- mdb_pos inPos, mdb_size* outActualSize) = 0;
- NS_IMETHOD Flush(nsIMdbEnv* ev) = 0;
- // } ----- end attribute methods -----
-
- // { ----- begin path methods -----
- NS_IMETHOD Path(nsIMdbEnv* ev, mdbYarn* outFilePath) = 0;
- // } ----- end path methods -----
-
- // { ----- begin replacement methods -----
- NS_IMETHOD Steal(nsIMdbEnv* ev, nsIMdbFile* ioThief) = 0;
- NS_IMETHOD Thief(nsIMdbEnv* ev, nsIMdbFile** acqThief) = 0;
- // } ----- end replacement methods -----
-
- // { ----- begin versioning methods -----
- NS_IMETHOD BecomeTrunk(nsIMdbEnv* ev) = 0;
- // If this file is a file version branch created by calling AcquireBud(),
- // BecomeTrunk() causes this file's content to replace the original
- // file's content, typically by assuming the original file's identity.
- // This default implementation of BecomeTrunk() does nothing, and this
- // is appropriate behavior for files which are not branches, and is
- // also the right behavior for files returned from AcquireBud() which are
- // in fact the original file that has been truncated down to zero length.
-
- NS_IMETHOD AcquireBud(nsIMdbEnv* ev, nsIMdbHeap* ioHeap,
- nsIMdbFile** acqBud) = 0; // acquired file for new version of content
- // AcquireBud() starts a new "branch" version of the file, empty of content,
- // so that a new version of the file can be written. This new file
- // can later be told to BecomeTrunk() the original file, so the branch
- // created by budding the file will replace the original file. Some
- // file subclasses might initially take the unsafe but expedient
- // approach of simply truncating this file down to zero length, and
- // then returning the same morkFile pointer as this, with an extra
- // reference count increment. Note that the caller of AcquireBud() is
- // expected to eventually call CutStrongRef() on the returned file
- // in order to release the strong reference. High quality versions
- // of morkFile subclasses will create entirely new files which later
- // are renamed to become the old file, so that better transactional
- // behavior is exhibited by the file, so crashes protect old files.
- // Note that AcquireBud() is an illegal operation on readonly files.
- // } ----- end versioning methods -----
-
-// } ===== end nsIMdbFile methods =====
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(nsIMdbFile, NS_IMDBFILE_IID)
-
-/*| nsIMdbPort: a readonly interface to a specific database file. The mutable
-**| nsIMdbStore interface is a subclass that includes writing behavior, but
-**| most of the needed db methods appear in the readonly nsIMdbPort interface.
-**|
-**|| mdbYarn: note all nsIMdbPort and nsIMdbStore subclasses must guarantee null
-**| termination of all strings written into mdbYarn instances, as long as
-**| mYarn_Size and mYarn_Buf are nonzero. Even truncated string values must
-**| be null terminated. This is more strict behavior than mdbYarn requires,
-**| but it is part of the nsIMdbPort and nsIMdbStore interface.
-**|
-**|| attributes: methods are provided to distinguish a readonly port from a
-**| mutable store, and whether a mutable store actually has any dirty content.
-**|
-**|| filepath: the file path used to open the port from the nsIMdbFactory can be
-**| queried and discovered by GetPortFilePath(), which includes format info.
-**|
-**|| export: a port can write itself in other formats, with perhaps a typical
-**| emphasis on text interchange formats used by other systems. A port can be
-**| queried to determine its preferred export interchange format, and a port
-**| can be queried to see whether a specific export format is supported. And
-**| actually exporting a port requires a new destination file name and format.
-**|
-**|| tokens: a port supports queries about atomized strings to map tokens to
-**| strings or strings to token integers. (All atomized strings must be in
-**| US-ASCII iso-8859-1 Latin1 charset encoding.) When a port is actually a
-**| mutable store and a string has not yet been atomized, then StringToToken()
-**| will actually do so and modify the store. The QueryToken() method will not
-**| atomize a string if it has not already been atomized yet, even in stores.
-**|
-**|| tables: other than string tokens, all port content is presented through
-**| tables, which are ordered collections of rows. Tables are identified by
-**| row scope and table kind, which might or might not be unique in a port,
-**| depending on app convention. When tables are effectively unique, then
-**| queries for specific scope and kind pairs will find those tables. To see
-**| all tables that match specific row scope and table kind patterns, even in
-**| the presence of duplicates, every port supports a GetPortTableCursor()
-**| method that returns an iterator over all matching tables. Table kind is
-**| considered scoped inside row scope, so passing a zero for table kind will
-**| find all table kinds for some nonzero row scope. Passing a zero for row
-**| scope will iterate over all tables in the port, in some undefined order.
-**| (A new table can be added to a port using nsIMdbStore::NewTable(), even when
-**| the requested scope and kind combination is already used by other tables.)
-**|
-**|| memory: callers can request that a database use less memory footprint in
-**| several flavors, from an inconsequential idle flavor to a rather drastic
-**| panic flavor. Callers might perform an idle purge very frequently if desired
-**| with very little cost, since only normally scheduled memory management will
-**| be conducted, such as freeing resources for objects scheduled to be dropped.
-**| Callers should perform session memory purges infrequently because they might
-**| involve costly scanning of data structures to removed cached content, and
-**| session purges are recommended only when a caller experiences memory crunch.
-**| Callers should only rarely perform a panic purge, in response to dire memory
-**| straits, since this is likely to make db operations much more expensive
-**| than they would be otherwise. A panic purge asks a database to free as much
-**| memory as possible while staying effective and operational, because a caller
-**| thinks application failure might otherwise occur. (Apps might better close
-**| an open db, so panic purges only make sense when a db is urgently needed.)
-|*/
-class nsIMdbPort : public nsISupports {
-public:
-
-// { ===== begin nsIMdbPort methods =====
-
- // { ----- begin attribute methods -----
- NS_IMETHOD GetIsPortReadonly(nsIMdbEnv* ev, mdb_bool* outBool) = 0;
- NS_IMETHOD GetIsStore(nsIMdbEnv* ev, mdb_bool* outBool) = 0;
- NS_IMETHOD GetIsStoreAndDirty(nsIMdbEnv* ev, mdb_bool* outBool) = 0;
-
- NS_IMETHOD GetUsagePolicy(nsIMdbEnv* ev,
- mdbUsagePolicy* ioUsagePolicy) = 0;
-
- NS_IMETHOD SetUsagePolicy(nsIMdbEnv* ev,
- const mdbUsagePolicy* inUsagePolicy) = 0;
- // } ----- end attribute methods -----
-
- // { ----- begin memory policy methods -----
- NS_IMETHOD IdleMemoryPurge( // do memory management already scheduled
- nsIMdbEnv* ev, // context
- mdb_size* outEstimatedBytesFreed) = 0; // approximate bytes actually freed
-
- NS_IMETHOD SessionMemoryPurge( // request specific footprint decrease
- nsIMdbEnv* ev, // context
- mdb_size inDesiredBytesFreed, // approximate number of bytes wanted
- mdb_size* outEstimatedBytesFreed) = 0; // approximate bytes actually freed
-
- NS_IMETHOD PanicMemoryPurge( // desperately free all possible memory
- nsIMdbEnv* ev, // context
- mdb_size* outEstimatedBytesFreed) = 0; // approximate bytes actually freed
- // } ----- end memory policy methods -----
-
- // { ----- begin filepath methods -----
- NS_IMETHOD GetPortFilePath(
- nsIMdbEnv* ev, // context
- mdbYarn* outFilePath, // name of file holding port content
- mdbYarn* outFormatVersion) = 0; // file format description
-
- NS_IMETHOD GetPortFile(
- nsIMdbEnv* ev, // context
- nsIMdbFile** acqFile) = 0; // acquire file used by port or store
- // } ----- end filepath methods -----
-
- // { ----- begin export methods -----
- NS_IMETHOD BestExportFormat( // determine preferred export format
- nsIMdbEnv* ev, // context
- mdbYarn* outFormatVersion) = 0; // file format description
-
- // some tentative suggested import/export formats
- // "ns:msg:db:port:format:ldif:ns4.0:passthrough" // necessary
- // "ns:msg:db:port:format:ldif:ns4.5:utf8" // necessary
- // "ns:msg:db:port:format:ldif:ns4.5:tabbed"
- // "ns:msg:db:port:format:ldif:ns4.5:binary" // necessary
- // "ns:msg:db:port:format:html:ns3.0:addressbook" // necessary
- // "ns:msg:db:port:format:html:display:verbose"
- // "ns:msg:db:port:format:html:display:concise"
- // "ns:msg:db:port:format:mork:zany:verbose" // necessary
- // "ns:msg:db:port:format:mork:zany:atomized" // necessary
- // "ns:msg:db:port:format:rdf:xml"
- // "ns:msg:db:port:format:xml:mork"
- // "ns:msg:db:port:format:xml:display:verbose"
- // "ns:msg:db:port:format:xml:display:concise"
- // "ns:msg:db:port:format:xml:print:verbose" // recommended
- // "ns:msg:db:port:format:xml:print:concise"
-
- NS_IMETHOD
- CanExportToFormat( // can export content in given specific format?
- nsIMdbEnv* ev, // context
- const char* inFormatVersion, // file format description
- mdb_bool* outCanExport) = 0; // whether ExportSource() might succeed
-
- NS_IMETHOD ExportToFormat( // export content in given specific format
- nsIMdbEnv* ev, // context
- // const char* inFilePath, // the file to receive exported content
- nsIMdbFile* ioFile, // destination abstract file interface
- const char* inFormatVersion, // file format description
- nsIMdbThumb** acqThumb) = 0; // acquire thumb for incremental export
- // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and
- // then the export will be finished.
-
- // } ----- end export methods -----
-
- // { ----- begin token methods -----
- NS_IMETHOD TokenToString( // return a string name for an integer token
- nsIMdbEnv* ev, // context
- mdb_token inToken, // token for inTokenName inside this port
- mdbYarn* outTokenName) = 0; // the type of table to access
-
- NS_IMETHOD StringToToken( // return an integer token for scope name
- nsIMdbEnv* ev, // context
- const char* inTokenName, // Latin1 string to tokenize if possible
- mdb_token* outToken) = 0; // token for inTokenName inside this port
-
- // String token zero is never used and never supported. If the port
- // is a mutable store, then StringToToken() to create a new
- // association of inTokenName with a new integer token if possible.
- // But a readonly port will return zero for an unknown scope name.
-
- NS_IMETHOD QueryToken( // like StringToToken(), but without adding
- nsIMdbEnv* ev, // context
- const char* inTokenName, // Latin1 string to tokenize if possible
- mdb_token* outToken) = 0; // token for inTokenName inside this port
-
- // QueryToken() will return a string token if one already exists,
- // but unlike StringToToken(), will not assign a new token if not
- // already in use.
-
- // } ----- end token methods -----
-
- // { ----- begin row methods -----
- NS_IMETHOD HasRow( // contains a row with the specified oid?
- nsIMdbEnv* ev, // context
- const mdbOid* inOid, // hypothetical