merge the last green changeset on m-c to fx-team
authorTim Taubert <tim.taubert@gmx.de>
Tue, 09 Aug 2011 18:00:52 +0200
changeset 74068 8f9746b88447b8990ef45da38791ba5369cec945
parent 74067 f356bab9216412cdeafd040856fd8362e4a2e7fa (current diff)
parent 74056 fc0c60debaaea204df096d81668de3dac24ca070 (diff)
child 74078 a0e3c589c8fad05ab6e67efe7cd4911469561dbf
child 74102 3a90c075243624a98d33e20b4ffc7e87c6c001e4
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
milestone8.0a1
merge the last green changeset on m-c to fx-team
content/html/content/test/test_bug418756.html
db/README.html
db/mdb/Makefile.in
db/mdb/public/Makefile.in
db/mdb/public/mdb.h
db/mork/Makefile.in
db/mork/build/Makefile.in
db/mork/build/nsIMdbFactoryFactory.h
db/mork/build/nsMorkCID.h
db/mork/build/nsMorkFactory.cpp
db/mork/src/Makefile.in
db/mork/src/mork.h
db/mork/src/morkArray.cpp
db/mork/src/morkArray.h
db/mork/src/morkAtom.cpp
db/mork/src/morkAtom.h
db/mork/src/morkAtomMap.cpp
db/mork/src/morkAtomMap.h
db/mork/src/morkAtomSpace.cpp
db/mork/src/morkAtomSpace.h
db/mork/src/morkBead.cpp
db/mork/src/morkBead.h
db/mork/src/morkBlob.cpp
db/mork/src/morkBlob.h
db/mork/src/morkBuilder.cpp
db/mork/src/morkBuilder.h
db/mork/src/morkCell.cpp
db/mork/src/morkCell.h
db/mork/src/morkCellObject.cpp
db/mork/src/morkCellObject.h
db/mork/src/morkCh.cpp
db/mork/src/morkCh.h
db/mork/src/morkConfig.cpp
db/mork/src/morkConfig.h
db/mork/src/morkCursor.cpp
db/mork/src/morkCursor.h
db/mork/src/morkDeque.cpp
db/mork/src/morkDeque.h
db/mork/src/morkEnv.cpp
db/mork/src/morkEnv.h
db/mork/src/morkFactory.cpp
db/mork/src/morkFactory.h
db/mork/src/morkFile.cpp
db/mork/src/morkFile.h
db/mork/src/morkHandle.cpp
db/mork/src/morkHandle.h
db/mork/src/morkIntMap.cpp
db/mork/src/morkIntMap.h
db/mork/src/morkMap.cpp
db/mork/src/morkMap.h
db/mork/src/morkNode.cpp
db/mork/src/morkNode.h
db/mork/src/morkNodeMap.cpp
db/mork/src/morkNodeMap.h
db/mork/src/morkObject.cpp
db/mork/src/morkObject.h
db/mork/src/morkParser.cpp
db/mork/src/morkParser.h
db/mork/src/morkPool.cpp
db/mork/src/morkPool.h
db/mork/src/morkPortTableCursor.cpp
db/mork/src/morkPortTableCursor.h
db/mork/src/morkProbeMap.cpp
db/mork/src/morkProbeMap.h
db/mork/src/morkQuickSort.cpp
db/mork/src/morkQuickSort.h
db/mork/src/morkRow.cpp
db/mork/src/morkRow.h
db/mork/src/morkRowCellCursor.cpp
db/mork/src/morkRowCellCursor.h
db/mork/src/morkRowMap.cpp
db/mork/src/morkRowMap.h
db/mork/src/morkRowObject.cpp
db/mork/src/morkRowObject.h
db/mork/src/morkRowSpace.cpp
db/mork/src/morkRowSpace.h
db/mork/src/morkSearchRowCursor.cpp
db/mork/src/morkSearchRowCursor.h
db/mork/src/morkSink.cpp
db/mork/src/morkSink.h
db/mork/src/morkSpace.cpp
db/mork/src/morkSpace.h
db/mork/src/morkStore.cpp
db/mork/src/morkStore.h
db/mork/src/morkStream.cpp
db/mork/src/morkStream.h
db/mork/src/morkTable.cpp
db/mork/src/morkTable.h
db/mork/src/morkTableRowCursor.cpp
db/mork/src/morkTableRowCursor.h
db/mork/src/morkThumb.cpp
db/mork/src/morkThumb.h
db/mork/src/morkUniqRowCursor.h
db/mork/src/morkWriter.cpp
db/mork/src/morkWriter.h
db/mork/src/morkYarn.cpp
db/mork/src/morkYarn.h
db/mork/src/morkZone.cpp
db/mork/src/morkZone.h
db/mork/src/orkinHeap.cpp
db/mork/src/orkinHeap.h
db/morkreader/Makefile.in
db/morkreader/external/Makefile.in
db/morkreader/nsMorkReader.cpp
db/morkreader/nsMorkReader.h
dom/public/coreEvents/Makefile.in
dom/public/coreEvents/nsIDOMCompositionListener.h
dom/public/coreEvents/nsIDOMContextMenuListener.h
dom/public/coreEvents/nsIDOMFocusListener.h
dom/public/coreEvents/nsIDOMFormListener.h
dom/public/coreEvents/nsIDOMKeyListener.h
dom/public/coreEvents/nsIDOMLoadListener.h
dom/public/coreEvents/nsIDOMMouseListener.h
dom/public/coreEvents/nsIDOMMouseMotionListener.h
dom/public/coreEvents/nsIDOMTextListener.h
dom/public/coreEvents/nsIDOMUIListener.h
js/src/xpconnect/loader/ISO8601DateUtils.jsm
layout/reftests/backgrounds/background-size-no-intrinsic-height-image-ref.html
layout/reftests/backgrounds/background-size-no-intrinsic-height-image.html
layout/reftests/backgrounds/background-size-no-intrinsic-width-image-ref.html
layout/reftests/backgrounds/background-size-no-intrinsic-width-image.html
layout/reftests/backgrounds/no-intrinsic-size.svg
mobile/chrome/content/browser.xul
mobile/components/build/nsIPhoneSupport.idl
mobile/components/build/nsPhoneSupport.cpp
mobile/components/build/nsPhoneSupport.h
toolkit/components/places/nsMorkHistoryImporter.cpp
toolkit/components/places/nsNoMorkStubImporter.cpp
toolkit/components/places/tests/unit/history.dat
toolkit/components/places/tests/unit/migrateFrecency.dat
toolkit/components/satchel/test/unit/formhistory.dat
toolkit/components/satchel/test/unit/test_bug_329741.js
toolkit/components/webapps/Makefile.in
toolkit/components/webapps/nsIWebappsSupport.idl
toolkit/components/webapps/nsWebappsSupport.cpp
toolkit/components/webapps/nsWebappsSupport.h
--- 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
zc$@*%2rBo9P)<h;3K|Lk000e1NJLTq003G50018d1ONa4%`_5L00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU)XGugsR9M5k
zms@OH)fI;SeLH97%$%7y<FP09BzEk?apIuFC{1HSASgkIP*oA_3u;qE2&q)9`cUPm
zqP)<eR(+{TUP>h%KvV)G3Kc3CL=okdq``t35>qGGxr{Gye4G26%ig;WLvi9uJQJj@
z^)%A?&iZHVwf0(vV5M1TMGKOMBMhK|9Of~DDU`9keG}GzjVLUHAOQHNqKqO6@RmPF
zmi>0n)z$su%)zG3DLZLK0Jl__zc~BO+@B}L&SMM<Hwo&Xi*-`YT@i3iG@wa9d>)u8
zkmKvHVKfc2{bI|vHYP%0Vo1Pa6}?#fIQxe$PflVEm9<6p-oESctq0nZ?eL+XpaBq2
zP>A`<|GfO`3!e<*+!|qfjqQ|$tENvBQAF2RO*GZi6_t>Z-WO}K=_6gg+TGn0pTI0~
zD4+@;1RHUra+&jUzxnsy#&C5t(H3?+*8h{vjh*lyp;w#;gOMHo)A*C8FudZhE$lM7
zBE^VD1Lm`UDynLkR#Z{RrBJ+Nl%n3)Dy%@;v-|Gf+HxLQTwCQ2HDlvU_uz$Nr!fit
zM$uMy?}>d6?TAF+uMoT>T$D;LjQsp`<;)GCt?*uKNR&dZ@PudhOftn3)qo<BN-CKr
ze8V@Y=3)fX%UF@<`0L%@jz&Jk#7&APQ|kLy@q6zrUaHAvUzOC}KMwrpwlISS3AKhx
z1P0&P+$P@kgDcmS<6fFcm!fXOjd*d-_8mVaZ5flcim0fHNJE>NLqH&;%1Lfr&pI71
z-?NWKPOh5cCCeMrEtxypUz@KkE{X0vzW-<2ECLsD9rrnUVy^LF;p;HHVn=H!=0;uH
zbv(y+f~1VAxQeToit4D2>W~g;Lo+aNVxW)?<kxKa={pWZq93BT?#<#F)2YtQ$yaAl
zs)=^?-u=6+=|~-tB_skvY~df#$t<b>oa8{0+w9qH+-vfhf+m?zQG|&Flb9q-OkyDd
z3nmOO!ib<m)7Hu)ssO?d?fhwP(|dJD1_0l@*3vgo`Fs`u1JZqu?>vw}5kY;T;W_cJ
z_fff&1=4*avDvdd$4mN-bd-%S2@{hTwB{x;iJ&235<vuEl&}z65H>GmfgSC?@9!DH
zHRw9MYUes``{3H_0*96CI^-btzs{`7<RK^7b#)l<J2nO}Y0D-VSGMMq5w2IxjDQ%#
z(qUyvDw%8zvK<&k(4Ow3$f6O;cJ6LZk7Rk<rXx<Pg~c`RjMdC*O&oD@n*f(*{J2cY
zq>hjfW16q}783!Hgb|^sWRmC!-nOYZ_i#t*6jVc^kvjG8_UUmR${e(iN3}5+`GeL=
z86Y0SbV4VPAl9l`zFxLT1W{00>z2UH#A#nM-b14{(|1?g;bo^wpty3ruVbo9lpUZQ
z36(&C*wh5S=~<Zw2&0N9XqCnnPCgeaH=1Vvh?VmeFGW%m6$A~kGG&$`K#OP51mYyh
z46+_#LQoI|m$s0h$P70pZbh^?F~fPuh)R?is%QWpQM+USNoD&MkEk%=b-aNQ&0KEN
zBrh2O30-P9DuB?Xg*XS4$EuBsRvrL^X@pwL<Yt|sC9_zBhA9B}m0QWQUqPJPe$Gw#
z4VMScxwa1wgt;Xn+N7)w(VP(K^D-x}eFwQzJlDABTq+Hob|*rqpyAsiG~uURpe#%-
zq@fK}k7!9W72M=yo%TA2w+R;-7wv88p5~e2S$nsJ+h{+WRhc4i%@N#?hBoUKZE(S_
z1({-ZP<C#mJjzaYmTy~ltN8~UUPCXS;BN)n7JxHN%;1_4A?vB>fcT6HW{j)73q94L
z#a*``dT6nyN)Jzc><^g$+y)#&=Ewfwsl!t_ITbL$gy2RUE;tiROa(c4c<RpF;N0jy
z-FwGZJ~}WscV~_tnS5^X)#RQK@^$B$!g-bV%paKqo?ASV+7$voiCQn$0RaV5#+lOY
z#UqnIPwVBjZ4Ku7a;j%+&kQBi2d@muH<J+X>&mhZ@n&*RK6r&xN%g@iqrq8M8iaF3
zxL|90?Fng|bw`65dtd&g>EU}D$@B2NFHPT<Cshg@9qXSz5&End1m3!mJ&@0uPlWpC
zkB$Mr(Xj(_ugEDag%XT`bGEvJGp2+TQ~DKoV6MjQ&+e(di_z_Cekm>U(e3YIPj!D5
zpa3bHIA>L!N?qIlh5+78JOI16;i;5WIdP5@fEt@AyjY#1fdRoe5quRRf^&$#n4>RN
zGleDg(aD9}@Ya#`da^vyKD>1y_vj=k02BborQ@R$-V>QK9WWu+lq_MM>3AYD;T<0(
zm%bj2myVAX3s0A_$`b*n6pYau9gNa|dm^izE)@$mvd3mmUj2OcXz#iW*!%hJlUI+;
z*4VGs9BqEG^S50K<|B&_eTjKgS2QI>2+0?=Jd<$TUyj{=mRxtQ*Vy^kF|p4MOQwZh
z`pDM+d?HDOoi04<C-W=WY|k@^sC@{1gKM|nr}zH@#lj<t8~;;d$r6q&k8OM1x<lSS
z``roT;i5L&IRs3^Uds%oK4K4)pB%-PWZ5XHv2R5C&F`4qQA06Jz%(F<h9n+6U;Mj!
z$~|0Mi~URb9sT{(=Gop=_Um(ZUrfC`dyxF_>JodyLa966?tDIZGTbTe^12IKi=7o<
zJbWQ~-hSU0X9Ja^^Y@M~9qzK=9dCC&pFCx4GY04mvB8W9An#ARBmPM>>h+gz&W>bW
z=O5^MV*R!?%P+GjK(+?$<<zOdyZQa(fndkP_3W}OSlehDX?r8~KL5g)G718){Z?<g
zcUN#Yzhe@UwH8_<^fzRuTZY7Ge@LEFR{^BaOZTvSVvoOJW;wgc>aIg*LIN>FP@9w`
j<gti3QpZyD|6%_NY2V3qr=j_O00000NkvXXu0mjf^B+o{
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c3ecea0315f6f42b06dc2fe869d6d0461fef0930
GIT binary patch
literal 2262
zc$@*&2r2i8P)<h;3K|Lk000e1NJLTq003G50018d1ONa4%`_5L00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU)Xh}ptR9M5U
zn14`HR~E;^SpIPQXUDNPb&9h)<68e|t@}^^$f%>zK@1e3wxGjMVqvI*qKhI}FpUDD
zM2$R9AX=y_Ly2_3AE1EjhA0Y{1+B1B?X1#82u6&=G=bzj-*-=50s$eAIGfL$%(>^D
zGaT+a@7{AG5>5N;TabTHb|=ZWm5tyd_^oV`QFbT);JyVSFFxYM;&8ECd_jCi{Dine
znw%_)y@_Q4m`zL?Q_3_mcZp`w(#R4pXW;3;!;R5w2CC7G7qAj9NUKH$qS?cZrvqnA
z_yh6YwKq1s++vBfC33s?U3?-JYujSk^m6SD@m}!<vnITZNjh8KIB?%MU@@~C&+%q<
zz;fT%IB>R}Nn)1G5}K#j%I2dVV>8f?d~CDlDLf?XCyrgG4SyxI@1uY45VCQE$R;fV
z`yjQ4zgnji$BO-COxTZ!DyzR`(2w$%j(+r(p{$;XVrGh!zmwjTNULgvg|G@@b!p>t
zBM~y)g?ZCb4iL*W8e_-Ok%f~e!uKdg1yN2~5m~a3j@Yq{MzKsh?O`*EnAG~GeZRkk
zXZn7xf6AmXi{1#mFfX@zJBDF)@k)?aF3rs_LXq-V{?62t*C@hFJ2*L%l;n@7#T8sb
zBXNziTC#jkGji<U!c1!vQ`2S^6&}_+dtqlWJ1^{-XN8B~NPGX?P)caT3x**@hHi3U
ztdWPAl3(Z0npWa6nxMf=wBi=gN}7f&muaR5IY@p@Y0KS3!uS=YYo3`nJLbm3QQGN~
zisXnQ0fR6SF9h+7V^)s@9GR$Xacs!TBrXRkdR?zlimkYfc67LCr%@|euhOiF(oW(+
zUW#KUl8&kyFxbc79R_>d02Ad3JrNki>R`Zg!XSvjrMa1E*CC2M5$N18f?B__Wl=&u
zp#fT2-8M>eDs5!d((F&<m4&ZtL9Nc6gjrVJ@T+AM-t()ayur1TWHjYr$OC#o^e)ZK
zF=RA3V%Mi{HfN#`YO3FsiL!VTN13#chnhSyvDv&n-4T0ckM_9*zM*}7W{=2mlzhS7
z$AAY01sQZ{Ztmj?cHaW=;-Iz!dmheH)&7Ihx-kna<Z+oi^N?T<Y7;MJ0!o`7kDB2d
zk4H<J>A1-~xR>_e{|e$6r-$3GAA6B|aDAj?Bm<{u1+StR|D1zn@=}v`1|%cvBhQ4@
z=}qvRI{le2(SDr@PtYewpG%uQ9%tO%hqFl4Z9Eob&7lpgmMXRh*XN*#ylTli2T|6I
z$Ic#VA2Gsr+DFbF62%*@<3DdfGvbY(UWvCU=m@z)_1fSC*T}OR3dGw!y`rjmU>%0<
zJg};&M4z)=c=Q%@;d6FFcQU8M-)Q~nyrh=Al}P3`bQj(3V-4_~KDOw#NW%Bv7xW6^
z#%Xce$H#7Z5X!H8n#!M|<GO}c&^v0#`xH_s@^tS2KLp<y;7|8b(m&(h6Z8nu<I+5j
zdvK4EUN^X(SJDHo#^1f9n!J_RPmx6r`}qO*PCsAtP!!3w(FW!_ZHQ!pdUkUsP)gl}
z+Dm>U?-SU~1@)A4JYxIdJCE3s4pE%(BJNIbPY^dw%S>EEoKeykZ#zckTm|(O-cdo`
z$LK|rG@h&Nvi=6&>9U@y747L%q7(lTWIE0n_x$*{lPYs}*Or24YZjeyW%SU!ql~<>
z5N+L3P=35+<OzJIWu*MLC_6U^cjlx+kPesT_)bE0u5^2-DTDfD6+QGaFDNC?lXSR*
znxxy+u{A?)v(?rNsbfVq-rLMJP=)$N12(fa-czgy=}ffepn#G&=LIVA%t4|(q*Jj%
zyS(hCZq(O}RySI9Q@dOQzm%45g+`}!61OHg;#)J0zr|l$;0OPhyhw8f9Tx@EFBi{2
z5qT+Sog>XLdGLpSWp>^0FYt}J;mU0IQ_FOHRRnv%)z)YQapSbO?N03iBG~Jz9GzO$
zYKcy2JA~tOgDj-J!ZU^Bah&dqQkz7Vwb~KeEH2l!S{}fAS}o<;X0gzkVxGKsn{eaM
zP+OxBnj5D!GfmhAc`<~WBIYNgZ8GiT4pH}}q_h|h<kM^(rM#2dWJ*ZGd}nNRidwI;
z_rN=JcD24b#Tn}eU-(UT0^RAFy`T}n_~t$qj^9440Wrnl<~^_FI7&P4NlNb28z{+o
zf@bB|^E%udQ*52MCE5cj^J@*ATsP*XldCmU=G!OVFh~9r_ggUa28}M71aafEG?K?o
zB=?T~aq|7LVrBICaB~uuNt;<Nt*3&@z>R_|xiphWSFLb!^!bXFlVk6GR8dl6=&=8c
z+3B#?7%EEcel+D`3%{{tiQUoofjTh<R|UE1(#H7#(Maqz{TWk!gMfe4s+eMlDbAJ-
z84lC_aD>u4O5~E3LlznRgb-(wm|}{nRtc}sq}Y2OSLRpgHI{qujK)%>ugt&q@zhu$
zZ7j`Hea5EHxpjqB^or1xIW@<3B~tJio2kN5O#9gc{$qi=WD;G3Io_U%1GK6#d`HMg
zJAhQg+at^p-7eW!;IuzWv25VQ1Lw6Dhqa?!n2vVz;xNq~U}uPR)%NWTJ6poouc`iu
zsZ*$>u1rnZcla7%?9P_k8{D-#E%x2w5UDbxGt~5@RchP8?dEs$J2<KBOKYepq*JOa
z4#B&gW7~t(N6T)ihw4W();3nh>-aWSW33-i50Uj~d$8wNVJE?oC!ffbiCxjgFgBPE
z=0n+NV`7(F`Q#HU!93AyvGcK{ZcSQBj4G@tsAt{ay1}5Hu%;MQT1wp-ik&}KZ13v&
z<jR85OC=pe4~rg_bd+AIET~WJT|HOqc%l4(ieLp+;xEKX(w36NZ_YsBVPhfQ$8vm#
kRm6v+y-ybZ|8MO703C%2de`kFq5uE@07*qoM6N<$f+T@*r2qf`
--- 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