From 2bc98482827bfc770afaa464f42dd0024076b11c Mon Sep 17 00:00:00 2001 From: Adrian Tamas Date: Tue, 20 Aug 2013 10:26:55 +0300 Subject: [PATCH 01/82] Bug 899187 - add a Robocop tests for Bookmarks Folders and the Bookmarks Page. r=lucasr --- .../android/base/tests/AboutHomeTest.java.in | 85 ++------ mobile/android/base/tests/BaseTest.java.in | 1 + .../android/base/tests/StringHelper.java.in | 7 + mobile/android/base/tests/robocop.ini | 2 + .../android/base/tests/testBookmark.java.in | 2 +- .../base/tests/testBookmarkFolders.java.in | 187 ++++++++++++++++++ .../base/tests/testBookmarksPage.java.in | 99 ++++++++++ 7 files changed, 315 insertions(+), 68 deletions(-) create mode 100644 mobile/android/base/tests/testBookmarkFolders.java.in create mode 100644 mobile/android/base/tests/testBookmarksPage.java.in diff --git a/mobile/android/base/tests/AboutHomeTest.java.in b/mobile/android/base/tests/AboutHomeTest.java.in index ea0239d1cd68..6df8ab062bdb 100644 --- a/mobile/android/base/tests/AboutHomeTest.java.in +++ b/mobile/android/base/tests/AboutHomeTest.java.in @@ -20,6 +20,7 @@ import android.widget.TextView; import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Arrays; /** * This class is an extension of BaseTest that helps with interaction with about:home @@ -61,13 +62,16 @@ abstract class AboutHomeTest extends PixelTest { } // Returns true if the bookmark is displayed in the bookmarks tab, false otherwise - does not check in folders - protected boolean isBookmarkDisplayed(String url) { - View bookmark = getDisplayedBookmark(url); - if (bookmark != null) { - return true; - } else { - return false; - } + protected void isBookmarkDisplayed(final String url) { + boolean isCorrect = waitForTest(new BooleanTest() { + @Override + public boolean test() { + View bookmark = getDisplayedBookmark(url); + return bookmark != null; + } + }, MAX_WAIT_MS); + + mAsserter.ok(isCorrect, "Checking that " + url + " displayed as a bookmark", url + " displayed"); } // Loads a bookmark by tapping on the bookmark view in the Bookmarks tab @@ -79,7 +83,7 @@ abstract class AboutHomeTest extends PixelTest { contentEventExpecter.blockForEvent(); contentEventExpecter.unregisterListener(); } else { - mAsserter.ok(false, url + " is not one of the displayed bookmarks", "Please make sure the url provided is ookmarked"); + mAsserter.ok(false, url + " is not one of the displayed bookmarks", "Please make sure the url provided is bookmarked"); } } @@ -87,8 +91,9 @@ abstract class AboutHomeTest extends PixelTest { protected void openBookmarkContextMenu(String url) { View bookmark = getDisplayedBookmark(url); if (bookmark != null) { - mSolo.clickLongOnView(bookmark); - waitForText("Share"); + mSolo.waitForView(bookmark); + mSolo.clickLongOnView(bookmark, LONG_PRESS_TIME); + mSolo.waitForDialogToOpen(); } else { mAsserter.ok(false, url + " is not one of the displayed bookmarks", "Please make sure the url provided is bookmarked"); } @@ -97,6 +102,8 @@ abstract class AboutHomeTest extends PixelTest { // @return the View associated with bookmark for the provided url or null if the link is not bookmarked protected View getDisplayedBookmark(String url) { openAboutHomeTab(AboutHomeTabs.BOOKMARKS); + mSolo.hideSoftKeyboard(); + getInstrumentation().waitForIdleSync(); ListView bookmarksTabList = findListViewWithTag("bookmarks"); waitForNonEmptyListToLoad(bookmarksTabList); ListAdapter adapter = bookmarksTabList.getAdapter(); @@ -112,7 +119,7 @@ abstract class AboutHomeTest extends PixelTest { if (bookmarkContent instanceof android.widget.LinearLayout) { ViewGroup bookmarkItemLayout = (ViewGroup) bookmarkContent; for (int k = 0 ; k < bookmarkItemLayout.getChildCount(); k++) { - // Both the title and url are represented as text views so we can cast the view without any ssues + // Both the title and url are represented as text views so we can cast the view without any issues TextView bookmarkTextContent = (TextView)bookmarkItemLayout.getChildAt(k); if (url.equals(bookmarkTextContent.getText().toString())) { return bookmarkView; @@ -176,62 +183,6 @@ abstract class AboutHomeTest extends PixelTest { return null; } - /** - * FIXME: rewrite this to work with fig when rewriting the testBookmarksTab test - * This method will edit the bookmark with index = bookmarkIndex from the list of bookmarks - * For the field index: - * fieldIndex = 1 - the Bookmark name - * fieldIndex = 2 - the Bookmark url - * fieldIndex = 3 - the Bookmark keyword - */ - protected void editBookmark(int bookmarkIndex, int fieldIndex, String addedText, ListView list) { - - // Open the Edit Bookmark context menu - View child; - mSolo.clickOnText("Bookmarks"); - child = list.getChildAt(bookmarkIndex); - mAsserter.ok(child != null, "edit item can be retrieved", child != null ? child.toString() : "null!"); - waitForText("Switch to tab"); - mSolo.clickLongOnView(child); - waitForText("Share"); - mSolo.clickOnText("Edit"); - waitForText("Edit Bookmark"); - - // Clear the Field - mSolo.clearEditText(fieldIndex); - - // Enter the new text - mSolo.clickOnEditText(fieldIndex); - mActions.sendKeys(addedText); - mSolo.clickOnText("OK"); - waitForText("Bookmark updated"); - } - - // FIXME: rewrite this to work with fig when rewriting the testBookmarksTab test - protected boolean checkBookmarkEdit(int bookmarkIndex, String addedText, ListView list) { - // Open the Edit Bookmark context menu - View child; - mSolo.clickOnText("Bookmarks"); - child = list.getChildAt(bookmarkIndex); - mAsserter.ok(child != null, "check item can be retrieved", child != null ? child.toString() : "null!"); - waitForText("Switch to tab"); - mSolo.clickLongOnView(child); - waitForText("Share"); - mSolo.clickOnText("Edit"); - waitForText("Edit Bookmark"); - - // Check if the new text was added - if (mSolo.searchText(addedText)) { - clickOnButton("Cancel"); - waitForText("about:home"); - return true; - } else { - clickOnButton("Cancel"); - waitForText("about:home"); - return false; - } - } - // A wait in order for the about:home tab to be rendered after drag/tab selection private void waitForAboutHomeTab(final int tabIndex) { boolean correctTab = waitForCondition(new Condition() { diff --git a/mobile/android/base/tests/BaseTest.java.in b/mobile/android/base/tests/BaseTest.java.in index c2100e77d5f1..0aadbd10df4f 100644 --- a/mobile/android/base/tests/BaseTest.java.in +++ b/mobile/android/base/tests/BaseTest.java.in @@ -52,6 +52,7 @@ abstract class BaseTest extends ActivityInstrumentationTestCase2 { private static final int MAX_WAIT_ENABLED_TEXT_MS = 10000; private static final int MAX_WAIT_HOME_PAGER_HIDDEN_MS = 15000; public static final int MAX_WAIT_MS = 4500; + public static final int LONG_PRESS_TIME = 6000; // IDs for UI views private static final String BROWSER_TOOLBAR_ID = "browser_toolbar"; diff --git a/mobile/android/base/tests/StringHelper.java.in b/mobile/android/base/tests/StringHelper.java.in index df818475b1f2..b676a856c735 100644 --- a/mobile/android/base/tests/StringHelper.java.in +++ b/mobile/android/base/tests/StringHelper.java.in @@ -40,6 +40,13 @@ class StringHelper { "Bookmark Link" }; + public static final String[] BOOKMARK_CONTEXT_MENU_ITEMS = new String[] { + "Open in New Tab", + "Open in Private Tab", + "Edit", + "Remove" + }; + public static final String TITLE_PLACE_HOLDER = "Enter Search or Address"; // Robocop page urls diff --git a/mobile/android/base/tests/robocop.ini b/mobile/android/base/tests/robocop.ini index 7b825e306812..ecc8419a3046 100644 --- a/mobile/android/base/tests/robocop.ini +++ b/mobile/android/base/tests/robocop.ini @@ -1,6 +1,8 @@ [testAwesomebar] # [testAwesomebarSwipes] # disabled on fig - bug 880060 [testBookmark] +[testBookmarksPage] +[testBookmarkFolders] # [testBookmarklets] # see bug 915350 # [testBookmarkKeyword] # see bug 915350 [testBrowserSearchVisibility] diff --git a/mobile/android/base/tests/testBookmark.java.in b/mobile/android/base/tests/testBookmark.java.in index 35c959d6570d..b4f118e287f2 100644 --- a/mobile/android/base/tests/testBookmark.java.in +++ b/mobile/android/base/tests/testBookmark.java.in @@ -42,7 +42,7 @@ public class testBookmark extends AboutHomeTest { mDatabaseHelper.addOrUpdateMobileBookmark(StringHelper.ROBOCOP_BLANK_PAGE_01_TITLE, BOOKMARK_URL); waitForBookmarked(true); - mAsserter.ok(isBookmarkDisplayed(BOOKMARK_URL), "Checking if " + BOOKMARK_URL + " is displayed in the Bookmarks Tab", "The bookmark is displayed"); + isBookmarkDisplayed(BOOKMARK_URL); loadBookmark(BOOKMARK_URL); waitForText(StringHelper.ROBOCOP_BLANK_PAGE_01_TITLE); verifyPageTitle(StringHelper.ROBOCOP_BLANK_PAGE_01_TITLE); diff --git a/mobile/android/base/tests/testBookmarkFolders.java.in b/mobile/android/base/tests/testBookmarkFolders.java.in new file mode 100644 index 000000000000..3c54acbf8e9b --- /dev/null +++ b/mobile/android/base/tests/testBookmarkFolders.java.in @@ -0,0 +1,187 @@ +#filter substitution +package @ANDROID_PACKAGE_NAME@.tests; + +import @ANDROID_PACKAGE_NAME@.*; + +import com.jayway.android.robotium.solo.Condition; + +import android.content.ContentResolver; +import android.content.ContentValues; +import android.content.ContentUris; +import android.database.Cursor; +import android.net.Uri; +import android.view.View; +import android.widget.ListAdapter; +import android.widget.ListView; +import android.widget.TextView; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; + +public class testBookmarkFolders extends AboutHomeTest { + private static String DESKTOP_BOOKMARK_URL; + + @Override + protected int getTestType() { + return TEST_MOCHITEST; + } + + public void testBookmarkFolders() { + DESKTOP_BOOKMARK_URL = getAbsoluteUrl(StringHelper.ROBOCOP_BLANK_PAGE_02_URL); + + setUpDesktopBookmarks(); + checkBookmarkList(); + } + + private void checkBookmarkList() { + openAboutHomeTab(AboutHomeTabs.BOOKMARKS); + waitForText(StringHelper.DESKTOP_FOLDER_LABEL); + clickOnBookmarkFolder(StringHelper.DESKTOP_FOLDER_LABEL); + waitForText(StringHelper.TOOLBAR_FOLDER_LABEL); + + // Verify the number of folders displayed in the Desktop Bookmarks folder is correct + ListView desktopFolderContent = findListViewWithTag("bookmarks"); + ListAdapter adapter = desktopFolderContent.getAdapter(); + if (mDevice.type.equals("tablet")) { // On tablets it's 4 folders and 1 view for top padding + mAsserter.is(adapter.getCount(), 5, "Checking that the correct number of folders is displayed in the Desktop Bookmarks folder"); + } else { // On phones it's just the 4 folders + mAsserter.is(adapter.getCount(), 4, "Checking that the correct number of folders is displayed in the Desktop Bookmarks folder"); + } + + clickOnBookmarkFolder(StringHelper.TOOLBAR_FOLDER_LABEL); + + // Go up in the bookmark folder hierarchy + clickOnBookmarkFolder(StringHelper.TOOLBAR_FOLDER_LABEL); + mAsserter.ok(waitForText(StringHelper.BOOKMARKS_MENU_FOLDER_LABEL), "Going up in the folder hierarchy", "We are back in the Desktop Bookmarks folder"); + + clickOnBookmarkFolder(StringHelper.DESKTOP_FOLDER_LABEL); + mAsserter.ok(waitForText(StringHelper.DESKTOP_FOLDER_LABEL), "Going up in the folder hierarchy", "We are back in the main Bookmarks List View"); + + clickOnBookmarkFolder(StringHelper.DESKTOP_FOLDER_LABEL); + clickOnBookmarkFolder(StringHelper.TOOLBAR_FOLDER_LABEL); + isBookmarkDisplayed(DESKTOP_BOOKMARK_URL); + + // Open the bookmark from a bookmark folder hierarchy + loadBookmark(DESKTOP_BOOKMARK_URL); + waitForText(StringHelper.ROBOCOP_BLANK_PAGE_02_TITLE); + verifyPageTitle(StringHelper.ROBOCOP_BLANK_PAGE_02_TITLE); + openAboutHomeTab(AboutHomeTabs.BOOKMARKS); + + // Check that folders don't have a context menu + boolean success = waitForCondition(new Condition() { + @Override + public boolean isSatisfied() { + View desktopFolder = getBookmarkFolderView(StringHelper.DESKTOP_FOLDER_LABEL); + if (desktopFolder == null) { + return false; + } + mSolo.clickLongOnView(desktopFolder); + return true; } + }, MAX_WAIT_MS); + + mAsserter.ok(success, "Trying to long click on the Desktop Bookmarks","Desktop Bookmarks folder could not be long clicked"); + + final String contextMenuString = StringHelper.BOOKMARK_CONTEXT_MENU_ITEMS[0]; + mAsserter.ok(!waitForText(contextMenuString), "Folders do not have context menus", "The context menu was not opened"); + + // Even if no context menu is opened long clicking a folder still opens it. We need to close it. + clickOnBookmarkFolder(StringHelper.DESKTOP_FOLDER_LABEL); + } + + private void clickOnBookmarkFolder(final String folderName) { + boolean success = waitForCondition(new Condition() { + @Override + public boolean isSatisfied() { + View bookmarksFolder = getBookmarkFolderView(folderName); + if (bookmarksFolder == null) { + return false; + } + mSolo.waitForView(bookmarksFolder); + mSolo.clickOnView(bookmarksFolder); + return true; + } + }, MAX_WAIT_MS); + mAsserter.ok(success, "Trying to click on the " + folderName + " folder","The " + folderName + " folder was clicked"); + } + + private View getBookmarkFolderView(String folderName) { + openAboutHomeTab(AboutHomeTabs.BOOKMARKS); + mSolo.hideSoftKeyboard(); + getInstrumentation().waitForIdleSync(); + + ListView bookmarksTabList = findListViewWithTag("bookmarks"); + if (!waitForNonEmptyListToLoad(bookmarksTabList)) { + return null; + } + + ListAdapter adapter = bookmarksTabList.getAdapter(); + if (adapter == null) { + return null; + } + + for (int i = 0; i < adapter.getCount(); i++ ) { + View bookmarkView = bookmarksTabList.getChildAt(i); + if (bookmarkView instanceof TextView) { + TextView folderTextView = (TextView) bookmarkView; + if (folderTextView.getText().equals(folderName)) { + return bookmarkView; + } + } + } + + return null; + } + + // Add a bookmark in the Desktop folder so we can check the folder navigation in the bookmarks page + private void setUpDesktopBookmarks() { + blockForGeckoReady(); + + // Get the folder id of the StringHelper.DESKTOP_FOLDER_LABEL folder + Long desktopFolderId = mDatabaseHelper.getFolderIdFromGuid("toolbar"); + + // Generate a Guid for the bookmark + String generatedGuid = null; + try { + ClassLoader classLoader = getActivity().getClassLoader(); + Class syncUtilityClass = classLoader.loadClass("org.mozilla.gecko.sync.Utils"); + Method generateGuid = syncUtilityClass.getMethod("generateGuid", (Class[]) null); + generatedGuid = (String)generateGuid.invoke(null); + } catch (Exception e) { + mAsserter.dumpLog("Exception in setUpDesktopBookmarks" + e); + } + mAsserter.ok((generatedGuid != null), "Generating a random Guid for the bookmark", "We could not generate a Guid for the bookmark"); + + // Insert the bookmark + ContentResolver resolver = getActivity().getContentResolver(); + Uri bookmarksUri = mDatabaseHelper.buildUri(DatabaseHelper.BrowserDataType.BOOKMARKS); + + long now = System.currentTimeMillis(); + ContentValues values = new ContentValues(); + values.put("title", StringHelper.ROBOCOP_BLANK_PAGE_02_TITLE); + values.put("url", DESKTOP_BOOKMARK_URL); + values.put("parent", desktopFolderId); + values.put("modified", now); + values.put("type", 1); + values.put("guid", generatedGuid); + values.put("position", 10); + values.put("created", now); + + int updated = resolver.update(bookmarksUri, + values, + "url = ?", + new String[] { DESKTOP_BOOKMARK_URL }); + if (updated == 0) { + Uri uri = resolver.insert(bookmarksUri, values); + mAsserter.ok(true, "Inserted at: ", uri.toString()); + } else { + mAsserter.ok(false, "Failed to insert the Desktop bookmark", "Something went wrong"); + } + } + + @Override + public void tearDown() throws Exception { + mDatabaseHelper.deleteBookmark(DESKTOP_BOOKMARK_URL); + super.tearDown(); + } +} diff --git a/mobile/android/base/tests/testBookmarksPage.java.in b/mobile/android/base/tests/testBookmarksPage.java.in new file mode 100644 index 000000000000..c4895f23e07d --- /dev/null +++ b/mobile/android/base/tests/testBookmarksPage.java.in @@ -0,0 +1,99 @@ +#filter substitution +package @ANDROID_PACKAGE_NAME@.tests; + +import @ANDROID_PACKAGE_NAME@.*; + +public class testBookmarksPage extends AboutHomeTest { + + protected int getTestType() { + return TEST_MOCHITEST; + } + + public void testBookmarksPage() { + final String BOOKMARK_URL = getAbsoluteUrl(StringHelper.ROBOCOP_BLANK_PAGE_01_URL); + + // Add a mobile bookmark + mDatabaseHelper.addOrUpdateMobileBookmark(StringHelper.ROBOCOP_BLANK_PAGE_01_TITLE, BOOKMARK_URL); + + openAboutHomeTab(AboutHomeTabs.BOOKMARKS); + + // Check that the default bookmarks are displayed + for (String url : StringHelper.DEFAULT_BOOKMARKS_URLS) { + isBookmarkDisplayed(url); + } + + // Open the context menu for the first bookmark in the list + openBookmarkContextMenu(StringHelper.DEFAULT_BOOKMARKS_URLS[0]); + + // Test that the options are all displayed + for (String contextMenuOption : StringHelper.BOOKMARK_CONTEXT_MENU_ITEMS) { + mAsserter.ok(mSolo.searchText(contextMenuOption), "Checking that the context menu option is present", contextMenuOption + " is present"); + } + + // Test that "Open in New Tab" works + final Element tabCount = mDriver.findElement(getActivity(), "tabs_counter"); + final int tabCountInt = Integer.parseInt(tabCount.getText()); + Actions.EventExpecter tabEventExpecter = mActions.expectGeckoEvent("Tab:Added"); + mSolo.clickOnText(StringHelper.BOOKMARK_CONTEXT_MENU_ITEMS[0]); + tabEventExpecter.blockForEvent(); + tabEventExpecter.unregisterListener(); + mAsserter.ok(mSolo.searchText(StringHelper.TITLE_PLACE_HOLDER), "Checking that the tab is not changed", "The tab was not changed"); + + // Test that "Open in Private Tab" works + openBookmarkContextMenu(StringHelper.DEFAULT_BOOKMARKS_URLS[1]); + tabEventExpecter = mActions.expectGeckoEvent("Tab:Added"); + mSolo.clickOnText(StringHelper.BOOKMARK_CONTEXT_MENU_ITEMS[1]); + tabEventExpecter.blockForEvent(); + tabEventExpecter.unregisterListener(); + mAsserter.ok(mSolo.searchText(StringHelper.TITLE_PLACE_HOLDER), "Checking that the tab is not changed", "The tab was not changed"); + + // Test that "Edit" works + String[] editedBookmarkValues = new String[] { "New bookmark title", "www.NewBookmark.url", "newBookmarkKeyword" }; + editBookmark(BOOKMARK_URL, editedBookmarkValues); + checkBookmarkEdit(editedBookmarkValues[1], editedBookmarkValues); + + // Test that "Remove" works + openBookmarkContextMenu(editedBookmarkValues[1]); + mSolo.clickOnText(StringHelper.BOOKMARK_CONTEXT_MENU_ITEMS[3]); + waitForText("Bookmark removed"); + mAsserter.ok(!mDatabaseHelper.isBookmark(editedBookmarkValues[1]), "Checking that the bookmark was removed", "The bookmark was removed"); + } + + /** + * @param bookmarkUrl URL of the bookmark to edit + * @param values String array with the new values for all fields + */ + private void editBookmark(String bookmarkUrl, String[] values) { + openBookmarkContextMenu(bookmarkUrl); + mSolo.clickOnText("Edit"); + waitForText("Edit Bookmark"); + + // Update the fields with the new values + for (int i = 0; i < values.length; i++) { + mSolo.clearEditText(i); + mSolo.clickOnEditText(i); + mActions.sendKeys(values[i]); + } + + mSolo.clickOnButton("OK"); + waitForText("Bookmark updated"); + } + + /** + * @param bookmarkUrl String with the original url + * @param values String array with the new values for all fields + */ + private void checkBookmarkEdit(String bookmarkUrl, String[] values) { + openBookmarkContextMenu(bookmarkUrl); + mSolo.clickOnText("Edit"); + waitForText("Edit Bookmark"); + + // Check the values of the fields + for (String value : values) { + mAsserter.ok(mSolo.searchText(value), "Checking that the value is correct", "The value = " + value + " is correct"); + } + + mSolo.clickOnButton("Cancel"); + waitForText("BOOKMARKS"); + } +} From fd154e1b9c9a6837afabf871c1fa4c9ca3d6c4ca Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Tue, 5 Nov 2013 11:35:22 -0800 Subject: [PATCH 02/82] Bug 935156 - Exactly root the script stored in BytecodeParser; r=wingo --HG-- extra : rebase_source : f8c9500a04e10711680e6f8c729f438678054ad6 --- js/src/jsopcode.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index 786815895a77..12758170010c 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -389,7 +389,7 @@ class BytecodeParser JSContext *cx_; LifoAllocScope allocScope_; - JSScript *script_; + RootedScript script_; Bytecode **codeArray_; @@ -397,7 +397,7 @@ class BytecodeParser BytecodeParser(JSContext *cx, JSScript *script) : cx_(cx), allocScope_(&cx->tempLifoAlloc()), - script_(script), + script_(cx, script), codeArray_(nullptr) { } bool parse(); From e902bd3672cc6aac1622650bbfbffc26f014a2b1 Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Wed, 6 Nov 2013 17:16:56 +0000 Subject: [PATCH 03/82] Bug 935494 - AssertAppPrincipal doesn't compile when MOZ_CHILD_PERMISSIONS is not defined, r=bz --- dom/ipc/AppProcessChecker.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/dom/ipc/AppProcessChecker.cpp b/dom/ipc/AppProcessChecker.cpp index 7b36470a822d..6dbf484697e0 100644 --- a/dom/ipc/AppProcessChecker.cpp +++ b/dom/ipc/AppProcessChecker.cpp @@ -25,7 +25,12 @@ using namespace mozilla::dom; using namespace mozilla::hal_sandbox; using namespace mozilla::services; #else +namespace mozilla { +namespace dom { class PContentParent; +} +} + class nsIPrincipal; #endif @@ -280,16 +285,16 @@ AssertAppProcess(mozilla::hal_sandbox::PHalParent* aActor, } bool -AssertAppPrincipal(PContentParent* aActor, +AssertAppPrincipal(mozilla::dom::PContentParent* aActor, nsIPrincipal* aPrincipal) { return true; } uint32_t -CheckPermission(PContentParent*, - nsIPrincipal*, - const char*) +CheckPermission(mozilla::dom::PContentParent* aActor, + nsIPrincipal* aPrincipal, + const char* aPermission) { return nsIPermissionManager::ALLOW_ACTION; } From b331fe6f4314ffa7a60667a1cb3906873b4d8550 Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Wed, 6 Nov 2013 17:21:15 +0000 Subject: [PATCH 04/82] Bug 916091 - patch 1 - nsIMessageSender should send the nsIPrincipal with the messages, r=smaug --- content/base/public/nsIMessageManager.idl | 31 +++-- content/base/src/nsFrameLoader.cpp | 19 ++- content/base/src/nsFrameLoader.h | 3 +- content/base/src/nsFrameMessageManager.cpp | 113 ++++++++++++++---- content/base/src/nsFrameMessageManager.h | 11 +- .../base/src/nsInProcessTabChildGlobal.cpp | 17 ++- content/base/src/nsInProcessTabChildGlobal.h | 12 +- content/base/test/chrome.ini | 1 + .../test/test_messagemanager_principal.html | 94 +++++++++++++++ dom/ipc/ContentChild.cpp | 7 +- dom/ipc/ContentChild.h | 3 +- dom/ipc/ContentParent.cpp | 19 +-- dom/ipc/ContentParent.h | 8 +- dom/ipc/PBrowser.ipdl | 9 +- dom/ipc/PContent.ipdl | 9 +- dom/ipc/TabChild.cpp | 25 ++-- dom/ipc/TabChild.h | 15 ++- dom/ipc/TabParent.cpp | 17 ++- dom/ipc/TabParent.h | 7 +- 19 files changed, 328 insertions(+), 92 deletions(-) create mode 100644 content/base/test/test_messagemanager_principal.html diff --git a/content/base/public/nsIMessageManager.idl b/content/base/public/nsIMessageManager.idl index 417eb0fdafba..fbeb920d8de9 100644 --- a/content/base/public/nsIMessageManager.idl +++ b/content/base/public/nsIMessageManager.idl @@ -9,6 +9,7 @@ interface nsIDOMDOMStringList; interface nsIDOMWindow; interface nsIDocShell; interface nsIContent; +interface nsIPrincipal; /** * Message managers provide a way for chrome-privileged JS code to @@ -156,14 +157,15 @@ interface nsIMessageListener : nsISupports * receiveMessage is called with one parameter, which has the following * properties: * { - * target: %the target of the message. Either an element owning - * the message manager, or message manager itself if no - * element owns it% - * name: %message name%, - * sync: %true or false%. - * data: %structured clone of the sent message data%, - * json: %same as .data, deprecated%, - * objects: %named table of jsvals/objects, or null% + * target: %the target of the message. Either an element owning + * the message manager, or message manager itself if no + * element owns it% + * name: %message name%, + * sync: %true or false%. + * data: %structured clone of the sent message data%, + * json: %same as .data, deprecated%, + * objects: %named table of jsvals/objects, or null% + * principal: %principal for the window app * } * * Each listener is invoked with its own copy of the message @@ -231,7 +233,7 @@ interface nsIMessageListenerManager : nsISupports * messages that are only delivered to its one parent-process message * manager. */ -[scriptable, builtinclass, uuid(7f23767d-0f39-40c1-a22d-d3ab8a481f9d)] +[scriptable, builtinclass, uuid(d6b0d851-43e6-426d-9f13-054bc0198175)] interface nsIMessageSender : nsIMessageListenerManager { /** @@ -252,7 +254,8 @@ interface nsIMessageSender : nsIMessageListenerManager [implicit_jscontext, optional_argc] void sendAsyncMessage([optional] in AString messageName, [optional] in jsval obj, - [optional] in jsval objects); + [optional] in jsval objects, + [optional] in nsIPrincipal principal); }; /** @@ -289,7 +292,7 @@ interface nsIMessageBroadcaster : nsIMessageListenerManager nsIMessageListenerManager getChildAt(in unsigned long aIndex); }; -[scriptable, builtinclass, uuid(79eeb70f-58e3-4d32-b46f-106f42ada12b)] +[scriptable, builtinclass, uuid(7fda0941-9dcc-448b-bd39-16373c5b4003)] interface nsISyncMessageSender : nsIMessageSender { /** @@ -300,7 +303,8 @@ interface nsISyncMessageSender : nsIMessageSender [implicit_jscontext, optional_argc] jsval sendSyncMessage([optional] in AString messageName, [optional] in jsval obj, - [optional] in jsval objects); + [optional] in jsval objects, + [optional] in nsIPrincipal principal); /** * Like |sendSyncMessage()|, except re-entrant. New RPC messages may be @@ -314,7 +318,8 @@ interface nsISyncMessageSender : nsIMessageSender [implicit_jscontext, optional_argc] jsval sendRpcMessage([optional] in AString messageName, [optional] in jsval obj, - [optional] in jsval objects); + [optional] in jsval objects, + [optional] in nsIPrincipal principal); }; [scriptable, builtinclass, uuid(894ff2d4-39a3-4df8-9d76-8ee329975488)] diff --git a/content/base/src/nsFrameLoader.cpp b/content/base/src/nsFrameLoader.cpp index c7b75c447c84..d0270f36ec03 100644 --- a/content/base/src/nsFrameLoader.cpp +++ b/content/base/src/nsFrameLoader.cpp @@ -2215,8 +2215,10 @@ public: nsFrameLoader* aFrameLoader, const nsAString& aMessage, const StructuredCloneData& aData, - JS::Handle aCpows) - : mRuntime(js::GetRuntime(aCx)), mFrameLoader(aFrameLoader), mMessage(aMessage), mCpows(aCpows) + JS::Handle aCpows, + nsIPrincipal* aPrincipal) + : mRuntime(js::GetRuntime(aCx)), mFrameLoader(aFrameLoader) + , mMessage(aMessage), mCpows(aCpows), mPrincipal(aPrincipal) { if (aData.mDataLength && !mData.copy(aData.mData, aData.mDataLength)) { NS_RUNTIMEABORT("OOM"); @@ -2249,7 +2251,7 @@ public: nsRefPtr mm = tabChild->GetInnerManager(); mm->ReceiveMessage(static_cast(tabChild), mMessage, - false, &data, &cpows, nullptr); + false, &data, &cpows, mPrincipal, nullptr); } return NS_OK; } @@ -2259,13 +2261,15 @@ public: JSAutoStructuredCloneBuffer mData; StructuredCloneClosure mClosure; JSObject* mCpows; + nsCOMPtr mPrincipal; }; bool nsFrameLoader::DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage, const StructuredCloneData& aData, - JS::Handle aCpows) + JS::Handle aCpows, + nsIPrincipal* aPrincipal) { TabParent* tabParent = mRemoteBrowser; if (tabParent) { @@ -2278,11 +2282,14 @@ nsFrameLoader::DoSendAsyncMessage(JSContext* aCx, if (aCpows && !cp->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) { return false; } - return tabParent->SendAsyncMessage(nsString(aMessage), data, cpows); + return tabParent->SendAsyncMessage(nsString(aMessage), data, cpows, + aPrincipal); } if (mChildMessageManager) { - nsRefPtr ev = new nsAsyncMessageToChild(aCx, this, aMessage, aData, aCpows); + nsRefPtr ev = new nsAsyncMessageToChild(aCx, this, aMessage, + aData, aCpows, + aPrincipal); NS_DispatchToCurrentThread(ev); return true; } diff --git a/content/base/src/nsFrameLoader.h b/content/base/src/nsFrameLoader.h index 55623c683782..91e2dcc48611 100644 --- a/content/base/src/nsFrameLoader.h +++ b/content/base/src/nsFrameLoader.h @@ -184,7 +184,8 @@ public: virtual bool DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage, const mozilla::dom::StructuredCloneData& aData, - JS::Handle aCpows); + JS::Handle aCpows, + nsIPrincipal* aPrincipal) MOZ_OVERRIDE; virtual bool CheckPermission(const nsAString& aPermission) MOZ_OVERRIDE; virtual bool CheckManifestURL(const nsAString& aManifestURL) MOZ_OVERRIDE; virtual bool CheckAppHasPermission(const nsAString& aPermission) MOZ_OVERRIDE; diff --git a/content/base/src/nsFrameMessageManager.cpp b/content/base/src/nsFrameMessageManager.cpp index a989affc923c..e038283aa215 100644 --- a/content/base/src/nsFrameMessageManager.cpp +++ b/content/base/src/nsFrameMessageManager.cpp @@ -500,28 +500,33 @@ NS_IMETHODIMP nsFrameMessageManager::SendSyncMessage(const nsAString& aMessageName, const JS::Value& aJSON, const JS::Value& aObjects, + nsIPrincipal* aPrincipal, JSContext* aCx, uint8_t aArgc, JS::Value* aRetval) { - return SendMessage(aMessageName, aJSON, aObjects, aCx, aArgc, aRetval, true); + return SendMessage(aMessageName, aJSON, aObjects, aPrincipal, aCx, aArgc, + aRetval, true); } NS_IMETHODIMP nsFrameMessageManager::SendRpcMessage(const nsAString& aMessageName, const JS::Value& aJSON, const JS::Value& aObjects, + nsIPrincipal* aPrincipal, JSContext* aCx, uint8_t aArgc, JS::Value* aRetval) { - return SendMessage(aMessageName, aJSON, aObjects, aCx, aArgc, aRetval, false); + return SendMessage(aMessageName, aJSON, aObjects, aPrincipal, aCx, aArgc, + aRetval, false); } nsresult nsFrameMessageManager::SendMessage(const nsAString& aMessageName, const JS::Value& aJSON, const JS::Value& aObjects, + nsIPrincipal* aPrincipal, JSContext* aCx, uint8_t aArgc, JS::Value* aRetval, @@ -556,7 +561,8 @@ nsFrameMessageManager::SendMessage(const nsAString& aMessageName, InfallibleTArray retval; sSendingSyncMessage |= aIsSync; - bool rv = mCallback->DoSendBlockingMessage(aCx, aMessageName, data, objects, &retval, aIsSync); + bool rv = mCallback->DoSendBlockingMessage(aCx, aMessageName, data, objects, + aPrincipal, &retval, aIsSync); if (aIsSync) { sSendingSyncMessage = false; } @@ -591,19 +597,20 @@ nsresult nsFrameMessageManager::DispatchAsyncMessageInternal(JSContext* aCx, const nsAString& aMessage, const StructuredCloneData& aData, - JS::Handle aCpows) + JS::Handle aCpows, + nsIPrincipal* aPrincipal) { if (mIsBroadcaster) { int32_t len = mChildManagers.Count(); for (int32_t i = 0; i < len; ++i) { static_cast(mChildManagers[i])-> - DispatchAsyncMessageInternal(aCx, aMessage, aData, aCpows); + DispatchAsyncMessageInternal(aCx, aMessage, aData, aCpows, aPrincipal); } return NS_OK; } NS_ENSURE_TRUE(mCallback, NS_ERROR_NOT_INITIALIZED); - if (!mCallback->DoSendAsyncMessage(aCx, aMessage, aData, aCpows)) { + if (!mCallback->DoSendAsyncMessage(aCx, aMessage, aData, aCpows, aPrincipal)) { return NS_ERROR_FAILURE; } return NS_OK; @@ -613,6 +620,7 @@ nsresult nsFrameMessageManager::DispatchAsyncMessage(const nsAString& aMessageName, const JS::Value& aJSON, const JS::Value& aObjects, + nsIPrincipal* aPrincipal, JSContext* aCx, uint8_t aArgc) { @@ -632,7 +640,8 @@ nsFrameMessageManager::DispatchAsyncMessage(const nsAString& aMessageName, data.mData = buffer.data(); data.mDataLength = buffer.nbytes(); - return DispatchAsyncMessageInternal(aCx, aMessageName, data, objects); + return DispatchAsyncMessageInternal(aCx, aMessageName, data, objects, + aPrincipal); } @@ -642,10 +651,12 @@ NS_IMETHODIMP nsFrameMessageManager::SendAsyncMessage(const nsAString& aMessageName, const JS::Value& aJSON, const JS::Value& aObjects, + nsIPrincipal* aPrincipal, JSContext* aCx, uint8_t aArgc) { - return DispatchAsyncMessage(aMessageName, aJSON, aObjects, aCx, aArgc); + return DispatchAsyncMessage(aMessageName, aJSON, aObjects, aPrincipal, aCx, + aArgc); } @@ -658,7 +669,8 @@ nsFrameMessageManager::BroadcastAsyncMessage(const nsAString& aMessageName, JSContext* aCx, uint8_t aArgc) { - return DispatchAsyncMessage(aMessageName, aJSON, aObjects, aCx, aArgc); + return DispatchAsyncMessage(aMessageName, aJSON, aObjects, nullptr, aCx, + aArgc); } NS_IMETHODIMP @@ -841,6 +853,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget, bool aIsSync, const StructuredCloneData* aCloneData, CpowHolder* aCpows, + nsIPrincipal* aPrincipal, InfallibleTArray* aJSONRetVal) { AutoSafeJSContext ctx; @@ -926,6 +939,42 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget, JS_DefineProperty(ctx, param, "data", json, nullptr, nullptr, JSPROP_ENUMERATE); JS_DefineProperty(ctx, param, "objects", cpowsv, nullptr, nullptr, JSPROP_ENUMERATE); + // message.principal == null + if (!aPrincipal) { + JS::Rooted nullValue(ctx); + JS_DefineProperty(ctx, param, "principal", nullValue, nullptr, nullptr, JSPROP_ENUMERATE); + } + + // message.principal = { appId: , origin: , isInBrowserElement: } + else { + JS::Rooted principalObj(ctx, + JS_NewObject(ctx, nullptr, nullptr, nullptr)); + + uint32_t appId; + nsresult rv = aPrincipal->GetAppId(&appId); + NS_ENSURE_SUCCESS(rv, rv); + + JS::Rooted appIdValue(ctx, INT_TO_JSVAL(appId)); + JS_DefineProperty(ctx, principalObj, "appId", appIdValue, nullptr, nullptr, JSPROP_ENUMERATE); + + nsCString origin; + rv = aPrincipal->GetOrigin(getter_Copies(origin)); + NS_ENSURE_SUCCESS(rv, rv); + + JS::Rooted originValue(ctx, JS_InternString(ctx, origin.get())); + JS_DefineProperty(ctx, principalObj, "origin", STRING_TO_JSVAL(originValue), nullptr, nullptr, JSPROP_ENUMERATE); + + bool browser; + rv = aPrincipal->GetIsInBrowserElement(&browser); + NS_ENSURE_SUCCESS(rv, rv); + + JS::Rooted browserValue(ctx, BOOLEAN_TO_JSVAL(browser)); + JS_DefineProperty(ctx, principalObj, "isInBrowserElement", browserValue, nullptr, nullptr, JSPROP_ENUMERATE); + + JS::RootedValue principalValue(ctx, JS::ObjectValue(*principalObj)); + JS_DefineProperty(ctx, param, "principal", principalValue, nullptr, nullptr, JSPROP_ENUMERATE); + } + JS::Rooted thisValue(ctx, JS::UndefinedValue()); JS::Rooted funval(ctx); @@ -981,7 +1030,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget, nsRefPtr kungfuDeathGrip = mParentManager; return mParentManager ? mParentManager->ReceiveMessage(aTarget, aMessage, aIsSync, aCloneData, - aCpows, + aCpows, aPrincipal, aJSONRetVal) : NS_OK; } @@ -1452,10 +1501,12 @@ public: nsAsyncMessageToSameProcessChild(JSContext* aCx, const nsAString& aMessage, const StructuredCloneData& aData, - JS::Handle aCpows) + JS::Handle aCpows, + nsIPrincipal* aPrincipal) : mRuntime(js::GetRuntime(aCx)), mMessage(aMessage), - mCpows(aCpows) + mCpows(aCpows), + mPrincipal(aPrincipal) { if (aData.mDataLength && !mData.copy(aData.mData, aData.mDataLength)) { NS_RUNTIMEABORT("OOM"); @@ -1485,7 +1536,7 @@ public: nsRefPtr ppm = nsFrameMessageManager::sChildProcessManager; ppm->ReceiveMessage(static_cast(ppm.get()), mMessage, - false, &data, &cpows, nullptr); + false, &data, &cpows, mPrincipal, nullptr); } return NS_OK; } @@ -1494,6 +1545,7 @@ public: JSAutoStructuredCloneBuffer mData; StructuredCloneClosure mClosure; JSObject* mCpows; + nsCOMPtr mPrincipal; }; @@ -1515,10 +1567,12 @@ public: virtual bool DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage, const StructuredCloneData& aData, - JS::Handle aCpows) + JS::Handle aCpows, + nsIPrincipal* aPrincipal) { nsRefPtr ev = - new nsAsyncMessageToSameProcessChild(aCx, aMessage, aData, aCpows); + new nsAsyncMessageToSameProcessChild(aCx, aMessage, aData, aCpows, + aPrincipal); NS_DispatchToCurrentThread(ev); return true; } @@ -1562,6 +1616,7 @@ public: const nsAString& aMessage, const mozilla::dom::StructuredCloneData& aData, JS::Handle aCpows, + nsIPrincipal* aPrincipal, InfallibleTArray* aJSONRetVal, bool aIsSync) MOZ_OVERRIDE { @@ -1579,15 +1634,18 @@ public: return false; } if (aIsSync) { - return cc->SendSyncMessage(nsString(aMessage), data, cpows, aJSONRetVal); + return cc->SendSyncMessage(nsString(aMessage), data, cpows, aPrincipal, + aJSONRetVal); } - return cc->CallRpcMessage(nsString(aMessage), data, cpows, aJSONRetVal); + return cc->CallRpcMessage(nsString(aMessage), data, cpows, aPrincipal, + aJSONRetVal); } virtual bool DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage, const mozilla::dom::StructuredCloneData& aData, - JS::Handle aCpows) MOZ_OVERRIDE + JS::Handle aCpows, + nsIPrincipal* aPrincipal) MOZ_OVERRIDE { mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton(); @@ -1602,7 +1660,7 @@ public: if (!cc->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) { return false; } - return cc->SendAsyncMessage(nsString(aMessage), data, cpows); + return cc->SendAsyncMessage(nsString(aMessage), data, cpows, aPrincipal); } }; @@ -1614,10 +1672,12 @@ public: nsAsyncMessageToSameProcessParent(JSContext* aCx, const nsAString& aMessage, const StructuredCloneData& aData, - JS::Handle aCpows) + JS::Handle aCpows, + nsIPrincipal* aPrincipal) : mRuntime(js::GetRuntime(aCx)), mMessage(aMessage), - mCpows(aCpows) + mCpows(aCpows), + mPrincipal(aPrincipal) { if (aData.mDataLength && !mData.copy(aData.mData, aData.mDataLength)) { NS_RUNTIMEABORT("OOM"); @@ -1651,7 +1711,7 @@ public: nsRefPtr ppm = nsFrameMessageManager::sSameProcessParentManager; ppm->ReceiveMessage(static_cast(ppm.get()), - mMessage, false, &data, &cpows, nullptr); + mMessage, false, &data, &cpows, mPrincipal, nullptr); } return NS_OK; } @@ -1660,6 +1720,7 @@ public: JSAutoStructuredCloneBuffer mData; StructuredCloneClosure mClosure; JSObject* mCpows; + nsCOMPtr mPrincipal; }; /** @@ -1681,6 +1742,7 @@ public: const nsAString& aMessage, const mozilla::dom::StructuredCloneData& aData, JS::Handle aCpows, + nsIPrincipal* aPrincipal, InfallibleTArray* aJSONRetVal, bool aIsSync) MOZ_OVERRIDE { @@ -1697,7 +1759,7 @@ public: SameProcessCpowHolder cpows(js::GetRuntime(aCx), aCpows); nsRefPtr ppm = nsFrameMessageManager::sSameProcessParentManager; ppm->ReceiveMessage(static_cast(ppm.get()), aMessage, - true, &aData, &cpows, aJSONRetVal); + true, &aData, &cpows, aPrincipal, aJSONRetVal); } return true; } @@ -1705,13 +1767,14 @@ public: virtual bool DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage, const mozilla::dom::StructuredCloneData& aData, - JS::Handle aCpows) + JS::Handle aCpows, + nsIPrincipal* aPrincipal) { if (!nsFrameMessageManager::sPendingSameProcessAsyncMessages) { nsFrameMessageManager::sPendingSameProcessAsyncMessages = new nsTArray >; } nsCOMPtr ev = - new nsAsyncMessageToSameProcessParent(aCx, aMessage, aData, aCpows); + new nsAsyncMessageToSameProcessParent(aCx, aMessage, aData, aCpows, aPrincipal); nsFrameMessageManager::sPendingSameProcessAsyncMessages->AppendElement(ev); NS_DispatchToCurrentThread(ev); return true; diff --git a/content/base/src/nsFrameMessageManager.h b/content/base/src/nsFrameMessageManager.h index f3e710743c9f..b18dc838e18c 100644 --- a/content/base/src/nsFrameMessageManager.h +++ b/content/base/src/nsFrameMessageManager.h @@ -61,6 +61,7 @@ public: const nsAString& aMessage, const mozilla::dom::StructuredCloneData& aData, JS::Handle aCpows, + nsIPrincipal* aPrincipal, InfallibleTArray* aJSONRetVal, bool aIsSync) { @@ -70,7 +71,8 @@ public: virtual bool DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage, const mozilla::dom::StructuredCloneData& aData, - JS::Handle aCpows) + JS::Handle aCpows, + nsIPrincipal* aPrincipal) { return true; } @@ -218,7 +220,7 @@ public: nsresult ReceiveMessage(nsISupports* aTarget, const nsAString& aMessage, bool aIsSync, const StructuredCloneData* aCloneData, - CpowHolder* aCpows, + CpowHolder* aCpows, nsIPrincipal* aPrincipal, InfallibleTArray* aJSONRetVal); void AddChildManager(nsFrameMessageManager* aManager, @@ -239,12 +241,14 @@ public: nsresult DispatchAsyncMessage(const nsAString& aMessageName, const JS::Value& aJSON, const JS::Value& aObjects, + nsIPrincipal* aPrincipal, JSContext* aCx, uint8_t aArgc); nsresult DispatchAsyncMessageInternal(JSContext* aCx, const nsAString& aMessage, const StructuredCloneData& aData, - JS::Handle aCpows); + JS::Handle aCpows, + nsIPrincipal* aPrincipal); void RemoveFromParent(); nsFrameMessageManager* GetParentManager() { return mParentManager; } void SetParentManager(nsFrameMessageManager* aParent) @@ -268,6 +272,7 @@ private: nsresult SendMessage(const nsAString& aMessageName, const JS::Value& aJSON, const JS::Value& aObjects, + nsIPrincipal* aPrincipal, JSContext* aCx, uint8_t aArgc, JS::Value* aRetval, diff --git a/content/base/src/nsInProcessTabChildGlobal.cpp b/content/base/src/nsInProcessTabChildGlobal.cpp index 051c739c481c..f6e89831f1c4 100644 --- a/content/base/src/nsInProcessTabChildGlobal.cpp +++ b/content/base/src/nsInProcessTabChildGlobal.cpp @@ -30,6 +30,7 @@ nsInProcessTabChildGlobal::DoSendBlockingMessage(JSContext* aCx, const nsAString& aMessage, const mozilla::dom::StructuredCloneData& aData, JS::Handle aCpows, + nsIPrincipal* aPrincipal, InfallibleTArray* aJSONRetVal, bool aIsSync) { @@ -43,7 +44,8 @@ nsInProcessTabChildGlobal::DoSendBlockingMessage(JSContext* aCx, if (mChromeMessageManager) { SameProcessCpowHolder cpows(js::GetRuntime(aCx), aCpows); nsRefPtr mm = mChromeMessageManager; - mm->ReceiveMessage(mOwner, aMessage, true, &aData, &cpows, aJSONRetVal); + mm->ReceiveMessage(mOwner, aMessage, true, &aData, &cpows, aPrincipal, + aJSONRetVal); } return true; } @@ -55,11 +57,13 @@ public: nsInProcessTabChildGlobal* aTabChild, const nsAString& aMessage, const StructuredCloneData& aData, - JS::Handle aCpows) + JS::Handle aCpows, + nsIPrincipal* aPrincipal) : mRuntime(js::GetRuntime(aCx)), mTabChild(aTabChild), mMessage(aMessage), mCpows(aCpows), + mPrincipal(aPrincipal), mRun(false) { if (aData.mDataLength && !mData.copy(aData.mData, aData.mDataLength)) { @@ -95,7 +99,8 @@ public: SameProcessCpowHolder cpows(mRuntime, JS::Handle::fromMarkedLocation(&mCpows)); nsRefPtr mm = mTabChild->mChromeMessageManager; - mm->ReceiveMessage(mTabChild->mOwner, mMessage, false, &data, &cpows, nullptr); + mm->ReceiveMessage(mTabChild->mOwner, mMessage, false, &data, &cpows, + mPrincipal, nullptr); } return NS_OK; } @@ -105,6 +110,7 @@ public: JSAutoStructuredCloneBuffer mData; StructuredCloneClosure mClosure; JSObject* mCpows; + nsCOMPtr mPrincipal; // True if this runnable has already been called. This can happen if DoSendSyncMessage // is called while waiting for an asynchronous message send. bool mRun; @@ -114,10 +120,11 @@ bool nsInProcessTabChildGlobal::DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage, const StructuredCloneData& aData, - JS::Handle aCpows) + JS::Handle aCpows, + nsIPrincipal* aPrincipal) { nsCOMPtr ev = - new nsAsyncMessageToParent(aCx, this, aMessage, aData, aCpows); + new nsAsyncMessageToParent(aCx, this, aMessage, aData, aCpows, aPrincipal); mASyncMessages.AppendElement(ev); NS_DispatchToCurrentThread(ev); return true; diff --git a/content/base/src/nsInProcessTabChildGlobal.h b/content/base/src/nsInProcessTabChildGlobal.h index 07ace7d8c08d..fedfe89b66aa 100644 --- a/content/base/src/nsInProcessTabChildGlobal.h +++ b/content/base/src/nsInProcessTabChildGlobal.h @@ -43,23 +43,27 @@ public: NS_IMETHOD SendSyncMessage(const nsAString& aMessageName, const JS::Value& aObject, const JS::Value& aRemote, + nsIPrincipal* aPrincipal, JSContext* aCx, uint8_t aArgc, JS::Value* aRetval) { return mMessageManager - ? mMessageManager->SendSyncMessage(aMessageName, aObject, aRemote, aCx, aArgc, aRetval) + ? mMessageManager->SendSyncMessage(aMessageName, aObject, aRemote, + aPrincipal, aCx, aArgc, aRetval) : NS_ERROR_NULL_POINTER; } NS_IMETHOD SendRpcMessage(const nsAString& aMessageName, const JS::Value& aObject, const JS::Value& aRemote, + nsIPrincipal* aPrincipal, JSContext* aCx, uint8_t aArgc, JS::Value* aRetval) { return mMessageManager - ? mMessageManager->SendRpcMessage(aMessageName, aObject, aRemote, aCx, aArgc, aRetval) + ? mMessageManager->SendRpcMessage(aMessageName, aObject, aRemote, + aPrincipal, aCx, aArgc, aRetval) : NS_ERROR_NULL_POINTER; } NS_IMETHOD GetContent(nsIDOMWindow** aContent) MOZ_OVERRIDE; @@ -83,12 +87,14 @@ public: const nsAString& aMessage, const mozilla::dom::StructuredCloneData& aData, JS::Handle aCpows, + nsIPrincipal* aPrincipal, InfallibleTArray* aJSONRetVal, bool aIsSync) MOZ_OVERRIDE; virtual bool DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage, const mozilla::dom::StructuredCloneData& aData, - JS::Handle aCpows); + JS::Handle aCpows, + nsIPrincipal* aPrincipal) MOZ_OVERRIDE; virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor) MOZ_OVERRIDE; NS_IMETHOD AddEventListener(const nsAString& aType, diff --git a/content/base/test/chrome.ini b/content/base/test/chrome.ini index 0a1f2e864359..4432f014e9a7 100644 --- a/content/base/test/chrome.ini +++ b/content/base/test/chrome.ini @@ -2,3 +2,4 @@ [test_bug357450.js] [test_copypaste.xul] +[test_messagemanager_principal.html] diff --git a/content/base/test/test_messagemanager_principal.html b/content/base/test/test_messagemanager_principal.html new file mode 100644 index 000000000000..768c10d45150 --- /dev/null +++ b/content/base/test/test_messagemanager_principal.html @@ -0,0 +1,94 @@ + + + + Test for Principal in MessageManager + + + + + + + + diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index 26b54a6078a4..59f27358a8a2 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -72,6 +72,8 @@ #include "nsPermissionManager.h" #endif +#include "PermissionMessageUtils.h" + #if defined(MOZ_WIDGET_ANDROID) #include "APKOpen.h" #endif @@ -1172,14 +1174,15 @@ ContentChild::RecvNotifyVisited(const URIParams& aURI) bool ContentChild::RecvAsyncMessage(const nsString& aMsg, const ClonedMessageData& aData, - const InfallibleTArray& aCpows) + const InfallibleTArray& aCpows, + const IPC::Principal& aPrincipal) { nsRefPtr cpm = nsFrameMessageManager::sChildProcessManager; if (cpm) { StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForChild(aData); CpowIdHolder cpows(GetCPOWManager(), aCpows); cpm->ReceiveMessage(static_cast(cpm.get()), - aMsg, false, &cloneData, &cpows, nullptr); + aMsg, false, &cloneData, &cpows, aPrincipal, nullptr); } return true; } diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index 71e703a02e71..7303b077f841 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -188,7 +188,8 @@ public: virtual bool RecvAsyncMessage(const nsString& aMsg, const ClonedMessageData& aData, - const InfallibleTArray& aCpows); + const InfallibleTArray& aCpows, + const IPC::Principal& aPrincipal); virtual bool RecvGeolocationUpdate(const GeoPosition& somewhere); diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index c2a2366dd09f..8f367df9d4ff 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -1139,7 +1139,7 @@ ContentParent::ActorDestroy(ActorDestroyReason why) if (ppm) { ppm->ReceiveMessage(static_cast(ppm.get()), CHILD_PROCESS_SHUTDOWN_MESSAGE, false, - nullptr, nullptr, nullptr); + nullptr, nullptr, nullptr, nullptr); } nsCOMPtr kungFuDeathGrip(static_cast(this)); @@ -2865,14 +2865,16 @@ bool ContentParent::RecvSyncMessage(const nsString& aMsg, const ClonedMessageData& aData, const InfallibleTArray& aCpows, + const IPC::Principal& aPrincipal, InfallibleTArray* aRetvals) { nsRefPtr ppm = mMessageManager; if (ppm) { StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData); CpowIdHolder cpows(GetCPOWManager(), aCpows); + ppm->ReceiveMessage(static_cast(ppm.get()), - aMsg, true, &cloneData, &cpows, aRetvals); + aMsg, true, &cloneData, &cpows, aPrincipal, aRetvals); } return true; } @@ -2881,6 +2883,7 @@ bool ContentParent::AnswerRpcMessage(const nsString& aMsg, const ClonedMessageData& aData, const InfallibleTArray& aCpows, + const IPC::Principal& aPrincipal, InfallibleTArray* aRetvals) { nsRefPtr ppm = mMessageManager; @@ -2888,7 +2891,7 @@ ContentParent::AnswerRpcMessage(const nsString& aMsg, StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData); CpowIdHolder cpows(GetCPOWManager(), aCpows); ppm->ReceiveMessage(static_cast(ppm.get()), - aMsg, true, &cloneData, &cpows, aRetvals); + aMsg, true, &cloneData, &cpows, aPrincipal, aRetvals); } return true; } @@ -2896,14 +2899,15 @@ ContentParent::AnswerRpcMessage(const nsString& aMsg, bool ContentParent::RecvAsyncMessage(const nsString& aMsg, const ClonedMessageData& aData, - const InfallibleTArray& aCpows) + const InfallibleTArray& aCpows, + const IPC::Principal& aPrincipal) { nsRefPtr ppm = mMessageManager; if (ppm) { StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData); CpowIdHolder cpows(GetCPOWManager(), aCpows); ppm->ReceiveMessage(static_cast(ppm.get()), - aMsg, false, &cloneData, &cpows, nullptr); + aMsg, false, &cloneData, &cpows, aPrincipal, nullptr); } return true; } @@ -3110,7 +3114,8 @@ bool ContentParent::DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage, const mozilla::dom::StructuredCloneData& aData, - JS::Handle aCpows) + JS::Handle aCpows, + nsIPrincipal* aPrincipal) { ClonedMessageData data; if (!BuildClonedMessageDataForParent(this, aData, data)) { @@ -3120,7 +3125,7 @@ ContentParent::DoSendAsyncMessage(JSContext* aCx, if (!GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) { return false; } - return SendAsyncMessage(nsString(aMessage), data, cpows); + return SendAsyncMessage(nsString(aMessage), data, cpows, aPrincipal); } bool diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index cb2ca2751c32..54ecbcdb910f 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -117,7 +117,8 @@ public: virtual bool DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage, const mozilla::dom::StructuredCloneData& aData, - JS::Handle aCpows) MOZ_OVERRIDE; + JS::Handle aCpows, + nsIPrincipal* aPrincipal) MOZ_OVERRIDE; virtual bool CheckPermission(const nsAString& aPermission) MOZ_OVERRIDE; virtual bool CheckManifestURL(const nsAString& aManifestURL) MOZ_OVERRIDE; virtual bool CheckAppHasPermission(const nsAString& aPermission) MOZ_OVERRIDE; @@ -420,14 +421,17 @@ private: virtual bool RecvSyncMessage(const nsString& aMsg, const ClonedMessageData& aData, const InfallibleTArray& aCpows, + const IPC::Principal& aPrincipal, InfallibleTArray* aRetvals); virtual bool AnswerRpcMessage(const nsString& aMsg, const ClonedMessageData& aData, const InfallibleTArray& aCpows, + const IPC::Principal& aPrincipal, InfallibleTArray* aRetvals); virtual bool RecvAsyncMessage(const nsString& aMsg, const ClonedMessageData& aData, - const InfallibleTArray& aCpows); + const InfallibleTArray& aCpows, + const IPC::Principal& aPrincipal); virtual bool RecvFilePathUpdateNotify(const nsString& aType, const nsString& aStorageName, diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl index ea39cb6b26d0..8dcc684c630e 100644 --- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -61,7 +61,8 @@ intr protocol PBrowser manages PIndexedDB; both: - AsyncMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows); + AsyncMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows, + Principal aPrincipal); parent: /** @@ -74,10 +75,12 @@ parent: intr CreateWindow() returns (PBrowser window); - sync SyncMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows) + sync SyncMessage(nsString aMessage, ClonedMessageData aData, + CpowEntry[] aCpows, Principal aPrincipal) returns (nsString[] retval); - rpc RpcMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows) + rpc RpcMessage(nsString aMessage, ClonedMessageData aData, + CpowEntry[] aCpows, Principal aPrincipal) returns (nsString[] retval); /** diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index 59c9184ce967..445b14decf8c 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -375,10 +375,12 @@ parent: sync ReadFontList() returns (FontListEntry[] retValue); - sync SyncMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows) + sync SyncMessage(nsString aMessage, ClonedMessageData aData, + CpowEntry[] aCpows, Principal aPrincipal) returns (nsString[] retval); - rpc RpcMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows) + rpc RpcMessage(nsString aMessage, ClonedMessageData aData, + CpowEntry[] aCpows, Principal aPrincipal) returns (nsString[] retval); ShowAlertNotification(nsString imageUrl, @@ -469,7 +471,8 @@ parent: returns (OptionalInputStreamParams postData, OptionalURIParams uri); both: - AsyncMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows); + AsyncMessage(nsString aMessage, ClonedMessageData aData, + CpowEntry[] aCpows, Principal aPrincipal); }; } diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index f5fa0cbcd5fb..d4cb34d1a610 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -62,6 +62,7 @@ #include "nsPrintfCString.h" #include "nsThreadUtils.h" #include "nsWeakReference.h" +#include "PermissionMessageUtils.h" #include "PCOMContentPermissionRequestChild.h" #include "PuppetWidget.h" #include "StructuredCloneUtils.h" @@ -1506,7 +1507,7 @@ TabChild::DispatchMessageManagerMessage(const nsAString& aMessageName, nsRefPtr mm = static_cast(mTabChildGlobal->mMessageManager.get()); mm->ReceiveMessage(static_cast(mTabChildGlobal), - aMessageName, false, &cloneData, nullptr, nullptr); + aMessageName, false, &cloneData, nullptr, nullptr, nullptr); } bool @@ -2071,7 +2072,8 @@ TabChild::RecvLoadRemoteScript(const nsString& aURL) bool TabChild::RecvAsyncMessage(const nsString& aMessage, const ClonedMessageData& aData, - const InfallibleTArray& aCpows) + const InfallibleTArray& aCpows, + const IPC::Principal& aPrincipal) { if (mTabChildGlobal) { nsCOMPtr kungFuDeathGrip(GetGlobal()); @@ -2080,7 +2082,7 @@ TabChild::RecvAsyncMessage(const nsString& aMessage, static_cast(mTabChildGlobal->mMessageManager.get()); CpowIdHolder cpows(static_cast(Manager())->GetCPOWManager(), aCpows); mm->ReceiveMessage(static_cast(mTabChildGlobal), - aMessage, false, &cloneData, &cpows, nullptr); + aMessage, false, &cloneData, &cpows, aPrincipal, nullptr); } return true; } @@ -2404,6 +2406,7 @@ TabChild::DoSendBlockingMessage(JSContext* aCx, const nsAString& aMessage, const StructuredCloneData& aData, JS::Handle aCpows, + nsIPrincipal* aPrincipal, InfallibleTArray* aJSONRetVal, bool aIsSync) { @@ -2418,16 +2421,21 @@ TabChild::DoSendBlockingMessage(JSContext* aCx, return false; } } - if (aIsSync) - return SendSyncMessage(nsString(aMessage), data, cpows, aJSONRetVal); - return CallRpcMessage(nsString(aMessage), data, cpows, aJSONRetVal); + if (aIsSync) { + return SendSyncMessage(nsString(aMessage), data, cpows, aPrincipal, + aJSONRetVal); + } + + return CallRpcMessage(nsString(aMessage), data, cpows, aPrincipal, + aJSONRetVal); } bool TabChild::DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage, const StructuredCloneData& aData, - JS::Handle aCpows) + JS::Handle aCpows, + nsIPrincipal* aPrincipal) { ContentChild* cc = Manager(); ClonedMessageData data; @@ -2440,7 +2448,8 @@ TabChild::DoSendAsyncMessage(JSContext* aCx, return false; } } - return SendAsyncMessage(nsString(aMessage), data, cpows); + return SendAsyncMessage(nsString(aMessage), data, cpows, + aPrincipal); } TabChild* diff --git a/dom/ipc/TabChild.h b/dom/ipc/TabChild.h index 095ec72784aa..0c7859409682 100644 --- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -63,23 +63,27 @@ public: NS_IMETHOD SendSyncMessage(const nsAString& aMessageName, const JS::Value& aObject, const JS::Value& aRemote, + nsIPrincipal* aPrincipal, JSContext* aCx, uint8_t aArgc, JS::Value* aRetval) { return mMessageManager - ? mMessageManager->SendSyncMessage(aMessageName, aObject, aRemote, aCx, aArgc, aRetval) + ? mMessageManager->SendSyncMessage(aMessageName, aObject, aRemote, + aPrincipal, aCx, aArgc, aRetval) : NS_ERROR_NULL_POINTER; } NS_IMETHOD SendRpcMessage(const nsAString& aMessageName, const JS::Value& aObject, const JS::Value& aRemote, + nsIPrincipal* aPrincipal, JSContext* aCx, uint8_t aArgc, JS::Value* aRetval) { return mMessageManager - ? mMessageManager->SendRpcMessage(aMessageName, aObject, aRemote, aCx, aArgc, aRetval) + ? mMessageManager->SendRpcMessage(aMessageName, aObject, aRemote, + aPrincipal, aCx, aArgc, aRetval) : NS_ERROR_NULL_POINTER; } NS_IMETHOD GetContent(nsIDOMWindow** aContent) MOZ_OVERRIDE; @@ -194,12 +198,14 @@ public: const nsAString& aMessage, const mozilla::dom::StructuredCloneData& aData, JS::Handle aCpows, + nsIPrincipal* aPrincipal, InfallibleTArray* aJSONRetVal, bool aIsSync) MOZ_OVERRIDE; virtual bool DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage, const mozilla::dom::StructuredCloneData& aData, - JS::Handle aCpows) MOZ_OVERRIDE; + JS::Handle aCpows, + nsIPrincipal* aPrincipal) MOZ_OVERRIDE; virtual bool RecvLoadURL(const nsCString& uri); virtual bool RecvCacheFileDescriptor(const nsString& aPath, @@ -237,7 +243,8 @@ public: virtual bool RecvLoadRemoteScript(const nsString& aURL); virtual bool RecvAsyncMessage(const nsString& aMessage, const ClonedMessageData& aData, - const InfallibleTArray& aCpows); + const InfallibleTArray& aCpows, + const IPC::Principal& aPrincipal) MOZ_OVERRIDE; virtual PDocumentRendererChild* AllocPDocumentRendererChild(const nsRect& documentRect, const gfxMatrix& transform, diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index 863445a92ddc..f43fcc37927c 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -52,6 +52,7 @@ #include "nsServiceManagerUtils.h" #include "nsThreadUtils.h" #include "private/pprio.h" +#include "PermissionMessageUtils.h" #include "StructuredCloneUtils.h" #include "JavaScriptParent.h" #include "TabChild.h" @@ -299,7 +300,8 @@ TabParent::ActorDestroy(ActorDestroyReason why) if (frameLoader) { fmm = frameLoader->GetFrameMessageManager(); nsCOMPtr frameElement(mFrameElement); - ReceiveMessage(CHILD_PROCESS_SHUTDOWN_MESSAGE, false, nullptr, nullptr); + ReceiveMessage(CHILD_PROCESS_SHUTDOWN_MESSAGE, false, nullptr, nullptr, + nullptr); frameLoader->DestroyChild(); if (why == AbnormalShutdown && os) { @@ -765,32 +767,35 @@ bool TabParent::RecvSyncMessage(const nsString& aMessage, const ClonedMessageData& aData, const InfallibleTArray& aCpows, + const IPC::Principal& aPrincipal, InfallibleTArray* aJSONRetVal) { StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData); CpowIdHolder cpows(static_cast(Manager())->GetCPOWManager(), aCpows); - return ReceiveMessage(aMessage, true, &cloneData, &cpows, aJSONRetVal); + return ReceiveMessage(aMessage, true, &cloneData, &cpows, aPrincipal, aJSONRetVal); } bool TabParent::AnswerRpcMessage(const nsString& aMessage, const ClonedMessageData& aData, const InfallibleTArray& aCpows, + const IPC::Principal& aPrincipal, InfallibleTArray* aJSONRetVal) { StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData); CpowIdHolder cpows(static_cast(Manager())->GetCPOWManager(), aCpows); - return ReceiveMessage(aMessage, true, &cloneData, &cpows, aJSONRetVal); + return ReceiveMessage(aMessage, true, &cloneData, &cpows, aPrincipal, aJSONRetVal); } bool TabParent::RecvAsyncMessage(const nsString& aMessage, const ClonedMessageData& aData, - const InfallibleTArray& aCpows) + const InfallibleTArray& aCpows, + const IPC::Principal& aPrincipal) { StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData); CpowIdHolder cpows(static_cast(Manager())->GetCPOWManager(), aCpows); - return ReceiveMessage(aMessage, false, &cloneData, &cpows, nullptr); + return ReceiveMessage(aMessage, false, &cloneData, &cpows, aPrincipal, nullptr); } bool @@ -1214,6 +1219,7 @@ TabParent::ReceiveMessage(const nsString& aMessage, bool aSync, const StructuredCloneData* aCloneData, CpowHolder* aCpows, + nsIPrincipal* aPrincipal, InfallibleTArray* aJSONRetVal) { nsRefPtr frameLoader = GetFrameLoader(); @@ -1226,6 +1232,7 @@ TabParent::ReceiveMessage(const nsString& aMessage, aSync, aCloneData, aCpows, + aPrincipal, aJSONRetVal); } return true; diff --git a/dom/ipc/TabParent.h b/dom/ipc/TabParent.h index bfbc9644ebc8..a7c565cbc2b9 100644 --- a/dom/ipc/TabParent.h +++ b/dom/ipc/TabParent.h @@ -23,6 +23,7 @@ struct gfxMatrix; class nsFrameLoader; class nsIContent; +class nsIPrincipal; class nsIURI; class nsIWidget; class CpowHolder; @@ -121,14 +122,17 @@ public: virtual bool RecvSyncMessage(const nsString& aMessage, const ClonedMessageData& aData, const InfallibleTArray& aCpows, + const IPC::Principal& aPrincipal, InfallibleTArray* aJSONRetVal); virtual bool AnswerRpcMessage(const nsString& aMessage, const ClonedMessageData& aData, const InfallibleTArray& aCpows, + const IPC::Principal& aPrincipal, InfallibleTArray* aJSONRetVal); virtual bool RecvAsyncMessage(const nsString& aMessage, const ClonedMessageData& aData, - const InfallibleTArray& aCpows); + const InfallibleTArray& aCpows, + const IPC::Principal& aPrincipal); virtual bool RecvNotifyIMEFocus(const bool& aFocus, nsIMEUpdatePreference* aPreference, uint32_t* aSeqno); @@ -254,6 +258,7 @@ protected: bool aSync, const StructuredCloneData* aCloneData, CpowHolder* aCpows, + nsIPrincipal* aPrincipal, InfallibleTArray* aJSONRetVal = nullptr); virtual bool Recv__delete__() MOZ_OVERRIDE; From 8abae6153f82eefbf0354ea94ea8466a0851b35d Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Wed, 6 Nov 2013 17:21:17 +0000 Subject: [PATCH 05/82] Bug 916091 - patch 2 - nsIMessageSender should check if the principal is valid., r=smaug --- dom/ipc/ContentParent.cpp | 15 +++++++++++++++ dom/ipc/TabParent.cpp | 25 ++++++++++++++++++++++--- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 8f367df9d4ff..02dd24914367 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -2868,6 +2868,11 @@ ContentParent::RecvSyncMessage(const nsString& aMsg, const IPC::Principal& aPrincipal, InfallibleTArray* aRetvals) { + nsIPrincipal* principal = aPrincipal; + if (principal && !AssertAppPrincipal(this, principal)) { + return false; + } + nsRefPtr ppm = mMessageManager; if (ppm) { StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData); @@ -2886,6 +2891,11 @@ ContentParent::AnswerRpcMessage(const nsString& aMsg, const IPC::Principal& aPrincipal, InfallibleTArray* aRetvals) { + nsIPrincipal* principal = aPrincipal; + if (principal && !AssertAppPrincipal(this, principal)) { + return false; + } + nsRefPtr ppm = mMessageManager; if (ppm) { StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData); @@ -2902,6 +2912,11 @@ ContentParent::RecvAsyncMessage(const nsString& aMsg, const InfallibleTArray& aCpows, const IPC::Principal& aPrincipal) { + nsIPrincipal* principal = aPrincipal; + if (principal && !AssertAppPrincipal(this, principal)) { + return false; + } + nsRefPtr ppm = mMessageManager; if (ppm) { StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData); diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index f43fcc37927c..ec3ba977a8d2 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -8,6 +8,7 @@ #include "TabParent.h" +#include "AppProcessChecker.h" #include "IDBFactory.h" #include "IndexedDBParent.h" #include "mozIApplication.h" @@ -770,8 +771,14 @@ TabParent::RecvSyncMessage(const nsString& aMessage, const IPC::Principal& aPrincipal, InfallibleTArray* aJSONRetVal) { + nsIPrincipal* principal = aPrincipal; + ContentParent* parent = static_cast(Manager()); + if (principal && !AssertAppPrincipal(parent, principal)) { + return false; + } + StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData); - CpowIdHolder cpows(static_cast(Manager())->GetCPOWManager(), aCpows); + CpowIdHolder cpows(parent->GetCPOWManager(), aCpows); return ReceiveMessage(aMessage, true, &cloneData, &cpows, aPrincipal, aJSONRetVal); } @@ -782,8 +789,14 @@ TabParent::AnswerRpcMessage(const nsString& aMessage, const IPC::Principal& aPrincipal, InfallibleTArray* aJSONRetVal) { + nsIPrincipal* principal = aPrincipal; + ContentParent* parent = static_cast(Manager()); + if (principal && !AssertAppPrincipal(parent, principal)) { + return false; + } + StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData); - CpowIdHolder cpows(static_cast(Manager())->GetCPOWManager(), aCpows); + CpowIdHolder cpows(parent->GetCPOWManager(), aCpows); return ReceiveMessage(aMessage, true, &cloneData, &cpows, aPrincipal, aJSONRetVal); } @@ -793,8 +806,14 @@ TabParent::RecvAsyncMessage(const nsString& aMessage, const InfallibleTArray& aCpows, const IPC::Principal& aPrincipal) { + nsIPrincipal* principal = aPrincipal; + ContentParent* parent = static_cast(Manager()); + if (principal && !AssertAppPrincipal(parent, principal)) { + return false; + } + StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData); - CpowIdHolder cpows(static_cast(Manager())->GetCPOWManager(), aCpows); + CpowIdHolder cpows(parent->GetCPOWManager(), aCpows); return ReceiveMessage(aMessage, false, &cloneData, &cpows, aPrincipal, nullptr); } From efcf3b13895c26fbd620233c87c81f7f1d570f44 Mon Sep 17 00:00:00 2001 From: Eitan Isaacson Date: Wed, 6 Nov 2013 09:43:53 -0800 Subject: [PATCH 06/82] Bug 924983 - Introduce context actions. r=yzen --- accessible/src/jsat/AccessFu.jsm | 12 ++++++++++++ accessible/src/jsat/content-script.js | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/accessible/src/jsat/AccessFu.jsm b/accessible/src/jsat/AccessFu.jsm index c07f4597d673..43cacb5f7fbc 100644 --- a/accessible/src/jsat/AccessFu.jsm +++ b/accessible/src/jsat/AccessFu.jsm @@ -735,6 +735,12 @@ var Input = { case 'swipeleft1': this.moveCursor('movePrevious', 'Simple', 'gesture'); break; + case 'swipeup1': + this.contextAction('backward'); + break; + case 'swipedown1': + this.contextAction('forward'); + break; case 'exploreend1': this.activateCurrent(null, true); break; @@ -859,6 +865,12 @@ var Input = { origin: 'top', inputType: aInputType}); }, + contextAction: function contextAction(aDirection) { + // XXX: For now, the only supported context action is adjusting a range. + let mm = Utils.getMessageManager(Utils.CurrentBrowser); + mm.sendAsyncMessage('AccessFu:AdjustRange', {direction: aDirection}); + }, + moveByGranularity: function moveByGranularity(aDetails) { const MOVEMENT_GRANULARITY_PARAGRAPH = 8; diff --git a/accessible/src/jsat/content-script.js b/accessible/src/jsat/content-script.js index 1b1075d233fa..69101a78b84f 100644 --- a/accessible/src/jsat/content-script.js +++ b/accessible/src/jsat/content-script.js @@ -331,6 +331,23 @@ function scroll(aMessage) { } } +function adjustRange(aMessage) { + function sendUpDownKey(aAccessible) { + let evt = content.document.createEvent('KeyboardEvent'); + let keycode = aMessage.json.direction == 'forward' ? + content.KeyEvent.DOM_VK_DOWN : content.KeyEvent.DOM_VK_UP; + evt.initKeyEvent( + "keypress", false, true, null, false, false, false, false, keycode, 0); + if (aAccessible.DOMNode) { + aAccessible.DOMNode.dispatchEvent(evt); + } + } + + let position = Utils.getVirtualCursor(content.document).position; + if (!forwardToChild(aMessage, adjustRange, position)) { + sendUpDownKey(position); + } +} addMessageListener( 'AccessFu:Start', function(m) { @@ -344,6 +361,7 @@ addMessageListener( addMessageListener('AccessFu:Activate', activateCurrent); addMessageListener('AccessFu:ContextMenu', activateContextMenu); addMessageListener('AccessFu:Scroll', scroll); + addMessageListener('AccessFu:AdjustRange', adjustRange); addMessageListener('AccessFu:MoveCaret', moveCaret); addMessageListener('AccessFu:MoveByGranularity', moveByGranularity); From 98c132e989434366a23ca1e44b65d26373281003 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 6 Nov 2013 12:49:00 -0500 Subject: [PATCH 07/82] Bug 935593 - Remove an incorrect input event transformation. r=jimm --- gfx/layers/composite/APZCTreeManager.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/gfx/layers/composite/APZCTreeManager.cpp b/gfx/layers/composite/APZCTreeManager.cpp index a9aaec77a0ab..4f191cbeb131 100644 --- a/gfx/layers/composite/APZCTreeManager.cpp +++ b/gfx/layers/composite/APZCTreeManager.cpp @@ -392,7 +392,6 @@ APZCTreeManager::ProcessEvent(const WidgetInputEvent& aEvent, gfx3DMatrix transformToApzc; gfx3DMatrix transformToGecko; GetInputTransforms(apzc, transformToApzc, transformToGecko); - ApplyTransform(&(aOutEvent->refPoint), transformToApzc); gfx3DMatrix outTransform = transformToApzc * transformToGecko; ApplyTransform(&(aOutEvent->refPoint), outTransform); return nsEventStatus_eIgnore; From 3953712d920803bad88975d5676028fb8ea2395c Mon Sep 17 00:00:00 2001 From: Josh Aas Date: Wed, 6 Nov 2013 11:55:24 -0600 Subject: [PATCH 08/82] Bug 934538: Remove remaining references to Growl, including the license. r=wchen --- .../components/alerts/nsIAlertsService.idl | 4 +- .../components/alerts/test/test_alerts.html | 4 +- .../alerts/test/test_alerts_noobserve.html | 4 +- toolkit/content/license.html | 42 ------------------- 4 files changed, 5 insertions(+), 49 deletions(-) diff --git a/toolkit/components/alerts/nsIAlertsService.idl b/toolkit/components/alerts/nsIAlertsService.idl index 82fc94c8ee91..836c88d9ea55 100644 --- a/toolkit/components/alerts/nsIAlertsService.idl +++ b/toolkit/components/alerts/nsIAlertsService.idl @@ -24,9 +24,7 @@ interface nsIAlertsService : nsISupports * @param alertListener Used for callbacks. May be null if the caller * doesn't care about callbacks. * @param name The name of the notification. This is currently - * only used on OS X with Growl and Android. - * On OS X with Growl, users can disable notifications - * with a given name. On Android the name is hashed + * only used on Android. On Android the name is hashed * and used as a notification ID. Notifications will * replace previous notifications with the same name. * @param dir Bidi override for the title. Valid values are diff --git a/toolkit/components/alerts/test/test_alerts.html b/toolkit/components/alerts/test/test_alerts.html index 7ebef2008c46..431f0d76749b 100644 --- a/toolkit/components/alerts/test/test_alerts.html +++ b/toolkit/components/alerts/test/test_alerts.html @@ -53,7 +53,7 @@ function runTest() { ok(true, "Alerts service is available"); } catch (ex) { todo(false, - "Alerts service is not available. (Mac OS X without Growl?)", ex); + "Alerts service is not available.", ex); return; } @@ -64,7 +64,7 @@ function runTest() { false, "foobarcookie", observer); ok(true, "showAlertNotification() succeeded. Waiting for notification..."); } catch (ex) { - todo(false, "showAlertNotification() failed. (Mac OS X without Growl?)", ex); + todo(false, "showAlertNotification() failed.", ex); SimpleTest.finish(); } } diff --git a/toolkit/components/alerts/test/test_alerts_noobserve.html b/toolkit/components/alerts/test/test_alerts_noobserve.html index db235bff8545..fa903a060a44 100644 --- a/toolkit/components/alerts/test/test_alerts_noobserve.html +++ b/toolkit/components/alerts/test/test_alerts_noobserve.html @@ -35,7 +35,7 @@ if (!("@mozilla.org/alerts-service;1" in Cc)) { getService(Ci.nsIAlertsService); ok(true, "Alerts service is available"); } catch (ex) { - todo(false, "Alerts service is not available. (Mac OS X without Growl?)", ex); + todo(false, "Alerts service is not available.", ex); } if (notifier) { @@ -46,7 +46,7 @@ if (!("@mozilla.org/alerts-service;1" in Cc)) { gNotificationIsAvailable = true; } catch (ex) { - todo(false, "showAlertNotification() failed. (Mac OS X without Growl?)", ex); + todo(false, "showAlertNotification() failed.", ex); } } } diff --git a/toolkit/content/license.html b/toolkit/content/license.html index f0cbdeb3cc5d..812179e94d9c 100644 --- a/toolkit/content/license.html +++ b/toolkit/content/license.html @@ -83,7 +83,6 @@
  • Google Gears License
  • Google Gears/iStumbler License
  • Google VP8 License
  • -
  • Growl License
  • gyp License
  • halloc License
  • HarfBuzz License
  • @@ -2260,48 +2259,7 @@ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -
    -

    Growl License

    - -

    This license applies to certain files in the directory - toolkit/components/alerts/mac/growl/. - (This code only ships in the Mac OS X version of the product.) - -

    -Copyright (c) The Growl Project, 2004-2011
    -All rights reserved.
    -
    -Redistribution and use in source and binary forms, with or without
    -modification, are permitted provided that the following conditions are met:
    -
    -
    -1. Redistributions of source code must retain the above copyright
    -   notice, this list of conditions and the following disclaimer.
    -2. Redistributions in binary form must reproduce the above copyright
    -   notice, this list of conditions and the following disclaimer in the
    -   documentation and/or other materials provided with the distribution.
    -3. Neither the name of Growl nor the names of its contributors
    -   may be used to endorse or promote products derived from this software
    -   without specific prior written permission.
    -
    -
    -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
    -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
    -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    -
    - - -
    -

    gyp License

    From 5cb8ccfc854964a483e840b13a699729239bdfa0 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Wed, 6 Nov 2013 13:02:58 -0500 Subject: [PATCH 09/82] Bug 927796. Make sure we don't end up with options in a bogus state where their DefaultSelected() doesn't match mIsSelected but they think their mIsSelected value hasn't changed from the default. r=sicking --- .../html/content/src/HTMLOptionElement.cpp | 9 ++-- content/html/content/test/mochitest.ini | 1 + .../test/test_option_defaultSelected.html | 47 +++++++++++++++++++ 3 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 content/html/content/test/test_option_defaultSelected.html diff --git a/content/html/content/src/HTMLOptionElement.cpp b/content/html/content/src/HTMLOptionElement.cpp index 1758667b06a0..f74dfde701e3 100644 --- a/content/html/content/src/HTMLOptionElement.cpp +++ b/content/html/content/src/HTMLOptionElement.cpp @@ -211,7 +211,8 @@ HTMLOptionElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, int32_t index = Index(); uint32_t mask = HTMLSelectElement::SET_DISABLED; - if (aValue) { + bool defaultSelected = aValue; + if (defaultSelected) { mask |= HTMLSelectElement::IS_SELECTED; } @@ -227,8 +228,10 @@ HTMLOptionElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, // Now reset our members; when we finish the attr set we'll end up with the // rigt selected state. mIsInSetDefaultSelected = inSetDefaultSelected; - mSelectedChanged = false; - // mIsSelected doesn't matter while mSelectedChanged is false + // mIsSelected has already been set by SetOptionsSelectedByIndex. + // Possibly more than once; make sure our mSelectedChanged state is + // set correctly. + mSelectedChanged = mIsSelected != defaultSelected; return NS_OK; } diff --git a/content/html/content/test/mochitest.ini b/content/html/content/test/mochitest.ini index 1c1263f7af1d..f4246a1ff634 100644 --- a/content/html/content/test/mochitest.ini +++ b/content/html/content/test/mochitest.ini @@ -402,6 +402,7 @@ support-files = [test_object_attributes_reflection.html] [test_object_plugin_nav.html] [test_ol_attributes_reflection.html] +[test_option_defaultSelected.html] [test_param_attributes_reflection.html] [test_q_attributes_reflection.html] [test_restore_from_parser_fragment.html] diff --git a/content/html/content/test/test_option_defaultSelected.html b/content/html/content/test/test_option_defaultSelected.html new file mode 100644 index 000000000000..f3994e784d59 --- /dev/null +++ b/content/html/content/test/test_option_defaultSelected.html @@ -0,0 +1,47 @@ + + + + + + Test for Bug 927796 + + + + +Mozilla Bug 927796 +

    + + +

    + +
    +
    + + + From 4c89853298a43dcd41d5faf1150d4be774d70089 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Wed, 6 Nov 2013 13:02:58 -0500 Subject: [PATCH 10/82] Bug 934544. For the case when we have to copy an XPCOM string into a JSString, just ask the JS engine to do that. It'll do a better job of avoiding malloc than we can, since it can sometimes store string data inline in the string. r=peterv --- js/xpconnect/src/XPCString.cpp | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/js/xpconnect/src/XPCString.cpp b/js/xpconnect/src/XPCString.cpp index df9e400e4770..9c9f50b13142 100644 --- a/js/xpconnect/src/XPCString.cpp +++ b/js/xpconnect/src/XPCString.cpp @@ -83,26 +83,6 @@ XPCStringConvert::ReadableToJSVal(JSContext *cx, } // blech, have to copy. - - jschar *chars = reinterpret_cast - (JS_malloc(cx, (length + 1) * - sizeof(jschar))); - if (!chars) - return JS::NullValue(); - - if (length && !CopyUnicodeTo(readable, 0, - reinterpret_cast(chars), - length)) { - JS_free(cx, chars); - return JS::NullValue(); - } - - chars[length] = 0; - - str = JS_NewUCString(cx, chars, length); - if (!str) { - JS_free(cx, chars); - } - - return str ? STRING_TO_JSVAL(str) : JSVAL_NULL; + str = JS_NewUCStringCopyN(cx, readable.BeginReading(), length); + return str ? JS::StringValue(str) : JS::NullValue(); } From a06c944e1e3a98af650602ea8d57a67f34a67e53 Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Wed, 6 Nov 2013 10:23:43 -0800 Subject: [PATCH 11/82] Bug 935032 - Fix more miscellaneous uses of JSContext in IonBuilder, r=luke,jandem. --- js/src/frontend/BytecodeEmitter.cpp | 7 ++- js/src/jit/BaselineCompiler.cpp | 4 +- js/src/jit/BaselineIC.cpp | 4 +- js/src/jit/IonBuilder.cpp | 41 +++++++------- js/src/jit/IonBuilder.h | 7 ++- js/src/jsfriendapi.cpp | 6 +- js/src/jsopcode.cpp | 4 +- js/src/jsscript.cpp | 12 ++-- js/src/vm/GlobalObject.h | 6 ++ js/src/vm/Interpreter.cpp | 2 +- js/src/vm/ScopeObject-inl.h | 68 ++++++++++++++++++++++ js/src/vm/ScopeObject.cpp | 87 +++-------------------------- js/src/vm/ScopeObject.h | 23 ++++++-- js/src/vm/Shape.h | 27 +++++++-- js/src/vm/Stack.cpp | 9 +-- 15 files changed, 172 insertions(+), 135 deletions(-) diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index e5784a7e4d02..4de784ea04be 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -38,6 +38,7 @@ #include "frontend/ParseMaps-inl.h" #include "frontend/ParseNode-inl.h" +#include "vm/ScopeObject-inl.h" using namespace js; using namespace js::gc; @@ -1165,9 +1166,9 @@ TryConvertFreeName(BytecodeEmitter *bce, ParseNode *pn) if (bce->script->directlyInsideEval) return false; RootedObject outerScope(bce->sc->context, bce->script->enclosingStaticScope()); - for (StaticScopeIter ssi(bce->sc->context, outerScope); !ssi.done(); ssi++) { - if (ssi.type() != StaticScopeIter::FUNCTION) { - if (ssi.type() == StaticScopeIter::BLOCK) { + for (StaticScopeIter ssi(bce->sc->context, outerScope); !ssi.done(); ssi++) { + if (ssi.type() != StaticScopeIter::FUNCTION) { + if (ssi.type() == StaticScopeIter::BLOCK) { // Use generic ops if a catch block is encountered. return false; } diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp index 396396147ed1..3a86f46622e0 100644 --- a/js/src/jit/BaselineCompiler.cpp +++ b/js/src/jit/BaselineCompiler.cpp @@ -1907,7 +1907,7 @@ Address BaselineCompiler::getScopeCoordinateAddressFromObject(Register objReg, Register reg) { ScopeCoordinate sc(pc); - Shape *shape = ScopeCoordinateToStaticScopeShape(cx, script, pc); + Shape *shape = ScopeCoordinateToStaticScopeShape(script, pc); Address addr; if (shape->numFixedSlots() <= sc.slot) { @@ -1950,7 +1950,7 @@ BaselineCompiler::emit_JSOP_CALLALIASEDVAR() bool BaselineCompiler::emit_JSOP_SETALIASEDVAR() { - JSScript *outerScript = ScopeCoordinateFunctionScript(cx, script, pc); + JSScript *outerScript = ScopeCoordinateFunctionScript(script, pc); if (outerScript && outerScript->treatAsRunOnce) { // Type updates for this operation might need to be tracked, so treat // this as a SETPROP. diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp index f76c1124f4d9..538904ba2b9b 100644 --- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -1460,7 +1460,7 @@ DoTypeUpdateFallback(JSContext *cx, BaselineFrame *frame, ICUpdatedStub *stub, H JS_ASSERT(obj->isNative()); jsbytecode *pc = stub->getChainFallback()->icEntry()->pc(script); if (*pc == JSOP_SETALIASEDVAR) - id = NameToId(ScopeCoordinateName(cx, script, pc)); + id = NameToId(ScopeCoordinateName(script, pc)); else id = NameToId(script->getName(pc)); types::AddTypePropertyId(cx, obj, id, value); @@ -6843,7 +6843,7 @@ DoSetPropFallback(JSContext *cx, BaselineFrame *frame, ICSetProp_Fallback *stub, RootedPropertyName name(cx); if (op == JSOP_SETALIASEDVAR) - name = ScopeCoordinateName(cx, script, pc); + name = ScopeCoordinateName(script, pc); else name = script->getName(pc); RootedId id(cx, NameToId(name)); diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index 3190fa8dea5e..ed43d4b72b8e 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -46,6 +46,7 @@ IonBuilder::IonBuilder(JSContext *cx, TempAllocator *temp, MIRGraph *graph, cx(cx), baselineFrame_(baselineFrame), abortReason_(AbortReason_Disable), + reprSetHash_(nullptr), constraints_(constraints), analysis_(info->script()), thisTypes(nullptr), @@ -7678,8 +7679,9 @@ IonBuilder::testCommonGetterSetter(types::TemporaryTypeSet *types, PropertyName } bool -IonBuilder::annotateGetPropertyCache(JSContext *cx, MDefinition *obj, MGetPropertyCache *getPropCache, - types::TemporaryTypeSet *objTypes, types::TemporaryTypeSet *pushedTypes) +IonBuilder::annotateGetPropertyCache(MDefinition *obj, MGetPropertyCache *getPropCache, + types::TemporaryTypeSet *objTypes, + types::TemporaryTypeSet *pushedTypes) { PropertyName *name = getPropCache->name(); @@ -8240,7 +8242,7 @@ IonBuilder::getPropTryInlineAccess(bool *emitted, PropertyName *name, Shape *objShape = shapes[0]; obj = addShapeGuard(obj, objShape, Bailout_ShapeGuard); - Shape *shape = objShape->search(cx, NameToId(name)); + Shape *shape = objShape->searchLinear(NameToId(name)); JS_ASSERT(shape); if (!loadSlot(obj, shape, rvalType, barrier, types)) @@ -8255,7 +8257,7 @@ IonBuilder::getPropTryInlineAccess(bool *emitted, PropertyName *name, for (size_t i = 0; i < shapes.length(); i++) { Shape *objShape = shapes[i]; - Shape *shape = objShape->search(cx, NameToId(name)); + Shape *shape = objShape->searchLinear(NameToId(name)); JS_ASSERT(shape); if (!load->addShape(objShape, shape)) return false; @@ -8307,7 +8309,7 @@ IonBuilder::getPropTryCache(bool *emitted, PropertyName *name, } if (JSOp(*pc) == JSOP_CALLPROP) { - if (!annotateGetPropertyCache(cx, obj, load, obj->resultTypeSet(), types)) + if (!annotateGetPropertyCache(obj, load, obj->resultTypeSet(), types)) return false; } @@ -8642,7 +8644,7 @@ IonBuilder::setPropTryInlineAccess(bool *emitted, MDefinition *obj, Shape *objShape = shapes[0]; obj = addShapeGuard(obj, objShape, Bailout_ShapeGuard); - Shape *shape = objShape->search(cx, NameToId(name)); + Shape *shape = objShape->searchLinear(NameToId(name)); JS_ASSERT(shape); bool needsBarrier = objTypes->propertyNeedsBarrier(constraints(), NameToId(name)); @@ -8658,7 +8660,7 @@ IonBuilder::setPropTryInlineAccess(bool *emitted, MDefinition *obj, for (size_t i = 0; i < shapes.length(); i++) { Shape *objShape = shapes[i]; - Shape *shape = objShape->search(cx, NameToId(name)); + Shape *shape = objShape->searchLinear(NameToId(name)); JS_ASSERT(shape); if (!ins->addShape(objShape, shape)) return false; @@ -8727,9 +8729,8 @@ IonBuilder::jsop_delelem() bool IonBuilder::jsop_regexp(RegExpObject *reobj) { - JSObject *prototype = script()->global().getOrCreateRegExpPrototype(cx); - if (!prototype) - return false; + JSObject *prototype = reobj->getProto(); + JS_ASSERT(prototype == script()->global().maybeGetRegExpPrototype()); JS_ASSERT(&reobj->JSObject::global() == &script()->global()); @@ -9057,7 +9058,7 @@ IonBuilder::walkScopeChain(unsigned hops) bool IonBuilder::hasStaticScopeObject(ScopeCoordinate sc, JSObject **pcall) { - JSScript *outerScript = ScopeCoordinateFunctionScript(cx, script(), pc); + JSScript *outerScript = ScopeCoordinateFunctionScript(script(), pc); if (!outerScript || !outerScript->treatAsRunOnce) return false; @@ -9114,7 +9115,7 @@ IonBuilder::jsop_getaliasedvar(ScopeCoordinate sc) { JSObject *call = nullptr; if (hasStaticScopeObject(sc, &call) && call) { - PropertyName *name = ScopeCoordinateName(cx, script(), pc); + PropertyName *name = ScopeCoordinateName(script(), pc); bool succeeded; if (!getStaticName(call, name, &succeeded)) return false; @@ -9124,7 +9125,7 @@ IonBuilder::jsop_getaliasedvar(ScopeCoordinate sc) MDefinition *obj = walkScopeChain(sc.hops); - Shape *shape = ScopeCoordinateToStaticScopeShape(cx, script(), pc); + Shape *shape = ScopeCoordinateToStaticScopeShape(script(), pc); MInstruction *load; if (shape->numFixedSlots() <= sc.slot) { @@ -9154,7 +9155,7 @@ IonBuilder::jsop_setaliasedvar(ScopeCoordinate sc) return false; } MDefinition *value = current->pop(); - PropertyName *name = ScopeCoordinateName(cx, script(), pc); + PropertyName *name = ScopeCoordinateName(script(), pc); if (call) { // Push the object on the stack to match the bound object expected in @@ -9177,7 +9178,7 @@ IonBuilder::jsop_setaliasedvar(ScopeCoordinate sc) MDefinition *rval = current->peek(-1); MDefinition *obj = walkScopeChain(sc.hops); - Shape *shape = ScopeCoordinateToStaticScopeShape(cx, script(), pc); + Shape *shape = ScopeCoordinateToStaticScopeShape(script(), pc); if (NeedsPostBarrier(info(), rval)) current->add(MPostWriteBarrier::New(obj, rval)); @@ -9333,16 +9334,14 @@ TypeRepresentationSetHash * IonBuilder::getOrCreateReprSetHash() { if (!reprSetHash_) { - TypeRepresentationSetHash* hash = - cx->new_(); - if (!hash || !hash->init()) { - js_delete(hash); + TypeRepresentationSetHash *hash = + temp_->lifoAlloc()->new_(); + if (!hash || !hash->init()) return nullptr; - } reprSetHash_ = hash; } - return reprSetHash_.get(); + return reprSetHash_; } bool diff --git a/js/src/jit/IonBuilder.h b/js/src/jit/IonBuilder.h index da63f2afee54..a774b2f6ee99 100644 --- a/js/src/jit/IonBuilder.h +++ b/js/src/jit/IonBuilder.h @@ -636,8 +636,9 @@ class IonBuilder : public MIRGenerator bool testShouldDOMCall(types::TypeSet *inTypes, JSFunction *func, JSJitInfo::OpType opType); - bool annotateGetPropertyCache(JSContext *cx, MDefinition *obj, MGetPropertyCache *getPropCache, - types::TemporaryTypeSet *objTypes, types::TemporaryTypeSet *pushedTypes); + bool annotateGetPropertyCache(MDefinition *obj, MGetPropertyCache *getPropCache, + types::TemporaryTypeSet *objTypes, + types::TemporaryTypeSet *pushedTypes); MGetPropertyCache *getInlineableGetPropertyCache(CallInfo &callInfo); @@ -712,7 +713,7 @@ class IonBuilder : public MIRGenerator JSContext *cx; BaselineFrame *baselineFrame_; AbortReason abortReason_; - ScopedJSDeletePtr reprSetHash_; + TypeRepresentationSetHash *reprSetHash_; // Constraints for recording dependencies on type information. types::CompilerConstraintList *constraints_; diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp index 9affb38146ee..6b236f4c207e 100644 --- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -25,6 +25,8 @@ #include "jsobjinlines.h" +#include "vm/ScopeObject-inl.h" + using namespace js; using namespace JS; @@ -453,8 +455,8 @@ js::GetOutermostEnclosingFunctionOfScriptedCaller(JSContext *cx) RootedFunction scriptedCaller(cx, iter.callee()); RootedScript outermost(cx, scriptedCaller->nonLazyScript()); - for (StaticScopeIter i(cx, scriptedCaller); !i.done(); i++) { - if (i.type() == StaticScopeIter::FUNCTION) + for (StaticScopeIter i(scriptedCaller); !i.done(); i++) { + if (i.type() == StaticScopeIter::FUNCTION) outermost = i.funScript(); } return outermost; diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index 12758170010c..756f16b2326e 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -949,7 +949,7 @@ js_Disassemble1(JSContext *cx, HandleScript script, jsbytecode *pc, } case JOF_SCOPECOORD: { - Value v = StringValue(ScopeCoordinateName(cx, script, pc)); + Value v = StringValue(ScopeCoordinateName(script, pc)); JSAutoByteString bytes; if (!ToDisassemblySource(cx, v, &bytes)) return 0; @@ -1590,7 +1590,7 @@ ExpressionDecompiler::decompilePC(jsbytecode *pc) } case JSOP_CALLALIASEDVAR: case JSOP_GETALIASEDVAR: { - JSAtom *atom = ScopeCoordinateName(cx, script, pc); + JSAtom *atom = ScopeCoordinateName(script, pc); JS_ASSERT(atom); return write(atom); } diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index fbc451ea37b9..691de9e83ff8 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -687,8 +687,8 @@ js::XDRScript(XDRState *xdr, HandleObject enclosingScope, HandleScript enc if (!innerScript) return false; RootedObject staticScope(cx, innerScript->enclosingStaticScope()); - StaticScopeIter ssi(cx, staticScope); - if (ssi.done() || ssi.type() == StaticScopeIter::FUNCTION) { + StaticScopeIter ssi(staticScope); + if (ssi.done() || ssi.type() == StaticScopeIter::FUNCTION) { JS_ASSERT(ssi.done() == !fun); funEnclosingScopeIndex = UINT32_MAX; } else { @@ -2315,9 +2315,9 @@ js::CloneScript(JSContext *cx, HandleObject enclosingScope, HandleFunction fun, return nullptr; } RootedObject staticScope(cx, innerFun->nonLazyScript()->enclosingStaticScope()); - StaticScopeIter ssi(cx, staticScope); + StaticScopeIter ssi(cx, staticScope); RootedObject enclosingScope(cx); - if (!ssi.done() && ssi.type() == StaticScopeIter::BLOCK) + if (!ssi.done() && ssi.type() == StaticScopeIter::BLOCK) enclosingScope = objects[FindBlockIndex(src, ssi.block())]; else enclosingScope = fun; @@ -3001,8 +3001,8 @@ LazyScript::Create(ExclusiveContext *cx, HandleFunction fun, uint32_t LazyScript::staticLevel(JSContext *cx) const { - for (StaticScopeIter ssi(cx, enclosingScope()); !ssi.done(); ssi++) { - if (ssi.type() == StaticScopeIter::FUNCTION) + for (StaticScopeIter ssi(enclosingScope()); !ssi.done(); ssi++) { + if (ssi.type() == StaticScopeIter::FUNCTION) return ssi.funScript()->staticLevel + 1; } return 1; diff --git a/js/src/vm/GlobalObject.h b/js/src/vm/GlobalObject.h index 8dd14ba0f829..7e8b004aa9a3 100644 --- a/js/src/vm/GlobalObject.h +++ b/js/src/vm/GlobalObject.h @@ -390,6 +390,12 @@ class GlobalObject : public JSObject return &self->getPrototype(JSProto_RegExp).toObject(); } + JSObject *maybeGetRegExpPrototype() { + if (regexpClassInitialized()) + return &getPrototype(JSProto_RegExp).toObject(); + return nullptr; + } + JSObject *getOrCreateArrayBufferPrototype(JSContext *cx) { if (arrayBufferClassInitialized()) return &getPrototype(JSProto_ArrayBuffer).toObject(); diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index 470b053d1eca..3aeeadb0e0e4 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -2787,7 +2787,7 @@ CASE(JSOP_SETALIASEDVAR) // Avoid computing the name if no type updates are needed, as this may be // expensive on scopes with large numbers of variables. - PropertyName *name = obj.hasSingletonType() ? ScopeCoordinateName(cx, script, REGS.pc) + PropertyName *name = obj.hasSingletonType() ? ScopeCoordinateName(script, REGS.pc) : nullptr; obj.setAliasedVar(cx, sc, name, REGS.sp[-1]); diff --git a/js/src/vm/ScopeObject-inl.h b/js/src/vm/ScopeObject-inl.h index 8a1f19f00599..cfb878a9038c 100644 --- a/js/src/vm/ScopeObject-inl.h +++ b/js/src/vm/ScopeObject-inl.h @@ -36,6 +36,74 @@ CallObject::setAliasedVar(JSContext *cx, AliasedFormalIter fi, PropertyName *nam types::AddTypePropertyId(cx, this, NameToId(name), v); } +template +inline bool +StaticScopeIter::done() const +{ + return !obj; +} + +template +inline void +StaticScopeIter::operator++(int) +{ + if (obj->template is()) { + obj = obj->template as().enclosingStaticScope(); + } else if (onNamedLambda || !obj->template as().isNamedLambda()) { + onNamedLambda = false; + obj = obj->template as().nonLazyScript()->enclosingStaticScope(); + } else { + onNamedLambda = true; + } + JS_ASSERT_IF(obj, obj->template is() || obj->template is()); + JS_ASSERT_IF(onNamedLambda, obj->template is()); +} + +template +inline bool +StaticScopeIter::hasDynamicScopeObject() const +{ + return obj->template is() + ? obj->template as().needsClone() + : obj->template as().isHeavyweight(); +} + +template +inline Shape * +StaticScopeIter::scopeShape() const +{ + JS_ASSERT(hasDynamicScopeObject()); + JS_ASSERT(type() != NAMED_LAMBDA); + return type() == BLOCK + ? block().lastProperty() + : funScript()->bindings.callObjShape(); +} + +template +inline typename StaticScopeIter::Type +StaticScopeIter::type() const +{ + if (onNamedLambda) + return NAMED_LAMBDA; + return obj->template is() ? BLOCK : FUNCTION; +} + +template +inline StaticBlockObject & +StaticScopeIter::block() const +{ + JS_ASSERT(type() == BLOCK); + return obj->template as(); +} + +template +inline JSScript * +StaticScopeIter::funScript() const +{ + JS_ASSERT(type() == FUNCTION); + return obj->template as().nonLazyScript(); +} + } /* namespace js */ #endif /* vm_ScopeObject_inl_h */ diff --git a/js/src/vm/ScopeObject.cpp b/js/src/vm/ScopeObject.cpp index 89fd6c8564d5..82b23cb7545f 100644 --- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -32,75 +32,6 @@ typedef Rooted RootedArgumentsObject; /*****************************************************************************/ -StaticScopeIter::StaticScopeIter(ExclusiveContext *cx, JSObject *objArg) - : obj(cx, objArg), onNamedLambda(false) -{ - JS_ASSERT_IF(obj, obj->is() || obj->is()); -} - -bool -StaticScopeIter::done() const -{ - return !obj; -} - -void -StaticScopeIter::operator++(int) -{ - if (obj->is()) { - obj = obj->as().enclosingStaticScope(); - } else if (onNamedLambda || !obj->as().isNamedLambda()) { - onNamedLambda = false; - obj = obj->as().nonLazyScript()->enclosingStaticScope(); - } else { - onNamedLambda = true; - } - JS_ASSERT_IF(obj, obj->is() || obj->is()); - JS_ASSERT_IF(onNamedLambda, obj->is()); -} - -bool -StaticScopeIter::hasDynamicScopeObject() const -{ - return obj->is() - ? obj->as().needsClone() - : obj->as().isHeavyweight(); -} - -Shape * -StaticScopeIter::scopeShape() const -{ - JS_ASSERT(hasDynamicScopeObject()); - JS_ASSERT(type() != NAMED_LAMBDA); - return type() == BLOCK - ? block().lastProperty() - : funScript()->bindings.callObjShape(); -} - -StaticScopeIter::Type -StaticScopeIter::type() const -{ - if (onNamedLambda) - return NAMED_LAMBDA; - return obj->is() ? BLOCK : FUNCTION; -} - -StaticBlockObject & -StaticScopeIter::block() const -{ - JS_ASSERT(type() == BLOCK); - return obj->as(); -} - -JSScript * -StaticScopeIter::funScript() const -{ - JS_ASSERT(type() == FUNCTION); - return obj->as().nonLazyScript(); -} - -/*****************************************************************************/ - static JSObject * InnermostStaticScope(JSScript *script, jsbytecode *pc) { @@ -115,9 +46,9 @@ InnermostStaticScope(JSScript *script, jsbytecode *pc) } Shape * -js::ScopeCoordinateToStaticScopeShape(JSContext *cx, JSScript *script, jsbytecode *pc) +js::ScopeCoordinateToStaticScopeShape(JSScript *script, jsbytecode *pc) { - StaticScopeIter ssi(cx, InnermostStaticScope(script, pc)); + StaticScopeIter ssi(InnermostStaticScope(script, pc)); ScopeCoordinate sc(pc); while (true) { if (ssi.hasDynamicScopeObject()) { @@ -131,9 +62,9 @@ js::ScopeCoordinateToStaticScopeShape(JSContext *cx, JSScript *script, jsbytecod } PropertyName * -js::ScopeCoordinateName(JSContext *cx, JSScript *script, jsbytecode *pc) +js::ScopeCoordinateName(JSScript *script, jsbytecode *pc) { - Shape::Range r(ScopeCoordinateToStaticScopeShape(cx, script, pc)); + Shape::Range r(ScopeCoordinateToStaticScopeShape(script, pc)); ScopeCoordinate sc(pc); while (r.front().slot() != sc.slot) r.popFront(); @@ -141,14 +72,14 @@ js::ScopeCoordinateName(JSContext *cx, JSScript *script, jsbytecode *pc) /* Beware nameless destructuring formal. */ if (!JSID_IS_ATOM(id)) - return cx->runtime()->atomState.empty; + return script->runtimeFromAnyThread()->atomState.empty; return JSID_TO_ATOM(id)->asPropertyName(); } JSScript * -js::ScopeCoordinateFunctionScript(JSContext *cx, JSScript *script, jsbytecode *pc) +js::ScopeCoordinateFunctionScript(JSScript *script, jsbytecode *pc) { - StaticScopeIter ssi(cx, InnermostStaticScope(script, pc)); + StaticScopeIter ssi(InnermostStaticScope(script, pc)); ScopeCoordinate sc(pc); while (true) { if (ssi.hasDynamicScopeObject()) { @@ -158,7 +89,7 @@ js::ScopeCoordinateFunctionScript(JSContext *cx, JSScript *script, jsbytecode *p } ssi++; } - if (ssi.type() != StaticScopeIter::FUNCTION) + if (ssi.type() != StaticScopeIter::FUNCTION) return nullptr; return ssi.funScript(); } @@ -2195,7 +2126,7 @@ RemoveReferencedNames(JSContext *cx, HandleScript script, PropertyNameSet &remai case JSOP_GETALIASEDVAR: case JSOP_CALLALIASEDVAR: case JSOP_SETALIASEDVAR: - name = ScopeCoordinateName(cx, script, pc); + name = ScopeCoordinateName(script, pc); break; default: diff --git a/js/src/vm/ScopeObject.h b/js/src/vm/ScopeObject.h index 7d56b3e8b48d..3c65f296e184 100644 --- a/js/src/vm/ScopeObject.h +++ b/js/src/vm/ScopeObject.h @@ -54,13 +54,26 @@ namespace frontend { struct Definition; } * * (See also AssertDynamicScopeMatchesStaticScope.) */ +template class StaticScopeIter { - RootedObject obj; + typename MaybeRooted::RootType obj; bool onNamedLambda; public: - explicit StaticScopeIter(ExclusiveContext *cx, JSObject *obj); + StaticScopeIter(ExclusiveContext *cx, JSObject *obj) + : obj(cx, obj), onNamedLambda(false) + { + JS_STATIC_ASSERT(allowGC == CanGC); + JS_ASSERT_IF(obj, obj->is() || obj->is()); + } + + StaticScopeIter(JSObject *obj) + : obj((ExclusiveContext *) nullptr, obj), onNamedLambda(false) + { + JS_STATIC_ASSERT(allowGC == NoGC); + JS_ASSERT_IF(obj, obj->is() || obj->is()); + } bool done() const; void operator++(int); @@ -106,15 +119,15 @@ struct ScopeCoordinate * accessed by the ALIASEDVAR op at 'pc'. */ extern Shape * -ScopeCoordinateToStaticScopeShape(JSContext *cx, JSScript *script, jsbytecode *pc); +ScopeCoordinateToStaticScopeShape(JSScript *script, jsbytecode *pc); /* Return the name being accessed by the given ALIASEDVAR op. */ extern PropertyName * -ScopeCoordinateName(JSContext *cx, JSScript *script, jsbytecode *pc); +ScopeCoordinateName(JSScript *script, jsbytecode *pc); /* Return the function script accessed by the given ALIASEDVAR op, or nullptr. */ extern JSScript * -ScopeCoordinateFunctionScript(JSContext *cx, JSScript *script, jsbytecode *pc); +ScopeCoordinateFunctionScript(JSScript *script, jsbytecode *pc); /*****************************************************************************/ diff --git a/js/src/vm/Shape.h b/js/src/vm/Shape.h index 65f34422123c..975035b91424 100644 --- a/js/src/vm/Shape.h +++ b/js/src/vm/Shape.h @@ -1295,6 +1295,7 @@ class Shape : public gc::BarrieredCell } inline Shape *search(ExclusiveContext *cx, jsid id); + inline Shape *searchLinear(jsid id); /* For JIT usage */ static inline size_t offsetOfBase() { return offsetof(Shape, base_); } @@ -1582,6 +1583,25 @@ Shape::Shape(UnownedBaseShape *base, uint32_t nfixed) kids.setNull(); } +inline Shape * +Shape::searchLinear(jsid id) +{ + /* + * Non-dictionary shapes can acquire a table at any point the main thread + * is operating on it, so other threads inspecting such shapes can't use + * their table without racing. This function can be called from any thread + * on any non-dictionary shape. + */ + JS_ASSERT(!inDictionary()); + + for (Shape *shape = this; shape; shape = shape->parent) { + if (shape->propidRef() == id) + return shape; + } + + return nullptr; +} + /* * Keep this function in sync with search. It neither hashifies the start * shape nor increments linear search count. @@ -1598,12 +1618,7 @@ Shape::searchNoHashify(Shape *start, jsid id) return SHAPE_FETCH(spp); } - for (Shape *shape = start; shape; shape = shape->parent) { - if (shape->propidRef() == id) - return shape; - } - - return nullptr; + return start->searchLinear(id); } inline bool diff --git a/js/src/vm/Stack.cpp b/js/src/vm/Stack.cpp index 46317e7451be..e92bca1ace47 100644 --- a/js/src/vm/Stack.cpp +++ b/js/src/vm/Stack.cpp @@ -20,6 +20,7 @@ #include "jit/IonFrameIterator-inl.h" #include "vm/Interpreter-inl.h" #include "vm/Probes-inl.h" +#include "vm/ScopeObject-inl.h" using namespace js; @@ -204,7 +205,7 @@ AssertDynamicScopeMatchesStaticScope(JSContext *cx, JSScript *script, JSObject * { #ifdef DEBUG RootedObject enclosingScope(cx, script->enclosingStaticScope()); - for (StaticScopeIter i(cx, enclosingScope); !i.done(); i++) { + for (StaticScopeIter i(enclosingScope); !i.done(); i++) { if (i.hasDynamicScopeObject()) { /* * 'with' does not participate in the static scope of the script, @@ -214,15 +215,15 @@ AssertDynamicScopeMatchesStaticScope(JSContext *cx, JSScript *script, JSObject * scope = &scope->as().enclosingScope(); switch (i.type()) { - case StaticScopeIter::BLOCK: + case StaticScopeIter::BLOCK: JS_ASSERT(i.block() == scope->as().staticBlock()); scope = &scope->as().enclosingScope(); break; - case StaticScopeIter::FUNCTION: + case StaticScopeIter::FUNCTION: JS_ASSERT(scope->as().callee().nonLazyScript() == i.funScript()); scope = &scope->as().enclosingScope(); break; - case StaticScopeIter::NAMED_LAMBDA: + case StaticScopeIter::NAMED_LAMBDA: scope = &scope->as().enclosingScope(); break; } From 669a2906e479654780f8eb9cede159b8c9b62ebd Mon Sep 17 00:00:00 2001 From: Kannan Vijayan Date: Wed, 6 Nov 2013 13:26:44 -0500 Subject: [PATCH 12/82] Bug 925470 - Dont use ArgsObj-based args when OSR-ing into scripts with argsObjAliasesFormals=false. r=h4writer --- .../tests/arguments/strict-osr-shadowed-args.js | 13 +++++++++++++ js/src/jit/IonBuilder.cpp | 6 +++++- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 js/src/jit-test/tests/arguments/strict-osr-shadowed-args.js diff --git a/js/src/jit-test/tests/arguments/strict-osr-shadowed-args.js b/js/src/jit-test/tests/arguments/strict-osr-shadowed-args.js new file mode 100644 index 000000000000..5c193b99f630 --- /dev/null +++ b/js/src/jit-test/tests/arguments/strict-osr-shadowed-args.js @@ -0,0 +1,13 @@ + +"use strict"; + +function loop(a) { + a = arguments.length; + var result = 0; + for (var i = 0; i < 5000; i++) { + result += a; + } + return result; +} + +assertEq(loop(11), 5000); diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index ed43d4b72b8e..7e335f7bd425 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -5697,7 +5697,11 @@ IonBuilder::newOsrPreheader(MBasicBlock *predecessor, jsbytecode *loopEntry) for (uint32_t i = 0; i < info().nargs(); i++) { uint32_t slot = needsArgsObj ? info().argSlotUnchecked(i) : info().argSlot(i); - if (needsArgsObj) { + // Only grab arguments from the arguments object if the arguments object + // aliases formals. If the argsobj does not alias formals, then the + // formals may have been assigned to during interpretation, and that change + // will not be reflected in the argsobj. + if (needsArgsObj && info().argsObjAliasesFormals()) { JS_ASSERT(argsObj && argsObj->isOsrArgumentsObject()); // If this is an aliased formal, then the arguments object // contains a hole at this index. Any references to this From 587777116aa6c71eac73f6cd1ea796d471c39e6b Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 6 Nov 2013 12:31:25 -0600 Subject: [PATCH 13/82] Add passing tests for bug 934789, which was fixed by backing out bug 933798 in rev 175bebe48034. Thanks to luke for test cases. no_r=testonly. --- js/src/jit-test/tests/basic/bug934789-1.js | 13 +++++++++++++ js/src/jit-test/tests/basic/bug934789-2.js | 15 +++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 js/src/jit-test/tests/basic/bug934789-1.js create mode 100644 js/src/jit-test/tests/basic/bug934789-2.js diff --git a/js/src/jit-test/tests/basic/bug934789-1.js b/js/src/jit-test/tests/basic/bug934789-1.js new file mode 100644 index 000000000000..3b290e135b47 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug934789-1.js @@ -0,0 +1,13 @@ +if (typeof dis === "function") { + (function() { + function foo() {} + + dis(function bar(e) { + try { + (function() { e; }); + } catch (e) { + foo(); + } + }); + }()); +} diff --git a/js/src/jit-test/tests/basic/bug934789-2.js b/js/src/jit-test/tests/basic/bug934789-2.js new file mode 100644 index 000000000000..5272d63e0197 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug934789-2.js @@ -0,0 +1,15 @@ +load(libdir + "asserts.js"); +assertThrowsInstanceOf( + function() { + function foo() {} + foo = null; + (function bar(e) { + try { + (function() { e; }); + throw 1; + } catch (e) { + foo(); + } + })(); + }, + TypeError); From d1aa0a285c1321529785f09b00d9c30c6b219f1d Mon Sep 17 00:00:00 2001 From: Nikhil Marathe Date: Wed, 6 Nov 2013 10:41:44 -0800 Subject: [PATCH 14/82] Bug 915233 - DOM Promises on Workers. r=baku,smaug,bz sr=sicking --HG-- extra : rebase_source : 0923cb54bb13291df69c894866b4054310a4627c --- dom/promise/Promise.cpp | 234 +++++++++++++--- dom/promise/Promise.h | 8 +- dom/promise/PromiseCallback.cpp | 28 +- dom/promise/PromiseCallback.h | 2 +- dom/promise/tests/test_promise.html | 10 + dom/workers/RegisterBindings.cpp | 5 +- dom/workers/test/mochitest.ini | 2 + dom/workers/test/promise_worker.js | 395 ++++++++++++++++++++++++++++ dom/workers/test/test_promise.html | 44 ++++ 9 files changed, 677 insertions(+), 51 deletions(-) create mode 100644 dom/workers/test/promise_worker.js create mode 100644 dom/workers/test/test_promise.html diff --git a/dom/promise/Promise.cpp b/dom/promise/Promise.cpp index 49879e478ff5..375e261fe840 100644 --- a/dom/promise/Promise.cpp +++ b/dom/promise/Promise.cpp @@ -10,6 +10,7 @@ #include "mozilla/dom/OwningNonNull.h" #include "mozilla/dom/PromiseBinding.h" #include "mozilla/Preferences.h" +#include "mozilla/SyncRunnable.h" #include "PromiseCallback.h" #include "nsContentUtils.h" #include "nsPIDOMWindow.h" @@ -22,6 +23,8 @@ namespace mozilla { namespace dom { +using namespace workers; + // PromiseTask // This class processes the promise's callbacks with promise's result. @@ -51,36 +54,65 @@ private: nsRefPtr mPromise; }; -// This class processes the promise's callbacks with promise's result. -class PromiseResolverTask MOZ_FINAL : public nsRunnable +class WorkerPromiseTask MOZ_FINAL : public WorkerRunnable { public: - PromiseResolverTask(Promise* aPromise, - JS::Handle aValue, - Promise::PromiseState aState) + WorkerPromiseTask(WorkerPrivate* aWorkerPrivate, Promise* aPromise) + : WorkerRunnable(aWorkerPrivate, WorkerThread, + UnchangedBusyCount, SkipWhenClearing) + , mPromise(aPromise) + { + MOZ_ASSERT(aPromise); + MOZ_COUNT_CTOR(WorkerPromiseTask); + } + + ~WorkerPromiseTask() + { + MOZ_COUNT_DTOR(WorkerPromiseTask); + } + + bool + WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) + { + mPromise->mTaskPending = false; + mPromise->RunTask(); + return true; + } + +private: + nsRefPtr mPromise; +}; + +class PromiseResolverMixin +{ +public: + PromiseResolverMixin(Promise* aPromise, + JS::Handle aValue, + Promise::PromiseState aState) : mPromise(aPromise) , mValue(aValue) , mState(aState) { MOZ_ASSERT(aPromise); MOZ_ASSERT(mState != Promise::Pending); - MOZ_COUNT_CTOR(PromiseResolverTask); + MOZ_COUNT_CTOR(PromiseResolverMixin); - JSContext* cx = nsContentUtils::GetSafeJSContext(); + JSContext* cx = nsContentUtils::GetDefaultJSContextForThread(); /* It's safe to use unsafeGet() here: the unsafeness comes from the * possibility of updating the value of mJSObject without triggering the * barriers. However if the value will always be marked, post barriers * unnecessary. */ JS_AddNamedValueRootRT(JS_GetRuntime(cx), mValue.unsafeGet(), - "PromiseResolverTask.mValue"); + "PromiseResolverMixin.mValue"); } - ~PromiseResolverTask() + virtual ~PromiseResolverMixin() { - MOZ_COUNT_DTOR(PromiseResolverTask); + NS_ASSERT_OWNINGTHREAD(PromiseResolverMixin); + MOZ_COUNT_DTOR(PromiseResolverMixin); - JSContext* cx = nsContentUtils::GetSafeJSContext(); + JSContext* cx = nsContentUtils::GetDefaultJSContextForThread(); /* It's safe to use unsafeGet() here: the unsafeness comes from the * possibility of updating the value of mJSObject without triggering the @@ -89,18 +121,66 @@ public: JS_RemoveValueRootRT(JS_GetRuntime(cx), mValue.unsafeGet()); } - NS_IMETHOD Run() +protected: + void + RunInternal() { + NS_ASSERT_OWNINGTHREAD(PromiseResolverMixin); mPromise->RunResolveTask( JS::Handle::fromMarkedLocation(mValue.address()), mState, Promise::SyncTask); - return NS_OK; } private: nsRefPtr mPromise; JS::Heap mValue; Promise::PromiseState mState; + NS_DECL_OWNINGTHREAD; +}; + +// This class processes the promise's callbacks with promise's result. +class PromiseResolverTask MOZ_FINAL : public nsRunnable, + public PromiseResolverMixin +{ +public: + PromiseResolverTask(Promise* aPromise, + JS::Handle aValue, + Promise::PromiseState aState) + : PromiseResolverMixin(aPromise, aValue, aState) + {} + + ~PromiseResolverTask() + {} + + NS_IMETHOD Run() + { + RunInternal(); + return NS_OK; + } +}; + +class WorkerPromiseResolverTask MOZ_FINAL : public WorkerRunnable, + public PromiseResolverMixin +{ +public: + WorkerPromiseResolverTask(WorkerPrivate* aWorkerPrivate, + Promise* aPromise, + JS::Handle aValue, + Promise::PromiseState aState) + : WorkerRunnable(aWorkerPrivate, WorkerThread, + UnchangedBusyCount, SkipWhenClearing), + PromiseResolverMixin(aPromise, aValue, aState) + {} + + ~WorkerPromiseResolverTask() + {} + + bool + WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) + { + RunInternal(); + return true; + } }; // Promise @@ -163,25 +243,55 @@ Promise::WrapObject(JSContext* aCx, JS::Handle aScope) return PromiseBinding::Wrap(aCx, aScope, this); } -/* static */ bool -Promise::PrefEnabled() +class PromisePrefEnabledRunnable : public nsRunnable { - return Preferences::GetBool("dom.promise.enabled", false); -} +public: + PromisePrefEnabledRunnable() : mEnabled(false) {} + + bool + Enabled() + { + return mEnabled; + } + + NS_IMETHODIMP + Run() + { + MOZ_ASSERT(NS_IsMainThread()); + mEnabled = Preferences::GetBool("dom.promise.enabled", false); + return NS_OK; + } + +private: + bool mEnabled; +}; /* static */ bool Promise::EnabledForScope(JSContext* aCx, JSObject* /* unused */) { // Enable if the pref is enabled or if we're chrome or if we're a // certified app. - if (PrefEnabled()) { + nsCOMPtr mainThread; + nsresult rv = NS_GetMainThread(getter_AddRefs(mainThread)); + NS_ENSURE_SUCCESS(rv, false); + + nsRefPtr r = new PromisePrefEnabledRunnable(); + + // When used from the main thread, SyncRunnable will internally directly call + // the function rather than dispatch a Runnable. So this is usable on any + // thread. + // Although this pause is expensive, it is performed only once per worker when + // the worker in initialized. + SyncRunnable::DispatchToThread(mainThread, r); + if (r->Enabled()) { return true; } + // FIXME(nsm): Remove these checks once promises are enabled by default. // Note that we have no concept of a certified app in workers. // XXXbz well, why not? if (!NS_IsMainThread()) { - return workers::GetWorkerPrivateFromContext(aCx)->IsChromeWorker(); + return GetWorkerPrivateFromContext(aCx)->IsChromeWorker(); } nsIPrincipal* prin = nsContentUtils::GetSubjectPrincipal(); @@ -280,10 +390,15 @@ Promise::Constructor(const GlobalObject& aGlobal, PromiseInit& aInit, ErrorResult& aRv) { JSContext* cx = aGlobal.GetContext(); - nsCOMPtr window = do_QueryInterface(aGlobal.GetAsSupports()); - if (!window) { - aRv.Throw(NS_ERROR_UNEXPECTED); - return nullptr; + nsCOMPtr window; + + // On workers, let the window be null. + if (MOZ_LIKELY(NS_IsMainThread())) { + window = do_QueryInterface(aGlobal.GetAsSupports()); + if (!window) { + aRv.Throw(NS_ERROR_UNEXPECTED); + return nullptr; + } } nsRefPtr promise = new Promise(window); @@ -324,10 +439,13 @@ Promise::Constructor(const GlobalObject& aGlobal, Promise::Resolve(const GlobalObject& aGlobal, JSContext* aCx, JS::Handle aValue, ErrorResult& aRv) { - nsCOMPtr window = do_QueryInterface(aGlobal.GetAsSupports()); - if (!window) { - aRv.Throw(NS_ERROR_UNEXPECTED); - return nullptr; + nsCOMPtr window; + if (MOZ_LIKELY(NS_IsMainThread())) { + window = do_QueryInterface(aGlobal.GetAsSupports()); + if (!window) { + aRv.Throw(NS_ERROR_UNEXPECTED); + return nullptr; + } } nsRefPtr promise = new Promise(window); @@ -341,10 +459,13 @@ Promise::Resolve(const GlobalObject& aGlobal, JSContext* aCx, Promise::Reject(const GlobalObject& aGlobal, JSContext* aCx, JS::Handle aValue, ErrorResult& aRv) { - nsCOMPtr window = do_QueryInterface(aGlobal.GetAsSupports()); - if (!window) { - aRv.Throw(NS_ERROR_UNEXPECTED); - return nullptr; + nsCOMPtr window; + if (MOZ_LIKELY(NS_IsMainThread())) { + window = do_QueryInterface(aGlobal.GetAsSupports()); + if (!window) { + aRv.Throw(NS_ERROR_UNEXPECTED); + return nullptr; + } } nsRefPtr promise = new Promise(window); @@ -403,8 +524,15 @@ Promise::AppendCallbacks(PromiseCallback* aResolveCallback, // callbacks with promise's result. If promise's state is rejected, queue a // task to process our reject callbacks with promise's result. if (mState != Pending && !mTaskPending) { - nsRefPtr task = new PromiseTask(this); - NS_DispatchToCurrentThread(task); + if (MOZ_LIKELY(NS_IsMainThread())) { + nsRefPtr task = new PromiseTask(this); + NS_DispatchToCurrentThread(task); + } else { + WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); + MOZ_ASSERT(worker); + nsRefPtr task = new WorkerPromiseTask(worker, this); + worker->Dispatch(task); + } mTaskPending = true; } } @@ -420,8 +548,9 @@ Promise::RunTask() mResolveCallbacks.Clear(); mRejectCallbacks.Clear(); - JSAutoRequest ar(nsContentUtils::GetSafeJSContext()); - Optional > value(nsContentUtils::GetSafeJSContext(), mResult); + JSContext* cx = nsContentUtils::GetDefaultJSContextForThread(); + JSAutoRequest ar(cx); + Optional > value(cx, mResult); for (uint32_t i = 0; i < callbacks.Length(); ++i) { callbacks[i]->Call(value); @@ -442,16 +571,27 @@ Promise::MaybeReportRejected() MOZ_ASSERT(mResult.isObject(), "How did we get a JSErrorReport?"); - nsCOMPtr win = - do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(&mResult.toObject())); + // Remains null in case of worker. + nsCOMPtr win; + bool isChromeError = false; + + if (MOZ_LIKELY(NS_IsMainThread())) { + win = + do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(&mResult.toObject())); + nsIPrincipal* principal = nsContentUtils::GetObjectPrincipal(&mResult.toObject()); + isChromeError = nsContentUtils::IsSystemPrincipal(principal); + } else { + WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); + MOZ_ASSERT(worker); + isChromeError = worker->IsChromeWorker(); + } - nsIPrincipal* principal = nsContentUtils::GetObjectPrincipal(&mResult.toObject()); // Now post an event to do the real reporting async - NS_DispatchToCurrentThread( + NS_DispatchToMainThread( new AsyncErrorReporter(JS_GetObjectRuntime(&mResult.toObject()), report, nullptr, - nsContentUtils::IsSystemPrincipal(principal), + isChromeError, win)); } @@ -530,9 +670,17 @@ Promise::RunResolveTask(JS::Handle aValue, // If the synchronous flag is unset, queue a task to process our // accept callbacks with value. if (aAsynchronous == AsyncTask) { - nsRefPtr task = - new PromiseResolverTask(this, aValue, aState); - NS_DispatchToCurrentThread(task); + if (MOZ_LIKELY(NS_IsMainThread())) { + nsRefPtr task = + new PromiseResolverTask(this, aValue, aState); + NS_DispatchToCurrentThread(task); + } else { + WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); + MOZ_ASSERT(worker); + nsRefPtr task = + new WorkerPromiseResolverTask(worker, this, aValue, aState); + worker->Dispatch(task); + } return; } diff --git a/dom/promise/Promise.h b/dom/promise/Promise.h index de2c06f11525..6a3f1ca7e889 100644 --- a/dom/promise/Promise.h +++ b/dom/promise/Promise.h @@ -27,10 +27,13 @@ class AnyCallback; class Promise MOZ_FINAL : public nsISupports, public nsWrapperCache { - friend class PromiseTask; + friend class PromiseResolverMixin; friend class PromiseResolverTask; - friend class ResolvePromiseCallback; + friend class PromiseTask; friend class RejectPromiseCallback; + friend class ResolvePromiseCallback; + friend class WorkerPromiseResolverTask; + friend class WorkerPromiseTask; friend class WrapperPromiseCallback; public: @@ -40,7 +43,6 @@ public: Promise(nsPIDOMWindow* aWindow); ~Promise(); - static bool PrefEnabled(); static bool EnabledForScope(JSContext* aCx, JSObject* /* unused */); void MaybeResolve(JSContext* aCx, diff --git a/dom/promise/PromiseCallback.cpp b/dom/promise/PromiseCallback.cpp index f8cb9b9c9a1a..c828b2171355 100644 --- a/dom/promise/PromiseCallback.cpp +++ b/dom/promise/PromiseCallback.cpp @@ -74,7 +74,13 @@ void ResolvePromiseCallback::Call(const Optional >& aValue) { // Run resolver's algorithm with value and the synchronous flag set. - AutoJSContext cx; + JSContext *cx = nsContentUtils::GetDefaultJSContextForThread(); + + Maybe pusher; + if (NS_IsMainThread()) { + pusher.construct(cx); + } + Maybe ac; EnterCompartment(ac, cx, aValue); @@ -109,7 +115,13 @@ void RejectPromiseCallback::Call(const Optional >& aValue) { // Run resolver's algorithm with value and the synchronous flag set. - AutoJSContext cx; + JSContext *cx = nsContentUtils::GetDefaultJSContextForThread(); + + Maybe pusher; + if (NS_IsMainThread()) { + pusher.construct(cx); + } + Maybe ac; EnterCompartment(ac, cx, aValue); @@ -145,7 +157,17 @@ WrapperPromiseCallback::~WrapperPromiseCallback() void WrapperPromiseCallback::Call(const Optional >& aValue) { - AutoJSContext cx; + // AutoCxPusher and co. interact with xpconnect, which crashes on + // workers. On workers we'll get the right context from + // GetDefaultJSContextForThread(), and since there is only one context, we + // don't need to push or pop it from the stack. Is that correct? + JSContext* cx = nsContentUtils::GetDefaultJSContextForThread(); + + Maybe pusher; + if (NS_IsMainThread()) { + pusher.construct(cx); + } + Maybe ac; EnterCompartment(ac, cx, aValue); diff --git a/dom/promise/PromiseCallback.h b/dom/promise/PromiseCallback.h index 38089466eed6..07f156100820 100644 --- a/dom/promise/PromiseCallback.h +++ b/dom/promise/PromiseCallback.h @@ -37,7 +37,7 @@ public: }; // WrapperPromiseCallback execs a JS Callback with a value, and then the return -// value is sent to the aNextPromise->resolveFunction() or to +// value is sent to the aNextPromise->ResolveFunction() or to // aNextPromise->RejectFunction() if the JS Callback throws. class WrapperPromiseCallback MOZ_FINAL : public PromiseCallback { diff --git a/dom/promise/tests/test_promise.html b/dom/promise/tests/test_promise.html index 3e5b1f3cad6a..0cc6a5822b7c 100644 --- a/dom/promise/tests/test_promise.html +++ b/dom/promise/tests/test_promise.html @@ -368,6 +368,15 @@ function promiseResolveNestedPromise() { }); } +function promiseRejectNoHandler() { + // This test only checks that the code that reports unhandled errors in the + // Promises implementation does not crash or leak. + var promise = new Promise(function(res, rej) { + noSuchMethod(); + }); + runTest(); +} + var tests = [ promiseResolve, promiseReject, promiseException, promiseGC, promiseAsync, promiseDoubleThen, promiseThenException, @@ -380,6 +389,7 @@ var tests = [ promiseResolve, promiseReject, promiseWrongNestedPromise, promiseLoop, promiseStaticReject, promiseStaticResolve, promiseResolveNestedPromise, + promiseRejectNoHandler, ]; function runTest() { diff --git a/dom/workers/RegisterBindings.cpp b/dom/workers/RegisterBindings.cpp index 505e304d3aab..4dfae63199ab 100644 --- a/dom/workers/RegisterBindings.cpp +++ b/dom/workers/RegisterBindings.cpp @@ -19,6 +19,7 @@ #include "mozilla/dom/ImageDataBinding.h" #include "mozilla/dom/MessageEventBinding.h" #include "mozilla/dom/MessagePortBinding.h" +#include "mozilla/dom/PromiseBinding.h" #include "mozilla/dom/TextDecoderBinding.h" #include "mozilla/dom/TextEncoderBinding.h" #include "mozilla/dom/XMLHttpRequestBinding.h" @@ -61,6 +62,8 @@ WorkerPrivate::RegisterBindings(JSContext* aCx, JS::Handle aGlobal) !ImageDataBinding::GetConstructorObject(aCx, aGlobal) || !MessageEventBinding::GetConstructorObject(aCx, aGlobal) || !MessagePortBinding::GetConstructorObject(aCx, aGlobal) || + (PromiseBinding::ConstructorEnabled(aCx, aGlobal) && + !PromiseBinding::GetConstructorObject(aCx, aGlobal)) || !TextDecoderBinding::GetConstructorObject(aCx, aGlobal) || !TextEncoderBinding::GetConstructorObject(aCx, aGlobal) || !XMLHttpRequestBinding_workers::GetConstructorObject(aCx, aGlobal) || @@ -77,4 +80,4 @@ WorkerPrivate::RegisterBindings(JSContext* aCx, JS::Handle aGlobal) } return true; -} \ No newline at end of file +} diff --git a/dom/workers/test/mochitest.ini b/dom/workers/test/mochitest.ini index ce42a9cb05d8..d13b71239381 100644 --- a/dom/workers/test/mochitest.ini +++ b/dom/workers/test/mochitest.ini @@ -27,6 +27,7 @@ support-files = multi_sharedWorker_sharedWorker.js navigator_worker.js newError_worker.js + promise_worker.js recursion_worker.js recursiveOnerror_worker.js relativeLoad_import.js @@ -83,6 +84,7 @@ support-files = [test_multi_sharedWorker_lifetimes.html] [test_navigator.html] [test_newError.html] +[test_promise.html] [test_recursion.html] [test_recursiveOnerror.html] [test_relativeLoad.html] diff --git a/dom/workers/test/promise_worker.js b/dom/workers/test/promise_worker.js new file mode 100644 index 000000000000..d89b41d24b12 --- /dev/null +++ b/dom/workers/test/promise_worker.js @@ -0,0 +1,395 @@ +function ok(a, msg) { + dump("OK: " + !!a + " => " + a + " " + msg + "\n"); + postMessage({type: 'status', status: !!a, msg: a + ": " + msg }); +} + +function is(a, b, msg) { + dump("IS: " + (a===b) + " => " + a + " | " + b + " " + msg + "\n"); + postMessage({type: 'status', status: a === b, msg: a + " === " + b + ": " + msg }); +} + +function isnot(a, b, msg) { + dump("ISNOT: " + (a!==b) + " => " + a + " | " + b + " " + msg + "\n"); + postMessage({type: 'status', status: a !== b, msg: a + " !== " + b + ": " + msg }); +} + +function promiseResolve() { + ok(Promise, "Promise object should exist"); + + var promise = new Promise(function(resolve, reject) { + ok(resolve, "Promise.resolve exists"); + ok(reject, "Promise.reject exists"); + + resolve(42); + }).then(function(what) { + ok(true, "Then - resolveCb has been called"); + is(what, 42, "ResolveCb received 42"); + runTest(); + }, function() { + ok(false, "Then - rejectCb has been called"); + runTest(); + }); +} + + +function promiseReject() { + var promise = new Promise(function(resolve, reject) { + reject(42); + }).then(function(what) { + ok(false, "Then - resolveCb has been called"); + runTest(); + }, function(what) { + ok(true, "Then - rejectCb has been called"); + is(what, 42, "RejectCb received 42"); + runTest(); + }); +} + +function promiseException() { + var promise = new Promise(function(resolve, reject) { + throw 42; + }).then(function(what) { + ok(false, "Then - resolveCb has been called"); + runTest(); + }, function(what) { + ok(true, "Then - rejectCb has been called"); + is(what, 42, "RejectCb received 42"); + runTest(); + }); +} + +function promiseAsync() { + var global = "foo"; + var f = new Promise(function(r1, r2) { + is(global, "foo", "Global should be foo"); + r1(42); + is(global, "foo", "Global should still be foo"); + setTimeout(function() { + is(global, "bar", "Global should still be bar!"); + runTest(); + }, 0); + }).then(function() { + global = "bar"; + }); + is(global, "foo", "Global should still be foo (2)"); +} + +function promiseDoubleThen() { + var steps = 0; + var promise = new Promise(function(r1, r2) { + r1(42); + }); + + promise.then(function(what) { + ok(true, "Then.resolve has been called"); + is(what, 42, "Value == 42"); + steps++; + }, function(what) { + ok(false, "Then.reject has been called"); + }); + + promise.then(function(what) { + ok(true, "Then.resolve has been called"); + is(steps, 1, "Then.resolve - step == 1"); + is(what, 42, "Value == 42"); + runTest(); + }, function(what) { + ok(false, "Then.reject has been called"); + }); +} + +function promiseThenException() { + var promise = new Promise(function(resolve, reject) { + resolve(42); + }); + + promise.then(function(what) { + ok(true, "Then.resolve has been called"); + throw "booh"; + }).catch(function(e) { + ok(true, "Catch has been called!"); + runTest(); + }); +} + +function promiseThenCatchThen() { + var promise = new Promise(function(resolve, reject) { + resolve(42); + }); + + var promise2 = promise.then(function(what) { + ok(true, "Then.resolve has been called"); + is(what, 42, "Value == 42"); + return what + 1; + }, function(what) { + ok(false, "Then.reject has been called"); + }); + + isnot(promise, promise2, "These 2 promise objs are different"); + + promise2.then(function(what) { + ok(true, "Then.resolve has been called"); + is(what, 43, "Value == 43"); + return what + 1; + }, function(what) { + ok(false, "Then.reject has been called"); + }).catch(function() { + ok(false, "Catch has been called"); + }).then(function(what) { + ok(true, "Then.resolve has been called"); + is(what, 44, "Value == 44"); + runTest(); + }, function(what) { + ok(false, "Then.reject has been called"); + }); +} + +function promiseRejectThenCatchThen() { + var promise = new Promise(function(resolve, reject) { + reject(42); + }); + + var promise2 = promise.then(function(what) { + ok(false, "Then.resolve has been called"); + }, function(what) { + ok(true, "Then.reject has been called"); + is(what, 42, "Value == 42"); + return what + 1; + }); + + isnot(promise, promise2, "These 2 promise objs are different"); + + promise2.then(function(what) { + ok(true, "Then.resolve has been called"); + is(what, 43, "Value == 43"); + return what+1; + }).catch(function(what) { + ok(false, "Catch has been called"); + }).then(function(what) { + ok(true, "Then.resolve has been called"); + is(what, 44, "Value == 44"); + runTest(); + }); +} + +function promiseRejectThenCatchThen2() { + var promise = new Promise(function(resolve, reject) { + reject(42); + }); + + promise.then(function(what) { + ok(true, "Then.resolve has been called"); + is(what, 42, "Value == 42"); + return what+1; + }).catch(function(what) { + is(what, 42, "Value == 42"); + ok(true, "Catch has been called"); + return what+1; + }).then(function(what) { + ok(true, "Then.resolve has been called"); + is(what, 43, "Value == 43"); + runTest(); + }); +} + +function promiseRejectThenCatchExceptionThen() { + var promise = new Promise(function(resolve, reject) { + reject(42); + }); + + promise.then(function(what) { + ok(false, "Then.resolve has been called"); + }, function(what) { + ok(true, "Then.reject has been called"); + is(what, 42, "Value == 42"); + throw(what + 1); + }).catch(function(what) { + ok(true, "Catch has been called"); + is(what, 43, "Value == 43"); + return what + 1; + }).then(function(what) { + ok(true, "Then.resolve has been called"); + is(what, 44, "Value == 44"); + runTest(); + }); +} + +function promiseThenCatchOrderingResolve() { + var global = 0; + var f = new Promise(function(r1, r2) { + r1(42); + }); + + f.then(function() { + f.then(function() { + global++; + }); + f.catch(function() { + global++; + }); + f.then(function() { + global++; + }); + setTimeout(function() { + is(global, 2, "Many steps... should return 2"); + runTest(); + }, 0); + }); +} + +function promiseThenCatchOrderingReject() { + var global = 0; + var f = new Promise(function(r1, r2) { + r2(42); + }) + + f.then(function() {}, function() { + f.then(function() { + global++; + }); + f.catch(function() { + global++; + }); + f.then(function() {}, function() { + global++; + }); + setTimeout(function() { + is(global, 2, "Many steps... should return 2"); + runTest(); + }, 0); + }); +} + +function promiseNestedPromise() { + new Promise(function(resolve, reject) { + resolve(new Promise(function(resolve, reject) { + ok(true, "Nested promise is executed"); + resolve(42); + })); + }).then(function(value) { + is(value, 42, "Nested promise is executed and then == 42"); + runTest(); + }); +} + +function promiseNestedNestedPromise() { + new Promise(function(resolve, reject) { + resolve(new Promise(function(resolve, reject) { + ok(true, "Nested promise is executed"); + resolve(42); + }).then(function(what) { return what+1; })); + }).then(function(value) { + is(value, 43, "Nested promise is executed and then == 43"); + runTest(); + }); +} + +function promiseWrongNestedPromise() { + new Promise(function(resolve, reject) { + resolve(new Promise(function(r, r2) { + ok(true, "Nested promise is executed"); + r(42); + })); + reject(42); + }).then(function(value) { + is(value, 42, "Nested promise is executed and then == 42"); + runTest(); + }, function(value) { + ok(false, "This is wrong"); + }); +} + +function promiseLoop() { + new Promise(function(resolve, reject) { + resolve(new Promise(function(r1, r2) { + ok(true, "Nested promise is executed"); + r1(new Promise(function(r1, r2) { + ok(true, "Nested nested promise is executed"); + r1(42); + })); + })); + }).then(function(value) { + is(value, 42, "Nested nested promise is executed and then == 42"); + runTest(); + }, function(value) { + ok(false, "This is wrong"); + }); +} + +function promiseStaticReject() { + var promise = Promise.reject(42).then(function(what) { + ok(false, "This should not be called"); + }, function(what) { + is(what, 42, "Value == 42"); + runTest(); + }); +} + +function promiseStaticResolve() { + var promise = Promise.resolve(42).then(function(what) { + is(what, 42, "Value == 42"); + runTest(); + }, function() { + ok(false, "This should not be called"); + }); +} + +function promiseResolveNestedPromise() { + var promise = Promise.resolve(new Promise(function(r, r2) { + ok(true, "Nested promise is executed"); + r(42); + }, function() { + ok(false, "This should not be called"); + })).then(function(what) { + is(what, 42, "Value == 42"); + runTest(); + }, function() { + ok(false, "This should not be called"); + }); +} + +function promiseRejectNoHandler() { + // This test only checks that the code that reports unhandled errors in the + // Promises implementation does not crash or leak. + var promise = new Promise(function(res, rej) { + noSuchMethod(); + }); + runTest(); +} + +var tests = [ + promiseResolve, + promiseReject, + promiseException, + promiseAsync, + promiseDoubleThen, + promiseThenException, + promiseThenCatchThen, + promiseRejectThenCatchThen, + promiseRejectThenCatchThen2, + promiseRejectThenCatchExceptionThen, + promiseThenCatchOrderingResolve, + promiseThenCatchOrderingReject, + promiseNestedPromise, + promiseNestedNestedPromise, + promiseWrongNestedPromise, + promiseLoop, + promiseStaticReject, + promiseStaticResolve, + promiseResolveNestedPromise, + promiseRejectNoHandler, +]; + +function runTest() { + if (!tests.length) { + postMessage({ type: 'finish' }); + return; + } + + var test = tests.shift(); + test(); +} + +onmessage = function() { + runTest(); +} diff --git a/dom/workers/test/test_promise.html b/dom/workers/test/test_promise.html new file mode 100644 index 000000000000..4548072c7080 --- /dev/null +++ b/dom/workers/test/test_promise.html @@ -0,0 +1,44 @@ + + + + + Test for Promise object in workers + + + + +

    + +
    
    +
    +
    +
    +
    +
    
    From c87ac54a6235d32e91610e9f39b30832086b5627 Mon Sep 17 00:00:00 2001
    From: Eddy Bruel 
    Date: Wed, 6 Nov 2013 20:04:12 +0100
    Subject: [PATCH 15/82] Bug 927116 - Implement parser support for import
     declarations; r=jorendorff
    
    ---
     js/src/frontend/BytecodeEmitter.cpp |   5 ++
     js/src/frontend/FullParseHandler.h  |  10 +++
     js/src/frontend/ParseNode.h         |   3 +
     js/src/frontend/Parser.cpp          | 130 ++++++++++++++++++++++++++++
     js/src/frontend/Parser.h            |   1 +
     js/src/js.msg                       |  10 +++
     js/src/vm/CommonPropertyNames.h     |   3 +
     js/src/vm/Keywords.h                |   2 +-
     8 files changed, 163 insertions(+), 1 deletion(-)
    
    diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
    index 4de784ea04be..a078a94b681a 100644
    --- a/js/src/frontend/BytecodeEmitter.cpp
    +++ b/js/src/frontend/BytecodeEmitter.cpp
    @@ -6447,6 +6447,11 @@ frontend::EmitTree(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
                  : EmitVariables(cx, bce, pn, InitializeVars);
             break;
     
    +      case PNK_IMPORT:
    +       // TODO: Implement emitter support for modules
    +       bce->reportError(nullptr, JSMSG_MODULES_NOT_IMPLEMENTED);
    +       return false;
    +
           case PNK_ARRAYPUSH: {
             int slot;
     
    diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h
    index 7bde5f46eca9..b638d76daeff 100644
    --- a/js/src/frontend/FullParseHandler.h
    +++ b/js/src/frontend/FullParseHandler.h
    @@ -295,6 +295,16 @@ class FullParseHandler
             return new_(PNK_SEMI, JSOP_NOP, pos, (ParseNode *) nullptr);
         }
     
    +    ParseNode *newImportDeclaration(ParseNode *importSpecSet,
    +                                    ParseNode *moduleSpec, const TokenPos &pos)
    +    {
    +        ParseNode *pn = new_(PNK_IMPORT, JSOP_NOP, pos,
    +                                         importSpecSet, moduleSpec);
    +        if (!pn)
    +            return null();
    +        return pn;
    +    }
    +
         ParseNode *newExprStatement(ParseNode *expr, uint32_t end) {
             JS_ASSERT(expr->pn_pos.end <= end);
             return new_(PNK_SEMI, JSOP_NOP, TokenPos(expr->pn_pos.begin, end), expr);
    diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h
    index bb981cb8cbaf..4b8cb1bf7943 100644
    --- a/js/src/frontend/ParseNode.h
    +++ b/js/src/frontend/ParseNode.h
    @@ -128,6 +128,9 @@ class UpvarCookie
         F(ARRAYPUSH) \
         F(LEXICALSCOPE) \
         F(LET) \
    +    F(IMPORT) \
    +    F(IMPORT_SPEC_LIST) \
    +    F(IMPORT_SPEC) \
         F(SEQ) \
         F(FORIN) \
         F(FOROF) \
    diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
    index 0cb25dbac7e3..d191d17b8ffe 100644
    --- a/js/src/frontend/Parser.cpp
    +++ b/js/src/frontend/Parser.cpp
    @@ -3628,6 +3628,134 @@ Parser::letStatement()
         return SyntaxParseHandler::NodeFailure;
     }
     
    +template
    +typename ParseHandler::Node
    +Parser::importDeclaration()
    +{
    +    JS_ASSERT(tokenStream.currentToken().type == TOK_IMPORT);
    +
    +    if (pc->sc->isFunctionBox() || !pc->atBodyLevel()) {
    +        report(ParseError, false, null(), JSMSG_IMPORT_DECL_AT_TOP_LEVEL);
    +        return null();
    +    }
    +
    +    uint32_t begin = pos().begin;
    +    TokenKind tt = tokenStream.getToken();
    +
    +    Node importSpecSet = handler.newList(PNK_IMPORT_SPEC_LIST);
    +    if (!importSpecSet)
    +        return null();
    +
    +    if (tt == TOK_NAME || tt == TOK_LC) {
    +        if (tt == TOK_NAME) {
    +            // Handle the form |import a from 'b'|, by adding a single import
    +            // specifier to the list, with 'default' as the import name and
    +            // 'a' as the binding name. This is equivalent to
    +            // |import { default as a } from 'b'|.
    +            Node importName = newName(context->names().default_);
    +            if (!importName)
    +                return null();
    +
    +            Node bindingName = newName(tokenStream.currentName());
    +            if (!bindingName)
    +                return null();
    +
    +            Node importSpec = handler.newBinary(PNK_IMPORT_SPEC, importName, bindingName);
    +            if (!importSpec)
    +                return null();
    +
    +            handler.addList(importSpecSet, importSpec);
    +        } else {
    +            do {
    +                // Handle the forms |import {} from 'a'| and
    +                // |import { ..., } from 'a'| (where ... is non empty), by
    +                // escaping the loop early if the next token is }.
    +                tt = tokenStream.peekToken(TokenStream::KeywordIsName);
    +                if (tt == TOK_ERROR)
    +                    return null();
    +                if (tt == TOK_RC)
    +                    break;
    +
    +                // If the next token is a keyword, the previous call to
    +                // peekToken matched it as a TOK_NAME, and put it in the
    +                // lookahead buffer, so this call will match keywords as well.
    +                MUST_MATCH_TOKEN(TOK_NAME, JSMSG_NO_IMPORT_NAME);
    +                Node importName = newName(tokenStream.currentName());
    +                if (!importName)
    +                    return null();
    +
    +                if (tokenStream.getToken() == TOK_NAME &&
    +                    tokenStream.currentName() == context->names().as)
    +                {
    +                    if (tokenStream.getToken() != TOK_NAME) {
    +                        report(ParseError, false, null(), JSMSG_NO_BINDING_NAME);
    +                        return null();
    +                    }
    +                } else {
    +                    // Keywords cannot be bound to themselves, so an import name
    +                    // that is a keyword is a syntax error if it is not followed
    +                    // by the keyword 'as'.
    +                    if (IsKeyword(importName->name())) {
    +                        JSAutoByteString bytes;
    +                        if (!AtomToPrintableString(context, importName->name(), &bytes))
    +                            return null();
    +                        report(ParseError, false, null(), JSMSG_AS_AFTER_RESERVED_WORD, bytes.ptr());
    +                        return null();
    +                    }
    +                    tokenStream.ungetToken();
    +                }
    +                Node bindingName = newName(tokenStream.currentName());
    +                if (!bindingName)
    +                    return null();
    +
    +                Node importSpec = handler.newBinary(PNK_IMPORT_SPEC, importName, bindingName);
    +                if (!importSpec)
    +                    return null();
    +
    +                handler.addList(importSpecSet, importSpec);
    +            } while (tokenStream.matchToken(TOK_COMMA));
    +
    +            MUST_MATCH_TOKEN(TOK_RC, JSMSG_RC_AFTER_IMPORT_SPEC_LIST);
    +        }
    +
    +        if (tokenStream.getToken() != TOK_NAME ||
    +            tokenStream.currentName() != context->names().from)
    +        {
    +            report(ParseError, false, null(), JSMSG_FROM_AFTER_IMPORT_SPEC_SET);
    +            return null();
    +        }
    +
    +        MUST_MATCH_TOKEN(TOK_STRING, JSMSG_MODULE_SPEC_AFTER_FROM);
    +    } else {
    +        if (tt != TOK_STRING) {
    +            report(ParseError, false, null(), JSMSG_DECLARATION_AFTER_IMPORT);
    +            return null();
    +        }
    +
    +        // Handle the form |import 'a'| by leaving the list empty. This is
    +        // equivalent to |import {} from 'a'|.
    +        importSpecSet->pn_pos.end = importSpecSet->pn_pos.begin;
    +    }
    +
    +    Node moduleSpec = stringLiteral();
    +    if (!moduleSpec)
    +        return null();
    +
    +    if (!MatchOrInsertSemicolon(tokenStream))
    +        return null();
    +
    +    return handler.newImportDeclaration(importSpecSet, moduleSpec,
    +                                        TokenPos(begin, pos().end));
    +}
    +
    +template<>
    +SyntaxParseHandler::Node
    +Parser::importDeclaration()
    +{
    +    JS_ALWAYS_FALSE(abortIfSyntaxParser());
    +    return SyntaxParseHandler::NodeFailure;
    +}
    +
     template 
     typename ParseHandler::Node
     Parser::expressionStatement()
    @@ -4907,6 +5035,8 @@ Parser::statement(bool canHaveDirectives)
     
           case TOK_LET:
             return letStatement();
    +      case TOK_IMPORT:
    +        return importDeclaration();
           case TOK_SEMI:
             return handler.newEmptyStatement(pos());
           case TOK_IF:
    diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h
    index 2de501307e5b..119a6892d434 100644
    --- a/js/src/frontend/Parser.h
    +++ b/js/src/frontend/Parser.h
    @@ -512,6 +512,7 @@ class Parser : private AutoGCRooter, public StrictModeGetter
         Node debuggerStatement();
     
         Node letStatement();
    +    Node importDeclaration();
         Node expressionStatement();
         Node variables(ParseNodeKind kind, bool *psimple = nullptr,
                        StaticBlockObject *blockObj = nullptr,
    diff --git a/js/src/js.msg b/js/src/js.msg
    index 15986cd569c7..8bd4f8bd0556 100644
    --- a/js/src/js.msg
    +++ b/js/src/js.msg
    @@ -417,3 +417,13 @@ MSG_DEF(JSMSG_TYPEDOBJECT_NO_SUCH_PROP, 363, 1, JSEXN_TYPEERR, "No such property
     MSG_DEF(JSMSG_TYPEDOBJECT_HANDLE_BAD_ARGS, 364, 2, JSEXN_TYPEERR, "argument {0} invalid: expected {1}")
     MSG_DEF(JSMSG_TYPEDOBJECT_HANDLE_UNATTACHED, 365, 0, JSEXN_TYPEERR, "handle unattached")
     MSG_DEF(JSMSG_TYPEDOBJECT_HANDLE_BAD_TYPE, 366, 0, JSEXN_TYPEERR, "handle moved to destination of incorrect type")
    +
    +MSG_DEF(JSMSG_IMPORT_DECL_AT_TOP_LEVEL, 367, 0, JSEXN_SYNTAXERR, "import declarations may only appear at top level")
    +MSG_DEF(JSMSG_NO_IMPORT_NAME,         368, 0, JSEXN_SYNTAXERR, "missing import name")
    +MSG_DEF(JSMSG_AS_AFTER_RESERVED_WORD, 369, 1, JSEXN_SYNTAXERR, "missing keyword 'as' after reserved word '{0}'")
    +MSG_DEF(JSMSG_NO_BINDING_NAME,	      370, 0, JSEXN_SYNTAXERR, "missing binding name")
    +MSG_DEF(JSMSG_RC_AFTER_IMPORT_SPEC_LIST, 371, 0, JSEXN_SYNTAXERR, "missing '}' after module specifier list")
    +MSG_DEF(JSMSG_FROM_AFTER_IMPORT_SPEC_SET, 372, 0, JSEXN_SYNTAXERR, "missing keyword 'from' after import specifier set")
    +MSG_DEF(JSMSG_DECLARATION_AFTER_IMPORT, 373, 0, JSEXN_SYNTAXERR, "missing declaration after 'import' keyword")
    +MSG_DEF(JSMSG_MODULE_SPEC_AFTER_FROM,   374, 0, JSEXN_SYNTAXERR, "missing module specifier after 'from' keyword")
    +MSG_DEF(JSMSG_MODULES_NOT_IMPLEMENTED,  375, 0, JSEXN_SYNTAXERR, "modules are not implemented yet")
    diff --git a/js/src/vm/CommonPropertyNames.h b/js/src/vm/CommonPropertyNames.h
    index f4f3e03ba8bd..6406291bfa6b 100644
    --- a/js/src/vm/CommonPropertyNames.h
    +++ b/js/src/vm/CommonPropertyNames.h
    @@ -15,6 +15,7 @@
         macro(anonymous, anonymous, "anonymous") \
         macro(apply, apply, "apply") \
         macro(arguments, arguments, "arguments") \
    +    macro(as, as, "as") \
         macro(ArrayType, ArrayType, "ArrayType") \
         macro(buffer, buffer, "buffer") \
         macro(builder, builder, "builder") \
    @@ -43,6 +44,7 @@
         macro(DateTimeFormatFormatGet, DateTimeFormatFormatGet, "Intl_DateTimeFormat_format_get") \
         macro(decodeURI, decodeURI, "decodeURI") \
         macro(decodeURIComponent, decodeURIComponent, "decodeURIComponent") \
    +    macro(default_, default_, "default") \
         macro(defineProperty, defineProperty, "defineProperty") \
         macro(defineGetter, defineGetter, "__defineGetter__") \
         macro(defineSetter, defineSetter, "__defineSetter__") \
    @@ -68,6 +70,7 @@
         macro(float32, float32, "float32") \
         macro(float64, float64, "float64") \
         macro(format, format, "format") \
    +    macro(from, from, "from") \
         macro(get, get, "get") \
         macro(getInternals, getInternals, "getInternals") \
         macro(getOwnPropertyDescriptor, getOwnPropertyDescriptor, "getOwnPropertyDescriptor") \
    diff --git a/js/src/vm/Keywords.h b/js/src/vm/Keywords.h
    index f1d7211b2029..a6c867e79214 100644
    --- a/js/src/vm/Keywords.h
    +++ b/js/src/vm/Keywords.h
    @@ -41,12 +41,12 @@
         macro(void, void_, TOK_VOID, JSVERSION_DEFAULT) \
         macro(while, while_, TOK_WHILE, JSVERSION_DEFAULT) \
         macro(with, with, TOK_WITH, JSVERSION_DEFAULT) \
    +    macro(import, import, TOK_IMPORT, JSVERSION_DEFAULT) \
         /* Reserved keywords. */ \
         macro(class, class_, TOK_RESERVED, JSVERSION_DEFAULT) \
         macro(enum, enum_, TOK_RESERVED, JSVERSION_DEFAULT) \
         macro(export, export, TOK_RESERVED, JSVERSION_DEFAULT) \
         macro(extends, extends, TOK_RESERVED, JSVERSION_DEFAULT) \
    -    macro(import, import, TOK_RESERVED, JSVERSION_DEFAULT) \
         macro(super, super, TOK_RESERVED, JSVERSION_DEFAULT) \
         /* Future reserved keywords, but only in strict mode. */ \
         macro(implements, implements, TOK_STRICT_RESERVED, JSVERSION_DEFAULT) \
    
    From d9f31784a51db420d8b1fbe411f0dac58a86fe9e Mon Sep 17 00:00:00 2001
    From: Eddy Bruel 
    Date: Wed, 6 Nov 2013 20:04:45 +0100
    Subject: [PATCH 16/82] Bug 927116 - Implement reflect support for import
     declarations; r=jorendorff
    
    ---
     js/src/jsast.tbl     |  2 ++
     js/src/jsreflect.cpp | 76 ++++++++++++++++++++++++++++++++++++++++++++
     2 files changed, 78 insertions(+)
    
    diff --git a/js/src/jsast.tbl b/js/src/jsast.tbl
    index bcfb6907b634..4e2aa4daedb6 100644
    --- a/js/src/jsast.tbl
    +++ b/js/src/jsast.tbl
    @@ -57,6 +57,8 @@ ASTDEF(AST_TRY_STMT,              "TryStatement",                   "tryStatemen
     ASTDEF(AST_THROW_STMT,            "ThrowStatement",                 "throwStatement")
     ASTDEF(AST_DEBUGGER_STMT,         "DebuggerStatement",              "debuggerStatement")
     ASTDEF(AST_LET_STMT,              "LetStatement",                   "letStatement")
    +ASTDEF(AST_IMPORT_DECL,           "ImportDeclaration",              "importDeclaration")
    +ASTDEF(AST_IMPORT_SPEC,           "ImportSpecifier",                "importSpecifier")
     
     ASTDEF(AST_CASE,                  "SwitchCase",                     "switchCase")
     ASTDEF(AST_CATCH,                 "CatchClause",                    "catchClause")
    diff --git a/js/src/jsreflect.cpp b/js/src/jsreflect.cpp
    index 34baac115ca4..7cf7f2fd0a79 100644
    --- a/js/src/jsreflect.cpp
    +++ b/js/src/jsreflect.cpp
    @@ -562,6 +562,10 @@ class NodeBuilder
     
         bool letStatement(NodeVector &head, HandleValue stmt, TokenPos *pos, MutableHandleValue dst);
     
    +    bool importDeclaration(NodeVector &elts, HandleValue moduleSpec, TokenPos *pos, MutableHandleValue dst);
    +
    +    bool importSpecifier(HandleValue importName, HandleValue bindingName, TokenPos *pos, MutableHandleValue dst);
    +
         /*
          * expressions
          */
    @@ -1353,6 +1357,38 @@ NodeBuilder::letStatement(NodeVector &head, HandleValue stmt, TokenPos *pos, Mut
                        dst);
     }
     
    +bool
    +NodeBuilder::importDeclaration(NodeVector &elts, HandleValue moduleSpec, TokenPos *pos,
    +                               MutableHandleValue dst)
    +{
    +    RootedValue array(cx);
    +    if (!newArray(elts, &array))
    +        return false;
    +
    +    RootedValue cb(cx, callbacks[AST_IMPORT_DECL]);
    +    if (!cb.isNull())
    +        return callback(cb, array, moduleSpec, pos, dst);
    +
    +    return newNode(AST_IMPORT_DECL, pos,
    +                   "specifiers", array,
    +                   "source", moduleSpec,
    +                   dst);
    +}
    +
    +bool
    +NodeBuilder::importSpecifier(HandleValue importName, HandleValue bindingName, TokenPos *pos,
    +                             MutableHandleValue dst)
    +{
    +    RootedValue cb(cx, callbacks[AST_IMPORT_SPEC]);
    +    if (!cb.isNull())
    +        return callback(cb, importName, bindingName, pos, dst);
    +
    +    return newNode(AST_IMPORT_SPEC, pos,
    +                   "id", importName,
    +                   "name", bindingName,
    +                   dst);
    +}
    +
     bool
     NodeBuilder::variableDeclaration(NodeVector &elts, VarDeclKind kind, TokenPos *pos,
                                      MutableHandleValue dst)
    @@ -1520,6 +1556,8 @@ class ASTSerializer
         bool variableDeclaration(ParseNode *pn, bool let, MutableHandleValue dst);
         bool variableDeclarator(ParseNode *pn, VarDeclKind *pkind, MutableHandleValue dst);
         bool let(ParseNode *pn, bool expr, MutableHandleValue dst);
    +    bool importDeclaration(ParseNode *pn, MutableHandleValue dst);
    +    bool importSpecifier(ParseNode *pn, MutableHandleValue dst);
     
         bool optStatement(ParseNode *pn, MutableHandleValue dst) {
             if (!pn) {
    @@ -1883,6 +1921,41 @@ ASTSerializer::let(ParseNode *pn, bool expr, MutableHandleValue dst)
                  builder.letStatement(dtors, v, &pn->pn_pos, dst);
     }
     
    +bool
    +ASTSerializer::importDeclaration(ParseNode *pn, MutableHandleValue dst)
    +{
    +    JS_ASSERT(pn->isKind(PNK_IMPORT));
    +    JS_ASSERT(pn->pn_left->isKind(PNK_IMPORT_SPEC_LIST));
    +    JS_ASSERT(pn->pn_right->isKind(PNK_STRING));
    +
    +    NodeVector elts(cx);
    +    if (!elts.reserve(pn->pn_count))
    +        return false;
    +
    +    for (ParseNode *next = pn->pn_left->pn_head; next; next = next->pn_next) {
    +        RootedValue elt(cx);
    +        if (!importSpecifier(next, &elt))
    +            return false;
    +        elts.infallibleAppend(elt);
    +    }
    +
    +    RootedValue moduleSpec(cx);
    +    return literal(pn->pn_right, &moduleSpec) &&
    +           builder.importDeclaration(elts, moduleSpec, &pn->pn_pos, dst);
    +}
    +
    +bool
    +ASTSerializer::importSpecifier(ParseNode *pn, MutableHandleValue dst)
    +{
    +    JS_ASSERT(pn->isKind(PNK_IMPORT_SPEC));
    +
    +    RootedValue importName(cx);
    +    RootedValue bindingName(cx);
    +    return identifier(pn->pn_left, &importName) &&
    +           identifier(pn->pn_right, &bindingName) &&
    +           builder.importSpecifier(importName, bindingName, &pn->pn_pos, dst);
    +}
    +
     bool
     ASTSerializer::switchCase(ParseNode *pn, MutableHandleValue dst)
     {
    @@ -2038,6 +2111,9 @@ ASTSerializer::statement(ParseNode *pn, MutableHandleValue dst)
                    ? let(pn, false, dst)
                    : declaration(pn, dst);
     
    +      case PNK_IMPORT:
    +        return importDeclaration(pn, dst);
    +
           case PNK_NAME:
             LOCAL_ASSERT(pn->isUsed());
             return statement(pn->pn_lexdef, dst);
    
    From 991aa5c90b3f4ce15310eaaee371649c661f57f3 Mon Sep 17 00:00:00 2001
    From: Eddy Bruel 
    Date: Wed, 6 Nov 2013 20:05:23 +0100
    Subject: [PATCH 17/82] Bug 927116 - Test reflect support for import
     declarations; r=jorendorff
    
    ---
     js/src/jit-test/lib/match.js                  |   1 +
     .../tests/modules/import-declaration.js       | 186 ++++++++++++++++++
     2 files changed, 187 insertions(+)
     create mode 100644 js/src/jit-test/lib/match.js
     create mode 100644 js/src/jit-test/tests/modules/import-declaration.js
    
    diff --git a/js/src/jit-test/lib/match.js b/js/src/jit-test/lib/match.js
    new file mode 100644
    index 000000000000..87d84688ecd4
    --- /dev/null
    +++ b/js/src/jit-test/lib/match.js
    @@ -0,0 +1 @@
    +loadRelativeToScript("../../tests/js1_8_5/extensions/shell.js");
    diff --git a/js/src/jit-test/tests/modules/import-declaration.js b/js/src/jit-test/tests/modules/import-declaration.js
    new file mode 100644
    index 000000000000..54596359a92a
    --- /dev/null
    +++ b/js/src/jit-test/tests/modules/import-declaration.js
    @@ -0,0 +1,186 @@
    +load(libdir + "match.js");
    +load(libdir + "asserts.js");
    +
    +var { Pattern, MatchError } = Match;
    +
    +program = (elts) => Pattern({
    +    type: "Program",
    +    body: elts
    +})
    +importDeclaration = (specifiers, source) => Pattern({
    +    type: "ImportDeclaration",
    +    specifiers: specifiers,
    +    source: source
    +});
    +importSpecifier = (id, name) => Pattern({
    +    type: "ImportSpecifier",
    +    id: id,
    +    name: name
    +});
    +ident = (name) => Pattern({
    +    type: "Identifier",
    +    name: name
    +})
    +lit = (val) => Pattern({
    +    type: "Literal",
    +    value: val
    +})
    +
    +program([
    +    importDeclaration(
    +        [
    +            importSpecifier(
    +                ident("default"),
    +                ident("a")
    +            )
    +        ],
    +        lit("b")
    +    )
    +]).assert(Reflect.parse("import a from 'b'"));
    +
    +program([
    +    importDeclaration(
    +        [],
    +        lit("a")
    +    )
    +]).assert(Reflect.parse("import {} from 'a'"));
    +
    +program([
    +    importDeclaration(
    +        [
    +            importSpecifier(
    +                ident("a"),
    +                ident("a")
    +            )
    +        ],
    +        lit("b")
    +    )
    +]).assert(Reflect.parse("import { a } from 'b'"));
    +
    +program([
    +    importDeclaration(
    +        [
    +            importSpecifier(
    +                ident("a"),
    +                ident("a")
    +            )
    +        ],
    +        lit("b")
    +    )
    +]).assert(Reflect.parse("import { a, } from 'b'"));
    +
    +program([
    +    importDeclaration(
    +        [
    +            importSpecifier(
    +                ident("a"),
    +                ident("b")
    +            )
    +        ],
    +        lit("c")
    +    )
    +]).assert(Reflect.parse("import { a as b } from 'c'"));
    +
    +program([
    +    importDeclaration(
    +        [
    +            importSpecifier(
    +                ident("as"),
    +                ident("as")
    +            )
    +        ],
    +        lit("a")
    +    )
    +]).assert(Reflect.parse("import { as as as } from 'a'"));
    +
    +program([
    +    importDeclaration(
    +        [
    +            importSpecifier(
    +                ident("true"),
    +                ident("a")
    +            )
    +        ],
    +        lit("b")
    +    )
    +]).assert(Reflect.parse("import { true as a } from 'b'"));
    +
    +program([
    +    importDeclaration(
    +        [
    +            importSpecifier(
    +                ident("a"),
    +                ident("a")
    +            ),
    +            importSpecifier(
    +                ident("b"),
    +                ident("b")
    +            ),
    +        ],
    +        lit("c")
    +    )
    +]).assert(Reflect.parse("import { a, b } from 'c'"));
    +
    +program([
    +    importDeclaration(
    +        [
    +            importSpecifier(
    +                ident("a"),
    +                ident("b")
    +            ),
    +            importSpecifier(
    +                ident("c"),
    +                ident("d")
    +            ),
    +        ],
    +        lit("e")
    +    )
    +]).assert(Reflect.parse("import { a as b, c as d } from 'e'"));
    +
    +program([
    +    importDeclaration(
    +        [],
    +        lit("a")
    +    )
    +]).assert(Reflect.parse("import 'a'"));
    +
    +var loc = Reflect.parse("import { a as b } from 'c'", {
    +    loc: true
    +}).body[0].loc;
    +
    +assertEq(loc.start.line, 1);
    +assertEq(loc.start.column, 0);
    +assertEq(loc.start.line, 1);
    +assertEq(loc.end.column, 26);
    +
    +assertThrowsInstanceOf(function () {
    +   Reflect.parse("function f() { import a from 'b' }");
    +}, SyntaxError);
    +
    +assertThrowsInstanceOf(function () {
    +   Reflect.parse("if (true) import a from 'b'");
    +}, SyntaxError);
    +
    +assertThrowsInstanceOf(function() {
    +    Reflect.parse("import {");
    +}, SyntaxError);
    +
    +assertThrowsInstanceOf(function() {
    +    Reflect.parse("import {}");
    +}, SyntaxError);
    +
    +assertThrowsInstanceOf(function() {
    +    Reflect.parse("import {} from");
    +}, SyntaxError);
    +
    +assertThrowsInstanceOf(function() {
    +    Reflect.parse("import {,} from 'a'");
    +}, SyntaxError);
    +
    +assertThrowsInstanceOf(function() {
    +    Reflect.parse("import { a as true } from 'b'");
    +}, SyntaxError);
    +
    +assertThrowsInstanceOf(function() {
    +    Reflect.parse("import { true } from 'a'");
    +}, SyntaxError);
    
    From d89f0d8a75897e3d784ae031b6ca2d0762bd8046 Mon Sep 17 00:00:00 2001
    From: Matt Woodrow 
    Date: Thu, 7 Nov 2013 08:10:49 +1300
    Subject: [PATCH 18/82] Bug 934860 - Start and finish transactions with
     temporary layer managers each time we use them to ensure that these are
     paired. r=roc
    
    ---
     layout/base/FrameLayerBuilder.cpp | 12 ++++--------
     layout/base/FrameLayerBuilder.h   |  6 ++++--
     2 files changed, 8 insertions(+), 10 deletions(-)
    
    diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp
    index 7966d965e6a4..bcab98eda224 100644
    --- a/layout/base/FrameLayerBuilder.cpp
    +++ b/layout/base/FrameLayerBuilder.cpp
    @@ -1942,6 +1942,7 @@ PaintInactiveLayer(nsDisplayListBuilder* aBuilder,
         context = new gfxContext(surf);
       }
     #endif
    +  basic->BeginTransaction();
       basic->SetTarget(context);
     
       if (aItem->GetType() == nsDisplayItem::TYPE_SVG_EFFECTS) {
    @@ -2347,7 +2348,7 @@ FrameLayerBuilder::AddThebesDisplayItem(ThebesLayer* aLayer,
     {
       ThebesDisplayItemLayerUserData* thebesData =
         static_cast(aLayer->GetUserData(&gThebesDisplayItemLayerUserData));
    -  nsRefPtr tempManager;
    +  nsRefPtr tempManager;
       nsIntRect intClip;
       bool hasClip = false;
       if (aLayerState != LAYER_NONE) {
    @@ -2417,6 +2418,7 @@ FrameLayerBuilder::AddThebesDisplayItem(ThebesLayer* aLayer,
     
           tempManager->SetRoot(layer);
           layerBuilder->WillEndTransaction();
    +      tempManager->AbortTransaction();
     
           nsIntPoint offset = GetLastPaintOffset(aLayer) - GetTranslationForThebesLayer(aLayer);
           props->MoveBy(-offset);
    @@ -2506,13 +2508,7 @@ FrameLayerBuilder::StoreDataForFrame(nsIFrame* aFrame,
     FrameLayerBuilder::ClippedDisplayItem::~ClippedDisplayItem()
     {
       if (mInactiveLayerManager) {
    -    // We always start a transaction during layer construction for all inactive
    -    // layers, but we don't necessarily call EndTransaction during painting.
    -    // If the transaaction is still open, end it to avoid assertions.
         BasicLayerManager* basic = static_cast(mInactiveLayerManager.get());
    -    if (basic->InTransaction()) {
    -      basic->EndTransaction(nullptr, nullptr);
    -    }
         basic->SetUserData(&gLayerManagerLayerBuilder, nullptr);
       }
     }
    @@ -2523,7 +2519,7 @@ FrameLayerBuilder::AddLayerDisplayItem(Layer* aLayer,
                                            const DisplayItemClip& aClip,
                                            LayerState aLayerState,
                                            const nsPoint& aTopLeft,
    -                                       LayerManager* aManager,
    +                                       BasicLayerManager* aManager,
                                            nsAutoPtr aGeometry)
     {
       if (aLayer->Manager() != mRetainingManager)
    diff --git a/layout/base/FrameLayerBuilder.h b/layout/base/FrameLayerBuilder.h
    index 04b01955cd8f..9d62746a71d7 100644
    --- a/layout/base/FrameLayerBuilder.h
    +++ b/layout/base/FrameLayerBuilder.h
    @@ -24,6 +24,7 @@ namespace mozilla {
     namespace layers {
     class ContainerLayer;
     class LayerManager;
    +class BasicLayerManager;
     class ThebesLayer;
     }
     
    @@ -95,6 +96,7 @@ public:
       typedef layers::ThebesLayer ThebesLayer;
       typedef layers::ImageLayer ImageLayer;
       typedef layers::LayerManager LayerManager;
    +  typedef layers::BasicLayerManager BasicLayerManager;
     
       FrameLayerBuilder() :
         mRetainingManager(nullptr),
    @@ -273,7 +275,7 @@ public:
                                const DisplayItemClip& aClip,
                                LayerState aLayerState,
                                const nsPoint& aTopLeft,
    -                           LayerManager* aManager,
    +                           BasicLayerManager* aManager,
                                nsAutoPtr aGeometry);
     
       /**
    @@ -420,7 +422,7 @@ public:
         LayerManagerData* mParent;
         nsRefPtr mLayer;
         nsRefPtr mOptLayer;
    -    nsRefPtr mInactiveManager;
    +    nsRefPtr mInactiveManager;
         nsAutoTArray mFrameList;
         nsAutoPtr mGeometry;
         DisplayItemClip mClip;
    
    From 485862da70339297fc28a1605a37223da5aa1c1b Mon Sep 17 00:00:00 2001
    From: Matt Woodrow 
    Date: Thu, 7 Nov 2013 08:10:49 +1300
    Subject: [PATCH 19/82] Bug 934860 - Move some parts of
     FrameLayerBuilder::DrawThebesLayer into helper functions. r=roc
    
    ---
     layout/base/FrameLayerBuilder.cpp | 262 +++++++++++++++---------------
     layout/base/FrameLayerBuilder.h   |  15 ++
     2 files changed, 150 insertions(+), 127 deletions(-)
    
    diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp
    index bcab98eda224..16942e4fd3ff 100644
    --- a/layout/base/FrameLayerBuilder.cpp
    +++ b/layout/base/FrameLayerBuilder.cpp
    @@ -3110,6 +3110,132 @@ static void DebugPaintItem(nsRenderingContext* aDest, nsDisplayItem *aItem, nsDi
     }
     #endif
     
    +/* static */ void
    +FrameLayerBuilder::RecomputeVisibilityForItems(nsTArray& aItems,
    +                                               nsDisplayListBuilder *aBuilder,
    +                                               const nsIntRegion& aRegionToDraw,
    +                                               const nsIntPoint& aOffset,
    +                                               int32_t aAppUnitsPerDevPixel,
    +                                               float aXScale,
    +                                               float aYScale)
    +{
    +  uint32_t i;
    +  // Update visible regions. We need perform visibility analysis again
    +  // because we may be asked to draw into part of a ThebesLayer that
    +  // isn't actually visible in the window (e.g., because a ThebesLayer
    +  // expanded its visible region to a rectangle internally), in which
    +  // case the mVisibleRect stored in the display item may be wrong.
    +  nsRegion visible = aRegionToDraw.ToAppUnits(aAppUnitsPerDevPixel);
    +  visible.MoveBy(NSIntPixelsToAppUnits(aOffset.x, aAppUnitsPerDevPixel),
    +                 NSIntPixelsToAppUnits(aOffset.y, aAppUnitsPerDevPixel));
    +  visible.ScaleInverseRoundOut(aXScale, aYScale);
    +
    +  for (i = aItems.Length(); i > 0; --i) {
    +    ClippedDisplayItem* cdi = &aItems[i - 1];
    +    const DisplayItemClip& clip = cdi->mItem->GetClip();
    +
    +    NS_ASSERTION(AppUnitsPerDevPixel(cdi->mItem) == aAppUnitsPerDevPixel,
    +                 "a thebes layer should contain items only at the same zoom");
    +
    +    NS_ABORT_IF_FALSE(clip.HasClip() ||
    +                      clip.GetRoundedRectCount() == 0,
    +                      "If we have rounded rects, we must have a clip rect");
    +
    +    if (!clip.IsRectAffectedByClip(visible.GetBounds())) {
    +      cdi->mItem->RecomputeVisibility(aBuilder, &visible);
    +      continue;
    +    }
    +
    +    // Do a little dance to account for the fact that we're clipping
    +    // to cdi->mClipRect
    +    nsRegion clipped;
    +    clipped.And(visible, clip.NonRoundedIntersection());
    +    nsRegion finalClipped = clipped;
    +    cdi->mItem->RecomputeVisibility(aBuilder, &finalClipped);
    +    // If we have rounded clip rects, don't subtract from the visible
    +    // region since we aren't displaying everything inside the rect.
    +    if (clip.GetRoundedRectCount() == 0) {
    +      nsRegion removed;
    +      removed.Sub(clipped, finalClipped);
    +      nsRegion newVisible;
    +      newVisible.Sub(visible, removed);
    +      // Don't let the visible region get too complex.
    +      if (newVisible.GetNumRects() <= 15) {
    +        visible = newVisible;
    +      }
    +    }
    +  }
    +}
    +
    +void
    +FrameLayerBuilder::PaintItems(nsTArray& aItems,
    +                              gfxContext *aContext,
    +                              nsRenderingContext *aRC,
    +                              nsDisplayListBuilder* aBuilder,
    +                              nsPresContext* aPresContext,
    +                              int32_t aCommonClipCount)
    +{
    +  DisplayItemClip currentClip;
    +  bool currentClipIsSetInContext = false;
    +  DisplayItemClip tmpClip;
    +
    +  for (uint32_t i = 0; i < aItems.Length(); ++i) {
    +    ClippedDisplayItem* cdi = &aItems[i];
    +
    +    if (cdi->mItem->GetVisibleRect().IsEmpty())
    +      continue;
    +
    +    // If the new desired clip state is different from the current state,
    +    // update the clip.
    +    const DisplayItemClip* clip = &cdi->mItem->GetClip();
    +    if (clip->GetRoundedRectCount() > 0 &&
    +        !clip->IsRectClippedByRoundedCorner(cdi->mItem->GetVisibleRect())) {
    +      tmpClip = *clip;
    +      tmpClip.RemoveRoundedCorners();
    +      clip = &tmpClip;
    +    }
    +    if (currentClipIsSetInContext != clip->HasClip() ||
    +        (clip->HasClip() && *clip != currentClip)) {
    +      if (currentClipIsSetInContext) {
    +        aContext->Restore();
    +      }
    +      currentClipIsSetInContext = clip->HasClip();
    +      if (currentClipIsSetInContext) {
    +        currentClip = *clip;
    +        aContext->Save();
    +        NS_ASSERTION(aCommonClipCount < 100,
    +          "Maybe you really do have more than a hundred clipping rounded rects, or maybe something has gone wrong.");
    +        currentClip.ApplyTo(aContext, aPresContext, aCommonClipCount);
    +        aContext->NewPath();
    +      }
    +    }
    +
    +    if (cdi->mInactiveLayerManager) {
    +      PaintInactiveLayer(aBuilder, cdi->mInactiveLayerManager, cdi->mItem, aContext, aRC);
    +    } else {
    +      nsIFrame* frame = cdi->mItem->Frame();
    +      frame->AddStateBits(NS_FRAME_PAINTED_THEBES);
    +#ifdef MOZ_DUMP_PAINTING
    +
    +      if (gfxUtils::sDumpPainting) {
    +        DebugPaintItem(aRC, cdi->mItem, aBuilder);
    +      } else {
    +#else
    +      {
    +#endif
    +        cdi->mItem->Paint(aBuilder, aRC);
    +      }
    +    }
    +
    +    if (CheckDOMModified())
    +      break;
    +  }
    +
    +  if (currentClipIsSetInContext) {
    +    aContext->Restore();
    +  }
    +}
    +
     /*
      * A note on residual transforms:
      *
    @@ -3156,21 +3282,9 @@ FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer,
       if (layerBuilder->CheckDOMModified())
         return;
     
    -  nsTArray items;
    -  uint32_t commonClipCount;
    -  nsIFrame* containerLayerFrame;
    -  {
    -    ThebesLayerItemsEntry* entry = layerBuilder->mThebesLayerItems.GetEntry(aLayer);
    -    NS_ASSERTION(entry, "We shouldn't be drawing into a layer with no items!");
    -    items.SwapElements(entry->mItems);
    -    commonClipCount = entry->mCommonClipCount;
    -    containerLayerFrame = entry->mContainerLayerFrame;
    -    // Later after this point, due to calls to DidEndTransaction
    -    // for temporary layer managers, mThebesLayerItems can change,
    -    // so 'entry' could become invalid.
    -  }
    -
    -  if (!containerLayerFrame) {
    +  ThebesLayerItemsEntry* entry = layerBuilder->mThebesLayerItems.GetEntry(aLayer);
    +  NS_ASSERTION(entry, "We shouldn't be drawing into a layer with no items!");
    +  if (!entry->mContainerLayerFrame) {
         return;
       }
     
    @@ -3196,124 +3310,18 @@ FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer,
       aContext->Translate(aLayer->GetResidualTranslation() - gfxPoint(offset.x, offset.y));
       aContext->Scale(userData->mXScale, userData->mYScale);
     
    -  nsPresContext* presContext = containerLayerFrame->PresContext();
    +  nsPresContext* presContext = entry->mContainerLayerFrame->PresContext();
       int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
     
    -  uint32_t i;
    -  // Update visible regions. We need perform visibility analysis again
    -  // because we may be asked to draw into part of a ThebesLayer that
    -  // isn't actually visible in the window (e.g., because a ThebesLayer
    -  // expanded its visible region to a rectangle internally), in which
    -  // case the mVisibleRect stored in the display item may be wrong.
    -  nsRegion visible = aRegionToDraw.ToAppUnits(appUnitsPerDevPixel);
    -  visible.MoveBy(NSIntPixelsToAppUnits(offset.x, appUnitsPerDevPixel),
    -                 NSIntPixelsToAppUnits(offset.y, appUnitsPerDevPixel));
    -  visible.ScaleInverseRoundOut(userData->mXScale, userData->mYScale);
    -
    -  for (i = items.Length(); i > 0; --i) {
    -    ClippedDisplayItem* cdi = &items[i - 1];
    -    const DisplayItemClip& clip = cdi->mItem->GetClip();
    -
    -    NS_ASSERTION(AppUnitsPerDevPixel(cdi->mItem) == appUnitsPerDevPixel,
    -                 "a thebes layer should contain items only at the same zoom");
    -
    -    NS_ABORT_IF_FALSE(clip.HasClip() ||
    -                      clip.GetRoundedRectCount() == 0,
    -                      "If we have rounded rects, we must have a clip rect");
    -
    -    if (!clip.IsRectAffectedByClip(visible.GetBounds())) {
    -      cdi->mItem->RecomputeVisibility(builder, &visible);
    -      continue;
    -    }
    -
    -    // Do a little dance to account for the fact that we're clipping
    -    // to cdi->mClipRect
    -    nsRegion clipped;
    -    clipped.And(visible, clip.NonRoundedIntersection());
    -    nsRegion finalClipped = clipped;
    -    cdi->mItem->RecomputeVisibility(builder, &finalClipped);
    -    // If we have rounded clip rects, don't subtract from the visible
    -    // region since we aren't displaying everything inside the rect.
    -    if (clip.GetRoundedRectCount() == 0) {
    -      nsRegion removed;
    -      removed.Sub(clipped, finalClipped);
    -      nsRegion newVisible;
    -      newVisible.Sub(visible, removed);
    -      // Don't let the visible region get too complex.
    -      if (newVisible.GetNumRects() <= 15) {
    -        visible = newVisible;
    -      }
    -    }
    -  }
    +  RecomputeVisibilityForItems(entry->mItems, builder, aRegionToDraw,
    +                              offset, appUnitsPerDevPixel,
    +                              userData->mXScale, userData->mYScale);
     
       nsRefPtr rc = new nsRenderingContext();
       rc->Init(presContext->DeviceContext(), aContext);
     
    -  DisplayItemClip currentClip;
    -  bool currentClipIsSetInContext = false;
    -  DisplayItemClip tmpClip;
    -
    -  for (i = 0; i < items.Length(); ++i) {
    -    ClippedDisplayItem* cdi = &items[i];
    -
    -    if (cdi->mItem->GetVisibleRect().IsEmpty())
    -      continue;
    -
    -    // If the new desired clip state is different from the current state,
    -    // update the clip.
    -    const DisplayItemClip* clip = &cdi->mItem->GetClip();
    -    if (clip->GetRoundedRectCount() > 0 &&
    -        !clip->IsRectClippedByRoundedCorner(cdi->mItem->GetVisibleRect())) {
    -      tmpClip = *clip;
    -      tmpClip.RemoveRoundedCorners();
    -      clip = &tmpClip;
    -    }
    -    if (currentClipIsSetInContext != clip->HasClip() ||
    -        (clip->HasClip() && *clip != currentClip)) {
    -      if (currentClipIsSetInContext) {
    -        aContext->Restore();
    -      }
    -      currentClipIsSetInContext = clip->HasClip();
    -      if (currentClipIsSetInContext) {
    -        currentClip = *clip;
    -        aContext->Save();
    -        NS_ASSERTION(commonClipCount < 100,
    -          "Maybe you really do have more than a hundred clipping rounded rects, or maybe something has gone wrong.");
    -        currentClip.ApplyTo(aContext, presContext, commonClipCount);
    -        aContext->NewPath();
    -      }
    -    }
    -
    -    if (cdi->mInactiveLayerManager) {
    -      PaintInactiveLayer(builder, cdi->mInactiveLayerManager, cdi->mItem, aContext, rc);
    -    } else {
    -      nsIFrame* frame = cdi->mItem->Frame();
    -      frame->AddStateBits(NS_FRAME_PAINTED_THEBES);
    -#ifdef MOZ_DUMP_PAINTING
    -
    -      if (gfxUtils::sDumpPainting) {
    -        DebugPaintItem(rc, cdi->mItem, builder);
    -      } else {
    -#else
    -      {
    -#endif
    -        cdi->mItem->Paint(builder, rc);
    -      }
    -    }
    -
    -    if (layerBuilder->CheckDOMModified())
    -      break;
    -  }
    -
    -  {
    -    ThebesLayerItemsEntry* entry =
    -      layerBuilder->mThebesLayerItems.GetEntry(aLayer);
    -    items.SwapElements(entry->mItems);
    -  }
    -
    -  if (currentClipIsSetInContext) {
    -    aContext->Restore();
    -  }
    +  layerBuilder->PaintItems(entry->mItems, aContext, rc,
    +                           builder, presContext, entry->mCommonClipCount);
     
       if (presContext->GetPaintFlashing()) {
         FlashPaint(aContext);
    diff --git a/layout/base/FrameLayerBuilder.h b/layout/base/FrameLayerBuilder.h
    index 9d62746a71d7..088bd2c1b9da 100644
    --- a/layout/base/FrameLayerBuilder.h
    +++ b/layout/base/FrameLayerBuilder.h
    @@ -520,6 +520,21 @@ protected:
         uint32_t mContainerLayerGeneration;
       };
     
    +  static void RecomputeVisibilityForItems(nsTArray& aItems,
    +                                          nsDisplayListBuilder* aBuilder,
    +                                          const nsIntRegion& aRegionToDraw,
    +                                          const nsIntPoint& aOffset,
    +                                          int32_t aAppUnitsPerDevPixel,
    +                                          float aXScale,
    +                                          float aYScale);
    +
    +  void PaintItems(nsTArray& aItems,
    +                  gfxContext* aContext,
    +                  nsRenderingContext* aRC,
    +                  nsDisplayListBuilder* aBuilder,
    +                  nsPresContext* aPresContext,
    +                  int32_t aCommonClipCount);
    +
       /**
        * We accumulate ClippedDisplayItem elements in a hashtable during
        * the paint process. This is the hashentry for that hashtable.
    
    From 43199694b86bc7701c82c0ebe0907d67a06c691b Mon Sep 17 00:00:00 2001
    From: Matt Woodrow 
    Date: Thu, 7 Nov 2013 08:10:50 +1300
    Subject: [PATCH 20/82] Bug 934860 - Move paint region clipping into
     DrawThebesLayer. r=roc
    
    ---
     embedding/browser/webBrowser/nsWebBrowser.cpp |  1 +
     gfx/layers/Layers.h                           |  1 +
     gfx/layers/LayersTypes.h                      |  6 ++++
     gfx/layers/ThebesLayerBuffer.cpp              |  8 ++---
     gfx/layers/ThebesLayerBuffer.h                |  2 ++
     gfx/layers/basic/BasicThebesLayer.cpp         |  3 +-
     gfx/layers/basic/BasicThebesLayer.h           |  5 +--
     gfx/layers/client/ClientThebesLayer.cpp       |  7 ++--
     gfx/layers/client/ClientThebesLayer.h         |  3 +-
     gfx/layers/client/ClientTiledThebesLayer.h    | 12 -------
     gfx/layers/client/ContentClient.cpp           |  6 ++--
     gfx/layers/client/TiledContentClient.cpp      |  3 +-
     gfx/layers/composite/LayerManagerComposite.h  | 14 --------
     gfx/layers/d3d10/ThebesLayerD3D10.cpp         | 34 +++++--------------
     gfx/layers/d3d9/ThebesLayerD3D9.cpp           |  2 +-
     gfx/layers/opengl/LayerManagerOGL.h           | 15 --------
     gfx/layers/opengl/ThebesLayerOGL.cpp          |  8 +++--
     layout/base/FrameLayerBuilder.cpp             |  7 ++++
     layout/base/FrameLayerBuilder.h               |  1 +
     19 files changed, 52 insertions(+), 86 deletions(-)
    
    diff --git a/embedding/browser/webBrowser/nsWebBrowser.cpp b/embedding/browser/webBrowser/nsWebBrowser.cpp
    index b61ad5d72741..3b3744e82575 100644
    --- a/embedding/browser/webBrowser/nsWebBrowser.cpp
    +++ b/embedding/browser/webBrowser/nsWebBrowser.cpp
    @@ -1662,6 +1662,7 @@ NS_IMETHODIMP nsWebBrowser::EnsureDocShellTreeOwner()
     static void DrawThebesLayer(ThebesLayer* aLayer,
                                 gfxContext* aContext,
                                 const nsIntRegion& aRegionToDraw,
    +                            DrawRegionClip aClip,
                                 const nsIntRegion& aRegionToInvalidate,
                                 void* aCallbackData)
     {
    diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h
    index 924cd1400de2..87be868fe94e 100644
    --- a/gfx/layers/Layers.h
    +++ b/gfx/layers/Layers.h
    @@ -265,6 +265,7 @@ public:
       typedef void (* DrawThebesLayerCallback)(ThebesLayer* aLayer,
                                                gfxContext* aContext,
                                                const nsIntRegion& aRegionToDraw,
    +                                           DrawRegionClip aClip,
                                                const nsIntRegion& aRegionToInvalidate,
                                                void* aCallbackData);
     
    diff --git a/gfx/layers/LayersTypes.h b/gfx/layers/LayersTypes.h
    index a3b20e72b5c2..3721389de1e2 100644
    --- a/gfx/layers/LayersTypes.h
    +++ b/gfx/layers/LayersTypes.h
    @@ -58,6 +58,12 @@ enum BufferMode {
       BUFFER_BUFFERED
     };
     
    +enum DrawRegionClip {
    +  CLIP_DRAW,
    +  CLIP_DRAW_SNAPPED,
    +  CLIP_NONE,
    +};
    +
     // LayerRenderState for Composer2D
     // We currently only support Composer2D using gralloc. If we want to be backed
     // by other surfaces we will need a more generic LayerRenderState.
    diff --git a/gfx/layers/ThebesLayerBuffer.cpp b/gfx/layers/ThebesLayerBuffer.cpp
    index e0b4cb0516ad..6af984379586 100644
    --- a/gfx/layers/ThebesLayerBuffer.cpp
    +++ b/gfx/layers/ThebesLayerBuffer.cpp
    @@ -856,6 +856,7 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
     
       nsIntPoint topLeft;
       result.mContext = GetContextForQuadrantUpdate(drawBounds, BUFFER_BOTH, &topLeft);
    +  result.mClip = CLIP_DRAW_SNAPPED;
     
       if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
         if (IsAzureBuffer()) {
    @@ -873,7 +874,6 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
           FillSurface(mBuffer, result.mRegionToDraw, topLeft, gfxRGBA(0.0, 0.0, 0.0, 1.0));
           FillSurface(mBufferOnWhite, result.mRegionToDraw, topLeft, gfxRGBA(1.0, 1.0, 1.0, 1.0));
         }
    -    gfxUtils::ClipToRegionSnapped(result.mContext, result.mRegionToDraw);
       } else if (contentType == GFX_CONTENT_COLOR_ALPHA && !isClear) {
         if (IsAzureBuffer()) {
           nsIntRegionRectIterator iter(result.mRegionToDraw);
    @@ -883,16 +883,14 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
           }
           // Clear will do something expensive with a complex clip pushed, so clip
           // here.
    -      gfxUtils::ClipToRegionSnapped(result.mContext, result.mRegionToDraw);
         } else {
           MOZ_ASSERT(result.mContext->IsCairo());
    +      result.mContext->Save();
           gfxUtils::ClipToRegionSnapped(result.mContext, result.mRegionToDraw);
           result.mContext->SetOperator(gfxContext::OPERATOR_CLEAR);
           result.mContext->Paint();
    -      result.mContext->SetOperator(gfxContext::OPERATOR_OVER);
    +      result.mContext->Restore();
         }
    -  } else {
    -    gfxUtils::ClipToRegionSnapped(result.mContext, result.mRegionToDraw);
       }
     
       return result;
    diff --git a/gfx/layers/ThebesLayerBuffer.h b/gfx/layers/ThebesLayerBuffer.h
    index 819eab4452c9..1df643c65e4e 100644
    --- a/gfx/layers/ThebesLayerBuffer.h
    +++ b/gfx/layers/ThebesLayerBuffer.h
    @@ -21,6 +21,7 @@
     #include "nsRect.h"                     // for nsIntRect
     #include "nsRegion.h"                   // for nsIntRegion
     #include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
    +#include "LayersTypes.h"
     
     struct gfxMatrix;
     struct nsIntSize;
    @@ -218,6 +219,7 @@ public:
         nsIntRegion mRegionToDraw;
         nsIntRegion mRegionToInvalidate;
         bool mDidSelfCopy;
    +    DrawRegionClip mClip;
       };
     
       enum {
    diff --git a/gfx/layers/basic/BasicThebesLayer.cpp b/gfx/layers/basic/BasicThebesLayer.cpp
    index dd7d146f4394..a739debebfc6 100644
    --- a/gfx/layers/basic/BasicThebesLayer.cpp
    +++ b/gfx/layers/basic/BasicThebesLayer.cpp
    @@ -131,7 +131,7 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
             groupContext = aContext;
           }
           SetAntialiasingFlags(this, groupContext);
    -      aCallback(this, groupContext, toDraw, nsIntRegion(), aCallbackData);
    +      aCallback(this, groupContext, toDraw, CLIP_NONE, nsIntRegion(), aCallbackData);
           if (needsGroup) {
             BasicManager()->PopGroupToSourceWithCachedSurface(aContext, groupContext);
             if (needsClipToVisibleRegion) {
    @@ -236,6 +236,7 @@ BasicThebesLayer::Validate(LayerManager::DrawThebesLayerCallback aCallback,
         PaintBuffer(state.mContext,
                     state.mRegionToDraw, extendedDrawRegion, state.mRegionToInvalidate,
                     state.mDidSelfCopy,
    +                state.mClip,
                     aCallback, aCallbackData);
         MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PaintThebes", this));
         Mutated();
    diff --git a/gfx/layers/basic/BasicThebesLayer.h b/gfx/layers/basic/BasicThebesLayer.h
    index af9220dc0fbe..6c0ecc97603b 100644
    --- a/gfx/layers/basic/BasicThebesLayer.h
    +++ b/gfx/layers/basic/BasicThebesLayer.h
    @@ -103,6 +103,7 @@ protected:
                   const nsIntRegion& aExtendedRegionToDraw,
                   const nsIntRegion& aRegionToInvalidate,
                   bool aDidSelfCopy,
    +              DrawRegionClip aClip,
                   LayerManager::DrawThebesLayerCallback aCallback,
                   void* aCallbackData)
       {
    @@ -110,8 +111,8 @@ protected:
           BasicManager()->SetTransactionIncomplete();
           return;
         }
    -    aCallback(this, aContext, aExtendedRegionToDraw, aRegionToInvalidate,
    -              aCallbackData);
    +    aCallback(this, aContext, aExtendedRegionToDraw, aClip,
    +              aRegionToInvalidate, aCallbackData);
         // Everything that's visible has been validated. Do this instead of just
         // OR-ing with aRegionToDraw, since that can lead to a very complex region
         // here (OR doesn't automatically simplify to the simplest possible
    diff --git a/gfx/layers/client/ClientThebesLayer.cpp b/gfx/layers/client/ClientThebesLayer.cpp
    index 51a15ba7ef0f..95d4496827ea 100644
    --- a/gfx/layers/client/ClientThebesLayer.cpp
    +++ b/gfx/layers/client/ClientThebesLayer.cpp
    @@ -106,7 +106,7 @@ ClientThebesLayer::PaintThebes()
     
           PaintBuffer(state.mContext,
                       state.mRegionToDraw, extendedDrawRegion, state.mRegionToInvalidate,
    -                  state.mDidSelfCopy);
    +                  state.mDidSelfCopy, state.mClip);
           MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PaintThebes", this));
           Mutated();
         } else {
    @@ -146,7 +146,7 @@ ClientThebesLayer::PaintBuffer(gfxContext* aContext,
                                    const nsIntRegion& aRegionToDraw,
                                    const nsIntRegion& aExtendedRegionToDraw,
                                    const nsIntRegion& aRegionToInvalidate,
    -                               bool aDidSelfCopy)
    +                               bool aDidSelfCopy, DrawRegionClip aClip)
     {
       ContentClientRemote* contentClientRemote = static_cast(mContentClient.get());
       MOZ_ASSERT(contentClientRemote->GetIPDLActor());
    @@ -161,7 +161,8 @@ ClientThebesLayer::PaintBuffer(gfxContext* aContext,
       }
       ClientManager()->GetThebesLayerCallback()(this, 
                                                 aContext, 
    -                                            aExtendedRegionToDraw, 
    +                                            aExtendedRegionToDraw,
    +                                            aClip,
                                                 aRegionToInvalidate,
                                                 ClientManager()->GetThebesLayerCallbackData());
     
    diff --git a/gfx/layers/client/ClientThebesLayer.h b/gfx/layers/client/ClientThebesLayer.h
    index 6f1eae7da1aa..42fbfe49dcd8 100644
    --- a/gfx/layers/client/ClientThebesLayer.h
    +++ b/gfx/layers/client/ClientThebesLayer.h
    @@ -105,7 +105,8 @@ protected:
                   const nsIntRegion& aRegionToDraw,
                   const nsIntRegion& aExtendedRegionToDraw,
                   const nsIntRegion& aRegionToInvalidate,
    -              bool aDidSelfCopy);
    +              bool aDidSelfCopy,
    +              DrawRegionClip aClip);
       
       void PaintThebes();
       
    diff --git a/gfx/layers/client/ClientTiledThebesLayer.h b/gfx/layers/client/ClientTiledThebesLayer.h
    index c01967653492..01c262e06abf 100644
    --- a/gfx/layers/client/ClientTiledThebesLayer.h
    +++ b/gfx/layers/client/ClientTiledThebesLayer.h
    @@ -69,18 +69,6 @@ private:
         return static_cast(mManager);
       }
     
    -  // BasicImplData
    -  virtual void
    -  PaintBuffer(gfxContext* aContext,
    -              const nsIntRegion& aRegionToDraw,
    -              const nsIntRegion& aExtendedRegionToDraw,
    -              const nsIntRegion& aRegionToInvalidate,
    -              bool aDidSelfCopy,
    -              LayerManager::DrawThebesLayerCallback aCallback,
    -              void* aCallbackData)
    -  { NS_RUNTIMEABORT("Not reached."); }
    -
    -
       /**
        * For the initial PaintThebes of a transaction, calculates all the data
        * needed for that paint and any repeated transactions.
    diff --git a/gfx/layers/client/ContentClient.cpp b/gfx/layers/client/ContentClient.cpp
    index 5ecf1568ebed..ad23e2fcac63 100644
    --- a/gfx/layers/client/ContentClient.cpp
    +++ b/gfx/layers/client/ContentClient.cpp
    @@ -894,12 +894,14 @@ ContentClientIncremental::BeginPaintBuffer(ThebesLayer* aLayer,
       // although they never cover it. This leads to two draw rects, the narow strip and the actually
       // newly exposed area. It would be wise to fix this glitch in any way to have simpler
       // clip and draw regions.
    -  gfxUtils::ClipToRegion(result.mContext, result.mRegionToDraw);
    +  result.mClip = CLIP_DRAW;
     
       if (mContentType == GFX_CONTENT_COLOR_ALPHA) {
    +    result.mContext->Save();
    +    gfxUtils::ClipToRegion(result.mContext, result.mRegionToDraw);
         result.mContext->SetOperator(gfxContext::OPERATOR_CLEAR);
         result.mContext->Paint();
    -    result.mContext->SetOperator(gfxContext::OPERATOR_OVER);
    +    result.mContext->Restore();
       }
     
       return result;
    diff --git a/gfx/layers/client/TiledContentClient.cpp b/gfx/layers/client/TiledContentClient.cpp
    index 5f98aa4ce5a1..cdf98d15385d 100644
    --- a/gfx/layers/client/TiledContentClient.cpp
    +++ b/gfx/layers/client/TiledContentClient.cpp
    @@ -274,7 +274,7 @@ BasicTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
     #endif
         PROFILER_LABEL("BasicTiledLayerBuffer", "PaintThebesSingleBufferDraw");
     
    -    mCallback(mThebesLayer, ctxt, aPaintRegion, nsIntRegion(), mCallbackData);
    +    mCallback(mThebesLayer, ctxt, aPaintRegion, CLIP_NONE, nsIntRegion(), mCallbackData);
       }
     
     #ifdef GFX_TILEDLAYER_PREF_WARNINGS
    @@ -383,6 +383,7 @@ BasicTiledLayerBuffer::ValidateTileInternal(BasicTiledLayerTile aTile,
         mCallback(mThebesLayer, ctxt,
                   nsIntRegion(nsIntRect(a, nsIntSize(GetScaledTileLength(),
                                                      GetScaledTileLength()))),
    +              CLIP_NONE,
                   nsIntRegion(), mCallbackData);
       }
     
    diff --git a/gfx/layers/composite/LayerManagerComposite.h b/gfx/layers/composite/LayerManagerComposite.h
    index fa32b5ac35df..476a4a1afde0 100644
    --- a/gfx/layers/composite/LayerManagerComposite.h
    +++ b/gfx/layers/composite/LayerManagerComposite.h
    @@ -158,20 +158,6 @@ public:
       void* GetThebesLayerCallbackData() const
       { return mThebesLayerCallbackData; }
     
    -  /*
    -   * Helper functions for our layers
    -   */
    -  void CallThebesLayerDrawCallback(ThebesLayer* aLayer,
    -                                   gfxContext* aContext,
    -                                   const nsIntRegion& aRegionToDraw)
    -  {
    -    NS_ASSERTION(mThebesLayerCallback,
    -                 "CallThebesLayerDrawCallback without callback!");
    -    mThebesLayerCallback(aLayer, aContext,
    -                         aRegionToDraw, nsIntRegion(),
    -                         mThebesLayerCallbackData);
    -  }
    -
     #ifdef MOZ_LAYERS_HAVE_LOG
       virtual const char* Name() const MOZ_OVERRIDE { return ""; }
     #endif // MOZ_LAYERS_HAVE_LOG
    diff --git a/gfx/layers/d3d10/ThebesLayerD3D10.cpp b/gfx/layers/d3d10/ThebesLayerD3D10.cpp
    index a0d12f4899c0..f6239932fc58 100644
    --- a/gfx/layers/d3d10/ThebesLayerD3D10.cpp
    +++ b/gfx/layers/d3d10/ThebesLayerD3D10.cpp
    @@ -414,40 +414,22 @@ ThebesLayerD3D10::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode)
         destinationSurface = mD2DSurface;
       }
     
    -  nsRefPtr context;
    +  MOZ_ASSERT(mDrawTarget);
    +  nsRefPtr context = new gfxContext(mDrawTarget);
     
    -  if (mDrawTarget) {
    -    context = new gfxContext(mDrawTarget);
    -  } else {
    -    context = new gfxContext(destinationSurface);
    -  }
    -
    -  nsIntRegionRectIterator iter(aRegion);
       context->Translate(gfxPoint(-visibleRect.x, -visibleRect.y));
    -  context->NewPath();
    -  const nsIntRect *iterRect;
    -  while ((iterRect = iter.Next())) {
    -    context->Rectangle(gfxRect(iterRect->x, iterRect->y, iterRect->width, iterRect->height));
    -    if (mDrawTarget && aMode == SURFACE_SINGLE_CHANNEL_ALPHA) {
    +  if (aMode == SURFACE_SINGLE_CHANNEL_ALPHA) {
    +    nsIntRegionRectIterator iter(aRegion);
    +    const nsIntRect *iterRect;
    +    while ((iterRect = iter.Next())) {
           mDrawTarget->ClearRect(Rect(iterRect->x, iterRect->y, iterRect->width, iterRect->height));
         }
       }
    -  context->Clip();
     
    -  if (!mDrawTarget && aMode == SURFACE_SINGLE_CHANNEL_ALPHA) {
    -    context->SetOperator(gfxContext::OPERATOR_CLEAR);
    -    context->Paint();
    -    context->SetOperator(gfxContext::OPERATOR_OVER);
    -  }
    -
    -  if (mD2DSurface) {
    -    mD2DSurface->SetSubpixelAntialiasingEnabled(!(mContentFlags & CONTENT_COMPONENT_ALPHA));
    -  } else if (mDrawTarget) {
    -    mDrawTarget->SetPermitSubpixelAA(!(mContentFlags & CONTENT_COMPONENT_ALPHA));
    -  }
    +  mDrawTarget->SetPermitSubpixelAA(!(mContentFlags & CONTENT_COMPONENT_ALPHA));
     
       LayerManagerD3D10::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
    -  cbInfo.Callback(this, context, aRegion, nsIntRegion(), cbInfo.CallbackData);
    +  cbInfo.Callback(this, context, aRegion, CLIP_DRAW, nsIntRegion(), cbInfo.CallbackData);
     }
     
     void
    diff --git a/gfx/layers/d3d9/ThebesLayerD3D9.cpp b/gfx/layers/d3d9/ThebesLayerD3D9.cpp
    index 7fa002cdf2e6..8543fa8f969d 100644
    --- a/gfx/layers/d3d9/ThebesLayerD3D9.cpp
    +++ b/gfx/layers/d3d9/ThebesLayerD3D9.cpp
    @@ -493,7 +493,7 @@ ThebesLayerD3D9::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode,
     
       context->Translate(gfxPoint(-bounds.x, -bounds.y));
       LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
    -  cbInfo.Callback(this, context, aRegion, nsIntRegion(), cbInfo.CallbackData);
    +  cbInfo.Callback(this, context, aRegion, CLIP_NONE, nsIntRegion(), cbInfo.CallbackData);
     
       for (uint32_t i = 0; i < aReadbackUpdates.Length(); ++i) {
         NS_ASSERTION(aMode == SURFACE_OPAQUE,
    diff --git a/gfx/layers/opengl/LayerManagerOGL.h b/gfx/layers/opengl/LayerManagerOGL.h
    index bfa22e2fafb2..e0dde9d06493 100644
    --- a/gfx/layers/opengl/LayerManagerOGL.h
    +++ b/gfx/layers/opengl/LayerManagerOGL.h
    @@ -200,21 +200,6 @@ public:
       void* GetThebesLayerCallbackData() const
       { return mThebesLayerCallbackData; }
     
    -  /*
    -   * Helper functions for our layers
    -   */
    -  void CallThebesLayerDrawCallback(ThebesLayer* aLayer,
    -                                   gfxContext* aContext,
    -                                   const nsIntRegion& aRegionToDraw)
    -  {
    -    NS_ASSERTION(mThebesLayerCallback,
    -                 "CallThebesLayerDrawCallback without callback!");
    -    mThebesLayerCallback(aLayer, aContext,
    -                         aRegionToDraw, nsIntRegion(),
    -                         mThebesLayerCallbackData);
    -  }
    -
    -
       GLenum FBOTextureTarget() { return mFBOTextureTarget; }
     
       /**
    diff --git a/gfx/layers/opengl/ThebesLayerOGL.cpp b/gfx/layers/opengl/ThebesLayerOGL.cpp
    index 6293314ab5d4..85fb106af71c 100644
    --- a/gfx/layers/opengl/ThebesLayerOGL.cpp
    +++ b/gfx/layers/opengl/ThebesLayerOGL.cpp
    @@ -828,12 +828,14 @@ BasicBufferOGL::BeginPaint(ContentType aContentType,
       // although they never cover it. This leads to two draw rects, the narow strip and the actually
       // newly exposed area. It would be wise to fix this glitch in any way to have simpler
       // clip and draw regions.
    -  gfxUtils::ClipToRegion(result.mContext, result.mRegionToDraw);
    +  result.mClip = CLIP_DRAW;
     
       if (mTexImage->GetContentType() == GFX_CONTENT_COLOR_ALPHA) {
    +    result.mContext->Save();
    +    gfxUtils::ClipToRegion(result.mContext, result.mRegionToDraw);
         result.mContext->SetOperator(gfxContext::OPERATOR_CLEAR);
         result.mContext->Paint();
    -    result.mContext->SetOperator(gfxContext::OPERATOR_OVER);
    +    result.mContext->Restore();
       }
     
       return result;
    @@ -931,7 +933,7 @@ ThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer,
         } else {
           void* callbackData = mOGLManager->GetThebesLayerCallbackData();
           SetAntialiasingFlags(this, state.mContext);
    -      callback(this, state.mContext, state.mRegionToDraw,
    +      callback(this, state.mContext, state.mRegionToDraw, state.mClip,
                    state.mRegionToInvalidate, callbackData);
           // Everything that's visible has been validated. Do this instead of just
           // OR-ing with aRegionToDraw, since that can lead to a very complex region
    diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp
    index 16942e4fd3ff..aae14f67ca00 100644
    --- a/layout/base/FrameLayerBuilder.cpp
    +++ b/layout/base/FrameLayerBuilder.cpp
    @@ -3268,6 +3268,7 @@ FrameLayerBuilder::PaintItems(nsTArray& aItems,
     FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer,
                                        gfxContext* aContext,
                                        const nsIntRegion& aRegionToDraw,
    +                                   DrawRegionClip aClip,
                                        const nsIntRegion& aRegionToInvalidate,
                                        void* aCallbackData)
     {
    @@ -3276,6 +3277,12 @@ FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer,
       nsDisplayListBuilder* builder = static_cast
         (aCallbackData);
     
    +  if (aClip == CLIP_DRAW_SNAPPED) {
    +    gfxUtils::ClipToRegionSnapped(aContext, aRegionToDraw);
    +  } else if (aClip == CLIP_DRAW) {
    +    gfxUtils::ClipToRegion(aContext, aRegionToDraw);
    +  }
    +
       FrameLayerBuilder *layerBuilder = aLayer->Manager()->GetLayerBuilder();
       NS_ASSERTION(layerBuilder, "Unexpectedly null layer builder!");
     
    diff --git a/layout/base/FrameLayerBuilder.h b/layout/base/FrameLayerBuilder.h
    index 088bd2c1b9da..c6bfa24229fb 100644
    --- a/layout/base/FrameLayerBuilder.h
    +++ b/layout/base/FrameLayerBuilder.h
    @@ -244,6 +244,7 @@ public:
       static void DrawThebesLayer(ThebesLayer* aLayer,
                                   gfxContext* aContext,
                                   const nsIntRegion& aRegionToDraw,
    +                              mozilla::layers::DrawRegionClip aClip,
                                   const nsIntRegion& aRegionToInvalidate,
                                   void* aCallbackData);
     
    
    From c0af504d85770e901609f271ec25997af8b8e5b9 Mon Sep 17 00:00:00 2001
    From: Matt Woodrow 
    Date: Thu, 7 Nov 2013 08:10:50 +1300
    Subject: [PATCH 21/82] Bug 934860 - Draw each rect of the invalid region
     separately on Direct2D. r=roc
    
    ---
     layout/base/FrameLayerBuilder.cpp | 88 ++++++++++++++++++++++++-------
     1 file changed, 69 insertions(+), 19 deletions(-)
    
    diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp
    index aae14f67ca00..200baa27adb2 100644
    --- a/layout/base/FrameLayerBuilder.cpp
    +++ b/layout/base/FrameLayerBuilder.cpp
    @@ -24,6 +24,7 @@
     
     #include "GeckoProfiler.h"
     #include "mozilla/gfx/Tools.h"
    +#include "mozilla/gfx/2D.h"
     
     #include 
     
    @@ -3236,6 +3237,31 @@ FrameLayerBuilder::PaintItems(nsTArray& aItems,
       }
     }
     
    +/**
    + * Returns true if it is preferred to draw the list of display
    + * items separately for each rect in the visible region rather
    + * than clipping to a complex region.
    + */
    +static bool ShouldDrawRectsSeparately(gfxContext* aContext, DrawRegionClip aClip)
    +{
    +  if (aContext->IsCairo() || aClip == CLIP_NONE) {
    +    return false;
    +  }
    +  DrawTarget *dt = aContext->GetDrawTarget();
    +  return dt->GetType() == BACKEND_DIRECT2D;
    +}
    +
    +static void DrawForcedBackgroundColor(gfxContext* aContext, Layer* aLayer, nscolor aBackgroundColor)
    +{
    +  if (NS_GET_A(aBackgroundColor) > 0) {
    +    nsIntRect r = aLayer->GetVisibleRegion().GetBounds();
    +    aContext->NewPath();
    +    aContext->Rectangle(gfxRect(r.x, r.y, r.width, r.height));
    +    aContext->SetColor(gfxRGBA(aBackgroundColor));
    +    aContext->Fill();
    +  }
    +}
    +
     /*
      * A note on residual transforms:
      *
    @@ -3277,12 +3303,6 @@ FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer,
       nsDisplayListBuilder* builder = static_cast
         (aCallbackData);
     
    -  if (aClip == CLIP_DRAW_SNAPPED) {
    -    gfxUtils::ClipToRegionSnapped(aContext, aRegionToDraw);
    -  } else if (aClip == CLIP_DRAW) {
    -    gfxUtils::ClipToRegion(aContext, aRegionToDraw);
    -  }
    -
       FrameLayerBuilder *layerBuilder = aLayer->Manager()->GetLayerBuilder();
       NS_ASSERTION(layerBuilder, "Unexpectedly null layer builder!");
     
    @@ -3295,27 +3315,28 @@ FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer,
         return;
       }
     
    +
       ThebesDisplayItemLayerUserData* userData =
         static_cast
           (aLayer->GetUserData(&gThebesDisplayItemLayerUserData));
       NS_ASSERTION(userData, "where did our user data go?");
    -  if (NS_GET_A(userData->mForcedBackgroundColor) > 0) {
    -    nsIntRect r = aLayer->GetVisibleRegion().GetBounds();
    -    aContext->NewPath();
    -    aContext->Rectangle(gfxRect(r.x, r.y, r.width, r.height));
    -    aContext->SetColor(gfxRGBA(userData->mForcedBackgroundColor));
    -    aContext->Fill();
    +
    +  bool shouldDrawRectsSeparately = ShouldDrawRectsSeparately(aContext, aClip);
    +
    +  if (!shouldDrawRectsSeparately) {
    +    if (aClip == CLIP_DRAW_SNAPPED) {
    +      gfxUtils::ClipToRegionSnapped(aContext, aRegionToDraw);
    +    } else if (aClip == CLIP_DRAW) {
    +      gfxUtils::ClipToRegion(aContext, aRegionToDraw);
    +    }
    +
    +    DrawForcedBackgroundColor(aContext, aLayer, userData->mForcedBackgroundColor);
       }
     
       // make the origin of the context coincide with the origin of the
       // ThebesLayer
       gfxContextMatrixAutoSaveRestore saveMatrix(aContext);
       nsIntPoint offset = GetTranslationForThebesLayer(aLayer);
    -  // Apply the residual transform if it has been enabled, to ensure that
    -  // snapping when we draw into aContext exactly matches the ideal transform.
    -  // See above for why this is OK.
    -  aContext->Translate(aLayer->GetResidualTranslation() - gfxPoint(offset.x, offset.y));
    -  aContext->Scale(userData->mXScale, userData->mYScale);
     
       nsPresContext* presContext = entry->mContainerLayerFrame->PresContext();
       int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
    @@ -3327,8 +3348,37 @@ FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer,
       nsRefPtr rc = new nsRenderingContext();
       rc->Init(presContext->DeviceContext(), aContext);
     
    -  layerBuilder->PaintItems(entry->mItems, aContext, rc,
    -                           builder, presContext, entry->mCommonClipCount);
    +  if (shouldDrawRectsSeparately) {
    +    nsIntRegionRectIterator it(aRegionToDraw);
    +    while (const nsIntRect* iterRect = it.Next()) {
    +      gfxContextAutoSaveRestore save(aContext);
    +      aContext->NewPath();
    +      aContext->Rectangle(*iterRect, aClip == CLIP_DRAW_SNAPPED);
    +      aContext->Clip();
    +
    +      DrawForcedBackgroundColor(aContext, aLayer, userData->mForcedBackgroundColor);
    +
    +      // Apply the residual transform if it has been enabled, to ensure that
    +      // snapping when we draw into aContext exactly matches the ideal transform.
    +      // See above for why this is OK.
    +      aContext->Translate(aLayer->GetResidualTranslation() - gfxPoint(offset.x, offset.y));
    +      aContext->Scale(userData->mXScale, userData->mYScale);
    +
    +      layerBuilder->PaintItems(entry->mItems, aContext, rc,
    +                               builder, presContext,
    +                               entry->mCommonClipCount);
    +    }
    +  } else {
    +    // Apply the residual transform if it has been enabled, to ensure that
    +    // snapping when we draw into aContext exactly matches the ideal transform.
    +    // See above for why this is OK.
    +    aContext->Translate(aLayer->GetResidualTranslation() - gfxPoint(offset.x, offset.y));
    +    aContext->Scale(userData->mXScale, userData->mYScale);
    +
    +    layerBuilder->PaintItems(entry->mItems, aContext, rc,
    +                             builder, presContext,
    +                             entry->mCommonClipCount);
    +  }
     
       if (presContext->GetPaintFlashing()) {
         FlashPaint(aContext);
    
    From 1077db1b3c03198a5aa97a074c8c42b157c32659 Mon Sep 17 00:00:00 2001
    From: Matt Woodrow 
    Date: Thu, 7 Nov 2013 08:10:50 +1300
    Subject: [PATCH 22/82] Bug 934860 - Don't paint display items that don't
     intersect the current invalid rects. r=roc
    
    ---
     layout/base/FrameLayerBuilder.cpp | 18 +++++++++++++++---
     layout/base/FrameLayerBuilder.h   |  3 +++
     2 files changed, 18 insertions(+), 3 deletions(-)
    
    diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp
    index 200baa27adb2..fa237b93dd03 100644
    --- a/layout/base/FrameLayerBuilder.cpp
    +++ b/layout/base/FrameLayerBuilder.cpp
    @@ -3170,12 +3170,21 @@ FrameLayerBuilder::RecomputeVisibilityForItems(nsTArray& aIt
     
     void
     FrameLayerBuilder::PaintItems(nsTArray& aItems,
    +                              const nsIntRect& aRect,
                                   gfxContext *aContext,
                                   nsRenderingContext *aRC,
                                   nsDisplayListBuilder* aBuilder,
                                   nsPresContext* aPresContext,
    +                              const nsIntPoint& aOffset,
    +                              float aXScale, float aYScale,
                                   int32_t aCommonClipCount)
     {
    +  int32_t appUnitsPerDevPixel = aPresContext->AppUnitsPerDevPixel();
    +  nsRect boundRect = aRect.ToAppUnits(appUnitsPerDevPixel);
    +  boundRect.MoveBy(NSIntPixelsToAppUnits(aOffset.x, appUnitsPerDevPixel),
    +                 NSIntPixelsToAppUnits(aOffset.y, appUnitsPerDevPixel));
    +  boundRect.ScaleInverseRoundOut(aXScale, aYScale);
    +
       DisplayItemClip currentClip;
       bool currentClipIsSetInContext = false;
       DisplayItemClip tmpClip;
    @@ -3183,7 +3192,8 @@ FrameLayerBuilder::PaintItems(nsTArray& aItems,
       for (uint32_t i = 0; i < aItems.Length(); ++i) {
         ClippedDisplayItem* cdi = &aItems[i];
     
    -    if (cdi->mItem->GetVisibleRect().IsEmpty())
    +    nsRect paintRect = cdi->mItem->GetVisibleRect().Intersect(boundRect);
    +    if (paintRect.IsEmpty())
           continue;
     
         // If the new desired clip state is different from the current state,
    @@ -3364,8 +3374,9 @@ FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer,
           aContext->Translate(aLayer->GetResidualTranslation() - gfxPoint(offset.x, offset.y));
           aContext->Scale(userData->mXScale, userData->mYScale);
     
    -      layerBuilder->PaintItems(entry->mItems, aContext, rc,
    +      layerBuilder->PaintItems(entry->mItems, *iterRect, aContext, rc,
                                    builder, presContext,
    +                               offset, userData->mXScale, userData->mYScale,
                                    entry->mCommonClipCount);
         }
       } else {
    @@ -3375,8 +3386,9 @@ FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer,
         aContext->Translate(aLayer->GetResidualTranslation() - gfxPoint(offset.x, offset.y));
         aContext->Scale(userData->mXScale, userData->mYScale);
     
    -    layerBuilder->PaintItems(entry->mItems, aContext, rc,
    +    layerBuilder->PaintItems(entry->mItems, aRegionToDraw.GetBounds(), aContext, rc,
                                  builder, presContext,
    +                             offset, userData->mXScale, userData->mYScale,
                                  entry->mCommonClipCount);
       }
     
    diff --git a/layout/base/FrameLayerBuilder.h b/layout/base/FrameLayerBuilder.h
    index c6bfa24229fb..9ea239215b42 100644
    --- a/layout/base/FrameLayerBuilder.h
    +++ b/layout/base/FrameLayerBuilder.h
    @@ -530,10 +530,13 @@ protected:
                                               float aYScale);
     
       void PaintItems(nsTArray& aItems,
    +                  const nsIntRect& aRect,
                       gfxContext* aContext,
                       nsRenderingContext* aRC,
                       nsDisplayListBuilder* aBuilder,
                       nsPresContext* aPresContext,
    +                  const nsIntPoint& aOffset,
    +                  float aXScale, float aYScale,
                       int32_t aCommonClipCount);
     
       /**
    
    From 2b8772922b512b34617cc6f3628ba42a33b80ed4 Mon Sep 17 00:00:00 2001
    From: Andrew McCreight 
    Date: Tue, 27 Aug 2013 09:42:11 -0700
    Subject: [PATCH 23/82] Bug 909490, part 1 - Add per-zone data for use by
     embedder. r=billm
    
    ---
     js/src/gc/Zone.cpp |  1 +
     js/src/gc/Zone.h   |  3 +++
     js/src/jsapi.cpp   | 12 ++++++++++++
     js/src/jsapi.h     |  6 ++++++
     4 files changed, 22 insertions(+)
    
    diff --git a/js/src/gc/Zone.cpp b/js/src/gc/Zone.cpp
    index 9e8551b7162d..72d648529114 100644
    --- a/js/src/gc/Zone.cpp
    +++ b/js/src/gc/Zone.cpp
    @@ -39,6 +39,7 @@ JS::Zone::Zone(JSRuntime *rt)
         maybeAlive(true),
         gcMallocBytes(0),
         gcGrayRoots(),
    +    data(nullptr),
         types(this)
     {
         /* Ensure that there are no vtables to mess us up here. */
    diff --git a/js/src/gc/Zone.h b/js/src/gc/Zone.h
    index 2f641ea4de60..c11c73f956d5 100644
    --- a/js/src/gc/Zone.h
    +++ b/js/src/gc/Zone.h
    @@ -255,6 +255,9 @@ struct Zone : public JS::shadow::Zone,
         /* This compartment's gray roots. */
         js::Vector gcGrayRoots;
     
    +    /* Per-zone data for use by an embedder. */
    +    void *data;
    +
         Zone(JSRuntime *rt);
         ~Zone();
         bool init(JSContext *cx);
    diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
    index d548b4da0500..8bdb70b681e2 100644
    --- a/js/src/jsapi.cpp
    +++ b/js/src/jsapi.cpp
    @@ -988,6 +988,18 @@ JS_GetCompartmentPrivate(JSCompartment *compartment)
         return compartment->data;
     }
     
    +JS_PUBLIC_API(void)
    +JS_SetZoneUserData(JS::Zone *zone, void *data)
    +{
    +    zone->data = data;
    +}
    +
    +JS_PUBLIC_API(void *)
    +JS_GetZoneUserData(JS::Zone *zone)
    +{
    +    return zone->data;
    +}
    +
     JS_PUBLIC_API(bool)
     JS_WrapObject(JSContext *cx, MutableHandleObject objp)
     {
    diff --git a/js/src/jsapi.h b/js/src/jsapi.h
    index 69a6af98676d..552d5c5c534a 100644
    --- a/js/src/jsapi.h
    +++ b/js/src/jsapi.h
    @@ -1638,6 +1638,12 @@ JS_SetCompartmentPrivate(JSCompartment *compartment, void *data);
     extern JS_PUBLIC_API(void *)
     JS_GetCompartmentPrivate(JSCompartment *compartment);
     
    +extern JS_PUBLIC_API(void)
    +JS_SetZoneUserData(JS::Zone *zone, void *data);
    +
    +extern JS_PUBLIC_API(void *)
    +JS_GetZoneUserData(JS::Zone *zone);
    +
     extern JS_PUBLIC_API(bool)
     JS_WrapObject(JSContext *cx, JS::MutableHandleObject objp);
     
    
    From 81d93626909f91f85f324bf059bc259b9417a2d4 Mon Sep 17 00:00:00 2001
    From: Brandon Benvie 
    Date: Thu, 17 Oct 2013 16:05:14 -0700
    Subject: [PATCH 24/82] Bug 862849 - Remove __iterator__ use from the devtools.
     r=vp
    
    ---
     browser/devtools/debugger/CmdDebugger.jsm     |  4 +--
     browser/devtools/debugger/debugger-panes.js   | 26 +++++++++----------
     browser/devtools/debugger/debugger-toolbar.js |  2 +-
     .../browser_dbg_breakpoints-contextmenu.js    | 24 ++++++++---------
     .../devtools/netmonitor/netmonitor-view.js    |  4 +--
     .../test/browser_scratchpad_inspect.js        |  6 ++---
     .../devtools/shared/widgets/VariablesView.jsm | 20 +++++++-------
     .../devtools/shared/widgets/ViewHelpers.jsm   | 16 +++++-------
     8 files changed, 48 insertions(+), 54 deletions(-)
    
    diff --git a/browser/devtools/debugger/CmdDebugger.jsm b/browser/devtools/debugger/CmdDebugger.jsm
    index 3f910d7dce87..59231e23eebf 100644
    --- a/browser/devtools/debugger/CmdDebugger.jsm
    +++ b/browser/devtools/debugger/CmdDebugger.jsm
    @@ -37,8 +37,8 @@ function getAllBreakpoints(dbg) {
       let sources = dbg._view.Sources;
       let { trimUrlLength: trim } = dbg.panelWin.SourceUtils;
     
    -  for (let source in sources) {
    -    for (let { attachment: breakpoint } in source) {
    +  for (let source of sources) {
    +    for (let { attachment: breakpoint } of source) {
           breakpoints.push({
             url: source.value,
             label: source.label + ":" + breakpoint.line,
    diff --git a/browser/devtools/debugger/debugger-panes.js b/browser/devtools/debugger/debugger-panes.js
    index d42bfc38d172..1c938ab549f1 100644
    --- a/browser/devtools/debugger/debugger-panes.js
    +++ b/browser/devtools/debugger/debugger-panes.js
    @@ -231,8 +231,8 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
        *         The corresponding breakpoints if found, an empty array otherwise.
        */
       getOtherBreakpoints: function(aLocation = {}, aStore = []) {
    -    for (let source in this) {
    -      for (let breakpointItem in source) {
    +    for (let source of this) {
    +      for (let breakpointItem of source) {
             let { url, line } = breakpointItem.attachment;
             if (url != aLocation.url || line != aLocation.line) {
               aStore.push(breakpointItem);
    @@ -1340,7 +1340,7 @@ WatchExpressionsView.prototype = Heritage.extend(WidgetMethods, {
        */
       switchExpression: function(aVar, aExpression) {
         let expressionItem =
    -      [i for (i in this) if (i.attachment.currentExpression == aVar.name)][0];
    +      [i for (i of this) if (i.attachment.currentExpression == aVar.name)][0];
     
         // Remove the watch expression if it's going to be empty or a duplicate.
         if (!aExpression || this.getAllStrings().indexOf(aExpression) != -1) {
    @@ -1366,7 +1366,7 @@ WatchExpressionsView.prototype = Heritage.extend(WidgetMethods, {
        */
       deleteExpression: function(aVar) {
         let expressionItem =
    -      [i for (i in this) if (i.attachment.currentExpression == aVar.name)][0];
    +      [i for (i of this) if (i.attachment.currentExpression == aVar.name)][0];
     
         // Remove the watch expression.
         this.remove(expressionItem);
    @@ -1998,7 +1998,7 @@ GlobalSearchView.prototype = Heritage.extend(WidgetMethods, {
       _createGlobalResultsUI: function(aGlobalResults) {
         let i = 0;
     
    -    for (let sourceResults in aGlobalResults) {
    +    for (let sourceResults of aGlobalResults) {
           if (i++ == 0) {
             this._createSourceResultsUI(sourceResults);
           } else {
    @@ -2123,7 +2123,7 @@ GlobalSearchView.prototype = Heritage.extend(WidgetMethods, {
     
     /**
      * An object containing all source results, grouped by source location.
    - * Iterable via "for (let [location, sourceResults] in globalResults) { }".
    + * Iterable via "for (let [location, sourceResults] of globalResults) { }".
      */
     function GlobalResults() {
       this._store = [];
    @@ -2150,7 +2150,7 @@ GlobalResults.prototype = {
     
     /**
      * An object containing all the matched lines for a specific source.
    - * Iterable via "for (let [lineNumber, lineResults] in sourceResults) { }".
    + * Iterable via "for (let [lineNumber, lineResults] of sourceResults) { }".
      *
      * @param string aUrl
      *        The target source url.
    @@ -2291,7 +2291,7 @@ SourceResults.prototype = {
     
     /**
      * An object containing all the matches for a specific line.
    - * Iterable via "for (let chunk in lineResults) { }".
    + * Iterable via "for (let chunk of lineResults) { }".
      *
      * @param number aLine
      *        The target line in the source.
    @@ -2436,12 +2436,10 @@ LineResults.prototype = {
     /**
      * A generator-iterator over the global, source or line results.
      */
    -GlobalResults.prototype.__iterator__ =
    -SourceResults.prototype.__iterator__ =
    -LineResults.prototype.__iterator__ = function() {
    -  for (let item of this._store) {
    -    yield item;
    -  }
    +GlobalResults.prototype["@@iterator"] =
    +SourceResults.prototype["@@iterator"] =
    +LineResults.prototype["@@iterator"] = function*() {
    +  yield* this._store;
     };
     
     /**
    diff --git a/browser/devtools/debugger/debugger-toolbar.js b/browser/devtools/debugger/debugger-toolbar.js
    index 4830f4b8fae9..50ca51265dfd 100644
    --- a/browser/devtools/debugger/debugger-toolbar.js
    +++ b/browser/devtools/debugger/debugger-toolbar.js
    @@ -615,7 +615,7 @@ StackFramesView.prototype = Heritage.extend(WidgetMethods, {
     
           // Update the context menu to show the currently selected stackframe item
           // as a checked entry.
    -      for (let otherItem in this) {
    +      for (let otherItem of this) {
             if (otherItem != stackframeItem) {
               otherItem.attachment.popup.menuitem.removeAttribute("checked");
             } else {
    diff --git a/browser/devtools/debugger/test/browser_dbg_breakpoints-contextmenu.js b/browser/devtools/debugger/test/browser_dbg_breakpoints-contextmenu.js
    index 838c45e2794e..1212e4fe85cb 100644
    --- a/browser/devtools/debugger/test/browser_dbg_breakpoints-contextmenu.js
    +++ b/browser/devtools/debugger/test/browser_dbg_breakpoints-contextmenu.js
    @@ -107,8 +107,8 @@ function test() {
       }
     
       function initialChecks() {
    -    for (let source in gSources) {
    -      for (let breakpoint in source) {
    +    for (let source of gSources) {
    +      for (let breakpoint of source) {
             ok(gBreakpoints._getAdded(breakpoint.attachment),
               "All breakpoint items should have corresponding promises (1).");
             ok(!gBreakpoints._getRemoving(breakpoint.attachment),
    @@ -223,8 +223,8 @@ function test() {
           is(!!selectedBreakpoint.attachment.disabled, false,
             "The targetted breakpoint should not have been disabled (" + aIndex + ").");
     
    -      for (let source in gSources) {
    -        for (let otherBreakpoint in source) {
    +      for (let source of gSources) {
    +        for (let otherBreakpoint of source) {
               if (otherBreakpoint != selectedBreakpoint) {
                 ok(!gBreakpoints._getAdded(otherBreakpoint.attachment),
                   "There should be no breakpoint client for a disabled breakpoint (9).");
    @@ -235,8 +235,8 @@ function test() {
           }
     
           waitForDebuggerEvents(gPanel, gDebugger.EVENTS.BREAKPOINT_ADDED, 4).then(() => {
    -        for (let source in gSources) {
    -          for (let someBreakpoint in source) {
    +        for (let source of gSources) {
    +          for (let someBreakpoint of source) {
                 ok(gBreakpoints._getAdded(someBreakpoint.attachment),
                   "There should be a breakpoint client for all enabled breakpoints (11).");
                 is(someBreakpoint.attachment.disabled, false,
    @@ -245,8 +245,8 @@ function test() {
             }
     
             waitForDebuggerEvents(gPanel, gDebugger.EVENTS.BREAKPOINT_REMOVED, 5).then(() => {
    -          for (let source in gSources) {
    -            for (let someBreakpoint in source) {
    +          for (let source of gSources) {
    +            for (let someBreakpoint of source) {
                   ok(!gBreakpoints._getAdded(someBreakpoint.attachment),
                     "There should be no breakpoint client for a disabled breakpoint (13).");
                   is(someBreakpoint.attachment.disabled, true,
    @@ -255,8 +255,8 @@ function test() {
               }
     
               waitForDebuggerEvents(gPanel, gDebugger.EVENTS.BREAKPOINT_ADDED, 5).then(() => {
    -            for (let source in gSources) {
    -              for (let someBreakpoint in source) {
    +            for (let source of gSources) {
    +              for (let someBreakpoint of source) {
                     ok(gBreakpoints._getAdded(someBreakpoint.attachment),
                       "There should be a breakpoint client for all enabled breakpoints (15).");
                     is(someBreakpoint.attachment.disabled, false,
    @@ -293,8 +293,8 @@ function test() {
           ok(!gSources._selectedBreakpointItem,
             "There should be no breakpoint available after removing all breakpoints.");
     
    -      for (let source in gSources) {
    -        for (let otherBreakpoint in source) {
    +      for (let source of gSources) {
    +        for (let otherBreakpoint of source) {
               ok(false, "It's a trap!");
             }
           }
    diff --git a/browser/devtools/netmonitor/netmonitor-view.js b/browser/devtools/netmonitor/netmonitor-view.js
    index 09d29c01c258..a6ce58834a4a 100644
    --- a/browser/devtools/netmonitor/netmonitor-view.js
    +++ b/browser/devtools/netmonitor/netmonitor-view.js
    @@ -1008,7 +1008,7 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
     
         // Apply CSS transforms to each waterfall in this container totalTime
         // accurately translate and resize as needed.
    -    for (let { target, attachment } in this) {
    +    for (let { target, attachment } of this) {
           let timingsNode = $(".requests-menu-timings", target);
           let startCapNode = $(".requests-menu-timings-cap.start", target);
           let endCapNode = $(".requests-menu-timings-cap.end", target);
    @@ -1144,7 +1144,7 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
        * Reapplies the current waterfall background on all request items.
        */
       _flushWaterfallBackgrounds: function() {
    -    for (let { target } in this) {
    +    for (let { target } of this) {
           let waterfallNode = $(".requests-menu-waterfall", target);
           waterfallNode.style.backgroundImage = this._cachedWaterfallBackground;
         }
    diff --git a/browser/devtools/scratchpad/test/browser_scratchpad_inspect.js b/browser/devtools/scratchpad/test/browser_scratchpad_inspect.js
    index b4e81a9916c4..1f1b5651757e 100644
    --- a/browser/devtools/scratchpad/test/browser_scratchpad_inspect.js
    +++ b/browser/devtools/scratchpad/test/browser_scratchpad_inspect.js
    @@ -28,9 +28,9 @@ function runTests()
     
         let found = false;
     
    -    outer: for (let scope in sidebar.variablesView) {
    -      for (let [, obj] in scope) {
    -        for (let [, prop] in obj) {
    +    outer: for (let scope of sidebar.variablesView) {
    +      for (let [, obj] of scope) {
    +        for (let [, prop] of obj) {
               if (prop.name == "a" && prop.value == "foobarBug636725") {
                 found = true;
                 break outer;
    diff --git a/browser/devtools/shared/widgets/VariablesView.jsm b/browser/devtools/shared/widgets/VariablesView.jsm
    index 50b925fa43a5..df0cc400d676 100644
    --- a/browser/devtools/shared/widgets/VariablesView.jsm
    +++ b/browser/devtools/shared/widgets/VariablesView.jsm
    @@ -55,7 +55,7 @@ const STR = Services.strings.createBundle(DBG_STRINGS_URI);
     
     /**
      * A tree view for inspecting scopes, objects and properties.
    - * Iterable via "for (let [id, scope] in instance) { }".
    + * Iterable via "for (let [id, scope] of instance) { }".
      * Requires the devtools common.css and debugger.css skin stylesheets.
      *
      * To allow replacing variable or property values in this view, provide an
    @@ -1126,7 +1126,7 @@ VariablesView.getterOrSetterDeleteCallback = function(aItem) {
     
     /**
      * A Scope is an object holding Variable instances.
    - * Iterable via "for (let [name, variable] in instance) { }".
    + * Iterable via "for (let [name, variable] of instance) { }".
      *
      * @param VariablesView aView
      *        The view to contain this scope.
    @@ -2077,7 +2077,7 @@ DevToolsUtils.defineLazyPrototypeGetter(Scope.prototype, "_batchItems", Array);
     
     /**
      * A Variable is a Scope holding Property instances.
    - * Iterable via "for (let [name, property] in instance) { }".
    + * Iterable via "for (let [name, property] of instance) { }".
      *
      * @param Scope aScope
      *        The scope to contain this variable.
    @@ -2867,7 +2867,7 @@ Variable.prototype = Heritage.extend(Scope.prototype, {
     
     /**
      * A Property is a Variable holding additional child Property instances.
    - * Iterable via "for (let [name, property] in instance) { }".
    + * Iterable via "for (let [name, property] of instance) { }".
      *
      * @param Variable aVar
      *        The variable to contain this property.
    @@ -2928,13 +2928,11 @@ Property.prototype = Heritage.extend(Variable.prototype, {
     /**
      * A generator-iterator over the VariablesView, Scopes, Variables and Properties.
      */
    -VariablesView.prototype.__iterator__ =
    -Scope.prototype.__iterator__ =
    -Variable.prototype.__iterator__ =
    -Property.prototype.__iterator__ = function() {
    -  for (let item of this._store) {
    -    yield item;
    -  }
    +VariablesView.prototype["@@iterator"] =
    +Scope.prototype["@@iterator"] =
    +Variable.prototype["@@iterator"] =
    +Property.prototype["@@iterator"] = function*() {
    +  yield* this._store;
     };
     
     /**
    diff --git a/browser/devtools/shared/widgets/ViewHelpers.jsm b/browser/devtools/shared/widgets/ViewHelpers.jsm
    index facbb2ba820e..582dbb147f29 100644
    --- a/browser/devtools/shared/widgets/ViewHelpers.jsm
    +++ b/browser/devtools/shared/widgets/ViewHelpers.jsm
    @@ -405,7 +405,7 @@ ViewHelpers.Prefs.prototype = {
     /**
      * A generic Item is used to describe children present in a Widget.
      * The label, value and description properties are necessarily strings.
    - * Iterable via "for (let childItem in parentItem) { }".
    + * Iterable via "for (let childItem of parentItem) { }".
      *
      * @param object aOwnerView
      *        The owner view creating this item.
    @@ -513,7 +513,7 @@ Item.prototype = {
         if (aItem.finalize) {
           aItem.finalize(aItem);
         }
    -    for (let childItem in aItem) {
    +    for (let childItem of aItem) {
           aItem.remove(childItem);
         }
     
    @@ -557,7 +557,7 @@ Item.prototype = {
     
     /**
      * Some generic Widget methods handling Item instances.
    - * Iterable via "for (let childItem in wrappedView) { }".
    + * Iterable via "for (let childItem of wrappedView) { }".
      *
      * Usage:
      *   function MyView() {
    @@ -1529,7 +1529,7 @@ this.WidgetMethods = {
         if (aItem.finalize) {
           aItem.finalize(aItem);
         }
    -    for (let childItem in aItem) {
    +    for (let childItem of aItem) {
           aItem.remove(childItem);
         }
     
    @@ -1654,9 +1654,7 @@ this.WidgetMethods = {
     /**
      * A generator-iterator over all the items in this container.
      */
    -Item.prototype.__iterator__ =
    -WidgetMethods.__iterator__ = function() {
    -  for (let [, item] of this._itemsByElement) {
    -    yield item;
    -  }
    +Item.prototype["@@iterator"] =
    +WidgetMethods["@@iterator"] = function*() {
    +  yield* this._itemsByElement.values();
     };
    
    From a0bd27f0870e492c74d44ea4282bd3875f956f45 Mon Sep 17 00:00:00 2001
    From: Matt Brubeck 
    Date: Wed, 6 Nov 2013 13:16:44 -0800
    Subject: [PATCH 25/82] Bug 934713 - Explicitly use $(PYTHON) to run
     config.status [r=gps]
    
    This fixes a mysterious bug where config.status has the wrong sys.path when
    this recipe is built using GNU Make on Windows.
    ---
     Makefile.in | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/Makefile.in b/Makefile.in
    index aa7ded0aae98..291f399e0db1 100644
    --- a/Makefile.in
    +++ b/Makefile.in
    @@ -69,7 +69,7 @@ config.status: $(topsrcdir)/configure
     
     backend.RecursiveMakeBackend:
     	@echo "Build configuration changed. Regenerating backend."
    -	./config.status
    +	$(PYTHON) config.status
     
     Makefile: backend.RecursiveMakeBackend
     	@$(TOUCH) $@
    
    From ed56f0b1b32bd164dbcf51974cfe1d8081d56571 Mon Sep 17 00:00:00 2001
    From: Brian Grinstead 
    Date: Tue, 5 Nov 2013 11:00:13 -0600
    Subject: [PATCH 26/82]  Last Comment Bug 931191 - Inspector janks for seconds
     at a time looking at chat.meatspac.es; r=mratcliffe
    
    ---
     toolkit/devtools/output-parser.js | 26 ++++++++++++++++++--------
     1 file changed, 18 insertions(+), 8 deletions(-)
    
    diff --git a/toolkit/devtools/output-parser.js b/toolkit/devtools/output-parser.js
    index 747998b6b718..13259bfb7230 100644
    --- a/toolkit/devtools/output-parser.js
    +++ b/toolkit/devtools/output-parser.js
    @@ -8,6 +8,7 @@ const {Cc, Ci, Cu} = require("chrome");
     const {colorUtils} = require("devtools/css-color");
     const {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
     
    +const MAX_ITERATIONS = 100;
     const REGEX_QUOTES = /^".*?"|^".*/;
     const REGEX_URL = /^url\(["']?(.+?)(?::(\d+))?["']?\)/;
     const REGEX_WHITESPACE = /^\s+/;
    @@ -135,6 +136,7 @@ OutputParser.prototype = {
         let dirty = false;
         let matched = null;
         let nameValueSupported = false;
    +    let i = 0;
     
         let trimMatchFromStart = function(match) {
           text = text.substr(match.length);
    @@ -207,6 +209,14 @@ OutputParser.prototype = {
           }
     
           dirty = false;
    +
    +      // Prevent this loop from slowing down the browser with too
    +      // many nodes being appended into output.
    +      i++;
    +      if (i > MAX_ITERATIONS) {
    +        trimMatchFromStart(text);
    +        this._appendTextNode(text);
    +      }
         }
     
         return this._toDOM();
    @@ -312,14 +322,10 @@ OutputParser.prototype = {
        */
       _appendTextNode: function(text) {
         let lastItem = this.parsed[this.parsed.length - 1];
    -
    -    if (typeof lastItem !== "undefined" && lastItem.nodeName === "#text") {
    -      lastItem.nodeValue += text;
    +    if (typeof lastItem === "string") {
    +      this.parsed[this.parsed.length - 1] = lastItem + text
         } else {
    -      let win = Services.appShell.hiddenDOMWindow;
    -      let doc = win.document;
    -      let textNode = doc.createTextNode(text);
    -      this.parsed.push(textNode);
    +      this.parsed.push(text);
         }
       },
     
    @@ -335,7 +341,11 @@ OutputParser.prototype = {
         let frag = doc.createDocumentFragment();
     
         for (let item of this.parsed) {
    -      frag.appendChild(item);
    +      if (typeof item === "string") {
    +        frag.appendChild(doc.createTextNode(item));
    +      } else {
    +        frag.appendChild(item);
    +      }
         }
     
         this.parsed.length = 0;
    
    From 8f0f084fed69ac2aec26feade19ce4894d8040d9 Mon Sep 17 00:00:00 2001
    From: Mark Finkle 
    Date: Wed, 6 Nov 2013 17:56:23 -0500
    Subject: [PATCH 27/82] Bug 880119 - Improve the API for GeckoView r=blassey
    
    ---
     mobile/android/base/GeckoView.java       | 174 ++++++++++++++++++++++-
     mobile/android/chrome/content/browser.js |  11 +-
     2 files changed, 178 insertions(+), 7 deletions(-)
    
    diff --git a/mobile/android/base/GeckoView.java b/mobile/android/base/GeckoView.java
    index c17cda45a3d5..a27b52d255b8 100644
    --- a/mobile/android/base/GeckoView.java
    +++ b/mobile/android/base/GeckoView.java
    @@ -29,6 +29,10 @@ import android.util.Log;
     import android.view.SurfaceHolder;
     import android.view.SurfaceView;
     
    +import java.util.ArrayList;
    +import java.util.Collections;
    +import java.util.List;
    +
     public class GeckoView extends LayerView
         implements GeckoEventListener, ContextGetter {
     
    @@ -90,14 +94,68 @@ public class GeckoView extends LayerView
             }
         }
     
    -    public void loadUrl(String uri) {
    -        Tabs.getInstance().loadUrl(uri);
    +    /**
    +    * Add a Browser to the GeckoView container.
    +    * @param url The URL resource to load into the new Browser.
    +    */
    +    public Browser addBrowser(String url) {
    +        Tab tab = Tabs.getInstance().loadUrl(url, Tabs.LOADURL_NEW_TAB);
    +        if (tab != null) {
    +            return new Browser(tab.getId());
    +        }
    +        return null;
         }
     
    -    public void loadUrlInNewTab(String uri) {
    -        Tabs.getInstance().loadUrl(uri, Tabs.LOADURL_NEW_TAB);
    -     }
    +    /**
    +    * Remove a Browser from the GeckoView container.
    +    * @param browser The Browser to remove.
    +    */
    +    public void removeBrowser(Browser browser) {
    +        Tab tab = Tabs.getInstance().getTab(browser.getId());
    +        if (tab != null) {
    +            Tabs.getInstance().closeTab(tab);
    +        }
    +    }
     
    +    /**
    +    * Set the active/visible Browser.
    +    * @param browser The Browser to make selected.
    +    */
    +    public void setCurrentBrowser(Browser browser) {
    +        Tab tab = Tabs.getInstance().getTab(browser.getId());
    +        if (tab != null) {
    +            Tabs.getInstance().selectTab(tab.getId());
    +        }
    +    }
    +
    +    /**
    +    * Get the active/visible Browser.
    +    * @return The current selected Browser.
    +    */
    +    public Browser getCurrentBrowser() {
    +        Tab tab = Tabs.getInstance().getSelectedTab();
    +        if (tab != null) {
    +            return new Browser(tab.getId());
    +        }
    +        return null;
    +    }
    +
    +    /**
    +    * Get the list of current Browsers in the GeckoView container.
    +    * @return An unmodifiable List of Browser objects.
    +    */
    +    public List getBrowsers() {
    +        ArrayList browsers = new ArrayList();
    +        Iterable tabs = Tabs.getInstance().getTabsInOrder();
    +        for (Tab tab : tabs) {
    +            browsers.add(new Browser(tab.getId()));
    +        }
    +        return Collections.unmodifiableList(browsers);
    +    }
    +
    +    /**
    +    * Not part of the public API. Ignore.
    +    */
         public void handleMessage(String event, JSONObject message) {
             if (event.equals("Gecko:Ready")) {
                 GeckoThread.setLaunchState(GeckoThread.LaunchState.GeckoRunning);
    @@ -119,4 +177,110 @@ public class GeckoView extends LayerView
         public static GeckoAppShell.GeckoInterface getGeckoInterface() {
             return GeckoAppShell.getGeckoInterface();
         }
    +
    +    /**
    +    * Wrapper for a browser in the GeckoView container. Associated with a browser
    +    * element in the Gecko system.
    +    */
    +    public class Browser {
    +        private final int mId;
    +        private Browser(int Id) {
    +            mId = Id;
    +        }
    +
    +        /**
    +        * Get the ID of the Browser. This is the same ID used by Gecko for it's underlying
    +        * browser element.
    +        * @return The integer ID of the Browser.
    +        */
    +        private int getId() {
    +            return mId;
    +        }
    +
    +        /**
    +        * Load a URL resource into the Browser.
    +        * @param url The URL string.
    +        */
    +        public void loadUrl(String url) {
    +            JSONObject args = new JSONObject();
    +            try {
    +                args.put("url", url);
    +                args.put("parentId", -1);
    +                args.put("newTab", false);
    +                args.put("tabID", mId);
    +            } catch (Exception e) {
    +                Log.w(LOGTAG, "Error building JSON arguments for loadUrl.", e);
    +            }
    +            GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Tab:Load", args.toString()));
    +        }
    +
    +        /**
    +        * Reload the current URL resource into the Browser. The URL is force loaded from the
    +        * network and is not pulled from cache.
    +        */
    +        public void reload() {
    +            Tab tab = Tabs.getInstance().getTab(mId);
    +            if (tab != null) {
    +                tab.doReload();
    +            }
    +        }
    +
    +        /**
    +        * Stop the current loading operation.
    +        */
    +        public void stop() {
    +            Tab tab = Tabs.getInstance().getTab(mId);
    +            if (tab != null) {
    +                tab.doStop();
    +            }
    +        }
    +
    +        /**
    +        * Check to see if the Browser has session history and can go back to a
    +        * previous page.
    +        * @return A boolean flag indicating if previous session exists.
    +        * This method will likely be removed and replaced by a callback in GeckoViewContent
    +        */
    +        public boolean canGoBack() {
    +            Tab tab = Tabs.getInstance().getTab(mId);
    +            if (tab != null) {
    +                return tab.canDoBack();
    +            }
    +            return false;
    +        }
    +
    +        /**
    +        * Move backward in the session history, if that's possible.
    +        */
    +        public void goBack() {
    +            Tab tab = Tabs.getInstance().getTab(mId);
    +            if (tab != null) {
    +                tab.doBack();
    +            }
    +        }
    +
    +        /**
    +        * Check to see if the Browser has session history and can go forward to a
    +        * new page.
    +        * @return A boolean flag indicating if forward session exists.
    +        * This method will likely be removed and replaced by a callback in GeckoViewContent
    +        */
    +        public boolean canGoForward() {
    +            Tab tab = Tabs.getInstance().getTab(mId);
    +            if (tab != null) {
    +                return tab.canDoForward();
    +            }
    +            return false;
    +        }
    +
    +        /**
    +        * Move forward in the session history, if that's possible.
    +        */
    +        public void goForward() {
    +            Tab tab = Tabs.getInstance().getTab(mId);
    +            if (tab != null) {
    +                tab.doForward();
    +            }
    +        }
    +    }
     }
    diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js
    index 2875be2fad85..182cb2f2cd8d 100644
    --- a/mobile/android/chrome/content/browser.js
    +++ b/mobile/android/chrome/content/browser.js
    @@ -1397,10 +1397,17 @@ var BrowserApp = {
             if (!shouldShowProgress(url))
               params.showProgress = false;
     
    -        if (data.newTab)
    +        if (data.newTab) {
               this.addTab(url, params);
    -        else
    +        } else {
    +          if (data.tabId) {
    +            // Use a specific browser instead of the selected browser, if it exists
    +            let specificBrowser = this.getTabForId(data.tabId).browser;
    +            if (specificBrowser)
    +              browser = specificBrowser;
    +          }
               this.loadURI(url, browser, params);
    +        }
             break;
           }
     
    
    From f8ec0ce9abf31353d133ee95ee3b1cbf758c7d5e Mon Sep 17 00:00:00 2001
    From: Mark Finkle 
    Date: Wed, 6 Nov 2013 17:58:29 -0500
    Subject: [PATCH 28/82] Bug 880121 - Add support for Browser (Chrome)
     application interfaces to GeckoView r=blassey
    
    ---
     mobile/android/base/GeckoView.java       | 45 +++++++++++++++++++-----
     mobile/android/base/GeckoViewChrome.java | 14 ++++++++
     mobile/android/base/moz.build            |  1 +
     3 files changed, 51 insertions(+), 9 deletions(-)
     create mode 100644 mobile/android/base/GeckoViewChrome.java
    
    diff --git a/mobile/android/base/GeckoView.java b/mobile/android/base/GeckoView.java
    index a27b52d255b8..29f9026c8ac4 100644
    --- a/mobile/android/base/GeckoView.java
    +++ b/mobile/android/base/GeckoView.java
    @@ -38,6 +38,8 @@ public class GeckoView extends LayerView
     
         private static final String LOGTAG = "GeckoView";
     
    +    private ChromeDelegate mChromeDelegate;
    +
         public GeckoView(Context context, AttributeSet attrs) {
             super(context, attrs);
             TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.GeckoView);
    @@ -158,18 +160,35 @@ public class GeckoView extends LayerView
         */
         public void handleMessage(String event, JSONObject message) {
             if (event.equals("Gecko:Ready")) {
    -            GeckoThread.setLaunchState(GeckoThread.LaunchState.GeckoRunning);
    -            Tab selectedTab = Tabs.getInstance().getSelectedTab();
    -            if (selectedTab != null)
    -                Tabs.getInstance().notifyListeners(selectedTab, Tabs.TabEvents.SELECTED);
    -            geckoConnected();
    -            GeckoAppShell.setLayerClient(getLayerClient());
    -            GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Viewport:Flush", null));
    -            show();
    -            requestRender();
    +            handleReady();
             }
         }
     
    +    private void handleReady() {
    +        GeckoThread.setLaunchState(GeckoThread.LaunchState.GeckoRunning);
    +        Tab selectedTab = Tabs.getInstance().getSelectedTab();
    +        if (selectedTab != null)
    +            Tabs.getInstance().notifyListeners(selectedTab, Tabs.TabEvents.SELECTED);
    +        geckoConnected();
    +        GeckoAppShell.setLayerClient(getLayerClient());
    +        GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Viewport:Flush", null));
    +        show();
    +        requestRender();
    +
    +        if (mChromeDelegate != null) {
    +            mChromeDelegate.onReady(this);
    +        }
    +    }
    +
    +    /**
    +    * Set the chrome callback handler.
    +    * This will replace the current handler.
    +    * @param chrome An implementation of GeckoViewChrome.
    +    */
    +    public void setChromeDelegate(ChromeDelegate chrome) {
    +        mChromeDelegate = chrome;
    +    }
    +
         public static void setGeckoInterface(final BaseGeckoInterface geckoInterface) {
             GeckoAppShell.setGeckoInterface(geckoInterface);
         }
    @@ -283,4 +302,12 @@ public class GeckoView extends LayerView
                 }
             }
         }
    +
    +    public interface ChromeDelegate {
    +        /**
    +        * Tell the host application that Gecko is ready to handle requests.
    +        * @param view The GeckoView that initiated the callback.
    +        */
    +        public void onReady(GeckoView view);
    +    }
     }
    diff --git a/mobile/android/base/GeckoViewChrome.java b/mobile/android/base/GeckoViewChrome.java
    new file mode 100644
    index 000000000000..efb2127d9b8e
    --- /dev/null
    +++ b/mobile/android/base/GeckoViewChrome.java
    @@ -0,0 +1,14 @@
    +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
    + * This Source Code Form is subject to the terms of the Mozilla Public
    + * License, v. 2.0. If a copy of the MPL was not distributed with this
    + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
    +
    +package org.mozilla.gecko;
    +
    +public class GeckoViewChrome implements GeckoView.ChromeDelegate {
    +    /**
    +    * Tell the host application that Gecko is ready to handle requests.
    +    * @param view The GeckoView that initiated the callback.
    +    */
    +    public void onReady(GeckoView view) {}
    +}
    diff --git a/mobile/android/base/moz.build b/mobile/android/base/moz.build
    index 93e95f3c68e0..d631990e1654 100644
    --- a/mobile/android/base/moz.build
    +++ b/mobile/android/base/moz.build
    @@ -148,6 +148,7 @@ gbjar.sources += [
         'GeckoJavaSampler.java',
         'GlobalHistory.java',
         'GeckoView.java',
    +    'GeckoViewChrome.java',
         'health/BrowserHealthRecorder.java',
         'health/BrowserHealthReporter.java',
         'InputMethods.java',
    
    From 3f114af3d23798e49f794c6c95ada3af7c886cc7 Mon Sep 17 00:00:00 2001
    From: Mark Finkle 
    Date: Wed, 6 Nov 2013 17:59:07 -0500
    Subject: [PATCH 29/82] Bug 880123 - Add support for content callback
     interfaces to GeckoView r=blassey
    
    ---
     mobile/android/base/GeckoView.java        | 137 +++++++++++++++++++++-
     mobile/android/base/GeckoViewContent.java |  51 ++++++++
     mobile/android/base/moz.build             |   1 +
     3 files changed, 184 insertions(+), 5 deletions(-)
     create mode 100644 mobile/android/base/GeckoViewContent.java
    
    diff --git a/mobile/android/base/GeckoView.java b/mobile/android/base/GeckoView.java
    index 29f9026c8ac4..9c597d45d485 100644
    --- a/mobile/android/base/GeckoView.java
    +++ b/mobile/android/base/GeckoView.java
    @@ -13,6 +13,7 @@ import org.mozilla.gecko.util.HardwareUtils;
     import org.mozilla.gecko.util.GeckoEventListener;
     import org.mozilla.gecko.util.ThreadUtils;
     
    +import org.json.JSONException;
     import org.json.JSONObject;
     
     import android.app.Activity;
    @@ -39,6 +40,7 @@ public class GeckoView extends LayerView
         private static final String LOGTAG = "GeckoView";
     
         private ChromeDelegate mChromeDelegate;
    +    private ContentDelegate mContentDelegate;
     
         public GeckoView(Context context, AttributeSet attrs) {
             super(context, attrs);
    @@ -82,7 +84,13 @@ public class GeckoView extends LayerView
                 Tabs tabs = Tabs.getInstance();
                 tabs.attachToContext(context);
             }
    +
             GeckoAppShell.registerEventListener("Gecko:Ready", this);
    +        GeckoAppShell.registerEventListener("Content:StateChange", this);
    +        GeckoAppShell.registerEventListener("Content:LoadError", this);
    +        GeckoAppShell.registerEventListener("Content:PageShow", this);
    +        GeckoAppShell.registerEventListener("DOMTitleChanged", this);
    +        GeckoAppShell.registerEventListener("Link:Favicon", this);
     
             ThreadUtils.setUiThread(Thread.currentThread(), new Handler());
             initializeView(GeckoAppShell.getEventDispatcher());
    @@ -158,13 +166,32 @@ public class GeckoView extends LayerView
         /**
         * Not part of the public API. Ignore.
         */
    -    public void handleMessage(String event, JSONObject message) {
    -        if (event.equals("Gecko:Ready")) {
    -            handleReady();
    -        }
    +    public void handleMessage(final String event, final JSONObject message) {
    +        ThreadUtils.postToUiThread(new Runnable() {
    +            @Override
    +            public void run() {
    +                try {
    +                    if (event.equals("Gecko:Ready")) {
    +                        GeckoView.this.handleReady(message);
    +                    } else if (event.equals("Content:StateChange")) {
    +                        GeckoView.this.handleStateChange(message);
    +                    } else if (event.equals("Content:LoadError")) {
    +                        GeckoView.this.handleLoadError(message);
    +                    } else if (event.equals("Content:PageShow")) {
    +                        GeckoView.this.handlePageShow(message);
    +                    } else if (event.equals("DOMTitleChanged")) {
    +                        GeckoView.this.handleTitleChanged(message);
    +                    } else if (event.equals("Link:Favicon")) {
    +                        GeckoView.this.handleLinkFavicon(message);
    +                    }
    +                } catch (Exception e) {
    +                    Log.w(LOGTAG, "handleMessage threw for " + event, e);
    +                }
    +            }
    +        });
         }
     
    -    private void handleReady() {
    +    private void handleReady(final JSONObject message) {
             GeckoThread.setLaunchState(GeckoThread.LaunchState.GeckoRunning);
             Tab selectedTab = Tabs.getInstance().getSelectedTab();
             if (selectedTab != null)
    @@ -180,6 +207,51 @@ public class GeckoView extends LayerView
             }
         }
     
    +    private void handleStateChange(final JSONObject message) throws JSONException {
    +        int state = message.getInt("state");
    +        if ((state & GeckoAppShell.WPL_STATE_IS_NETWORK) != 0) {
    +            if ((state & GeckoAppShell.WPL_STATE_START) != 0) {
    +                if (mContentDelegate != null) {
    +                    int id = message.getInt("tabID");
    +                    mContentDelegate.onPageStart(this, new Browser(id), message.getString("uri"));
    +                }
    +            } else if ((state & GeckoAppShell.WPL_STATE_STOP) != 0) {
    +                if (mContentDelegate != null) {
    +                    int id = message.getInt("tabID");
    +                    mContentDelegate.onPageStop(this, new Browser(id), message.getBoolean("success"));
    +                }
    +            }
    +        }
    +    }
    +
    +    private void handleLoadError(final JSONObject message) throws JSONException {
    +        if (mContentDelegate != null) {
    +            int id = message.getInt("tabID");
    +            mContentDelegate.onPageStop(GeckoView.this, new Browser(id), false);
    +        }
    +    }
    +
    +    private void handlePageShow(final JSONObject message) throws JSONException {
    +        if (mContentDelegate != null) {
    +            int id = message.getInt("tabID");
    +            mContentDelegate.onPageShow(GeckoView.this, new Browser(id));
    +        }
    +    }
    +
    +    private void handleTitleChanged(final JSONObject message) throws JSONException {
    +        if (mContentDelegate != null) {
    +            int id = message.getInt("tabID");
    +            mContentDelegate.onReceivedTitle(GeckoView.this, new Browser(id), message.getString("title"));
    +        }
    +    }
    +
    +    private void handleLinkFavicon(final JSONObject message) throws JSONException {
    +        if (mContentDelegate != null) {
    +            int id = message.getInt("tabID");
    +            mContentDelegate.onReceivedFavicon(GeckoView.this, new Browser(id), message.getString("href"), message.getInt("size"));
    +        }
    +    }
    +
         /**
         * Set the chrome callback handler.
         * This will replace the current handler.
    @@ -189,6 +261,15 @@ public class GeckoView extends LayerView
             mChromeDelegate = chrome;
         }
     
    +    /**
    +    * Set the content callback handler.
    +    * This will replace the current handler.
    +    * @param content An implementation of ContentDelegate.
    +    */
    +    public void setContentDelegate(ContentDelegate content) {
    +        mContentDelegate = content;
    +    }
    +
         public static void setGeckoInterface(final BaseGeckoInterface geckoInterface) {
             GeckoAppShell.setGeckoInterface(geckoInterface);
         }
    @@ -310,4 +391,50 @@ public class GeckoView extends LayerView
             */
             public void onReady(GeckoView view);
         }
    +
    +    public interface ContentDelegate {
    +        /**
    +        * A Browser has started loading content from the network.
    +        * @param view The GeckoView that initiated the callback.
    +        * @param browser The Browser that is loading the content.
    +        * @param url The resource being loaded.
    +        */
    +        public void onPageStart(GeckoView view, GeckoView.Browser browser, String url);
    +    
    +        /**
    +        * A Browser has finished loading content from the network.
    +        * @param view The GeckoView that initiated the callback.
    +        * @param browser The Browser that was loading the content.
    +        * @param success Whether the page loaded successfully or an error occured.
    +        */
    +        public void onPageStop(GeckoView view, GeckoView.Browser browser, boolean success);
    +    
    +        /**
    +        * A Browser is displaying content. This page could have been loaded via
    +        * network or from the session history.
    +        * @param view The GeckoView that initiated the callback.
    +        * @param browser The Browser that is showing the content.
    +        */
    +        public void onPageShow(GeckoView view, GeckoView.Browser browser);
    +    
    +        /**
    +        * A page title was discovered in the content or updated after the content
    +        * loaded.
    +        * @param view The GeckoView that initiated the callback.
    +        * @param browser The Browser that is showing the content.
    +        * @param title The title sent from the content.
    +        */
    +        public void onReceivedTitle(GeckoView view, GeckoView.Browser browser, String title);
    +    
    +        /**
    +        * A link element was discovered in the content or updated after the content
    +        * loaded that specifies a favicon.
    +        * @param view The GeckoView that initiated the callback.
    +        * @param browser The Browser that is showing the content.
    +        * @param url The href of the link element specifying the favicon.
    +        * @param size The maximum size specified for the favicon, or -1 for any size.
    +        */
    +        public void onReceivedFavicon(GeckoView view, GeckoView.Browser browser, String url, int size);
    +    }
    +
     }
    diff --git a/mobile/android/base/GeckoViewContent.java b/mobile/android/base/GeckoViewContent.java
    new file mode 100644
    index 000000000000..c5fb54c4c6c2
    --- /dev/null
    +++ b/mobile/android/base/GeckoViewContent.java
    @@ -0,0 +1,51 @@
    +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
    + * This Source Code Form is subject to the terms of the Mozilla Public
    + * License, v. 2.0. If a copy of the MPL was not distributed with this
    + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
    +
    +package org.mozilla.gecko;
    +
    +public class GeckoViewContent implements GeckoView.ContentDelegate {
    +    /**
    +    * A Browser has started loading content from the network.
    +    * @param view The GeckoView that initiated the callback.
    +    * @param browser The Browser that is loading the content.
    +    * @param url The resource being loaded.
    +    */
    +    public void onPageStart(GeckoView view, GeckoView.Browser browser, String url) {}
    +
    +    /**
    +    * A Browser has finished loading content from the network.
    +    * @param view The GeckoView that initiated the callback.
    +    * @param browser The Browser that was loading the content.
    +    * @param success Whether the page loaded successfully or an error occured.
    +    */
    +    public void onPageStop(GeckoView view, GeckoView.Browser browser, boolean success) {}
    +
    +    /**
    +    * A Browser is displaying content. This page could have been loaded via
    +    * network or from the session history.
    +    * @param view The GeckoView that initiated the callback.
    +    * @param browser The Browser that is showing the content.
    +    */
    +    public void onPageShow(GeckoView view, GeckoView.Browser browser) {}
    +
    +    /**
    +    * A page title was discovered in the content or updated after the content
    +    * loaded.
    +    * @param view The GeckoView that initiated the callback.
    +    * @param browser The Browser that is showing the content.
    +    * @param title The title sent from the content.
    +    */
    +    public void onReceivedTitle(GeckoView view, GeckoView.Browser browser, String title) {}
    +
    +    /**
    +    * A link element was discovered in the content or updated after the content
    +    * loaded that specifies a favicon.
    +    * @param view The GeckoView that initiated the callback.
    +    * @param browser The Browser that is showing the content.
    +    * @param url The href of the link element specifying the favicon.
    +    * @param size The maximum size specified for the favicon, or -1 for any size.
    +    */
    +    public void onReceivedFavicon(GeckoView view, GeckoView.Browser browser, String url, int size) {}
    +}
    diff --git a/mobile/android/base/moz.build b/mobile/android/base/moz.build
    index d631990e1654..33e1f1ed2269 100644
    --- a/mobile/android/base/moz.build
    +++ b/mobile/android/base/moz.build
    @@ -149,6 +149,7 @@ gbjar.sources += [
         'GlobalHistory.java',
         'GeckoView.java',
         'GeckoViewChrome.java',
    +    'GeckoViewContent.java',
         'health/BrowserHealthRecorder.java',
         'health/BrowserHealthReporter.java',
         'InputMethods.java',
    
    From 115cc337dcd571f6ebf24edd107c9edd20cb5043 Mon Sep 17 00:00:00 2001
    From: Mark Finkle 
    Date: Wed, 6 Nov 2013 17:59:11 -0500
    Subject: [PATCH 30/82] Bug 928756 - [geckoview] Convert prompt-based actions
     into separate GeckoView endpoints r=bnicholson
    
    ---
     mobile/android/base/GeckoView.java         | 114 +++++++++++++++++++++
     mobile/android/base/GeckoViewChrome.java   |  47 +++++++++
     mobile/android/chrome/content/browser.js   |   1 +
     mobile/android/components/PromptService.js |   3 +
     mobile/android/modules/Prompt.jsm          |  11 ++
     5 files changed, 176 insertions(+)
    
    diff --git a/mobile/android/base/GeckoView.java b/mobile/android/base/GeckoView.java
    index 9c597d45d485..52931d11c744 100644
    --- a/mobile/android/base/GeckoView.java
    +++ b/mobile/android/base/GeckoView.java
    @@ -91,6 +91,8 @@ public class GeckoView extends LayerView
             GeckoAppShell.registerEventListener("Content:PageShow", this);
             GeckoAppShell.registerEventListener("DOMTitleChanged", this);
             GeckoAppShell.registerEventListener("Link:Favicon", this);
    +        GeckoAppShell.registerEventListener("Prompt:Show", this);
    +        GeckoAppShell.registerEventListener("Prompt:ShowTop", this);
     
             ThreadUtils.setUiThread(Thread.currentThread(), new Handler());
             initializeView(GeckoAppShell.getEventDispatcher());
    @@ -183,6 +185,8 @@ public class GeckoView extends LayerView
                             GeckoView.this.handleTitleChanged(message);
                         } else if (event.equals("Link:Favicon")) {
                             GeckoView.this.handleLinkFavicon(message);
    +                    } else if (event.equals("Prompt:Show") || event.equals("Prompt:ShowTop")) {
    +                        GeckoView.this.handlePrompt(message);
                         }
                     } catch (Exception e) {
                         Log.w(LOGTAG, "handleMessage threw for " + event, e);
    @@ -252,6 +256,25 @@ public class GeckoView extends LayerView
             }
         }
     
    +    private void handlePrompt(final JSONObject message) throws JSONException {
    +        if (mChromeDelegate != null) {
    +            String hint = message.optString("hint");
    +            if ("alert".equals(hint)) {
    +                String text = message.optString("text");
    +                mChromeDelegate.onAlert(GeckoView.this, null, text, new PromptResult(message.optString("guid")));
    +            } else if ("confirm".equals(hint)) {
    +                String text = message.optString("text");
    +                mChromeDelegate.onConfirm(GeckoView.this, null, text, new PromptResult(message.optString("guid")));
    +            } else if ("prompt".equals(hint)) {
    +                String text = message.optString("text");
    +                String defaultValue = message.optString("textbox0");
    +                mChromeDelegate.onPrompt(GeckoView.this, null, text, defaultValue, new PromptResult(message.optString("guid")));
    +            } else if ("remotedebug".equals(hint)) {
    +                mChromeDelegate.onDebugRequest(GeckoView.this, new PromptResult(message.optString("guid")));
    +            }
    +        }
    +    }
    +
         /**
         * Set the chrome callback handler.
         * This will replace the current handler.
    @@ -384,12 +407,103 @@ public class GeckoView extends LayerView
             }
         }
     
    +    /* Provides a means for the client to indicate whether a JavaScript
    +     * dialog request should proceed. An instance of this class is passed to
    +     * various GeckoViewChrome callback actions.
    +     */
    +    public class PromptResult {
    +        private final int RESULT_OK = 0;
    +        private final int RESULT_CANCEL = 1;
    +
    +        private final String mGUID;
    +
    +        public PromptResult(String guid) {
    +            mGUID = guid;
    +        }
    +
    +        private JSONObject makeResult(int resultCode) {
    +            JSONObject result = new JSONObject();
    +            try {
    +                result.put("guid", mGUID);
    +                result.put("button", resultCode);
    +            } catch(JSONException ex) { }
    +            return result;
    +        }
    +
    +        /**
    +        * Handle a confirmation response from the user.
    +        */
    +        public void confirm() {
    +            JSONObject result = makeResult(RESULT_OK);
    +            GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Prompt:Reply", result.toString()));
    +        }
    +
    +        /**
    +        * Handle a confirmation response from the user.
    +        * @param value String value to return to the browser context.
    +        */
    +        public void confirmWithValue(String value) {
    +            JSONObject result = makeResult(RESULT_OK);
    +            try {
    +                result.put("textbox0", value);
    +            } catch(JSONException ex) { }
    +            GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Prompt:Reply", result.toString()));
    +        }
    +
    +        /**
    +        * Handle a cancellation response from the user.
    +        */
    +        public void cancel() {
    +            JSONObject result = makeResult(RESULT_CANCEL);
    +            GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Prompt:Reply", result.toString()));
    +        }
    +    }
    +
         public interface ChromeDelegate {
             /**
             * Tell the host application that Gecko is ready to handle requests.
             * @param view The GeckoView that initiated the callback.
             */
             public void onReady(GeckoView view);
    +
    +        /**
    +        * Tell the host application to display an alert dialog.
    +        * @param view The GeckoView that initiated the callback.
    +        * @param browser The Browser that is loading the content.
    +        * @param message The string to display in the dialog.
    +        * @param result A PromptResult used to send back the result without blocking.
    +        * Defaults to cancel requests.
    +        */
    +        public void onAlert(GeckoView view, GeckoView.Browser browser, String message, GeckoView.PromptResult result);
    +    
    +        /**
    +        * Tell the host application to display a confirmation dialog.
    +        * @param view The GeckoView that initiated the callback.
    +        * @param browser The Browser that is loading the content.
    +        * @param message The string to display in the dialog.
    +        * @param result A PromptResult used to send back the result without blocking.
    +        * Defaults to cancel requests.
    +        */
    +        public void onConfirm(GeckoView view, GeckoView.Browser browser, String message, GeckoView.PromptResult result);
    +    
    +        /**
    +        * Tell the host application to display an input prompt dialog.
    +        * @param view The GeckoView that initiated the callback.
    +        * @param browser The Browser that is loading the content.
    +        * @param message The string to display in the dialog.
    +        * @param defaultValue The string to use as default input.
    +        * @param result A PromptResult used to send back the result without blocking.
    +        * Defaults to cancel requests.
    +        */
    +        public void onPrompt(GeckoView view, GeckoView.Browser browser, String message, String defaultValue, GeckoView.PromptResult result);
    +    
    +        /**
    +        * Tell the host application to display a remote debugging request dialog.
    +        * @param view The GeckoView that initiated the callback.
    +        * @param result A PromptResult used to send back the result without blocking.
    +        * Defaults to cancel requests.
    +        */
    +        public void onDebugRequest(GeckoView view, GeckoView.PromptResult result);
         }
     
         public interface ContentDelegate {
    diff --git a/mobile/android/base/GeckoViewChrome.java b/mobile/android/base/GeckoViewChrome.java
    index efb2127d9b8e..e6d0945882d3 100644
    --- a/mobile/android/base/GeckoViewChrome.java
    +++ b/mobile/android/base/GeckoViewChrome.java
    @@ -11,4 +11,51 @@ public class GeckoViewChrome implements GeckoView.ChromeDelegate {
         * @param view The GeckoView that initiated the callback.
         */
         public void onReady(GeckoView view) {}
    +
    +    /**
    +    * Tell the host application to display an alert dialog.
    +    * @param view The GeckoView that initiated the callback.
    +    * @param browser The Browser that is loading the content.
    +    * @param message The string to display in the dialog.
    +    * @param result A PromptResult used to send back the result without blocking.
    +    * Defaults to cancel requests.
    +    */
    +    public void onAlert(GeckoView view, GeckoView.Browser browser, String message, GeckoView.PromptResult result) {
    +        result.cancel();
    +    }
    +
    +    /**
    +    * Tell the host application to display a confirmation dialog.
    +    * @param view The GeckoView that initiated the callback.
    +    * @param browser The Browser that is loading the content.
    +    * @param message The string to display in the dialog.
    +    * @param result A PromptResult used to send back the result without blocking.
    +    * Defaults to cancel requests.
    +    */
    +    public void onConfirm(GeckoView view, GeckoView.Browser browser, String message, GeckoView.PromptResult result) {
    +        result.cancel();
    +    }
    +
    +    /**
    +    * Tell the host application to display an input prompt dialog.
    +    * @param view The GeckoView that initiated the callback.
    +    * @param browser The Browser that is loading the content.
    +    * @param message The string to display in the dialog.
    +    * @param defaultValue The string to use as default input.
    +    * @param result A PromptResult used to send back the result without blocking.
    +    * Defaults to cancel requests.
    +    */
    +    public void onPrompt(GeckoView view, GeckoView.Browser browser, String message, String defaultValue, GeckoView.PromptResult result) {
    +        result.cancel();
    +    }
    +
    +    /**
    +    * Tell the host application to display a remote debugging request dialog.
    +    * @param view The GeckoView that initiated the callback.
    +    * @param result A PromptResult used to send back the result without blocking.
    +    * Defaults to cancel requests.
    +    */
    +    public void onDebugRequest(GeckoView view, GeckoView.PromptResult result) {
    +        result.cancel();
    +    }
     }
    diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js
    index 182cb2f2cd8d..d1de7a631390 100644
    --- a/mobile/android/chrome/content/browser.js
    +++ b/mobile/android/chrome/content/browser.js
    @@ -7125,6 +7125,7 @@ var RemoteDebugger = {
         // Make prompt. Note: button order is in reverse.
         let prompt = new Prompt({
           window: null,
    +      hint: "remotedebug",
           title: title,
           message: msg,
           buttons: [ agree, cancel, disable ],
    diff --git a/mobile/android/components/PromptService.js b/mobile/android/components/PromptService.js
    index 4bf08979dadb..67abd6b3d93d 100644
    --- a/mobile/android/components/PromptService.js
    +++ b/mobile/android/components/PromptService.js
    @@ -218,6 +218,7 @@ InternalPrompt.prototype = {
     
       alert: function alert(aTitle, aText) {
         let p = this._getPrompt(aTitle, aText, [ PromptUtils.getLocaleString("OK") ]);
    +    p.setHint("alert");
         this.showPrompt(p);
       },
     
    @@ -230,6 +231,7 @@ InternalPrompt.prototype = {
     
       confirm: function confirm(aTitle, aText) {
         let p = this._getPrompt(aTitle, aText);
    +    p.setHint("confirm");
         let data = this.showPrompt(p);
         return (data.button == 0);
       },
    @@ -291,6 +293,7 @@ InternalPrompt.prototype = {
     
       nsIPrompt_prompt: function nsIPrompt_prompt(aTitle, aText, aValue, aCheckMsg, aCheckState) {
         let p = this._getPrompt(aTitle, aText, null, aCheckMsg, aCheckState);
    +    p.setHint("prompt");
         p.addTextbox({
           value: aValue.value,
           autofocus: true
    diff --git a/mobile/android/modules/Prompt.jsm b/mobile/android/modules/Prompt.jsm
    index 5999f30a2a8a..a4a8f42af73d 100644
    --- a/mobile/android/modules/Prompt.jsm
    +++ b/mobile/android/modules/Prompt.jsm
    @@ -32,12 +32,23 @@ function Prompt(aOptions) {
       if ("buttons" in aOptions && aOptions.buttons != null)
         this.msg.buttons = aOptions.buttons;
     
    +  if ("hint" in aOptions && aOptions.hint != null)
    +    this.msg.hint = aOptions.hint;
    +
       let idService = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator); 
       this.guid = idService.generateUUID().toString();
       this.msg.guid = this.guid;
     }
     
     Prompt.prototype = {
    +  setHint: function(aHint) {
    +    if (!aHint)
    +      delete this.msg.hint;
    +    else
    +      this.msg.hint = aHint;
    +    return this;
    +  },
    +
       addButton: function(aOptions) {
         if (!this.msg.buttons)
           this.msg.buttons = [];
    
    From 19f53ae65decc0b8bde1b95a47e30cdcb19565ad Mon Sep 17 00:00:00 2001
    From: Wes Kocher 
    Date: Wed, 6 Nov 2013 15:13:53 -0800
    Subject: [PATCH 31/82] Backed out changeset 7dd13d06f132 (bug 862849) for
     breaking webconsole tests
    
    ---
     browser/devtools/debugger/CmdDebugger.jsm     |  4 +--
     browser/devtools/debugger/debugger-panes.js   | 26 ++++++++++---------
     browser/devtools/debugger/debugger-toolbar.js |  2 +-
     .../browser_dbg_breakpoints-contextmenu.js    | 24 ++++++++---------
     .../devtools/netmonitor/netmonitor-view.js    |  4 +--
     .../test/browser_scratchpad_inspect.js        |  6 ++---
     .../devtools/shared/widgets/VariablesView.jsm | 20 +++++++-------
     .../devtools/shared/widgets/ViewHelpers.jsm   | 16 +++++++-----
     8 files changed, 54 insertions(+), 48 deletions(-)
    
    diff --git a/browser/devtools/debugger/CmdDebugger.jsm b/browser/devtools/debugger/CmdDebugger.jsm
    index 59231e23eebf..3f910d7dce87 100644
    --- a/browser/devtools/debugger/CmdDebugger.jsm
    +++ b/browser/devtools/debugger/CmdDebugger.jsm
    @@ -37,8 +37,8 @@ function getAllBreakpoints(dbg) {
       let sources = dbg._view.Sources;
       let { trimUrlLength: trim } = dbg.panelWin.SourceUtils;
     
    -  for (let source of sources) {
    -    for (let { attachment: breakpoint } of source) {
    +  for (let source in sources) {
    +    for (let { attachment: breakpoint } in source) {
           breakpoints.push({
             url: source.value,
             label: source.label + ":" + breakpoint.line,
    diff --git a/browser/devtools/debugger/debugger-panes.js b/browser/devtools/debugger/debugger-panes.js
    index 1c938ab549f1..d42bfc38d172 100644
    --- a/browser/devtools/debugger/debugger-panes.js
    +++ b/browser/devtools/debugger/debugger-panes.js
    @@ -231,8 +231,8 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
        *         The corresponding breakpoints if found, an empty array otherwise.
        */
       getOtherBreakpoints: function(aLocation = {}, aStore = []) {
    -    for (let source of this) {
    -      for (let breakpointItem of source) {
    +    for (let source in this) {
    +      for (let breakpointItem in source) {
             let { url, line } = breakpointItem.attachment;
             if (url != aLocation.url || line != aLocation.line) {
               aStore.push(breakpointItem);
    @@ -1340,7 +1340,7 @@ WatchExpressionsView.prototype = Heritage.extend(WidgetMethods, {
        */
       switchExpression: function(aVar, aExpression) {
         let expressionItem =
    -      [i for (i of this) if (i.attachment.currentExpression == aVar.name)][0];
    +      [i for (i in this) if (i.attachment.currentExpression == aVar.name)][0];
     
         // Remove the watch expression if it's going to be empty or a duplicate.
         if (!aExpression || this.getAllStrings().indexOf(aExpression) != -1) {
    @@ -1366,7 +1366,7 @@ WatchExpressionsView.prototype = Heritage.extend(WidgetMethods, {
        */
       deleteExpression: function(aVar) {
         let expressionItem =
    -      [i for (i of this) if (i.attachment.currentExpression == aVar.name)][0];
    +      [i for (i in this) if (i.attachment.currentExpression == aVar.name)][0];
     
         // Remove the watch expression.
         this.remove(expressionItem);
    @@ -1998,7 +1998,7 @@ GlobalSearchView.prototype = Heritage.extend(WidgetMethods, {
       _createGlobalResultsUI: function(aGlobalResults) {
         let i = 0;
     
    -    for (let sourceResults of aGlobalResults) {
    +    for (let sourceResults in aGlobalResults) {
           if (i++ == 0) {
             this._createSourceResultsUI(sourceResults);
           } else {
    @@ -2123,7 +2123,7 @@ GlobalSearchView.prototype = Heritage.extend(WidgetMethods, {
     
     /**
      * An object containing all source results, grouped by source location.
    - * Iterable via "for (let [location, sourceResults] of globalResults) { }".
    + * Iterable via "for (let [location, sourceResults] in globalResults) { }".
      */
     function GlobalResults() {
       this._store = [];
    @@ -2150,7 +2150,7 @@ GlobalResults.prototype = {
     
     /**
      * An object containing all the matched lines for a specific source.
    - * Iterable via "for (let [lineNumber, lineResults] of sourceResults) { }".
    + * Iterable via "for (let [lineNumber, lineResults] in sourceResults) { }".
      *
      * @param string aUrl
      *        The target source url.
    @@ -2291,7 +2291,7 @@ SourceResults.prototype = {
     
     /**
      * An object containing all the matches for a specific line.
    - * Iterable via "for (let chunk of lineResults) { }".
    + * Iterable via "for (let chunk in lineResults) { }".
      *
      * @param number aLine
      *        The target line in the source.
    @@ -2436,10 +2436,12 @@ LineResults.prototype = {
     /**
      * A generator-iterator over the global, source or line results.
      */
    -GlobalResults.prototype["@@iterator"] =
    -SourceResults.prototype["@@iterator"] =
    -LineResults.prototype["@@iterator"] = function*() {
    -  yield* this._store;
    +GlobalResults.prototype.__iterator__ =
    +SourceResults.prototype.__iterator__ =
    +LineResults.prototype.__iterator__ = function() {
    +  for (let item of this._store) {
    +    yield item;
    +  }
     };
     
     /**
    diff --git a/browser/devtools/debugger/debugger-toolbar.js b/browser/devtools/debugger/debugger-toolbar.js
    index 50ca51265dfd..4830f4b8fae9 100644
    --- a/browser/devtools/debugger/debugger-toolbar.js
    +++ b/browser/devtools/debugger/debugger-toolbar.js
    @@ -615,7 +615,7 @@ StackFramesView.prototype = Heritage.extend(WidgetMethods, {
     
           // Update the context menu to show the currently selected stackframe item
           // as a checked entry.
    -      for (let otherItem of this) {
    +      for (let otherItem in this) {
             if (otherItem != stackframeItem) {
               otherItem.attachment.popup.menuitem.removeAttribute("checked");
             } else {
    diff --git a/browser/devtools/debugger/test/browser_dbg_breakpoints-contextmenu.js b/browser/devtools/debugger/test/browser_dbg_breakpoints-contextmenu.js
    index 1212e4fe85cb..838c45e2794e 100644
    --- a/browser/devtools/debugger/test/browser_dbg_breakpoints-contextmenu.js
    +++ b/browser/devtools/debugger/test/browser_dbg_breakpoints-contextmenu.js
    @@ -107,8 +107,8 @@ function test() {
       }
     
       function initialChecks() {
    -    for (let source of gSources) {
    -      for (let breakpoint of source) {
    +    for (let source in gSources) {
    +      for (let breakpoint in source) {
             ok(gBreakpoints._getAdded(breakpoint.attachment),
               "All breakpoint items should have corresponding promises (1).");
             ok(!gBreakpoints._getRemoving(breakpoint.attachment),
    @@ -223,8 +223,8 @@ function test() {
           is(!!selectedBreakpoint.attachment.disabled, false,
             "The targetted breakpoint should not have been disabled (" + aIndex + ").");
     
    -      for (let source of gSources) {
    -        for (let otherBreakpoint of source) {
    +      for (let source in gSources) {
    +        for (let otherBreakpoint in source) {
               if (otherBreakpoint != selectedBreakpoint) {
                 ok(!gBreakpoints._getAdded(otherBreakpoint.attachment),
                   "There should be no breakpoint client for a disabled breakpoint (9).");
    @@ -235,8 +235,8 @@ function test() {
           }
     
           waitForDebuggerEvents(gPanel, gDebugger.EVENTS.BREAKPOINT_ADDED, 4).then(() => {
    -        for (let source of gSources) {
    -          for (let someBreakpoint of source) {
    +        for (let source in gSources) {
    +          for (let someBreakpoint in source) {
                 ok(gBreakpoints._getAdded(someBreakpoint.attachment),
                   "There should be a breakpoint client for all enabled breakpoints (11).");
                 is(someBreakpoint.attachment.disabled, false,
    @@ -245,8 +245,8 @@ function test() {
             }
     
             waitForDebuggerEvents(gPanel, gDebugger.EVENTS.BREAKPOINT_REMOVED, 5).then(() => {
    -          for (let source of gSources) {
    -            for (let someBreakpoint of source) {
    +          for (let source in gSources) {
    +            for (let someBreakpoint in source) {
                   ok(!gBreakpoints._getAdded(someBreakpoint.attachment),
                     "There should be no breakpoint client for a disabled breakpoint (13).");
                   is(someBreakpoint.attachment.disabled, true,
    @@ -255,8 +255,8 @@ function test() {
               }
     
               waitForDebuggerEvents(gPanel, gDebugger.EVENTS.BREAKPOINT_ADDED, 5).then(() => {
    -            for (let source of gSources) {
    -              for (let someBreakpoint of source) {
    +            for (let source in gSources) {
    +              for (let someBreakpoint in source) {
                     ok(gBreakpoints._getAdded(someBreakpoint.attachment),
                       "There should be a breakpoint client for all enabled breakpoints (15).");
                     is(someBreakpoint.attachment.disabled, false,
    @@ -293,8 +293,8 @@ function test() {
           ok(!gSources._selectedBreakpointItem,
             "There should be no breakpoint available after removing all breakpoints.");
     
    -      for (let source of gSources) {
    -        for (let otherBreakpoint of source) {
    +      for (let source in gSources) {
    +        for (let otherBreakpoint in source) {
               ok(false, "It's a trap!");
             }
           }
    diff --git a/browser/devtools/netmonitor/netmonitor-view.js b/browser/devtools/netmonitor/netmonitor-view.js
    index a6ce58834a4a..09d29c01c258 100644
    --- a/browser/devtools/netmonitor/netmonitor-view.js
    +++ b/browser/devtools/netmonitor/netmonitor-view.js
    @@ -1008,7 +1008,7 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
     
         // Apply CSS transforms to each waterfall in this container totalTime
         // accurately translate and resize as needed.
    -    for (let { target, attachment } of this) {
    +    for (let { target, attachment } in this) {
           let timingsNode = $(".requests-menu-timings", target);
           let startCapNode = $(".requests-menu-timings-cap.start", target);
           let endCapNode = $(".requests-menu-timings-cap.end", target);
    @@ -1144,7 +1144,7 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
        * Reapplies the current waterfall background on all request items.
        */
       _flushWaterfallBackgrounds: function() {
    -    for (let { target } of this) {
    +    for (let { target } in this) {
           let waterfallNode = $(".requests-menu-waterfall", target);
           waterfallNode.style.backgroundImage = this._cachedWaterfallBackground;
         }
    diff --git a/browser/devtools/scratchpad/test/browser_scratchpad_inspect.js b/browser/devtools/scratchpad/test/browser_scratchpad_inspect.js
    index 1f1b5651757e..b4e81a9916c4 100644
    --- a/browser/devtools/scratchpad/test/browser_scratchpad_inspect.js
    +++ b/browser/devtools/scratchpad/test/browser_scratchpad_inspect.js
    @@ -28,9 +28,9 @@ function runTests()
     
         let found = false;
     
    -    outer: for (let scope of sidebar.variablesView) {
    -      for (let [, obj] of scope) {
    -        for (let [, prop] of obj) {
    +    outer: for (let scope in sidebar.variablesView) {
    +      for (let [, obj] in scope) {
    +        for (let [, prop] in obj) {
               if (prop.name == "a" && prop.value == "foobarBug636725") {
                 found = true;
                 break outer;
    diff --git a/browser/devtools/shared/widgets/VariablesView.jsm b/browser/devtools/shared/widgets/VariablesView.jsm
    index df0cc400d676..50b925fa43a5 100644
    --- a/browser/devtools/shared/widgets/VariablesView.jsm
    +++ b/browser/devtools/shared/widgets/VariablesView.jsm
    @@ -55,7 +55,7 @@ const STR = Services.strings.createBundle(DBG_STRINGS_URI);
     
     /**
      * A tree view for inspecting scopes, objects and properties.
    - * Iterable via "for (let [id, scope] of instance) { }".
    + * Iterable via "for (let [id, scope] in instance) { }".
      * Requires the devtools common.css and debugger.css skin stylesheets.
      *
      * To allow replacing variable or property values in this view, provide an
    @@ -1126,7 +1126,7 @@ VariablesView.getterOrSetterDeleteCallback = function(aItem) {
     
     /**
      * A Scope is an object holding Variable instances.
    - * Iterable via "for (let [name, variable] of instance) { }".
    + * Iterable via "for (let [name, variable] in instance) { }".
      *
      * @param VariablesView aView
      *        The view to contain this scope.
    @@ -2077,7 +2077,7 @@ DevToolsUtils.defineLazyPrototypeGetter(Scope.prototype, "_batchItems", Array);
     
     /**
      * A Variable is a Scope holding Property instances.
    - * Iterable via "for (let [name, property] of instance) { }".
    + * Iterable via "for (let [name, property] in instance) { }".
      *
      * @param Scope aScope
      *        The scope to contain this variable.
    @@ -2867,7 +2867,7 @@ Variable.prototype = Heritage.extend(Scope.prototype, {
     
     /**
      * A Property is a Variable holding additional child Property instances.
    - * Iterable via "for (let [name, property] of instance) { }".
    + * Iterable via "for (let [name, property] in instance) { }".
      *
      * @param Variable aVar
      *        The variable to contain this property.
    @@ -2928,11 +2928,13 @@ Property.prototype = Heritage.extend(Variable.prototype, {
     /**
      * A generator-iterator over the VariablesView, Scopes, Variables and Properties.
      */
    -VariablesView.prototype["@@iterator"] =
    -Scope.prototype["@@iterator"] =
    -Variable.prototype["@@iterator"] =
    -Property.prototype["@@iterator"] = function*() {
    -  yield* this._store;
    +VariablesView.prototype.__iterator__ =
    +Scope.prototype.__iterator__ =
    +Variable.prototype.__iterator__ =
    +Property.prototype.__iterator__ = function() {
    +  for (let item of this._store) {
    +    yield item;
    +  }
     };
     
     /**
    diff --git a/browser/devtools/shared/widgets/ViewHelpers.jsm b/browser/devtools/shared/widgets/ViewHelpers.jsm
    index 582dbb147f29..facbb2ba820e 100644
    --- a/browser/devtools/shared/widgets/ViewHelpers.jsm
    +++ b/browser/devtools/shared/widgets/ViewHelpers.jsm
    @@ -405,7 +405,7 @@ ViewHelpers.Prefs.prototype = {
     /**
      * A generic Item is used to describe children present in a Widget.
      * The label, value and description properties are necessarily strings.
    - * Iterable via "for (let childItem of parentItem) { }".
    + * Iterable via "for (let childItem in parentItem) { }".
      *
      * @param object aOwnerView
      *        The owner view creating this item.
    @@ -513,7 +513,7 @@ Item.prototype = {
         if (aItem.finalize) {
           aItem.finalize(aItem);
         }
    -    for (let childItem of aItem) {
    +    for (let childItem in aItem) {
           aItem.remove(childItem);
         }
     
    @@ -557,7 +557,7 @@ Item.prototype = {
     
     /**
      * Some generic Widget methods handling Item instances.
    - * Iterable via "for (let childItem of wrappedView) { }".
    + * Iterable via "for (let childItem in wrappedView) { }".
      *
      * Usage:
      *   function MyView() {
    @@ -1529,7 +1529,7 @@ this.WidgetMethods = {
         if (aItem.finalize) {
           aItem.finalize(aItem);
         }
    -    for (let childItem of aItem) {
    +    for (let childItem in aItem) {
           aItem.remove(childItem);
         }
     
    @@ -1654,7 +1654,9 @@ this.WidgetMethods = {
     /**
      * A generator-iterator over all the items in this container.
      */
    -Item.prototype["@@iterator"] =
    -WidgetMethods["@@iterator"] = function*() {
    -  yield* this._itemsByElement.values();
    +Item.prototype.__iterator__ =
    +WidgetMethods.__iterator__ = function() {
    +  for (let [, item] of this._itemsByElement) {
    +    yield item;
    +  }
     };
    
    From 579c0f4be113adadf7b57aa43546aaac92b417b5 Mon Sep 17 00:00:00 2001
    From: Chenxia Liu 
    Date: Wed, 6 Nov 2013 15:21:56 -0800
    Subject: [PATCH 32/82] Bug 852608 - Part 1: Support opensearch 
     tag. r=lucasr
    
    ---
     mobile/android/chrome/content/browser.js | 54 ++++++++++++++++++++++++
     1 file changed, 54 insertions(+)
    
    diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js
    index d1de7a631390..08b52c00463f 100644
    --- a/mobile/android/chrome/content/browser.js
    +++ b/mobile/android/chrome/content/browser.js
    @@ -3494,6 +3494,60 @@ Tab.prototype = {
                 };
                 sendMessageToJava(json);
               } catch (e) {}
    +        } else if (list.indexOf("[search]" != -1)) {
    +          let type = target.type && target.type.toLowerCase();
    +
    +          // Replace all starting or trailing spaces or spaces before "*;" globally w/ "".
    +          type = type.replace(/^\s+|\s*(?:;.*)?$/g, "");
    +
    +          // Check that type matches opensearch.
    +          let isOpenSearch = (type == "application/opensearchdescription+xml");
    +          if (isOpenSearch && target.title && /^(?:https?|ftp):/i.test(target.href)) {
    +            let visibleEngines = Services.search.getVisibleEngines();
    +            // NOTE: Engines are currently identified by name, but this can be changed
    +            // when Engines are identified by URL (see bug 335102).
    +            if (visibleEngines.some(function(e) {
    +              return e.name == target.title;
    +            })) {
    +              // This engine is already present, do nothing.
    +              return;
    +            }
    +
    +            if (this.browser.engines) {
    +              // This engine has already been handled, do nothing.
    +              if (this.browser.engines.some(function(e) {
    +                return e.url == target.href;
    +              })) {
    +                  return;
    +              }
    +            } else {
    +              this.browser.engines = [];
    +            }
    +
    +            // Get favicon.
    +            let iconURL = target.ownerDocument.documentURIObject.prePath + "/favicon.ico";
    +
    +            let newEngine = {
    +              title: target.title,
    +              url: target.href,
    +              iconURL: iconURL
    +            };
    +
    +            this.browser.engines.push(newEngine);
    +
    +            // Don't send a message to display engines if we've already handled an engine.
    +            if (this.browser.engines.length > 1)
    +              return;
    +
    +            // Broadcast message that this tab contains search engines that should be visible.
    +            let newEngineMessage = {
    +              type: "Link:OpenSearch",
    +              tabID: this.id,
    +              visible: true
    +            };
    +
    +            sendMessageToJava(newEngineMessage);
    +          }
             }
             break;
           }
    
    From 773ca272ed823fa51146af1b02ed5daf835b57fd Mon Sep 17 00:00:00 2001
    From: Chenxia Liu 
    Date: Wed, 6 Nov 2013 15:21:56 -0800
    Subject: [PATCH 33/82] Bug 852608 - Part 2: Support adding search engines.
     r=lucasr
    
    ---
     mobile/android/chrome/content/browser.js      | 49 +++++++++++++++++++
     .../locales/en-US/chrome/browser.properties   |  5 ++
     2 files changed, 54 insertions(+)
    
    diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js
    index 08b52c00463f..65a7de299740 100644
    --- a/mobile/android/chrome/content/browser.js
    +++ b/mobile/android/chrome/content/browser.js
    @@ -6617,6 +6617,7 @@ var SearchEngines = {
       PREF_SUGGEST_PROMPTED: "browser.search.suggest.prompted",
     
       init: function init() {
    +    Services.obs.addObserver(this, "SearchEngines:Add", false);
         Services.obs.addObserver(this, "SearchEngines:Get", false);
         Services.obs.addObserver(this, "SearchEngines:GetVisible", false);
         Services.obs.addObserver(this, "SearchEngines:SetDefault", false);
    @@ -6631,6 +6632,7 @@ var SearchEngines = {
       },
     
       uninit: function uninit() {
    +    Services.obs.removeObserver(this, "SearchEngines:Add");
         Services.obs.removeObserver(this, "SearchEngines:Get");
         Services.obs.removeObserver(this, "SearchEngines:GetVisible");
         Services.obs.removeObserver(this, "SearchEngines:SetDefault");
    @@ -6712,6 +6714,9 @@ var SearchEngines = {
       observe: function observe(aSubject, aTopic, aData) {
         let engine;
         switch(aTopic) {
    +      case "SearchEngines:Add":
    +        this.displaySearchEnginesList(aData);
    +        break;
           case "SearchEngines:GetVisible":
             Services.search.init(this._handleSearchEnginesGetVisible.bind(this));
             break;
    @@ -6738,6 +6743,50 @@ var SearchEngines = {
         }
       },
     
    +  // Display context menu listing names of the search engines available to be added.
    +  displaySearchEnginesList: function displaySearchEnginesList(aData) {
    +    let data = JSON.parse(aData);
    +    let tab = BrowserApp.getTabForId(data.tabId);
    +
    +    if (!tab)
    +      return;
    +
    +    let browser = tab.browser;
    +    let engines = browser.engines;
    +
    +    let p = new Prompt({
    +      window: browser.contentWindow
    +    }).setSingleChoiceItems(engines.map(function(e) {
    +      return { label: e.title };
    +    })).show((function(data) {
    +      if (data.button == -1)
    +        return;
    +
    +      this.addOpenSearchEngine(engines[data.button]);
    +      engines.splice(data.button, 1);
    +
    +      if (engines.length < 1) {
    +        // Broadcast message that there are no more add-able search engines.
    +        let newEngineMessage = {
    +          type: "Link:OpenSearch",
    +          tabID: tab.id,
    +          visible: false
    +        };
    +
    +        sendMessageToJava(newEngineMessage);
    +      }
    +    }).bind(this));
    +  },
    +
    +  addOpenSearchEngine: function addOpenSearchEngine(engine) {
    +    Services.search.addEngine(engine.url, Ci.nsISearchEngine.DATA_XML, engine.iconURL, false, {
    +      onSuccess: function() {
    +        // Display a toast confirming addition of new search engine.
    +        NativeWindow.toast.show(Strings.browser.formatStringFromName("alertSearchEngineAddedToast", [engine.title], 1), "long");
    +      }
    +    });
    +  },
    +
       addEngine: function addEngine(aElement) {
         let form = aElement.form;
         let charset = aElement.ownerDocument.characterSet;
    diff --git a/mobile/android/locales/en-US/chrome/browser.properties b/mobile/android/locales/en-US/chrome/browser.properties
    index ad8c175a734f..b02a7184f80c 100644
    --- a/mobile/android/locales/en-US/chrome/browser.properties
    +++ b/mobile/android/locales/en-US/chrome/browser.properties
    @@ -22,6 +22,11 @@ alertDownloadsCancel=Cancel
     
     alertFullScreenToast=Press BACK to leave full-screen mode
     
    +# LOCALIZATION NOTE (alertSearchEngineAddedToast)
    +# %S will be replaced by the name of the search engine (exposed by the current page)
    +# that has been added; for example, 'Google'.
    +alertSearchEngineAddedToast='%S' has been added as a search engine
    +
     downloadCancelPromptTitle=Cancel Download
     downloadCancelPromptMessage=Do you want to cancel this download?
     
    
    From c4eedb156df7d7c59743604d76d03c0121f97dfe Mon Sep 17 00:00:00 2001
    From: Chenxia Liu 
    Date: Wed, 6 Nov 2013 15:21:56 -0800
    Subject: [PATCH 34/82] Bug 852608 - Part 3: Add UI for adding a search engine.
     r=lucasr
    
    ---
     mobile/android/base/BrowserApp.java           | 17 ++++++++++++-
     mobile/android/base/BrowserToolbar.java       |  6 ++++-
     mobile/android/base/Tab.java                  | 24 +++++++++++++------
     mobile/android/base/Tabs.java                 |  6 ++++-
     .../base/locales/en-US/android_strings.dtd    |  1 +
     .../resources/menu/titlebar_contextmenu.xml   |  4 ++++
     mobile/android/base/strings.xml.in            |  1 +
     mobile/android/chrome/content/browser.js      | 16 +++++++++++++
     8 files changed, 65 insertions(+), 10 deletions(-)
    
    diff --git a/mobile/android/base/BrowserApp.java b/mobile/android/base/BrowserApp.java
    index 0fcebfe4753d..debe14a22dbe 100644
    --- a/mobile/android/base/BrowserApp.java
    +++ b/mobile/android/base/BrowserApp.java
    @@ -712,7 +712,7 @@ abstract public class BrowserApp extends GeckoApp
     
             if (itemId == R.id.subscribe) {
                 Tab tab = Tabs.getInstance().getSelectedTab();
    -            if (tab != null && tab.getFeedsEnabled()) {
    +            if (tab != null && tab.hasFeeds()) {
                     JSONObject args = new JSONObject();
                     try {
                         args.put("tabId", tab.getId());
    @@ -724,6 +724,21 @@ abstract public class BrowserApp extends GeckoApp
                 return true;
             }
     
    +        if (itemId == R.id.add_search_engine) {
    +            Tab tab = Tabs.getInstance().getSelectedTab();
    +            if (tab != null && tab.hasOpenSearch()) {
    +                JSONObject args = new JSONObject();
    +                try {
    +                    args.put("tabId", tab.getId());
    +                } catch (JSONException e) {
    +                    Log.e(LOGTAG, "error building json arguments");
    +                    return true;
    +                }
    +                GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("SearchEngines:Add", args.toString()));
    +            }
    +            return true;
    +        }
    +
             if (itemId == R.id.copyurl) {
                 Tab tab = Tabs.getInstance().getSelectedTab();
                 if (tab != null) {
    diff --git a/mobile/android/base/BrowserToolbar.java b/mobile/android/base/BrowserToolbar.java
    index 210879b3e2e9..a3a4310cc973 100644
    --- a/mobile/android/base/BrowserToolbar.java
    +++ b/mobile/android/base/BrowserToolbar.java
    @@ -377,15 +377,19 @@ public class BrowserToolbar extends GeckoRelativeLayout
                             menu.findItem(R.id.share).setVisible(false);
                             menu.findItem(R.id.add_to_launcher).setVisible(false);
                         }
    -                    if (!tab.getFeedsEnabled()) {
    +
    +                    if (!tab.hasFeeds()) {
                             menu.findItem(R.id.subscribe).setVisible(false);
                         }
    +
    +                    menu.findItem(R.id.add_search_engine).setVisible(tab.hasOpenSearch());
                     } else {
                         // if there is no tab, remove anything tab dependent
                         menu.findItem(R.id.copyurl).setVisible(false);
                         menu.findItem(R.id.share).setVisible(false);
                         menu.findItem(R.id.add_to_launcher).setVisible(false);
                         menu.findItem(R.id.subscribe).setVisible(false);
    +                    menu.findItem(R.id.add_search_engine).setVisible(false);
                     }
     
                     menu.findItem(R.id.share).setVisible(!GeckoProfile.get(getContext()).inGuestMode());
    diff --git a/mobile/android/base/Tab.java b/mobile/android/base/Tab.java
    index 032f262487f0..4d171e0b647d 100644
    --- a/mobile/android/base/Tab.java
    +++ b/mobile/android/base/Tab.java
    @@ -43,7 +43,8 @@ public class Tab {
         private Bitmap mFavicon;
         private String mFaviconUrl;
         private int mFaviconSize;
    -    private boolean mFeedsEnabled;
    +    private boolean mHasFeeds;
    +    private boolean mHasOpenSearch;
         private JSONObject mIdentityData;
         private boolean mReaderEnabled;
         private BitmapDrawable mThumbnail;
    @@ -98,7 +99,8 @@ public class Tab {
             mFavicon = null;
             mFaviconUrl = null;
             mFaviconSize = 0;
    -        mFeedsEnabled = false;
    +        mHasFeeds = false;
    +        mHasOpenSearch = false;
             mIdentityData = null;
             mReaderEnabled = false;
             mEnteringReaderMode = false;
    @@ -236,8 +238,12 @@ public class Tab {
             return mFaviconUrl;
         }
     
    -    public boolean getFeedsEnabled() {
    -        return mFeedsEnabled;
    +    public boolean hasFeeds() {
    +        return mHasFeeds;
    +    }
    +
    +    public boolean hasOpenSearch() {
    +        return mHasOpenSearch;
         }
     
         public String getSecurityMode() {
    @@ -393,8 +399,12 @@ public class Tab {
             mFaviconSize = 0;
         }
     
    -    public void setFeedsEnabled(boolean feedsEnabled) {
    -        mFeedsEnabled = feedsEnabled;
    +    public void setHasFeeds(boolean hasFeeds) {
    +        mHasFeeds = hasFeeds;
    +    }
    +
    +    public void setHasOpenSearch(boolean hasOpenSearch) {
    +        mHasOpenSearch = hasOpenSearch;
         }
     
         public void updateIdentityData(JSONObject identityData) {
    @@ -622,7 +632,7 @@ public class Tab {
     
             setContentType(message.getString("contentType"));
             clearFavicon();
    -        setFeedsEnabled(false);
    +        setHasFeeds(false);
             updateTitle(null);
             updateIdentityData(null);
             setReaderEnabled(false);
    diff --git a/mobile/android/base/Tabs.java b/mobile/android/base/Tabs.java
    index b183201efa34..3bebcfce71e0 100644
    --- a/mobile/android/base/Tabs.java
    +++ b/mobile/android/base/Tabs.java
    @@ -102,6 +102,7 @@ public class Tabs implements GeckoEventListener {
             registerEventListener("DOMTitleChanged");
             registerEventListener("Link:Favicon");
             registerEventListener("Link:Feed");
    +        registerEventListener("Link:OpenSearch");
             registerEventListener("DesktopMode:Changed");
             registerEventListener("Tab:ViewportMetadata");
         }
    @@ -467,8 +468,11 @@ public class Tabs implements GeckoEventListener {
                     tab.updateFaviconURL(message.getString("href"), message.getInt("size"));
                     notifyListeners(tab, TabEvents.LINK_FAVICON);
                 } else if (event.equals("Link:Feed")) {
    -                tab.setFeedsEnabled(true);
    +                tab.setHasFeeds(true);
                     notifyListeners(tab, TabEvents.LINK_FEED);
    +            } else if (event.equals("Link:OpenSearch")) {
    +                boolean visible = message.getBoolean("visible");
    +                tab.setHasOpenSearch(visible);
                 } else if (event.equals("DesktopMode:Changed")) {
                     tab.setDesktopMode(message.getBoolean("desktopMode"));
                     notifyListeners(tab, TabEvents.DESKTOP_MODE_CHANGE);
    diff --git a/mobile/android/base/locales/en-US/android_strings.dtd b/mobile/android/base/locales/en-US/android_strings.dtd
    index e2bd1ce42a45..72e1ae1ae5b6 100644
    --- a/mobile/android/base/locales/en-US/android_strings.dtd
    +++ b/mobile/android/base/locales/en-US/android_strings.dtd
    @@ -228,6 +228,7 @@ size. -->
     
     
     
    +
     
     
     
    diff --git a/mobile/android/base/resources/menu/titlebar_contextmenu.xml b/mobile/android/base/resources/menu/titlebar_contextmenu.xml
    index 6daae1d6c028..45bcf61971c3 100644
    --- a/mobile/android/base/resources/menu/titlebar_contextmenu.xml
    +++ b/mobile/android/base/resources/menu/titlebar_contextmenu.xml
    @@ -17,6 +17,10 @@
         
     
    +    
    +
         
     
    diff --git a/mobile/android/base/strings.xml.in b/mobile/android/base/strings.xml.in
    index dee5d71c3fa7..a6b1d067be26 100644
    --- a/mobile/android/base/strings.xml.in
    +++ b/mobile/android/base/strings.xml.in
    @@ -228,6 +228,7 @@
       &contextmenu_top_sites_edit;
       &contextmenu_top_sites_pin;
       &contextmenu_top_sites_unpin;
    +  &contextmenu_add_search_engine;
     
       &pref_titlebar_mode;
       &pref_titlebar_mode_title;
    diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js
    index 65a7de299740..3a0b82e2b873 100644
    --- a/mobile/android/chrome/content/browser.js
    +++ b/mobile/android/chrome/content/browser.js
    @@ -3702,6 +3702,22 @@ Tab.prototype = {
             return;
           }
     
    +      // Clear page-specific opensearch engines and feeds for a new request.
    +      if (aStateFlags & Ci.nsIWebProgressListener.STATE_START && aRequest && aWebProgress.isTopLevel) {
    +          this.browser.engines = null;
    +
    +          // Send message to clear search engine option in context menu.
    +          let newEngineMessage = {
    +            type: "Link:OpenSearch",
    +            tabID: this.id,
    +            visible: false
    +          };
    +
    +          sendMessageToJava(newEngineMessage);
    +
    +          this.browser.feeds = null;
    +      }
    +
           // Check to see if we restoring the content from a previous presentation (session)
           // since there should be no real network activity
           let restoring = aStateFlags & Ci.nsIWebProgressListener.STATE_RESTORING;
    
    From ce03d3ad64bcebfcc9b866b1ad590e59625a6de3 Mon Sep 17 00:00:00 2001
    From: Mark Hammond 
    Date: Thu, 7 Nov 2013 10:43:59 +1100
    Subject: [PATCH 35/82] Bug 935379 - RemoteWebProgress should handle
     missing/failing progress listener methods.  r=felipe
    
    ---
     toolkit/modules/RemoteWebProgress.jsm | 28 +++++++++++++++------------
     1 file changed, 16 insertions(+), 12 deletions(-)
    
    diff --git a/toolkit/modules/RemoteWebProgress.jsm b/toolkit/modules/RemoteWebProgress.jsm
    index 324583d58c6d..367604b8e6e7 100644
    --- a/toolkit/modules/RemoteWebProgress.jsm
    +++ b/toolkit/modules/RemoteWebProgress.jsm
    @@ -109,6 +109,18 @@ RemoteWebProgressManager.prototype = {
         return [deserialized, aState];
       },
     
    +  _callProgressListeners: function(methodName, ...args) {
    +    for (let p of this._progressListeners) {
    +      if (p[methodName]) {
    +        try {
    +          p[methodName].apply(p, args);
    +        } catch (ex) {
    +          Cu.reportError("RemoteWebProgress failed to call " + methodName + ": " + ex + "\n");
    +        }
    +      }
    +    }
    +  },
    +
       receiveMessage: function (aMessage) {
         let json = aMessage.json;
         let objects = aMessage.objects;
    @@ -133,9 +145,7 @@ RemoteWebProgressManager.prototype = {
     
         switch (aMessage.name) {
         case "Content:StateChange":
    -      for (let p of this._progressListeners) {
    -        p.onStateChange(webProgress, request, json.stateFlags, json.status);
    -      }
    +      this._callProgressListeners("onStateChange", webProgress, request, json.stateFlags, json.status);
           break;
     
         case "Content:LocationChange":
    @@ -150,9 +160,7 @@ RemoteWebProgressManager.prototype = {
             this._browser._imageDocument = null;
           }
     
    -      for (let p of this._progressListeners) {
    -        p.onLocationChange(webProgress, request, location);
    -      }
    +      this._callProgressListeners("onLocationChange", webProgress, request, location);
           break;
     
         case "Content:SecurityChange":
    @@ -166,15 +174,11 @@ RemoteWebProgressManager.prototype = {
             this._browser._securityUI._update(status, state);
           }
     
    -      for (let p of this._progressListeners) {
    -        p.onSecurityChange(webProgress, request, state);
    -      }
    +      this._callProgressListeners("onSecurityChange", webProgress, request, state);
           break;
     
         case "Content:StatusChange":
    -      for (let p of this._progressListeners) {
    -        p.onStatusChange(webProgress, request, json.status, json.message);
    -      }
    +      this._callProgressListeners("onStatusChange", webProgress, request, json.status, json.message);
           break;
         }
       }
    
    From 6a0deca9e6326cc088b0ced02e81301fb98b4d11 Mon Sep 17 00:00:00 2001
    From: Jared Wein 
    Date: Mon, 28 Oct 2013 13:27:53 -0400
    Subject: [PATCH 36/82] Bug 704326 - Standalone audio files should have
     different style so they don't look awkward. r=smaug,dolske
    
    ---
     dom/webidl/Document.webidl                |  2 +-
     toolkit/content/widgets/videocontrols.xml | 37 +++++++++++++++++------
     2 files changed, 29 insertions(+), 10 deletions(-)
    
    diff --git a/dom/webidl/Document.webidl b/dom/webidl/Document.webidl
    index 1520239d0e33..18ef74c70c4a 100644
    --- a/dom/webidl/Document.webidl
    +++ b/dom/webidl/Document.webidl
    @@ -151,7 +151,7 @@ partial interface Document {
        * True if this document is synthetic : stand alone image, video, audio file,
        * etc.
        */
    -  [ChromeOnly] readonly attribute boolean mozSyntheticDocument;
    +  [Func="IsChromeOrXBL"] readonly attribute boolean mozSyntheticDocument;
       /**
        * Returns the script element whose script is currently being processed.
        *
    diff --git a/toolkit/content/widgets/videocontrols.xml b/toolkit/content/widgets/videocontrols.xml
    index 9b2b811e9fe4..27f6be83d793 100644
    --- a/toolkit/content/widgets/videocontrols.xml
    +++ b/toolkit/content/widgets/videocontrols.xml
    @@ -338,7 +338,15 @@
                     firstFrameShown : false,
                     timeUpdateCount : 0,
                     maxCurrentTimeSeen : 0,
    -                isAudioOnly : false,
    +                _isAudioOnly : false,
    +                get isAudioOnly() { return this._isAudioOnly; },
    +                set isAudioOnly(val) {
    +                    this._isAudioOnly = val;
    +                    if (!this.isTopLevelSyntheticDocument)
    +                        return;
    +                    this.video.style.height = this._controlBarHeight + "px";
    +                    this.video.style.width = "66%";
    +                },
                     suppressError : false,
     
                     setupStatusFader : function(immediate) {
    @@ -842,7 +850,10 @@
                     },
     
                     onVolumeMouseInOut : function (event) {
    -                    if (this.isVideoWithoutAudioTrack()) {
    +                    let doc = this.video.ownerDocument;
    +                    let win = doc.defaultView;
    +                    if (this.isVideoWithoutAudioTrack() ||
    +                        (this.isAudioOnly && this.isTopLevelSyntheticDocument)) {
                             return;
                         }
                         // Ignore events caused by transitions between mute button and volumeStack,
    @@ -1335,6 +1346,12 @@
                             dump("videoctl: " + msg + "\n");
                     },
     
    +                get isTopLevelSyntheticDocument() {
    +                  let doc = this.video.ownerDocument;
    +                  let win = doc.defaultView;
    +                  return doc.mozSyntheticDocument && win === win.top;
    +                },
    +
                     _playButtonWidth : 0,
                     _durationLabelWidth : 0,
                     _muteButtonWidth : 0,
    @@ -1343,15 +1360,11 @@
                     _overlayPlayButtonHeight : 64,
                     _overlayPlayButtonWidth : 64,
                     adjustControlSize : function adjustControlSize() {
    -                    if (this.isAudioOnly)
    +                    let doc = this.video.ownerDocument;
    +                    let isAudioOnly = this.isAudioOnly;
    +                    if (isAudioOnly && !this.isTopLevelSyntheticDocument)
                             return;
     
    -                    let videoHeight = this.video.clientHeight;
    -                    let videoWidth = this.video.clientWidth;
    -
    -                    if (this._overlayPlayButtonHeight > videoHeight || this._overlayPlayButtonWidth > videoWidth)
    -                        this.clickToPlay.hidden = true;
    -
                         // The scrubber has |flex=1|, therefore |minScrubberWidth|
                         // was generated by empirical testing.
                         let minScrubberWidth = 25;
    @@ -1363,6 +1376,12 @@
                         let minHeightForControlBar = this._controlBarHeight;
                         let minWidthOnlyPlayPause = this._playButtonWidth + this._muteButtonWidth;
     
    +                    let videoHeight = isAudioOnly ? minHeightForControlBar : this.video.clientHeight;
    +                    let videoWidth = isAudioOnly ? minWidthAllControls : this.video.clientWidth;
    +
    +                    if (this._overlayPlayButtonHeight > videoHeight || this._overlayPlayButtonWidth > videoWidth)
    +                        this.clickToPlay.hidden = true;
    +
                         let size = "normal";
                         if (videoHeight < minHeightForControlBar)
                             size = "hidden";
    
    From 608efc5a34d64cba788513c24f2bd3c621fee6bb Mon Sep 17 00:00:00 2001
    From: Rodrigo Silveira 
    Date: Sun, 22 Sep 2013 20:01:01 -0700
    Subject: [PATCH 37/82] Bug 900137 - add support for multple icon sizes to the
     search service r=yoric sr=gavin
    
    ---
     .../base/public/nsIBrowserSearchService.idl   |  21 ++-
     toolkit/components/search/nsSearchService.js  | 136 +++++++++++++++---
     2 files changed, 136 insertions(+), 21 deletions(-)
    
    diff --git a/netwerk/base/public/nsIBrowserSearchService.idl b/netwerk/base/public/nsIBrowserSearchService.idl
    index c15e1298bfd3..b9aa8abea94c 100644
    --- a/netwerk/base/public/nsIBrowserSearchService.idl
    +++ b/netwerk/base/public/nsIBrowserSearchService.idl
    @@ -22,7 +22,7 @@ interface nsISearchSubmission : nsISupports
       readonly attribute nsIURI uri;
     };
     
    -[scriptable, uuid(ccf6aa20-10a9-4a0c-a81d-31b10ea846de)]
    +[scriptable, uuid(7914c4b8-f05b-40c9-a982-38a058cd1769)]
     interface nsISearchEngine : nsISupports
     {
       /**
    @@ -83,6 +83,25 @@ interface nsISearchEngine : nsISupports
        */
       boolean supportsResponseType(in AString responseType);
     
    +  /**
    +   * Returns a string with the URL to an engine's icon matching both width and
    +   * height. Returns null if icon with specified dimensions is not found.
    +   *
    +   * @param width
    +   *        Width of the requested icon.
    +   * @param height
    +   *        Height of the requested icon.
    +   */
    +  AString getIconURLBySize(in long width, in long height);
    +
    +  /**
    +   * Gets an array of all available icons. Each entry is an object with
    +   * width, height and url properties. width and height are numeric and
    +   * represent the icon's dimensions. url is a string with the URL for
    +   * the icon.
    +   */
    +  jsval getIcons();
    +
       /**
        * Supported search engine types.
        */
    diff --git a/toolkit/components/search/nsSearchService.js b/toolkit/components/search/nsSearchService.js
    index f24c7822bbc6..397aa0850dbb 100644
    --- a/toolkit/components/search/nsSearchService.js
    +++ b/toolkit/components/search/nsSearchService.js
    @@ -1556,7 +1556,45 @@ Engine.prototype = {
       },
     
       /**
    -   * Sets the .iconURI property of the engine.
    +   * Creates a key by serializing an object that contains the icon's width
    +   * and height.
    +   *
    +   * @param aWidth
    +   *        Width of the icon.
    +   * @param aHeight
    +   *        Height of the icon.
    +   * @returns key string
    +   */
    +  _getIconKey: function SRCH_ENG_getIconKey(aWidth, aHeight) {
    +    let keyObj = {
    +     width: aWidth,
    +     height: aHeight
    +    };
    +
    +    return JSON.stringify(keyObj);
    +  },
    +
    +  /**
    +   * Add an icon to the icon map used by getIconURIBySize() and getIcons().
    +   *
    +   * @param aWidth
    +   *        Width of the icon.
    +   * @param aHeight
    +   *        Height of the icon.
    +   * @param aURISpec
    +   *        String with the icon's URI.
    +   */
    +  _addIconToMap: function SRCH_ENG_addIconToMap(aWidth, aHeight, aURISpec) {
    +    // Use an object instead of a Map() because it needs to be serializable.
    +    this._iconMapObj = this._iconMapObj || {};
    +    let key = this._getIconKey(aWidth, aHeight);
    +    this._iconMapObj[key] = aURISpec;
    +  },
    +
    +  /**
    +   * Sets the .iconURI property of the engine. If both aWidth and aHeight are
    +   * provided an entry will be added to _iconMapObj that will enable accessing
    +   * icon's data through getIcons() and getIconURIBySize() APIs.
        *
        *  @param aIconURL
        *         A URI string pointing to the engine's icon. Must have a http[s],
    @@ -1566,13 +1604,12 @@ Engine.prototype = {
        *  @param aIsPreferred
        *         Whether or not this icon is to be preferred. Preferred icons can
        *         override non-preferred icons.
    +   *  @param aWidth (optional)
    +   *         Width of the icon.
    +   *  @param aHeight (optional)
    +   *         Height of the icon.
        */
    -  _setIcon: function SRCH_ENG_setIcon(aIconURL, aIsPreferred) {
    -    // If we already have a preferred icon, and this isn't a preferred icon,
    -    // just ignore it.
    -    if (this._hasPreferredIcon && !aIsPreferred)
    -      return;
    -
    +  _setIcon: function SRCH_ENG_setIcon(aIconURL, aIsPreferred, aWidth, aHeight) {
         var uri = makeURI(aIconURL);
     
         // Ignore bad URIs
    @@ -1584,9 +1621,15 @@ Engine.prototype = {
         // Only accept remote icons from http[s] or ftp
         switch (uri.scheme) {
           case "data":
    -        this._iconURI = uri;
    -        notifyAction(this, SEARCH_ENGINE_CHANGED);
    -        this._hasPreferredIcon = aIsPreferred;
    +        if (!this._hasPreferredIcon || aIsPreferred) {
    +          this._iconURI = uri;
    +          notifyAction(this, SEARCH_ENGINE_CHANGED);
    +          this._hasPreferredIcon = aIsPreferred;
    +        }
    +
    +        if (aWidth && aHeight) {
    +          this._addIconToMap(aWidth, aHeight, aIconURL)
    +        }
             break;
           case "http":
           case "https":
    @@ -1610,7 +1653,12 @@ Engine.prototype = {
                 }
     
                 var str = btoa(String.fromCharCode.apply(null, aByteArray));
    -            aEngine._iconURI = makeURI(ICON_DATAURL_PREFIX + str);
    +            let dataURL = ICON_DATAURL_PREFIX + str;
    +            aEngine._iconURI = makeURI(dataURL);
    +
    +            if (aWidth && aHeight) {
    +              aEngine._addIconToMap(aWidth, aHeight, dataURL)
    +            }
     
                 // The engine might not have a file yet, if it's being downloaded,
                 // because the request for the engine file itself (_onLoad) may not
    @@ -1804,14 +1852,17 @@ Engine.prototype = {
        */
       _parseImage: function SRCH_ENG_parseImage(aElement) {
         LOG("_parseImage: Image textContent: \"" + limitURILength(aElement.textContent) + "\"");
    -    if (aElement.getAttribute("width")  == "16" &&
    -        aElement.getAttribute("height") == "16") {
    -      this._setIcon(aElement.textContent, true);
    -    }
    -    else {
    -      LOG("OpenSearch image must have explicit width=16 height=16: " +
    -          aElement.textContent);
    +
    +    let width = parseInt(aElement.getAttribute("width"), 10);
    +    let height = parseInt(aElement.getAttribute("height"), 10);
    +    let isPrefered = width == 16 && height == 16;
    +
    +    if (isNaN(width) || isNaN(height) || width <= 0 || height <=0) {
    +      LOG("OpenSearch image element must have positive width and height.");
    +      return;
         }
    +
    +    this._setIcon(aElement.textContent, isPrefered, width, height);
       },
     
       _parseAsMozSearch: function SRCH_ENG_parseAsMoz() {
    @@ -2209,6 +2260,7 @@ Engine.prototype = {
         else
           this._readOnly = false;
         this._iconURI = makeURI(aJson._iconURL);
    +    this._iconMapObj = aJson._iconMapObj;
         for (let i = 0; i < aJson._urls.length; ++i) {
           let url = aJson._urls[i];
           let engineURL = new EngineURL(url.type || URLTYPE_SEARCH_HTML,
    @@ -2233,7 +2285,8 @@ Engine.prototype = {
           description: this.description,
           __searchForm: this.__searchForm,
           _iconURL: this._iconURL,
    -      _urls: [url._serializeToJSON() for each(url in this._urls)] 
    +      _iconMapObj: this._iconMapObj,
    +      _urls: [url._serializeToJSON() for each(url in this._urls)]
         };
     
         if (this._file instanceof Ci.nsILocalFile)
    @@ -2679,8 +2732,51 @@ Engine.prototype = {
     
       get wrappedJSObject() {
         return this;
    -  }
    +  },
     
    +  /**
    +   * Returns a string with the URL to an engine's icon matching both width and
    +   * height. Returns null if icon with specified dimensions is not found.
    +   *
    +   * @param width
    +   *        Width of the requested icon.
    +   * @param height
    +   *        Height of the requested icon.
    +   */
    +  getIconURLBySize: function SRCH_ENG_getIconURLBySize(aWidth, aHeight) {
    +    if (!this._iconMapObj)
    +      return null;
    +
    +    let key = this._getIconKey(aWidth, aHeight);
    +    if (key in this._iconMapObj) {
    +      return this._iconMapObj[key];
    +    }
    +    return null;
    +  },
    +
    +  /**
    +   * Gets an array of all available icons. Each entry is an object with
    +   * width, height and url properties. width and height are numeric and
    +   * represent the icon's dimensions. url is a string with the URL for
    +   * the icon.
    +   */
    +  getIcons: function SRCH_ENG_getIcons() {
    +    let result = [];
    +
    +    if (!this._iconMapObj)
    +      return result;
    +
    +    for (let key of Object.keys(this._iconMapObj)) {
    +      let iconSize = JSON.parse(key);
    +      result.push({
    +        width: iconSize.width,
    +        height: iconSize.height,
    +        url: this._iconMapObj[key]
    +      });
    +    }
    +
    +    return result;
    +  }
     };
     
     // nsISearchSubmission
    
    From 3dcd9930d3f762c9c4b1b15edd8236620f8644c4 Mon Sep 17 00:00:00 2001
    From: Andrew McCreight 
    Date: Wed, 25 Sep 2013 13:41:25 -0700
    Subject: [PATCH 38/82] Bug 909490, part 2 - Add callback for zone destruction.
     r=billm
    
    ---
     js/src/jsapi.cpp      | 6 ++++++
     js/src/jsapi.h        | 6 ++++++
     js/src/jsgc.cpp       | 3 +++
     js/src/vm/Runtime.cpp | 1 +
     js/src/vm/Runtime.h   | 3 +++
     5 files changed, 19 insertions(+)
    
    diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
    index 8bdb70b681e2..4182e89d3279 100644
    --- a/js/src/jsapi.cpp
    +++ b/js/src/jsapi.cpp
    @@ -908,6 +908,12 @@ JS_SetDestroyCompartmentCallback(JSRuntime *rt, JSDestroyCompartmentCallback cal
         rt->destroyCompartmentCallback = callback;
     }
     
    +JS_PUBLIC_API(void)
    +JS_SetDestroyZoneCallback(JSRuntime *rt, JSZoneCallback callback)
    +{
    +    rt->destroyZoneCallback = callback;
    +}
    +
     JS_PUBLIC_API(void)
     JS_SetCompartmentNameCallback(JSRuntime *rt, JSCompartmentNameCallback callback)
     {
    diff --git a/js/src/jsapi.h b/js/src/jsapi.h
    index 552d5c5c534a..303bde968351 100644
    --- a/js/src/jsapi.h
    +++ b/js/src/jsapi.h
    @@ -841,6 +841,9 @@ typedef JSObject *
     typedef void
     (* JSDestroyCompartmentCallback)(JSFreeOp *fop, JSCompartment *compartment);
     
    +typedef void
    +(* JSZoneCallback)(JS::Zone *zone);
    +
     typedef void
     (* JSCompartmentNameCallback)(JSRuntime *rt, JSCompartment *compartment,
                                   char *buf, size_t bufsize);
    @@ -1623,6 +1626,9 @@ JS_GetImplementationVersion(void);
     extern JS_PUBLIC_API(void)
     JS_SetDestroyCompartmentCallback(JSRuntime *rt, JSDestroyCompartmentCallback callback);
     
    +extern JS_PUBLIC_API(void)
    +JS_SetDestroyZoneCallback(JSRuntime *rt, JSZoneCallback callback);
    +
     extern JS_PUBLIC_API(void)
     JS_SetCompartmentNameCallback(JSRuntime *rt, JSCompartmentNameCallback callback);
     
    diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp
    index 463b3588df9c..b2dfe59898d0 100644
    --- a/js/src/jsgc.cpp
    +++ b/js/src/jsgc.cpp
    @@ -2614,6 +2614,7 @@ static void
     SweepZones(FreeOp *fop, bool lastGC)
     {
         JSRuntime *rt = fop->runtime();
    +    JSZoneCallback callback = rt->destroyZoneCallback;
     
         /* Skip the atomsCompartment zone. */
         Zone **read = rt->zones.begin() + 1;
    @@ -2628,6 +2629,8 @@ SweepZones(FreeOp *fop, bool lastGC)
             if (!zone->hold && zone->wasGCStarted()) {
                 if (zone->allocator.arenas.arenaListsAreEmpty() || lastGC) {
                     zone->allocator.arenas.checkEmptyFreeLists();
    +                if (callback)
    +                    callback(zone);
                     SweepCompartments(fop, zone, false, lastGC);
                     JS_ASSERT(zone->compartments.empty());
                     fop->delete_(zone);
    diff --git a/js/src/vm/Runtime.cpp b/js/src/vm/Runtime.cpp
    index 3f9a5fc22242..6fff96feba78 100644
    --- a/js/src/vm/Runtime.cpp
    +++ b/js/src/vm/Runtime.cpp
    @@ -146,6 +146,7 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
         nativeStackBase(0),
         cxCallback(nullptr),
         destroyCompartmentCallback(nullptr),
    +    destroyZoneCallback(nullptr),
         compartmentNameCallback(nullptr),
         activityCallback(nullptr),
         activityCallbackArg(nullptr),
    diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h
    index 92810edfbaf3..9541aa345dde 100644
    --- a/js/src/vm/Runtime.h
    +++ b/js/src/vm/Runtime.h
    @@ -950,6 +950,9 @@ struct JSRuntime : public JS::shadow::Runtime,
         /* Compartment destroy callback. */
         JSDestroyCompartmentCallback destroyCompartmentCallback;
     
    +    /* Zone destroy callback. */
    +    JSZoneCallback destroyZoneCallback;
    +
         /* Call this to get the name of a compartment. */
         JSCompartmentNameCallback compartmentNameCallback;
     
    
    From e36d22d3964848e7819a0cbf5b07d47c99f3aecc Mon Sep 17 00:00:00 2001
    From: Andrew McCreight 
    Date: Wed, 25 Sep 2013 13:41:25 -0700
    Subject: [PATCH 39/82] Bug 909490, part 3 - Add callback for zone sweeping.
     r=jonco
    
    ---
     js/src/jsapi.cpp      | 6 ++++++
     js/src/jsapi.h        | 3 +++
     js/src/jsgc.cpp       | 3 +++
     js/src/vm/Runtime.cpp | 1 +
     js/src/vm/Runtime.h   | 3 +++
     5 files changed, 16 insertions(+)
    
    diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
    index 4182e89d3279..f0800eda9e31 100644
    --- a/js/src/jsapi.cpp
    +++ b/js/src/jsapi.cpp
    @@ -914,6 +914,12 @@ JS_SetDestroyZoneCallback(JSRuntime *rt, JSZoneCallback callback)
         rt->destroyZoneCallback = callback;
     }
     
    +JS_PUBLIC_API(void)
    +JS_SetSweepZoneCallback(JSRuntime *rt, JSZoneCallback callback)
    +{
    +    rt->sweepZoneCallback = callback;
    +}
    +
     JS_PUBLIC_API(void)
     JS_SetCompartmentNameCallback(JSRuntime *rt, JSCompartmentNameCallback callback)
     {
    diff --git a/js/src/jsapi.h b/js/src/jsapi.h
    index 303bde968351..b7fd10b44c08 100644
    --- a/js/src/jsapi.h
    +++ b/js/src/jsapi.h
    @@ -1629,6 +1629,9 @@ JS_SetDestroyCompartmentCallback(JSRuntime *rt, JSDestroyCompartmentCallback cal
     extern JS_PUBLIC_API(void)
     JS_SetDestroyZoneCallback(JSRuntime *rt, JSZoneCallback callback);
     
    +extern JS_PUBLIC_API(void)
    +JS_SetSweepZoneCallback(JSRuntime *rt, JSZoneCallback callback);
    +
     extern JS_PUBLIC_API(void)
     JS_SetCompartmentNameCallback(JSRuntime *rt, JSCompartmentNameCallback callback);
     
    diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp
    index b2dfe59898d0..ab4f63861089 100644
    --- a/js/src/jsgc.cpp
    +++ b/js/src/jsgc.cpp
    @@ -3717,6 +3717,9 @@ BeginSweepingZoneGroup(JSRuntime *rt)
     
             if (rt->isAtomsZone(zone))
                 sweepingAtoms = true;
    +
    +        if (rt->sweepZoneCallback)
    +            rt->sweepZoneCallback(zone);
         }
     
         ValidateIncrementalMarking(rt);
    diff --git a/js/src/vm/Runtime.cpp b/js/src/vm/Runtime.cpp
    index 6fff96feba78..1985db85d18a 100644
    --- a/js/src/vm/Runtime.cpp
    +++ b/js/src/vm/Runtime.cpp
    @@ -147,6 +147,7 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
         cxCallback(nullptr),
         destroyCompartmentCallback(nullptr),
         destroyZoneCallback(nullptr),
    +    sweepZoneCallback(nullptr),
         compartmentNameCallback(nullptr),
         activityCallback(nullptr),
         activityCallbackArg(nullptr),
    diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h
    index 9541aa345dde..a144c8af0e34 100644
    --- a/js/src/vm/Runtime.h
    +++ b/js/src/vm/Runtime.h
    @@ -953,6 +953,9 @@ struct JSRuntime : public JS::shadow::Runtime,
         /* Zone destroy callback. */
         JSZoneCallback destroyZoneCallback;
     
    +    /* Zone sweep callback. */
    +    JSZoneCallback sweepZoneCallback;
    +
         /* Call this to get the name of a compartment. */
         JSCompartmentNameCallback compartmentNameCallback;
     
    
    From 5f3b6da48192769c55c9c9e3e24ab690bbaa2171 Mon Sep 17 00:00:00 2001
    From: Andrew McCreight 
    Date: Mon, 4 Nov 2013 15:01:38 -0800
    Subject: [PATCH 40/82] Bug 905382, part 1 - Implement a read barrier for GC
     things. r=jonco
    
    ---
     js/public/GCAPI.h | 25 +++++++++++++++++++++++++
     1 file changed, 25 insertions(+)
    
    diff --git a/js/public/GCAPI.h b/js/public/GCAPI.h
    index a156ea1d4d16..7c3e9b32de52 100644
    --- a/js/public/GCAPI.h
    +++ b/js/public/GCAPI.h
    @@ -311,6 +311,31 @@ ExposeObjectToActiveJS(JSObject *obj)
         ExposeGCThingToActiveJS(obj, JSTRACE_OBJECT);
     }
     
    +/*
    + * If a GC is currently marking, mark the object black.
    + */
    +static JS_ALWAYS_INLINE void
    +MarkGCThingAsLive(JSRuntime *rt_, void *thing, JSGCTraceKind kind)
    +{
    +    shadow::Runtime *rt = shadow::Runtime::asShadowRuntime(rt_);
    +#ifdef JSGC_GENERATIONAL
    +    /*
    +     * Any object in the nursery will not be freed during any GC running at that time.
    +     */
    +    if (js::gc::IsInsideNursery(rt, thing))
    +        return;
    +#endif
    +    if (IsIncrementalBarrierNeededOnGCThing(rt, thing, kind))
    +        IncrementalReferenceBarrier(thing, kind);
    +}
    +
    +static JS_ALWAYS_INLINE void
    +MarkStringAsLive(Zone *zone, JSString *string)
    +{
    +    JSRuntime *rt = JS::shadow::Zone::asShadowZone(zone)->runtimeFromMainThread();
    +    MarkGCThingAsLive(rt, string, JSTRACE_STRING);
    +}
    +
     } /* namespace JS */
     
     #endif /* js_GCAPI_h */
    
    From 952d88056963f92a90b2d89bccbafd6398cba591 Mon Sep 17 00:00:00 2001
    From: Andrew McCreight 
    Date: Thu, 26 Sep 2013 16:18:27 -0700
    Subject: [PATCH 41/82] Bug 905382, part 2 - Implement per-zone string
     conversion cache. r=bz
    
    ---
     js/xpconnect/src/XPCJSRuntime.cpp      |  2 --
     js/xpconnect/src/XPCString.cpp         | 29 +++++++++++++---------
     js/xpconnect/src/xpcpublic.h           | 34 +++++++++++++++++++-------
     xpcom/base/CycleCollectedJSRuntime.cpp |  2 ++
     4 files changed, 44 insertions(+), 23 deletions(-)
    
    diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp
    index acb6f2976100..84384dbec723 100644
    --- a/js/xpconnect/src/XPCJSRuntime.cpp
    +++ b/js/xpconnect/src/XPCJSRuntime.cpp
    @@ -741,8 +741,6 @@ XPCJSRuntime::FinalizeCallback(JSFreeOp *fop, JSFinalizeStatus status, bool isCo
                 // Find dying scopes.
                 XPCWrappedNativeScope::StartFinalizationPhaseOfGC(fop, self);
     
    -            XPCStringConvert::ClearCache();
    -
                 self->mDoingFinalization = true;
                 break;
             }
    diff --git a/js/xpconnect/src/XPCString.cpp b/js/xpconnect/src/XPCString.cpp
    index 9c9f50b13142..2e21f7aadeaa 100644
    --- a/js/xpconnect/src/XPCString.cpp
    +++ b/js/xpconnect/src/XPCString.cpp
    @@ -24,24 +24,29 @@
     #include "jsapi.h"
     #include "xpcpublic.h"
     
    -// One-slot cache, because it turns out it's common for web pages to
    -// get the same string a few times in a row.  We get about a 40% cache
    -// hit rate on this cache last it was measured.  We'd get about 70%
    -// hit rate with a hashtable with removal on finalization, but that
    -// would take a lot more machinery.
    -nsStringBuffer* XPCStringConvert::sCachedBuffer = nullptr;
    -JSString* XPCStringConvert::sCachedString = nullptr;
     
    -// Called from GC finalize callback to make sure we don't hand out a pointer to
    -// a JSString that's about to be finalized by incremental sweeping.
     // static
     void
    -XPCStringConvert::ClearCache()
    +XPCStringConvert::FreeZoneCache(JS::Zone *zone)
     {
    -    sCachedBuffer = nullptr;
    -    sCachedString = nullptr;
    +    // Put the zone user data into an AutoPtr (which will do the cleanup for us),
    +    // and null out the user data (which may already be null).
    +    nsAutoPtr cache(static_cast(JS_GetZoneUserData(zone)));
    +    JS_SetZoneUserData(zone, nullptr);
     }
     
    +// static
    +void
    +XPCStringConvert::ClearZoneCache(JS::Zone *zone)
    +{
    +    ZoneStringCache *cache = static_cast(JS_GetZoneUserData(zone));
    +    if (cache) {
    +        cache->mBuffer = nullptr;
    +        cache->mString = nullptr;
    +    }
    +}
    +
    +// static
     void
     XPCStringConvert::FinalizeDOMString(const JSStringFinalizer *fin, jschar *chars)
     {
    diff --git a/js/xpconnect/src/xpcpublic.h b/js/xpconnect/src/xpcpublic.h
    index 995ac4c43cdf..8f0fcefaea84 100644
    --- a/js/xpconnect/src/xpcpublic.h
    +++ b/js/xpconnect/src/xpcpublic.h
    @@ -149,6 +149,17 @@ xpc_ActivateDebugMode();
     // readable string conversions, static methods and members only
     class XPCStringConvert
     {
    +    // One-slot cache, because it turns out it's common for web pages to
    +    // get the same string a few times in a row.  We get about a 40% cache
    +    // hit rate on this cache last it was measured.  We'd get about 70%
    +    // hit rate with a hashtable with removal on finalization, but that
    +    // would take a lot more machinery.
    +    struct ZoneStringCache
    +    {
    +        nsStringBuffer* mBuffer;
    +        JSString* mString;
    +    };
    +
     public:
     
         // If the string shares the readable's buffer, that buffer will
    @@ -162,10 +173,12 @@ public:
         StringBufferToJSVal(JSContext* cx, nsStringBuffer* buf, uint32_t length,
                             JS::MutableHandleValue rval, bool* sharedBuffer)
         {
    -        if (buf == sCachedBuffer &&
    -            JS::GetGCThingZone(sCachedString) == js::GetContextZone(cx))
    -        {
    -            rval.set(JS::StringValue(sCachedString));
    +        JS::Zone *zone = js::GetContextZone(cx);
    +        ZoneStringCache *cache = static_cast(JS_GetZoneUserData(zone));
    +        if (cache && buf == cache->mBuffer) {
    +            MOZ_ASSERT(JS::GetGCThingZone(cache->mString) == zone);
    +            JS::MarkStringAsLive(zone, cache->mString);
    +            rval.setString(cache->mString);
                 *sharedBuffer = false;
                 return true;
             }
    @@ -177,17 +190,20 @@ public:
                 return false;
             }
             rval.setString(str);
    -        sCachedString = str;
    -        sCachedBuffer = buf;
    +        if (!cache) {
    +            cache = new ZoneStringCache();
    +            JS_SetZoneUserData(zone, cache);
    +        }
    +        cache->mBuffer = buf;
    +        cache->mString = str;
             *sharedBuffer = true;
             return true;
         }
     
    -    static void ClearCache();
    +    static void FreeZoneCache(JS::Zone *zone);
    +    static void ClearZoneCache(JS::Zone *zone);
     
     private:
    -    static nsStringBuffer* sCachedBuffer;
    -    static JSString* sCachedString;
         static const JSStringFinalizer sDOMStringFinalizer;
     
         static void FinalizeDOMString(const JSStringFinalizer *fin, jschar *chars);
    diff --git a/xpcom/base/CycleCollectedJSRuntime.cpp b/xpcom/base/CycleCollectedJSRuntime.cpp
    index f5563c5d1b56..1956832e0245 100644
    --- a/xpcom/base/CycleCollectedJSRuntime.cpp
    +++ b/xpcom/base/CycleCollectedJSRuntime.cpp
    @@ -452,6 +452,8 @@ CycleCollectedJSRuntime::CycleCollectedJSRuntime(uint32_t aMaxbytes,
       JS_SetGrayGCRootsTracer(mJSRuntime, TraceGrayJS, this);
       JS_SetGCCallback(mJSRuntime, GCCallback, this);
       JS_SetContextCallback(mJSRuntime, ContextCallback, this);
    +  JS_SetDestroyZoneCallback(mJSRuntime, XPCStringConvert::FreeZoneCache);
    +  JS_SetSweepZoneCallback(mJSRuntime, XPCStringConvert::ClearZoneCache);
     
       nsCycleCollector_registerJSRuntime(this);
     }
    
    From 85942e591bfa0d48edd1caf5f3a3f5190652370c Mon Sep 17 00:00:00 2001
    From: Rodrigo Silveira 
    Date: Wed, 2 Oct 2013 17:08:34 -0700
    Subject: [PATCH 42/82] Bug 900137 - xpcshell tests r=yoric
    
    ---
     .../tests/xpcshell/data/engineImages.xml      | 22 ++++++
     .../tests/xpcshell/test_multipleIcons.js      | 78 +++++++++++++++++++
     .../search/tests/xpcshell/xpcshell.ini        |  2 +
     3 files changed, 102 insertions(+)
     create mode 100644 toolkit/components/search/tests/xpcshell/data/engineImages.xml
     create mode 100644 toolkit/components/search/tests/xpcshell/test_multipleIcons.js
    
    diff --git a/toolkit/components/search/tests/xpcshell/data/engineImages.xml b/toolkit/components/search/tests/xpcshell/data/engineImages.xml
    new file mode 100644
    index 000000000000..65b550b31b11
    --- /dev/null
    +++ b/toolkit/components/search/tests/xpcshell/data/engineImages.xml
    @@ -0,0 +1,22 @@
    +
    +
    +
    +    IconsTest
    +    IconsTest. Search by Test.
    +    UTF-8
    +    data:image/x-icon;base64,ico16
    +    data:image/x-icon;base64,ico32
    +    data:image/png;base64,ico74
    +    
    +        
    +        
    +    
    +    
    +        
    +        
    +        
    +    
    +    http://www.bing.com/search
    +
    diff --git a/toolkit/components/search/tests/xpcshell/test_multipleIcons.js b/toolkit/components/search/tests/xpcshell/test_multipleIcons.js
    new file mode 100644
    index 000000000000..253ea7f9d026
    --- /dev/null
    +++ b/toolkit/components/search/tests/xpcshell/test_multipleIcons.js
    @@ -0,0 +1,78 @@
    +/* Any copyright is dedicated to the Public Domain.
    + http://creativecommons.org/publicdomain/zero/1.0/ */
    +
    +/*
    + * Tests getIcons() and getIconURLBySize() on engine with multiple icons.
    + */
    +
    +"use strict";
    +
    +const Ci = Components.interfaces;
    +const Cu = Components.utils;
    +
    +Cu.import("resource://testing-common/httpd.js");
    +
    +  function test_multiIcon() {
    +  let engine = Services.search.getEngineByName("IconsTest");
    +  do_check_neq(engine, null);
    +
    +  do_print("Running tests on IconsTest engine");
    +
    +  do_print("The default should be the 16x16 icon");
    +  do_check_true(engine.iconURI.spec.contains("ico16"));
    +
    +  do_check_true(engine.getIconURLBySize(32,32).contains("ico32"));
    +  do_check_true(engine.getIconURLBySize(74,74).contains("ico74"));
    +
    +  do_print("Invalid dimensions should return null.");
    +  do_check_null(engine.getIconURLBySize(50,50));
    +
    +  let allIcons = engine.getIcons();
    +
    +  do_print("Check that allIcons contains expected icon sizes");
    +  do_check_eq(allIcons.length, 3);
    +  let expectedWidths = [16, 32, 74];
    +  do_check_true(allIcons.every((item) => {
    +    let width = item.width;
    +    do_check_neq(expectedWidths.indexOf(width), -1);
    +    do_check_eq(width, item.height);
    +
    +    let icon = item.url.split(",").pop();
    +    do_check_eq(icon, "ico" + width);
    +
    +    return true;
    +  }));
    +
    +  do_test_finished();
    +}
    +
    +function run_test() {
    +  removeMetadata();
    +  updateAppInfo();
    +
    +  let httpServer = new HttpServer();
    +  httpServer.start(4444);
    +  httpServer.registerDirectory("/", do_get_cwd());
    +
    +  do_register_cleanup(function cleanup() {
    +    httpServer.stop(function() {});
    +  });
    +
    +  do_test_pending();
    +
    +  let observer = function(aSubject, aTopic, aData) {
    +    if (aData == "engine-loaded") {
    +      test_multiIcon();
    +    }
    +  };
    +
    +  Services.obs.addObserver(observer, "browser-search-engine-modified", false);
    +
    +  do_print("Adding engine with multiple images");
    +  Services.search.addEngine("http://localhost:4444/data/engineImages.xml",
    +    Ci.nsISearchEngine.DATA_XML, null, false);
    +
    +  do_timeout(12000, function() {
    +    do_throw("Timeout");
    +  });
    +}
    diff --git a/toolkit/components/search/tests/xpcshell/xpcshell.ini b/toolkit/components/search/tests/xpcshell/xpcshell.ini
    index 38658c085665..8540282ca75d 100644
    --- a/toolkit/components/search/tests/xpcshell/xpcshell.ini
    +++ b/toolkit/components/search/tests/xpcshell/xpcshell.ini
    @@ -7,6 +7,7 @@ support-files =
       data/engine.src
       data/engine.xml
       data/engine2.xml
    +  data/engineImages.xml
       data/ico-size-16x16-png.ico
       data/search-metadata.json
       data/search.json
    @@ -27,6 +28,7 @@ support-files =
     [test_prefSync.js]
     [test_notifications.js]
     [test_addEngine_callback.js]
    +[test_multipleIcons.js]
     [test_async.js]
     [test_sync.js]
     [test_sync_fallback.js]
    
    From 0d1eacd64bf4a762b0d5c380e7a57af0be6426ac Mon Sep 17 00:00:00 2001
    From: Terrence Cole 
    Date: Tue, 5 Nov 2013 10:22:43 -0800
    Subject: [PATCH 43/82] Bug 930526 - Add a missing OOM check to
     js_InitTypedObjectClass; r=nmatsakis
    
    --HG--
    extra : rebase_source : 86049b48e6fb0f772d8edaabb403e1d8c1442706
    ---
     js/src/builtin/TypedObject.cpp | 2 ++
     1 file changed, 2 insertions(+)
    
    diff --git a/js/src/builtin/TypedObject.cpp b/js/src/builtin/TypedObject.cpp
    index d58b2e971bf1..583de578c5fb 100644
    --- a/js/src/builtin/TypedObject.cpp
    +++ b/js/src/builtin/TypedObject.cpp
    @@ -1249,6 +1249,8 @@ js_InitTypedObjectClass(JSContext *cx, HandleObject obj)
     
         RootedObject module(cx, NewObjectWithClassProto(cx, &JSObject::class_,
                                                         objProto, global));
    +    if (!module)
    +        return nullptr;
     
         // Define TypedObject global.
     
    
    From 23727cd8e77e247037f4c8d1962196b3fe647eff Mon Sep 17 00:00:00 2001
    From: Terrence Cole 
    Date: Wed, 6 Nov 2013 08:43:04 -0800
    Subject: [PATCH 44/82] Bug 935271 - Fix ifdefs in js/src/gc/Memory.cpp;
     r=billm
    
    --HG--
    extra : rebase_source : 182c3747cafb76ee1c325515a22c1c89c7bd0930
    ---
     js/src/gc/Memory.cpp | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/js/src/gc/Memory.cpp b/js/src/gc/Memory.cpp
    index 97e30db09c73..4c9159809f01 100644
    --- a/js/src/gc/Memory.cpp
    +++ b/js/src/gc/Memory.cpp
    @@ -297,7 +297,7 @@ gc::GetPageFaultCount()
         return 0;
     }
     
    -#elif defined(XP_UNIX) || defined(XP_MACOSX) || defined(DARWIN)
    +#elif defined(XP_UNIX)
     
     #include 
     #include 
    
    From 99ef56df988accd42e3ef9399b89603d3b83c995 Mon Sep 17 00:00:00 2001
    From: Terrence Cole 
    Date: Wed, 6 Nov 2013 09:06:57 -0800
    Subject: [PATCH 45/82] Bug 935586 - Fix an exact rooting hazard in
     getIntrinsicValue; r=bhackett
    
    --HG--
    extra : rebase_source : eca4c08e60a5583c18a6f1d985ff1a86d19c8a7e
    ---
     js/src/vm/GlobalObject.h | 3 ++-
     1 file changed, 2 insertions(+), 1 deletion(-)
    
    diff --git a/js/src/vm/GlobalObject.h b/js/src/vm/GlobalObject.h
    index 7e8b004aa9a3..401bf8b2c4e3 100644
    --- a/js/src/vm/GlobalObject.h
    +++ b/js/src/vm/GlobalObject.h
    @@ -529,9 +529,10 @@ class GlobalObject : public JSObject
         bool getIntrinsicValue(JSContext *cx, HandlePropertyName name, MutableHandleValue value) {
             if (maybeGetIntrinsicValue(name, value.address()))
                 return true;
    +        Rooted self(cx, this);
             if (!cx->runtime()->cloneSelfHostedValue(cx, name, value))
                 return false;
    -        RootedObject holder(cx, intrinsicsHolder());
    +        RootedObject holder(cx, self->intrinsicsHolder());
             RootedId id(cx, NameToId(name));
             return JS_DefinePropertyById(cx, holder, id, value, nullptr, nullptr, 0);
         }
    
    From 2bd8f8f14823f0a6b7ae0969b72378f6cbacac53 Mon Sep 17 00:00:00 2001
    From: Terrence Cole 
    Date: Tue, 5 Nov 2013 15:02:35 -0800
    Subject: [PATCH 46/82] Bug 931912 - Suppress an exact rooting hazard false
     positive in nsWindowSH::Finalize; r=sfink
    
    --HG--
    extra : rebase_source : 3934e7cd7e21e37de20aadac203db6a285021691
    ---
     dom/base/nsDOMClassInfo.cpp | 8 ++++++++
     js/public/GCAPI.h           | 7 ++++++-
     2 files changed, 14 insertions(+), 1 deletion(-)
    
    diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp
    index 78a55c5da911..b6ad4c2b3a25 100644
    --- a/dom/base/nsDOMClassInfo.cpp
    +++ b/dom/base/nsDOMClassInfo.cpp
    @@ -3651,6 +3651,14 @@ NS_IMETHODIMP
     nsWindowSH::Finalize(nsIXPConnectWrappedNative *wrapper, JSFreeOp *fop,
                          JSObject *obj)
     {
    +  // Since this call is virtual, the exact rooting hazard static analysis is
    +  // not able to determine that it happens during finalization and should be
    +  // ignored. Moreover, the analysis cannot discover and validate the
    +  // potential targets of the virtual call to OnFinalize below because of the
    +  // indirection through nsCOMMPtr. Thus, we annotate the analysis here so
    +  // that it does not report OnFinalize as GCing with |obj| on stack.
    +  JS::AutoAssertNoGC nogc;
    +
       nsCOMPtr sgo(do_QueryWrappedNative(wrapper));
       NS_ENSURE_TRUE(sgo, NS_ERROR_UNEXPECTED);
     
    diff --git a/js/public/GCAPI.h b/js/public/GCAPI.h
    index 7c3e9b32de52..8102d7f7e337 100644
    --- a/js/public/GCAPI.h
    +++ b/js/public/GCAPI.h
    @@ -213,13 +213,18 @@ WasIncrementalGC(JSRuntime *rt);
     extern JS_FRIEND_API(size_t)
     GetGCNumber();
     
    -class AutoAssertNoGC {
    +class JS_PUBLIC_API(AutoAssertNoGC)
    +{
     #ifdef DEBUG
         size_t gcNumber;
     
       public:
         AutoAssertNoGC();
         ~AutoAssertNoGC();
    +#else
    +  public:
    +    /* Prevent unreferenced local warnings in opt builds. */
    +    AutoAssertNoGC() {}
     #endif
     };
     
    
    From 748b85286179b5f5573f88346591049c92a26f37 Mon Sep 17 00:00:00 2001
    From: David Anderson 
    Date: Wed, 6 Nov 2013 11:55:58 -0800
    Subject: [PATCH 47/82] Don't copy surfaces in DeprecatedTextureHostBasic::Lock
     (bug 935641, r=mattwoodrow).
    
    --HG--
    extra : rebase_source : e97318912cc295b6b1dc5027eba1690e42d24003
    ---
     gfx/layers/basic/BasicCompositor.cpp | 8 ++++----
     1 file changed, 4 insertions(+), 4 deletions(-)
    
    diff --git a/gfx/layers/basic/BasicCompositor.cpp b/gfx/layers/basic/BasicCompositor.cpp
    index 2200776506df..a263b055377b 100644
    --- a/gfx/layers/basic/BasicCompositor.cpp
    +++ b/gfx/layers/basic/BasicCompositor.cpp
    @@ -115,10 +115,10 @@ protected:
       {
         EnsureSurface();
         if (!mSurface) {
    -      mSurface = mCompositor->GetDrawTarget()->CreateSourceSurfaceFromData(mThebesImage->Data(),
    -                                                                           mSize,
    -                                                                           mThebesImage->Stride(),
    -                                                                           mFormat);
    +      mSurface = Factory::CreateWrappingDataSourceSurface(mThebesImage->Data(),
    +                                                          mThebesImage->Stride(),
    +                                                          mSize,
    +                                                          mFormat);
         }
         return true;
       }
    
    From f34062284cedf544d8dab3d7678e13c6086026c0 Mon Sep 17 00:00:00 2001
    From: Terrence Cole 
    Date: Thu, 17 Oct 2013 09:12:23 -0700
    Subject: [PATCH 48/82] Bug 909972 - Avoid unnecessary GCs in asm.js
     compilation; r=luke
    
    --HG--
    extra : rebase_source : 41a55a9f837016efbcf013f9b51e9f5f5c48f28b
    ---
     js/src/jit/AsmJS.cpp | 27 ++++++++++++++++++++++-----
     js/src/jsfriendapi.h | 10 +++++++++-
     2 files changed, 31 insertions(+), 6 deletions(-)
    
    diff --git a/js/src/jit/AsmJS.cpp b/js/src/jit/AsmJS.cpp
    index 03d75992e9f6..fc188ef8fec9 100644
    --- a/js/src/jit/AsmJS.cpp
    +++ b/js/src/jit/AsmJS.cpp
    @@ -1231,6 +1231,7 @@ class MOZ_STACK_CLASS ModuleCompiler
     
         char *                         errorString_;
         uint32_t                       errorOffset_;
    +    bool                           errorOverRecursed_;
     
         int64_t                        usecBefore_;
         SlowFunctionVector             slowFunctions_;
    @@ -1260,6 +1261,7 @@ class MOZ_STACK_CLASS ModuleCompiler
             globalAccesses_(cx),
             errorString_(nullptr),
             errorOffset_(UINT32_MAX),
    +        errorOverRecursed_(false),
             usecBefore_(PRMJ_Now()),
             slowFunctions_(cx),
             finishedFunctionBodies_(false)
    @@ -1275,6 +1277,8 @@ class MOZ_STACK_CLASS ModuleCompiler
                                                      errorString_);
                 js_free(errorString_);
             }
    +        if (errorOverRecursed_)
    +            js_ReportOverRecursed(cx_);
     
             // Avoid spurious Label assertions on compilation failure.
             if (!stackOverflowLabel_.bound())
    @@ -1324,7 +1328,15 @@ class MOZ_STACK_CLASS ModuleCompiler
         }
     
         bool fail(ParseNode *pn, const char *str) {
    -        return failOffset(pn ? pn->pn_pos.begin : parser_.tokenStream.peekTokenPos().begin, str);
    +        if (pn)
    +            return failOffset(pn->pn_pos.begin, str);
    +
    +        // The exact rooting static analysis does not perform dataflow analysis, so it believes
    +        // that unrooted things on the stack during compilation may still be accessed after this.
    +        // Since pn is typically only null under OOM, this suppression simply forces any GC to be
    +        // delayed until the compilation is off the stack and more memory can be freed.
    +        gc::AutoSuppressGC nogc(cx_);
    +        return failOffset(parser_.tokenStream.peekTokenPos().begin, str);
         }
     
         bool failfVA(ParseNode *pn, const char *fmt, va_list ap) {
    @@ -1353,6 +1365,11 @@ class MOZ_STACK_CLASS ModuleCompiler
             return false;
         }
     
    +    bool failOverRecursed() {
    +        errorOverRecursed_ = true;
    +        return false;
    +    }
    +
         static const unsigned SLOW_FUNCTION_THRESHOLD_MS = 250;
     
         bool maybeReportCompileTime(const Func &func) {
    @@ -3813,7 +3830,7 @@ CheckMathBuiltinCall(FunctionCompiler &f, ParseNode *callNode, AsmJSMathBuiltin
     static bool
     CheckCall(FunctionCompiler &f, ParseNode *call, RetType retType, MDefinition **def, Type *type)
     {
    -    JS_CHECK_RECURSION(f.cx(), return false);
    +    JS_CHECK_RECURSION_DONT_REPORT(f.cx(), return f.m().failOverRecursed());
     
         ParseNode *callee = CallCallee(call);
     
    @@ -4104,7 +4121,7 @@ static bool
     CheckAddOrSub(FunctionCompiler &f, ParseNode *expr, MDefinition **def, Type *type,
                   unsigned *numAddOrSubOut = nullptr)
     {
    -    JS_CHECK_RECURSION(f.cx(), return false);
    +    JS_CHECK_RECURSION_DONT_REPORT(f.cx(), return f.m().failOverRecursed());
     
         JS_ASSERT(expr->isKind(PNK_ADD) || expr->isKind(PNK_SUB));
         ParseNode *lhs = BinaryLeft(expr);
    @@ -4308,7 +4325,7 @@ CheckBitwise(FunctionCompiler &f, ParseNode *bitwise, MDefinition **def, Type *t
     static bool
     CheckExpr(FunctionCompiler &f, ParseNode *expr, MDefinition **def, Type *type)
     {
    -    JS_CHECK_RECURSION(f.cx(), return false);
    +    JS_CHECK_RECURSION_DONT_REPORT(f.cx(), return f.m().failOverRecursed());
     
         if (!f.mirGen().ensureBallast())
             return false;
    @@ -4781,7 +4798,7 @@ CheckStatementList(FunctionCompiler &f, ParseNode *stmtList)
     static bool
     CheckStatement(FunctionCompiler &f, ParseNode *stmt, LabelVector *maybeLabels)
     {
    -    JS_CHECK_RECURSION(f.cx(), return false);
    +    JS_CHECK_RECURSION_DONT_REPORT(f.cx(), return f.m().failOverRecursed());
     
         if (!f.mirGen().ensureBallast())
             return false;
    diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h
    index 92a84cf57df3..d0c13dfd9410 100644
    --- a/js/src/jsfriendapi.h
    +++ b/js/src/jsfriendapi.h
    @@ -665,7 +665,7 @@ GetNativeStackLimit(JSContext *cx)
      * extra space so that we can ensure that crucial code is able to run.
      */
     
    -#define JS_CHECK_RECURSION(cx, onerror)                              \
    +#define JS_CHECK_RECURSION(cx, onerror)                                         \
         JS_BEGIN_MACRO                                                              \
             int stackDummy_;                                                        \
             if (!JS_CHECK_STACK_SIZE(js::GetNativeStackLimit(cx), &stackDummy_)) {  \
    @@ -674,6 +674,14 @@ GetNativeStackLimit(JSContext *cx)
             }                                                                       \
         JS_END_MACRO
     
    +#define JS_CHECK_RECURSION_DONT_REPORT(cx, onerror)                             \
    +    JS_BEGIN_MACRO                                                              \
    +        int stackDummy_;                                                        \
    +        if (!JS_CHECK_STACK_SIZE(js::GetNativeStackLimit(cx), &stackDummy_)) {  \
    +            onerror;                                                            \
    +        }                                                                       \
    +    JS_END_MACRO
    +
     #define JS_CHECK_RECURSION_WITH_SP_DONT_REPORT(cx, sp, onerror)                 \
         JS_BEGIN_MACRO                                                              \
             if (!JS_CHECK_STACK_SIZE(js::GetNativeStackLimit(cx), sp)) {            \
    
    From 6138889fff87a5f11130bd0dc013319cda852e6b Mon Sep 17 00:00:00 2001
    From: Mark Hammond 
    Date: Thu, 7 Nov 2013 10:49:41 +1100
    Subject: [PATCH 49/82] Bug 883858 - pass disabled tests to the test runner and
     have them reported in the test log. r=jmaher
    
    ---
     testing/mochitest/manifestLibrary.js | 4 ++++
     testing/mochitest/runtests.py        | 5 ++++-
     2 files changed, 8 insertions(+), 1 deletion(-)
    
    diff --git a/testing/mochitest/manifestLibrary.js b/testing/mochitest/manifestLibrary.js
    index b7986431d700..04c227cba812 100644
    --- a/testing/mochitest/manifestLibrary.js
    +++ b/testing/mochitest/manifestLibrary.js
    @@ -19,6 +19,10 @@ function parseTestManifest(testManifest, params, callback) {
       // For mochitest-plain, we define lists as an array of testnames.
       for (var obj of testManifest['tests']) {
         var path = obj['path'];
    +    if (obj.disabled) {
    +      dump("TEST-SKIPPED | " + path + " | " + obj.disabled + "\n");
    +      continue;
    +    }
         if (params.testRoot != 'tests' && params.testRoot !== undefined) {
           links[params.baseurl + '/' + params.testRoot + '/' + path] = true
         } else {
    diff --git a/testing/mochitest/runtests.py b/testing/mochitest/runtests.py
    index 1a60b5f57891..ec0a38d8d426 100644
    --- a/testing/mochitest/runtests.py
    +++ b/testing/mochitest/runtests.py
    @@ -362,7 +362,10 @@ class MochitestUtilsMixin(object):
             if options.testPath and not tp.startswith(options.testPath):
               continue
     
    -        paths.append({'path': tp})
    +        testob = {'path': tp}
    +        if test.has_key('disabled'):
    +          testob['disabled'] = test['disabled']
    +        paths.append(testob)
     
           # Bug 883865 - add this functionality into manifestDestiny
           with open('tests.json', 'w') as manifestFile:
    
    From 863ffe2480f308697327db876e57a0f061c436c1 Mon Sep 17 00:00:00 2001
    From: Andrew McCreight 
    Date: Wed, 6 Nov 2013 16:58:13 -0800
    Subject: [PATCH 50/82] Bug 934568 - Don't make ScanRoots CC OOM assertion
     fatal due to Win7 debug M2 failures. s=smaug
    
    ---
     xpcom/base/nsCycleCollector.cpp | 5 ++---
     1 file changed, 2 insertions(+), 3 deletions(-)
    
    diff --git a/xpcom/base/nsCycleCollector.cpp b/xpcom/base/nsCycleCollector.cpp
    index ba01e6f0f6cf..da0bd54e13cc 100644
    --- a/xpcom/base/nsCycleCollector.cpp
    +++ b/xpcom/base/nsCycleCollector.cpp
    @@ -2132,8 +2132,7 @@ nsCycleCollector::MarkRoots(GCGraphBuilder &aBuilder)
         }
     
         if (aBuilder.RanOutOfMemory()) {
    -        MOZ_ASSERT(false,
    -                     "Ran out of memory while building cycle collector graph");
    +        MOZ_ASSERT(false, "Ran out of memory while building cycle collector graph");
             CC_TELEMETRY(_OOM, true);
         }
     }
    @@ -2267,7 +2266,7 @@ nsCycleCollector::ScanRoots(nsICycleCollectorListener *aListener)
         GraphWalker(scanVisitor(mWhiteNodeCount, failed)).WalkFromRoots(mGraph);
     
         if (failed) {
    -        MOZ_ASSERT(false, "Ran out of memory in ScanRoots");
    +        NS_ASSERTION(false, "Ran out of memory in ScanRoots");
             CC_TELEMETRY(_OOM, true);
         }
     
    
    From aa1e8d3d40b36c6ba5749fcde4c4d92ed5e8289f Mon Sep 17 00:00:00 2001
    From: Matthew Gregan 
    Date: Wed, 23 Oct 2013 15:31:28 +1300
    Subject: [PATCH 51/82] Bug 927245 - Pref off deprecated Audio Data API
     implementation.  r=ehsan
    
    ---
     modules/libpref/src/init/all.js | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js
    index 3653bbec5d9b..3df16e3f28df 100644
    --- a/modules/libpref/src/init/all.js
    +++ b/modules/libpref/src/init/all.js
    @@ -282,7 +282,7 @@ pref("media.video-queue.default-size", 10);
     pref("media.video_stats.enabled", true);
     
     // Whether to enable the audio writing APIs on the audio element
    -pref("media.audio_data.enabled", true);
    +pref("media.audio_data.enabled", false);
     
     // Whether to lock touch scrolling to one axis at a time
     // 0 = FREE (No locking at all)
    
    From ee433d829f6a67b9e4c63d81ad5b0ee8fd2406e0 Mon Sep 17 00:00:00 2001
    From: Matt Brubeck 
    Date: Wed, 6 Nov 2013 12:06:46 -0800
    Subject: [PATCH 52/82] Bug 934750 - Don't cancel content touch events unless
     APZC consumes them [r=jimm,kats]
    
    This is necessary for our "cross-slide" hack to work.  We need to send
    input to both content and APZC until the input passes the pan threshold, so
    that the start page can use touch events without disabling async panning.
    
    In the long run we hope to use "touch-action: pan-x" for this and no longer
    rely on this hack.
    ---
     gfx/layers/ipc/AsyncPanZoomController.cpp |  2 +-
     widget/windows/winrt/MetroInput.cpp       | 32 +++++++++++++++--------
     widget/windows/winrt/MetroInput.h         |  1 +
     3 files changed, 23 insertions(+), 12 deletions(-)
    
    diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp
    index 0d363b509c4d..45dfb11e80b2 100644
    --- a/gfx/layers/ipc/AsyncPanZoomController.cpp
    +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp
    @@ -383,7 +383,7 @@ nsEventStatus AsyncPanZoomController::ReceiveInputEvent(const InputData& aEvent)
             PostDelayedTask(mTouchListenerTimeoutTask, gTouchListenerTimeout);
           }
         }
    -    return nsEventStatus_eConsumeNoDefault;
    +    return nsEventStatus_eIgnore;
       }
     
       return HandleInputEvent(aEvent);
    diff --git a/widget/windows/winrt/MetroInput.cpp b/widget/windows/winrt/MetroInput.cpp
    index a9ace45f9d94..65947328f780 100644
    --- a/widget/windows/winrt/MetroInput.cpp
    +++ b/widget/windows/winrt/MetroInput.cpp
    @@ -491,6 +491,7 @@ MetroInput::OnPointerPressed(UI::Core::ICoreWindow* aSender,
         // If this is the first touchstart of a touch session reset some
         // tracking flags.
         mContentConsumingTouch = false;
    +    mApzConsumingTouch = false;
         mRecognizerWantsEvents = true;
         mCancelable = true;
         mCanceledIds.Clear();
    @@ -1096,7 +1097,9 @@ MetroInput::DeliverNextQueuedTouchEvent()
        * 3) If mContentConsumingTouch is true: deliver touch to content after
        *  transforming through the apz. Also let the apz know content is
        *  consuming touch.
    -   * 4) If mContentConsumingTouch is false: send a touchcancel to content
    +   * 4) If mContentConsumingTouch is false: check the result from the apz and
    +   *  set mApzConsumingTouch appropriately.
    +   * 5) If mApzConsumingTouch is true: send a touchcancel to content
        *  and deliver all events to the apz. If the apz is doing something with
        *  the events we can save ourselves the overhead of delivering dom events.
        *
    @@ -1149,7 +1152,6 @@ MetroInput::DeliverNextQueuedTouchEvent()
             mWidget->ApzContentConsumingTouch();
           } else {
             mWidget->ApzContentIgnoringTouch();
    -        DispatchTouchCancel(&transformedEvent);
           }
         }
         // If content is consuming touch don't generate any gesture based
    @@ -1160,22 +1162,30 @@ MetroInput::DeliverNextQueuedTouchEvent()
         return;
       }
     
    +  // Forward event data to apz.  Even if content is consuming input, we still
    +  // need APZC to transform the coordinates.  It won't actually react to the
    +  // event if ContentReceivedTouch was called previously.
    +  DUMP_TOUCH_IDS("APZC(2)", event);
    +  status = mWidget->ApzReceiveInputEvent(event);
    +
       // If content called preventDefault on touchstart or first touchmove send
    -  // the event to content.
    +  // the event to content only.
       if (mContentConsumingTouch) {
    -    // ContentReceivedTouch has already been called in the mCancelable block
    -    // above so this shouldn't cause the apz to react. We still need to
    -    // transform our coordinates though.
    -    DUMP_TOUCH_IDS("APZC(2)", event);
    -    mWidget->ApzReceiveInputEvent(event);
         DUMP_TOUCH_IDS("DOM(3)", event);
         mWidget->DispatchEvent(event, status);
         return;
       }
     
    -  // Forward event data to apz.
    -  DUMP_TOUCH_IDS("APZC(3)", event);
    -  mWidget->ApzReceiveInputEvent(event);
    +  // Send the event to content unless APZC is consuming it.
    +  if (!mApzConsumingTouch) {
    +    if (status == nsEventStatus_eConsumeNoDefault) {
    +      mApzConsumingTouch = true;
    +      DispatchTouchCancel(event);
    +      return;
    +    }
    +    DUMP_TOUCH_IDS("DOM(4)", event);
    +    mWidget->DispatchEvent(event, status);
    +  }
     }
     
     void
    diff --git a/widget/windows/winrt/MetroInput.h b/widget/windows/winrt/MetroInput.h
    index d0e2ab0a9135..e7383ba47a43 100644
    --- a/widget/windows/winrt/MetroInput.h
    +++ b/widget/windows/winrt/MetroInput.h
    @@ -203,6 +203,7 @@ private:
       //   For example, a set of mousemove, mousedown, and mouseup events might
       //   be sent if a tap is detected.
       bool mContentConsumingTouch;
    +  bool mApzConsumingTouch;
       bool mCancelable;
       bool mRecognizerWantsEvents;
       nsTArray mCanceledIds;
    
    From afb0b98b127654e3278d1a90b9f2f7b1f7634434 Mon Sep 17 00:00:00 2001
    From: Matt Brubeck 
    Date: Wed, 6 Nov 2013 12:06:47 -0800
    Subject: [PATCH 53/82] Bug 935554 - Don't show navbar when url changes in a
     background tab. r=rsilveira
    
    ---
     browser/metro/base/content/ContextUI.js | 4 +++-
     1 file changed, 3 insertions(+), 1 deletion(-)
    
    diff --git a/browser/metro/base/content/ContextUI.js b/browser/metro/base/content/ContextUI.js
    index 59b057513cd3..ab588c93e688 100644
    --- a/browser/metro/base/content/ContextUI.js
    +++ b/browser/metro/base/content/ContextUI.js
    @@ -292,7 +292,9 @@ var ContextUI = {
       handleEvent: function handleEvent(aEvent) {
         switch (aEvent.type) {
           case "URLChanged":
    -        this.displayNavbar();
    +        if (aEvent.target == Browser.selectedBrowser) {
    +          this.displayNavbar();
    +        }
             break;
           case "MozEdgeUIStarted":
             this._onEdgeUIStarted(aEvent);
    
    From 336c93949dd1b2e66bed07667341afe381733097 Mon Sep 17 00:00:00 2001
    From: Rodrigo Silveira 
    Date: Tue, 29 Oct 2013 21:29:07 -0700
    Subject: [PATCH 54/82] Bug 927172 - Can't touch scroll when second monitor is
     attached r=jimm
    
    --HG--
    extra : rebase_source : 9d583bda2e6def27f5f99c74481635dd79621179
    ---
     widget/windows/winrt/FrameworkView.cpp | 30 +++++++++++++++-----------
     widget/windows/winrt/FrameworkView.h   |  1 +
     2 files changed, 19 insertions(+), 12 deletions(-)
    
    diff --git a/widget/windows/winrt/FrameworkView.cpp b/widget/windows/winrt/FrameworkView.cpp
    index 9405006befb3..19a4d48c7267 100644
    --- a/widget/windows/winrt/FrameworkView.cpp
    +++ b/widget/windows/winrt/FrameworkView.cpp
    @@ -258,6 +258,7 @@ FrameworkView::UpdateWidgetSizeAndPosition()
       NS_ASSERTION(mWindow, "SetWindow must be called before UpdateWidgetSizeAndPosition!");
       NS_ASSERTION(mWidget, "SetWidget must be called before UpdateWidgetSizeAndPosition!");
     
    +  UpdateBounds();
       mWidget->Move(0, 0);
       mWidget->Resize(0, 0, mWindowBounds.width, mWindowBounds.height, true);
       mWidget->SizeModeChanged();
    @@ -284,21 +285,30 @@ void FrameworkView::SetDpi(float aDpi)
         LogFunction();
     
         mDPI = aDpi;
    -    // Often a DPI change implies a window size change.
    -    NS_ASSERTION(mWindow, "SetWindow must be called before SetDpi!");
    -    Rect logicalBounds;
    -    mWindow->get_Bounds(&logicalBounds);
    -
    -    // convert to physical (device) pixels
    -    mWindowBounds = MetroUtils::LogToPhys(logicalBounds);
     
         // notify the widget that dpi has changed
         if (mWidget) {
           mWidget->ChangedDPI();
    +      UpdateBounds();
         }
       }
     }
     
    +void
    +FrameworkView::UpdateBounds()
    +{
    +  if (!mWidget)
    +    return;
    +
    +  RECT winRect;
    +  GetClientRect(mWidget->GetICoreWindowHWND(), &winRect);
    +
    +  mWindowBounds = nsIntRect(winRect.left,
    +                            winRect.top,
    +                            winRect.right - winRect.left,
    +                            winRect.bottom - winRect.top);
    +}
    +
     void
     FrameworkView::SetWidget(MetroWidget* aWidget)
     {
    @@ -307,6 +317,7 @@ FrameworkView::SetWidget(MetroWidget* aWidget)
       LogFunction();
       mWidget = aWidget;
       mWidget->FindMetroWindow();
    +  UpdateBounds();
     }
     
     ////////////////////////////////////////////////////
    @@ -394,11 +405,6 @@ FrameworkView::OnWindowSizeChanged(ICoreWindow* aSender, IWindowSizeChangedEvent
         return S_OK;
       }
     
    -  NS_ASSERTION(mWindow, "SetWindow must be called before OnWindowSizeChanged!");
    -  Rect logicalBounds;
    -  mWindow->get_Bounds(&logicalBounds);
    -  mWindowBounds = MetroUtils::LogToPhys(logicalBounds);
    -
       UpdateWidgetSizeAndPosition();
       return S_OK;
     }
    diff --git a/widget/windows/winrt/FrameworkView.h b/widget/windows/winrt/FrameworkView.h
    index 8b50ef74fae2..ea0139160e3d 100644
    --- a/widget/windows/winrt/FrameworkView.h
    +++ b/widget/windows/winrt/FrameworkView.h
    @@ -150,6 +150,7 @@ protected:
       void UpdateLogicalDPI();
       void FireViewStateObservers();
       void ProcessLaunchArguments();
    +  void UpdateBounds();
     
       // Printing and preview
       void CreatePrintControl(IPrintDocumentPackageTarget* aDocPackageTarget, 
    
    From 7cbc50abf139e3b73a0494c948f37a965f3ff2e8 Mon Sep 17 00:00:00 2001
    From: Wes Kocher 
    Date: Wed, 6 Nov 2013 12:53:11 -0800
    Subject: [PATCH 55/82] Backed out 3 changesets (bug 927116) for Win debug
     XPCShell test bustage
    
    Backed out changeset dfeee13c85fb (bug 927116)
    Backed out changeset 17b2babbe34e (bug 927116)
    Backed out changeset 13f60271f4f6 (bug 927116)
    ---
     js/src/frontend/BytecodeEmitter.cpp           |   5 -
     js/src/frontend/FullParseHandler.h            |  10 -
     js/src/frontend/ParseNode.h                   |   3 -
     js/src/frontend/Parser.cpp                    | 130 ------------
     js/src/frontend/Parser.h                      |   1 -
     js/src/jit-test/lib/match.js                  |   1 -
     .../tests/modules/import-declaration.js       | 186 ------------------
     js/src/js.msg                                 |  10 -
     js/src/jsast.tbl                              |   2 -
     js/src/jsreflect.cpp                          |  76 -------
     js/src/vm/CommonPropertyNames.h               |   3 -
     js/src/vm/Keywords.h                          |   2 +-
     12 files changed, 1 insertion(+), 428 deletions(-)
     delete mode 100644 js/src/jit-test/lib/match.js
     delete mode 100644 js/src/jit-test/tests/modules/import-declaration.js
    
    diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
    index a078a94b681a..4de784ea04be 100644
    --- a/js/src/frontend/BytecodeEmitter.cpp
    +++ b/js/src/frontend/BytecodeEmitter.cpp
    @@ -6447,11 +6447,6 @@ frontend::EmitTree(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
                  : EmitVariables(cx, bce, pn, InitializeVars);
             break;
     
    -      case PNK_IMPORT:
    -       // TODO: Implement emitter support for modules
    -       bce->reportError(nullptr, JSMSG_MODULES_NOT_IMPLEMENTED);
    -       return false;
    -
           case PNK_ARRAYPUSH: {
             int slot;
     
    diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h
    index b638d76daeff..7bde5f46eca9 100644
    --- a/js/src/frontend/FullParseHandler.h
    +++ b/js/src/frontend/FullParseHandler.h
    @@ -295,16 +295,6 @@ class FullParseHandler
             return new_(PNK_SEMI, JSOP_NOP, pos, (ParseNode *) nullptr);
         }
     
    -    ParseNode *newImportDeclaration(ParseNode *importSpecSet,
    -                                    ParseNode *moduleSpec, const TokenPos &pos)
    -    {
    -        ParseNode *pn = new_(PNK_IMPORT, JSOP_NOP, pos,
    -                                         importSpecSet, moduleSpec);
    -        if (!pn)
    -            return null();
    -        return pn;
    -    }
    -
         ParseNode *newExprStatement(ParseNode *expr, uint32_t end) {
             JS_ASSERT(expr->pn_pos.end <= end);
             return new_(PNK_SEMI, JSOP_NOP, TokenPos(expr->pn_pos.begin, end), expr);
    diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h
    index 4b8cb1bf7943..bb981cb8cbaf 100644
    --- a/js/src/frontend/ParseNode.h
    +++ b/js/src/frontend/ParseNode.h
    @@ -128,9 +128,6 @@ class UpvarCookie
         F(ARRAYPUSH) \
         F(LEXICALSCOPE) \
         F(LET) \
    -    F(IMPORT) \
    -    F(IMPORT_SPEC_LIST) \
    -    F(IMPORT_SPEC) \
         F(SEQ) \
         F(FORIN) \
         F(FOROF) \
    diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
    index d191d17b8ffe..0cb25dbac7e3 100644
    --- a/js/src/frontend/Parser.cpp
    +++ b/js/src/frontend/Parser.cpp
    @@ -3628,134 +3628,6 @@ Parser::letStatement()
         return SyntaxParseHandler::NodeFailure;
     }
     
    -template
    -typename ParseHandler::Node
    -Parser::importDeclaration()
    -{
    -    JS_ASSERT(tokenStream.currentToken().type == TOK_IMPORT);
    -
    -    if (pc->sc->isFunctionBox() || !pc->atBodyLevel()) {
    -        report(ParseError, false, null(), JSMSG_IMPORT_DECL_AT_TOP_LEVEL);
    -        return null();
    -    }
    -
    -    uint32_t begin = pos().begin;
    -    TokenKind tt = tokenStream.getToken();
    -
    -    Node importSpecSet = handler.newList(PNK_IMPORT_SPEC_LIST);
    -    if (!importSpecSet)
    -        return null();
    -
    -    if (tt == TOK_NAME || tt == TOK_LC) {
    -        if (tt == TOK_NAME) {
    -            // Handle the form |import a from 'b'|, by adding a single import
    -            // specifier to the list, with 'default' as the import name and
    -            // 'a' as the binding name. This is equivalent to
    -            // |import { default as a } from 'b'|.
    -            Node importName = newName(context->names().default_);
    -            if (!importName)
    -                return null();
    -
    -            Node bindingName = newName(tokenStream.currentName());
    -            if (!bindingName)
    -                return null();
    -
    -            Node importSpec = handler.newBinary(PNK_IMPORT_SPEC, importName, bindingName);
    -            if (!importSpec)
    -                return null();
    -
    -            handler.addList(importSpecSet, importSpec);
    -        } else {
    -            do {
    -                // Handle the forms |import {} from 'a'| and
    -                // |import { ..., } from 'a'| (where ... is non empty), by
    -                // escaping the loop early if the next token is }.
    -                tt = tokenStream.peekToken(TokenStream::KeywordIsName);
    -                if (tt == TOK_ERROR)
    -                    return null();
    -                if (tt == TOK_RC)
    -                    break;
    -
    -                // If the next token is a keyword, the previous call to
    -                // peekToken matched it as a TOK_NAME, and put it in the
    -                // lookahead buffer, so this call will match keywords as well.
    -                MUST_MATCH_TOKEN(TOK_NAME, JSMSG_NO_IMPORT_NAME);
    -                Node importName = newName(tokenStream.currentName());
    -                if (!importName)
    -                    return null();
    -
    -                if (tokenStream.getToken() == TOK_NAME &&
    -                    tokenStream.currentName() == context->names().as)
    -                {
    -                    if (tokenStream.getToken() != TOK_NAME) {
    -                        report(ParseError, false, null(), JSMSG_NO_BINDING_NAME);
    -                        return null();
    -                    }
    -                } else {
    -                    // Keywords cannot be bound to themselves, so an import name
    -                    // that is a keyword is a syntax error if it is not followed
    -                    // by the keyword 'as'.
    -                    if (IsKeyword(importName->name())) {
    -                        JSAutoByteString bytes;
    -                        if (!AtomToPrintableString(context, importName->name(), &bytes))
    -                            return null();
    -                        report(ParseError, false, null(), JSMSG_AS_AFTER_RESERVED_WORD, bytes.ptr());
    -                        return null();
    -                    }
    -                    tokenStream.ungetToken();
    -                }
    -                Node bindingName = newName(tokenStream.currentName());
    -                if (!bindingName)
    -                    return null();
    -
    -                Node importSpec = handler.newBinary(PNK_IMPORT_SPEC, importName, bindingName);
    -                if (!importSpec)
    -                    return null();
    -
    -                handler.addList(importSpecSet, importSpec);
    -            } while (tokenStream.matchToken(TOK_COMMA));
    -
    -            MUST_MATCH_TOKEN(TOK_RC, JSMSG_RC_AFTER_IMPORT_SPEC_LIST);
    -        }
    -
    -        if (tokenStream.getToken() != TOK_NAME ||
    -            tokenStream.currentName() != context->names().from)
    -        {
    -            report(ParseError, false, null(), JSMSG_FROM_AFTER_IMPORT_SPEC_SET);
    -            return null();
    -        }
    -
    -        MUST_MATCH_TOKEN(TOK_STRING, JSMSG_MODULE_SPEC_AFTER_FROM);
    -    } else {
    -        if (tt != TOK_STRING) {
    -            report(ParseError, false, null(), JSMSG_DECLARATION_AFTER_IMPORT);
    -            return null();
    -        }
    -
    -        // Handle the form |import 'a'| by leaving the list empty. This is
    -        // equivalent to |import {} from 'a'|.
    -        importSpecSet->pn_pos.end = importSpecSet->pn_pos.begin;
    -    }
    -
    -    Node moduleSpec = stringLiteral();
    -    if (!moduleSpec)
    -        return null();
    -
    -    if (!MatchOrInsertSemicolon(tokenStream))
    -        return null();
    -
    -    return handler.newImportDeclaration(importSpecSet, moduleSpec,
    -                                        TokenPos(begin, pos().end));
    -}
    -
    -template<>
    -SyntaxParseHandler::Node
    -Parser::importDeclaration()
    -{
    -    JS_ALWAYS_FALSE(abortIfSyntaxParser());
    -    return SyntaxParseHandler::NodeFailure;
    -}
    -
     template 
     typename ParseHandler::Node
     Parser::expressionStatement()
    @@ -5035,8 +4907,6 @@ Parser::statement(bool canHaveDirectives)
     
           case TOK_LET:
             return letStatement();
    -      case TOK_IMPORT:
    -        return importDeclaration();
           case TOK_SEMI:
             return handler.newEmptyStatement(pos());
           case TOK_IF:
    diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h
    index 119a6892d434..2de501307e5b 100644
    --- a/js/src/frontend/Parser.h
    +++ b/js/src/frontend/Parser.h
    @@ -512,7 +512,6 @@ class Parser : private AutoGCRooter, public StrictModeGetter
         Node debuggerStatement();
     
         Node letStatement();
    -    Node importDeclaration();
         Node expressionStatement();
         Node variables(ParseNodeKind kind, bool *psimple = nullptr,
                        StaticBlockObject *blockObj = nullptr,
    diff --git a/js/src/jit-test/lib/match.js b/js/src/jit-test/lib/match.js
    deleted file mode 100644
    index 87d84688ecd4..000000000000
    --- a/js/src/jit-test/lib/match.js
    +++ /dev/null
    @@ -1 +0,0 @@
    -loadRelativeToScript("../../tests/js1_8_5/extensions/shell.js");
    diff --git a/js/src/jit-test/tests/modules/import-declaration.js b/js/src/jit-test/tests/modules/import-declaration.js
    deleted file mode 100644
    index 54596359a92a..000000000000
    --- a/js/src/jit-test/tests/modules/import-declaration.js
    +++ /dev/null
    @@ -1,186 +0,0 @@
    -load(libdir + "match.js");
    -load(libdir + "asserts.js");
    -
    -var { Pattern, MatchError } = Match;
    -
    -program = (elts) => Pattern({
    -    type: "Program",
    -    body: elts
    -})
    -importDeclaration = (specifiers, source) => Pattern({
    -    type: "ImportDeclaration",
    -    specifiers: specifiers,
    -    source: source
    -});
    -importSpecifier = (id, name) => Pattern({
    -    type: "ImportSpecifier",
    -    id: id,
    -    name: name
    -});
    -ident = (name) => Pattern({
    -    type: "Identifier",
    -    name: name
    -})
    -lit = (val) => Pattern({
    -    type: "Literal",
    -    value: val
    -})
    -
    -program([
    -    importDeclaration(
    -        [
    -            importSpecifier(
    -                ident("default"),
    -                ident("a")
    -            )
    -        ],
    -        lit("b")
    -    )
    -]).assert(Reflect.parse("import a from 'b'"));
    -
    -program([
    -    importDeclaration(
    -        [],
    -        lit("a")
    -    )
    -]).assert(Reflect.parse("import {} from 'a'"));
    -
    -program([
    -    importDeclaration(
    -        [
    -            importSpecifier(
    -                ident("a"),
    -                ident("a")
    -            )
    -        ],
    -        lit("b")
    -    )
    -]).assert(Reflect.parse("import { a } from 'b'"));
    -
    -program([
    -    importDeclaration(
    -        [
    -            importSpecifier(
    -                ident("a"),
    -                ident("a")
    -            )
    -        ],
    -        lit("b")
    -    )
    -]).assert(Reflect.parse("import { a, } from 'b'"));
    -
    -program([
    -    importDeclaration(
    -        [
    -            importSpecifier(
    -                ident("a"),
    -                ident("b")
    -            )
    -        ],
    -        lit("c")
    -    )
    -]).assert(Reflect.parse("import { a as b } from 'c'"));
    -
    -program([
    -    importDeclaration(
    -        [
    -            importSpecifier(
    -                ident("as"),
    -                ident("as")
    -            )
    -        ],
    -        lit("a")
    -    )
    -]).assert(Reflect.parse("import { as as as } from 'a'"));
    -
    -program([
    -    importDeclaration(
    -        [
    -            importSpecifier(
    -                ident("true"),
    -                ident("a")
    -            )
    -        ],
    -        lit("b")
    -    )
    -]).assert(Reflect.parse("import { true as a } from 'b'"));
    -
    -program([
    -    importDeclaration(
    -        [
    -            importSpecifier(
    -                ident("a"),
    -                ident("a")
    -            ),
    -            importSpecifier(
    -                ident("b"),
    -                ident("b")
    -            ),
    -        ],
    -        lit("c")
    -    )
    -]).assert(Reflect.parse("import { a, b } from 'c'"));
    -
    -program([
    -    importDeclaration(
    -        [
    -            importSpecifier(
    -                ident("a"),
    -                ident("b")
    -            ),
    -            importSpecifier(
    -                ident("c"),
    -                ident("d")
    -            ),
    -        ],
    -        lit("e")
    -    )
    -]).assert(Reflect.parse("import { a as b, c as d } from 'e'"));
    -
    -program([
    -    importDeclaration(
    -        [],
    -        lit("a")
    -    )
    -]).assert(Reflect.parse("import 'a'"));
    -
    -var loc = Reflect.parse("import { a as b } from 'c'", {
    -    loc: true
    -}).body[0].loc;
    -
    -assertEq(loc.start.line, 1);
    -assertEq(loc.start.column, 0);
    -assertEq(loc.start.line, 1);
    -assertEq(loc.end.column, 26);
    -
    -assertThrowsInstanceOf(function () {
    -   Reflect.parse("function f() { import a from 'b' }");
    -}, SyntaxError);
    -
    -assertThrowsInstanceOf(function () {
    -   Reflect.parse("if (true) import a from 'b'");
    -}, SyntaxError);
    -
    -assertThrowsInstanceOf(function() {
    -    Reflect.parse("import {");
    -}, SyntaxError);
    -
    -assertThrowsInstanceOf(function() {
    -    Reflect.parse("import {}");
    -}, SyntaxError);
    -
    -assertThrowsInstanceOf(function() {
    -    Reflect.parse("import {} from");
    -}, SyntaxError);
    -
    -assertThrowsInstanceOf(function() {
    -    Reflect.parse("import {,} from 'a'");
    -}, SyntaxError);
    -
    -assertThrowsInstanceOf(function() {
    -    Reflect.parse("import { a as true } from 'b'");
    -}, SyntaxError);
    -
    -assertThrowsInstanceOf(function() {
    -    Reflect.parse("import { true } from 'a'");
    -}, SyntaxError);
    diff --git a/js/src/js.msg b/js/src/js.msg
    index 8bd4f8bd0556..15986cd569c7 100644
    --- a/js/src/js.msg
    +++ b/js/src/js.msg
    @@ -417,13 +417,3 @@ MSG_DEF(JSMSG_TYPEDOBJECT_NO_SUCH_PROP, 363, 1, JSEXN_TYPEERR, "No such property
     MSG_DEF(JSMSG_TYPEDOBJECT_HANDLE_BAD_ARGS, 364, 2, JSEXN_TYPEERR, "argument {0} invalid: expected {1}")
     MSG_DEF(JSMSG_TYPEDOBJECT_HANDLE_UNATTACHED, 365, 0, JSEXN_TYPEERR, "handle unattached")
     MSG_DEF(JSMSG_TYPEDOBJECT_HANDLE_BAD_TYPE, 366, 0, JSEXN_TYPEERR, "handle moved to destination of incorrect type")
    -
    -MSG_DEF(JSMSG_IMPORT_DECL_AT_TOP_LEVEL, 367, 0, JSEXN_SYNTAXERR, "import declarations may only appear at top level")
    -MSG_DEF(JSMSG_NO_IMPORT_NAME,         368, 0, JSEXN_SYNTAXERR, "missing import name")
    -MSG_DEF(JSMSG_AS_AFTER_RESERVED_WORD, 369, 1, JSEXN_SYNTAXERR, "missing keyword 'as' after reserved word '{0}'")
    -MSG_DEF(JSMSG_NO_BINDING_NAME,	      370, 0, JSEXN_SYNTAXERR, "missing binding name")
    -MSG_DEF(JSMSG_RC_AFTER_IMPORT_SPEC_LIST, 371, 0, JSEXN_SYNTAXERR, "missing '}' after module specifier list")
    -MSG_DEF(JSMSG_FROM_AFTER_IMPORT_SPEC_SET, 372, 0, JSEXN_SYNTAXERR, "missing keyword 'from' after import specifier set")
    -MSG_DEF(JSMSG_DECLARATION_AFTER_IMPORT, 373, 0, JSEXN_SYNTAXERR, "missing declaration after 'import' keyword")
    -MSG_DEF(JSMSG_MODULE_SPEC_AFTER_FROM,   374, 0, JSEXN_SYNTAXERR, "missing module specifier after 'from' keyword")
    -MSG_DEF(JSMSG_MODULES_NOT_IMPLEMENTED,  375, 0, JSEXN_SYNTAXERR, "modules are not implemented yet")
    diff --git a/js/src/jsast.tbl b/js/src/jsast.tbl
    index 4e2aa4daedb6..bcfb6907b634 100644
    --- a/js/src/jsast.tbl
    +++ b/js/src/jsast.tbl
    @@ -57,8 +57,6 @@ ASTDEF(AST_TRY_STMT,              "TryStatement",                   "tryStatemen
     ASTDEF(AST_THROW_STMT,            "ThrowStatement",                 "throwStatement")
     ASTDEF(AST_DEBUGGER_STMT,         "DebuggerStatement",              "debuggerStatement")
     ASTDEF(AST_LET_STMT,              "LetStatement",                   "letStatement")
    -ASTDEF(AST_IMPORT_DECL,           "ImportDeclaration",              "importDeclaration")
    -ASTDEF(AST_IMPORT_SPEC,           "ImportSpecifier",                "importSpecifier")
     
     ASTDEF(AST_CASE,                  "SwitchCase",                     "switchCase")
     ASTDEF(AST_CATCH,                 "CatchClause",                    "catchClause")
    diff --git a/js/src/jsreflect.cpp b/js/src/jsreflect.cpp
    index 7cf7f2fd0a79..34baac115ca4 100644
    --- a/js/src/jsreflect.cpp
    +++ b/js/src/jsreflect.cpp
    @@ -562,10 +562,6 @@ class NodeBuilder
     
         bool letStatement(NodeVector &head, HandleValue stmt, TokenPos *pos, MutableHandleValue dst);
     
    -    bool importDeclaration(NodeVector &elts, HandleValue moduleSpec, TokenPos *pos, MutableHandleValue dst);
    -
    -    bool importSpecifier(HandleValue importName, HandleValue bindingName, TokenPos *pos, MutableHandleValue dst);
    -
         /*
          * expressions
          */
    @@ -1357,38 +1353,6 @@ NodeBuilder::letStatement(NodeVector &head, HandleValue stmt, TokenPos *pos, Mut
                        dst);
     }
     
    -bool
    -NodeBuilder::importDeclaration(NodeVector &elts, HandleValue moduleSpec, TokenPos *pos,
    -                               MutableHandleValue dst)
    -{
    -    RootedValue array(cx);
    -    if (!newArray(elts, &array))
    -        return false;
    -
    -    RootedValue cb(cx, callbacks[AST_IMPORT_DECL]);
    -    if (!cb.isNull())
    -        return callback(cb, array, moduleSpec, pos, dst);
    -
    -    return newNode(AST_IMPORT_DECL, pos,
    -                   "specifiers", array,
    -                   "source", moduleSpec,
    -                   dst);
    -}
    -
    -bool
    -NodeBuilder::importSpecifier(HandleValue importName, HandleValue bindingName, TokenPos *pos,
    -                             MutableHandleValue dst)
    -{
    -    RootedValue cb(cx, callbacks[AST_IMPORT_SPEC]);
    -    if (!cb.isNull())
    -        return callback(cb, importName, bindingName, pos, dst);
    -
    -    return newNode(AST_IMPORT_SPEC, pos,
    -                   "id", importName,
    -                   "name", bindingName,
    -                   dst);
    -}
    -
     bool
     NodeBuilder::variableDeclaration(NodeVector &elts, VarDeclKind kind, TokenPos *pos,
                                      MutableHandleValue dst)
    @@ -1556,8 +1520,6 @@ class ASTSerializer
         bool variableDeclaration(ParseNode *pn, bool let, MutableHandleValue dst);
         bool variableDeclarator(ParseNode *pn, VarDeclKind *pkind, MutableHandleValue dst);
         bool let(ParseNode *pn, bool expr, MutableHandleValue dst);
    -    bool importDeclaration(ParseNode *pn, MutableHandleValue dst);
    -    bool importSpecifier(ParseNode *pn, MutableHandleValue dst);
     
         bool optStatement(ParseNode *pn, MutableHandleValue dst) {
             if (!pn) {
    @@ -1921,41 +1883,6 @@ ASTSerializer::let(ParseNode *pn, bool expr, MutableHandleValue dst)
                  builder.letStatement(dtors, v, &pn->pn_pos, dst);
     }
     
    -bool
    -ASTSerializer::importDeclaration(ParseNode *pn, MutableHandleValue dst)
    -{
    -    JS_ASSERT(pn->isKind(PNK_IMPORT));
    -    JS_ASSERT(pn->pn_left->isKind(PNK_IMPORT_SPEC_LIST));
    -    JS_ASSERT(pn->pn_right->isKind(PNK_STRING));
    -
    -    NodeVector elts(cx);
    -    if (!elts.reserve(pn->pn_count))
    -        return false;
    -
    -    for (ParseNode *next = pn->pn_left->pn_head; next; next = next->pn_next) {
    -        RootedValue elt(cx);
    -        if (!importSpecifier(next, &elt))
    -            return false;
    -        elts.infallibleAppend(elt);
    -    }
    -
    -    RootedValue moduleSpec(cx);
    -    return literal(pn->pn_right, &moduleSpec) &&
    -           builder.importDeclaration(elts, moduleSpec, &pn->pn_pos, dst);
    -}
    -
    -bool
    -ASTSerializer::importSpecifier(ParseNode *pn, MutableHandleValue dst)
    -{
    -    JS_ASSERT(pn->isKind(PNK_IMPORT_SPEC));
    -
    -    RootedValue importName(cx);
    -    RootedValue bindingName(cx);
    -    return identifier(pn->pn_left, &importName) &&
    -           identifier(pn->pn_right, &bindingName) &&
    -           builder.importSpecifier(importName, bindingName, &pn->pn_pos, dst);
    -}
    -
     bool
     ASTSerializer::switchCase(ParseNode *pn, MutableHandleValue dst)
     {
    @@ -2111,9 +2038,6 @@ ASTSerializer::statement(ParseNode *pn, MutableHandleValue dst)
                    ? let(pn, false, dst)
                    : declaration(pn, dst);
     
    -      case PNK_IMPORT:
    -        return importDeclaration(pn, dst);
    -
           case PNK_NAME:
             LOCAL_ASSERT(pn->isUsed());
             return statement(pn->pn_lexdef, dst);
    diff --git a/js/src/vm/CommonPropertyNames.h b/js/src/vm/CommonPropertyNames.h
    index 6406291bfa6b..f4f3e03ba8bd 100644
    --- a/js/src/vm/CommonPropertyNames.h
    +++ b/js/src/vm/CommonPropertyNames.h
    @@ -15,7 +15,6 @@
         macro(anonymous, anonymous, "anonymous") \
         macro(apply, apply, "apply") \
         macro(arguments, arguments, "arguments") \
    -    macro(as, as, "as") \
         macro(ArrayType, ArrayType, "ArrayType") \
         macro(buffer, buffer, "buffer") \
         macro(builder, builder, "builder") \
    @@ -44,7 +43,6 @@
         macro(DateTimeFormatFormatGet, DateTimeFormatFormatGet, "Intl_DateTimeFormat_format_get") \
         macro(decodeURI, decodeURI, "decodeURI") \
         macro(decodeURIComponent, decodeURIComponent, "decodeURIComponent") \
    -    macro(default_, default_, "default") \
         macro(defineProperty, defineProperty, "defineProperty") \
         macro(defineGetter, defineGetter, "__defineGetter__") \
         macro(defineSetter, defineSetter, "__defineSetter__") \
    @@ -70,7 +68,6 @@
         macro(float32, float32, "float32") \
         macro(float64, float64, "float64") \
         macro(format, format, "format") \
    -    macro(from, from, "from") \
         macro(get, get, "get") \
         macro(getInternals, getInternals, "getInternals") \
         macro(getOwnPropertyDescriptor, getOwnPropertyDescriptor, "getOwnPropertyDescriptor") \
    diff --git a/js/src/vm/Keywords.h b/js/src/vm/Keywords.h
    index a6c867e79214..f1d7211b2029 100644
    --- a/js/src/vm/Keywords.h
    +++ b/js/src/vm/Keywords.h
    @@ -41,12 +41,12 @@
         macro(void, void_, TOK_VOID, JSVERSION_DEFAULT) \
         macro(while, while_, TOK_WHILE, JSVERSION_DEFAULT) \
         macro(with, with, TOK_WITH, JSVERSION_DEFAULT) \
    -    macro(import, import, TOK_IMPORT, JSVERSION_DEFAULT) \
         /* Reserved keywords. */ \
         macro(class, class_, TOK_RESERVED, JSVERSION_DEFAULT) \
         macro(enum, enum_, TOK_RESERVED, JSVERSION_DEFAULT) \
         macro(export, export, TOK_RESERVED, JSVERSION_DEFAULT) \
         macro(extends, extends, TOK_RESERVED, JSVERSION_DEFAULT) \
    +    macro(import, import, TOK_RESERVED, JSVERSION_DEFAULT) \
         macro(super, super, TOK_RESERVED, JSVERSION_DEFAULT) \
         /* Future reserved keywords, but only in strict mode. */ \
         macro(implements, implements, TOK_STRICT_RESERVED, JSVERSION_DEFAULT) \
    
    From c70c64f80b55252b67417778197637342dc2892a Mon Sep 17 00:00:00 2001
    From: Peter Van der Beken 
    Date: Wed, 6 Nov 2013 10:21:36 +0100
    Subject: [PATCH 56/82] Bug 935283, Keep document as a data property on window
     for now. r=bz
    
    --HG--
    extra : rebase_source : cca1ee4bf96315526e953235a76522cb71f44bfa
    ---
     content/base/public/nsIDocument.h |  3 ++
     content/base/src/nsDocument.cpp   | 51 +++++++++++++++++++++++++++++++
     2 files changed, 54 insertions(+)
    
    diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h
    index dfa6afdd1e12..f0e579723d73 100644
    --- a/content/base/public/nsIDocument.h
    +++ b/content/base/public/nsIDocument.h
    @@ -2171,6 +2171,9 @@ public:
     
       virtual nsHTMLDocument* AsHTMLDocument() { return nullptr; }
     
    +  virtual JSObject* WrapObject(JSContext *aCx,
    +                               JS::Handle aScope) MOZ_OVERRIDE;
    +
     private:
       uint64_t mWarnedAbout;
       SelectorCache mSelectorCache;
    diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp
    index d4e7f1e0d9dc..6a4d68ff9369 100644
    --- a/content/base/src/nsDocument.cpp
    +++ b/content/base/src/nsDocument.cpp
    @@ -11329,6 +11329,57 @@ nsDocument::Evaluate(const nsAString& aExpression, nsIDOMNode* aContextNode,
                                         aInResult, aResult);
     } 
     
    +// This is just a hack around the fact that window.document is not
    +// [Unforgeable] yet.
    +JSObject*
    +nsIDocument::WrapObject(JSContext *aCx, JS::Handle aScope)
    +{
    +  MOZ_ASSERT(IsDOMBinding());
    +
    +  JS::Rooted obj(aCx, nsINode::WrapObject(aCx, aScope));
    +  if (!obj) {
    +    return nullptr;
    +  }
    +
    +  nsCOMPtr win = do_QueryInterface(GetInnerWindow());
    +  if (!win) {
    +    // No window, nothing else to do here
    +    return obj;
    +  }
    +
    +  if (this != win->GetExtantDoc()) {
    +    // We're not the current document; we're also done here
    +    return obj;
    +  }
    +
    +  JSAutoCompartment ac(aCx, obj);
    +
    +  JS::Rooted winVal(aCx);
    +  nsCOMPtr holder;
    +  nsresult rv = nsContentUtils::WrapNative(aCx, obj, win,
    +                                           &NS_GET_IID(nsIDOMWindow),
    +                                           &winVal,
    +                                           getter_AddRefs(holder),
    +                                           false);
    +  if (NS_FAILED(rv)) {
    +    Throw(aCx, rv);
    +    return nullptr;
    +  }
    +
    +  NS_NAMED_LITERAL_STRING(doc_str, "document");
    +
    +  if (!JS_DefineUCProperty(aCx, JSVAL_TO_OBJECT(winVal),
    +                           reinterpret_cast
    +                                           (doc_str.get()),
    +                           doc_str.Length(), JS::ObjectValue(*obj),
    +                           JS_PropertyStub, JS_StrictPropertyStub,
    +                           JSPROP_READONLY | JSPROP_ENUMERATE)) {
    +    return nullptr;
    +  }
    +
    +  return obj;
    +}
    +
     XPathEvaluator*
     nsIDocument::XPathEvaluator()
     {
    
    From 11a4f6427919ebd58097e1f8c90caa9a884d020a Mon Sep 17 00:00:00 2001
    From: Benjamin Bouvier 
    Date: Wed, 6 Nov 2013 19:47:29 +0100
    Subject: [PATCH 57/82] Bug 926431 - Make clone unsafe for fuzzing in the JS
     shell. r=luke
    
    ---
     js/src/shell/js.cpp | 8 ++++----
     1 file changed, 4 insertions(+), 4 deletions(-)
    
    diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp
    index bf6aadf1600f..5a6a07e29b88 100644
    --- a/js/src/shell/js.cpp
    +++ b/js/src/shell/js.cpp
    @@ -4129,10 +4129,6 @@ static const JSFunctionSpecWithHelp shell_functions[] = {
     "intern(str)",
     "  Internalize str in the atom table."),
     
    -    JS_FN_HELP("clone", Clone, 1, 0,
    -"clone(fun[, scope])",
    -"  Clone function object."),
    -
         JS_FN_HELP("getpda", GetPDA, 1, 0,
     "getpda(obj)",
     "  Get the property descriptors for obj."),
    @@ -4277,6 +4273,10 @@ static const JSFunctionSpecWithHelp shell_functions[] = {
     };
     
     static const JSFunctionSpecWithHelp fuzzing_unsafe_functions[] = {
    +    JS_FN_HELP("clone", Clone, 1, 0,
    +"clone(fun[, scope])",
    +"  Clone function object."),
    +
         JS_FN_HELP("getSelfHostedValue", GetSelfHostedValue, 1, 0,
     "getSelfHostedValue()",
     "  Get a self-hosted value by its name. Note that these values don't get \n"
    
    From a4e5ca9e84bab98f1827317df77d53a6938890ad Mon Sep 17 00:00:00 2001
    From: "Gordon P. Hemsley" 
    Date: Wed, 6 Nov 2013 16:19:53 -0500
    Subject: [PATCH 58/82] Bug 934165 - Increase clang version to 3.3 for
     MacPorts. r=gps
    
    ---
     python/mozboot/mozboot/osx.py | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/python/mozboot/mozboot/osx.py b/python/mozboot/mozboot/osx.py
    index bfe2965a94ea..94182750a03d 100644
    --- a/python/mozboot/mozboot/osx.py
    +++ b/python/mozboot/mozboot/osx.py
    @@ -27,7 +27,7 @@ MACPORTS_URL = {'8': 'https://distfiles.macports.org/MacPorts/MacPorts-2.1.3-10.
                     '7': 'https://distfiles.macports.org/MacPorts/MacPorts-2.1.3-10.7-Lion.pkg',
                     '6': 'https://distfiles.macports.org/MacPorts/MacPorts-2.1.3-10.6-SnowLeopard.pkg',}
     
    -MACPORTS_CLANG_PACKAGE = 'clang-3.2'
    +MACPORTS_CLANG_PACKAGE = 'clang-3.3'
     
     RE_CLANG_VERSION = re.compile('Apple (?:clang|LLVM) version (\d+\.\d+)')
     
    
    From 43fe8b20564624b93b4dba4dfec1ea2af0248fe9 Mon Sep 17 00:00:00 2001
    From: Jonathan Griffin 
    Date: Wed, 6 Nov 2013 13:43:16 -0800
    Subject: [PATCH 59/82] Bug 934555 - Report filenames for errors in JS files,
     r=mdas
    
    ---
     .../marionette/client/marionette/runtests.py  | 39 ++++++++++++++++---
     1 file changed, 34 insertions(+), 5 deletions(-)
    
    diff --git a/testing/marionette/client/marionette/runtests.py b/testing/marionette/client/marionette/runtests.py
    index a982933b13a2..0fe9353092b4 100644
    --- a/testing/marionette/client/marionette/runtests.py
    +++ b/testing/marionette/client/marionette/runtests.py
    @@ -19,12 +19,26 @@ from manifestparser import TestManifest
     from mozhttpd import MozHttpd
     
     from marionette import Marionette
    -from moztest.results import TestResultCollection
    +from moztest.results import TestResultCollection, TestResult, relevant_line
     from marionette_test import MarionetteJSTestCase, MarionetteTestCase
     
     
    +class MarionetteTest(TestResult):
    +
    +    @property
    +    def test_name(self):
    +        if self.test_class is not None:
    +            return '%s.py %s.%s' % (self.test_class.split('.')[0],
    +                                    self.test_class,
    +                                    self.name)
    +        else:
    +            return self.name
    +
    +
     class MarionetteTestResult(unittest._TextTestResult, TestResultCollection):
     
    +    resultClass = MarionetteTest
    +
         def __init__(self, *args, **kwargs):
             self.marionette = kwargs.pop('marionette')
             TestResultCollection.__init__(self, 'MarionetteTest')
    @@ -83,10 +97,25 @@ class MarionetteTestResult(unittest._TextTestResult, TestResultCollection):
             else:
                 return 0
     
    -    def add_test_result(self, test, *args, **kwargs):
    -        self.add_result(test, *args, **kwargs)
    -        self[-1].time_start = test.start_time
    -        self[-1].time_end = time.time() if test.start_time else 0
    +    def add_test_result(self, test, result_expected='PASS',
    +                        result_actual='PASS', output='', context=None, **kwargs):
    +        def get_class(test):
    +            return test.__class__.__module__ + '.' + test.__class__.__name__
    +
    +        name = str(test).split()[0]
    +        test_class = get_class(test)
    +        if hasattr(test, 'jsFile'):
    +            name = os.path.basename(test.jsFile)
    +            test_class = None
    +
    +        t = self.resultClass(name=name, test_class=test_class,
    +                       time_start=test.start_time, result_expected=result_expected,
    +                       context=context, **kwargs)
    +        t.finish(result_actual,
    +                 time_end=time.time() if test.start_time else 0,
    +                 reason=relevant_line(output),
    +                 output=output)
    +        self.append(t)
     
         def addError(self, test, err):
             self.add_test_result(test, output=self._exc_info_to_string(err, test), result_actual='ERROR')
    
    From f5eea02b5b756afbbc6ed1c6dbbbd69fe05661bc Mon Sep 17 00:00:00 2001
    From: Ryan VanderMeulen 
    Date: Wed, 6 Nov 2013 17:40:46 -0500
    Subject: [PATCH 60/82] Backed out changeset faee77ddc112 (bug 935283) for
     mochitest-4 failures.
    
    ---
     content/base/public/nsIDocument.h |  3 --
     content/base/src/nsDocument.cpp   | 51 -------------------------------
     2 files changed, 54 deletions(-)
    
    diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h
    index f0e579723d73..dfa6afdd1e12 100644
    --- a/content/base/public/nsIDocument.h
    +++ b/content/base/public/nsIDocument.h
    @@ -2171,9 +2171,6 @@ public:
     
       virtual nsHTMLDocument* AsHTMLDocument() { return nullptr; }
     
    -  virtual JSObject* WrapObject(JSContext *aCx,
    -                               JS::Handle aScope) MOZ_OVERRIDE;
    -
     private:
       uint64_t mWarnedAbout;
       SelectorCache mSelectorCache;
    diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp
    index 6a4d68ff9369..d4e7f1e0d9dc 100644
    --- a/content/base/src/nsDocument.cpp
    +++ b/content/base/src/nsDocument.cpp
    @@ -11329,57 +11329,6 @@ nsDocument::Evaluate(const nsAString& aExpression, nsIDOMNode* aContextNode,
                                         aInResult, aResult);
     } 
     
    -// This is just a hack around the fact that window.document is not
    -// [Unforgeable] yet.
    -JSObject*
    -nsIDocument::WrapObject(JSContext *aCx, JS::Handle aScope)
    -{
    -  MOZ_ASSERT(IsDOMBinding());
    -
    -  JS::Rooted obj(aCx, nsINode::WrapObject(aCx, aScope));
    -  if (!obj) {
    -    return nullptr;
    -  }
    -
    -  nsCOMPtr win = do_QueryInterface(GetInnerWindow());
    -  if (!win) {
    -    // No window, nothing else to do here
    -    return obj;
    -  }
    -
    -  if (this != win->GetExtantDoc()) {
    -    // We're not the current document; we're also done here
    -    return obj;
    -  }
    -
    -  JSAutoCompartment ac(aCx, obj);
    -
    -  JS::Rooted winVal(aCx);
    -  nsCOMPtr holder;
    -  nsresult rv = nsContentUtils::WrapNative(aCx, obj, win,
    -                                           &NS_GET_IID(nsIDOMWindow),
    -                                           &winVal,
    -                                           getter_AddRefs(holder),
    -                                           false);
    -  if (NS_FAILED(rv)) {
    -    Throw(aCx, rv);
    -    return nullptr;
    -  }
    -
    -  NS_NAMED_LITERAL_STRING(doc_str, "document");
    -
    -  if (!JS_DefineUCProperty(aCx, JSVAL_TO_OBJECT(winVal),
    -                           reinterpret_cast
    -                                           (doc_str.get()),
    -                           doc_str.Length(), JS::ObjectValue(*obj),
    -                           JS_PropertyStub, JS_StrictPropertyStub,
    -                           JSPROP_READONLY | JSPROP_ENUMERATE)) {
    -    return nullptr;
    -  }
    -
    -  return obj;
    -}
    -
     XPathEvaluator*
     nsIDocument::XPathEvaluator()
     {
    
    From a30d2750e186e4347ac208efb51d25d5a13e0881 Mon Sep 17 00:00:00 2001
    From: Eddy Bruel 
    Date: Wed, 6 Nov 2013 20:04:12 +0100
    Subject: [PATCH 61/82] Bug 927116 - Implement parser support for import
     declarations; r=jorendorff
    
    ---
     js/src/frontend/BytecodeEmitter.cpp |   5 ++
     js/src/frontend/FullParseHandler.h  |  10 +++
     js/src/frontend/ParseNode.h         |   3 +
     js/src/frontend/Parser.cpp          | 130 ++++++++++++++++++++++++++++
     js/src/frontend/Parser.h            |   1 +
     js/src/js.msg                       |  10 +++
     js/src/vm/CommonPropertyNames.h     |   3 +
     js/src/vm/Keywords.h                |   2 +-
     8 files changed, 163 insertions(+), 1 deletion(-)
    
    diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
    index 4de784ea04be..a078a94b681a 100644
    --- a/js/src/frontend/BytecodeEmitter.cpp
    +++ b/js/src/frontend/BytecodeEmitter.cpp
    @@ -6447,6 +6447,11 @@ frontend::EmitTree(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
                  : EmitVariables(cx, bce, pn, InitializeVars);
             break;
     
    +      case PNK_IMPORT:
    +       // TODO: Implement emitter support for modules
    +       bce->reportError(nullptr, JSMSG_MODULES_NOT_IMPLEMENTED);
    +       return false;
    +
           case PNK_ARRAYPUSH: {
             int slot;
     
    diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h
    index 7bde5f46eca9..b638d76daeff 100644
    --- a/js/src/frontend/FullParseHandler.h
    +++ b/js/src/frontend/FullParseHandler.h
    @@ -295,6 +295,16 @@ class FullParseHandler
             return new_(PNK_SEMI, JSOP_NOP, pos, (ParseNode *) nullptr);
         }
     
    +    ParseNode *newImportDeclaration(ParseNode *importSpecSet,
    +                                    ParseNode *moduleSpec, const TokenPos &pos)
    +    {
    +        ParseNode *pn = new_(PNK_IMPORT, JSOP_NOP, pos,
    +                                         importSpecSet, moduleSpec);
    +        if (!pn)
    +            return null();
    +        return pn;
    +    }
    +
         ParseNode *newExprStatement(ParseNode *expr, uint32_t end) {
             JS_ASSERT(expr->pn_pos.end <= end);
             return new_(PNK_SEMI, JSOP_NOP, TokenPos(expr->pn_pos.begin, end), expr);
    diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h
    index bb981cb8cbaf..4b8cb1bf7943 100644
    --- a/js/src/frontend/ParseNode.h
    +++ b/js/src/frontend/ParseNode.h
    @@ -128,6 +128,9 @@ class UpvarCookie
         F(ARRAYPUSH) \
         F(LEXICALSCOPE) \
         F(LET) \
    +    F(IMPORT) \
    +    F(IMPORT_SPEC_LIST) \
    +    F(IMPORT_SPEC) \
         F(SEQ) \
         F(FORIN) \
         F(FOROF) \
    diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
    index 0cb25dbac7e3..d191d17b8ffe 100644
    --- a/js/src/frontend/Parser.cpp
    +++ b/js/src/frontend/Parser.cpp
    @@ -3628,6 +3628,134 @@ Parser::letStatement()
         return SyntaxParseHandler::NodeFailure;
     }
     
    +template
    +typename ParseHandler::Node
    +Parser::importDeclaration()
    +{
    +    JS_ASSERT(tokenStream.currentToken().type == TOK_IMPORT);
    +
    +    if (pc->sc->isFunctionBox() || !pc->atBodyLevel()) {
    +        report(ParseError, false, null(), JSMSG_IMPORT_DECL_AT_TOP_LEVEL);
    +        return null();
    +    }
    +
    +    uint32_t begin = pos().begin;
    +    TokenKind tt = tokenStream.getToken();
    +
    +    Node importSpecSet = handler.newList(PNK_IMPORT_SPEC_LIST);
    +    if (!importSpecSet)
    +        return null();
    +
    +    if (tt == TOK_NAME || tt == TOK_LC) {
    +        if (tt == TOK_NAME) {
    +            // Handle the form |import a from 'b'|, by adding a single import
    +            // specifier to the list, with 'default' as the import name and
    +            // 'a' as the binding name. This is equivalent to
    +            // |import { default as a } from 'b'|.
    +            Node importName = newName(context->names().default_);
    +            if (!importName)
    +                return null();
    +
    +            Node bindingName = newName(tokenStream.currentName());
    +            if (!bindingName)
    +                return null();
    +
    +            Node importSpec = handler.newBinary(PNK_IMPORT_SPEC, importName, bindingName);
    +            if (!importSpec)
    +                return null();
    +
    +            handler.addList(importSpecSet, importSpec);
    +        } else {
    +            do {
    +                // Handle the forms |import {} from 'a'| and
    +                // |import { ..., } from 'a'| (where ... is non empty), by
    +                // escaping the loop early if the next token is }.
    +                tt = tokenStream.peekToken(TokenStream::KeywordIsName);
    +                if (tt == TOK_ERROR)
    +                    return null();
    +                if (tt == TOK_RC)
    +                    break;
    +
    +                // If the next token is a keyword, the previous call to
    +                // peekToken matched it as a TOK_NAME, and put it in the
    +                // lookahead buffer, so this call will match keywords as well.
    +                MUST_MATCH_TOKEN(TOK_NAME, JSMSG_NO_IMPORT_NAME);
    +                Node importName = newName(tokenStream.currentName());
    +                if (!importName)
    +                    return null();
    +
    +                if (tokenStream.getToken() == TOK_NAME &&
    +                    tokenStream.currentName() == context->names().as)
    +                {
    +                    if (tokenStream.getToken() != TOK_NAME) {
    +                        report(ParseError, false, null(), JSMSG_NO_BINDING_NAME);
    +                        return null();
    +                    }
    +                } else {
    +                    // Keywords cannot be bound to themselves, so an import name
    +                    // that is a keyword is a syntax error if it is not followed
    +                    // by the keyword 'as'.
    +                    if (IsKeyword(importName->name())) {
    +                        JSAutoByteString bytes;
    +                        if (!AtomToPrintableString(context, importName->name(), &bytes))
    +                            return null();
    +                        report(ParseError, false, null(), JSMSG_AS_AFTER_RESERVED_WORD, bytes.ptr());
    +                        return null();
    +                    }
    +                    tokenStream.ungetToken();
    +                }
    +                Node bindingName = newName(tokenStream.currentName());
    +                if (!bindingName)
    +                    return null();
    +
    +                Node importSpec = handler.newBinary(PNK_IMPORT_SPEC, importName, bindingName);
    +                if (!importSpec)
    +                    return null();
    +
    +                handler.addList(importSpecSet, importSpec);
    +            } while (tokenStream.matchToken(TOK_COMMA));
    +
    +            MUST_MATCH_TOKEN(TOK_RC, JSMSG_RC_AFTER_IMPORT_SPEC_LIST);
    +        }
    +
    +        if (tokenStream.getToken() != TOK_NAME ||
    +            tokenStream.currentName() != context->names().from)
    +        {
    +            report(ParseError, false, null(), JSMSG_FROM_AFTER_IMPORT_SPEC_SET);
    +            return null();
    +        }
    +
    +        MUST_MATCH_TOKEN(TOK_STRING, JSMSG_MODULE_SPEC_AFTER_FROM);
    +    } else {
    +        if (tt != TOK_STRING) {
    +            report(ParseError, false, null(), JSMSG_DECLARATION_AFTER_IMPORT);
    +            return null();
    +        }
    +
    +        // Handle the form |import 'a'| by leaving the list empty. This is
    +        // equivalent to |import {} from 'a'|.
    +        importSpecSet->pn_pos.end = importSpecSet->pn_pos.begin;
    +    }
    +
    +    Node moduleSpec = stringLiteral();
    +    if (!moduleSpec)
    +        return null();
    +
    +    if (!MatchOrInsertSemicolon(tokenStream))
    +        return null();
    +
    +    return handler.newImportDeclaration(importSpecSet, moduleSpec,
    +                                        TokenPos(begin, pos().end));
    +}
    +
    +template<>
    +SyntaxParseHandler::Node
    +Parser::importDeclaration()
    +{
    +    JS_ALWAYS_FALSE(abortIfSyntaxParser());
    +    return SyntaxParseHandler::NodeFailure;
    +}
    +
     template 
     typename ParseHandler::Node
     Parser::expressionStatement()
    @@ -4907,6 +5035,8 @@ Parser::statement(bool canHaveDirectives)
     
           case TOK_LET:
             return letStatement();
    +      case TOK_IMPORT:
    +        return importDeclaration();
           case TOK_SEMI:
             return handler.newEmptyStatement(pos());
           case TOK_IF:
    diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h
    index 2de501307e5b..119a6892d434 100644
    --- a/js/src/frontend/Parser.h
    +++ b/js/src/frontend/Parser.h
    @@ -512,6 +512,7 @@ class Parser : private AutoGCRooter, public StrictModeGetter
         Node debuggerStatement();
     
         Node letStatement();
    +    Node importDeclaration();
         Node expressionStatement();
         Node variables(ParseNodeKind kind, bool *psimple = nullptr,
                        StaticBlockObject *blockObj = nullptr,
    diff --git a/js/src/js.msg b/js/src/js.msg
    index 15986cd569c7..8bd4f8bd0556 100644
    --- a/js/src/js.msg
    +++ b/js/src/js.msg
    @@ -417,3 +417,13 @@ MSG_DEF(JSMSG_TYPEDOBJECT_NO_SUCH_PROP, 363, 1, JSEXN_TYPEERR, "No such property
     MSG_DEF(JSMSG_TYPEDOBJECT_HANDLE_BAD_ARGS, 364, 2, JSEXN_TYPEERR, "argument {0} invalid: expected {1}")
     MSG_DEF(JSMSG_TYPEDOBJECT_HANDLE_UNATTACHED, 365, 0, JSEXN_TYPEERR, "handle unattached")
     MSG_DEF(JSMSG_TYPEDOBJECT_HANDLE_BAD_TYPE, 366, 0, JSEXN_TYPEERR, "handle moved to destination of incorrect type")
    +
    +MSG_DEF(JSMSG_IMPORT_DECL_AT_TOP_LEVEL, 367, 0, JSEXN_SYNTAXERR, "import declarations may only appear at top level")
    +MSG_DEF(JSMSG_NO_IMPORT_NAME,         368, 0, JSEXN_SYNTAXERR, "missing import name")
    +MSG_DEF(JSMSG_AS_AFTER_RESERVED_WORD, 369, 1, JSEXN_SYNTAXERR, "missing keyword 'as' after reserved word '{0}'")
    +MSG_DEF(JSMSG_NO_BINDING_NAME,	      370, 0, JSEXN_SYNTAXERR, "missing binding name")
    +MSG_DEF(JSMSG_RC_AFTER_IMPORT_SPEC_LIST, 371, 0, JSEXN_SYNTAXERR, "missing '}' after module specifier list")
    +MSG_DEF(JSMSG_FROM_AFTER_IMPORT_SPEC_SET, 372, 0, JSEXN_SYNTAXERR, "missing keyword 'from' after import specifier set")
    +MSG_DEF(JSMSG_DECLARATION_AFTER_IMPORT, 373, 0, JSEXN_SYNTAXERR, "missing declaration after 'import' keyword")
    +MSG_DEF(JSMSG_MODULE_SPEC_AFTER_FROM,   374, 0, JSEXN_SYNTAXERR, "missing module specifier after 'from' keyword")
    +MSG_DEF(JSMSG_MODULES_NOT_IMPLEMENTED,  375, 0, JSEXN_SYNTAXERR, "modules are not implemented yet")
    diff --git a/js/src/vm/CommonPropertyNames.h b/js/src/vm/CommonPropertyNames.h
    index f4f3e03ba8bd..6406291bfa6b 100644
    --- a/js/src/vm/CommonPropertyNames.h
    +++ b/js/src/vm/CommonPropertyNames.h
    @@ -15,6 +15,7 @@
         macro(anonymous, anonymous, "anonymous") \
         macro(apply, apply, "apply") \
         macro(arguments, arguments, "arguments") \
    +    macro(as, as, "as") \
         macro(ArrayType, ArrayType, "ArrayType") \
         macro(buffer, buffer, "buffer") \
         macro(builder, builder, "builder") \
    @@ -43,6 +44,7 @@
         macro(DateTimeFormatFormatGet, DateTimeFormatFormatGet, "Intl_DateTimeFormat_format_get") \
         macro(decodeURI, decodeURI, "decodeURI") \
         macro(decodeURIComponent, decodeURIComponent, "decodeURIComponent") \
    +    macro(default_, default_, "default") \
         macro(defineProperty, defineProperty, "defineProperty") \
         macro(defineGetter, defineGetter, "__defineGetter__") \
         macro(defineSetter, defineSetter, "__defineSetter__") \
    @@ -68,6 +70,7 @@
         macro(float32, float32, "float32") \
         macro(float64, float64, "float64") \
         macro(format, format, "format") \
    +    macro(from, from, "from") \
         macro(get, get, "get") \
         macro(getInternals, getInternals, "getInternals") \
         macro(getOwnPropertyDescriptor, getOwnPropertyDescriptor, "getOwnPropertyDescriptor") \
    diff --git a/js/src/vm/Keywords.h b/js/src/vm/Keywords.h
    index f1d7211b2029..a6c867e79214 100644
    --- a/js/src/vm/Keywords.h
    +++ b/js/src/vm/Keywords.h
    @@ -41,12 +41,12 @@
         macro(void, void_, TOK_VOID, JSVERSION_DEFAULT) \
         macro(while, while_, TOK_WHILE, JSVERSION_DEFAULT) \
         macro(with, with, TOK_WITH, JSVERSION_DEFAULT) \
    +    macro(import, import, TOK_IMPORT, JSVERSION_DEFAULT) \
         /* Reserved keywords. */ \
         macro(class, class_, TOK_RESERVED, JSVERSION_DEFAULT) \
         macro(enum, enum_, TOK_RESERVED, JSVERSION_DEFAULT) \
         macro(export, export, TOK_RESERVED, JSVERSION_DEFAULT) \
         macro(extends, extends, TOK_RESERVED, JSVERSION_DEFAULT) \
    -    macro(import, import, TOK_RESERVED, JSVERSION_DEFAULT) \
         macro(super, super, TOK_RESERVED, JSVERSION_DEFAULT) \
         /* Future reserved keywords, but only in strict mode. */ \
         macro(implements, implements, TOK_STRICT_RESERVED, JSVERSION_DEFAULT) \
    
    From 8529d263047d0f839811b82e11e57831b34e0c38 Mon Sep 17 00:00:00 2001
    From: Eddy Bruel 
    Date: Wed, 6 Nov 2013 20:05:23 +0100
    Subject: [PATCH 62/82] Bug 927116 - Test reflect support for import
     declarations; r=jorendorff
    
    ---
     js/src/jit-test/lib/match.js                  |   1 +
     .../tests/modules/import-declaration.js       | 186 ++++++++++++++++++
     2 files changed, 187 insertions(+)
     create mode 100644 js/src/jit-test/lib/match.js
     create mode 100644 js/src/jit-test/tests/modules/import-declaration.js
    
    diff --git a/js/src/jit-test/lib/match.js b/js/src/jit-test/lib/match.js
    new file mode 100644
    index 000000000000..87d84688ecd4
    --- /dev/null
    +++ b/js/src/jit-test/lib/match.js
    @@ -0,0 +1 @@
    +loadRelativeToScript("../../tests/js1_8_5/extensions/shell.js");
    diff --git a/js/src/jit-test/tests/modules/import-declaration.js b/js/src/jit-test/tests/modules/import-declaration.js
    new file mode 100644
    index 000000000000..54596359a92a
    --- /dev/null
    +++ b/js/src/jit-test/tests/modules/import-declaration.js
    @@ -0,0 +1,186 @@
    +load(libdir + "match.js");
    +load(libdir + "asserts.js");
    +
    +var { Pattern, MatchError } = Match;
    +
    +program = (elts) => Pattern({
    +    type: "Program",
    +    body: elts
    +})
    +importDeclaration = (specifiers, source) => Pattern({
    +    type: "ImportDeclaration",
    +    specifiers: specifiers,
    +    source: source
    +});
    +importSpecifier = (id, name) => Pattern({
    +    type: "ImportSpecifier",
    +    id: id,
    +    name: name
    +});
    +ident = (name) => Pattern({
    +    type: "Identifier",
    +    name: name
    +})
    +lit = (val) => Pattern({
    +    type: "Literal",
    +    value: val
    +})
    +
    +program([
    +    importDeclaration(
    +        [
    +            importSpecifier(
    +                ident("default"),
    +                ident("a")
    +            )
    +        ],
    +        lit("b")
    +    )
    +]).assert(Reflect.parse("import a from 'b'"));
    +
    +program([
    +    importDeclaration(
    +        [],
    +        lit("a")
    +    )
    +]).assert(Reflect.parse("import {} from 'a'"));
    +
    +program([
    +    importDeclaration(
    +        [
    +            importSpecifier(
    +                ident("a"),
    +                ident("a")
    +            )
    +        ],
    +        lit("b")
    +    )
    +]).assert(Reflect.parse("import { a } from 'b'"));
    +
    +program([
    +    importDeclaration(
    +        [
    +            importSpecifier(
    +                ident("a"),
    +                ident("a")
    +            )
    +        ],
    +        lit("b")
    +    )
    +]).assert(Reflect.parse("import { a, } from 'b'"));
    +
    +program([
    +    importDeclaration(
    +        [
    +            importSpecifier(
    +                ident("a"),
    +                ident("b")
    +            )
    +        ],
    +        lit("c")
    +    )
    +]).assert(Reflect.parse("import { a as b } from 'c'"));
    +
    +program([
    +    importDeclaration(
    +        [
    +            importSpecifier(
    +                ident("as"),
    +                ident("as")
    +            )
    +        ],
    +        lit("a")
    +    )
    +]).assert(Reflect.parse("import { as as as } from 'a'"));
    +
    +program([
    +    importDeclaration(
    +        [
    +            importSpecifier(
    +                ident("true"),
    +                ident("a")
    +            )
    +        ],
    +        lit("b")
    +    )
    +]).assert(Reflect.parse("import { true as a } from 'b'"));
    +
    +program([
    +    importDeclaration(
    +        [
    +            importSpecifier(
    +                ident("a"),
    +                ident("a")
    +            ),
    +            importSpecifier(
    +                ident("b"),
    +                ident("b")
    +            ),
    +        ],
    +        lit("c")
    +    )
    +]).assert(Reflect.parse("import { a, b } from 'c'"));
    +
    +program([
    +    importDeclaration(
    +        [
    +            importSpecifier(
    +                ident("a"),
    +                ident("b")
    +            ),
    +            importSpecifier(
    +                ident("c"),
    +                ident("d")
    +            ),
    +        ],
    +        lit("e")
    +    )
    +]).assert(Reflect.parse("import { a as b, c as d } from 'e'"));
    +
    +program([
    +    importDeclaration(
    +        [],
    +        lit("a")
    +    )
    +]).assert(Reflect.parse("import 'a'"));
    +
    +var loc = Reflect.parse("import { a as b } from 'c'", {
    +    loc: true
    +}).body[0].loc;
    +
    +assertEq(loc.start.line, 1);
    +assertEq(loc.start.column, 0);
    +assertEq(loc.start.line, 1);
    +assertEq(loc.end.column, 26);
    +
    +assertThrowsInstanceOf(function () {
    +   Reflect.parse("function f() { import a from 'b' }");
    +}, SyntaxError);
    +
    +assertThrowsInstanceOf(function () {
    +   Reflect.parse("if (true) import a from 'b'");
    +}, SyntaxError);
    +
    +assertThrowsInstanceOf(function() {
    +    Reflect.parse("import {");
    +}, SyntaxError);
    +
    +assertThrowsInstanceOf(function() {
    +    Reflect.parse("import {}");
    +}, SyntaxError);
    +
    +assertThrowsInstanceOf(function() {
    +    Reflect.parse("import {} from");
    +}, SyntaxError);
    +
    +assertThrowsInstanceOf(function() {
    +    Reflect.parse("import {,} from 'a'");
    +}, SyntaxError);
    +
    +assertThrowsInstanceOf(function() {
    +    Reflect.parse("import { a as true } from 'b'");
    +}, SyntaxError);
    +
    +assertThrowsInstanceOf(function() {
    +    Reflect.parse("import { true } from 'a'");
    +}, SyntaxError);
    
    From 3c583fb5f1282fa776fd4f28b89acb221f764344 Mon Sep 17 00:00:00 2001
    From: Ryan VanderMeulen 
    Date: Wed, 6 Nov 2013 17:48:11 -0500
    Subject: [PATCH 63/82] Backed out changeset 8222e9ae0a21 (bug 915233) for
     Windows xpcshell perma-fail on a CLOSED TREE.
    
    ---
     dom/promise/Promise.cpp             | 234 +++-------------
     dom/promise/Promise.h               |   8 +-
     dom/promise/PromiseCallback.cpp     |  28 +-
     dom/promise/PromiseCallback.h       |   2 +-
     dom/promise/tests/test_promise.html |  10 -
     dom/workers/RegisterBindings.cpp    |   5 +-
     dom/workers/test/mochitest.ini      |   2 -
     dom/workers/test/promise_worker.js  | 395 ----------------------------
     dom/workers/test/test_promise.html  |  44 ----
     9 files changed, 51 insertions(+), 677 deletions(-)
     delete mode 100644 dom/workers/test/promise_worker.js
     delete mode 100644 dom/workers/test/test_promise.html
    
    diff --git a/dom/promise/Promise.cpp b/dom/promise/Promise.cpp
    index 375e261fe840..49879e478ff5 100644
    --- a/dom/promise/Promise.cpp
    +++ b/dom/promise/Promise.cpp
    @@ -10,7 +10,6 @@
     #include "mozilla/dom/OwningNonNull.h"
     #include "mozilla/dom/PromiseBinding.h"
     #include "mozilla/Preferences.h"
    -#include "mozilla/SyncRunnable.h"
     #include "PromiseCallback.h"
     #include "nsContentUtils.h"
     #include "nsPIDOMWindow.h"
    @@ -23,8 +22,6 @@
     namespace mozilla {
     namespace dom {
     
    -using namespace workers;
    -
     // PromiseTask
     
     // This class processes the promise's callbacks with promise's result.
    @@ -54,65 +51,36 @@ private:
       nsRefPtr mPromise;
     };
     
    -class WorkerPromiseTask MOZ_FINAL : public WorkerRunnable
    +// This class processes the promise's callbacks with promise's result.
    +class PromiseResolverTask MOZ_FINAL : public nsRunnable
     {
     public:
    -  WorkerPromiseTask(WorkerPrivate* aWorkerPrivate, Promise* aPromise)
    -    : WorkerRunnable(aWorkerPrivate, WorkerThread,
    -                     UnchangedBusyCount, SkipWhenClearing)
    -    , mPromise(aPromise)
    -  {
    -    MOZ_ASSERT(aPromise);
    -    MOZ_COUNT_CTOR(WorkerPromiseTask);
    -  }
    -
    -  ~WorkerPromiseTask()
    -  {
    -    MOZ_COUNT_DTOR(WorkerPromiseTask);
    -  }
    -
    -  bool
    -  WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
    -  {
    -    mPromise->mTaskPending = false;
    -    mPromise->RunTask();
    -    return true;
    -  }
    -
    -private:
    -  nsRefPtr mPromise;
    -};
    -
    -class PromiseResolverMixin
    -{
    -public:
    -  PromiseResolverMixin(Promise* aPromise,
    -                       JS::Handle aValue,
    -                       Promise::PromiseState aState)
    +  PromiseResolverTask(Promise* aPromise,
    +                      JS::Handle aValue,
    +                      Promise::PromiseState aState)
         : mPromise(aPromise)
         , mValue(aValue)
         , mState(aState)
       {
         MOZ_ASSERT(aPromise);
         MOZ_ASSERT(mState != Promise::Pending);
    -    MOZ_COUNT_CTOR(PromiseResolverMixin);
    +    MOZ_COUNT_CTOR(PromiseResolverTask);
     
    -    JSContext* cx = nsContentUtils::GetDefaultJSContextForThread();
    +    JSContext* cx = nsContentUtils::GetSafeJSContext();
     
         /* It's safe to use unsafeGet() here: the unsafeness comes from the
          * possibility of updating the value of mJSObject without triggering the
          * barriers.  However if the value will always be marked, post barriers
          * unnecessary. */
         JS_AddNamedValueRootRT(JS_GetRuntime(cx), mValue.unsafeGet(),
    -                           "PromiseResolverMixin.mValue");
    +                           "PromiseResolverTask.mValue");
       }
     
    -  virtual ~PromiseResolverMixin()
    +  ~PromiseResolverTask()
       {
    -    NS_ASSERT_OWNINGTHREAD(PromiseResolverMixin);
    -    MOZ_COUNT_DTOR(PromiseResolverMixin);
    +    MOZ_COUNT_DTOR(PromiseResolverTask);
     
    -    JSContext* cx = nsContentUtils::GetDefaultJSContextForThread();
    +    JSContext* cx = nsContentUtils::GetSafeJSContext();
     
         /* It's safe to use unsafeGet() here: the unsafeness comes from the
          * possibility of updating the value of mJSObject without triggering the
    @@ -121,66 +89,18 @@ public:
         JS_RemoveValueRootRT(JS_GetRuntime(cx), mValue.unsafeGet());
       }
     
    -protected:
    -  void
    -  RunInternal()
    +  NS_IMETHOD Run()
       {
    -    NS_ASSERT_OWNINGTHREAD(PromiseResolverMixin);
         mPromise->RunResolveTask(
           JS::Handle::fromMarkedLocation(mValue.address()),
           mState, Promise::SyncTask);
    +    return NS_OK;
       }
     
     private:
       nsRefPtr mPromise;
       JS::Heap mValue;
       Promise::PromiseState mState;
    -  NS_DECL_OWNINGTHREAD;
    -};
    -
    -// This class processes the promise's callbacks with promise's result.
    -class PromiseResolverTask MOZ_FINAL : public nsRunnable,
    -                                      public PromiseResolverMixin
    -{
    -public:
    -  PromiseResolverTask(Promise* aPromise,
    -                      JS::Handle aValue,
    -                      Promise::PromiseState aState)
    -    : PromiseResolverMixin(aPromise, aValue, aState)
    -  {}
    -
    -  ~PromiseResolverTask()
    -  {}
    -
    -  NS_IMETHOD Run()
    -  {
    -    RunInternal();
    -    return NS_OK;
    -  }
    -};
    -
    -class WorkerPromiseResolverTask MOZ_FINAL : public WorkerRunnable,
    -                                            public PromiseResolverMixin
    -{
    -public:
    -  WorkerPromiseResolverTask(WorkerPrivate* aWorkerPrivate,
    -                            Promise* aPromise,
    -                            JS::Handle aValue,
    -                            Promise::PromiseState aState)
    -    : WorkerRunnable(aWorkerPrivate, WorkerThread,
    -                     UnchangedBusyCount, SkipWhenClearing),
    -      PromiseResolverMixin(aPromise, aValue, aState)
    -  {}
    -
    -  ~WorkerPromiseResolverTask()
    -  {}
    -
    -  bool
    -  WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
    -  {
    -    RunInternal();
    -    return true;
    -  }
     };
     
     // Promise
    @@ -243,55 +163,25 @@ Promise::WrapObject(JSContext* aCx, JS::Handle aScope)
       return PromiseBinding::Wrap(aCx, aScope, this);
     }
     
    -class PromisePrefEnabledRunnable : public nsRunnable
    +/* static */ bool
    +Promise::PrefEnabled()
     {
    -public:
    -  PromisePrefEnabledRunnable() : mEnabled(false) {}
    -
    -  bool
    -  Enabled()
    -  {
    -    return mEnabled;
    -  }
    -
    -  NS_IMETHODIMP
    -  Run()
    -  {
    -    MOZ_ASSERT(NS_IsMainThread());
    -    mEnabled = Preferences::GetBool("dom.promise.enabled", false);
    -    return NS_OK;
    -  }
    -
    -private:
    -  bool mEnabled;
    -};
    +  return Preferences::GetBool("dom.promise.enabled", false);
    +}
     
     /* static */ bool
     Promise::EnabledForScope(JSContext* aCx, JSObject* /* unused */)
     {
       // Enable if the pref is enabled or if we're chrome or if we're a
       // certified app.
    -  nsCOMPtr mainThread;
    -  nsresult rv = NS_GetMainThread(getter_AddRefs(mainThread));
    -  NS_ENSURE_SUCCESS(rv, false);
    -
    -  nsRefPtr r = new PromisePrefEnabledRunnable();
    -
    -  // When used from the main thread, SyncRunnable will internally directly call
    -  // the function rather than dispatch a Runnable. So this is usable on any
    -  // thread.
    -  // Although this pause is expensive, it is performed only once per worker when
    -  // the worker in initialized.
    -  SyncRunnable::DispatchToThread(mainThread, r);
    -  if (r->Enabled()) {
    +  if (PrefEnabled()) {
         return true;
       }
     
    -  // FIXME(nsm): Remove these checks once promises are enabled by default.
       // Note that we have no concept of a certified app in workers.
       // XXXbz well, why not?
       if (!NS_IsMainThread()) {
    -    return GetWorkerPrivateFromContext(aCx)->IsChromeWorker();
    +    return workers::GetWorkerPrivateFromContext(aCx)->IsChromeWorker();
       }
     
       nsIPrincipal* prin = nsContentUtils::GetSubjectPrincipal();
    @@ -390,15 +280,10 @@ Promise::Constructor(const GlobalObject& aGlobal,
                          PromiseInit& aInit, ErrorResult& aRv)
     {
       JSContext* cx = aGlobal.GetContext();
    -  nsCOMPtr window;
    -
    -  // On workers, let the window be null.
    -  if (MOZ_LIKELY(NS_IsMainThread())) {
    -    window = do_QueryInterface(aGlobal.GetAsSupports());
    -    if (!window) {
    -      aRv.Throw(NS_ERROR_UNEXPECTED);
    -      return nullptr;
    -    }
    +  nsCOMPtr window = do_QueryInterface(aGlobal.GetAsSupports());
    +  if (!window) {
    +    aRv.Throw(NS_ERROR_UNEXPECTED);
    +    return nullptr;
       }
     
       nsRefPtr promise = new Promise(window);
    @@ -439,13 +324,10 @@ Promise::Constructor(const GlobalObject& aGlobal,
     Promise::Resolve(const GlobalObject& aGlobal, JSContext* aCx,
                      JS::Handle aValue, ErrorResult& aRv)
     {
    -  nsCOMPtr window;
    -  if (MOZ_LIKELY(NS_IsMainThread())) {
    -    window = do_QueryInterface(aGlobal.GetAsSupports());
    -    if (!window) {
    -      aRv.Throw(NS_ERROR_UNEXPECTED);
    -      return nullptr;
    -    }
    +  nsCOMPtr window = do_QueryInterface(aGlobal.GetAsSupports());
    +  if (!window) {
    +    aRv.Throw(NS_ERROR_UNEXPECTED);
    +    return nullptr;
       }
     
       nsRefPtr promise = new Promise(window);
    @@ -459,13 +341,10 @@ Promise::Resolve(const GlobalObject& aGlobal, JSContext* aCx,
     Promise::Reject(const GlobalObject& aGlobal, JSContext* aCx,
                     JS::Handle aValue, ErrorResult& aRv)
     {
    -  nsCOMPtr window;
    -  if (MOZ_LIKELY(NS_IsMainThread())) {
    -    window = do_QueryInterface(aGlobal.GetAsSupports());
    -    if (!window) {
    -      aRv.Throw(NS_ERROR_UNEXPECTED);
    -      return nullptr;
    -    }
    +  nsCOMPtr window = do_QueryInterface(aGlobal.GetAsSupports());
    +  if (!window) {
    +    aRv.Throw(NS_ERROR_UNEXPECTED);
    +    return nullptr;
       }
     
       nsRefPtr promise = new Promise(window);
    @@ -524,15 +403,8 @@ Promise::AppendCallbacks(PromiseCallback* aResolveCallback,
       // callbacks with promise's result. If promise's state is rejected, queue a
       // task to process our reject callbacks with promise's result.
       if (mState != Pending && !mTaskPending) {
    -    if (MOZ_LIKELY(NS_IsMainThread())) {
    -      nsRefPtr task = new PromiseTask(this);
    -      NS_DispatchToCurrentThread(task);
    -    } else {
    -      WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
    -      MOZ_ASSERT(worker);
    -      nsRefPtr task = new WorkerPromiseTask(worker, this);
    -      worker->Dispatch(task);
    -    }
    +    nsRefPtr task = new PromiseTask(this);
    +    NS_DispatchToCurrentThread(task);
         mTaskPending = true;
       }
     }
    @@ -548,9 +420,8 @@ Promise::RunTask()
       mResolveCallbacks.Clear();
       mRejectCallbacks.Clear();
     
    -  JSContext* cx = nsContentUtils::GetDefaultJSContextForThread();
    -  JSAutoRequest ar(cx);
    -  Optional > value(cx, mResult);
    +  JSAutoRequest ar(nsContentUtils::GetSafeJSContext());
    +  Optional > value(nsContentUtils::GetSafeJSContext(), mResult);
     
       for (uint32_t i = 0; i < callbacks.Length(); ++i) {
         callbacks[i]->Call(value);
    @@ -571,27 +442,16 @@ Promise::MaybeReportRejected()
     
       MOZ_ASSERT(mResult.isObject(), "How did we get a JSErrorReport?");
     
    -  // Remains null in case of worker.
    -  nsCOMPtr win;
    -  bool isChromeError = false;
    -
    -  if (MOZ_LIKELY(NS_IsMainThread())) {
    -    win =
    -      do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(&mResult.toObject()));
    -    nsIPrincipal* principal = nsContentUtils::GetObjectPrincipal(&mResult.toObject());
    -    isChromeError = nsContentUtils::IsSystemPrincipal(principal);
    -  } else {
    -    WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
    -    MOZ_ASSERT(worker);
    -    isChromeError = worker->IsChromeWorker();
    -  }
    +  nsCOMPtr win =
    +    do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(&mResult.toObject()));
     
    +  nsIPrincipal* principal = nsContentUtils::GetObjectPrincipal(&mResult.toObject());
       // Now post an event to do the real reporting async
    -  NS_DispatchToMainThread(
    +  NS_DispatchToCurrentThread(
         new AsyncErrorReporter(JS_GetObjectRuntime(&mResult.toObject()),
                                report,
                                nullptr,
    -                           isChromeError,
    +                           nsContentUtils::IsSystemPrincipal(principal),
                                win));
     }
     
    @@ -670,17 +530,9 @@ Promise::RunResolveTask(JS::Handle aValue,
       // If the synchronous flag is unset, queue a task to process our
       // accept callbacks with value.
       if (aAsynchronous == AsyncTask) {
    -    if (MOZ_LIKELY(NS_IsMainThread())) {
    -      nsRefPtr task =
    -        new PromiseResolverTask(this, aValue, aState);
    -      NS_DispatchToCurrentThread(task);
    -    } else {
    -      WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
    -      MOZ_ASSERT(worker);
    -      nsRefPtr task =
    -        new WorkerPromiseResolverTask(worker, this, aValue, aState);
    -      worker->Dispatch(task);
    -    }
    +    nsRefPtr task =
    +      new PromiseResolverTask(this, aValue, aState);
    +    NS_DispatchToCurrentThread(task);
         return;
       }
     
    diff --git a/dom/promise/Promise.h b/dom/promise/Promise.h
    index 6a3f1ca7e889..de2c06f11525 100644
    --- a/dom/promise/Promise.h
    +++ b/dom/promise/Promise.h
    @@ -27,13 +27,10 @@ class AnyCallback;
     class Promise MOZ_FINAL : public nsISupports,
                               public nsWrapperCache
     {
    -  friend class PromiseResolverMixin;
    -  friend class PromiseResolverTask;
       friend class PromiseTask;
    -  friend class RejectPromiseCallback;
    +  friend class PromiseResolverTask;
       friend class ResolvePromiseCallback;
    -  friend class WorkerPromiseResolverTask;
    -  friend class WorkerPromiseTask;
    +  friend class RejectPromiseCallback;
       friend class WrapperPromiseCallback;
     
     public:
    @@ -43,6 +40,7 @@ public:
       Promise(nsPIDOMWindow* aWindow);
       ~Promise();
     
    +  static bool PrefEnabled();
       static bool EnabledForScope(JSContext* aCx, JSObject* /* unused */);
     
       void MaybeResolve(JSContext* aCx,
    diff --git a/dom/promise/PromiseCallback.cpp b/dom/promise/PromiseCallback.cpp
    index c828b2171355..f8cb9b9c9a1a 100644
    --- a/dom/promise/PromiseCallback.cpp
    +++ b/dom/promise/PromiseCallback.cpp
    @@ -74,13 +74,7 @@ void
     ResolvePromiseCallback::Call(const Optional >& aValue)
     {
       // Run resolver's algorithm with value and the synchronous flag set.
    -  JSContext *cx = nsContentUtils::GetDefaultJSContextForThread();
    -
    -  Maybe pusher;
    -  if (NS_IsMainThread()) {
    -    pusher.construct(cx);
    -  }
    -
    +  AutoJSContext cx;
       Maybe ac;
       EnterCompartment(ac, cx, aValue);
     
    @@ -115,13 +109,7 @@ void
     RejectPromiseCallback::Call(const Optional >& aValue)
     {
       // Run resolver's algorithm with value and the synchronous flag set.
    -  JSContext *cx = nsContentUtils::GetDefaultJSContextForThread();
    -
    -  Maybe pusher;
    -  if (NS_IsMainThread()) {
    -    pusher.construct(cx);
    -  }
    -
    +  AutoJSContext cx;
       Maybe ac;
       EnterCompartment(ac, cx, aValue);
     
    @@ -157,17 +145,7 @@ WrapperPromiseCallback::~WrapperPromiseCallback()
     void
     WrapperPromiseCallback::Call(const Optional >& aValue)
     {
    -  // AutoCxPusher and co. interact with xpconnect, which crashes on
    -  // workers. On workers we'll get the right context from
    -  // GetDefaultJSContextForThread(), and since there is only one context, we
    -  // don't need to push or pop it from the stack. Is that correct?
    -  JSContext* cx = nsContentUtils::GetDefaultJSContextForThread();
    -
    -  Maybe pusher;
    -  if (NS_IsMainThread()) {
    -    pusher.construct(cx);
    -  }
    -
    +  AutoJSContext cx;
       Maybe ac;
       EnterCompartment(ac, cx, aValue);
     
    diff --git a/dom/promise/PromiseCallback.h b/dom/promise/PromiseCallback.h
    index 07f156100820..38089466eed6 100644
    --- a/dom/promise/PromiseCallback.h
    +++ b/dom/promise/PromiseCallback.h
    @@ -37,7 +37,7 @@ public:
     };
     
     // WrapperPromiseCallback execs a JS Callback with a value, and then the return
    -// value is sent to the aNextPromise->ResolveFunction() or to
    +// value is sent to the aNextPromise->resolveFunction() or to
     // aNextPromise->RejectFunction() if the JS Callback throws.
     class WrapperPromiseCallback MOZ_FINAL : public PromiseCallback
     {
    diff --git a/dom/promise/tests/test_promise.html b/dom/promise/tests/test_promise.html
    index 0cc6a5822b7c..3e5b1f3cad6a 100644
    --- a/dom/promise/tests/test_promise.html
    +++ b/dom/promise/tests/test_promise.html
    @@ -368,15 +368,6 @@ function promiseResolveNestedPromise() {
       });
     }
     
    -function promiseRejectNoHandler() {
    -  // This test only checks that the code that reports unhandled errors in the
    -  // Promises implementation does not crash or leak.
    -  var promise = new Promise(function(res, rej) {
    -    noSuchMethod();
    -  });
    -  runTest();
    -}
    -
     var tests = [ promiseResolve, promiseReject,
                   promiseException, promiseGC, promiseAsync,
                   promiseDoubleThen, promiseThenException,
    @@ -389,7 +380,6 @@ var tests = [ promiseResolve, promiseReject,
                   promiseWrongNestedPromise, promiseLoop,
                   promiseStaticReject, promiseStaticResolve,
                   promiseResolveNestedPromise,
    -              promiseRejectNoHandler,
                 ];
     
     function runTest() {
    diff --git a/dom/workers/RegisterBindings.cpp b/dom/workers/RegisterBindings.cpp
    index 4dfae63199ab..505e304d3aab 100644
    --- a/dom/workers/RegisterBindings.cpp
    +++ b/dom/workers/RegisterBindings.cpp
    @@ -19,7 +19,6 @@
     #include "mozilla/dom/ImageDataBinding.h"
     #include "mozilla/dom/MessageEventBinding.h"
     #include "mozilla/dom/MessagePortBinding.h"
    -#include "mozilla/dom/PromiseBinding.h"
     #include "mozilla/dom/TextDecoderBinding.h"
     #include "mozilla/dom/TextEncoderBinding.h"
     #include "mozilla/dom/XMLHttpRequestBinding.h"
    @@ -62,8 +61,6 @@ WorkerPrivate::RegisterBindings(JSContext* aCx, JS::Handle aGlobal)
           !ImageDataBinding::GetConstructorObject(aCx, aGlobal) ||
           !MessageEventBinding::GetConstructorObject(aCx, aGlobal) ||
           !MessagePortBinding::GetConstructorObject(aCx, aGlobal) ||
    -      (PromiseBinding::ConstructorEnabled(aCx, aGlobal) &&
    -       !PromiseBinding::GetConstructorObject(aCx, aGlobal)) ||
           !TextDecoderBinding::GetConstructorObject(aCx, aGlobal) ||
           !TextEncoderBinding::GetConstructorObject(aCx, aGlobal) ||
           !XMLHttpRequestBinding_workers::GetConstructorObject(aCx, aGlobal) ||
    @@ -80,4 +77,4 @@ WorkerPrivate::RegisterBindings(JSContext* aCx, JS::Handle aGlobal)
       }
     
       return true;
    -}
    +}
    \ No newline at end of file
    diff --git a/dom/workers/test/mochitest.ini b/dom/workers/test/mochitest.ini
    index d13b71239381..ce42a9cb05d8 100644
    --- a/dom/workers/test/mochitest.ini
    +++ b/dom/workers/test/mochitest.ini
    @@ -27,7 +27,6 @@ support-files =
       multi_sharedWorker_sharedWorker.js
       navigator_worker.js
       newError_worker.js
    -  promise_worker.js
       recursion_worker.js
       recursiveOnerror_worker.js
       relativeLoad_import.js
    @@ -84,7 +83,6 @@ support-files =
     [test_multi_sharedWorker_lifetimes.html]
     [test_navigator.html]
     [test_newError.html]
    -[test_promise.html]
     [test_recursion.html]
     [test_recursiveOnerror.html]
     [test_relativeLoad.html]
    diff --git a/dom/workers/test/promise_worker.js b/dom/workers/test/promise_worker.js
    deleted file mode 100644
    index d89b41d24b12..000000000000
    --- a/dom/workers/test/promise_worker.js
    +++ /dev/null
    @@ -1,395 +0,0 @@
    -function ok(a, msg) {
    -  dump("OK: " + !!a + "  =>  " + a + " " + msg + "\n");
    -  postMessage({type: 'status', status: !!a, msg: a + ": " + msg });
    -}
    -
    -function is(a, b, msg) {
    -  dump("IS: " + (a===b) + "  =>  " + a + " | " + b + " " + msg + "\n");
    -  postMessage({type: 'status', status: a === b, msg: a + " === " + b + ": " + msg });
    -}
    -
    -function isnot(a, b, msg) {
    -  dump("ISNOT: " + (a!==b) + "  =>  " + a + " | " + b + " " + msg + "\n");
    -  postMessage({type: 'status', status: a !== b, msg: a + " !== " + b + ": " + msg });
    -}
    -
    -function promiseResolve() {
    -  ok(Promise, "Promise object should exist");
    -
    -  var promise = new Promise(function(resolve, reject) {
    -    ok(resolve, "Promise.resolve exists");
    -    ok(reject, "Promise.reject exists");
    -
    -    resolve(42);
    -  }).then(function(what) {
    -    ok(true, "Then - resolveCb has been called");
    -    is(what, 42, "ResolveCb received 42");
    -    runTest();
    -  }, function() {
    -    ok(false, "Then - rejectCb has been called");
    -    runTest();
    -  });
    -}
    -
    -
    -function promiseReject() {
    -  var promise = new Promise(function(resolve, reject) {
    -    reject(42);
    -  }).then(function(what) {
    -    ok(false, "Then - resolveCb has been called");
    -    runTest();
    -  }, function(what) {
    -    ok(true, "Then - rejectCb has been called");
    -    is(what, 42, "RejectCb received 42");
    -    runTest();
    -  });
    -}
    -
    -function promiseException() {
    -  var promise = new Promise(function(resolve, reject) {
    -    throw 42;
    -  }).then(function(what) {
    -    ok(false, "Then - resolveCb has been called");
    -    runTest();
    -  }, function(what) {
    -    ok(true, "Then - rejectCb has been called");
    -    is(what, 42, "RejectCb received 42");
    -    runTest();
    -  });
    -}
    -
    -function promiseAsync() {
    -  var global = "foo";
    -  var f = new Promise(function(r1, r2) {
    -    is(global, "foo", "Global should be foo");
    -    r1(42);
    -    is(global, "foo", "Global should still be foo");
    -    setTimeout(function() {
    -      is(global, "bar", "Global should still be bar!");
    -      runTest();
    -    }, 0);
    -  }).then(function() {
    -    global = "bar";
    -  });
    -  is(global, "foo", "Global should still be foo (2)");
    -}
    -
    -function promiseDoubleThen() {
    -  var steps = 0;
    -  var promise = new Promise(function(r1, r2) {
    -    r1(42);
    -  });
    -
    -  promise.then(function(what) {
    -    ok(true, "Then.resolve has been called");
    -    is(what, 42, "Value == 42");
    -    steps++;
    -  }, function(what) {
    -    ok(false, "Then.reject has been called");
    -  });
    -
    -  promise.then(function(what) {
    -    ok(true, "Then.resolve has been called");
    -    is(steps, 1, "Then.resolve - step == 1");
    -    is(what, 42, "Value == 42");
    -    runTest();
    -  }, function(what) {
    -    ok(false, "Then.reject has been called");
    -  });
    -}
    -
    -function promiseThenException() {
    -  var promise = new Promise(function(resolve, reject) {
    -    resolve(42);
    -  });
    -
    -  promise.then(function(what) {
    -    ok(true, "Then.resolve has been called");
    -    throw "booh";
    -  }).catch(function(e) {
    -    ok(true, "Catch has been called!");
    -    runTest();
    -  });
    -}
    -
    -function promiseThenCatchThen() {
    -  var promise = new Promise(function(resolve, reject) {
    -    resolve(42);
    -  });
    -
    -  var promise2 = promise.then(function(what) {
    -    ok(true, "Then.resolve has been called");
    -    is(what, 42, "Value == 42");
    -    return what + 1;
    -  }, function(what) {
    -    ok(false, "Then.reject has been called");
    -  });
    -
    -  isnot(promise, promise2, "These 2 promise objs are different");
    -
    -  promise2.then(function(what) {
    -    ok(true, "Then.resolve has been called");
    -    is(what, 43, "Value == 43");
    -    return what + 1;
    -  }, function(what) {
    -    ok(false, "Then.reject has been called");
    -  }).catch(function() {
    -    ok(false, "Catch has been called");
    -  }).then(function(what) {
    -    ok(true, "Then.resolve has been called");
    -    is(what, 44, "Value == 44");
    -    runTest();
    -  }, function(what) {
    -    ok(false, "Then.reject has been called");
    -  });
    -}
    -
    -function promiseRejectThenCatchThen() {
    -  var promise = new Promise(function(resolve, reject) {
    -    reject(42);
    -  });
    -
    -  var promise2 = promise.then(function(what) {
    -    ok(false, "Then.resolve has been called");
    -  }, function(what) {
    -    ok(true, "Then.reject has been called");
    -    is(what, 42, "Value == 42");
    -    return what + 1;
    -  });
    -
    -  isnot(promise, promise2, "These 2 promise objs are different");
    -
    -  promise2.then(function(what) {
    -    ok(true, "Then.resolve has been called");
    -    is(what, 43, "Value == 43");
    -    return what+1;
    -  }).catch(function(what) {
    -    ok(false, "Catch has been called");
    -  }).then(function(what) {
    -    ok(true, "Then.resolve has been called");
    -    is(what, 44, "Value == 44");
    -    runTest();
    -  });
    -}
    -
    -function promiseRejectThenCatchThen2() {
    -  var promise = new Promise(function(resolve, reject) {
    -    reject(42);
    -  });
    -
    -  promise.then(function(what) {
    -    ok(true, "Then.resolve has been called");
    -    is(what, 42, "Value == 42");
    -    return what+1;
    -  }).catch(function(what) {
    -    is(what, 42, "Value == 42");
    -    ok(true, "Catch has been called");
    -    return what+1;
    -  }).then(function(what) {
    -    ok(true, "Then.resolve has been called");
    -    is(what, 43, "Value == 43");
    -    runTest();
    -  });
    -}
    -
    -function promiseRejectThenCatchExceptionThen() {
    -  var promise = new Promise(function(resolve, reject) {
    -    reject(42);
    -  });
    -
    -  promise.then(function(what) {
    -    ok(false, "Then.resolve has been called");
    -  }, function(what) {
    -    ok(true, "Then.reject has been called");
    -    is(what, 42, "Value == 42");
    -    throw(what + 1);
    -  }).catch(function(what) {
    -    ok(true, "Catch has been called");
    -    is(what, 43, "Value == 43");
    -    return what + 1;
    -  }).then(function(what) {
    -    ok(true, "Then.resolve has been called");
    -    is(what, 44, "Value == 44");
    -    runTest();
    -  });
    -}
    -
    -function promiseThenCatchOrderingResolve() {
    -  var global = 0;
    -  var f = new Promise(function(r1, r2) {
    -    r1(42);
    -  });
    -
    -  f.then(function() {
    -    f.then(function() {
    -      global++;
    -    });
    -    f.catch(function() {
    -      global++;
    -    });
    -    f.then(function() {
    -      global++;
    -    });
    -    setTimeout(function() {
    -      is(global, 2, "Many steps... should return 2");
    -      runTest();
    -    }, 0);
    -  });
    -}
    -
    -function promiseThenCatchOrderingReject() {
    -  var global = 0;
    -  var f = new Promise(function(r1, r2) {
    -    r2(42);
    -  })
    -
    -  f.then(function() {}, function() {
    -    f.then(function() {
    -      global++;
    -    });
    -    f.catch(function() {
    -      global++;
    -    });
    -    f.then(function() {}, function() {
    -      global++;
    -    });
    -    setTimeout(function() {
    -      is(global, 2, "Many steps... should return 2");
    -      runTest();
    -    }, 0);
    -  });
    -}
    -
    -function promiseNestedPromise() {
    -  new Promise(function(resolve, reject) {
    -    resolve(new Promise(function(resolve, reject) {
    -      ok(true, "Nested promise is executed");
    -      resolve(42);
    -    }));
    -  }).then(function(value) {
    -    is(value, 42, "Nested promise is executed and then == 42");
    -    runTest();
    -  });
    -}
    -
    -function promiseNestedNestedPromise() {
    -  new Promise(function(resolve, reject) {
    -    resolve(new Promise(function(resolve, reject) {
    -      ok(true, "Nested promise is executed");
    -      resolve(42);
    -    }).then(function(what) { return what+1; }));
    -  }).then(function(value) {
    -    is(value, 43, "Nested promise is executed and then == 43");
    -    runTest();
    -  });
    -}
    -
    -function promiseWrongNestedPromise() {
    -  new Promise(function(resolve, reject) {
    -    resolve(new Promise(function(r, r2) {
    -      ok(true, "Nested promise is executed");
    -      r(42);
    -    }));
    -    reject(42);
    -  }).then(function(value) {
    -    is(value, 42, "Nested promise is executed and then == 42");
    -    runTest();
    -  }, function(value) {
    -     ok(false, "This is wrong");
    -  });
    -}
    -
    -function promiseLoop() {
    -  new Promise(function(resolve, reject) {
    -    resolve(new Promise(function(r1, r2) {
    -      ok(true, "Nested promise is executed");
    -      r1(new Promise(function(r1, r2) {
    -        ok(true, "Nested nested promise is executed");
    -        r1(42);
    -      }));
    -    }));
    -  }).then(function(value) {
    -    is(value, 42, "Nested nested promise is executed and then == 42");
    -    runTest();
    -  }, function(value) {
    -     ok(false, "This is wrong");
    -  });
    -}
    -
    -function promiseStaticReject() {
    -  var promise = Promise.reject(42).then(function(what) {
    -    ok(false, "This should not be called");
    -  }, function(what) {
    -    is(what, 42, "Value == 42");
    -    runTest();
    -  });
    -}
    -
    -function promiseStaticResolve() {
    -  var promise = Promise.resolve(42).then(function(what) {
    -    is(what, 42, "Value == 42");
    -    runTest();
    -  }, function() {
    -    ok(false, "This should not be called");
    -  });
    -}
    -
    -function promiseResolveNestedPromise() {
    -  var promise = Promise.resolve(new Promise(function(r, r2) {
    -    ok(true, "Nested promise is executed");
    -    r(42);
    -  }, function() {
    -    ok(false, "This should not be called");
    -  })).then(function(what) {
    -    is(what, 42, "Value == 42");
    -    runTest();
    -  }, function() {
    -    ok(false, "This should not be called");
    -  });
    -}
    -
    -function promiseRejectNoHandler() {
    -  // This test only checks that the code that reports unhandled errors in the
    -  // Promises implementation does not crash or leak.
    -  var promise = new Promise(function(res, rej) {
    -    noSuchMethod();
    -  });
    -  runTest();
    -}
    -
    -var tests = [
    -    promiseResolve,
    -    promiseReject,
    -    promiseException,
    -    promiseAsync,
    -    promiseDoubleThen,
    -    promiseThenException,
    -    promiseThenCatchThen,
    -    promiseRejectThenCatchThen,
    -    promiseRejectThenCatchThen2,
    -    promiseRejectThenCatchExceptionThen,
    -    promiseThenCatchOrderingResolve,
    -    promiseThenCatchOrderingReject,
    -    promiseNestedPromise,
    -    promiseNestedNestedPromise,
    -    promiseWrongNestedPromise,
    -    promiseLoop,
    -    promiseStaticReject,
    -    promiseStaticResolve,
    -    promiseResolveNestedPromise,
    -    promiseRejectNoHandler,
    -];
    -
    -function runTest() {
    -  if (!tests.length) {
    -    postMessage({ type: 'finish' });
    -    return;
    -  }
    -
    -  var test = tests.shift();
    -  test();
    -}
    -
    -onmessage = function() {
    -  runTest();
    -}
    diff --git a/dom/workers/test/test_promise.html b/dom/workers/test/test_promise.html
    deleted file mode 100644
    index 4548072c7080..000000000000
    --- a/dom/workers/test/test_promise.html
    +++ /dev/null
    @@ -1,44 +0,0 @@
    -
    -
    -
    -
    -  Test for Promise object in workers
    -  
    -  
    -
    -
    -

    - -
    
    -
    -
    -
    -
    -
    
    From 95d9ab17a542e10f53b7b40f2220e9b7ef5d664d Mon Sep 17 00:00:00 2001
    From: Eddy Bruel 
    Date: Wed, 6 Nov 2013 20:04:45 +0100
    Subject: [PATCH 64/82] Bug 927116 - Implement reflect support for import
     declarations; r=jorendorff CLOSED TREE
    
    ---
     js/src/jsast.tbl     |  2 ++
     js/src/jsreflect.cpp | 76 ++++++++++++++++++++++++++++++++++++++++++++
     2 files changed, 78 insertions(+)
    
    diff --git a/js/src/jsast.tbl b/js/src/jsast.tbl
    index bcfb6907b634..4e2aa4daedb6 100644
    --- a/js/src/jsast.tbl
    +++ b/js/src/jsast.tbl
    @@ -57,6 +57,8 @@ ASTDEF(AST_TRY_STMT,              "TryStatement",                   "tryStatemen
     ASTDEF(AST_THROW_STMT,            "ThrowStatement",                 "throwStatement")
     ASTDEF(AST_DEBUGGER_STMT,         "DebuggerStatement",              "debuggerStatement")
     ASTDEF(AST_LET_STMT,              "LetStatement",                   "letStatement")
    +ASTDEF(AST_IMPORT_DECL,           "ImportDeclaration",              "importDeclaration")
    +ASTDEF(AST_IMPORT_SPEC,           "ImportSpecifier",                "importSpecifier")
     
     ASTDEF(AST_CASE,                  "SwitchCase",                     "switchCase")
     ASTDEF(AST_CATCH,                 "CatchClause",                    "catchClause")
    diff --git a/js/src/jsreflect.cpp b/js/src/jsreflect.cpp
    index 34baac115ca4..7cf7f2fd0a79 100644
    --- a/js/src/jsreflect.cpp
    +++ b/js/src/jsreflect.cpp
    @@ -562,6 +562,10 @@ class NodeBuilder
     
         bool letStatement(NodeVector &head, HandleValue stmt, TokenPos *pos, MutableHandleValue dst);
     
    +    bool importDeclaration(NodeVector &elts, HandleValue moduleSpec, TokenPos *pos, MutableHandleValue dst);
    +
    +    bool importSpecifier(HandleValue importName, HandleValue bindingName, TokenPos *pos, MutableHandleValue dst);
    +
         /*
          * expressions
          */
    @@ -1353,6 +1357,38 @@ NodeBuilder::letStatement(NodeVector &head, HandleValue stmt, TokenPos *pos, Mut
                        dst);
     }
     
    +bool
    +NodeBuilder::importDeclaration(NodeVector &elts, HandleValue moduleSpec, TokenPos *pos,
    +                               MutableHandleValue dst)
    +{
    +    RootedValue array(cx);
    +    if (!newArray(elts, &array))
    +        return false;
    +
    +    RootedValue cb(cx, callbacks[AST_IMPORT_DECL]);
    +    if (!cb.isNull())
    +        return callback(cb, array, moduleSpec, pos, dst);
    +
    +    return newNode(AST_IMPORT_DECL, pos,
    +                   "specifiers", array,
    +                   "source", moduleSpec,
    +                   dst);
    +}
    +
    +bool
    +NodeBuilder::importSpecifier(HandleValue importName, HandleValue bindingName, TokenPos *pos,
    +                             MutableHandleValue dst)
    +{
    +    RootedValue cb(cx, callbacks[AST_IMPORT_SPEC]);
    +    if (!cb.isNull())
    +        return callback(cb, importName, bindingName, pos, dst);
    +
    +    return newNode(AST_IMPORT_SPEC, pos,
    +                   "id", importName,
    +                   "name", bindingName,
    +                   dst);
    +}
    +
     bool
     NodeBuilder::variableDeclaration(NodeVector &elts, VarDeclKind kind, TokenPos *pos,
                                      MutableHandleValue dst)
    @@ -1520,6 +1556,8 @@ class ASTSerializer
         bool variableDeclaration(ParseNode *pn, bool let, MutableHandleValue dst);
         bool variableDeclarator(ParseNode *pn, VarDeclKind *pkind, MutableHandleValue dst);
         bool let(ParseNode *pn, bool expr, MutableHandleValue dst);
    +    bool importDeclaration(ParseNode *pn, MutableHandleValue dst);
    +    bool importSpecifier(ParseNode *pn, MutableHandleValue dst);
     
         bool optStatement(ParseNode *pn, MutableHandleValue dst) {
             if (!pn) {
    @@ -1883,6 +1921,41 @@ ASTSerializer::let(ParseNode *pn, bool expr, MutableHandleValue dst)
                  builder.letStatement(dtors, v, &pn->pn_pos, dst);
     }
     
    +bool
    +ASTSerializer::importDeclaration(ParseNode *pn, MutableHandleValue dst)
    +{
    +    JS_ASSERT(pn->isKind(PNK_IMPORT));
    +    JS_ASSERT(pn->pn_left->isKind(PNK_IMPORT_SPEC_LIST));
    +    JS_ASSERT(pn->pn_right->isKind(PNK_STRING));
    +
    +    NodeVector elts(cx);
    +    if (!elts.reserve(pn->pn_count))
    +        return false;
    +
    +    for (ParseNode *next = pn->pn_left->pn_head; next; next = next->pn_next) {
    +        RootedValue elt(cx);
    +        if (!importSpecifier(next, &elt))
    +            return false;
    +        elts.infallibleAppend(elt);
    +    }
    +
    +    RootedValue moduleSpec(cx);
    +    return literal(pn->pn_right, &moduleSpec) &&
    +           builder.importDeclaration(elts, moduleSpec, &pn->pn_pos, dst);
    +}
    +
    +bool
    +ASTSerializer::importSpecifier(ParseNode *pn, MutableHandleValue dst)
    +{
    +    JS_ASSERT(pn->isKind(PNK_IMPORT_SPEC));
    +
    +    RootedValue importName(cx);
    +    RootedValue bindingName(cx);
    +    return identifier(pn->pn_left, &importName) &&
    +           identifier(pn->pn_right, &bindingName) &&
    +           builder.importSpecifier(importName, bindingName, &pn->pn_pos, dst);
    +}
    +
     bool
     ASTSerializer::switchCase(ParseNode *pn, MutableHandleValue dst)
     {
    @@ -2038,6 +2111,9 @@ ASTSerializer::statement(ParseNode *pn, MutableHandleValue dst)
                    ? let(pn, false, dst)
                    : declaration(pn, dst);
     
    +      case PNK_IMPORT:
    +        return importDeclaration(pn, dst);
    +
           case PNK_NAME:
             LOCAL_ASSERT(pn->isUsed());
             return statement(pn->pn_lexdef, dst);
    
    From c55e498091a12276642c90c8ae6f25e68042787e Mon Sep 17 00:00:00 2001
    From: Mike Hommey 
    Date: Thu, 7 Nov 2013 10:37:44 +0900
    Subject: [PATCH 65/82] Bug 921816 - Handle idls in --with-libxul-sdk builds.
     r=gps
    
    ---
     config/config.mk                                 |  5 +++++
     config/makefiles/xpidl/Makefile.in               |  4 ++++
     js/src/config/config.mk                          |  5 +++++
     moz.build                                        |  2 ++
     python/mozbuild/mozbuild/action/xpidl-process.py | 10 ++++++----
     xpcom/moz.build                                  |  1 -
     xpcom/xpidl/Makefile.in                          |  2 ++
     7 files changed, 24 insertions(+), 5 deletions(-)
    
    diff --git a/config/config.mk b/config/config.mk
    index 1f93e731a3af..c56ca87fad53 100644
    --- a/config/config.mk
    +++ b/config/config.mk
    @@ -622,8 +622,13 @@ endif
     endif
     
     # Default location of include files
    +ifndef LIBXUL_SDK
     IDL_PARSER_DIR = $(topsrcdir)/xpcom/idl-parser
     IDL_PARSER_CACHE_DIR = $(DEPTH)/xpcom/idl-parser
    +else
    +IDL_PARSER_DIR = $(LIBXUL_SDK)/sdk/bin
    +IDL_PARSER_CACHE_DIR = $(LIBXUL_SDK)/sdk/bin
    +endif
     
     SDK_LIB_DIR = $(DIST)/sdk/lib
     SDK_BIN_DIR = $(DIST)/sdk/bin
    diff --git a/config/makefiles/xpidl/Makefile.in b/config/makefiles/xpidl/Makefile.in
    index da40675a94e2..832f9ff412d4 100644
    --- a/config/makefiles/xpidl/Makefile.in
    +++ b/config/makefiles/xpidl/Makefile.in
    @@ -49,6 +49,10 @@ idlprocess := $(PYTHON_PATH) $(PLY_INCLUDE) -I$(IDL_PARSER_DIR) -I$(IDL_PARSER_C
         $(process_py) --cache-dir $(IDL_PARSER_CACHE_DIR) $(dist_idl_dir) \
             $(dist_include_dir) $(idl_xpt_dir) $(idl_deps_dir)
     
    +ifdef LIBXUL_SDK
    +idlprocess += -I$(LIBXUL_SDK)/idl
    +endif
    +
     xpidl_modules := @xpidl_modules@
     
     @xpidl_rules@
    diff --git a/js/src/config/config.mk b/js/src/config/config.mk
    index 1f93e731a3af..c56ca87fad53 100644
    --- a/js/src/config/config.mk
    +++ b/js/src/config/config.mk
    @@ -622,8 +622,13 @@ endif
     endif
     
     # Default location of include files
    +ifndef LIBXUL_SDK
     IDL_PARSER_DIR = $(topsrcdir)/xpcom/idl-parser
     IDL_PARSER_CACHE_DIR = $(DEPTH)/xpcom/idl-parser
    +else
    +IDL_PARSER_DIR = $(LIBXUL_SDK)/sdk/bin
    +IDL_PARSER_CACHE_DIR = $(LIBXUL_SDK)/sdk/bin
    +endif
     
     SDK_LIB_DIR = $(DIST)/sdk/lib
     SDK_BIN_DIR = $(DIST)/sdk/bin
    diff --git a/moz.build b/moz.build
    index fea23f9cc07d..86d8b958cdad 100644
    --- a/moz.build
    +++ b/moz.build
    @@ -26,6 +26,8 @@ if not CONFIG['LIBXUL_SDK']:
     
         add_tier_dir('base', ['mozglue', 'memory/mozalloc'])
     
    +add_tier_dir('precompile', 'xpcom/xpidl')
    +
     # Bring in the configuration for the configured application.
     if CONFIG['COMPILE_ENVIRONMENT']:
         include('/' + CONFIG['MOZ_BUILD_APP'] + '/app.mozbuild')
    diff --git a/python/mozbuild/mozbuild/action/xpidl-process.py b/python/mozbuild/mozbuild/action/xpidl-process.py
    index 2cf7d986dbca..df687547756e 100755
    --- a/python/mozbuild/mozbuild/action/xpidl-process.py
    +++ b/python/mozbuild/mozbuild/action/xpidl-process.py
    @@ -24,7 +24,7 @@ from mozbuild.pythonutil import iter_modules_in_path
     from mozbuild.util import FileAvoidWrite
     
     
    -def process(input_dir, cache_dir, header_dir, xpt_dir, deps_dir, module, stems):
    +def process(input_dir, inc_paths, cache_dir, header_dir, xpt_dir, deps_dir, module, stems):
         p = IDLParser(outputdir=cache_dir)
     
         xpts = {}
    @@ -40,7 +40,7 @@ def process(input_dir, cache_dir, header_dir, xpt_dir, deps_dir, module, stems):
             idl_data = open(path).read()
     
             idl = p.parse(idl_data, filename=path)
    -        idl.resolve([input_dir], p)
    +        idl.resolve([input_dir] + inc_paths, p)
     
             header_path = os.path.join(header_dir, '%s.h' % stem)
             deps_path = os.path.join(deps_dir, '%s.pp' % stem)
    @@ -81,10 +81,12 @@ def main(argv):
             help='Final module name to use for linked output xpt file.')
         parser.add_argument('idls', nargs='+',
             help='Source .idl file(s). Specified as stems only.')
    +    parser.add_argument('-I', dest='incpath', action='append', default=[],
    +        help='Extra directories where to look for included .idl files.')
     
         args = parser.parse_args(argv)
    -    process(args.inputdir, args.cache_dir, args.headerdir, args.xptdir,
    -        args.depsdir, args.module, args.idls)
    +    process(args.inputdir, args.incpath, args.cache_dir, args.headerdir,
    +        args.xptdir, args.depsdir, args.module, args.idls)
     
     if __name__ == '__main__':
         main(sys.argv[1:])
    diff --git a/xpcom/moz.build b/xpcom/moz.build
    index 143570c421f4..414f467fbf12 100644
    --- a/xpcom/moz.build
    +++ b/xpcom/moz.build
    @@ -6,7 +6,6 @@
     
     PARALLEL_DIRS += [
         'idl-parser',
    -    'xpidl',
     ]
     
     DIRS += [
    diff --git a/xpcom/xpidl/Makefile.in b/xpcom/xpidl/Makefile.in
    index 621a43aceebc..e5ba594380bf 100644
    --- a/xpcom/xpidl/Makefile.in
    +++ b/xpcom/xpidl/Makefile.in
    @@ -3,7 +3,9 @@
     # file, You can obtain one at http://mozilla.org/MPL/2.0/.
     
     export::
    +ifndef LIBXUL_SDK
     	$(call SUBMAKE,xpidl-parser,$(DEPTH)/xpcom/idl-parser)
    +endif
     	$(call py_action,process_install_manifest,$(DIST)/idl $(DEPTH)/_build_manifests/install/dist_idl)
     	$(call SUBMAKE,xpidl,$(DEPTH)/config/makefiles/xpidl)
     
    
    From 08e9003cce1d9f3f2acdde69fd95e26fd84b7029 Mon Sep 17 00:00:00 2001
    From: Mike Hommey 
    Date: Thu, 7 Nov 2013 10:37:44 +0900
    Subject: [PATCH 66/82] Bug 933145 - Skip directories without variables in
     moz.build that are relevant to compile or binaries during those tiers. r=gps
    
    ---
     .../mozbuild/mozbuild/backend/recursivemake.py   | 16 +++++++++++++---
     1 file changed, 13 insertions(+), 3 deletions(-)
    
    diff --git a/python/mozbuild/mozbuild/backend/recursivemake.py b/python/mozbuild/mozbuild/backend/recursivemake.py
    index 2e146bf5a256..1ee71ff8ae6f 100644
    --- a/python/mozbuild/mozbuild/backend/recursivemake.py
    +++ b/python/mozbuild/mozbuild/backend/recursivemake.py
    @@ -664,7 +664,9 @@ class RecursiveMakeBackend(CommonBackend):
                         # the autogenerated one automatically.
                         self.backend_input_files.add(makefile_in)
     
    -                    for skiplist in self._may_skip.values():
    +                    for tier, skiplist in self._may_skip.items():
    +                        if tier in ('compile', 'binaries'):
    +                            continue
                             if bf.relobjdir in skiplist:
                                 skiplist.remove(bf.relobjdir)
                     else:
    @@ -679,8 +681,6 @@ class RecursiveMakeBackend(CommonBackend):
                     with self._write_file(makefile) as fh:
                         bf.environment.create_makefile(fh, stub=stub)
     
    -        self._fill_root_mk()
    -
             # Write out a master list of all IPDL source files.
             ipdl_dir = os.path.join(self.environment.topobjdir, 'ipc', 'ipdl')
             mk = mozmakeutil.Makefile()
    @@ -711,6 +711,8 @@ class RecursiveMakeBackend(CommonBackend):
             with self._write_file(os.path.join(ipdl_dir, 'ipdlsrcs.mk')) as ipdls:
                 mk.dump(ipdls, removal_guard=False)
     
    +        self._may_skip['compile'] -= set(['ipc/ipdl'])
    +
             # Write out master lists of WebIDL source files.
             bindings_dir = os.path.join(self.environment.topobjdir, 'dom', 'bindings')
     
    @@ -744,6 +746,10 @@ class RecursiveMakeBackend(CommonBackend):
             with self._write_file(os.path.join(bindings_dir, 'webidlsrcs.mk')) as webidls:
                 mk.dump(webidls, removal_guard=False)
     
    +        self._may_skip['compile'] -= set(['dom/bindings', 'dom/bindings/test'])
    +
    +        self._fill_root_mk()
    +
             # Write out a dependency file used to determine whether a config.status
             # re-run is needed.
             inputs = sorted(p.replace(os.sep, '/') for p in self.backend_input_files)
    @@ -868,6 +874,10 @@ class RecursiveMakeBackend(CommonBackend):
                 return
     
             affected_tiers = set(obj.affected_tiers)
    +        # Until all SOURCES are really in moz.build, consider all directories
    +        # building binaries to require a pass at compile, too.
    +        if 'binaries' in affected_tiers:
    +            affected_tiers.add('compile')
             if 'compile' in affected_tiers or 'binaries' in affected_tiers:
                 affected_tiers.add('libs')
             if obj.is_tool_dir and 'libs' in affected_tiers:
    
    From 9c6d59da5721a29b9f09c62c2e45e780673088a1 Mon Sep 17 00:00:00 2001
    From: Mike Hommey 
    Date: Thu, 7 Nov 2013 10:37:45 +0900
    Subject: [PATCH 67/82] Bug 934332 - Don't install tests under js/src in
     --with-libxul-sdk builds. r=gps
    
    ---
     Makefile.in | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/Makefile.in b/Makefile.in
    index aa7ded0aae98..ce811dd824e0 100644
    --- a/Makefile.in
    +++ b/Makefile.in
    @@ -106,7 +106,7 @@ $(addprefix install-dist-,$(install_manifests)): install-dist-%: $(install_manif
     .PHONY: install-tests
     install-manifests: install-tests
     install-tests: $(install_manifest_depends)
    -	$(call py_action,process_install_manifest,$(if $(NO_REMOVE),--no-remove )_tests _build_manifests/install/tests js/src/_build_manifests/install/tests)
    +	$(call py_action,process_install_manifest,$(if $(NO_REMOVE),--no-remove )_tests _build_manifests/install/tests $(if $(LIBXUL_SDK),,js/src/_build_manifests/install/tests))
     
     
     # _tests should be purged during cleaning. However, we don't want it purged
    
    From e5c1aa4f98bc6e25363f0b89332985676bb3a02e Mon Sep 17 00:00:00 2001
    From: Mike Hommey 
    Date: Thu, 7 Nov 2013 10:37:45 +0900
    Subject: [PATCH 68/82] Bug 934334 - Fix packager's jar chrome formatter to
     handle resource:// urls. r=gps
    
    ---
     python/mozbuild/mozpack/packager/formats.py | 3 ++-
     1 file changed, 2 insertions(+), 1 deletion(-)
    
    diff --git a/python/mozbuild/mozpack/packager/formats.py b/python/mozbuild/mozpack/packager/formats.py
    index 6864768762a1..c3a8c5644857 100644
    --- a/python/mozbuild/mozpack/packager/formats.py
    +++ b/python/mozbuild/mozpack/packager/formats.py
    @@ -176,7 +176,8 @@ class JarFormatter(FlatFormatter):
             return chromepath, entry
     
         def add_manifest(self, entry):
    -        if isinstance(entry, ManifestChrome):
    +        if isinstance(entry, ManifestChrome) and \
    +                not urlparse(entry.relpath).scheme:
                 chromepath, entry = self._jarize(entry, entry.relpath)
                 assert not self._frozen_chrome
                 self._chrome.add(chromepath)
    
    From 50e2fd01b17dfea8fea50026225805690d7045dc Mon Sep 17 00:00:00 2001
    From: Mike Hommey 
    Date: Thu, 7 Nov 2013 10:37:45 +0900
    Subject: [PATCH 69/82] Bug 935387 - Remove non recursed install targets.
     r=mshal
    
    ---
     b2g/locales/Makefile.in                   | 5 -----
     browser/locales/Makefile.in               | 8 --------
     browser/metro/shell/Makefile.in           | 3 ---
     config/Makefile.in                        | 3 ---
     content/xml/content/src/Makefile.in       | 3 ---
     editor/composer/src/Makefile.in           | 3 ---
     extensions/spellcheck/locales/Makefile.in | 3 ---
     intl/locale/src/Makefile.in               | 3 ---
     intl/locales/Makefile.in                  | 3 ---
     intl/unicharutil/tables/Makefile.in       | 3 ---
     layout/generic/Makefile.in                | 3 ---
     layout/mathml/Makefile.in                 | 3 ---
     layout/style/Makefile.in                  | 3 ---
     layout/svg/Makefile.in                    | 3 ---
     netwerk/test/Makefile.in                  | 2 --
     rdf/tests/dsds/Makefile.in                | 3 ---
     toolkit/xre/Makefile.in                   | 3 ---
     tools/jprof/Makefile.in                   | 3 ---
     xpcom/sample/Makefile.in                  | 3 ---
     xpcom/tests/Makefile.in                   | 3 ---
     xulrunner/app/profile/Makefile.in         | 4 ----
     xulrunner/app/profile/chrome/Makefile.in  | 4 ----
     22 files changed, 74 deletions(-)
    
    diff --git a/b2g/locales/Makefile.in b/b2g/locales/Makefile.in
    index b3b1f85b222d..16ff711c18b1 100644
    --- a/b2g/locales/Makefile.in
    +++ b/b2g/locales/Makefile.in
    @@ -57,11 +57,6 @@ libs::
     	  $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(PREF_PPFLAGS) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) \
     	    $(LOCALE_SRCDIR)/existing-profile-defaults.js > $(FINAL_TARGET)/defaults/existing-profile-defaults.js; \
     	fi
    -install::
    -	@if test -f "$(LOCALE_SRCDIR)/existing-profile-defaults.js"; then \
    -	  $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(PREF_PPFLAGS) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) \
    -	    $(LOCALE_SRCDIR)/existing-profile-defaults.js > $(DESTDIR)$(mozappdir)/defaults/existing-profile-defaults.js; \
    -	fi
     
     NO_JA_JP_MAC_AB_CD := $(if $(filter ja-JP-mac, $(AB_CD)),ja,$(AB_CD))
     
    diff --git a/browser/locales/Makefile.in b/browser/locales/Makefile.in
    index 570485b82a1d..c6294145feb1 100644
    --- a/browser/locales/Makefile.in
    +++ b/browser/locales/Makefile.in
    @@ -120,14 +120,6 @@ libs:: $(addprefix generic/profile/,$(PROFILE_FILES))
     libs:: $(call MERGE_FILES,$(addprefix profile/chrome/,$(PROFILE_CHROME)))
     	$(SYSINSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)/defaults/profile/chrome
     
    -install:: $(DESTDIR)$(mozappdir)/defaults/profile/bookmarks.html ;
    -
    -install:: $(addprefix generic/profile/,$(PROFILE_FILES))
    -	$(SYSINSTALL) $(IFLAGS1) $^ $(DESTDIR)$(mozappdir)/defaults/profile
    -
    -install:: $(call MERGE_FILES,$(addprefix profile/chrome/,$(PROFILE_CHROME)))
    -	$(SYSINSTALL) $(IFLAGS1) $^ $(DESTDIR)$(mozappdir)/defaults/profile/chrome
    -
     # metro build calls back here for search engine plugins
     searchplugins: $(addprefix $(FINAL_TARGET)/searchplugins/,$(SEARCHPLUGINS))
     .PHONY: searchplugins
    diff --git a/browser/metro/shell/Makefile.in b/browser/metro/shell/Makefile.in
    index ce9f1e6fc965..d3f02b3985ab 100644
    --- a/browser/metro/shell/Makefile.in
    +++ b/browser/metro/shell/Makefile.in
    @@ -4,6 +4,3 @@
     
     export::
     	$(NSINSTALL) $(srcdir)/resources.pri $(DIST)/bin
    -
    -install::
    -	$(NSINSTALL) $(srcdir)/resources.pri $(DIST)/bin
    diff --git a/config/Makefile.in b/config/Makefile.in
    index 995ea67c6dd5..8668fbcf942e 100644
    --- a/config/Makefile.in
    +++ b/config/Makefile.in
    @@ -111,9 +111,6 @@ GARBAGE += $(STL_WRAPPERS_SENTINEL)
     GARBAGE_DIRS += stl_wrappers
     endif
     
    -install::
    -	$(SYSINSTALL) $(IFLAGS1) $(DEPTH)/mozilla-config.h $(DESTDIR)$(includedir)
    -
     GARBAGE += \
       $(FINAL_LINK_COMPS) $(FINAL_LINK_LIBS) $(FINAL_LINK_COMP_NAMES) buildid $(srcdir)/*.pyc *.pyc
     
    diff --git a/content/xml/content/src/Makefile.in b/content/xml/content/src/Makefile.in
    index 0b7085f0027d..83009b2fac70 100644
    --- a/content/xml/content/src/Makefile.in
    +++ b/content/xml/content/src/Makefile.in
    @@ -14,6 +14,3 @@ EXPORT_RESOURCE_CONTENT = \
     		$(NULL)
     libs::
     	$(INSTALL) $(EXPORT_RESOURCE_CONTENT) $(DIST)/bin/res/dtd
    -
    -install::
    -	$(SYSINSTALL) $(IFLAGS1) $(EXPORT_RESOURCE_CONTENT) $(DESTDIR)$(mozappdir)/res/dtd
    diff --git a/editor/composer/src/Makefile.in b/editor/composer/src/Makefile.in
    index 6e94b8ea518c..4a8c8475e9f0 100644
    --- a/editor/composer/src/Makefile.in
    +++ b/editor/composer/src/Makefile.in
    @@ -30,6 +30,3 @@ _FILES = \
     
     libs::
     	$(INSTALL) $(_FILES) $(DIST)/bin/res
    -
    -install::
    -	$(SYSINSTALL) $(IFLAGS1) $(_FILES) $(DESTDIR)$(mozappdir)/res
    diff --git a/extensions/spellcheck/locales/Makefile.in b/extensions/spellcheck/locales/Makefile.in
    index e31cf9b921e8..4faca1503b72 100644
    --- a/extensions/spellcheck/locales/Makefile.in
    +++ b/extensions/spellcheck/locales/Makefile.in
    @@ -11,7 +11,4 @@ DICTIONARY_FILES = $(strip $(wildcard $(LOCALE_SRCDIR)/hunspell/*.dic) $(wildcar
     ifneq (,$(DICTIONARY_FILES))
     libs::
     	$(INSTALL)  $(DICTIONARY_FILES) $(FINAL_TARGET)/dictionaries
    -
    -install::
    -	$(SYSINSTALL) $(IFLAGS1) $(DICTIONARY_FILES) $(DESTDIR)$(mozappdir)/dictionaries
     endif
    diff --git a/intl/locale/src/Makefile.in b/intl/locale/src/Makefile.in
    index 18a8c686093f..dd3d51079e1a 100644
    --- a/intl/locale/src/Makefile.in
    +++ b/intl/locale/src/Makefile.in
    @@ -30,6 +30,3 @@ GARBAGE += \
     
     libs::
     	$(INSTALL) $(EXPORT_RESOURCE) $(DIST)/bin/res
    -
    -install::
    -	$(SYSINSTALL) $(IFLAGS1) $(EXPORT_RESOURCE) $(DESTDIR)$(mozappdir)/res
    diff --git a/intl/locales/Makefile.in b/intl/locales/Makefile.in
    index 850178990fb5..15c036d47d69 100644
    --- a/intl/locales/Makefile.in
    +++ b/intl/locales/Makefile.in
    @@ -11,7 +11,4 @@ PATTERN_FILES = $(strip $(wildcard $(srcdir)/*/hyphenation/*.dic))
     ifneq (,$(PATTERN_FILES))
     libs::
     	$(INSTALL)  $(PATTERN_FILES) $(FINAL_TARGET)/hyphenation
    -
    -install::
    -	$(SYSINSTALL) $(IFLAGS1) $(PATTERN_FILES) $(DESTDIR)$(mozappdir)/hyphenation
     endif
    diff --git a/intl/unicharutil/tables/Makefile.in b/intl/unicharutil/tables/Makefile.in
    index f4e2c26c732d..30e8a2fa75df 100644
    --- a/intl/unicharutil/tables/Makefile.in
    +++ b/intl/unicharutil/tables/Makefile.in
    @@ -21,6 +21,3 @@ endif
     
     libs:: $(_PROP_TABLES)
     	$(INSTALL) $^ $(DIST)/bin/res/entityTables
    -
    -install:: $(_PROP_TABLES)
    -	$(SYSINSTALL) $(IFLAGS1) $^ $(DESTDIR)$(mozappdir)/res/entityTables
    diff --git a/layout/generic/Makefile.in b/layout/generic/Makefile.in
    index 8fdfa780e7f6..6ad05356c7e8 100644
    --- a/layout/generic/Makefile.in
    +++ b/layout/generic/Makefile.in
    @@ -35,6 +35,3 @@ endif
     
     libs::
     	$(INSTALL) $(RESOURCES_HTML) $(DIST)/bin/res/html
    -
    -install::
    -	$(SYSINSTALL) $(IFLAGS1) $(RESOURCES_HTML) $(DESTDIR)$(mozappdir)/res/html
    diff --git a/layout/mathml/Makefile.in b/layout/mathml/Makefile.in
    index 380af3c038f5..381b1577908e 100644
    --- a/layout/mathml/Makefile.in
    +++ b/layout/mathml/Makefile.in
    @@ -34,9 +34,6 @@ endif
     libs:: $(font_properties)
     	$(INSTALL) $^ $(DIST)/bin/res/fonts
     
    -install:: $(font_properties)
    -	$(SYSINSTALL) $(IFLAGS1) $^ $(DESTDIR)$(mozappdir)/res/fonts
    -
     math_properties = mathfont.properties
     
     $(DIST)/bin/res/fonts/$(math_properties) $(DESTDIR)$(mozappdir)/res/fonts/$(math_properties): $(math_properties) Makefile
    diff --git a/layout/style/Makefile.in b/layout/style/Makefile.in
    index 765d7b6d42cc..7abaadd31229 100644
    --- a/layout/style/Makefile.in
    +++ b/layout/style/Makefile.in
    @@ -43,6 +43,3 @@ GARBAGE	+= \
     
     libs:: $(_FILES)
     	$(INSTALL) $^ $(DIST)/bin/res
    -
    -install:: $(_FILES)
    -	$(SYSINSTALL) $(IFLAGS1) $^ $(DESTDIR)$(mozappdir)/res
    diff --git a/layout/svg/Makefile.in b/layout/svg/Makefile.in
    index 028bc3397462..a11a0ae86cea 100644
    --- a/layout/svg/Makefile.in
    +++ b/layout/svg/Makefile.in
    @@ -17,6 +17,3 @@ LOCAL_INCLUDES	= \
     
     libs::
     	$(INSTALL) $(srcdir)/svg.css $(DIST)/bin/res
    -
    -install::
    -	$(SYSINSTALL) $(IFLAGS1) $(srcdir)/svg.css $(DESTDIR)$(mozappdir)/res
    diff --git a/netwerk/test/Makefile.in b/netwerk/test/Makefile.in
    index 82bad2f537e9..5854f1d14fef 100644
    --- a/netwerk/test/Makefile.in
    +++ b/netwerk/test/Makefile.in
    @@ -22,8 +22,6 @@ _RES_FILES 	= urlparse.dat \
     		  $(NULL)
     libs:: $(_RES_FILES)
     	$(INSTALL) $^ $(DIST)/bin/res
    -install:: $(_RES_FILES)
    -	$(SYSINSTALL) $(IFLAGS1) $^ $(DESTDIR)$(mozappdir)/res
     
     # One of the xpcshell unit tests needs this file, so make sure it winds
     #  up in the test directory.
    diff --git a/rdf/tests/dsds/Makefile.in b/rdf/tests/dsds/Makefile.in
    index 2da6b49bcaa2..1ab3013cc91c 100644
    --- a/rdf/tests/dsds/Makefile.in
    +++ b/rdf/tests/dsds/Makefile.in
    @@ -24,6 +24,3 @@ GARBAGE		+= $(addprefix $(SAMPLES_DIR)/, $(RESOURCE_SAMPLES))
     
     libs::
     	$(INSTALL) $(addprefix $(srcdir)/,$(RESOURCE_SAMPLES)) $(SAMPLES_DIR)
    -
    -install:: $(RESOURCE_SAMPLES)
    -	$(SYSINSTALL) $(IFLAGS1) $^ $(DESTDIR)$(mozappdir)/res/samples/rdf
    diff --git a/toolkit/xre/Makefile.in b/toolkit/xre/Makefile.in
    index e8b609f6840b..b53a148b4658 100644
    --- a/toolkit/xre/Makefile.in
    +++ b/toolkit/xre/Makefile.in
    @@ -189,6 +189,3 @@ GARBAGE += platform.ini
     
     libs:: platform.ini
     	$(INSTALL) $^ $(DIST)/bin
    -
    -install::
    -	$(INSTALL) $(IFLAGS1) $^ $(DESTDIR)$(mozappdir)
    diff --git a/tools/jprof/Makefile.in b/tools/jprof/Makefile.in
    index f94a0355f459..e22c3029ace9 100644
    --- a/tools/jprof/Makefile.in
    +++ b/tools/jprof/Makefile.in
    @@ -18,6 +18,3 @@ include $(topsrcdir)/config/rules.mk
     INCLUDES += \
     	-I$(srcdir)/stub \
     	$(NULL)
    -
    -install::
    -	$(INSTALL) -m 555 $(HELPER_SCRIPTS)  $(DIST)/bin
    diff --git a/xpcom/sample/Makefile.in b/xpcom/sample/Makefile.in
    index 84da4e0a669a..c4e8b6328e77 100644
    --- a/xpcom/sample/Makefile.in
    +++ b/xpcom/sample/Makefile.in
    @@ -32,6 +32,3 @@ include $(topsrcdir)/config/rules.mk
     
     libs:: $(TARGETS)
     	$(INSTALL) $(srcdir)/xpconnect-sample.html $(DIST)/bin/res/samples
    -
    -install:: $(TARGETS)
    -	$(SYSINSTALL) $(IFLAGS1) $(srcdir)/xpconnect-sample.html $(DESTDIR)$(mozappdir)/res/samples
    diff --git a/xpcom/tests/Makefile.in b/xpcom/tests/Makefile.in
    index b256ac817601..3d02746ead5b 100644
    --- a/xpcom/tests/Makefile.in
    +++ b/xpcom/tests/Makefile.in
    @@ -26,9 +26,6 @@ ifneq (,$(SIMPLE_PROGRAMS))
     	$(INSTALL) $(SIMPLE_PROGRAMS) $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit
     endif
     
    -install::
    -	$(SYSINSTALL) $(IFLAGS1) $(srcdir)/test.properties $(DESTDIR)$(mozappdir)/res
    -
     ifeq (,$(filter-out WINNT os2-emx, $(HOST_OS_ARCH)))
     getnativepath = $(call normalizepath,$(1))
     else
    diff --git a/xulrunner/app/profile/Makefile.in b/xulrunner/app/profile/Makefile.in
    index adc738d3495f..62c92c89cdc2 100644
    --- a/xulrunner/app/profile/Makefile.in
    +++ b/xulrunner/app/profile/Makefile.in
    @@ -12,7 +12,3 @@ FILES := \
     libs:: $(FILES)
     	$(INSTALL) $^ $(DIST)/bin/defaults/profile
     	$(INSTALL) $^ $(DIST)/bin/defaults/profile/US
    -
    -install:: $(FILES)
    -	$(SYSINSTALL) $(IFLAGS1) $^ $(DESTDIR)$(mozappdir)/defaults/profile
    -	$(SYSINSTALL) $(IFLAGS1) $^ $(DESTDIR)$(mozappdir)/defaults/profile/US
    diff --git a/xulrunner/app/profile/chrome/Makefile.in b/xulrunner/app/profile/chrome/Makefile.in
    index bda2018d793f..67e8ce983d82 100644
    --- a/xulrunner/app/profile/chrome/Makefile.in
    +++ b/xulrunner/app/profile/chrome/Makefile.in
    @@ -15,7 +15,3 @@ FILES := $(addprefix $(srcdir)/, $(FILES))
     libs::
     	$(INSTALL) $(FILES) $(DIST)/bin/defaults/profile/chrome
     	$(INSTALL) $(FILES) $(DIST)/bin/defaults/profile/US/chrome
    -
    -install::
    -	$(SYSINSTALL) $(IFLAGS1) $(FILES) $(DESTDIR)$(mozappdir)/defaults/profile/chrome
    -	$(NSINSTALL)  -t $(IFLAGS1) $(FILES) $(DESTDIR)$(mozappdir)/defaults/profile/US/chrome
    
    From f932a1fe70519cd77479b55d1a94778131c832ea Mon Sep 17 00:00:00 2001
    From: Mike Hommey 
    Date: Thu, 7 Nov 2013 10:37:45 +0900
    Subject: [PATCH 70/82] Bug 862770 - Fix --disable-compile-environment a
     little. r=gps
    
    --HG--
    rename : config/makefiles/target_libs.mk => config/makefiles/target_binaries.mk
    rename : js/src/config/makefiles/target_libs.mk => js/src/config/makefiles/target_binaries.mk
    ---
     Makefile.in                                   | 23 +++++++++++--------
     browser/app/Makefile.in                       |  2 ++
     build/unix/elfhack/Makefile.in                |  4 +++-
     config/Makefile.in                            |  4 ++++
     .../{target_libs.mk => target_binaries.mk}    |  0
     config/recurse.mk                             |  7 ++++++
     config/rules.mk                               | 22 +++++++++++++++++-
     configure.in                                  | 11 +++++----
     .../{target_libs.mk => target_binaries.mk}    |  0
     js/src/config/recurse.mk                      |  7 ++++++
     js/src/config/rules.mk                        | 22 +++++++++++++++++-
     js/src/configure.in                           |  6 ++++-
     moz.build                                     |  3 +--
     testing/gtest/Makefile.in                     |  2 ++
     toolkit/library/Makefile.in                   |  4 ++--
     toolkit/mozapps/update/tests/Makefile.in      |  2 ++
     toolkit/toolkit.mozbuild                      | 13 ++++++-----
     widget/gonk/libdisplay/moz.build              |  2 +-
     xpcom/ds/moz.build                            |  2 +-
     xpcom/reflect/xptcall/src/md/unix/moz.build   |  2 +-
     20 files changed, 107 insertions(+), 31 deletions(-)
     rename config/makefiles/{target_libs.mk => target_binaries.mk} (100%)
     rename js/src/config/makefiles/{target_libs.mk => target_binaries.mk} (100%)
    
    diff --git a/Makefile.in b/Makefile.in
    index ce811dd824e0..f5cc46a06b35 100644
    --- a/Makefile.in
    +++ b/Makefile.in
    @@ -17,13 +17,16 @@ export TOPLEVEL_BUILD := 1
     
     default::
     
    -ifdef COMPILE_ENVIRONMENT
     include $(topsrcdir)/$(MOZ_BUILD_APP)/build.mk
    -endif
    -
     
     include $(topsrcdir)/config/config.mk
     
    +ifndef LIBXUL_SDK
    +ifdef COMPILE_ENVIRONMENT
    +BUILD_JS = 1
    +endif
    +endif
    +
     GARBAGE_DIRS += dist _javagen _profile staticlib
     DIST_GARBAGE = config.cache config.log config.status* config-defs.h \
        config/autoconf.mk \
    @@ -35,7 +38,7 @@ ifndef MOZ_PROFILE_USE
     # We need to explicitly put backend.RecursiveMakeBackend here
     # otherwise the rule in rules.mk doesn't run early enough.
     libs binaries export tools:: CLOBBER $(topsrcdir)/configure config.status backend.RecursiveMakeBackend
    -ifndef LIBXUL_SDK
    +ifdef BUILD_JS
     libs binaries export tools:: js-config-status
     endif
     endif
    @@ -78,7 +81,7 @@ include backend.RecursiveMakeBackend.pp
     
     default:: backend.RecursiveMakeBackend
     
    -ifndef LIBXUL_SDK
    +ifdef BUILD_JS
     .PHONY: js-config-status
     js-config-status:
     	$(call SUBMAKE,backend.RecursiveMakeBackend,js/src,1)
    @@ -92,7 +95,7 @@ install_manifest_depends = \
       backend.RecursiveMakeBackend \
       $(NULL)
     
    -ifndef LIBXUL_SDK
    +ifdef BUILD_JS
     install_manifest_depends += js-config-status
     endif
     
    @@ -101,12 +104,12 @@ install-manifests: $(addprefix install-dist-,$(install_manifests))
     
     .PHONY: $(addprefix install-dist-,$(install_manifests))
     $(addprefix install-dist-,$(install_manifests)): install-dist-%: $(install_manifest_depends)
    -	$(call py_action,process_install_manifest,$(if $(NO_REMOVE),--no-remove )$(DIST)/$* _build_manifests/install/dist_$* $(if $(LIBXUL_SDK),,js/src/_build_manifests/install/dist_$*))
    +	$(call py_action,process_install_manifest,$(if $(NO_REMOVE),--no-remove )$(DIST)/$* _build_manifests/install/dist_$* $(if $(BUILD_JS),js/src/_build_manifests/install/dist_$*))
     
     .PHONY: install-tests
     install-manifests: install-tests
     install-tests: $(install_manifest_depends)
    -	$(call py_action,process_install_manifest,$(if $(NO_REMOVE),--no-remove )_tests _build_manifests/install/tests $(if $(LIBXUL_SDK),,js/src/_build_manifests/install/tests))
    +	$(call py_action,process_install_manifest,$(if $(NO_REMOVE),--no-remove )_tests _build_manifests/install/tests $(if $(BUILD_JS),js/src/_build_manifests/install/tests))
     
     
     # _tests should be purged during cleaning. However, we don't want it purged
    @@ -142,7 +145,7 @@ include $(topsrcdir)/testing/testsuite-targets.mk
     endif
     
     default all::
    -	$(call BUILDSTATUS,TIERS export $(if $(MOZ_PSEUDO_DERECURSE),compile )libs tools)
    +	$(call BUILDSTATUS,TIERS export $(if $(COMPILE_ENVIRONMENT),$(if $(MOZ_PSEUDO_DERECURSE),compile ))libs tools)
     
     include $(topsrcdir)/config/rules.mk
     
    @@ -247,7 +250,7 @@ scheck::
     	@relcount=`find $(DIST)/bin -name "*.so" | xargs objdump -R | grep R_386_PC32 | wc -l` && if test $$relcount -gt 0; then echo "FAILED: R_386_PC32 relocations detected in a shared library.  Did you use a system header without adding it to config/system-headers?"; exit 1; else echo "PASSED"; fi
     endif
     
    -ifndef LIBXUL_SDK
    +ifdef BUILD_JS
     js/src/Makefile: subsrcdir := js/src
     
     ifdef ENABLE_TESTS
    diff --git a/browser/app/Makefile.in b/browser/app/Makefile.in
    index 838b32a2d62d..f495df5dd169 100644
    --- a/browser/app/Makefile.in
    +++ b/browser/app/Makefile.in
    @@ -120,8 +120,10 @@ endif #}
     
     ifneq (,$(filter-out OS2 WINNT,$(OS_ARCH)))
     
    +ifdef COMPILE_ENVIRONMENT
     libs:: 
     	cp -p $(MOZ_APP_NAME)$(BIN_SUFFIX) $(DIST)/bin/$(MOZ_APP_NAME)-bin$(BIN_SUFFIX)
    +endif
     
     GARBAGE += $(addprefix $(FINAL_TARGET)/defaults/pref/, firefox.js)
     
    diff --git a/build/unix/elfhack/Makefile.in b/build/unix/elfhack/Makefile.in
    index c8ad32877f75..1421c4e80047 100644
    --- a/build/unix/elfhack/Makefile.in
    +++ b/build/unix/elfhack/Makefile.in
    @@ -40,9 +40,10 @@ test-ctors$(DLL_SUFFIX): DT_TYPE=INIT
     
     GARBAGE += test-array$(DLL_SUFFIX) test-ctors$(DLL_SUFFIX) test-array$(DLL_SUFFIX).bak test-ctors$(DLL_SUFFIX).bak
     
    +ifndef CROSS_COMPILE
    +ifdef COMPILE_ENVIRONMENT
     libs:: test-array$(DLL_SUFFIX) test-ctors$(DLL_SUFFIX)
     
    -ifndef CROSS_COMPILE
     dummy: dummy.$(OBJ_SUFFIX)
     	$(CC) -o $@ $^ $(LDFLAGS)
     
    @@ -53,5 +54,6 @@ libs:: dummy
     
     GARBAGE += dummy
     endif
    +endif
     
     test.$(OBJ_SUFFIX): CFLAGS := -O0
    diff --git a/config/Makefile.in b/config/Makefile.in
    index 8668fbcf942e..9ff0bd2252c5 100644
    --- a/config/Makefile.in
    +++ b/config/Makefile.in
    @@ -9,10 +9,12 @@
     MOZ_LIBSTDCXX_HOST_VERSION =
     
     ifndef CROSS_COMPILE
    +ifdef COMPILE_ENVIRONMENT
     ifdef USE_ELF_DYNSTR_GC
     export:: elf-dynstr-gc
     endif
     endif
    +endif
     
     # IMPORTANT: Disable NSBUILDROOT for this directory only, otherwise we have
     # a recursive rule for finding nsinstall and the Perl scripts.
    @@ -27,6 +29,7 @@ endif
     include $(topsrcdir)/config/config.mk
     
     ifneq (WINNT,$(HOST_OS_ARCH))
    +ifdef COMPILE_ENVIRONMENT
     # Ensure nsinstall is atomically created
     nsinstall$(HOST_BIN_SUFFIX): $(HOST_PROGRAM)
     	cp $^ $@.tmp
    @@ -37,6 +40,7 @@ NSINSTALL_DEST := $(DIST)/bin
     NSINSTALL_TARGET := export
     INSTALL_TARGETS += NSINSTALL
     endif
    +endif
     
     HEADERS_FILES = \
     	$(DEPTH)/mozilla-config.h \
    diff --git a/config/makefiles/target_libs.mk b/config/makefiles/target_binaries.mk
    similarity index 100%
    rename from config/makefiles/target_libs.mk
    rename to config/makefiles/target_binaries.mk
    diff --git a/config/recurse.mk b/config/recurse.mk
    index c6f90b153f27..9b2c5fb75136 100644
    --- a/config/recurse.mk
    +++ b/config/recurse.mk
    @@ -112,6 +112,7 @@ ifeq ($(CURRENT_TIER),export)
     $(addsuffix /$(CURRENT_TIER),$(filter-out config,$(CURRENT_DIRS))): config/$(CURRENT_TIER)
     endif
     
    +ifdef COMPILE_ENVIRONMENT
     ifneq (,$(filter libs binaries,$(CURRENT_TIER)))
     # When doing a "libs" build, target_libs.mk ensures the interesting dependency data
     # is available in the "binaries" stamp. Once recursion is done, aggregate all that
    @@ -139,6 +140,8 @@ endif
     
     DIST_GARBAGE += binaries-deps.mk binaries-deps
     
    +endif
    +
     else
     
     # Don't recurse if MAKELEVEL is NO_RECURSE_MAKELEVEL as defined above, but
    @@ -209,6 +212,8 @@ endif
     endif
     endif
     
    +ifdef COMPILE_ENVIRONMENT
    +
     # Aggregate all dependency files relevant to a binaries build except in
     # the mozilla top-level directory.
     ifneq (_.,$(recurse_targets)_$(DEPTH))
    @@ -227,4 +232,6 @@ ifneq (_.,$(recurse_targets)_$(DEPTH))
     	@$(if $(or $(recurse_targets),$^),$(call py_action,link_deps,-o binaries --group-all $(if $(want_abspaths),--abspaths )--topsrcdir $(topsrcdir) --topobjdir $(DEPTH) --dist $(DIST) $(ALL_DEP_FILES)))
     endif
     
    +endif
    +
     endif # ifdef MOZ_PSEUDO_DERECURSE
    diff --git a/config/rules.mk b/config/rules.mk
    index 3caef33c53c3..3728cf28c023 100644
    --- a/config/rules.mk
    +++ b/config/rules.mk
    @@ -122,6 +122,7 @@ endif
     endif
     
     ifdef CPP_UNIT_TESTS
    +ifdef COMPILE_ENVIRONMENT
     
     # Compile the tests to $(DIST)/bin.  Make lots of niceties available by default
     # through TestHarness.h, by modifying the list of includes and the libs against
    @@ -153,6 +154,7 @@ cppunittests-remote:
     		echo "please prepare your host with environment variables for TEST_DEVICE"; \
     	fi
     
    +endif # COMPILE_ENVIRONMENT
     endif # CPP_UNIT_TESTS
     
     .PHONY: check
    @@ -303,6 +305,7 @@ EXCLUDED_OBJS := $(SIMPLE_PROGRAMS:$(BIN_SUFFIX)=.$(OBJ_SUFFIX))
     SIMPLE_PROGRAMS :=
     endif
     
    +ifdef COMPILE_ENVIRONMENT
     ifndef TARGETS
     TARGETS			= $(LIBRARY) $(SHARED_LIBRARY) $(PROGRAM) $(SIMPLE_PROGRAMS) $(HOST_LIBRARY) $(HOST_PROGRAM) $(HOST_SIMPLE_PROGRAMS)
     endif
    @@ -328,6 +331,19 @@ ifndef HOST_OBJS
     _HOST_OBJS = $(HOST_COBJS) $(HOST_CPPOBJS) $(HOST_CMOBJS) $(HOST_CMMOBJS)
     HOST_OBJS = $(strip $(_HOST_OBJS))
     endif
    +else
    +LIBRARY :=
    +SHARED_LIBRARY :=
    +IMPORT_LIBRARY :=
    +REAL_LIBRARY :=
    +PROGRAM :=
    +SIMPLE_PROGRAMS :=
    +HOST_LIBRARY :=
    +HOST_PROGRAM :=
    +HOST_SIMPLE_PROGRAMS :=
    +SDK_BINARY := $(filter %.py,$(SDK_BINARY))
    +SDK_LIBRARY :=
    +endif
     
     ALL_TRASH = \
     	$(GARBAGE) $(TARGETS) $(OBJS) $(PROGOBJS) LOGS TAGS a.out \
    @@ -613,7 +629,9 @@ ifndef SUPPRESS_DEFAULT_RULES
     default all::
     	$(MAKE) export
     ifdef MOZ_PSEUDO_DERECURSE
    +ifdef COMPILE_ENVIRONMENT
     	$(MAKE) compile
    +endif
     endif
     	$(MAKE) libs
     	$(MAKE) tools
    @@ -642,11 +660,13 @@ HOST_LIBS_DEPS = $(filter %.$(LIB_SUFFIX),$(HOST_LIBS))
     GLOBAL_DEPS += Makefile $(DEPTH)/config/autoconf.mk $(topsrcdir)/config/config.mk
     
     ##############################################
    +ifdef COMPILE_ENVIRONMENT
     OBJ_TARGETS = $(OBJS) $(PROGOBJS) $(HOST_OBJS) $(HOST_PROGOBJS)
     
     compile:: $(OBJ_TARGETS)
     
    -include $(topsrcdir)/config/makefiles/target_libs.mk
    +include $(topsrcdir)/config/makefiles/target_binaries.mk
    +endif
     
     ifdef IS_TOOL_DIR
     # One would think "tools:: libs" would work, but it turns out that combined with
    diff --git a/configure.in b/configure.in
    index f135c6475bbb..4cb9f733dd10 100644
    --- a/configure.in
    +++ b/configure.in
    @@ -2498,9 +2498,10 @@ esac
     if test -z "$COMPILE_ENVIRONMENT"; then
         SKIP_COMPILER_CHECKS=1
         SKIP_LIBRARY_CHECKS=1
    +else
    +    MOZ_COMPILER_OPTS
     fi
     
    -MOZ_COMPILER_OPTS
     if test -z "$SKIP_COMPILER_CHECKS"; then
     dnl Checks for typedefs, structures, and compiler characteristics.
     dnl ========================================================
    @@ -7179,7 +7180,7 @@ if test "$USE_ELF_HACK" = 1; then
         esac
     fi
     
    -if test -n "$USE_ELF_HACK"; then
    +if test -n "$COMPILE_ENVIRONMENT" -a -n "$USE_ELF_HACK"; then
         dnl PT_GNU_RELRO segment makes the dynamic linker set a read-only flag on
         dnl memory addresses it maps to. The result is that by the time elfhack
         dnl kicks in, it is not possible to apply relocations because of that,
    @@ -7874,7 +7875,9 @@ AC_SUBST(MOZ_PIXMAN_CFLAGS)
     AC_SUBST(MOZ_PIXMAN_LIBS)
     
     # Check for headers defining standard int types.
    -MOZ_CHECK_HEADERS(stdint.h inttypes.h sys/int_types.h)
    +if test -n "$COMPILE_ENVIRONMENT"; then
    +    MOZ_CHECK_HEADERS(stdint.h inttypes.h sys/int_types.h)
    +fi
     
     if test "$MOZ_TREE_CAIRO"; then
         MOZ_CAIRO_CFLAGS='-I$(LIBXUL_DIST)/include/cairo'
    @@ -8661,6 +8664,7 @@ AC_SUBST(MOZ_FOLD_LIBS)
     AC_SUBST(MOZ_ENABLE_SZIP)
     AC_SUBST(MOZ_SZIP_FLAGS)
     
    +if test -n "$COMPILE_ENVIRONMENT"; then
     AC_MSG_CHECKING([for posix_fallocate])
     AC_TRY_LINK([#define _XOPEN_SOURCE 600
       #include ],
    @@ -8676,7 +8680,6 @@ else
     fi
     
     dnl Check for missing components
    -if test "$COMPILE_ENVIRONMENT"; then
     if test "$MOZ_X11"; then
         if test "$WITHOUT_X11"; then
             AC_MSG_ERROR([--without-x specified and MOZ_X11 still defined])
    diff --git a/js/src/config/makefiles/target_libs.mk b/js/src/config/makefiles/target_binaries.mk
    similarity index 100%
    rename from js/src/config/makefiles/target_libs.mk
    rename to js/src/config/makefiles/target_binaries.mk
    diff --git a/js/src/config/recurse.mk b/js/src/config/recurse.mk
    index c6f90b153f27..9b2c5fb75136 100644
    --- a/js/src/config/recurse.mk
    +++ b/js/src/config/recurse.mk
    @@ -112,6 +112,7 @@ ifeq ($(CURRENT_TIER),export)
     $(addsuffix /$(CURRENT_TIER),$(filter-out config,$(CURRENT_DIRS))): config/$(CURRENT_TIER)
     endif
     
    +ifdef COMPILE_ENVIRONMENT
     ifneq (,$(filter libs binaries,$(CURRENT_TIER)))
     # When doing a "libs" build, target_libs.mk ensures the interesting dependency data
     # is available in the "binaries" stamp. Once recursion is done, aggregate all that
    @@ -139,6 +140,8 @@ endif
     
     DIST_GARBAGE += binaries-deps.mk binaries-deps
     
    +endif
    +
     else
     
     # Don't recurse if MAKELEVEL is NO_RECURSE_MAKELEVEL as defined above, but
    @@ -209,6 +212,8 @@ endif
     endif
     endif
     
    +ifdef COMPILE_ENVIRONMENT
    +
     # Aggregate all dependency files relevant to a binaries build except in
     # the mozilla top-level directory.
     ifneq (_.,$(recurse_targets)_$(DEPTH))
    @@ -227,4 +232,6 @@ ifneq (_.,$(recurse_targets)_$(DEPTH))
     	@$(if $(or $(recurse_targets),$^),$(call py_action,link_deps,-o binaries --group-all $(if $(want_abspaths),--abspaths )--topsrcdir $(topsrcdir) --topobjdir $(DEPTH) --dist $(DIST) $(ALL_DEP_FILES)))
     endif
     
    +endif
    +
     endif # ifdef MOZ_PSEUDO_DERECURSE
    diff --git a/js/src/config/rules.mk b/js/src/config/rules.mk
    index 3caef33c53c3..3728cf28c023 100644
    --- a/js/src/config/rules.mk
    +++ b/js/src/config/rules.mk
    @@ -122,6 +122,7 @@ endif
     endif
     
     ifdef CPP_UNIT_TESTS
    +ifdef COMPILE_ENVIRONMENT
     
     # Compile the tests to $(DIST)/bin.  Make lots of niceties available by default
     # through TestHarness.h, by modifying the list of includes and the libs against
    @@ -153,6 +154,7 @@ cppunittests-remote:
     		echo "please prepare your host with environment variables for TEST_DEVICE"; \
     	fi
     
    +endif # COMPILE_ENVIRONMENT
     endif # CPP_UNIT_TESTS
     
     .PHONY: check
    @@ -303,6 +305,7 @@ EXCLUDED_OBJS := $(SIMPLE_PROGRAMS:$(BIN_SUFFIX)=.$(OBJ_SUFFIX))
     SIMPLE_PROGRAMS :=
     endif
     
    +ifdef COMPILE_ENVIRONMENT
     ifndef TARGETS
     TARGETS			= $(LIBRARY) $(SHARED_LIBRARY) $(PROGRAM) $(SIMPLE_PROGRAMS) $(HOST_LIBRARY) $(HOST_PROGRAM) $(HOST_SIMPLE_PROGRAMS)
     endif
    @@ -328,6 +331,19 @@ ifndef HOST_OBJS
     _HOST_OBJS = $(HOST_COBJS) $(HOST_CPPOBJS) $(HOST_CMOBJS) $(HOST_CMMOBJS)
     HOST_OBJS = $(strip $(_HOST_OBJS))
     endif
    +else
    +LIBRARY :=
    +SHARED_LIBRARY :=
    +IMPORT_LIBRARY :=
    +REAL_LIBRARY :=
    +PROGRAM :=
    +SIMPLE_PROGRAMS :=
    +HOST_LIBRARY :=
    +HOST_PROGRAM :=
    +HOST_SIMPLE_PROGRAMS :=
    +SDK_BINARY := $(filter %.py,$(SDK_BINARY))
    +SDK_LIBRARY :=
    +endif
     
     ALL_TRASH = \
     	$(GARBAGE) $(TARGETS) $(OBJS) $(PROGOBJS) LOGS TAGS a.out \
    @@ -613,7 +629,9 @@ ifndef SUPPRESS_DEFAULT_RULES
     default all::
     	$(MAKE) export
     ifdef MOZ_PSEUDO_DERECURSE
    +ifdef COMPILE_ENVIRONMENT
     	$(MAKE) compile
    +endif
     endif
     	$(MAKE) libs
     	$(MAKE) tools
    @@ -642,11 +660,13 @@ HOST_LIBS_DEPS = $(filter %.$(LIB_SUFFIX),$(HOST_LIBS))
     GLOBAL_DEPS += Makefile $(DEPTH)/config/autoconf.mk $(topsrcdir)/config/config.mk
     
     ##############################################
    +ifdef COMPILE_ENVIRONMENT
     OBJ_TARGETS = $(OBJS) $(PROGOBJS) $(HOST_OBJS) $(HOST_PROGOBJS)
     
     compile:: $(OBJ_TARGETS)
     
    -include $(topsrcdir)/config/makefiles/target_libs.mk
    +include $(topsrcdir)/config/makefiles/target_binaries.mk
    +endif
     
     ifdef IS_TOOL_DIR
     # One would think "tools:: libs" would work, but it turns out that combined with
    diff --git a/js/src/configure.in b/js/src/configure.in
    index 1815b0764e40..43ae288d02dd 100644
    --- a/js/src/configure.in
    +++ b/js/src/configure.in
    @@ -124,6 +124,7 @@ MOZ_ARG_DISABLE_BOOL(compile-environment,
     [  --disable-compile-environment
                               Disable compiler/library checks.],
         COMPILE_ENVIRONMENT= )
    +AC_SUBST(COMPILE_ENVIRONMENT)
     
     dnl Check for Perl first -- needed for win32 SDK checks
     MOZ_PATH_PROGS(PERL, $PERL perl5 perl )
    @@ -2089,7 +2090,10 @@ if test "$ENABLE_YARR_JIT"; then
         AC_DEFINE(ENABLE_YARR_JIT)
     fi
     
    -MOZ_COMPILER_OPTS
    +if test -n "$COMPILE_ENVIRONMENT"; then
    +    MOZ_COMPILER_OPTS
    +fi
    +
     if test -z "$SKIP_COMPILER_CHECKS"; then
     dnl Checks for typedefs, structures, and compiler characteristics.
     dnl ========================================================
    diff --git a/moz.build b/moz.build
    index 86d8b958cdad..ac08994c5081 100644
    --- a/moz.build
    +++ b/moz.build
    @@ -29,5 +29,4 @@ if not CONFIG['LIBXUL_SDK']:
     add_tier_dir('precompile', 'xpcom/xpidl')
     
     # Bring in the configuration for the configured application.
    -if CONFIG['COMPILE_ENVIRONMENT']:
    -    include('/' + CONFIG['MOZ_BUILD_APP'] + '/app.mozbuild')
    +include('/' + CONFIG['MOZ_BUILD_APP'] + '/app.mozbuild')
    diff --git a/testing/gtest/Makefile.in b/testing/gtest/Makefile.in
    index 0bef5f897fee..d6e6d5045ed8 100644
    --- a/testing/gtest/Makefile.in
    +++ b/testing/gtest/Makefile.in
    @@ -27,6 +27,7 @@ ifeq (browser,$(MOZ_BUILD_APP))
     # And non metro linking error bug 886656:
     # LNK1112: module machine type 'x64' conflicts with target machine type 'X86'
     ifneq ($(OS_ARCH),WINNT)
    +ifdef COMPILE_ENVIRONMENT
     check gtest::
     	$(MAKE) -C $(DEPTH)/toolkit/library gtestxul
     ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
    @@ -35,3 +36,4 @@ endif
     	$(PYTHON) $(topsrcdir)/testing/gtest/rungtests.py --xre-path=$(DIST)/bin --symbols-path=$(DIST)/crashreporter-symbols $(DIST)/bin/$(MOZ_APP_NAME)$(BIN_SUFFIX)
     endif
     endif
    +endif
    diff --git a/toolkit/library/Makefile.in b/toolkit/library/Makefile.in
    index ccee2114f97b..ee4fc27fb188 100644
    --- a/toolkit/library/Makefile.in
    +++ b/toolkit/library/Makefile.in
    @@ -677,9 +677,9 @@ LD := $(PYTHON) $(topsrcdir)/build/link.py $(CURDIR)/linker-vsize $(LD)
     endif
     
     ifndef LINK_GTEST
    +ifdef COMPILE_ENVIRONMENT
     libs:: $(FINAL_TARGET)/dependentlibs.list
    -else
    -libs::
    +endif
     endif
     
     .PHONY: gtestxul
    diff --git a/toolkit/mozapps/update/tests/Makefile.in b/toolkit/mozapps/update/tests/Makefile.in
    index 6b3a43264567..df5fc516ade2 100644
    --- a/toolkit/mozapps/update/tests/Makefile.in
    +++ b/toolkit/mozapps/update/tests/Makefile.in
    @@ -44,10 +44,12 @@ service-updater-head_DEST    := $(XPCSHELLTESTROOT)/unit_service_updater
     service-updater-head_FILES   := $(XPCSHELLTESTROOT)/unit_aus_update/head_update.js
     
     ifndef MOZ_PROFILE_GENERATE
    +ifdef COMPILE_ENVIRONMENT
     INSTALL_TARGETS              += xpcshell-test-helper
     xpcshell-test-helper_TARGET  := libs
     xpcshell-test-helper_DEST    := $(XPCSHELLTESTROOT)/data
     xpcshell-test-helper_FILES   := $(DIST)/bin/TestAUSHelper$(BIN_SUFFIX)
    +endif
     endif # Not MOZ_PROFILE_GENERATE
     
     _CHROME_SHARED := \
    diff --git a/toolkit/toolkit.mozbuild b/toolkit/toolkit.mozbuild
    index ec599fc8dc93..1bfbee8e53a9 100644
    --- a/toolkit/toolkit.mozbuild
    +++ b/toolkit/toolkit.mozbuild
    @@ -6,15 +6,16 @@
     if CONFIG['LIBXUL_SDK']:
         error('toolkit.mozbuild is not compatible with --enable-libxul-sdk=')
     
    -if not CONFIG['MOZ_NATIVE_NSPR']:
    -    add_tier_dir('nspr', 'config/nspr')
    +if CONFIG['COMPILE_ENVIRONMENT']:
    +    if not CONFIG['MOZ_NATIVE_NSPR']:
    +        add_tier_dir('nspr', 'config/nspr')
     
    -add_tier_dir('external', 'config/external')
    +    add_tier_dir('external', 'config/external')
     
    -if not CONFIG['MOZ_NATIVE_NSS']:
    -    add_tier_dir('nss', 'security/build')
    +    if not CONFIG['MOZ_NATIVE_NSS']:
    +        add_tier_dir('nss', 'security/build')
     
    -include('/config/js/js.mozbuild')
    +    include('/config/js/js.mozbuild')
     
     if CONFIG['MOZ_CONTENT_SANDBOX']:
         add_tier_dir('sandbox', 'security/sandbox')
    diff --git a/widget/gonk/libdisplay/moz.build b/widget/gonk/libdisplay/moz.build
    index 41c4d37f20ae..7ce9e95c4ff0 100644
    --- a/widget/gonk/libdisplay/moz.build
    +++ b/widget/gonk/libdisplay/moz.build
    @@ -35,7 +35,7 @@ elif CONFIG['ANDROID_VERSION'] == '15':
         SOURCES += [
             'GonkDisplayICS.cpp'
         ]
    -else:
    +elif CONFIG['COMPILE_ENVIRONMENT']:
         error('Unsupported platform version: %s' % (CONFIG['ANDROID_VERSION']))
     
     LIBRARY_NAME = 'display'
    diff --git a/xpcom/ds/moz.build b/xpcom/ds/moz.build
    index 7ca875b23ead..4613ad85942b 100644
    --- a/xpcom/ds/moz.build
    +++ b/xpcom/ds/moz.build
    @@ -105,7 +105,7 @@ elif CONFIG['OS_ARCH'] == 'Darwin':
         SOURCES += [
             'TimeStamp_darwin.cpp',
         ]
    -else:
    +elif CONFIG['COMPILE_ENVIRONMENT']:
         error('No TimeStamp implementation on this platform.  Build will not succeed')
     
     EXTRA_COMPONENTS += [
    diff --git a/xpcom/reflect/xptcall/src/md/unix/moz.build b/xpcom/reflect/xptcall/src/md/unix/moz.build
    index b1855573dcca..5a67e6ac1afc 100644
    --- a/xpcom/reflect/xptcall/src/md/unix/moz.build
    +++ b/xpcom/reflect/xptcall/src/md/unix/moz.build
    @@ -155,7 +155,7 @@ if CONFIG['OS_ARCH'] == 'Linux':
                     'xptcstubs_asm_parisc_linux.s',
                     'xptcstubs_pa32.cpp',
                 ]
    -        else:
    +        elif CONFIG['COMPILE_ENVIRONMENT']:
                 error('Unknown C++ compiler, xptcall assembly will probably be incorrect.')
     
     if CONFIG['OS_ARCH'] == 'NetBSD':
    
    From 46de926a1279911b494b3a3988a3d9c8c48e953c Mon Sep 17 00:00:00 2001
    From: Mike Hommey 
    Date: Thu, 7 Nov 2013 10:38:13 +0900
    Subject: [PATCH 71/82] Bug 934070 - Stop copying dist/bin under
     dist/$(MOZ_MACBUNDLE_NAME)/Contents/MacOS in */app/Makefile.in. r=ted
    
    Consequently, revert changeset 92bea49b46b4 (bug 914560).
    ---
     b2g/app/Makefile.in       | 11 ++++-------
     browser/app/Makefile.in   | 10 ++++++----
     config/rules.mk           |  4 ++--
     js/src/config/rules.mk    |  4 ++--
     testing/gtest/Makefile.in |  3 ---
     xulrunner/app/Makefile.in |  5 +++--
     6 files changed, 17 insertions(+), 20 deletions(-)
    
    diff --git a/b2g/app/Makefile.in b/b2g/app/Makefile.in
    index e67a17f30c98..330f84ad0022 100644
    --- a/b2g/app/Makefile.in
    +++ b/b2g/app/Makefile.in
    @@ -113,7 +113,7 @@ AB_CD = $(MOZ_UI_LOCALE)
     
     AB := $(firstword $(subst -, ,$(AB_CD)))
     
    -clean clobber repackage::
    +clean clobber::
     	rm -rf $(DIST)/$(APP_NAME).app
     
     ifdef LIBXUL_SDK
    @@ -128,19 +128,16 @@ libs-preqs = \
       $(NULL)
     
     .PHONY: repackage
    -tools repackage:: $(libs-preqs)
    +libs:: $(libs-preqs)
     	rsync -a --exclude "*.in" $(srcdir)/macbuild/Contents $(DIST)/$(APP_NAME).app --exclude English.lproj
     	rsync -a --exclude "*.in" $(srcdir)/macbuild/Contents/Resources/English.lproj/ $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj
     	sed -e "s/%MOZ_APP_VERSION%/$(MOZ_APP_VERSION)/" -e "s/%MOZ_APP_NAME%/$(MOZ_APP_NAME)/" -e "s/%APP_VERSION%/$(APP_VERSION)/" -e "s/%APP_NAME%/$(APP_NAME)/" -e "s/%APP_BINARY%/$(APP_BINARY)/" $(srcdir)/macbuild/Contents/Info.plist.in > $(DIST)/$(APP_NAME).app/Contents/Info.plist
     	sed -e "s/%APP_VERSION%/$(APP_VERSION)/" -e "s/%APP_NAME%/$(APP_NAME)/" $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj/InfoPlist.strings
    -	rsync -a $(DIST)/bin/ $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)
    -	$(RM) $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)/mangle $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)/shlibsign
    +	rm -rf $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)
    +	ln -s $(abspath $(DIST)/bin) $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)
     ifdef LIBXUL_SDK
     	cp $(LIBXUL_DIST)/bin/xulrunner$(BIN_SUFFIX) $(DIST)/$(APP_NAME).app/Contents/MacOS/$(APP_BINARY)
     	rsync -a --exclude nsinstall --copy-unsafe-links $(LIBXUL_DIST)/XUL.framework $(DIST)/$(APP_NAME).app/Contents/Frameworks
    -else
    -	$(RM) $(DIST)/$(APP_NAME).app/Contents/MacOS/$(PROGRAM)
    -	rsync -aL $(PROGRAM) $(DIST)/$(APP_NAME).app/Contents/MacOS
     endif
     	cp -RL $(srcdir)/b2g.icns $(DIST)/$(APP_NAME).app/Contents/Resources/$(MOZ_APP_NAME).icns
     	printf "APPLMOZB" > $(DIST)/$(APP_NAME).app/Contents/PkgInfo
    diff --git a/browser/app/Makefile.in b/browser/app/Makefile.in
    index f495df5dd169..10237e1ae73b 100644
    --- a/browser/app/Makefile.in
    +++ b/browser/app/Makefile.in
    @@ -162,7 +162,7 @@ AB_CD = $(MOZ_UI_LOCALE)
     
     AB := $(firstword $(subst -, ,$(AB_CD)))
     
    -clean clobber repackage::
    +clean clobber::
     	$(RM) -r $(dist_dest)
     
     ifdef LIBXUL_SDK
    @@ -173,17 +173,19 @@ endif
     
     MAC_BUNDLE_VERSION = $(shell $(PYTHON) $(srcdir)/macversion.py --version=$(MOZ_APP_VERSION) --buildid=$(DEPTH)/config/buildid)
     
    -.PHONY: repackage
    -tools repackage:: $(PROGRAM)
    +libs:: $(PROGRAM)
     	$(MKDIR) -p $(dist_dest)/Contents/MacOS
     	$(MKDIR) -p $(dist_dest)/Contents/Resources/$(AB).lproj
     	rsync -a --exclude "*.in" $(srcdir)/macbuild/Contents $(dist_dest) --exclude English.lproj
     	rsync -a --exclude "*.in" $(srcdir)/macbuild/Contents/Resources/English.lproj/ $(dist_dest)/Contents/Resources/$(AB).lproj
     	sed -e "s/%APP_VERSION%/$(MOZ_APP_VERSION)/" -e "s/%MAC_APP_NAME%/$(MAC_APP_NAME)/" -e "s/%MOZ_MACBUNDLE_ID%/$(MOZ_MACBUNDLE_ID)/" -e "s/%MAC_BUNDLE_VERSION%/$(MAC_BUNDLE_VERSION)/" $(srcdir)/macbuild/Contents/Info.plist.in > $(dist_dest)/Contents/Info.plist
     	sed -e "s/%MAC_APP_NAME%/$(MAC_APP_NAME)/" $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(dist_dest)/Contents/Resources/$(AB).lproj/InfoPlist.strings
    -	rsync -a $(DIST)/bin/ $(dist_dest)/Contents/$(APPFILES)
    +	rm -rf $(dist_dest)/Contents/$(APPFILES)
    +	ln -s $(abspath $(DIST)/bin) $(dist_dest)/Contents/$(APPFILES)
    +ifdef LIBXUL_SDK
     	$(RM) $(dist_dest)/Contents/MacOS/$(PROGRAM)
     	rsync -aL $(PROGRAM) $(dist_dest)/Contents/MacOS
    +endif
     	cp -RL $(DIST)/branding/firefox.icns $(dist_dest)/Contents/Resources/firefox.icns
     	cp -RL $(DIST)/branding/document.icns $(dist_dest)/Contents/Resources/document.icns
     	printf APPLMOZB > $(dist_dest)/Contents/PkgInfo
    diff --git a/config/rules.mk b/config/rules.mk
    index 3728cf28c023..7bb5d4ad0cf3 100644
    --- a/config/rules.mk
    +++ b/config/rules.mk
    @@ -1373,7 +1373,7 @@ PP_TARGETS += DIST_CHROME_FILES
     endif
     
     ifneq ($(XPI_PKGNAME),)
    -tools realchrome::
    +libs realchrome::
     ifdef STRIP_XPI
     ifndef MOZ_DEBUG
     	@echo "Stripping $(XPI_PKGNAME) package directory..."
    @@ -1412,7 +1412,7 @@ ifndef XPI_NAME
     $(error XPI_NAME must be set for INSTALL_EXTENSION_ID)
     endif
     
    -tools::
    +libs::
     	$(RM) -r "$(DIST)/bin$(DIST_SUBDIR:%=/%)/extensions/$(INSTALL_EXTENSION_ID)"
     	$(NSINSTALL) -D "$(DIST)/bin$(DIST_SUBDIR:%=/%)/extensions/$(INSTALL_EXTENSION_ID)"
     	$(call copy_dir,$(FINAL_TARGET),$(DIST)/bin$(DIST_SUBDIR:%=/%)/extensions/$(INSTALL_EXTENSION_ID))
    diff --git a/js/src/config/rules.mk b/js/src/config/rules.mk
    index 3728cf28c023..7bb5d4ad0cf3 100644
    --- a/js/src/config/rules.mk
    +++ b/js/src/config/rules.mk
    @@ -1373,7 +1373,7 @@ PP_TARGETS += DIST_CHROME_FILES
     endif
     
     ifneq ($(XPI_PKGNAME),)
    -tools realchrome::
    +libs realchrome::
     ifdef STRIP_XPI
     ifndef MOZ_DEBUG
     	@echo "Stripping $(XPI_PKGNAME) package directory..."
    @@ -1412,7 +1412,7 @@ ifndef XPI_NAME
     $(error XPI_NAME must be set for INSTALL_EXTENSION_ID)
     endif
     
    -tools::
    +libs::
     	$(RM) -r "$(DIST)/bin$(DIST_SUBDIR:%=/%)/extensions/$(INSTALL_EXTENSION_ID)"
     	$(NSINSTALL) -D "$(DIST)/bin$(DIST_SUBDIR:%=/%)/extensions/$(INSTALL_EXTENSION_ID)"
     	$(call copy_dir,$(FINAL_TARGET),$(DIST)/bin$(DIST_SUBDIR:%=/%)/extensions/$(INSTALL_EXTENSION_ID))
    diff --git a/testing/gtest/Makefile.in b/testing/gtest/Makefile.in
    index d6e6d5045ed8..abcb215da153 100644
    --- a/testing/gtest/Makefile.in
    +++ b/testing/gtest/Makefile.in
    @@ -30,9 +30,6 @@ ifneq ($(OS_ARCH),WINNT)
     ifdef COMPILE_ENVIRONMENT
     check gtest::
     	$(MAKE) -C $(DEPTH)/toolkit/library gtestxul
    -ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
    -	$(MAKE) -C $(DEPTH)/browser/app repackage
    -endif
     	$(PYTHON) $(topsrcdir)/testing/gtest/rungtests.py --xre-path=$(DIST)/bin --symbols-path=$(DIST)/crashreporter-symbols $(DIST)/bin/$(MOZ_APP_NAME)$(BIN_SUFFIX)
     endif
     endif
    diff --git a/xulrunner/app/Makefile.in b/xulrunner/app/Makefile.in
    index 59b37cca96df..84ffc7c3b2e7 100644
    --- a/xulrunner/app/Makefile.in
    +++ b/xulrunner/app/Makefile.in
    @@ -132,10 +132,11 @@ FRAMEWORK_DIR = \
     $(FRAMEWORK_DIR)/Resources:
     	$(NSINSTALL) -D $@
     
    -tools:: $(PROGRAM) $(FRAMEWORK_DIR)/Resources
    +libs:: $(PROGRAM) $(FRAMEWORK_DIR)/Resources
     	$(NSINSTALL) $(srcdir)/macbuild/InfoPlist.strings $(FRAMEWORK_DIR)/Resources
     	sed -e "s/APP_VERSION/$(APP_VERSION)/" $(srcdir)/macbuild/Info.plist.in > $(FRAMEWORK_DIR)/Info.plist
    -	rsync -av $(DIST)/bin/ $(FRAMEWORK_DIR) --exclude mangle --exclude shlibsign
    +	rm -rf $(FRAMEWORK_DIR)
    +	ln -s $(abspath $(DIST)/bin) $(FRAMEWORK_DIR)
     	rm -f $(DIST)/$(FRAMEWORK_NAME).framework/Versions/Current \
     	      $(DIST)/$(FRAMEWORK_NAME).framework/libxpcom.dylib \
     	      $(DIST)/$(FRAMEWORK_NAME).framework/XUL \
    
    From e5e85044a96adead2184cd853e612a777aa3fccf Mon Sep 17 00:00:00 2001
    From: Alexander Surkov 
    Date: Wed, 6 Nov 2013 21:07:10 -0500
    Subject: [PATCH 72/82] Bug 935572 - remove nsIAccessibleHyperLink::selected,
     r=tbsaunde
    
    ---
     accessible/public/nsIAccessibleHyperLink.idl  | 12 +---------
     accessible/src/generic/Accessible.cpp         | 23 -------------------
     accessible/src/generic/Accessible.h           |  5 ----
     .../tests/mochitest/hyperlink/hyperlink.js    |  6 -----
     4 files changed, 1 insertion(+), 45 deletions(-)
    
    diff --git a/accessible/public/nsIAccessibleHyperLink.idl b/accessible/public/nsIAccessibleHyperLink.idl
    index 4e406913f0fd..e4477baa3443 100644
    --- a/accessible/public/nsIAccessibleHyperLink.idl
    +++ b/accessible/public/nsIAccessibleHyperLink.idl
    @@ -13,7 +13,7 @@ interface nsIAccessible;
      * A cross-platform interface that supports hyperlink-specific properties and
      * methods.  Anchors, image maps, xul:labels with class="text-link" implement this interface.
      */
    -[scriptable, uuid(38c60bfa-6040-4bfe-93f2-acd6a909bb60)]
    +[scriptable, uuid(883643d4-93a5-4f32-922c-6f06e01363c1)]
     interface nsIAccessibleHyperLink : nsISupports
     {
       /**
    @@ -38,16 +38,6 @@ interface nsIAccessibleHyperLink : nsISupports
        */
       readonly attribute boolean valid;
     
    -  /**
    -   * Determines whether the element currently has the focus, e. g. after
    -   * returning from the destination page.
    -   *
    -   * @note  ARIA links can only be focused if they have the tabindex
    -   * attribute set.  Also, state_focused should then be set on the accessible
    -   * for this link.
    -   */
    -  readonly attribute boolean selected;
    -
       /**
        * The numbber of anchors within this Hyperlink. Is normally 1 for anchors.
        * This anchor is, for example, the visible output of the html:a tag.
    diff --git a/accessible/src/generic/Accessible.cpp b/accessible/src/generic/Accessible.cpp
    index d7c4f8660c81..8f2ce0bdaff3 100644
    --- a/accessible/src/generic/Accessible.cpp
    +++ b/accessible/src/generic/Accessible.cpp
    @@ -2425,21 +2425,6 @@ Accessible::GetValid(bool *aValid)
       return NS_OK;
     }
     
    -// readonly attribute boolean nsIAccessibleHyperLink::selected
    -NS_IMETHODIMP
    -Accessible::GetSelected(bool *aSelected)
    -{
    -  NS_ENSURE_ARG_POINTER(aSelected);
    -  *aSelected = false;
    -
    -  if (IsDefunct())
    -    return NS_ERROR_FAILURE;
    -
    -  *aSelected = IsLinkSelected();
    -  return NS_OK;
    -
    -}
    -
     void
     Accessible::AppendTextTo(nsAString& aText, uint32_t aStartOffset,
                              uint32_t aLength)
    @@ -2779,14 +2764,6 @@ Accessible::EndOffset()
       return hyperText ? (hyperText->GetChildOffset(this) + 1) : 0;
     }
     
    -bool
    -Accessible::IsLinkSelected()
    -{
    -  NS_PRECONDITION(IsLink(),
    -                  "IsLinkSelected() called on something that is not a hyper link!");
    -  return FocusMgr()->IsFocused(this);
    -}
    -
     uint32_t
     Accessible::AnchorCount()
     {
    diff --git a/accessible/src/generic/Accessible.h b/accessible/src/generic/Accessible.h
    index 0d55cc76d439..4e8533c6430e 100644
    --- a/accessible/src/generic/Accessible.h
    +++ b/accessible/src/generic/Accessible.h
    @@ -629,11 +629,6 @@ public:
         return (0 == (State() & mozilla::a11y::states::INVALID));
       }
     
    -  /**
    -   * Return true if the link currently has the focus.
    -   */
    -  bool IsLinkSelected();
    -
       /**
        * Return the number of anchors within the link.
        */
    diff --git a/accessible/tests/mochitest/hyperlink/hyperlink.js b/accessible/tests/mochitest/hyperlink/hyperlink.js
    index 1a3d2263a3bf..4daa16275e86 100644
    --- a/accessible/tests/mochitest/hyperlink/hyperlink.js
    +++ b/accessible/tests/mochitest/hyperlink/hyperlink.js
    @@ -21,9 +21,6 @@ function focusLink(aID, aSelectedAfter)
     
       this.invoke = function focusLink_invoke()
       {
    -    is(this.accessible.selected, false,
    -       "Wrong selected state before focus for ID " + prettyName(aID) + "!");
    -
         var expectedStates = (aSelectedAfter ? STATE_FOCUSABLE : 0);
         var unexpectedStates = (!aSelectedAfter ? STATE_FOCUSABLE : 0) | STATE_FOCUSED;
         testStates(aID, expectedStates, 0, unexpectedStates, 0);
    @@ -33,9 +30,6 @@ function focusLink(aID, aSelectedAfter)
     
       this.finalCheck = function focusLink_finalCheck()
       {
    -    is(this.accessible.selected, aSelectedAfter,
    -       "Wrong seleccted state after focus for ID " + prettyName(aID) + "!");
    -
         var expectedStates = (aSelectedAfter ? STATE_FOCUSABLE | STATE_FOCUSED : 0);
         var unexpectedStates = (!aSelectedAfter ? STATE_FOCUSABLE | STATE_FOCUSED : 0);
         testStates(aID, expectedStates, 0, unexpectedStates, 0);
    
    From 5788c09304f96dd8c7dd3ef5a8ee8cdf7eb97e14 Mon Sep 17 00:00:00 2001
    From: Benoit Girard 
    Date: Wed, 6 Nov 2013 18:11:18 -0500
    Subject: [PATCH 73/82] Bug 935701 - Get drawing recording working on b2g.
     r=bas
    
    --HG--
    extra : rebase_source : 783627519f291d187552b464689315ce2697df95
    ---
     gfx/2d/DrawTargetRecording.cpp |  9 +++++++++
     gfx/thebes/gfxPlatform.cpp     | 17 ++++++++++++++++-
     2 files changed, 25 insertions(+), 1 deletion(-)
    
    diff --git a/gfx/2d/DrawTargetRecording.cpp b/gfx/2d/DrawTargetRecording.cpp
    index 972a73e5c9b9..80ddffe3243e 100644
    --- a/gfx/2d/DrawTargetRecording.cpp
    +++ b/gfx/2d/DrawTargetRecording.cpp
    @@ -214,7 +214,10 @@ void RecordingFontUserDataDestroyFunc(void *aUserData)
       RecordingFontUserData *userData =
         static_cast(aUserData);
     
    +  // TODO support font in b2g recordings
    +#ifndef MOZ_WIDGET_GONK
       userData->recorder->RecordEvent(RecordedScaledFontDestruction(userData->refPtr));
    +#endif
     
       delete userData;
     }
    @@ -227,7 +230,10 @@ DrawTargetRecording::FillGlyphs(ScaledFont *aFont,
                                     const GlyphRenderingOptions *aRenderingOptions)
     {
       if (!aFont->GetUserData(reinterpret_cast(mRecorder.get()))) {
    +  // TODO support font in b2g recordings
    +#ifndef MOZ_WIDGET_GONK
         mRecorder->RecordEvent(RecordedScaledFontCreation(aFont, aFont));
    +#endif
         RecordingFontUserData *userData = new RecordingFontUserData;
         userData->refPtr = aFont;
         userData->recorder = mRecorder;
    @@ -235,7 +241,10 @@ DrawTargetRecording::FillGlyphs(ScaledFont *aFont,
                            &RecordingFontUserDataDestroyFunc);
       }
     
    +  // TODO support font in b2g recordings
    +#ifndef MOZ_WIDGET_GONK
       mRecorder->RecordEvent(RecordedFillGlyphs(this, aFont, aPattern, aOptions, aBuffer.mGlyphs, aBuffer.mNumGlyphs));
    +#endif
       mFinalDT->FillGlyphs(aFont, aBuffer, aPattern, aOptions, aRenderingOptions);
     }
     
    diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp
    index 94ed53ff866a..40e6e799a0fd 100644
    --- a/gfx/thebes/gfxPlatform.cpp
    +++ b/gfx/thebes/gfxPlatform.cpp
    @@ -16,6 +16,8 @@
     #include "gfxPlatform.h"
     
     #include "nsXULAppAPI.h"
    +#include "nsDirectoryServiceUtils.h"
    +#include "nsDirectoryServiceDefs.h"
     
     #if defined(XP_WIN)
     #include "gfxWindowsPlatform.h"
    @@ -319,10 +321,23 @@ int RecordingPrefChanged(const char *aPrefName, void *aClosure)
         if (prefFileName) {
           fileName.Append(NS_ConvertUTF16toUTF8(prefFileName));
         } else {
    -      fileName.AssignLiteral("browserrecording.aer");
    +      nsCOMPtr tmpFile;
    +      if (NS_FAILED(NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tmpFile)))) {
    +        return 0;
    +      }
    +      fileName.AppendPrintf("moz2drec_%i_%i.aer", XRE_GetProcessType(), getpid());
    +
    +      nsresult rv = tmpFile->AppendNative(fileName);
    +      if (NS_FAILED(rv))
    +        return 0;
    +
    +      rv = tmpFile->GetNativePath(fileName);
    +      if (NS_FAILED(rv))
    +        return 0;
         }
     
         gPlatform->mRecorder = Factory::CreateEventRecorderForFile(fileName.BeginReading());
    +    printf_stderr("Recording to %s\n", fileName.get());
         Factory::SetGlobalEventRecorder(gPlatform->mRecorder);
       } else {
         Factory::SetGlobalEventRecorder(nullptr);
    
    From d6e730e4cf5163fa721704ba459b64cac2442d9f Mon Sep 17 00:00:00 2001
    From: Seth Fowler 
    Date: Wed, 6 Nov 2013 18:50:42 -0800
    Subject: [PATCH 74/82] Bug 917595 (Part 1) - Respect image-orientation in
     zoomed image documents. r=smaug
    
    ---
     content/html/document/src/ImageDocument.cpp | 39 +++++++++++++++++++++
     content/html/document/src/ImageDocument.h   |  2 ++
     2 files changed, 41 insertions(+)
    
    diff --git a/content/html/document/src/ImageDocument.cpp b/content/html/document/src/ImageDocument.cpp
    index ebe217d0ccc6..dd530a41ac6b 100644
    --- a/content/html/document/src/ImageDocument.cpp
    +++ b/content/html/document/src/ImageDocument.cpp
    @@ -15,6 +15,7 @@
     #include "nsIDOMKeyEvent.h"
     #include "nsIDOMMouseEvent.h"
     #include "nsIDOMEventListener.h"
    +#include "nsIFrame.h"
     #include "nsGkAtoms.h"
     #include "imgIRequest.h"
     #include "imgILoader.h"
    @@ -209,6 +210,7 @@ ImageDocument::Destroy()
       if (mImageContent) {
         // Remove our event listener from the image content.
         nsCOMPtr target = do_QueryInterface(mImageContent);
    +    target->RemoveEventListener(NS_LITERAL_STRING("load"), this, false);
         target->RemoveEventListener(NS_LITERAL_STRING("click"), this, false);
     
         // Break reference cycle with mImageContent, if we have one
    @@ -253,6 +255,7 @@ ImageDocument::SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject)
           NS_ASSERTION(NS_SUCCEEDED(rv), "failed to create synthetic document");
     
           target = do_QueryInterface(mImageContent);
    +      target->AddEventListener(NS_LITERAL_STRING("load"), this, false);
           target->AddEventListener(NS_LITERAL_STRING("click"), this, false);
         }
     
    @@ -509,8 +512,11 @@ ImageDocument::SetModeClass(eModeClasses mode)
     nsresult
     ImageDocument::OnStartContainer(imgIRequest* aRequest, imgIContainer* aImage)
     {
    +  // Styles have not yet been applied, so we don't know the final size. For now,
    +  // default to the image's intrinsic size.
       aImage->GetWidth(&mImageWidth);
       aImage->GetHeight(&mImageHeight);
    +
       nsCOMPtr runnable =
         NS_NewRunnableMethod(this, &ImageDocument::DefaultCheckOverflowing);
       nsContentUtils::AddScriptRunner(runnable);
    @@ -573,11 +579,44 @@ ImageDocument::HandleEvent(nsIDOMEvent* aEvent)
         else if (mImageIsOverflowing) {
           ShrinkToFit();
         }
    +  } else if (eventType.EqualsLiteral("load")) {
    +    UpdateSizeFromLayout();
       }
     
       return NS_OK;
     }
     
    +void
    +ImageDocument::UpdateSizeFromLayout()
    +{
    +  // Pull an updated size from the content frame to account for any size
    +  // change due to CSS properties like |image-orientation|.
    +  Element* contentElement = mImageContent->AsElement();
    +  if (!contentElement) {
    +    return;
    +  }
    +
    +  nsIFrame* contentFrame = contentElement->GetPrimaryFrame(Flush_Frames);
    +  if (!contentFrame) {
    +    return;
    +  }
    +
    +  nsIntSize oldSize(mImageWidth, mImageHeight);
    +  IntrinsicSize newSize = contentFrame->GetIntrinsicSize();
    +
    +  if (newSize.width.GetUnit() == eStyleUnit_Coord) {
    +    mImageWidth = nsPresContext::AppUnitsToFloatCSSPixels(newSize.width.GetCoordValue());
    +  }
    +  if (newSize.height.GetUnit() == eStyleUnit_Coord) {
    +    mImageHeight = nsPresContext::AppUnitsToFloatCSSPixels(newSize.height.GetCoordValue());
    +  }
    +
    +  // Ensure that our information about overflow is up-to-date if needed.
    +  if (mImageWidth != oldSize.width || mImageHeight != oldSize.height) {
    +    CheckOverflowing(false);
    +  }
    +}
    +
     nsresult
     ImageDocument::CreateSyntheticDocument()
     {
    diff --git a/content/html/document/src/ImageDocument.h b/content/html/document/src/ImageDocument.h
    index d431b29a4ff9..45de6062deb2 100644
    --- a/content/html/document/src/ImageDocument.h
    +++ b/content/html/document/src/ImageDocument.h
    @@ -94,6 +94,8 @@ protected:
       void ResetZoomLevel();
       float GetZoomLevel();
     
    +  void UpdateSizeFromLayout();
    +
       enum eModeClasses {
         eNone,
         eShrinkToFit,
    
    From d7efa3bda8843fad6e1228ecb6455b200d5e1aa9 Mon Sep 17 00:00:00 2001
    From: Seth Fowler 
    Date: Wed, 6 Nov 2013 18:50:43 -0800
    Subject: [PATCH 75/82] Bug 917595 (Part 2) - Reftests for zoomed image
     documents with EXIF orientations. r=smaug
    
    ---
     .../document/reftests/bug917595-1-ref.html    |  18 ++++++++++++++++++
     .../reftests/bug917595-exif-rotated.jpg       | Bin 0 -> 90700 bytes
     .../document/reftests/bug917595-iframe-1.html |  18 ++++++++++++++++++
     .../reftests/bug917595-pixel-rotated.jpg      | Bin 0 -> 91596 bytes
     .../document/reftests/bug917595-unrotated.jpg | Bin 0 -> 90864 bytes
     content/html/document/reftests/reftests.list  |   6 ++++++
     6 files changed, 42 insertions(+)
     create mode 100644 content/html/document/reftests/bug917595-1-ref.html
     create mode 100644 content/html/document/reftests/bug917595-exif-rotated.jpg
     create mode 100644 content/html/document/reftests/bug917595-iframe-1.html
     create mode 100644 content/html/document/reftests/bug917595-pixel-rotated.jpg
     create mode 100644 content/html/document/reftests/bug917595-unrotated.jpg
    
    diff --git a/content/html/document/reftests/bug917595-1-ref.html b/content/html/document/reftests/bug917595-1-ref.html
    new file mode 100644
    index 000000000000..6bb9e2dc92e4
    --- /dev/null
    +++ b/content/html/document/reftests/bug917595-1-ref.html
    @@ -0,0 +1,18 @@
    +
    +
    +
    +
    +
    +  
    +
    +
    diff --git a/content/html/document/reftests/bug917595-exif-rotated.jpg b/content/html/document/reftests/bug917595-exif-rotated.jpg
    new file mode 100644
    index 0000000000000000000000000000000000000000..e7b0c22f35102e02473f6cd3c4e42305fc6c95f6
    GIT binary patch
    literal 90700
    zcmeI4d0b52|Hsd4O{?}IGLsPbR4T31NVJGgA+nFONm{h1q%NWC*|V2@*9V^#ONO$G
    zvQ!9dQiS$xnz{FPCO%}l>|6o-IF7Pqhro?Q<F+5jUxnor3&Ol$nKlNN;}-aOg~ReASnfM7%-g_|8SLvbCzL(FV<6km!or;G;1xd4D>PKk
    z#ofctJ=l|N8|WY89uNt@hdPV)0!kv=vZ0Yp4J}Mf^^EkP`9FO~fBdu+c|mk%|#gYfWheP1sReUU*weZ+3?Y0DoMI-O5nbiPlvV~_Omb`P5u$`%>bBXC||STH*z
    z$lb$>t@pJP|HnIax~xvu@yB>CZ?9ml0C=iN(93)SeBkX4@bnG!4GduW2K?v_|A)JE
    zx&~44gI~jf@&O#EaP@>_q;N%K>y{89``>pa@nppafKa
    zYETQBK|2&OCPj{-OzA;kQTkB^QH&_&6l=;T${5Oc$`r~hiVr1#5=L1>SxQ+=*+|(z
    z*-JS}IZZi7xk9-`xlegQDW$xo)KmCW8da96Le-@9ry5YrsWwz6sw;H{)rUHtx{$hz
    zx{kVyx{rE-nnt}sy+h5XmQbsyO*BB0p{dcdXnHhrnk~(lHkIa03#P@;R?)W7_R&t!
    z&eLwt9@0u^Z)t6G3A!?!P1mCjr903k(mm+&=`r**^d0mg^fdZa`a^mty_SwMq7RN<>Mlk=QMfB5_&b
    zzC^i16O+m8!5qZ2VmdS3nW4-$=62=@CXe}mS;1_Tl#ygf8cEtoPL&LhjFsFfc}((>
    zx1~ESA|O^Owv`nNpcHStVIrSzFoZvSG68WDm<;mVF}IASWl+Uv9YE
    zRJl;Ob#h1LvgKaLwRThPrr*u6n`bwy+s#ydh
    zHcu@^SkqVuzQT^;n!nBkMthT
    zHRu|;8sjv=HTGy+(|FrcrRUI|9z9p}Jk#@OFKRE{UgLX3_1fPnr&p6^Z%up6AkFQX
    z*_v;AtMwk6h5=M!%N+I{n@H
    z$M;X~U!~Js$5CgY&T*Y*1LOv92FxF@Z@{C05(CW#`VHJYFi)4NYoa?xcc*UdAnG8~
    zLB4}_54!&c;}45J0{+jqo{ioDz2kbN`fB=P^kenY_1_!xHJEC!!Qh4gKGeF6L{@Z(1-cMp$4L7cJT>O)Wz$&sf$B)f?(J^w`j<
    zVLHRSh8-AIZq>)i-DaBU)@NZKG{3kED&XAGvDey-`Y|CXU)M>V;h&J0H8_cD42<_EGki9T*Ny4jUW_
    z9W@<29FIEIjy4+|J^HGXtkVRi9ZqFqbjJjbIX{*Mg@&xXLV-uQPN4O@q7EK&5F>GSiB>73xCmo&C
    z;x^K4qg%;jgUQj8?@ZB{;yWc{Ds$?jsfVUEO&c|B%e0E=Ce!1l7tGL^5i#S|OpTfI
    zW@d8bx$fMvvlz47W*wU)aCdg!=iW5iarUm+wH~$}i5}IS!#y{9zV@>6+UQm3ZRNeu
    zyUNGPXOqwCIh;9L=e+f`_1)oHH`ifq(%cq5XTQUK#5}ioDgKiFv;5BmC@-Wx-SnH`gbX=BTY33yv#{9~z&ug1*9c#l4lrE4Q!2S9z|wy?XHK
    zt*ZrVJl5P^Yq)mXT4J5|x_b$x347K{tPfaUuz|DT$VSDD3pbW;8oMcNGkf!@&5c{Q
    zTW)O~vNb7DIx#G-qjr~dBu_pVgs
    z)KzJew8*sD^f~Dz8B;RupBsHH>-^C3sTcGw9KNV^ac8D#X2K=uOUo`1yoJ1`%R!gl
    zUh%n7p2f{7%ATD4=<2wu_pUizyLsL2diD*Q8@!uVH!t3@ymjuj`R(*OrgzeEOmb51
    zn%qsjXL>I!*DN<9&m!;q{bBbnJ>WdJ@^IwC>yI2C-O2wm|9-*5g2#o^3rik*KCXH)
    z?@8U$1y9?H7C&P=TlHMw`PLV`UhFF#Se#N~T9R2hvNWe`LRnF{M|t(jke7mrWv}F3
    zZLMTg9<4H}y7=1eb>5q4Zz`&Ts@vbjy;FR*>-~WDf7cAJ$*G-OTTvHWN7S!r=+SVv
    zaY$oUlS|W!X8-2)mQ}4iT934ux82~o@hjWI1x&#<;XvVe+zEe1_!9(C3T}>y@bv~@
    z>{y@+X+RP%DN29_OBC3P02B?#2Oqd%Hl^pM@?6S*kK0h;kA|?%0U;9p52hG(lvQ9k
    zHr}@bFhoqU75*1}U|*(#Q98a|d?UQ(`MZY(2D6RyjQ}tjY-nsb*v!(%lx=7#Dwsfu
    zrX^E8o(Uc&nflKWX;sOzf6B}}(V>Y_%F&O+8W5uI?io1SOWz~V-yp(0$iPs4umKnr
    zVHx2cFgF3)cbX@n@fnlLmefo$_^y%~QI{kw_o#?w&`*dWu<1ko9OWR;Cky%{>
    z1Ls+PY2{%CU;qC3gdMw%4fOQ&jvVP8>SZmuA9{n$^o&eh|G6I@cJH*!$GwLci0aU(
    zP9F@`u@+j)S{m;7kM*ski6USt>fHX)M|6;1I)G?r;xbT_WaiPTXcR?2Riw}qDa2L4
    zf={Ztm}6YcPsSg2+4+o<36O9TKQ5@=mr~2k
    zZSV=>w)o)cZN}A{I4qdeGNH|_e9?rud;+BNOfk;JCROB*(+>|#<+h=vz`R*;nIokY`hEuC}S1``q-TBz_q*m_B+!J^Y;Z5wh
    za|L&8o%0Ph{Dt6&KzRK^K6IPLIaSuNydhCM=uK-gi;oMg9bk8XyLU7wT7xz3nEboN
    zU3NZ8`Bp)~8{WP1x&&Yd2w)mMkpK&@Qf!m;*;bzxEdqpbw#1lS<7jf*qZ)h~S~P0h
    zpyS-%pUjsQ+vLQ$mj6!Bb>C4OTYgM>5w?JM>-_7y&@eV
    zm3$h~A+gkebO`B?SSJw|4v`Ka9TMjwq!t3nNQaOPAszZ<3y`)l#6#kHlSqe<4*hZ~
    zL_CCa2=S0OA^F8-hVnxwKP1)yNQaOPAszZ!Y0-EYxh|mbvadbn8+)PgGI6qk#_h#M
    zXQV^lw5!hH8jahF&(|OwLOLWiSaohx-!m7|A*4g%e1z0OAQ|b<_Zn7bqahwbJS5fv
    zogL;ISw}pCc<9$WNTg9nhs4?t@etA>#6#kM=9~ER?{+{sgmg%(1&|IQ9r|~&@~>41
    z>5$k~hX)H@*{^w!h?S5I
    ziM1i(A*4fyhs1TPe$bg9b)8PfL^_0YNUQ}&oeA*};-O#jAjCsICE|#OkPaap>clQT
    z)oMt6=G%iI9ulkNNQX#$3h@x)A+c?U)PoQY{gkpJ9U}E2q(exDkPe9-5&S8wA!}(!
    zhsdlm0O=6YA*4e{hrYG|nr|;&7tnh@zRl2l8L!d&GO^l<=9iK433?ynmrd$BOGt;1
    z4t>Wh{@rK<(jlZn|ITB+u@}-Iq(exDe%S)ww5!g|67|bazf5eOg4BaV8io30Vr__c
    zh}4Ua4j~;9+lELz2dYt<5YxF1U7p{p-H*bDB+ShUGs8FG
    zKFwHxdSWpF=+@VxdB*sVs4zh>-?=RwtwnY~{(#!W|6?Vv^?q!AJ%%S-IQRUemUiA)
    zyVKG_YXY?XaX0S%rGlgy*@aEQm`q`m+t|_7k1w4MtQ7k3cW*Hq^yUH2fmhA1F1S&^
    zlRdHRfX*IjWjz5nWqx(1bWfeDe4gG=+`wzPfX9^2b9FuDf1&LH0l3D+e7DM-Z(1XHE^EQw61@zO@QQ!*|0H;
    zBS3`>0i)h62AW$Pf4yVjEBLRdJ&_!7Xn
    zf&j6_ZSew!a76;-&4kB~9YBEkWCAS5SVD#u0eCJ1s2hS^wYGk9{F$aq|GKLKtp{lXUa
    z37}9tgaApw1h^6?$j18)T>&rA03QE}3fAU=W$|DI&JdvZ2-doTQ>N*i)bO6$sz-or
    z*wy&?@bX@o+AI<%|jP0@9Oiy^;()cc#5;420Qr=BpH>|s(3dsn|JXR1*`ob
    zw61Ir96uDJ>Ah}EV&62sseu?TeL|#=VZQQV5Wm3V*qKa?X`uv2oCJ|DdQ0u`(gVi!
    z-NGWTFQ}x-+q{V{+~`*y)2}w&^!UJ3>7Bf`1%hHM`()ys25Yu(*COW~w*$;`@@HHK
    z&f8yji~v5-7cb@>RxU}~k+-tj=>^?S&EGlC2Nx>y3oBEy-V$K@DaZGaeRFuZb*U+@
    z7C8yG3B0hj?%vIXxcd?AZ34V~+E$&iVY;B_!+NZ2en_h@i2!R0lImoP3mgl62uOo(}UEka=`0m>V(tLa|6Mn#CvS3)2p((t~1@w_S>1GqflLmE~t
    zGKv7hr`5E#`w`$q)z@cX3LFaMvAjRI@T`YBlA9X!E%@T};+Ez@0wlofrqc7RFe_;X
    zQ<98a0<4#B-EgWmyo6m4NEyx@IoU62vLEkv0VX$-*RXIIh_`H3o%VDqm_4SRv4gQzeN3vRSZ|He8om@vNY}c;6)srz%$cxWYVA1w6cRI^Q#S2PF<U(~7^p2@4c-&mYoTolvt=j8c&=Z;Mebo7sGGB=|MIMZt<
    z@pZj2?xe4|(!c$|iKb}Q`;?X!!i0hhpXP|#>ptBrW}nG;QTS@F8$@`0&BpMU!#o{<
    zif+Yh2%XEKCf@|uiPQW_jvq56uaF~fyfm%f-KMt^nO3{~stFK;9d1cVHh6OO%GR^j
    zz4Ti6nK1?M$pTiw?Q4+k8T1Q%lUnVY0?m)us3QV1n#YvAkkjn_+kp&;t6E;ldyA;jSoD1rMR)jCIXb2V7Lpbw$_Qq
    zS5M`(xA_p@Rw#x}fJ}tE2(<$w6-Z4{JU}56Q3c|n|5bF1QH;Ec&&O4TUiU8CdB3t<
    zzToi7-XYj7Yg*B!LNY<(>;M2OVAoT466V
    zg#^fLD?8};;vE5I{HZ&6d$hN~jJ_!?cnr4kU5rwO|7o0cm{nMZ$L#6tJgP9dC2cK!
    zxY36?yW*D91GBc*t#202Szi)unFKrM)hSaZZH#Rc#t6CF+a>rbGcz%pDN(){e6&of
    z=xz+>WzV9*MwJgM*y%e2*iEzal&S&E5Ac(?O`r*!x3E4ikefH|-9h0rLF@}Z_^dzs
    z#S32Y{vs!SdK=?nVL5IiI;MSEVpCwfOk~Op!P2OOcx-~d!JFcjY7N|kHi_mYA*1(G
    zZa(j(-YXufUhZ8rU)t(#-f?XGG;{^X2FMTon{C1VR%(Mz?O!gG;S8Vxe)pGFRZQGs
    zU3>f@c9FBwCFlVGBDrP4aqng-wx1@zp0dng*3}QV+l8u^dD(EFJ^*F_?T@TmS~Um`
    z(I;Ys4Xo6YiTl*f4ty`fHkWl}TXVIi|I9N)l&zmiUSLonJurpI!__-nMZF
    zWjv>;Tv#f2x->4a9X?X4{w85=ZNl>eL5u3^(w3PU1-VtH7`P^Z2F63G{!z_jH^=av^JPvh)T5q_Aq_Up?wI
    zg!jU&mFF7ewk+l?R+*9FEPuW+@f9{I$ecc^}K8R{ZB7yw|Ef1>e|AH
    z=)wa$WB#BeSiCd-oB$6J#%VJ1+~A}?eQ4BI9KUG>BlWx|Jm>Rr1}OY)LHOu2i;}q3
    zn9TAnP#}0hYVY`}In)DK^^NxIwp6B^LCY50AisBhDeD5O?fsyK+3z#^wI$u3E+eqS
    znrraQ3s=DR6lAj6!iAV&`_v~3wfv0s)a2vt!(+Qf5@;{^Z4Ir{zoSgQ!+{kVIkv-9
    zwFxkj^MZBvh`BFzF{Li%NOOv$@G%6<`7`&h!d@HX;Hyfwr4I>^jy3LoWN*``3Lm<<
    z!>evfcv^7hzRZ-(Eiow#()2FU1eQ)=Zc;NY;|BU=rw~%v((jm9-gN
    zBz6db#OWr2ATh3pAm}@~(+R&31c^f_1VLmTgdj*<^RJf>1R)3_4^jw%5Cr|s2NV$m
    zk%u@0K?s7#Jp@6}zs8;~cR&z?AP7Ow@0{X;GC}12g&>GL#32Ym5Jc`F2!g(3nt#27
    zAP7Mad5}VxAe0G0nV`;L2+a-?8)ncHdGfG=rpS{A9W+H=%!EG%KvU#Nq7s@SFD|cx
    zrpSxwTcauRq!NT62tklIjp+={-|0jl2tp7fHi1X(LkNNp1d)cR@5oLk)j|-2Ac(x9
    z-pN_MqeKXT5CoBX2)X`1mqHMPAP7Ma3B{1R2l?m}oEV5QLE;1oK@fr<1VLhjj??S_2VmtXL6GXyL2!ap`pyviw*#yQ
    zf)E5D2qKq}Um5K{nIKZ{LJ))?h#Zr@4Ow4BJOn}H>V+~vqzZ&GK|f9+b_6~&941bn
    zP$mdvg2+4S
    +
    +
    +
    +
    +  
    +
    +
    diff --git a/content/html/document/reftests/bug917595-pixel-rotated.jpg b/content/html/document/reftests/bug917595-pixel-rotated.jpg
    new file mode 100644
    index 0000000000000000000000000000000000000000..ac39faadadd9e6c012aa5064ecbbcf7946f6c5a1
    GIT binary patch
    literal 91596
    zcmeI530zEV+raNxYFf1liKdc}nij39L9|$&ED;`z)U-&87KL=|9`eXuw#J_HXso5s
    zplpvG*|S%Yq-fu!nRC7~MZDkd&62m@_j~)U<5yjsbD!nD&b9pS>%JSr6QU3)k9Bf&
    zLKF%Gxsd-5@mgWJtD_@l;$$}`*YRV>0|+U&jQ0-;rYa*87!)2l*?AOm`iz-O#vMdO
    zvPc@4BIM~67BXRqlRF|e*D;RFFtU+E{<1YZM&y+cdSK)-k;(kB|A!b;1!6jwdcv4=w$e$ZY$`46-z=DWCe^PEDW%WR=XBa|s1q4YHf^?vqc-+=uHDXm5*E$^%TXh`hE
    zFFZWNmc@#Uj5PM=dKpU;+P;0aL3_)Ng|F^sEV*C1?wF&wKAsT^!kH4KdIc{CjtFIj
    zg?M^#nMVKHh&z4aSC948a}1r#_2GtcgUDM=BdyFo$d`QGLEir1{=q>^|DcZEa3@du
    z>KP*zMRiyoops1TK)
    za#V#HPzxEz7!*Z{8l?|Ko1#xKq?l2xDGrn|l<}0wlo^z{6kkdZC4v%7Sw)GZY^Cg`
    z9H1mqPEj%_S17kA_b5*(MU*m14Mj+$Q5C4_)PB@~R2J2mI+8k$>Q0?a^`$PPE}^cb
    zZlWeo4^sc4rctj@Z&M#p3#sMQdK#k1(==#0G$Wcd&5`Ctn@RJbh05bC+r1{d9
    zrSC}>OV=|Pj6MuQhCRcL;mHVRtYz$C{KXJ3?lVdlO)~N_+A?M`PBJrPf@D_8?36h!
    zlO=Osrc|ayR#{eG)>hU{)?0S5Y@F<2*-Y6y*%H|nITbkrIeR&Gx%qM{<6q|ae^)T+?+QYjC)?-hPv>x|+d{mNE(pMU(G)HNP(oUr_N_k2Z
    z%CgD>l^vBmm1C6mC}$|=E7z;2shFy`sRXKQR5`A4OXZy^Lv^6)7*%i8)vAY7vsH`L
    zXliH7Pt~5odQR&Z)pJkJOFauUXc_}G
    zTs0PG#A%$?c&s7p)vwpcUff>md!_ce->b2A-`*p7b9-;-&F}rFx3CYh&zL>|eYW&T
    z@AFcVt~o?=l4hi4qUJTtioWW7hxhgByP@ytzR$F%T0^uZYc16}q?M~x->-i^=YApm
    zcJ<5dSJ7Xi|A_wc`)}``)xS(zP1`}+UwgZ@K>IzjCvzlo0W*P_!>rQL(s9v=&^e%U
    zN2f*CKzFL{N?pG0OFcO~Yds&m?Rr=Bss?Bem@puEK+1q;`m*}g`hNQH`Zx3&2O13Y
    z7`Sd=`oMPvy$xIqmKdZMycnc7h&^cGpo4=R4wfElJvdBBK(MPb47C}bIkm_dG#>EVccPf!=6~ESxm54XK~d+
    zY-wc~YME+TW;MWSuGLBzw&=a2kr$uGE@@U#<=g}KR-x;GiX6l&TV_rGwI{7-KI8`}YI4^a+>>}kd&Si^B
    zzH2{MFV|$(sV&ZqwoQ2PoBnS>zook&H&?f9
    zZZ9VqOk6ne!X)WQ6DRGN^mel84+N^2G
    z(;7WSdu;V6oX(oQZ2IjPnlt=ooS(^*u-7+dHqy%h4;|tK55p_jd0xu03}vx75ep
    zXRFUUUwhwezGZ%Fzny*+{*L~;{j2A@%;(K-3~&ob3LqAEEZ_&q1kMf22vQ9S2+9fW
    z9~>2YFT^lpZAjrl+l4z8R)vlWJsL&{n;mvOT%Cle+=xLDYa)skIV{?l
    zEB;w&vU2Onx>X*lGFSIoy?k}?8s{}BYkRB>U7Npd_&VMn^gsOnxU=4T{jT-+2Ja1j
    z$C||Mj1_J4+W7aMrhg{16*$E}^icJkuo;v?b<6UHZ;-!)*@=3S!Qe!Cy-8MTMMS8MP3y^Z_4_uWq%k(kQs
    z$BX3&_xtaEa=`gO+QESbcOH^HwCK>=!_yAmIAVPy`Kad6*rVd4prpcMlaJ*jTO}tS
    z*E$}TLQRQCDf?^IUw2Q8K5;(PDD?negCBbmos2m7{?y!4k57*~ef5m>nbfoTXZM~{
    zJGUW?lD0UlD%~%=@cfMP_cF$2T+JMwdG3Pog`|r*7x!H1c_}VSE^BobAy^`)zZ`P8
    z;)?H;;;Wpi&$FjzKg^kwbLZN)Yd5buUC+KT@`m81{mqNFY;R@!ZT)xpZOhwfxfZ$S
    z{;~My+#Sn1X?a$8=kMCw&AexKFY7-0{*?!#A6$Rv`tbIn-yYq2JoWLD{8{;hPrRSJ
    zd%ECh^|M9KTAnX|A@yRzOXZh4UunHMSTMMNUuao)sc3Xj?&~S9pBH--m%j;nBPv<_
    zR`Ko5Qti^@cV_P{mN}K(egFIWlJb!9mWs6>R6gweIOyZq$`O^hRnx0Vsza-ZnvJ!6
    zYLn`Q)m^QhSpTXau%V@KLsOroW6jphH-sL-(w0aOLzEyMEY8Ho;V+0lf*^{}%`s8_
    zJ_t>ifQFDXAcGhbRYW5tii9R8nj{~zam74J-*$OEWzeTKRPvxHIp!cClKcv#n6=94
    zq`Y#Se=A@}m}DpUCE3WaOe>?b{+#F^#a$5S86F(UG&43s$jrpl+}6a(*36P=YAF#c
    zNQ$QIr+j&u{nXD_WZd0P`z+JmNiIzkQIbCqYfzZ6r+4r?uCZ5eAS=onyUpfKAgd)?M%wxlfC&C+GIHVF@~*PT9LB1wLsT&9Jwsj-=^gB+8|
    zvC@@tZ}z%hF><82ad4x#
    zRI2UT63dco6e^7_CC!kLm6InMoKr?r3XMjk)1;*6Bt%n|k;f5TMM_o2bfmP}Bu|F!
    zLUpqhTMo$RjXHIu=j3};1I*`zu9TJ2=+(QArv5;KL4$`3v#_+Xwy|{_J;uq|#dYiy
    z_o>r7NV@m(=KA>h`Ogmvk608LwRp*@)oa$S`(yovt=qQm*cqR&YxluJhmRahI+lF=
    z^qI5g($ddoWM0kAxpw`=&0BxpfAH|pepB+c^j+Ee>YCcR`i91)W}&2C
    zq${6)#OQ6IJCz^N;;dgha>
    zdd>^IC#NxBSdo6Uq-(7``>~F#>{QR%JNBht&yWI*LcTnj3SuLXHvff^@Uk2^j@eIL
    z-o1WM{bCxM>nsj0;=IO$<7`6;`qmN1{6pSTC7d0>7vix5a-GY6t9>|56zhjQ>BkWp
    zJ6ElH5Rbc7Sczlb6R0dAE+dACrQ8>k|0NLWmy5X7y>O=;*fn-8fz}I>;zZk{+**2j
    z5a@x0o598MCZ)HAg?@qBe7wp!)
    zgfCO{?-$?1!?)hqYjs`B&TR>6a3oON%K%((kU;mR8#b>i(<6}XGwlWjX#wN5h;-^o
    z2()#nB7x=!1;W{0A31+$zpvv9%USsPB?RgdJ%&JAj&Q2oYT2)Y%Zdr4-(L;C-jhIe
    z|4g}6X^YdEH#BMXbr!Z5R7qRKu1>*WU-`My2rqEl^D-)
    zrZX2eAkg76Ns841w_1l6;>`pqZk$OV{yRb4PC49D=t7{IY3sx*9+4*X29sH4gS|=2
    z#-3#H@%ZU2@vj-eONMynZ2}#fBe>2{!QS|Lh^C10n)V2z2z1MNHGxj8!Nlh7HB0XZ
    zmgDoXq}SfVvu=qf>z|WDm3yl-_;3;(Rb
    z17|V*X$*NbG-EaTa_?Cknc($jV0Ei&5y^Z@h#^!(fC1C^exi#z~506hRb
    z|2FJMb^`QtUFZSmf$6PZniGdg4^(T?e2Cpr=FQ_*PtPJqBxf
    zzN?~NSxXAg1JKhc=LF~h=mF^I&~*TM0D3w!j_+o4fS&KF2%x6}2ZQOY4iwXQcWk#c
    zfF6JzfSwK=381IzLJye`VNDOL>FGQdL8S*OJsn2wZcdG
    zuC^Y7O3!yy)IR#|L`#4kfSyh{CqNHC4?s_ct^?2m(9@xDd^b-6^n6!E06iTz7))<<
    zpqS3PW4o;Z^Z@h#^mOP*06kq7ddP$b(_1jT)p;(0N)J?eI*i=kGAn={fF6LJ4qXSJ
    z2cV}zuwZ9N8+p6{xtee~UlmH<5fJ)Lq+fF6JzfSwLr2cQR_r$giTZk`6{`L2op
    zdOC10nBM9@F`akEc3T7J0q6nf>Clk?db%$3kO>i{w_tj!^IQa#9;ozm7`eY?RscN!
    zJper&x(+}OKu?Fp@vXSpdJHN(-&Ilj=(`gw0eS#>I^~=IJperbJsr9ZKo3AqhsN>U
    zJPpwET^0Qj^d!EpcP=GRe%pVxu9*EW1`{tqR!Wna2~__MeLA|I7E-UxBhZ}X&_bdu
    z&JUix1v{}v625nfNT==%R=ugH{y8fJ6ZJUN$jXuKJ1omt^%n1XuN$SDVyi!H5oo^q
    zz4F1hAA!~jlGYTcc(N-zIn_tpYnEQM^0F%yDMl;OE6zR_ooMD=whsSLLm*ZSSF_Ca
    zSK{3-a9S7NRg?|t)A<&h2+mjDZ**$Y|n_WSm6arnYb$BA)
    zs+(!`?D`|G*rrTx0^Po7k11szHEiBirgi`J$rlB6@>9}9B3^NNafWDcU18EpI~&J+
    z7Wfs;(t@TPOB)>usw;XOv^NiB3m?-q;qLoFhu4eBMM2dX;nVyl*KpKd@n`4X7Ueai
    z2p9df`}I)P@Nu|$zyI3H9kV&~e$<~6^?hS;CzPmbqa_0Ly)#a`FEZp&f<+2xhA-9GzS(S;jT1Tv{%
    zu}gP}jy0TJN>d3d$6@7_O7NhdQLs^PCJ0XuM&HSSjy4c2!W8_rCIUOF=VFn2#MhNgy7ldFU!!MW4*aSTcd+98z0Ymk5*q
    z2SEv73E&P86Cf}`c7PNKoB*%{PzYoU!-M~ZF;c7st~&chBgSLrD>HQ?(p2Peh*+
    z%_b1-jO^vjp;*S8G||ViE#jb<)iF8RN*vv5=UUQ^*H;jcGX|;cobjUqFwAPe86sQX%gTrY&akE2lfO01M%al5DW1W
    z@(1Kk;0NF*;78zR7(c-HsoReqeM@{8`$Z{urhQ&{0)d{*zkRx8742?}`%+%M$&5vu
    zkhx2g{*DV1zLht={ZT<_Wb>qt*sLqur^~Lac*hj(^d+|EiipFYt_&a0^frSQPjL1d#vBNIPJoLL!4K
    z^KzP})wye>xm6Nq-K%W&Z&+bsvf8YsbxT%aX?pM3W!Lk2S3cw=4-~9-*rl=Q_mw3N
    z#4C@q6g;1XUub-XC2-E}V%3{VzbYS`^PE78{489sFYkWdpM&MfGHo^v@>*oR>3qwu
    zjJ(%USRQACu^W5e^BD0Q!7ENx;Nw@3?AkbSk|KdpXJEk}qTS|XWviVKaB3YQ?dnU*
    zIlFiz+-L6xk_jcb)}gWzd+Xr)Qd}v@mgJ|f)*V`T7s!QAYb7b??XrSb1j@DHMK%g*
    zTQgN|i$F5D)7G*z`|N7O$R+G1pPII2E%T3fBkuXBsU+ELYP-j$rji8Kc9V5&EhTBM
    z?H)bgVL&q|0c@tt@xYr}BND_Jh`^AW$dvluo+#NehWPC~@#QvimZN>IV<3}gX
    zSRoM0zb8=HGr?OdzToUW0$uM%eniPB2l7uWN|uzC`CcD2VeOVY(M9sJk@QQ*g%x-v
    z`L`F9>f|z%rL5|y*amj(4sntpZmuA}Z}jGgol*%jEt(v9#q&yBCQ?R7A$8Q}uR8?NBu~JE6eM?Gf)NyUI<_)KaY^UgJfe`@_fLhQfK+%`-Ft
    z%@YcQOOkO;%zdm`?kVBf1P+~Q1O;z{V<)qOBzTr22sCL7h`J$=pVOXhQ%Wr}=
    zCvOWX7Op4I!}+DlJxWTOCwD(1Y3-5rs(J$XFz~|e=?FG4RU&N5iDM#8zK_*|2lc*X
    zaU!)!+(G0>AkXOps@rs5umMlt)eOB%peI>;Jn^_B$nbEN3T^TFYPK*YLpY;)8*Vo&
    zPDp+z-SfqU_|oVp1lmHbn(OKIk9PCl_yd0PP_xPwt$A3zW=3Jp=Eb=Cnr;|UNNZsf
    zim|6F2z0*N#miP#=)t+j)_xN(pWUne>7R9V;u%6Rn9y4Y6emz7jbj>Htaq0GT5!}r
    z6l=n6V5N|YE06O^8b272Ya)j;$WRmQhVxQmc1DvQauKJfhi738uf~$8s6dj6$R(B6
    zrqnv)p@OsJ_&9|NpHfkjRLmS~hfcRlLh6(zHm6}O_OW|<11-K%=|;2Wv$$*GMPAG7
    z+0$akDZDEV1S+n~VK?-QBaq7n!zO+inM8DRmBg_UhIyaVysX8QG>1)BNQ>gBktS5m
    zJHqS3F3xr#KSzWoPTwjhO~1x&?k}iz7u_S!Uj7GL(!8>bN#MCo8rr0kL<)e*e`_uV
    zaQV+=4gePbmmeM80Js3S{0xKuxB$5PWJw4rE>Lm#F_Qss0dN6ufr`t2ZYcD{ngCn?
    zTz)JIwc8AU3xLaynGApnfJ=MW_)ZBHDlSlQfr`uLxC&E6T>!fPE&wi{9qikSR{&f9
    zTmW34;?f042-dj38ke6nD*zV&7XTM>$s;Vz{ZT6UHs7{h1u8C3ae<1<=ePGDP;r5Z3shV_$5p7f
    zbOG!FxB$3(cCc@=E`SSw3xEq$T)H3$!Qxz4ocpt81>geU0^kCRbAQYR09*iEem28=
    zr#RO-T7sz}m@4|o2n65);PPW80~HsjxB$2SxB$5P=Z@zQp-XWe46+m^ov#T?p
    zP$*y={0E3CrJ1fyPF(jXZqBX~$HEl=D2c0RO!UL55MZQ4X=uUZ`78x8G8&>k2R6&wIz52%}t>DKYd77e%gxMklfpkTeM8>
    zx@Q#aqR-1d@B4XK=zaif+n{eYeqJ_zCjeP10qFJY^Rj^%05DeoaG|(cd9)?*;vX3q
    zW@l;|9UW~F;OlK7apUi*%4u0
    z-o9+(zXtJtykob^>UJGJOz~ad8}1tdPc;KZSwM&%yxk!_0g(ZrA?$#VFWuq)aJO#P
    zATdA2H8eC1;y{yY0#u7N0qtE8plc`s+T6Wx4dv5)n!dn17Hlyfejb|MuD+lJa7Zk
    zz%1Yiyn#Om2H_wYECI{FDzFx81lzzakPZ%lW8gG61G2ysa1C4sx4}J70?I%Ir~wV2
    z3ABSwC}gq}Wr_x+H-$wRL@}b6Q*0>?l(CeFlqr;1lz9|CN(d#2vV^jnvX-)$vWv2h
    za*XmToj%E_E=~lxjQW120^iRMO|ONarEhQZ~7v7B7Gfw7yT&x0zIGpkX}h|qT>u@Mn8rT
    z!;ay~n91;CL^D<~wlfYh&NB)aC5#$IyNryCw#*P28<}x3vt$;^#LKLc*&~xF^P9|l
    znQECfSy|cMvPQD@vTm|ovXQc@WOvG*l;z1jkgbvB%PGpS=mXdEL2#gutVXrLV?0_
    zg%(9cMLosgijx%s6qhRQQ2a&lhGM0nKuKN6P{~PYu2PiJ2BjlPzbQRcYEf2J9;`e{
    zdA4$-@&@H&%6ZB!mH8?fDkdtfDn2ThN}9?Al?N*Cnexm*Oh=|CGmg2Pd6rqse5)$2
    zI#|_7)k`%|HBI%BYN=|QnueO0nwwg%+B&u4YB$yD)n(NOtB+OpQD32cKs`^rT7#yc
    zui>QOt+8C=phkg4ji!v|5KULjg_>(MPifxOY|>KKvecTP6{D4=m7`UmP17E%?W!H5
    zouYk4`?0oAM_0#D$5&^y&S{+oIvu_G_8Qg8x7V6pnY~JS34619kL?}UdsFYM-Y@#l
    z`xy3_+$Xxv-aZ9=-uBh(JEE_5-!*;D^nKQk+Rw1xlz#F34)iPP*QVQF*F`r>cc*Ti
    z?%V#_{YUj**neyPtNmZIG*}L-0M=F(kM)MF#dc%|v3IcZ*-Zob4H!2dYQVk$cL#Lp
    z4bhvfm!y}e_d;Jm-&TKt{#N~5{icDefs+O<8F*sgvqAEMYzO%dN*z=yWr1Cx$#XP&VKgEHc<{@Mx&aP}`w_L-!25XGk@)GW0i0Gb}cu8d)0!
    z80|5-{{!QP;Xj1@u>XfrV>=M&CNE>_+ZMMM
    z?nB%cxnG_vGueG|+T_|PW>c0-DV(Y?l{@wL)b?qkr=?6Qn{F^YYI^Pr=8U;Bj?L)s
    z7~`?oqhhA%%!HY@XZ4vCFze!M+1WE@AD-PdXY8D9b86;V&0RJ3@lQj3iuviLXCKcX
    z&m1n3>%~1gk1@|<-tl=NFE_9KUTyPT=kK21fPWo%4e(3YhQcc&AxRD>=$fa
    zQ155&x5e+ZKgWN&|JwkkfL#I23&$-?U)T}o7I-9(2=WNZ43-O?7knv1JtQzBKeT^n
    zOz8bEqp($B6^rZ^ZClh7J|X;Y1SR69h>MY$5T=Tv45C&>RW5c|oVJ)BJtO*Tj9N@c
    zOi`?1?CRLMIOn)S@$`7__}nD}mMmLRnc$ePFOiZsKQR~6$5vo9OI?;8U8b-saM_)t
    zVM&{lT9!zoM;%Vd4`!cmN*Zu;2iTdTuuk(I=d}hL#+_Sc4PoEofZufbO
    z^J^|pF2r7F%JR>uxH#+L{Y&F7v@Hag}fW~H?G{YyLsuB?X9fa*0(PdSrwhX
    zV|C~JUF*9SifxK7-Wz@|`~JxLS08X5Tzfd?;q^zZk8YRzSaSdI^v6$1=ayDH@p)4J
    zH0Wvbv&GLk%a%T8JYVxd^~Ls={a)@bA6lMSVO^0^Ii|9xYHC$kwRd&HtB6;kniaLm
    zwcG1hb;s(>>#w|aetqxFoHsQMVGW&cSG`kvxBI=p`*V$>8jG4{Hq|tTHxnP$we)T|
    z(rVe7+veW(vOT!HvttdvH~*->R!}JP5Y}}@i)2MR#6!i|_yqhp5lj$7CAcv*CSU;o
    zlO_Q}NCR>}mZA=5(4t6ag3<@_!AGu`PwD%~UPv+ceH$uVX$Jco5F+9KaEf`CtqJX<
    zH2mLi17^y_KFM*XPcXt17JSP%))M%jh(qQ+ss;GSV4-W
    zWl%m}O$POkBhu
    z?z6yd${6S0cZa|1^|~=~w1r7%xSuKPGYmH!W^QV3ZVb0Dj))D3^olVKiO~OekUx$y
    z26mXj1H!t%QgU3c`Jqvf_Ii4f6Mg#pex1Q#pHB3TMf-GQxZ_AzMmwi)Ux{0%g@y(>
    z{MpMRP5-+7^9j3lofPU5upoAfSER3lk1#~c*kj(>RHL4ha(PLj@Tk3N!v^ymPRor&Lonw;!CT0M=T2B>Njni_@32P_z*
    zjE~2bM3&@3q0;CK8Cf}b1x2{Qc~wBA&}dXTjlrNph^8dK^?`{eXT|9VYp%KfH+7W2cC66R;v0Tsz6e^ugqsvOlMWIGZ3a&XcbqKiwMawHe3_i)=uP{6y(X`3F{Mds
    ze)xR_?SYn+gPJ8p>nhpT6)fpLD%q!keJp)KOxd-5j}n3A%04LmH0$qab^1RWbq?>I=@^~6otKOypvx1JTQmr
    zAxL-Lu)N-=#pQAvwv%7>LdYwcJ^DLcFLf!$qCuE}KlyIwv&bMo$_@O4s9}F*6Sug<
    zFN)jYhwBI|8aS)4a8}1ufk*X{sm&z>$l_UJoJFVG61cSqee9SSnRog(mf(KXq0w&$
    zU=|?vU2do(WJJZ8ZV
    zLpmgt8jubl9g-R((wal0Lr90D#R#c~KnBtwq(exDdh7wxT84N?dT$cx5YnL@*FwZY
    zNQV#)NfVMDRx^|zLir)79zZ&TbO`CtUzHY(myzoN8ZY~6#Qe=)XuM3Cte|mwsjV~8
    zp}*Cu?#(qCx0jx;K{|wVNNQu%y;A*?yO0hc9g-F!q#gnpNQeHZVs&>K;vvLCQa#W;
    zVE!iSh=&jl^(=xU8ijO7st*wlAss?IBn@c();|5a9gq$o9g^w+q(exD{++D+YgIxz
    zB()YI9zr^VbO`AXde0TT=h`g=gPy1E=8P|>1A3nN3y%5Jo}lL#rScbgo|>G$(0i^@
    zdp$^pkPb-=l24lag)NZ|AsvzyBcvWe@3~5!O;gsNQV#)N$XgBp))}mI^B+mbO`B?R1c5_6XGGnLp_Ti#6w>t;)sWk4j~@u#x7q~
    zYe-|}?*~IXBvs3i4w1$b;vvLCQtJ?D1R);!DrHAHL>fg%hmZ~-9g;pG_*Gg%R@0CU
    zk$J}e=@8N(q(exD{^|krzP)r^K=Xe5Jwx;7_8PrkCRJO}`(@;Og63oVbCvpsUr2|L
    z4*f$|{JYTzq(exD{$0fU&0k1|kPaao>ahp@R%S_99SFex;m)f2S0C@ayvjbVE}fe>wc%Oz@fn^4Z4aB@2}KG4xU@#XN+s{}~HO1X9KtqaDEKU~HeahU)=6=Rvj
    z%$svAhhDzu{{32o>QKH%GXd_+;C8k#3829(OK(;=>n7+h6=@TohyW41DyNGncv1^f
    zq~=0^ZL%UGJ^|{DOvS=v0<1oO4|p6v0EZd^B$W%2MdPB?;L$w2;7
    zQD-Wyh}E*12Rw%-cZ^NO1OOzl&3)yCA*gJ(q7xfE`$V@*;S7wJg3~3IPn6e|Cn8
    z$m!%mJmEG07`zrHf8%?7czIXypfXG*K#d~-6mX7E0j^HmM}R7S0{k4c3oE{aRb=7N
    z0qVN>SgXzstYQsEbd*!cErbP_g*86nh$gYR`x3eQ;YSN?X0e_|EZL!K07lLt=Z_g5BXqoe?DZ<+IMFtZtb#sj&C16FI~E
    z?>CfSXRp5WT)f!t;p(P2ll;dd&%CVUyeKWm4;O0)YkBsGI(4Eu;cn3cFgb){>rY`8
    zRq1aFtBnY7BhTgnuSIz@K8XNl7dBqa7WjK`WLlekv|5{9_?7^okaG|WXYFlI#TBqx
    z4*#%CuN>@LL<*-ph*Mi{dc%!BbvvuI*Chhn#BduI(deR%bG)Xh1TZ5&fmuu*zG`?O
    zuHnTKjKgww{{jKDpctP3Q97GbrR|q<2!eJxp1n^yRk~^z698sEE;;7DO8$E
    zfLA;M^o5YVApRMbKU6}z=$Oc#D3(w?LK=ef6SWL5C@Iw1C`TjiCvYNQgN;@HQG>8dL^uz51>5R1y
    z&+_H9sx61v%m@f{G<;xSGOvD!Df|s7QIdvKj*Tb4s5ytpDp-WJTjjnb^G_
    zx$vwMadD1|Xu@Kc?RD(M
    z5$SO7QJgC0i}838%+-ptIFh7qX)3Rk0aN0<3p`O`3V-|CEIer##y7!4OR@a*VI5*R
    zOfK^cF-a0N(-f;$OdtRjjPb>+X5*)!V){G+G(pl809fumm5oCA+i<}&xWFCD^Ynz}
    z((c6ZXONhMoT@oz%7t>*psS(ZKTweGk?&F5ca72@%|V)j^d7afsIBcrY>0EdBV)>8
    zfw!xeBG=GtmLM>gkKGRWR2w}L??P^6GwZGLvI%gmrV+1{P^sp8@u|j@&$8O>1$lnr
    zC|+jfo(g4PUKmXPsJ6q!hbcyaych`0O#>caYXw0V-2lV$s*UQ
    zvj*L1dn=P;zX#I!>vX#qzG1z-JviOR&Zoh~9%9
    zLI@sln^Ql+6yCb&Ji$z?z}j{MzT6xW4bFt@Ps97mM-yOl`w0lqKR`$}N#Sp~au#3S
    zbq+h8u)dpWP(VhFsDh491~oXUz+tkrZOuj4~80X9pz7w8PgODL95eL$*#v=y}v
    zs1-%5fq3bEkSaxbEoq`^k&*EBp6JvU8ttr8ZZ}5O62KNd89cl+HsL-KEkOQ2;qYHt
    z8RVRY
    zsu>@E&46i>tX(4PhD}yxy+Qi}{1omOY6V~5*cckhy*K&YA@Lkh(#ybRxS8aT2g)W0
    zvjmJQrPa7&P7dbiav`-X^n+q-W}#?#d>o#X5^VaW{FQbKH$@=R-X>=Bf5t80-7rR1
    zfP8@B;QzBO=)Za<*utOrm$?MK!R!rPXHaeBIE~VRFE@E|Ub5~SwGF_oWHu)rZO@bw
    zLzOCC_1d%uUsJ)YgbBthto6Vn7spmDm!am>_OW2Gz;lYl16T~&x+BTQ-F)r^5@%S~ZO`Vyp
    ziGHmfR061^i!T%4Q2+gQ%#2JI{3j^hMTw6uc>X-Q=*Zly7S1vYa
    zQ@fYIh~s={6yo0P=g+i`e(Y-x--yp$_U%Kb>kP6t+gj?HE`FC-Wq<+oiK~_xy5Lu^
    zE1Wd-dx^+xdFoK&o|
    zg?0W^>VECBL*I+JwVHC@NfsR3GSfLLbEVJU(S07u|1^{+Os7^$$`nppwYXCBZ279x
    z&RYb~d6TlRDdk0qs6*>@WrycxQE~lg2CmELgq_Xt_G2Phj-Dx^%Q$a`_*77i>iL~+
    z(Qn{ur5TRjM-?a^5|#)=Cf{1=ey13-qmDdGeNI>WP)q?<5M$Ee&B3A9&2K?{HGcTzh9LB9*l7rzh$kvDD#g1#6!U2=*bNSbaU
    z2$It7A_yX9Hv~b_Pzpg1Sp*>nB5%S_CP>;$jtGLtBM3ndf*|q;k(y6J5Jc95DF6gP
    z2!hCa>f{M)1VPdS3T1-G;|oC$c?2N{LJ&kAAqawcIP8HS2tg2eBZVNSXU{1i2qKR!
    z1VQ9Y9D*POLF5sFAP7N_G>Yk28|IFN!^m=pC=(=2pb!Kh28bJ_(pl|wSHG&`nK?s7R^~T9Thipg{
    z4Tq6O7s>=li#-HE2!apdz1hoMZ6
    z)c8UWgdhkFhmntG^+18pGeP7H7
    Date: Wed, 6 Nov 2013 22:18:23 -0500
    Subject: [PATCH 76/82] Bug 935701 - Fix bustage on CLOSED TREE. r=bustage
    
    --HG--
    extra : rebase_source : b7586d185b814dcaa63a50a7ca932abb9759baea
    ---
     gfx/thebes/gfxPlatform.cpp | 5 +++++
     1 file changed, 5 insertions(+)
    
    diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp
    index 40e6e799a0fd..1957a7fed388 100644
    --- a/gfx/thebes/gfxPlatform.cpp
    +++ b/gfx/thebes/gfxPlatform.cpp
    @@ -15,6 +15,11 @@
     
     #include "gfxPlatform.h"
     
    +#ifdef XP_WIN
    +#include 
    +#define getpid _getpid
    +#endif
    +
     #include "nsXULAppAPI.h"
     #include "nsDirectoryServiceUtils.h"
     #include "nsDirectoryServiceDefs.h"
    
    From 5ccd288bd0422f94ccedd47f7ebeb8f115b86380 Mon Sep 17 00:00:00 2001
    From: Matthew Gregan 
    Date: Thu, 7 Nov 2013 17:08:30 +1300
    Subject: [PATCH 77/82] Bug 935349 - Remove disabled DASH code.  r=doublec
    
    ---
     configure.in                                  |    2 -
     content/media/dash/DASHDecoder.cpp            | 1387 -----------------
     content/media/dash/DASHDecoder.h              |  412 -----
     content/media/dash/DASHReader.cpp             |  674 --------
     content/media/dash/DASHReader.h               |  303 ----
     content/media/dash/DASHRepDecoder.cpp         |  517 ------
     content/media/dash/DASHRepDecoder.h           |  237 ---
     content/media/dash/DASHRepReader.h            |   68 -
     content/media/dash/Makefile.in                |   19 -
     content/media/dash/moz.build                  |   25 -
     content/media/moz.build                       |    3 -
     layout/build/Makefile.in                      |    6 -
     layout/build/nsContentDLF.h                   |   10 +-
     modules/libpref/src/init/all.js               |    3 -
     netwerk/build/Makefile.in                     |    5 -
     netwerk/dash/moz.build                        |    7 -
     netwerk/dash/mpd/AdaptationSet.cpp            |  122 --
     netwerk/dash/mpd/AdaptationSet.h              |  107 --
     netwerk/dash/mpd/IMPDManager.cpp              |   54 -
     netwerk/dash/mpd/IMPDManager.h                |  133 --
     netwerk/dash/mpd/IMPDParser.h                 |   53 -
     netwerk/dash/mpd/MPD.cpp                      |   91 --
     netwerk/dash/mpd/MPD.h                        |   90 --
     netwerk/dash/mpd/Makefile.in                  |   15 -
     netwerk/dash/mpd/Period.cpp                   |   98 --
     netwerk/dash/mpd/Period.h                     |   96 --
     netwerk/dash/mpd/Representation.cpp           |  120 --
     netwerk/dash/mpd/Representation.h             |  137 --
     netwerk/dash/mpd/SegmentBase.cpp              |  106 --
     netwerk/dash/mpd/SegmentBase.h                |  100 --
     netwerk/dash/mpd/moz.build                    |   24 -
     netwerk/dash/mpd/nsDASHMPDParser.cpp          |  219 ---
     netwerk/dash/mpd/nsDASHMPDParser.h            |   78 -
     netwerk/dash/mpd/nsDASHWebMODManager.cpp      |  236 ---
     netwerk/dash/mpd/nsDASHWebMODManager.h        |  104 --
     netwerk/dash/mpd/nsDASHWebMODParser.cpp       |  604 -------
     netwerk/dash/mpd/nsDASHWebMODParser.h         |  159 --
     netwerk/mime/nsMimeTypes.h                    |    3 -
     netwerk/moz.build                             |    3 -
     .../exthandler/nsExternalHelperAppService.cpp |    6 -
     40 files changed, 1 insertion(+), 6435 deletions(-)
     delete mode 100644 content/media/dash/DASHDecoder.cpp
     delete mode 100644 content/media/dash/DASHDecoder.h
     delete mode 100644 content/media/dash/DASHReader.cpp
     delete mode 100644 content/media/dash/DASHReader.h
     delete mode 100644 content/media/dash/DASHRepDecoder.cpp
     delete mode 100644 content/media/dash/DASHRepDecoder.h
     delete mode 100644 content/media/dash/DASHRepReader.h
     delete mode 100644 content/media/dash/Makefile.in
     delete mode 100644 content/media/dash/moz.build
     delete mode 100644 netwerk/dash/moz.build
     delete mode 100644 netwerk/dash/mpd/AdaptationSet.cpp
     delete mode 100644 netwerk/dash/mpd/AdaptationSet.h
     delete mode 100644 netwerk/dash/mpd/IMPDManager.cpp
     delete mode 100644 netwerk/dash/mpd/IMPDManager.h
     delete mode 100644 netwerk/dash/mpd/IMPDParser.h
     delete mode 100644 netwerk/dash/mpd/MPD.cpp
     delete mode 100644 netwerk/dash/mpd/MPD.h
     delete mode 100644 netwerk/dash/mpd/Makefile.in
     delete mode 100644 netwerk/dash/mpd/Period.cpp
     delete mode 100644 netwerk/dash/mpd/Period.h
     delete mode 100644 netwerk/dash/mpd/Representation.cpp
     delete mode 100644 netwerk/dash/mpd/Representation.h
     delete mode 100644 netwerk/dash/mpd/SegmentBase.cpp
     delete mode 100644 netwerk/dash/mpd/SegmentBase.h
     delete mode 100644 netwerk/dash/mpd/moz.build
     delete mode 100644 netwerk/dash/mpd/nsDASHMPDParser.cpp
     delete mode 100644 netwerk/dash/mpd/nsDASHMPDParser.h
     delete mode 100644 netwerk/dash/mpd/nsDASHWebMODManager.cpp
     delete mode 100644 netwerk/dash/mpd/nsDASHWebMODManager.h
     delete mode 100644 netwerk/dash/mpd/nsDASHWebMODParser.cpp
     delete mode 100644 netwerk/dash/mpd/nsDASHWebMODParser.h
    
    diff --git a/configure.in b/configure.in
    index 4cb9f733dd10..9a7495b7794a 100644
    --- a/configure.in
    +++ b/configure.in
    @@ -3929,7 +3929,6 @@ MOZ_SAMPLE_TYPE_FLOAT32=
     MOZ_SAMPLE_TYPE_S16=
     MOZ_OPUS=1
     MOZ_WEBM=1
    -MOZ_DASH=
     MOZ_DIRECTSHOW=
     MOZ_WMF=
     MOZ_WEBRTC=1
    @@ -8633,7 +8632,6 @@ AC_SUBST(MOZ_VORBIS)
     AC_SUBST(MOZ_TREMOR)
     AC_SUBST(MOZ_OPUS)
     AC_SUBST(MOZ_WEBM)
    -AC_SUBST(MOZ_DASH)
     AC_SUBST(MOZ_WMF)
     AC_SUBST(MOZ_DIRECTSHOW)
     AC_SUBST(MOZ_MEDIA_PLUGINS)
    diff --git a/content/media/dash/DASHDecoder.cpp b/content/media/dash/DASHDecoder.cpp
    deleted file mode 100644
    index b85763828efa..000000000000
    --- a/content/media/dash/DASHDecoder.cpp
    +++ /dev/null
    @@ -1,1387 +0,0 @@
    -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
    -/* vim:set ts=2 sw=2 sts=2 et cindent: */
    -
    -/* This Source Code Form Is subject to the terms of the Mozilla Public
    - * License, v. 2.0. If a copy of the MPL was not distributed with this file,
    - * You can obtain one at http://mozilla.org/MPL/2.0/. */
    -
    -/* DASH - Dynamic Adaptive Streaming over HTTP.
    - *
    - * DASH is an adaptive bitrate streaming technology where a multimedia file is
    - * partitioned into one or more segments and delivered to a client using HTTP.
    - *
    - * Interaction with MediaDecoderStateMachine, HTMLMediaElement,
    - * ChannelMediaResource and sub-decoders (WebMDecoder).
    - *
    - *
    - *        MediaDecoderStateMachine      HTMLMediaElement
    - *               1 /           \ 1           / 1
    - *                /             \           /
    - *             1 /               \ 1       / 1
    - * DASHReader ------ DASHDecoder ------------ ChannelMediaResource
    - *          |1          1      1     |1      \1             (for MPD Manifest)
    - *          |                        |        ------------
    - *          |*                       |*                   \*
    - *     WebMReader ------- DASHRepDecoder ------- ChannelMediaResource
    - *                 1       1                      1       1 (for media streams)
    - *
    - * One decoder and state-machine, as with current, non-DASH decoders.
    - *
    - * DASH adds multiple readers, decoders and resources, in order to manage
    - * download and decode of the MPD manifest and individual media streams.
    - *
    - * Rep/|Representation| is for an individual media stream, e.g. audio
    - * DASHRepDecoder is the decoder for a rep/|Representation|.
    - *
    - * FLOW
    - *
    - * 1 - Download and parse the MPD (DASH XML-based manifest).
    - *
    - * Media element creates new |DASHDecoder| object:
    - *   member var initialization to default values, including a/v sub-decoders.
    - *   MediaDecoder and MediaDecoder constructors are called.
    - *   MediaDecoder::Init() is called.
    - *
    - * Media element creates new |ChannelMediaResource|:
    - *   used to download MPD manifest.
    - *
    - * Media element calls |DASHDecoder|->Load() to download the MPD file:
    - *   creates an |DASHReader| object to forward calls to multiple
    - *     WebMReaders (corresponding to MPD |Representation|s i.e. streams).
    - *     Note: 1 |DASHReader| per DASH/WebM MPD.
    - *
    - *   also calls |ChannelMediaResource|::Open().
    - *     uses nsHttpChannel to download MPD; notifies DASHDecoder.
    - *
    - * Meanwhile, back in |DASHDecoder|->Load():
    - *   MediaDecoderStateMachine is created.
    - *     has ref to |DASHReader| object.
    - *     state machine is scheduled.
    - *
    - * Media element finishes decoder setup:
    - *   element added to media URI table etc.
    - *
    - * -- At this point, objects are waiting on HTTP returning MPD data.
    - *
    - * MPD Download (Async |ChannelMediaResource| channel callbacks):
    - *   calls DASHDecoder::|NotifyDownloadEnded|().
    - *     DASHDecoder parses MPD XML to DOM to MPD classes.
    - *       gets |Segment| URLs from MPD for audio and video streams.
    - *       creates |nsIChannel|s, |ChannelMediaResource|s.
    - *         stores resources as member vars (to forward function calls later).
    - *       creates |WebMReader|s and |DASHRepDecoder|s.
    - *         DASHreader creates |WebMReader|s.
    - *         |Representation| decoders are connected to the |ChannelMediaResource|s.
    - *
    - *     |DASHDecoder|->|LoadRepresentations|() starts download and decode.
    - *
    - *
    - * 2 - Media Stream, Byte Range downloads.
    - *
    - * -- At this point the Segment media stream downloads are managed by
    - *    individual |ChannelMediaResource|s and |WebMReader|s.
    - *    A single |DASHDecoder| and |MediaDecoderStateMachine| manage them
    - *    and communicate to |HTMLMediaElement|.
    - *
    - * Each |DASHRepDecoder| gets init range and index range from its MPD
    - * |Representation|. |DASHRepDecoder| uses ChannelMediaResource to start the
    - * byte range downloads, calling |OpenByteRange| with a |MediaByteRange|
    - * object.
    - * Once the init and index segments have been downloaded and |ReadMetadata| has
    - * completed, each |WebMReader| notifies it's peer |DASHRepDecoder|.
    - * Note: the decoder must wait until index data is parsed because it needs to
    - *       get the offsets of the subsegments (WebM clusters) from the media file
    - *       itself.
    - * Since byte ranges for subsegments are obtained, |nsDASHRepdecoder| continues
    - * downloading the files in byte range chunks.
    - *
    - * XXX Note that this implementation of DASHRepDecoder is focused on DASH
    - *     WebM On Demand profile: on the todo list is an action item to make this
    - *     more abstract.
    - *
    - * Note on |Seek|: Currently, |MediaCache| requires that seeking start at the
    - *                 beginning of the block in which the desired offset would be
    - *                 found. As such, when |ChannelMediaResource| does a seek
    - *                 using DASH WebM subsegments (clusters), it requests a start
    - *                 offset that corresponds to the beginning of the block, not
    - *                 the start offset of the cluster. For DASH Webm, which has
    - *                 media encoded in single files, this is fine. Future work on
    - *                 other profiles will require this to be re-examined.
    - */
    -
    -#include 
    -#include 
    -#include "nsIURI.h"
    -#include "nsIFileURL.h"
    -#include "nsNetUtil.h"
    -#include "VideoUtils.h"
    -#include "nsThreadUtils.h"
    -#include "nsContentUtils.h"
    -#include "nsIContentPolicy.h"
    -#include "nsIContentSecurityPolicy.h"
    -#include "nsICachingChannel.h"
    -#include "MediaDecoderStateMachine.h"
    -#include "WebMDecoder.h"
    -#include "WebMReader.h"
    -#include "DASHReader.h"
    -#include "nsDASHMPDParser.h"
    -#include "DASHRepDecoder.h"
    -#include "DASHDecoder.h"
    -#include 
    -
    -namespace mozilla {
    -
    -#ifdef PR_LOGGING
    -extern PRLogModuleInfo* gMediaDecoderLog;
    -#define LOG(msg, ...) PR_LOG(gMediaDecoderLog, PR_LOG_DEBUG, \
    -                             ("%p [DASHDecoder] " msg, this, __VA_ARGS__))
    -#define LOG1(msg) PR_LOG(gMediaDecoderLog, PR_LOG_DEBUG, \
    -                         ("%p [DASHDecoder] " msg, this))
    -#else
    -#define LOG(msg, ...)
    -#define LOG1(msg)
    -#endif
    -
    -DASHDecoder::DASHDecoder() :
    -  MediaDecoder(),
    -  mNotifiedLoadAborted(false),
    -  mBuffer(nullptr),
    -  mBufferLength(0),
    -  mMPDReaderThread(nullptr),
    -  mPrincipal(nullptr),
    -  mDASHReader(nullptr),
    -  mVideoAdaptSetIdx(-1),
    -  mAudioRepDecoderIdx(-1),
    -  mVideoRepDecoderIdx(-1),
    -  mAudioSubsegmentIdx(0),
    -  mVideoSubsegmentIdx(0),
    -  mAudioMetadataReadCount(0),
    -  mVideoMetadataReadCount(0),
    -  mSeeking(false),
    -  mStatisticsLock("DASHDecoder.mStatisticsLock")
    -{
    -  MOZ_COUNT_CTOR(DASHDecoder);
    -  mAudioStatistics = new MediaChannelStatistics();
    -  mVideoStatistics = new MediaChannelStatistics();
    -}
    -
    -DASHDecoder::~DASHDecoder()
    -{
    -  MOZ_COUNT_DTOR(DASHDecoder);
    -}
    -
    -MediaDecoderStateMachine*
    -DASHDecoder::CreateStateMachine()
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -  return new MediaDecoderStateMachine(this, mDASHReader);
    -}
    -
    -void
    -DASHDecoder::ReleaseStateMachine()
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Must be on main thread.");
    -
    -  // Since state machine owns mDASHReader, remove reference to it.
    -  mDASHReader = nullptr;
    -
    -  MediaDecoder::ReleaseStateMachine();
    -  for (uint i = 0; i < mAudioRepDecoders.Length(); i++) {
    -    mAudioRepDecoders[i]->ReleaseStateMachine();
    -  }
    -  for (uint i = 0; i < mVideoRepDecoders.Length(); i++) {
    -    mVideoRepDecoders[i]->ReleaseStateMachine();
    -  }
    -}
    -
    -nsresult
    -DASHDecoder::Load(nsIStreamListener** aStreamListener,
    -                  MediaDecoder* aCloneDonor)
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -
    -  mDASHReader = new DASHReader(this);
    -
    -  nsresult rv = OpenResource(aStreamListener);
    -  NS_ENSURE_SUCCESS(rv, rv);
    -
    -  mDecoderStateMachine = CreateStateMachine();
    -  if (!mDecoderStateMachine) {
    -    LOG1("Failed to create state machine!");
    -    return NS_ERROR_FAILURE;
    -  }
    -  return NS_OK;
    -}
    -
    -void
    -DASHDecoder::NotifyDownloadEnded(nsresult aStatus)
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -
    -  // Should be no download ended notification if MPD Manager exists.
    -  if (mMPDManager) {
    -    LOG("Network Error! Repeated MPD download notification but MPD Manager "
    -        "[%p] already exists!", mMPDManager.get());
    -    NetworkError();
    -    return;
    -  }
    -
    -  if (NS_SUCCEEDED(aStatus)) {
    -    LOG1("MPD downloaded.");
    -
    -    // mPrincipal must be set on main thread before dispatch to parser thread.
    -    mPrincipal = GetCurrentPrincipal();
    -
    -    // Create reader thread for |ChannelMediaResource|::|Read|.
    -    nsCOMPtr event =
    -      NS_NewRunnableMethod(this, &DASHDecoder::ReadMPDBuffer);
    -    NS_ENSURE_TRUE_VOID(event);
    -
    -    nsresult rv = NS_NewNamedThread("DASH MPD Reader",
    -                                    getter_AddRefs(mMPDReaderThread),
    -                                    event,
    -                                    MEDIA_THREAD_STACK_SIZE);
    -    if (NS_FAILED(rv) || !mMPDReaderThread) {
    -      LOG("Error creating MPD reader thread: rv[%x] thread [%p].",
    -          rv, mMPDReaderThread.get());
    -      DecodeError();
    -      return;
    -    }
    -  } else if (aStatus == NS_BINDING_ABORTED) {
    -    LOG("MPD download has been cancelled by the user: aStatus [%x].", aStatus);
    -    if (mOwner) {
    -      mOwner->LoadAborted();
    -    }
    -    return;
    -  } else if (aStatus != NS_BASE_STREAM_CLOSED) {
    -    LOG("Network error trying to download MPD: aStatus [%x].", aStatus);
    -    NetworkError();
    -  }
    -}
    -
    -void
    -DASHDecoder::ReadMPDBuffer()
    -{
    -  NS_ASSERTION(!NS_IsMainThread(), "Should not be on main thread.");
    -
    -  LOG1("Started reading from the MPD buffer.");
    -
    -  int64_t length = mResource->GetLength();
    -  if (length <= 0 || length > DASH_MAX_MPD_SIZE) {
    -    LOG("MPD is larger than [%d]MB.", DASH_MAX_MPD_SIZE/(1024*1024));
    -    DecodeError();
    -    return;
    -  }
    -
    -  mBuffer = new char[length];
    -
    -  uint32_t count = 0;
    -  nsresult rv = mResource->Read(mBuffer, length, &count);
    -  // By this point, all bytes should be available for reading.
    -  if (NS_FAILED(rv) || count != length) {
    -    LOG("Error reading MPD buffer: rv [%x] count [%d] length [%d].",
    -        rv, count, length);
    -    DecodeError();
    -    return;
    -  }
    -  // Store buffer length for processing on main thread.
    -  mBufferLength = static_cast(length);
    -
    -  LOG1("Finished reading MPD buffer; back to main thread for parsing.");
    -
    -  // Dispatch event to Main thread to parse MPD buffer.
    -  nsCOMPtr event =
    -    NS_NewRunnableMethod(this, &DASHDecoder::OnReadMPDBufferCompleted);
    -  rv = NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
    -  if (NS_FAILED(rv)) {
    -    LOG("Error dispatching parse event to main thread: rv[%x]", rv);
    -    DecodeError();
    -    return;
    -  }
    -}
    -
    -void
    -DASHDecoder::OnReadMPDBufferCompleted()
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -
    -  if (mShuttingDown) {
    -    LOG1("Shutting down! Ignoring OnReadMPDBufferCompleted().");
    -    return;
    -  }
    -
    -  // Shutdown the thread.
    -  if (!mMPDReaderThread) {
    -    LOG1("Error: MPD reader thread does not exist!");
    -    DecodeError();
    -    return;
    -  }
    -  nsresult rv = mMPDReaderThread->Shutdown();
    -  if (NS_FAILED(rv)) {
    -    LOG("MPD reader thread did not shutdown correctly! rv [%x]", rv);
    -    DecodeError();
    -    return;
    -  }
    -  mMPDReaderThread = nullptr;
    -
    -  // Start parsing the MPD data and loading the media.
    -  rv = ParseMPDBuffer();
    -  if (NS_FAILED(rv)) {
    -    LOG("Error parsing MPD buffer! rv [%x]", rv);
    -    DecodeError();
    -    return;
    -  }
    -  rv = CreateRepDecoders();
    -  if (NS_FAILED(rv)) {
    -    LOG("Error creating decoders for Representations! rv [%x]", rv);
    -    DecodeError();
    -    return;
    -  }
    -
    -  rv = LoadRepresentations();
    -  if (NS_FAILED(rv)) {
    -    LOG("Error loading Representations! rv [%x]", rv);
    -    NetworkError();
    -    return;
    -  }
    -
    -  // Notify reader that it can start reading metadata. Sub-readers will still
    -  // block until sub-resources have downloaded data into the media cache.
    -  mDASHReader->ReadyToReadMetadata();
    -}
    -
    -nsresult
    -DASHDecoder::ParseMPDBuffer()
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -  NS_ENSURE_TRUE(mBuffer, NS_ERROR_NULL_POINTER);
    -
    -  LOG1("Started parsing the MPD buffer.");
    -
    -  // Parse MPD buffer and get root DOM element.
    -  nsAutoPtr parser;
    -  parser = new nsDASHMPDParser(mBuffer.forget(), mBufferLength, mPrincipal,
    -                               mResource->URI());
    -  mozilla::net::DASHMPDProfile profile;
    -  parser->Parse(getter_Transfers(mMPDManager), &profile);
    -  mBuffer = nullptr;
    -  NS_ENSURE_TRUE(mMPDManager, NS_ERROR_NULL_POINTER);
    -
    -  LOG("Finished parsing the MPD buffer. Profile is [%d].", profile);
    -
    -  return NS_OK;
    -}
    -
    -nsresult
    -DASHDecoder::CreateRepDecoders()
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -  NS_ENSURE_TRUE(mMPDManager, NS_ERROR_NULL_POINTER);
    -
    -  // Global settings for the presentation.
    -  int64_t startTime = mMPDManager->GetStartTime();
    -  SetDuration(mMPDManager->GetDuration());
    -  NS_ENSURE_TRUE(startTime >= 0 && mDuration > 0, NS_ERROR_ILLEGAL_VALUE);
    -
    -  // For each audio/video stream, create a |ChannelMediaResource| object.
    -
    -  for (uint32_t i = 0; i < mMPDManager->GetNumAdaptationSets(); i++) {
    -    IMPDManager::AdaptationSetType asType = mMPDManager->GetAdaptationSetType(i);
    -    if (asType == IMPDManager::DASH_VIDEO_STREAM) {
    -      mVideoAdaptSetIdx = i;
    -    }
    -    for (uint32_t j = 0; j < mMPDManager->GetNumRepresentations(i); j++) {
    -      // Get URL string.
    -      nsAutoString segmentUrl;
    -      nsresult rv = mMPDManager->GetFirstSegmentUrl(i, j, segmentUrl);
    -      NS_ENSURE_SUCCESS(rv, rv);
    -
    -      // Get segment |nsIURI|; use MPD's base URI in case of relative paths.
    -      nsCOMPtr url;
    -      rv = NS_NewURI(getter_AddRefs(url), segmentUrl, nullptr, mResource->URI());
    -      NS_ENSURE_SUCCESS(rv, rv);
    -#ifdef PR_LOGGING
    -      nsAutoCString newUrl;
    -      rv = url->GetSpec(newUrl);
    -      NS_ENSURE_SUCCESS(rv, rv);
    -      LOG("Using URL=\"%s\" for AdaptationSet [%d] Representation [%d]",
    -          newUrl.get(), i, j);
    -#endif
    -
    -      // 'file://' URLs are not supported.
    -      nsCOMPtr fileURL = do_QueryInterface(url);
    -      NS_ENSURE_FALSE(fileURL, NS_ERROR_ILLEGAL_VALUE);
    -
    -      // Create |DASHRepDecoder| objects for each representation.
    -      if (asType == IMPDManager::DASH_VIDEO_STREAM) {
    -        Representation const * rep = mMPDManager->GetRepresentation(i, j);
    -        NS_ENSURE_TRUE(rep, NS_ERROR_NULL_POINTER);
    -        rv = CreateVideoRepDecoder(url, rep);
    -        NS_ENSURE_SUCCESS(rv, rv);
    -      } else if (asType == IMPDManager::DASH_AUDIO_STREAM) {
    -        Representation const * rep = mMPDManager->GetRepresentation(i, j);
    -        NS_ENSURE_TRUE(rep, NS_ERROR_NULL_POINTER);
    -        rv = CreateAudioRepDecoder(url, rep);
    -        NS_ENSURE_SUCCESS(rv, rv);
    -      }
    -    }
    -  }
    -
    -  NS_ENSURE_TRUE(VideoRepDecoder(), NS_ERROR_NOT_INITIALIZED);
    -  NS_ENSURE_TRUE(AudioRepDecoder(), NS_ERROR_NOT_INITIALIZED);
    -
    -  return NS_OK;
    -}
    -
    -nsresult
    -DASHDecoder::CreateAudioRepDecoder(nsIURI* aUrl,
    -                                   mozilla::net::Representation const * aRep)
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -  NS_ENSURE_ARG(aUrl);
    -  NS_ENSURE_ARG(aRep);
    -  NS_ENSURE_TRUE(mOwner, NS_ERROR_NOT_INITIALIZED);
    -
    -  // Create subdecoder and init with media element.
    -  DASHRepDecoder* audioDecoder = new DASHRepDecoder(this);
    -  NS_ENSURE_TRUE(audioDecoder->Init(mOwner), NS_ERROR_NOT_INITIALIZED);
    -
    -  // Set current decoder to the first one created.
    -  if (mAudioRepDecoderIdx == -1) {
    -    mAudioRepDecoderIdx = 0;
    -  }
    -  mAudioRepDecoders.AppendElement(audioDecoder);
    -
    -  // Create sub-reader; attach to DASH reader and sub-decoder.
    -  WebMReader* audioReader = new WebMReader(audioDecoder);
    -  if (mDASHReader) {
    -    audioReader->SetMainReader(mDASHReader);
    -    mDASHReader->AddAudioReader(audioReader);
    -  }
    -  audioDecoder->SetReader(audioReader);
    -
    -  // Create media resource with URL and connect to sub-decoder.
    -  MediaResource* audioResource
    -    = CreateAudioSubResource(aUrl, static_cast(audioDecoder));
    -  NS_ENSURE_TRUE(audioResource, NS_ERROR_NOT_INITIALIZED);
    -
    -  audioDecoder->SetResource(audioResource);
    -  audioDecoder->SetMPDRepresentation(aRep);
    -
    -  LOG("Created audio DASHRepDecoder [%p]", audioDecoder);
    -
    -  return NS_OK;
    -}
    -
    -nsresult
    -DASHDecoder::CreateVideoRepDecoder(nsIURI* aUrl,
    -                                   mozilla::net::Representation const * aRep)
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -  NS_ENSURE_ARG(aUrl);
    -  NS_ENSURE_ARG(aRep);
    -  NS_ENSURE_TRUE(mOwner, NS_ERROR_NOT_INITIALIZED);
    -
    -  // Create subdecoder and init with media element.
    -  DASHRepDecoder* videoDecoder = new DASHRepDecoder(this);
    -  NS_ENSURE_TRUE(videoDecoder->Init(mOwner), NS_ERROR_NOT_INITIALIZED);
    -
    -  // Set current decoder to the first one created.
    -  if (mVideoRepDecoderIdx == -1) {
    -    mVideoRepDecoderIdx = 0;
    -  }
    -  mVideoRepDecoders.AppendElement(videoDecoder);
    -
    -  // Create sub-reader; attach to DASH reader and sub-decoder.
    -  WebMReader* videoReader = new WebMReader(videoDecoder);
    -  if (mDASHReader) {
    -    videoReader->SetMainReader(mDASHReader);
    -    mDASHReader->AddVideoReader(videoReader);
    -  }
    -  videoDecoder->SetReader(videoReader);
    -
    -  // Create media resource with URL and connect to sub-decoder.
    -  MediaResource* videoResource
    -    = CreateVideoSubResource(aUrl, static_cast(videoDecoder));
    -  NS_ENSURE_TRUE(videoResource, NS_ERROR_NOT_INITIALIZED);
    -
    -  videoDecoder->SetResource(videoResource);
    -  videoDecoder->SetMPDRepresentation(aRep);
    -
    -  LOG("Created video DASHRepDecoder [%p]", videoDecoder);
    -
    -  return NS_OK;
    -}
    -
    -MediaResource*
    -DASHDecoder::CreateAudioSubResource(nsIURI* aUrl,
    -                                    MediaDecoder* aAudioDecoder)
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -  NS_ENSURE_TRUE(aUrl, nullptr);
    -  NS_ENSURE_TRUE(aAudioDecoder, nullptr);
    -
    -  // Create channel for representation.
    -  nsCOMPtr channel;
    -  nsresult rv = CreateSubChannel(aUrl, getter_AddRefs(channel));
    -  NS_ENSURE_SUCCESS(rv, nullptr);
    -
    -  // Create resource for representation.
    -  MediaResource* audioResource
    -    = MediaResource::Create(aAudioDecoder, channel);
    -  NS_ENSURE_TRUE(audioResource, nullptr);
    -
    -  audioResource->RecordStatisticsTo(mAudioStatistics);
    -  return audioResource;
    -}
    -
    -MediaResource*
    -DASHDecoder::CreateVideoSubResource(nsIURI* aUrl,
    -                                    MediaDecoder* aVideoDecoder)
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -  NS_ENSURE_TRUE(aUrl, nullptr);
    -  NS_ENSURE_TRUE(aVideoDecoder, nullptr);
    -
    -  // Create channel for representation.
    -  nsCOMPtr channel;
    -  nsresult rv = CreateSubChannel(aUrl, getter_AddRefs(channel));
    -  NS_ENSURE_SUCCESS(rv, nullptr);
    -
    -  // Create resource for representation.
    -  MediaResource* videoResource
    -    = MediaResource::Create(aVideoDecoder, channel);
    -  NS_ENSURE_TRUE(videoResource, nullptr);
    -
    -  videoResource->RecordStatisticsTo(mVideoStatistics);
    -  return videoResource;
    -}
    -
    -nsresult
    -DASHDecoder::CreateSubChannel(nsIURI* aUrl, nsIChannel** aChannel)
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -  NS_ENSURE_ARG(aUrl);
    -
    -  NS_ENSURE_TRUE(mOwner, NS_ERROR_NULL_POINTER);
    -  HTMLMediaElement* element = mOwner->GetMediaElement();
    -  NS_ENSURE_TRUE(element, NS_ERROR_NULL_POINTER);
    -
    -  nsCOMPtr loadGroup =
    -    element->GetDocumentLoadGroup();
    -  NS_ENSURE_TRUE(loadGroup, NS_ERROR_NULL_POINTER);
    -
    -  // Check for a Content Security Policy to pass down to the channel
    -  // created to load the media content.
    -  nsCOMPtr channelPolicy;
    -  nsCOMPtr csp;
    -  nsresult rv = element->NodePrincipal()->GetCsp(getter_AddRefs(csp));
    -  NS_ENSURE_SUCCESS(rv,rv);
    -  if (csp) {
    -    channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
    -    channelPolicy->SetContentSecurityPolicy(csp);
    -    channelPolicy->SetLoadType(nsIContentPolicy::TYPE_MEDIA);
    -  }
    -  nsCOMPtr channel;
    -  rv = NS_NewChannel(getter_AddRefs(channel),
    -                     aUrl,
    -                     nullptr,
    -                     loadGroup,
    -                     nullptr,
    -                     nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY,
    -                     channelPolicy);
    -  NS_ENSURE_SUCCESS(rv,rv);
    -  NS_ENSURE_TRUE(channel, NS_ERROR_NULL_POINTER);
    -
    -  NS_ADDREF(*aChannel = channel);
    -  return NS_OK;
    -}
    -
    -nsresult
    -DASHDecoder::LoadRepresentations()
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -
    -  nsresult rv;
    -  {
    -    // Hold the lock while we do this to set proper lock ordering
    -    // expectations for dynamic deadlock detectors: decoder lock(s)
    -    // should be grabbed before the cache lock.
    -    ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
    -
    -    // Load the decoders for each |Representation|'s media streams.
    -    // XXX Prob ok to load all audio decoders, since there should only be one
    -    //     created, but need to review the rest of the file.
    -    if (AudioRepDecoder()) {
    -      rv = AudioRepDecoder()->Load();
    -      NS_ENSURE_SUCCESS(rv, rv);
    -      mAudioMetadataReadCount++;
    -    }
    -    // Load all video decoders.
    -    for (uint32_t i = 0; i < mVideoRepDecoders.Length(); i++) {
    -      rv = mVideoRepDecoders[i]->Load();
    -      NS_ENSURE_SUCCESS(rv, rv);
    -      mVideoMetadataReadCount++;
    -    }
    -    if (AudioRepDecoder()) {
    -      AudioRepDecoder()->SetStateMachine(mDecoderStateMachine);
    -    }
    -    for (uint32_t i = 0; i < mVideoRepDecoders.Length(); i++) {
    -      mVideoRepDecoders[i]->SetStateMachine(mDecoderStateMachine);
    -    }
    -  }
    -
    -  // Ensure decoder is set to play if its already been requested.
    -  if (mPlayState == PLAY_STATE_PLAYING) {
    -    mNextState = PLAY_STATE_PLAYING;
    -  }
    -
    -  // Now that subreaders are init'd, it's ok to init state machine.
    -  return InitializeStateMachine(nullptr);
    -}
    -
    -void
    -DASHDecoder::NotifyDownloadEnded(DASHRepDecoder* aRepDecoder,
    -                                 nsresult aStatus,
    -                                 int32_t const aSubsegmentIdx)
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -
    -  if (mShuttingDown) {
    -    LOG1("Shutting down! Ignoring NotifyDownloadEnded().");
    -    return;
    -  }
    -
    -  // MPD Manager must exist, indicating MPD has been downloaded and parsed.
    -  if (!mMPDManager) {
    -    LOG1("Network Error! MPD Manager must exist, indicating MPD has been "
    -        "downloaded and parsed");
    -    NetworkError();
    -    return;
    -  }
    -
    -  // Decoder for the media |Representation| must not be null.
    -  if (!aRepDecoder) {
    -    LOG1("Decoder for Representation is reported as null.");
    -    DecodeError();
    -    return;
    -  }
    -
    -  if (NS_SUCCEEDED(aStatus)) {
    -    LOG("Byte range downloaded: decoder [%p] subsegmentIdx [%d]",
    -        aRepDecoder, aSubsegmentIdx);
    -
    -    if (aSubsegmentIdx < 0) {
    -      LOG("Last subsegment for decoder [%p] was downloaded",
    -          aRepDecoder);
    -      return;
    -    }
    -
    -    ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
    -    nsRefPtr decoder = aRepDecoder;
    -    {
    -      if (!IsDecoderAllowedToDownloadSubsegment(aRepDecoder,
    -                                                aSubsegmentIdx)) {
    -        NS_WARNING("Decoder downloaded subsegment but it is not allowed!");
    -        LOG("Error! Decoder [%p] downloaded subsegment [%d] but it is not "
    -            "allowed!", aRepDecoder, aSubsegmentIdx);
    -        return;
    -      }
    -
    -      if (aRepDecoder == VideoRepDecoder() &&
    -          mVideoSubsegmentIdx == aSubsegmentIdx) {
    -        IncrementSubsegmentIndex(aRepDecoder);
    -      } else if (aRepDecoder == AudioRepDecoder() &&
    -          mAudioSubsegmentIdx == aSubsegmentIdx) {
    -        IncrementSubsegmentIndex(aRepDecoder);
    -      } else {
    -        return;
    -      }
    -
    -      // Do Stream Switching here before loading next bytes.
    -      // Audio stream switching not supported.
    -      if (aRepDecoder == VideoRepDecoder() &&
    -          (uint32_t)mVideoSubsegmentIdx < VideoRepDecoder()->GetNumDataByteRanges()) {
    -        nsresult rv = PossiblySwitchDecoder(aRepDecoder);
    -        if (NS_FAILED(rv)) {
    -          LOG("Failed possibly switching decoder rv[0x%x]", rv);
    -          DecodeError();
    -          return;
    -        }
    -        decoder = VideoRepDecoder();
    -      }
    -    }
    -
    -    // Check that decoder is valid.
    -    if (!decoder || (decoder != AudioRepDecoder() &&
    -                     decoder != VideoRepDecoder())) {
    -      LOG("Invalid decoder [%p]: video idx [%d] audio idx [%d]",
    -          decoder.get(), AudioRepDecoder(), VideoRepDecoder());
    -      DecodeError();
    -      return;
    -    }
    -
    -    // Before loading, note the index of the decoder which will downloaded the
    -    // next video subsegment.
    -    if (decoder == VideoRepDecoder()) {
    -      if (mVideoSubsegmentLoads.IsEmpty() ||
    -          (uint32_t)mVideoSubsegmentIdx >= mVideoSubsegmentLoads.Length()) {
    -        LOG("Appending decoder [%d] [%p] to mVideoSubsegmentLoads at index "
    -            "[%d] before load; mVideoSubsegmentIdx[%d].",
    -            mVideoRepDecoderIdx, VideoRepDecoder(),
    -            mVideoSubsegmentLoads.Length(), mVideoSubsegmentIdx);
    -        mVideoSubsegmentLoads.AppendElement(mVideoRepDecoderIdx);
    -      } else {
    -        // Change an existing load, and keep subsequent entries to help
    -        // determine if subsegments are cached already.
    -        LOG("Setting decoder [%d] [%p] in mVideoSubsegmentLoads at index "
    -            "[%d] before load; mVideoSubsegmentIdx[%d].",
    -            mVideoRepDecoderIdx, VideoRepDecoder(),
    -            mVideoSubsegmentIdx, mVideoSubsegmentIdx);
    -        mVideoSubsegmentLoads[mVideoSubsegmentIdx] = mVideoRepDecoderIdx;
    -      }
    -      LOG("Notifying switch decided for video subsegment [%d]",
    -          mVideoSubsegmentIdx);
    -      mon.NotifyAll();
    -    }
    -
    -    // Load the next range of data bytes. If the range is already cached,
    -    // this function will be called again to adaptively download the next
    -    // subsegment.
    -    bool resourceLoaded = false;
    -    if (decoder.get() == AudioRepDecoder()) {
    -      LOG("Requesting load for audio decoder [%p] subsegment [%d].",
    -        decoder.get(), mAudioSubsegmentIdx);
    -      if (mAudioSubsegmentIdx >= decoder->GetNumDataByteRanges()) {
    -        resourceLoaded = true;
    -      }
    -    } else if (decoder.get() == VideoRepDecoder()) {
    -      LOG("Requesting load for video decoder [%p] subsegment [%d].",
    -        decoder.get(), mVideoSubsegmentIdx);
    -      if (mVideoSubsegmentIdx >= decoder->GetNumDataByteRanges()) {
    -        resourceLoaded = true;
    -      }
    -    }
    -    if (resourceLoaded) {
    -      ResourceLoaded();
    -      return;
    -    }
    -    decoder->LoadNextByteRange();
    -  } else if (aStatus == NS_BINDING_ABORTED) {
    -    LOG("Media download has been cancelled by the user: aStatus[%x]", aStatus);
    -    if (mOwner) {
    -      mOwner->LoadAborted();
    -    }
    -    return;
    -  } else if (aStatus != NS_BASE_STREAM_CLOSED) {
    -    LOG("Network error trying to download MPD: aStatus [%x].", aStatus);
    -    NetworkError();
    -  }
    -}
    -
    -void
    -DASHDecoder::LoadAborted()
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -
    -  if (!mNotifiedLoadAborted && mOwner) {
    -    LOG1("Load Aborted! Notifying media element.");
    -    mOwner->LoadAborted();
    -    mNotifiedLoadAborted = true;
    -  }
    -}
    -
    -void
    -DASHDecoder::Suspend()
    -{
    -  MOZ_ASSERT(NS_IsMainThread());
    -  // Suspend MPD download if not yet complete.
    -  if (!mMPDManager && mResource) {
    -    LOG1("Suspending MPD download.");
    -    mResource->Suspend(true);
    -    return;
    -  }
    -
    -  // Otherwise, forward |Suspend| to active rep decoders.
    -  if (AudioRepDecoder()) {
    -    LOG("Suspending download for audio decoder [%p].", AudioRepDecoder());
    -    AudioRepDecoder()->Suspend();
    -  }
    -  if (VideoRepDecoder()) {
    -    LOG("Suspending download for video decoder [%p].", VideoRepDecoder());
    -    VideoRepDecoder()->Suspend();
    -  }
    -}
    -
    -void
    -DASHDecoder::Resume(bool aForceBuffering)
    -{
    -  MOZ_ASSERT(NS_IsMainThread());
    -  // Resume MPD download if not yet complete.
    -  if (!mMPDManager) {
    -    if (mResource) {
    -      LOG1("Resuming MPD download.");
    -      mResource->Resume();
    -    }
    -    if (aForceBuffering) {
    -      ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
    -      if (mDecoderStateMachine) {
    -        mDecoderStateMachine->StartBuffering();
    -      }
    -    }
    -  }
    -
    -  // Otherwise, forward |Resume| to active rep decoders.
    -  if (AudioRepDecoder()) {
    -    LOG("Resuming download for audio decoder [%p].", AudioRepDecoder());
    -    AudioRepDecoder()->Resume(aForceBuffering);
    -  }
    -  if (VideoRepDecoder()) {
    -    LOG("Resuming download for video decoder [%p].", VideoRepDecoder());
    -    VideoRepDecoder()->Resume(aForceBuffering);
    -  }
    -}
    -
    -void
    -DASHDecoder::Shutdown()
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -
    -  LOG1("Shutting down.");
    -
    -  // Notify reader of shutdown first.
    -  if (mDASHReader) {
    -    mDASHReader->NotifyDecoderShuttingDown();
    -  }
    -
    -  // Call parent class shutdown.
    -  MediaDecoder::Shutdown();
    -  NS_ENSURE_TRUE_VOID(mShuttingDown);
    -
    -  // Shutdown reader thread if not already done.
    -  if (mMPDReaderThread) {
    -    nsresult rv = mMPDReaderThread->Shutdown();
    -    NS_ENSURE_SUCCESS_VOID(rv);
    -    mMPDReaderThread = nullptr;
    -  }
    -
    -  // Forward to sub-decoders.
    -  for (uint i = 0; i < mAudioRepDecoders.Length(); i++) {
    -    if (mAudioRepDecoders[i]) {
    -      mAudioRepDecoders[i]->Shutdown();
    -    }
    -  }
    -  for (uint i = 0; i < mVideoRepDecoders.Length(); i++) {
    -    if (mVideoRepDecoders[i]) {
    -      mVideoRepDecoders[i]->Shutdown();
    -    }
    -  }
    -}
    -
    -void
    -DASHDecoder::DecodeError()
    -{
    -  if (NS_IsMainThread()) {
    -    MediaDecoder::DecodeError();
    -  } else {
    -    nsCOMPtr event =
    -      NS_NewRunnableMethod(this, &MediaDecoder::DecodeError);
    -    nsresult rv = NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
    -    if (NS_FAILED(rv)) {
    -      LOG("Error dispatching DecodeError event to main thread: rv[%x]", rv);
    -    }
    -  }
    -}
    -
    -void
    -DASHDecoder::OnReadMetadataCompleted(DASHRepDecoder* aRepDecoder)
    -{
    -  if (mShuttingDown) {
    -    LOG1("Shutting down! Ignoring OnReadMetadataCompleted().");
    -    return;
    -  }
    -
    -  NS_ASSERTION(aRepDecoder, "aRepDecoder is null!");
    -  NS_ASSERTION(OnDecodeThread(), "Should be on decode thread.");
    -
    -  LOG("Metadata loaded for decoder[%p]", aRepDecoder);
    -
    -  // Decrement audio|video metadata read counter and get ref to active decoder.
    -  nsRefPtr activeDecoder;
    -  {
    -    ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
    -    for (uint32_t i = 0; i < mAudioRepDecoders.Length(); i++) {
    -      if (aRepDecoder == mAudioRepDecoders[i]) {
    -        --mAudioMetadataReadCount;
    -        break;
    -      }
    -    }
    -    for (uint32_t i = 0; i < mVideoRepDecoders.Length(); i++) {
    -      if (aRepDecoder == mVideoRepDecoders[i]) {
    -        --mVideoMetadataReadCount;
    -        break;
    -      }
    -    }
    -  }
    -
    -  // Once all metadata is downloaded for audio|video decoders, start loading
    -  // data for the active decoder.
    -  if (mAudioMetadataReadCount == 0 && mVideoMetadataReadCount == 0) {
    -    if (AudioRepDecoder()) {
    -      LOG("Dispatching load event for audio decoder [%p]", AudioRepDecoder());
    -      nsCOMPtr event =
    -        NS_NewRunnableMethod(AudioRepDecoder(), &DASHRepDecoder::LoadNextByteRange);
    -      nsresult rv = NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
    -      if (NS_FAILED(rv)) {
    -        LOG("Error dispatching audio decoder [%p] load event to main thread: "
    -            "rv[%x]", AudioRepDecoder(), rv);
    -        DecodeError();
    -        return;
    -      }
    -    }
    -    if (VideoRepDecoder()) {
    -      LOG("Dispatching load event for video decoder [%p]", VideoRepDecoder());
    -      // Add decoder to subsegment load history.
    -      NS_ASSERTION(mVideoSubsegmentLoads.IsEmpty(),
    -                   "No subsegment loads should be recorded at this stage!");
    -      NS_ASSERTION(mVideoSubsegmentIdx == 0,
    -                   "Current subsegment should be 0 at this stage!");
    -      LOG("Appending decoder [%d] [%p] to mVideoSubsegmentLoads at index "
    -          "[%d] before load; mVideoSubsegmentIdx[%d].",
    -          mVideoRepDecoderIdx, VideoRepDecoder(),
    -          (uint32_t)mVideoSubsegmentLoads.Length(), mVideoSubsegmentIdx);
    -      mVideoSubsegmentLoads.AppendElement(mVideoRepDecoderIdx);
    -
    -      nsCOMPtr event =
    -        NS_NewRunnableMethod(VideoRepDecoder(), &DASHRepDecoder::LoadNextByteRange);
    -      nsresult rv = NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
    -      if (NS_FAILED(rv)) {
    -        LOG("Error dispatching video decoder [%p] load event to main thread: "
    -            "rv[%x]", VideoRepDecoder(), rv);
    -        DecodeError();
    -        return;
    -      }
    -    }
    -  }
    -}
    -
    -nsresult
    -DASHDecoder::PossiblySwitchDecoder(DASHRepDecoder* aRepDecoder)
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -  NS_ENSURE_FALSE(mShuttingDown, NS_ERROR_UNEXPECTED);
    -  NS_ENSURE_TRUE(aRepDecoder == VideoRepDecoder(), NS_ERROR_ILLEGAL_VALUE);
    -  NS_ASSERTION((uint32_t)mVideoRepDecoderIdx < mVideoRepDecoders.Length(),
    -               "Index for video decoder is out of bounds!");
    -  NS_ASSERTION((uint32_t)mVideoSubsegmentIdx < VideoRepDecoder()->GetNumDataByteRanges(),
    -               "Can't switch to a byte range out of bounds.");
    -  ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
    -
    -  // Now, determine if and which decoder to switch to.
    -  // XXX This download rate is averaged over time, and only refers to the bytes
    -  // downloaded for the video decoder. A running average would be better, and
    -  // something that includes all downloads. But this will do for now.
    -  NS_ASSERTION(VideoRepDecoder(), "Video decoder should not be null.");
    -  NS_ASSERTION(VideoRepDecoder()->GetResource(),
    -               "Video resource should not be null");
    -  bool reliable = false;
    -  double downloadRate = 0;
    -  {
    -    MutexAutoLock lock(mStatisticsLock);
    -    downloadRate = mVideoStatistics->GetRate(&reliable);
    -  }
    -  uint32_t bestRepIdx = UINT32_MAX;
    -  bool noRepAvailable = !mMPDManager->GetBestRepForBandwidth(mVideoAdaptSetIdx,
    -                                                             downloadRate,
    -                                                             bestRepIdx);
    -  LOG("downloadRate [%0.2f kbps] reliable [%s] bestRepIdx [%d] noRepAvailable [%s]",
    -      downloadRate/1000.0, (reliable ? "yes" : "no"), bestRepIdx,
    -      (noRepAvailable ? "yes" : "no"));
    -
    -  // If there is a higher bitrate stream that can be downloaded with the
    -  // current estimated bandwidth, step up to the next stream, for a graceful
    -  // increase in quality.
    -  uint32_t toDecoderIdx = mVideoRepDecoderIdx;
    -  if (bestRepIdx > toDecoderIdx) {
    -    toDecoderIdx = std::min(toDecoderIdx+1, mVideoRepDecoders.Length()-1);
    -  } else if (toDecoderIdx < bestRepIdx) {
    -    // If the bitrate is too much for the current bandwidth, just use that
    -    // stream directly.
    -    toDecoderIdx = bestRepIdx;
    -  }
    -
    -  // Upgrade |toDecoderIdx| if a better subsegment was previously downloaded and
    -  // is still cached.
    -  if (mVideoSubsegmentIdx < mVideoSubsegmentLoads.Length() &&
    -      toDecoderIdx < mVideoSubsegmentLoads[mVideoSubsegmentIdx]) {
    -    // Check if the subsegment is cached.
    -    uint32_t betterRepIdx = mVideoSubsegmentLoads[mVideoSubsegmentIdx];
    -    if (mVideoRepDecoders[betterRepIdx]->IsSubsegmentCached(mVideoSubsegmentIdx)) {
    -      toDecoderIdx = betterRepIdx;
    -    }
    -  }
    -
    -  NS_ENSURE_TRUE(toDecoderIdx < mVideoRepDecoders.Length(),
    -                 NS_ERROR_ILLEGAL_VALUE);
    -
    -  // Notify reader and sub decoders and do the switch.
    -  if (toDecoderIdx != (uint32_t)mVideoRepDecoderIdx) {
    -    LOG("*** Switching video decoder from [%d] [%p] to [%d] [%p] at "
    -        "subsegment [%d]", mVideoRepDecoderIdx, VideoRepDecoder(),
    -        toDecoderIdx, mVideoRepDecoders[toDecoderIdx].get(),
    -        mVideoSubsegmentIdx);
    -
    -    // Tell main reader to switch subreaders at |subsegmentIdx| - equates to
    -    // switching data source for reading.
    -    mDASHReader->RequestVideoReaderSwitch(mVideoRepDecoderIdx, toDecoderIdx,
    -                                          mVideoSubsegmentIdx);
    -    // Notify decoder it is about to be switched.
    -    mVideoRepDecoders[mVideoRepDecoderIdx]->PrepareForSwitch();
    -    // Switch video decoders - equates to switching download source.
    -    mVideoRepDecoderIdx = toDecoderIdx;
    -  }
    -
    -  return NS_OK;
    -}
    -
    -nsresult
    -DASHDecoder::Seek(double aTime)
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -  NS_ENSURE_FALSE(mShuttingDown, NS_ERROR_UNEXPECTED);
    -
    -  LOG("Seeking to [%.2fs]", aTime);
    -
    -  {
    -    ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
    -    // Set the seeking flag, so that when current subsegments download (if
    -    // any), the next subsegment will not be downloaded.
    -    mSeeking = true;
    -  }
    -
    -  return MediaDecoder::Seek(aTime);
    -}
    -
    -void
    -DASHDecoder::NotifySeekInVideoSubsegment(int32_t aRepDecoderIdx,
    -                                         int32_t aSubsegmentIdx)
    -{
    -  NS_ASSERTION(OnDecodeThread(), "Should be on decode thread.");
    -
    -  ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
    -
    -  NS_ASSERTION(0 <= aRepDecoderIdx &&
    -               aRepDecoderIdx < mVideoRepDecoders.Length(),
    -               "Video decoder index is out of bounds");
    -
    -  // Reset current subsegment to match the one being seeked.
    -  mVideoSubsegmentIdx = aSubsegmentIdx;
    -  // Reset current decoder to match the one returned by
    -  // |GetRepIdxForVideoSubsegmentLoad|.
    -  mVideoRepDecoderIdx = aRepDecoderIdx;
    -
    -  mSeeking = false;
    -
    -  LOG("Dispatching load for video decoder [%d] [%p]: seek in subsegment [%d]",
    -      mVideoRepDecoderIdx, VideoRepDecoder(), aSubsegmentIdx);
    -
    -  nsCOMPtr event =
    -    NS_NewRunnableMethod(VideoRepDecoder(),
    -                         &DASHRepDecoder::LoadNextByteRange);
    -  nsresult rv = NS_DispatchToMainThread(event);
    -  if (NS_FAILED(rv)) {
    -    LOG("Error dispatching video byte range load: rv[0x%x].",
    -        rv);
    -    NetworkError();
    -    return;
    -  }
    -}
    -
    -void
    -DASHDecoder::NotifySeekInAudioSubsegment(int32_t aSubsegmentIdx)
    -{
    -  NS_ASSERTION(OnDecodeThread(), "Should be on decode thread.");
    -
    -  ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
    -
    -  // Reset current subsegment to match the one being seeked.
    -  mAudioSubsegmentIdx = aSubsegmentIdx;
    -
    -  LOG("Dispatching seeking load for audio decoder [%d] [%p]: subsegment [%d]",
    -     mAudioRepDecoderIdx, AudioRepDecoder(), aSubsegmentIdx);
    -
    -  nsCOMPtr event =
    -    NS_NewRunnableMethod(AudioRepDecoder(),
    -                         &DASHRepDecoder::LoadNextByteRange);
    -  nsresult rv = NS_DispatchToMainThread(event);
    -  if (NS_FAILED(rv)) {
    -    LOG("Error dispatching audio byte range load: rv[0x%x].",
    -        rv);
    -    NetworkError();
    -    return;
    -  }
    -}
    -
    -bool
    -DASHDecoder::IsDecoderAllowedToDownloadData(DASHRepDecoder* aRepDecoder)
    -{
    -  NS_ASSERTION(aRepDecoder, "DASHRepDecoder pointer is null.");
    -
    -  ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
    -  LOG("Checking aRepDecoder [%p] with AudioRepDecoder [%p] metadataReadCount "
    -      "[%d] and VideoRepDecoder [%p] metadataReadCount [%d]",
    -      aRepDecoder, AudioRepDecoder(), mAudioMetadataReadCount,
    -      VideoRepDecoder(), mVideoMetadataReadCount);
    -  // Only return true if |aRepDecoder| is active and metadata for all
    -  // representations has been downloaded.
    -  return ((aRepDecoder == AudioRepDecoder() && mAudioMetadataReadCount == 0) ||
    -          (aRepDecoder == VideoRepDecoder() && mVideoMetadataReadCount == 0));
    -}
    -
    -bool
    -DASHDecoder::IsDecoderAllowedToDownloadSubsegment(DASHRepDecoder* aRepDecoder,
    -                                                  int32_t const aSubsegmentIdx)
    -{
    -  NS_ASSERTION(aRepDecoder, "DASHRepDecoder pointer is null.");
    -
    -  ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
    -
    -  // Forbid any downloads until we've been told what subsegment to seek to.
    -  if (mSeeking) {
    -    return false;
    -  }
    -  // Return false if there is still metadata to be downloaded.
    -  if (mAudioMetadataReadCount != 0 || mVideoMetadataReadCount != 0) {
    -    return false;
    -  }
    -  // No audio switching; allow the audio decoder to download all subsegments.
    -  if (aRepDecoder == AudioRepDecoder()) {
    -    return true;
    -  }
    -
    -  int32_t videoDecoderIdx = GetRepIdxForVideoSubsegmentLoad(aSubsegmentIdx);
    -  if (aRepDecoder == mVideoRepDecoders[videoDecoderIdx]) {
    -    return true;
    -  }
    -  return false;
    -}
    -
    -void
    -DASHDecoder::SetSubsegmentIndex(DASHRepDecoder* aRepDecoder,
    -                                int32_t aSubsegmentIdx)
    -{
    -  NS_ASSERTION(0 <= aSubsegmentIdx,
    -               "Subsegment index should not be negative!");
    -  ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
    -  if (aRepDecoder == AudioRepDecoder()) {
    -    mAudioSubsegmentIdx = aSubsegmentIdx;
    -  } else if (aRepDecoder == VideoRepDecoder()) {
    -    // If this is called in the context of a Seek, we need to cancel downloads
    -    // from other rep decoders, or all rep decoders if we're not seeking in the
    -    // current subsegment.
    -    // Note: NotifySeekInSubsegment called from DASHReader will already have
    -    // set the current decoder.
    -    mVideoSubsegmentIdx = aSubsegmentIdx;
    -  }
    -}
    -
    -double
    -DASHDecoder::ComputePlaybackRate(bool* aReliable)
    -{
    -  GetReentrantMonitor().AssertCurrentThreadIn();
    -  MOZ_ASSERT(NS_IsMainThread() || OnStateMachineThread());
    -  NS_ASSERTION(aReliable, "Bool pointer aRelible should not be null!");
    -
    -  // While downloading the MPD, return 0; do not count manifest as media data.
    -  if (mResource && !mMPDManager) {
    -    return 0;
    -  }
    -
    -  // Once MPD is downloaded, use the rate from the video decoder.
    -  // XXX Not ideal, but since playback rate is used to estimate if we have
    -  // enough data to continue playing, this should be sufficient.
    -  double videoRate = 0;
    -  if (VideoRepDecoder()) {
    -    videoRate = VideoRepDecoder()->ComputePlaybackRate(aReliable);
    -  }
    -  return videoRate;
    -}
    -
    -void
    -DASHDecoder::UpdatePlaybackRate()
    -{
    -  MOZ_ASSERT(NS_IsMainThread() || OnStateMachineThread());
    -  GetReentrantMonitor().AssertCurrentThreadIn();
    -  // While downloading the MPD, return silently; playback rate has no meaning
    -  // for the manifest.
    -  if (mResource && !mMPDManager) {
    -    return;
    -  }
    -  // Once MPD is downloaded and audio/video decoder(s) are loading, forward to
    -  // active rep decoders.
    -  if (AudioRepDecoder()) {
    -    AudioRepDecoder()->UpdatePlaybackRate();
    -  }
    -  if (VideoRepDecoder()) {
    -    VideoRepDecoder()->UpdatePlaybackRate();
    -  }
    -}
    -
    -void
    -DASHDecoder::NotifyPlaybackStarted()
    -{
    -  GetReentrantMonitor().AssertCurrentThreadIn();
    -  // While downloading the MPD, return silently; playback rate has no meaning
    -  // for the manifest.
    -  if (mResource && !mMPDManager) {
    -    return;
    -  }
    -  // Once MPD is downloaded and audio/video decoder(s) are loading, forward to
    -  // active rep decoders.
    -  if (AudioRepDecoder()) {
    -    AudioRepDecoder()->NotifyPlaybackStarted();
    -  }
    -  if (VideoRepDecoder()) {
    -    VideoRepDecoder()->NotifyPlaybackStarted();
    -  }
    -}
    -
    -void
    -DASHDecoder::NotifyPlaybackStopped()
    -{
    -  GetReentrantMonitor().AssertCurrentThreadIn();
    -  // While downloading the MPD, return silently; playback rate has no meaning
    -  // for the manifest.
    -  if (mResource && !mMPDManager) {
    -    return;
    -  }
    -  // Once  // Once MPD is downloaded and audio/video decoder(s) are loading, forward to
    -  // active rep decoders.
    -  if (AudioRepDecoder()) {
    -    AudioRepDecoder()->NotifyPlaybackStopped();
    -  }
    -  if (VideoRepDecoder()) {
    -    VideoRepDecoder()->NotifyPlaybackStopped();
    -  }
    -}
    -
    -MediaDecoder::Statistics
    -DASHDecoder::GetStatistics()
    -{
    -  MOZ_ASSERT(NS_IsMainThread() || OnStateMachineThread());
    -  Statistics result;
    -
    -  ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
    -  if (mResource && !mMPDManager) {
    -    return MediaDecoder::GetStatistics();
    -  }
    -
    -  // XXX Use video decoder and its media resource to get stats.
    -  // This assumes that the following getter functions are getting relevant
    -  // video data only.
    -  if (VideoRepDecoder() && VideoRepDecoder()->GetResource()) {
    -    MediaResource *resource = VideoRepDecoder()->GetResource();
    -    // Note: this rate reflects the rate observed for all video downloads.
    -    result.mDownloadRate =
    -      resource->GetDownloadRate(&result.mDownloadRateReliable);
    -    result.mDownloadPosition =
    -      resource->GetCachedDataEnd(VideoRepDecoder()->mDecoderPosition);
    -    result.mTotalBytes = resource->GetLength();
    -    result.mPlaybackRate = ComputePlaybackRate(&result.mPlaybackRateReliable);
    -    result.mDecoderPosition = VideoRepDecoder()->mDecoderPosition;
    -    result.mPlaybackPosition = VideoRepDecoder()->mPlaybackPosition;
    -  }
    -  else {
    -    result.mDownloadRate = 0;
    -    result.mDownloadRateReliable = true;
    -    result.mPlaybackRate = 0;
    -    result.mPlaybackRateReliable = true;
    -    result.mDecoderPosition = 0;
    -    result.mPlaybackPosition = 0;
    -    result.mDownloadPosition = 0;
    -    result.mTotalBytes = 0;
    -  }
    -
    -  return result;
    -}
    -
    -bool
    -DASHDecoder::IsDataCachedToEndOfResource()
    -{
    -  NS_ASSERTION(!mShuttingDown, "Don't call during shutdown!");
    -  GetReentrantMonitor().AssertCurrentThreadIn();
    -
    -  if (!mMPDManager || !mResource) {
    -    return false;
    -  }
    -
    -  bool resourceIsLoaded = false;
    -  if (VideoRepDecoder()) {
    -    resourceIsLoaded = VideoRepDecoder()->IsDataCachedToEndOfResource();
    -    LOG("IsDataCachedToEndOfResource for VideoRepDecoder %p = %s",
    -       VideoRepDecoder(), resourceIsLoaded ? "yes" : "no");
    -  }
    -  if (AudioRepDecoder()) {
    -    bool isAudioResourceLoaded =
    -      AudioRepDecoder()->IsDataCachedToEndOfResource();
    -    LOG("IsDataCachedToEndOfResource for AudioRepDecoder %p = %s",
    -       AudioRepDecoder(), isAudioResourceLoaded ? "yes" : "no");
    -    resourceIsLoaded = resourceIsLoaded && isAudioResourceLoaded;
    -  }
    -
    -  return resourceIsLoaded;
    -}
    -
    -void
    -DASHDecoder::StopProgressUpdates()
    -{
    -  MOZ_ASSERT(OnStateMachineThread() || OnDecodeThread());
    -  GetReentrantMonitor().AssertCurrentThreadIn();
    -  mIgnoreProgressData = true;
    -  for (uint32_t i = 0; i < mVideoRepDecoders.Length(); i++) {
    -    mVideoRepDecoders[i]->StopProgressUpdates();
    -  }
    -  for (uint32_t i = 0; i < mAudioRepDecoders.Length(); i++) {
    -    mAudioRepDecoders[i]->StopProgressUpdates();
    -  }
    -}
    -
    -void
    -DASHDecoder::StartProgressUpdates()
    -{
    -  MOZ_ASSERT(OnStateMachineThread() || OnDecodeThread());
    -  GetReentrantMonitor().AssertCurrentThreadIn();
    -  mIgnoreProgressData = false;
    -  for (uint32_t i = 0; i < mVideoRepDecoders.Length(); i++) {
    -    mVideoRepDecoders[i]->StartProgressUpdates();
    -  }
    -  for (uint32_t i = 0; i < mAudioRepDecoders.Length(); i++) {
    -    mAudioRepDecoders[i]->StartProgressUpdates();
    -  }
    -}
    -
    -int32_t
    -DASHDecoder::GetRepIdxForVideoSubsegmentLoadAfterSeek(int32_t aSubsegmentIndex)
    -{
    -  NS_ASSERTION(OnDecodeThread(), "Should be on decode thread.");
    -  ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
    -  // Should not be requesting decoder index for the first subsegment, nor any
    -  // after the final subsegment.
    -  if (aSubsegmentIndex < 1 ||
    -      aSubsegmentIndex >= VideoRepDecoder()->GetNumDataByteRanges()) {
    -    return -1;
    -  }
    -  // Wait if we are still loading the subsegment previous to the one that was
    -  // queried. Note: |mVideoSubsegmentIdx| should have been updated to reflect
    -  // loads of the seeked subsegment before |DASHRepReader|::|Seek| was called,
    -  // i.e. before this function was called.
    -  while (mVideoSubsegmentIdx == aSubsegmentIndex-1) {
    -    LOG("Waiting for switching decision for video subsegment [%d].",
    -        aSubsegmentIndex);
    -    mon.Wait();
    -  }
    -
    -  return mVideoSubsegmentLoads[aSubsegmentIndex];
    -}
    -
    -} // namespace mozilla
    diff --git a/content/media/dash/DASHDecoder.h b/content/media/dash/DASHDecoder.h
    deleted file mode 100644
    index adc9dfd453e5..000000000000
    --- a/content/media/dash/DASHDecoder.h
    +++ /dev/null
    @@ -1,412 +0,0 @@
    -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
    -/* vim:set ts=2 sw=2 sts=2 et cindent: */
    -
    -/* This Source Code Form Is subject to the terms of the Mozilla Public
    - * License, v. 2.0. If a copy of the MPL was not distributed with this file,
    - * You can obtain one at http://mozilla.org/MPL/2.0/. */
    -
    -/* DASH - Dynamic Adaptive Streaming over HTTP
    - *
    - * DASH is an adaptive bitrate streaming technology where a multimedia file is
    - * partitioned into one or more segments and delivered to a client using HTTP.
    - *
    - * see DASHDecoder.cpp for info on DASH interaction with the media engine.*/
    -
    -#if !defined(DASHDecoder_h_)
    -#define DASHDecoder_h_
    -
    -#include "nsTArray.h"
    -#include "nsIURI.h"
    -#include "nsITimer.h"
    -#include "MediaDecoder.h"
    -#include "DASHReader.h"
    -
    -namespace mozilla {
    -namespace net {
    -class IMPDManager;
    -class nsDASHMPDParser;
    -class Representation;
    -}// net
    -
    -class DASHRepDecoder;
    -
    -class DASHDecoder : public MediaDecoder
    -{
    -public:
    -  typedef class mozilla::net::IMPDManager IMPDManager;
    -  typedef class mozilla::net::nsDASHMPDParser nsDASHMPDParser;
    -  typedef class mozilla::net::Representation Representation;
    -
    -  // XXX Arbitrary max file size for MPD. 50MB seems generously large.
    -  static const uint32_t DASH_MAX_MPD_SIZE = 50*1024*1024;
    -
    -  DASHDecoder();
    -  ~DASHDecoder();
    -
    -  MediaDecoder* Clone() MOZ_OVERRIDE {
    -    if (!IsDASHEnabled()) {
    -      return nullptr;
    -    }
    -    return new DASHDecoder();
    -  }
    -
    -  // Creates a single state machine for all stream decoders.
    -  // Called from Load on the main thread only.
    -  MediaDecoderStateMachine* CreateStateMachine();
    -
    -  // Loads the MPD from the network and subsequently loads the media streams.
    -  // Called from the main thread only.
    -  virtual nsresult Load(nsIStreamListener** aListener,
    -                        MediaDecoder* aCloneDonor) MOZ_OVERRIDE;
    -
    -  // Notifies download of MPD file has ended.
    -  // Called on the main thread only.
    -  void NotifyDownloadEnded(nsresult aStatus);
    -
    -  // Notification from |DASHReader| that a seek has occurred in
    -  // |aSubsegmentIdx|. Passes notification onto subdecoder which downloaded
    -  // the subsegment already, if download is in the past. Otherwise, it returns.
    -  void NotifySeekInVideoSubsegment(int32_t aRepDecoderIdx,
    -                                   int32_t aSubsegmentIdx);
    -  void NotifySeekInAudioSubsegment(int32_t aSubsegmentIdx);
    -
    -  // Notifies that a byte range download has ended. As per the DASH spec, this
    -  // allows for stream switching at the boundaries of the byte ranges.
    -  // Called on the main thread only.
    -  void NotifyDownloadEnded(DASHRepDecoder* aRepDecoder,
    -                           nsresult aStatus,
    -                           int32_t const aSubsegmentIdx);
    -
    -  // Notification from an |MediaDecoderReader| class that metadata has been
    -  // read. Declared here to allow overloading.
    -  void OnReadMetadataCompleted() MOZ_OVERRIDE { }
    -
    -  // Seeks to aTime in seconds
    -  nsresult Seek(double aTime) MOZ_OVERRIDE;
    -
    -  // Notification from |DASHRepDecoder| that a metadata has been read.
    -  // |DASHDecoder| will initiate load of data bytes for active audio/video
    -  // decoders. Called on the decode thread.
    -  void OnReadMetadataCompleted(DASHRepDecoder* aRepDecoder);
    -
    -  // Returns true if all subsegments from current decode position are
    -  // downloaded. Must be in monitor. Call from any thread.
    -  bool IsDataCachedToEndOfResource() MOZ_OVERRIDE;
    -
    -  // Refers to downloading data bytes, i.e. non metadata.
    -  // Returns true if |aRepDecoder| is an active audio or video sub decoder AND
    -  // if metadata for all audio or video decoders has been read.
    -  // Could be called from any thread; enters decoder monitor.
    -  bool IsDecoderAllowedToDownloadData(DASHRepDecoder* aRepDecoder);
    -
    -  // Refers to downloading data bytes during SEEKING.
    -  // Returns true if |aRepDecoder| is the active audio sub decoder, OR if
    -  // it is a video decoder and is allowed to download this subsegment.
    -  // Returns false if there is still some metadata to download.
    -  // Could be called from any thread; enters decoder monitor.
    -  bool IsDecoderAllowedToDownloadSubsegment(DASHRepDecoder* aRepDecoder,
    -                                            int32_t const aSubsegmentIdx);
    -
    -  // Determines if rep/sub decoders should be switched, and if so switches
    -  // them. Notifies |DASHReader| if and when it should switch readers.
    -  // Returns a pointer to the new active decoder.
    -  // Called on the main thread.
    -  nsresult PossiblySwitchDecoder(DASHRepDecoder* aRepDecoder);
    -
    -  // Sets the byte range index for audio|video downloads. Will only increment
    -  // for current active decoders. Could be called from any thread.
    -  // Requires monitor because of write to |mAudioSubsegmentIdx| or
    -  // |mVideoSubsegmentIdx|.
    -  void SetSubsegmentIndex(DASHRepDecoder* aRepDecoder,
    -                          int32_t aSubsegmentIdx);
    -
    -  // Suspend any media downloads that are in progress. Called by the
    -  // media element when it is sent to the bfcache, or when we need
    -  // to throttle the download. Call on the main thread only. This can
    -  // be called multiple times, there's an internal "suspend count".
    -  void Suspend() MOZ_OVERRIDE;
    -
    -  // Resume any media downloads that have been suspended. Called by the
    -  // media element when it is restored from the bfcache, or when we need
    -  // to stop throttling the download. Call on the main thread only.
    -  // The download will only actually resume once as many Resume calls
    -  // have been made as Suspend calls. When aForceBuffering is true,
    -  // we force the decoder to go into buffering state before resuming
    -  // playback.
    -  void Resume(bool aForceBuffering) MOZ_OVERRIDE;
    -private:
    -  // Increments the byte range index for audio|video downloads. Will only
    -  // increment for current active decoders. Could be called from any thread.
    -  // Requires monitor because of write to |mAudioSubsegmentIdx| or
    -  // |mVideoSubsegmentIdx|.
    -  void IncrementSubsegmentIndex(DASHRepDecoder* aRepDecoder)
    -  {
    -    ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
    -    if (aRepDecoder == AudioRepDecoder()) {
    -      mAudioSubsegmentIdx++;
    -    } else if (aRepDecoder == VideoRepDecoder()) {
    -      mVideoSubsegmentIdx++;
    -    }
    -  }
    -public:
    -  // Gets the byte range index for audio|video downloads. Will only increment
    -  // for current active decoders. Could be called from any thread. Will enter
    -  // monitor for read access off the decode thread.
    -  int32_t GetSubsegmentIndex(DASHRepDecoder* aRepDecoder)
    -  {
    -    ReentrantMonitorConditionallyEnter mon(!OnDecodeThread(),
    -                                           GetReentrantMonitor());
    -    if (aRepDecoder == AudioRepDecoder()) {
    -      return mAudioSubsegmentIdx;
    -    } else if (aRepDecoder == VideoRepDecoder()) {
    -      return mVideoSubsegmentIdx;
    -    }
    -    return (-1);
    -  }
    -
    -  // Returns the total number of subsegments that have been loaded. Will enter
    -  // monitor for read access off the decode thread.
    -  uint32_t GetNumSubsegmentLoads() {
    -    ReentrantMonitorConditionallyEnter mon(!OnDecodeThread(),
    -                                           GetReentrantMonitor());
    -    return mVideoSubsegmentLoads.Length();
    -  }
    -
    -  // Returns the index of the rep decoder used to load a subsegment. Will enter
    -  // monitor for read access off the decode thread.
    -  int32_t GetRepIdxForVideoSubsegmentLoad(int32_t aSubsegmentIdx)
    -  {
    -    NS_ASSERTION(0 <= aSubsegmentIdx, "Subsegment index should not be negative.");
    -    ReentrantMonitorConditionallyEnter mon(!OnDecodeThread(),
    -                                           GetReentrantMonitor());
    -    if ((uint32_t)aSubsegmentIdx < mVideoSubsegmentLoads.Length()) {
    -      return mVideoSubsegmentLoads[aSubsegmentIdx];
    -    } else {
    -      // If it hasn't been downloaded yet, use the lowest bitrate decoder.
    -      return 0;
    -    }
    -  }
    -
    -  // Returns the index of the rep decoder used to load a subsegment, after a
    -  // seek. Called on the decode thread, and will block if the subsegment
    -  // previous to the one specified has not yet been loaded. This ensures that
    -  // |DASHDecoder| has had a chance to determine which decoder should load the
    -  // next subsegment, in the case where |DASHRepReader|::|DecodeToTarget| has
    -  // read all the data for the current subsegment from the cache, and needs to
    -  // know which reader (including itself) to use next.
    -  int32_t GetRepIdxForVideoSubsegmentLoadAfterSeek(int32_t aSubsegmentIndex);
    -
    -  int32_t GetSwitchCountAtVideoSubsegment(int32_t aSubsegmentIdx)
    -  {
    -    ReentrantMonitorConditionallyEnter mon(!OnDecodeThread(),
    -                                           GetReentrantMonitor());
    -    NS_ASSERTION(0 <= aSubsegmentIdx, "Subsegment index should not be negative.");
    -    if (aSubsegmentIdx == 0) {
    -      // Do the zeroeth switch next.
    -      return 0;
    -    }
    -    int32_t switchCount = 0;
    -    for (uint32_t i = 1;
    -         i < mVideoSubsegmentLoads.Length() &&
    -         i <= (uint32_t)aSubsegmentIdx;
    -         i++) {
    -      if (mVideoSubsegmentLoads[i-1] != mVideoSubsegmentLoads[i]) {
    -        switchCount++;
    -      }
    -    }
    -    return switchCount;
    -  }
    -
    -  // The actual playback rate computation. The monitor must be held.
    -  // XXX Computes playback for the current video rep decoder only.
    -  double ComputePlaybackRate(bool* aReliable) MOZ_OVERRIDE;
    -
    -  // Something has changed that could affect the computed playback rate,
    -  // so recompute it. The monitor must be held. Will be forwarded to current
    -  // audio and video rep decoders.
    -  void UpdatePlaybackRate() MOZ_OVERRIDE;
    -
    -  // Stop updating the bytes downloaded for progress notifications. Called
    -  // when seeking to prevent wild changes to the progress notification.
    -  // Forwarded to sub-decoders. Must be called with the decoder monitor held.
    -  void StopProgressUpdates() MOZ_OVERRIDE;
    -
    -  // Allow updating the bytes downloaded for progress notifications.
    -  // Forwarded to sub-decoders. Must be called with the decoder monitor held.
    -  void StartProgressUpdates() MOZ_OVERRIDE;
    -
    -  // Used to estimate rates of data passing through the decoder's channel.
    -  // Records activity starting on the channel. The monitor must be held.
    -  virtual void NotifyPlaybackStarted() MOZ_OVERRIDE;
    -
    -  // Used to estimate rates of data passing through the decoder's channel.
    -  // Records activity stopping on the channel. The monitor must be held.
    -  virtual void NotifyPlaybackStopped() MOZ_OVERRIDE;
    -
    -  // Return statistics. This is used for progress events and other things.
    -  // This can be called from any thread. It's only a snapshot of the
    -  // current state, since other threads might be changing the state
    -  // at any time.
    -  // XXX Stats are calculated based on the current video rep decoder, with the
    -  // exception of download rate, which is based on all video downloads.
    -  virtual Statistics GetStatistics() MOZ_OVERRIDE;
    -
    -  // Drop reference to state machine and tell sub-decoders to do the same.
    -  // Only called during shutdown dance, on main thread only.
    -  void ReleaseStateMachine();
    -
    -  // Overridden to forward |Shutdown| to sub-decoders.
    -  // Called on the main thread only.
    -  void Shutdown();
    -
    -  // Called by sub-decoders when load has been aborted. Will notify media
    -  // element only once. Called on the main thread only.
    -  void LoadAborted();
    -
    -  // Notifies the element that decoding has failed. On main thread, call is
    -  // forwarded to |MediaDecoder|::|Error| immediately. On other threads,
    -  // a call is dispatched for execution on the main thread.
    -  void DecodeError();
    -
    -private:
    -  // Reads the MPD data from resource to a byte stream.
    -  // Called on the MPD reader thread.
    -  void ReadMPDBuffer();
    -
    -  // Called when MPD data is completely read.
    -  // On the main thread.
    -  void OnReadMPDBufferCompleted();
    -
    -  // Parses the copied MPD byte stream.
    -  // On the main thread: DOM APIs complain when off the main thread.
    -  nsresult ParseMPDBuffer();
    -
    -  // Creates the sub-decoders for a |Representation|, i.e. media streams.
    -  // On the main thread.
    -  nsresult CreateRepDecoders();
    -
    -  // Creates audio/video decoders for individual |Representation|s.
    -  // On the main thread.
    -  nsresult CreateAudioRepDecoder(nsIURI* aUrl, Representation const * aRep);
    -  nsresult CreateVideoRepDecoder(nsIURI* aUrl, Representation const * aRep);
    -
    -  // Get audio sub-decoder for current audio |Representation|. Will return
    -  // nullptr for out of range indexes.
    -  // Enters monitor for read access off the decode thread.
    -  // XXX Note: Although an array of audio decoders is provided, audio stream
    -  // switching is not yet supported.
    -  DASHRepDecoder* AudioRepDecoder() {
    -    ReentrantMonitorConditionallyEnter mon(!OnDecodeThread(),
    -                                           GetReentrantMonitor());
    -    if (0 == mAudioRepDecoders.Length()) {
    -      return nullptr;
    -    }
    -    NS_ENSURE_TRUE((uint32_t)mAudioRepDecoderIdx < mAudioRepDecoders.Length(),
    -                   nullptr);
    -    if (mAudioRepDecoderIdx < 0) {
    -      return nullptr;
    -    } else {
    -      return mAudioRepDecoders[mAudioRepDecoderIdx];
    -    }
    -  }
    -
    -  // Get video sub-decoder for current video |Representation|. Will return
    -  // nullptr for out of range indexes.
    -  // Enters monitor for read access off the decode thread.
    -  DASHRepDecoder* VideoRepDecoder() {
    -    ReentrantMonitorConditionallyEnter mon(!OnDecodeThread(),
    -                                           GetReentrantMonitor());
    -    if (0 == mVideoRepDecoders.Length()) {
    -      return nullptr;
    -    }
    -    NS_ENSURE_TRUE((uint32_t)mVideoRepDecoderIdx < mVideoRepDecoders.Length(),
    -                   nullptr);
    -    if (mVideoRepDecoderIdx < 0) {
    -      return nullptr;
    -    } else {
    -      return mVideoRepDecoders[mVideoRepDecoderIdx];
    -    }
    -  }
    -
    -  // Creates audio/video resources for individual |Representation|s.
    -  // On the main thread.
    -  MediaResource* CreateAudioSubResource(nsIURI* aUrl,
    -                                        MediaDecoder* aAudioDecoder);
    -  MediaResource* CreateVideoSubResource(nsIURI* aUrl,
    -                                        MediaDecoder* aVideoDecoder);
    -
    -  // Creates an http channel for a |Representation|.
    -  // On the main thread.
    -  nsresult CreateSubChannel(nsIURI* aUrl, nsIChannel** aChannel);
    -
    -  // Loads the media |Representations|, i.e. the media streams.
    -  // On the main thread.
    -  nsresult LoadRepresentations();
    -
    -  // True when media element has already been notified of an aborted load.
    -  bool mNotifiedLoadAborted;
    -
    -  // Ptr for the MPD data.
    -  nsAutoArrayPtr         mBuffer;
    -  // Length of the MPD data.
    -  uint32_t                     mBufferLength;
    -  // Ptr to the MPD Reader thread.
    -  nsCOMPtr          mMPDReaderThread;
    -  // Document Principal.
    -  nsCOMPtr       mPrincipal;
    -
    -  // MPD Manager provides access to the MPD information.
    -  nsAutoPtr       mMPDManager;
    -
    -  // Main reader object; manages all sub-readers for |Representation|s. Owned by
    -  // state machine; destroyed in state machine's destructor.
    -  DASHReader* mDASHReader;
    -
    -  // Sub-decoder vars. Note: For all following members, the decode monitor
    -  // should be held for write access on decode thread, and all read/write off
    -  // the decode thread.
    -
    -  // Index of the video |AdaptationSet|.
    -  int32_t mVideoAdaptSetIdx;
    -
    -  // Indexes for the current audio and video decoders.
    -  int32_t mAudioRepDecoderIdx;
    -  int32_t mVideoRepDecoderIdx;
    -
    -  // Array of pointers for the |Representation|s in the audio/video
    -  // |AdaptationSet|.
    -  nsTArray > mAudioRepDecoders;
    -  nsTArray > mVideoRepDecoders;
    -
    -  // Current index of subsegments downloaded for audio/video decoder.
    -  int32_t mAudioSubsegmentIdx;
    -  int32_t mVideoSubsegmentIdx;
    -
    -  // Count for the number of readers which have called |OnReadMetadataCompleted|.
    -  // Initialised to 0; incremented for every decoder which has |Load| called;
    -  // and decremented for every call to |OnReadMetadataCompleted|. When it is
    -  // zero again, all metadata has been read for audio or video, and data bytes
    -  // can be downloaded.
    -  uint32_t mAudioMetadataReadCount;
    -  uint32_t mVideoMetadataReadCount;
    -
    -  // Array records the index of the decoder/Representation which loaded each
    -  // subsegment.
    -  nsTArray mVideoSubsegmentLoads;
    -
    -  // True when Seek is called; will block any downloads until
    -  // |NotifySeekInSubsegment| is called, which will set it to false, and will
    -  // start a new series of downloads from the seeked subsegment.
    -  bool mSeeking;
    -
    -  // Mutex for statistics.
    -  Mutex mStatisticsLock;
    -  // Stores snapshot statistics, such as download rate, for the audio|video
    -  // data streams. |mStatisticsLock| must be locked for access.
    -  nsRefPtr mAudioStatistics;
    -  nsRefPtr mVideoStatistics;
    -};
    -
    -} // namespace mozilla
    -
    -#endif
    diff --git a/content/media/dash/DASHReader.cpp b/content/media/dash/DASHReader.cpp
    deleted file mode 100644
    index da3b5f96eb80..000000000000
    --- a/content/media/dash/DASHReader.cpp
    +++ /dev/null
    @@ -1,674 +0,0 @@
    -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
    -/* vim:set ts=2 sw=2 sts=2 et cindent: */
    -
    -/* This Source Code Form Is subject to the terms of the Mozilla Public
    - * License, v. 2.0. If a copy of the MPL was not distributed with this file,
    - * You can obtain one at http://mozilla.org/MPL/2.0/. */
    -
    -/* DASH - Dynamic Adaptive Streaming over HTTP
    - *
    - * DASH is an adaptive bitrate streaming technology where a multimedia file is
    - * partitioned into one or more segments and delivered to a client using HTTP.
    - *
    - * see DASHDecoder.cpp for info on DASH interaction with the media engine.*/
    -
    -#include "mozilla/dom/TimeRanges.h"
    -#include "VideoFrameContainer.h"
    -#include "AbstractMediaDecoder.h"
    -#include "DASHReader.h"
    -#include "DASHDecoder.h"
    -#include 
    -
    -namespace mozilla {
    -
    -#ifdef PR_LOGGING
    -PRLogModuleInfo* gDASHReaderLog;
    -#define LOG(msg, ...) PR_LOG(gDASHReaderLog, PR_LOG_DEBUG, \
    -                             ("%p [DASHReader] " msg, this, __VA_ARGS__))
    -#define LOG1(msg) PR_LOG(gDASHReaderLog, PR_LOG_DEBUG, \
    -                         ("%p [DASHReader] " msg, this))
    -#else
    -#define LOG(msg, ...)
    -#define LOG1(msg)
    -#endif
    -
    -DASHReader::DASHReader(AbstractMediaDecoder* aDecoder) :
    -  MediaDecoderReader(aDecoder),
    -  mReadMetadataMonitor("media.dashreader.readmetadata"),
    -  mReadyToReadMetadata(false),
    -  mDecoderIsShuttingDown(false),
    -  mAudioReader(this),
    -  mVideoReader(this),
    -  mAudioReaders(this),
    -  mVideoReaders(this),
    -  mSwitchVideoReaders(false),
    -  mSwitchCount(-1)
    -{
    -  MOZ_COUNT_CTOR(DASHReader);
    -#ifdef PR_LOGGING
    -  if (!gDASHReaderLog) {
    -    gDASHReaderLog = PR_NewLogModule("DASHReader");
    -  }
    -#endif
    -}
    -
    -DASHReader::~DASHReader()
    -{
    -  MOZ_COUNT_DTOR(DASHReader);
    -}
    -
    -nsresult
    -DASHReader::ResetDecode()
    -{
    -  MediaDecoderReader::ResetDecode();
    -  nsresult rv;
    -  for (uint i = 0; i < mAudioReaders.Length(); i++) {
    -    rv = mAudioReaders[i]->ResetDecode();
    -    NS_ENSURE_SUCCESS(rv, rv);
    -  }
    -  for (uint i = 0; i < mVideoReaders.Length(); i++) {
    -    rv = mVideoReaders[i]->ResetDecode();
    -    NS_ENSURE_SUCCESS(rv, rv);
    -  }
    -  return NS_OK;
    -}
    -
    -nsresult
    -DASHReader::Init(MediaDecoderReader* aCloneDonor)
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -
    -  ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
    -  NS_ASSERTION(mAudioReaders.Length() != 0 && mVideoReaders.Length() != 0,
    -               "Audio and video readers should exist already.");
    -
    -  nsresult rv;
    -  for (uint i = 0; i < mAudioReaders.Length(); i++) {
    -    rv = mAudioReaders[i]->Init(nullptr);
    -    NS_ENSURE_SUCCESS(rv, rv);
    -  }
    -  for (uint i = 0; i < mVideoReaders.Length(); i++) {
    -    rv = mVideoReaders[i]->Init(nullptr);
    -    NS_ENSURE_SUCCESS(rv, rv);
    -  }
    -  return NS_OK;
    -}
    -
    -void
    -DASHReader::AddAudioReader(DASHRepReader* aAudioReader)
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -  NS_ENSURE_TRUE_VOID(aAudioReader);
    -
    -  ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
    -
    -  mAudioReaders.AppendElement(aAudioReader);
    -  // XXX For now, just pick the first reader to be default.
    -  if (!mAudioReader)
    -    mAudioReader = aAudioReader;
    -}
    -
    -void
    -DASHReader::AddVideoReader(DASHRepReader* aVideoReader)
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -  NS_ENSURE_TRUE_VOID(aVideoReader);
    -
    -  ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
    -
    -  mVideoReaders.AppendElement(aVideoReader);
    -  // XXX For now, just pick the first reader to be default.
    -  if (!mVideoReader)
    -    mVideoReader = aVideoReader;
    -}
    -
    -bool
    -DASHReader::HasAudio()
    -{
    -  NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
    -  return mAudioReader ? mAudioReader->HasAudio() : false;
    -}
    -
    -bool
    -DASHReader::HasVideo()
    -{
    -  NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
    -  return mVideoReader ? mVideoReader->HasVideo() : false;
    -}
    -
    -int64_t
    -DASHReader::VideoQueueMemoryInUse()
    -{
    -  ReentrantMonitorConditionallyEnter mon(!mDecoder->OnDecodeThread(),
    -                                         mDecoder->GetReentrantMonitor());
    -  return VideoQueueMemoryInUse();
    -}
    -
    -int64_t
    -DASHReader::AudioQueueMemoryInUse()
    -{
    -  ReentrantMonitorConditionallyEnter mon(!mDecoder->OnDecodeThread(),
    -                                         mDecoder->GetReentrantMonitor());
    -  return AudioQueueMemoryInUse();
    -}
    -
    -bool
    -DASHReader::DecodeVideoFrame(bool &aKeyframeSkip,
    -                             int64_t aTimeThreshold)
    -{
    -  NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
    -  if (mVideoReader) {
    -   return mVideoReader->DecodeVideoFrame(aKeyframeSkip, aTimeThreshold);
    -  } else {
    -   return false;
    -  }
    -}
    -
    -bool
    -DASHReader::DecodeAudioData()
    -{
    -  NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
    -  return (mAudioReader ? mAudioReader->DecodeAudioData() : false);
    -}
    -
    -nsresult
    -DASHReader::ReadMetadata(MediaInfo* aInfo,
    -                         MetadataTags** aTags)
    -{
    -  NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
    -
    -  // Wait for MPD to be parsed and child readers created.
    -  LOG1("Waiting for metadata download.");
    -  nsresult rv = WaitForMetadata();
    -  // If we get an abort, return silently; the decoder is shutting down.
    -  if (NS_ERROR_ABORT == rv) {
    -    return NS_OK;
    -  }
    -  // Verify no other errors before continuing.
    -  NS_ENSURE_SUCCESS(rv, rv);
    -
    -  NS_ASSERTION(aTags, "Called with null MetadataTags**.");
    -  *aTags = nullptr;
    -
    -  // Get metadata from child readers.
    -  MediaInfo audioInfo, videoInfo;
    -
    -  // Read metadata for all video streams.
    -  for (uint i = 0; i < mVideoReaders.Length(); i++) {
    -    // Use an nsAutoPtr here to ensure |tags| memory does not leak.
    -    nsAutoPtr tags;
    -    rv = mVideoReaders[i]->ReadMetadata(&videoInfo, getter_Transfers(tags));
    -    NS_ENSURE_SUCCESS(rv, rv);
    -    // Use metadata from current video sub reader to populate aInfo.
    -    if (mVideoReaders[i] == mVideoReader) {
    -      mInfo.mVideo = videoInfo.mVideo;
    -    }
    -  }
    -  // Read metadata for audio stream.
    -  // Note: Getting metadata tags from audio reader only for now.
    -  // XXX Audio stream switching not yet supported.
    -  if (mAudioReader) {
    -    rv = mAudioReader->ReadMetadata(&audioInfo, aTags);
    -    NS_ENSURE_SUCCESS(rv, rv);
    -    mInfo.mAudio = audioInfo.mAudio;
    -  }
    -
    -  *aInfo = mInfo;
    -
    -  return NS_OK;
    -}
    -
    -nsresult
    -DASHReader::Seek(int64_t aTime,
    -                 int64_t aStartTime,
    -                 int64_t aEndTime,
    -                 int64_t aCurrentTime)
    -{
    -  NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
    -
    -  NS_ENSURE_SUCCESS(ResetDecode(), NS_ERROR_FAILURE);
    -
    -  LOG("Seeking to [%.2fs]", aTime/1000000.0);
    -
    -  nsresult rv;
    -  DASHDecoder* dashDecoder = static_cast(mDecoder);
    -
    -  if (mAudioReader) {
    -    int64_t subsegmentIdx = -1;
    -    {
    -      ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
    -      subsegmentIdx = mAudioReader->GetSubsegmentForSeekTime(aTime);
    -      NS_ENSURE_TRUE(0 <= subsegmentIdx, NS_ERROR_ILLEGAL_VALUE);
    -    }
    -    dashDecoder->NotifySeekInAudioSubsegment(subsegmentIdx);
    -
    -    rv = mAudioReader->Seek(aTime, aStartTime, aEndTime, aCurrentTime);
    -    NS_ENSURE_SUCCESS(rv, rv);
    -  }
    -
    -  if (mVideoReader) {
    -    // Determine the video subsegment we're seeking to.
    -    int32_t subsegmentIdx = -1;
    -    {
    -      ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
    -      subsegmentIdx = mVideoReader->GetSubsegmentForSeekTime(aTime);
    -      NS_ENSURE_TRUE(0 <= subsegmentIdx, NS_ERROR_ILLEGAL_VALUE);
    -    }
    -
    -    LOG("Seek to [%.2fs] found in video subsegment [%d]",
    -        aTime/1000000.0, subsegmentIdx);
    -
    -    // Determine if/which video reader previously downloaded this subsegment.
    -    int32_t readerIdx = dashDecoder->GetRepIdxForVideoSubsegmentLoad(subsegmentIdx);
    -
    -    dashDecoder->NotifySeekInVideoSubsegment(readerIdx, subsegmentIdx);
    -
    -    if (0 <= readerIdx) {
    -      NS_ENSURE_TRUE(readerIdx < mVideoReaders.Length(),
    -                     NS_ERROR_ILLEGAL_VALUE);
    -      // Switch to this reader and do the Seek.
    -      DASHRepReader* fromReader = mVideoReader;
    -      DASHRepReader* toReader = mVideoReaders[readerIdx];
    -
    -      {
    -        ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
    -        if (fromReader != toReader) {
    -          LOG("Switching video readers now from [%p] to [%p] for a seek to "
    -              "[%.2fs] in subsegment [%d]",
    -              fromReader, toReader, aTime/1000000.0, subsegmentIdx);
    -
    -          mVideoReader = toReader;
    -        }
    -      }
    -
    -      rv = mVideoReader->Seek(aTime, aStartTime, aEndTime, aCurrentTime);
    -      if (NS_FAILED(rv)) {
    -        NS_ENSURE_SUCCESS(rv, rv);
    -      }
    -
    -      // Go back to the appropriate count in the switching history, and setup
    -      // this main reader and the sub readers for the next switch (if any).
    -      {
    -        ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
    -        mSwitchCount = dashDecoder->GetSwitchCountAtVideoSubsegment(subsegmentIdx);
    -        LOG("After mVideoReader->Seek() mSwitchCount %d", mSwitchCount);
    -        NS_ENSURE_TRUE(0 <= mSwitchCount, NS_ERROR_ILLEGAL_VALUE);
    -        NS_ENSURE_TRUE(mSwitchCount <= subsegmentIdx, NS_ERROR_ILLEGAL_VALUE);
    -      }
    -    } else {
    -      LOG("Error getting rep idx for video subsegment [%d]",
    -          subsegmentIdx);
    -    }
    -  }
    -  return NS_OK;
    -}
    -
    -nsresult
    -DASHReader::GetBuffered(TimeRanges* aBuffered,
    -                        int64_t aStartTime)
    -{
    -  NS_ENSURE_ARG(aBuffered);
    -
    -  MediaResource* resource = nullptr;
    -  AbstractMediaDecoder* decoder = nullptr;
    -
    -  TimeRanges audioBuffered, videoBuffered;
    -  uint32_t audioRangeCount = 0, videoRangeCount = 0;
    -  bool audioCachedAtEnd = false, videoCachedAtEnd = false;
    -
    -  nsresult rv = NS_OK;
    -
    -  // Get all audio and video buffered ranges. Include inactive streams, since
    -  // we may have carried out a seek and future subsegments may be in currently
    -  // inactive decoders.
    -  ReentrantMonitorConditionallyEnter mon(!mDecoder->OnDecodeThread(),
    -                                         mDecoder->GetReentrantMonitor());
    -  for (uint32_t i = 0; i < mAudioReaders.Length(); i++) {
    -    decoder = mAudioReaders[i]->GetDecoder();
    -    NS_ENSURE_TRUE(decoder, NS_ERROR_NULL_POINTER);
    -    resource = decoder->GetResource();
    -    NS_ENSURE_TRUE(resource, NS_ERROR_NULL_POINTER);
    -    resource->Pin();
    -    rv = mAudioReaders[i]->GetBuffered(&audioBuffered, aStartTime);
    -    NS_ENSURE_SUCCESS(rv, rv);
    -    // If data was cached at the end, then the final timestamp refers to the
    -    // end of the data. Use this later to extend end time if necessary.
    -    if (!audioCachedAtEnd) {
    -      audioCachedAtEnd = mAudioReaders[i]->IsDataCachedAtEndOfSubsegments();
    -    }
    -    resource->Unpin();
    -  }
    -  for (uint32_t i = 0; i < mVideoReaders.Length(); i++) {
    -    decoder = mVideoReaders[i]->GetDecoder();
    -    NS_ENSURE_TRUE(decoder, NS_ERROR_NULL_POINTER);
    -    resource = decoder->GetResource();
    -    NS_ENSURE_TRUE(resource, NS_ERROR_NULL_POINTER);
    -    resource->Pin();
    -    rv = mVideoReaders[i]->GetBuffered(&videoBuffered, aStartTime);
    -    NS_ENSURE_SUCCESS(rv, rv);
    -    // If data was cached at the end, then the final timestamp refers to the
    -    // end of the data. Use this later to extend end time if necessary.
    -    if (!videoCachedAtEnd) {
    -      videoCachedAtEnd = mVideoReaders[i]->IsDataCachedAtEndOfSubsegments();
    -    }
    -    resource->Unpin();
    -  }
    -
    -  audioBuffered.Normalize();
    -  videoBuffered.Normalize();
    -
    -  rv = audioBuffered.GetLength(&audioRangeCount);
    -  NS_ENSURE_SUCCESS(rv, rv);
    -  rv = videoBuffered.GetLength(&videoRangeCount);
    -  NS_ENSURE_SUCCESS(rv, rv);
    -
    -#ifdef PR_LOGGING
    -  double start = 0, end = 0;
    -  for (uint32_t i = 0; i < audioRangeCount; i++) {
    -    rv = audioBuffered.Start(i, &start);
    -    NS_ENSURE_SUCCESS(rv, rv);
    -    rv = audioBuffered.End(i, &end);
    -    NS_ENSURE_SUCCESS(rv, rv);
    -    LOG("audioBuffered[%d] = (%f, %f)",
    -        i, start, end);
    -  }
    -  for (uint32_t i = 0; i < videoRangeCount; i++) {
    -    rv = videoBuffered.Start(i, &start);
    -    NS_ENSURE_SUCCESS(rv, rv);
    -    rv = videoBuffered.End(i, &end);
    -    NS_ENSURE_SUCCESS(rv, rv);
    -    LOG("videoBuffered[%d] = (%f, %f)",
    -        i, start, end);
    -  }
    -#endif
    -
    -  // If audio and video are cached to the end of their subsegments, extend the
    -  // end time of the shorter of the two. Presentation of the shorter stream
    -  // will stop at the end, while the other continues until the combined
    -  // playback is complete.
    -  // Note: Only in cases where the shorter stream is fully cached, and the
    -  // longer stream is partially cached, but with more time buffered than the
    -  // shorter stream.
    -  //
    -  // Audio ========|
    -  //               20
    -  // Video ============|----|
    -  //                   30   40
    -  // Combo ============|      <----- End time EXTENDED.
    -  //
    -  // For example, audio is fully cached to 20s, but video is partially cached
    -  // to 30s, full duration 40s. In this case, the buffered end time should be
    -  // extended to the video's end time.
    -  //
    -  // Audio =================|
    -  //                        40
    -  // Video ========|----|
    -  //               20   30
    -  // Combo ========|          <------ End time NOT EXTENDED.
    -  //
    -  // Conversely, if the longer stream is fully cached, but the shorter one is
    -  // not, no extension of end time should occur - we should consider the
    -  // partially cached, shorter end time to be the end time of the combined
    -  // stream
    -
    -  if (audioCachedAtEnd || videoCachedAtEnd) {
    -    NS_ENSURE_TRUE(audioRangeCount, NS_ERROR_FAILURE);
    -    NS_ENSURE_TRUE(videoRangeCount, NS_ERROR_FAILURE);
    -
    -    double audioEndTime = 0, videoEndTime = 0;
    -    // Get end time of the last range of buffered audio.
    -    audioEndTime = audioBuffered.GetFinalEndTime();
    -    NS_ENSURE_TRUE(audioEndTime > 0, NS_ERROR_ILLEGAL_VALUE);
    -    // Get end time of the last range of buffered video.
    -    videoEndTime = videoBuffered.GetFinalEndTime();
    -    NS_ENSURE_TRUE(videoEndTime > 0, NS_ERROR_ILLEGAL_VALUE);
    -
    -    // API for TimeRanges requires extending through adding and normalizing.
    -    if (videoCachedAtEnd && audioEndTime > videoEndTime) {
    -      videoBuffered.Add(videoEndTime, audioEndTime);
    -      videoBuffered.Normalize();
    -      LOG("videoBuffered extended to %f", audioEndTime);
    -    } else if (audioCachedAtEnd && videoEndTime > audioEndTime) {
    -      audioBuffered.Add(audioEndTime, videoEndTime);
    -      audioBuffered.Normalize();
    -      LOG("audioBuffered extended to %f", videoEndTime);
    -    }
    -  }
    -
    -  // Calculate intersecting ranges for video and audio.
    -  if (!mAudioReaders.IsEmpty() && !mVideoReaders.IsEmpty()) {
    -    for (uint32_t i = 0; i < audioRangeCount; i++) {
    -      // |A|udio, |V|ideo, |I|ntersect.
    -      double startA, startV, startI;
    -      double endA, endV, endI;
    -      rv = audioBuffered.Start(i, &startA);
    -      NS_ENSURE_SUCCESS(rv, rv);
    -      rv = audioBuffered.End(i, &endA);
    -      NS_ENSURE_SUCCESS(rv, rv);
    -
    -      for (uint32_t j = 0; j < videoRangeCount; j++) {
    -        rv = videoBuffered.Start(i, &startV);
    -        NS_ENSURE_SUCCESS(rv, rv);
    -        rv = videoBuffered.End(i, &endV);
    -        NS_ENSURE_SUCCESS(rv, rv);
    -
    -        // If video block is before audio block, compare next video block.
    -        if (startA > endV) {
    -          continue;
    -        // If video block is after audio block, all of them are; compare next
    -        // audio block.
    -        } else if (endA < startV) {
    -          break;
    -        }
    -        // Calculate intersections of current audio and video blocks.
    -        startI = (startA > startV) ? startA : startV;
    -        endI = (endA > endV) ? endV : endA;
    -        aBuffered->Add(startI, endI);
    -      }
    -    }
    -  } else if (!mAudioReaders.IsEmpty()) {
    -    *aBuffered = audioBuffered;
    -  } else if (!mVideoReaders.IsEmpty()) {
    -    *aBuffered = videoBuffered;
    -  } else {
    -    return NS_ERROR_NOT_INITIALIZED;
    -  }
    -
    -  return NS_OK;
    -}
    -
    -VideoData*
    -DASHReader::FindStartTime(int64_t& aOutStartTime)
    -{
    -  NS_ASSERTION(mDecoder->OnStateMachineThread() || mDecoder->OnDecodeThread(),
    -               "Should be on state machine or decode thread.");
    -
    -  // Extract the start times of the bitstreams in order to calculate
    -  // the duration.
    -  int64_t videoStartTime = INT64_MAX;
    -  int64_t audioStartTime = INT64_MAX;
    -  VideoData* videoData = nullptr;
    -
    -  ReentrantMonitorConditionallyEnter mon(!mDecoder->OnDecodeThread(),
    -                                         mDecoder->GetReentrantMonitor());
    -  if (HasVideo()) {
    -    // Forward to video reader.
    -    videoData = mVideoReader->DecodeToFirstVideoData();
    -    if (videoData) {
    -      videoStartTime = videoData->mTime;
    -    }
    -  }
    -  if (HasAudio()) {
    -    // Forward to audio reader.
    -    AudioData* audioData = mAudioReader->DecodeToFirstAudioData();
    -    if (audioData) {
    -      audioStartTime = audioData->mTime;
    -    }
    -  }
    -
    -  int64_t startTime = std::min(videoStartTime, audioStartTime);
    -  if (startTime != INT64_MAX) {
    -    aOutStartTime = startTime;
    -  }
    -
    -  return videoData;
    -}
    -
    -MediaQueue&
    -DASHReader::AudioQueue()
    -{
    -  ReentrantMonitorConditionallyEnter mon(!mDecoder->OnDecodeThread(),
    -                                         mDecoder->GetReentrantMonitor());
    -  NS_ASSERTION(mAudioReader, "mAudioReader is NULL!");
    -  return mAudioQueue;
    -}
    -
    -MediaQueue&
    -DASHReader::VideoQueue()
    -{
    -  ReentrantMonitorConditionallyEnter mon(!mDecoder->OnDecodeThread(),
    -                                         mDecoder->GetReentrantMonitor());
    -  NS_ASSERTION(mVideoReader, "mVideoReader is NULL!");
    -  return mVideoQueue;
    -}
    -
    -void
    -DASHReader::RequestVideoReaderSwitch(uint32_t aFromReaderIdx,
    -                                     uint32_t aToReaderIdx,
    -                                     uint32_t aSubsegmentIdx)
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -  NS_ASSERTION(aFromReaderIdx < mVideoReaders.Length(),
    -               "From index is greater than number of video readers!");
    -  NS_ASSERTION(aToReaderIdx < mVideoReaders.Length(),
    -               "To index is greater than number of video readers!");
    -  NS_ASSERTION(aToReaderIdx != aFromReaderIdx,
    -               "Don't request switches to same reader!");
    -  mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
    -
    -  if (mSwitchCount < 0) {
    -    mSwitchCount = 0;
    -  }
    -
    -  DASHRepReader* fromReader = mVideoReaders[aFromReaderIdx];
    -  DASHRepReader* toReader = mVideoReaders[aToReaderIdx];
    -
    -  LOG("Switch requested from reader [%d] [%p] to reader [%d] [%p] "
    -      "at subsegment[%d].",
    -      aFromReaderIdx, fromReader, aToReaderIdx, toReader, aSubsegmentIdx);
    -
    -  // Append the subsegment index to the list of pending switches.
    -  for (uint32_t i = 0; i < mSwitchToVideoSubsegmentIndexes.Length(); i++) {
    -    if (mSwitchToVideoSubsegmentIndexes[i] == aSubsegmentIdx) {
    -      // A backwards |Seek| has changed the switching history; delete from
    -      // this point on.
    -      mSwitchToVideoSubsegmentIndexes.TruncateLength(i);
    -      break;
    -    }
    -  }
    -  mSwitchToVideoSubsegmentIndexes.AppendElement(aSubsegmentIdx);
    -
    -  // Tell the SWITCH FROM reader when it should stop reading.
    -  fromReader->RequestSwitchAtSubsegment(aSubsegmentIdx, toReader);
    -
    -  // Tell the SWITCH TO reader to seek to the correct offset.
    -  toReader->RequestSeekToSubsegment(aSubsegmentIdx);
    -
    -  mSwitchVideoReaders = true;
    -}
    -
    -void
    -DASHReader::PossiblySwitchVideoReaders()
    -{
    -  NS_ASSERTION(mDecoder, "Decoder should not be null");
    -  NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
    -
    -  // Flag to switch streams is set in |RequestVideoReaderSwitch|.
    -  if (!mSwitchVideoReaders) {
    -    return;
    -  }
    -
    -  // Only switch if we reached a switch access point.
    -  NS_ENSURE_TRUE_VOID(0 <= mSwitchCount);
    -  NS_ENSURE_TRUE_VOID((uint32_t)mSwitchCount < mSwitchToVideoSubsegmentIndexes.Length());
    -  uint32_t switchIdx = mSwitchToVideoSubsegmentIndexes[mSwitchCount];
    -  if (!mVideoReader->HasReachedSubsegment(switchIdx)) {
    -    return;
    -  }
    -
    -  // Get Representation index to switch to.
    -  DASHDecoder* dashDecoder = static_cast(mDecoder);
    -  int32_t toReaderIdx = dashDecoder->GetRepIdxForVideoSubsegmentLoad(switchIdx);
    -  NS_ENSURE_TRUE_VOID(0 <= toReaderIdx);
    -  NS_ENSURE_TRUE_VOID((uint32_t)toReaderIdx < mVideoReaders.Length());
    -
    -  DASHRepReader* fromReader = mVideoReader;
    -  DASHRepReader* toReader = mVideoReaders[toReaderIdx];
    -  NS_ENSURE_TRUE_VOID(fromReader != toReader);
    -
    -  LOG("Switching video readers now from [%p] to [%p] at subsegment [%d]: "
    -      "mSwitchCount [%d].",
    -      fromReader, toReader, switchIdx, mSwitchCount);
    -
    -  // Switch readers while in the monitor.
    -  ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
    -  mVideoReader = toReader;
    -
    -  // Prep readers for next switch, also while in monitor.
    -  if ((uint32_t)++mSwitchCount < mSwitchToVideoSubsegmentIndexes.Length()) {
    -    // Get the subsegment at which to switch.
    -    switchIdx = mSwitchToVideoSubsegmentIndexes[mSwitchCount];
    -
    -    // Update from and to reader ptrs for next switch.
    -    fromReader = toReader;
    -    toReaderIdx = dashDecoder->GetRepIdxForVideoSubsegmentLoad(switchIdx);
    -    toReader = mVideoReaders[toReaderIdx];
    -    NS_ENSURE_TRUE_VOID((uint32_t)toReaderIdx < mVideoReaders.Length());
    -    NS_ENSURE_TRUE_VOID(fromReader != toReader);
    -
    -    // Tell the SWITCH FROM reader when it should stop reading.
    -    fromReader->RequestSwitchAtSubsegment(switchIdx, toReader);
    -
    -    // Tell the SWITCH TO reader to seek to the correct offset.
    -    toReader->RequestSeekToSubsegment(switchIdx);
    -  } else {
    -    // If there are no more pending switches, unset the switch readers flag.
    -    mSwitchVideoReaders = false;
    -  }
    -}
    -
    -void
    -DASHReader::PrepareToDecode()
    -{
    -  NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
    -
    -  // Flag to switch streams is set by |DASHDecoder|.
    -  if (!mSwitchVideoReaders) {
    -    return;
    -  }
    -
    -  PossiblySwitchVideoReaders();
    -
    -  // Prepare each sub reader for decoding: includes seeking to the correct
    -  // offset if a seek was previously requested.
    -  for (uint32_t i = 0; i < mVideoReaders.Length(); i++) {
    -    mVideoReaders[i]->PrepareToDecode();
    -  }
    -}
    -
    -DASHRepReader*
    -DASHReader::GetReaderForSubsegment(uint32_t aSubsegmentIdx)
    -{
    -  NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
    -  DASHDecoder* dashDecoder = static_cast(mDecoder);
    -  int32_t repIdx =
    -    dashDecoder->GetRepIdxForVideoSubsegmentLoadAfterSeek((int32_t)aSubsegmentIdx);
    -  if (0 <= repIdx && repIdx < mVideoReaders.Length()) {
    -    return mVideoReaders[repIdx];
    -  } else {
    -    return nullptr;
    -  }
    -}
    -
    -
    -} // namespace mozilla
    diff --git a/content/media/dash/DASHReader.h b/content/media/dash/DASHReader.h
    deleted file mode 100644
    index 6a79fdeb27f9..000000000000
    --- a/content/media/dash/DASHReader.h
    +++ /dev/null
    @@ -1,303 +0,0 @@
    -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
    -/* vim:set ts=2 sw=2 sts=2 et cindent: */
    -
    -/* This Source Code Form Is subject to the terms of the Mozilla Public
    - * License, v. 2.0. If a copy of the MPL was not distributed with this file,
    - * You can obtain one at http://mozilla.org/MPL/2.0/. */
    -
    -/* DASH - Dynamic Adaptive Streaming over HTTP
    - *
    - * DASH is an adaptive bitrate streaming technology where a multimedia file is
    - * partitioned into one or more segments and delivered to a client using HTTP.
    - *
    - * see DASHDecoder.cpp for comments on DASH object interaction
    - */
    -
    -#if !defined(DASHReader_h_)
    -#define DASHReader_h_
    -
    -#include "VideoUtils.h"
    -#include "MediaDecoderReader.h"
    -#include "DASHRepReader.h"
    -
    -namespace mozilla {
    -
    -class DASHRepReader;
    -
    -class DASHReader : public MediaDecoderReader
    -{
    -public:
    -  DASHReader(AbstractMediaDecoder* aDecoder);
    -  ~DASHReader();
    -  nsresult ResetDecode() MOZ_OVERRIDE;
    -
    -  // Adds a pointer to a audio/video reader for a media |Representation|.
    -  // Called on the main thread only.
    -  void AddAudioReader(DASHRepReader* aAudioReader);
    -  void AddVideoReader(DASHRepReader* aVideoReader);
    -
    -  // Waits for metadata bytes to be downloaded, then reads and parses them.
    -  // Called on the decode thread only.
    -  nsresult ReadMetadata(MediaInfo* aInfo,
    -                        MetadataTags** aTags) MOZ_OVERRIDE;
    -
    -  // Waits for |ReadyToReadMetadata| or |NotifyDecoderShuttingDown|
    -  // notification, whichever comes first. Ensures no attempt to read metadata
    -  // during |DASHDecoder|::|Shutdown|. Called on decode thread only.
    -  nsresult WaitForMetadata() {
    -    NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
    -    ReentrantMonitorAutoEnter mon(mReadMetadataMonitor);
    -    while (true) {
    -      // Abort if the decoder has started shutting down.
    -      if (mDecoderIsShuttingDown) {
    -        return NS_ERROR_ABORT;
    -      } else if (mReadyToReadMetadata) {
    -        break;
    -      }
    -      mon.Wait();
    -    }
    -    return NS_OK;
    -  }
    -
    -  // Called on the main thread by |DASHDecoder| to notify that metadata bytes
    -  // have been downloaded.
    -  void ReadyToReadMetadata() {
    -    NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -    ReentrantMonitorAutoEnter mon(mReadMetadataMonitor);
    -    mReadyToReadMetadata = true;
    -    mon.NotifyAll();
    -  }
    -
    -  // Called on the main thread by |DASHDecoder| when it starts Shutdown. Will
    -  // wake metadata monitor if waiting for a silent return from |ReadMetadata|.
    -  void NotifyDecoderShuttingDown() {
    -    NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -    ReentrantMonitorAutoEnter metadataMon(mReadMetadataMonitor);
    -    mDecoderIsShuttingDown = true;
    -    // Notify |ReadMetadata| of the shutdown if it's waiting.
    -    metadataMon.NotifyAll();
    -  }
    -
    -  // Audio/video status are dependent on the presence of audio/video readers.
    -  // Call on decode thread only.
    -  bool HasAudio() MOZ_OVERRIDE;
    -  bool HasVideo() MOZ_OVERRIDE;
    -
    -  // Returns references to the audio/video queues of sub-readers. Called on
    -  // decode, state machine and audio threads.
    -  MediaQueue& AudioQueue() MOZ_OVERRIDE;
    -  MediaQueue& VideoQueue() MOZ_OVERRIDE;
    -
    -  // Called from MediaDecoderStateMachine on the main thread.
    -  nsresult Init(MediaDecoderReader* aCloneDonor) MOZ_OVERRIDE;
    -
    -  // Used by |MediaMemoryReporter|.
    -  int64_t VideoQueueMemoryInUse() MOZ_OVERRIDE;
    -  int64_t AudioQueueMemoryInUse() MOZ_OVERRIDE;
    -
    -  // Called on the decode thread, at the start of the decode loop, before
    -  // |DecodeVideoFrame|.  Carries out video reader switch if previously
    -  // requested, and tells sub-readers to |PrepareToDecode|.
    -  void PrepareToDecode() MOZ_OVERRIDE;
    -
    -  // Called on the decode thread.
    -  bool DecodeVideoFrame(bool &aKeyframeSkip, int64_t aTimeThreshold) MOZ_OVERRIDE;
    -  bool DecodeAudioData() MOZ_OVERRIDE;
    -
    -  // Converts seek time to byte offset. Called on the decode thread only.
    -  nsresult Seek(int64_t aTime,
    -                int64_t aStartTime,
    -                int64_t aEndTime,
    -                int64_t aCurrentTime) MOZ_OVERRIDE;
    -
    -  // Called by state machine on multiple threads.
    -  nsresult GetBuffered(mozilla::dom::TimeRanges* aBuffered, int64_t aStartTime) MOZ_OVERRIDE;
    -
    -  // Called on the state machine or decode threads.
    -  VideoData* FindStartTime(int64_t& aOutStartTime) MOZ_OVERRIDE;
    -
    -  // Prepares for an upcoming switch of video readers. Called by
    -  // |DASHDecoder| when it has switched download streams. Sets the index of
    -  // the reader to switch TO and the index of the subsegment to switch AT
    -  // (start offset). (Note: Subsegment boundaries are switch access points for
    -  // DASH-WebM). Called on the main thread. Must be in the decode monitor.
    -  void RequestVideoReaderSwitch(uint32_t aFromReaderIdx,
    -                                uint32_t aToReaderIdx,
    -                                uint32_t aSubsegmentIdx);
    -
    -  // Returns a pointer to the reader which should be used for the specified
    -  // subsegment. Called on the decode thread only.
    -  DASHRepReader* GetReaderForSubsegment(uint32_t aSubsegmentIdx);
    -
    -private:
    -  // Switches video subreaders if a stream-switch flag has been set, and the
    -  // current reader has read up to the switching subsegment (start offset).
    -  // Called on the decode thread only.
    -  void PossiblySwitchVideoReaders();
    -
    -  // Monitor and booleans used to wait for metadata bytes to be downloaded, and
    -  // skip reading metadata if |DASHDecoder|'s shutdown is in progress.
    -  ReentrantMonitor mReadMetadataMonitor;
    -  bool mReadyToReadMetadata;
    -  bool mDecoderIsShuttingDown;
    -
    -  // Wrapper class protecting accesses to sub-readers. Asserts that the
    -  // decoder monitor has been entered for write access on all threads and read
    -  // access on all threads that are not the decode thread. Read access on the
    -  // decode thread does not need to be protected.
    -  class MonitoredSubReader
    -  {
    -  public:
    -    // Main constructor takes a pointer to the owning |DASHReader| to verify
    -    // correct entry into the decoder's |ReentrantMonitor|.
    -    MonitoredSubReader(DASHReader* aReader) :
    -      mReader(aReader),
    -      mSubReader(nullptr)
    -    {
    -      MOZ_COUNT_CTOR(DASHReader::MonitoredSubReader);
    -      NS_ASSERTION(mReader, "Reader is null!");
    -    }
    -    // Note: |mSubReader|'s refcount will be decremented in this destructor.
    -    ~MonitoredSubReader()
    -    {
    -      MOZ_COUNT_DTOR(DASHReader::MonitoredSubReader);
    -    }
    -
    -    // Override '=' to always assert thread is "in monitor" for writes/changes
    -    // to |mSubReader|.
    -    MonitoredSubReader& operator=(DASHRepReader* rhs)
    -    {
    -      NS_ASSERTION(mReader->GetDecoder(), "Decoder is null!");
    -      mReader->GetDecoder()->GetReentrantMonitor().AssertCurrentThreadIn();
    -      mSubReader = rhs;
    -      return *this;
    -    }
    -
    -    // Override '*' to assert threads other than the decode thread are "in
    -    // monitor" for ptr reads.
    -    operator DASHRepReader*() const
    -    {
    -      NS_ASSERTION(mReader->GetDecoder(), "Decoder is null!");
    -      if (!mReader->GetDecoder()->OnDecodeThread()) {
    -        mReader->GetDecoder()->GetReentrantMonitor().AssertCurrentThreadIn();
    -      }
    -      return mSubReader;
    -    }
    -
    -    // Override '->' to assert threads other than the decode thread are "in
    -    // monitor" for |mSubReader| function calls.
    -    DASHRepReader* operator->() const
    -    {
    -      return *this;
    -    }
    -  private:
    -    // Pointer to |DASHReader| object which owns this |MonitoredSubReader|.
    -    DASHReader* mReader;
    -    // Ref ptr to the sub reader.
    -    nsRefPtr mSubReader;
    -  };
    -
    -  // Wrapped ref ptrs to current sub-readers of individual media
    -  // |Representation|s. Decoder monitor must be entered for write access on all
    -  // threads and read access on all threads that are not the decode thread.
    -  // Read access on the decode thread does not need to be protected.
    -  // Note: |MonitoredSubReader| class will assert correct monitor use.
    -  MonitoredSubReader mAudioReader;
    -  MonitoredSubReader mVideoReader;
    -
    -  // Wrapper class protecting accesses to sub-reader list. Asserts that the
    -  // decoder monitor has been entered for write access on all threads and read
    -  // access on all threads that are not the decode thread. Read access on the
    -  // decode thread does not need to be protected.
    -  // Note: Elems accessed via operator[] are not protected with monitor
    -  // assertion checks once obtained.
    -  class MonitoredSubReaderList
    -  {
    -  public:
    -    // Main constructor takes a pointer to the owning |DASHReader| to verify
    -    // correct entry into the decoder's |ReentrantMonitor|.
    -    MonitoredSubReaderList(DASHReader* aReader) :
    -      mReader(aReader)
    -    {
    -      MOZ_COUNT_CTOR(DASHReader::MonitoredSubReaderList);
    -      NS_ASSERTION(mReader, "Reader is null!");
    -    }
    -    // Note: Elements in |mSubReaderList| will have their refcounts decremented
    -    // in this destructor.
    -    ~MonitoredSubReaderList()
    -    {
    -      MOZ_COUNT_DTOR(DASHReader::MonitoredSubReaderList);
    -    }
    -
    -    // Returns Length of |mSubReaderList| array. Will assert threads other than
    -    // the decode thread are "in monitor".
    -    uint32_t Length() const
    -    {
    -      NS_ASSERTION(mReader->GetDecoder(), "Decoder is null!");
    -      if (!mReader->GetDecoder()->OnDecodeThread()) {
    -        mReader->GetDecoder()->GetReentrantMonitor().AssertCurrentThreadIn();
    -      }
    -      return mSubReaderList.Length();
    -    }
    -
    -    // Returns true if |mSubReaderList| is empty. Will assert that threads
    -    // other than the decode thread are "in monitor".
    -    bool IsEmpty() const
    -    {
    -      NS_ASSERTION(mReader->GetDecoder(), "Decoder is null!");
    -      if (!mReader->GetDecoder()->OnDecodeThread()) {
    -        mReader->GetDecoder()->GetReentrantMonitor().AssertCurrentThreadIn();
    -      }
    -      return mSubReaderList.IsEmpty();
    -    }
    -    // Override '[]' to assert threads other than the decode thread are "in
    -    // monitor" for accessing individual elems. Note: elems returned do not
    -    // have monitor assertions builtin like |MonitoredSubReader| objects.
    -    nsRefPtr& operator[](uint32_t i)
    -    {
    -      NS_ASSERTION(mReader->GetDecoder(), "Decoder is null!");
    -      if (!mReader->GetDecoder()->OnDecodeThread()) {
    -        mReader->GetDecoder()->GetReentrantMonitor().AssertCurrentThreadIn();
    -      }
    -      return mSubReaderList[i];
    -    }
    -
    -    // Appends a reader to the end of |mSubReaderList|. Will always assert that
    -    // the thread is "in monitor".
    -    void
    -    AppendElement(DASHRepReader* aReader)
    -    {
    -      NS_ASSERTION(mReader->GetDecoder(), "Decoder is null!");
    -      mReader->GetDecoder()->GetReentrantMonitor().AssertCurrentThreadIn();
    -      mSubReaderList.AppendElement(aReader);
    -    }
    -  private:
    -    // Pointer to |DASHReader| object which owns this |MonitoredSubReader|.
    -    DASHReader* mReader;
    -    // Ref ptrs to the sub readers.
    -    nsTArray > mSubReaderList;
    -  };
    -
    -  // Ref ptrs to all sub-readers of individual media |Representation|s.
    -  // Decoder monitor must be entered for write access on all threads and read
    -  // access on all threads that are not the decode thread. Read acces on the
    -  // decode thread does not need to be protected.
    -  MonitoredSubReaderList mAudioReaders;
    -  MonitoredSubReaderList mVideoReaders;
    -
    -  // When true, indicates that we should switch reader. Must be in the monitor
    -  // for write access and read access off the decode thread.
    -  bool mSwitchVideoReaders;
    -
    -  // Indicates the subsegment index at which the reader should switch. Must be
    -  // in the monitor for write access and read access off the decode thread.
    -  nsTArray mSwitchToVideoSubsegmentIndexes;
    -
    -  // Counts the number of switches that have taken place. Must be in the
    -  // monitor for write access and read access off the decode thread.
    -  int32_t mSwitchCount;
    -};
    -
    -} // namespace mozilla
    -
    -#endif
    diff --git a/content/media/dash/DASHRepDecoder.cpp b/content/media/dash/DASHRepDecoder.cpp
    deleted file mode 100644
    index 742061f3a6af..000000000000
    --- a/content/media/dash/DASHRepDecoder.cpp
    +++ /dev/null
    @@ -1,517 +0,0 @@
    -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
    -/* vim:set ts=2 sw=2 sts=2 et cindent: */
    -
    -/* This Source Code Form Is subject to the terms of the Mozilla Public
    - * License, v. 2.0. If a copy of the MPL was not distributed with this file,
    - * You can obtain one at http://mozilla.org/MPL/2.0/. */
    -
    -/* DASH - Dynamic Adaptive Streaming over HTTP
    - *
    - * DASH is an adaptive bitrate streaming technology where a multimedia file is
    - * partitioned into one or more segments and delivered to a client using HTTP.
    - *
    - * see DASHDecoder.cpp for info on DASH interaction with the media engine.*/
    -
    -#include "prlog.h"
    -#include "VideoUtils.h"
    -#include "SegmentBase.h"
    -#include "MediaDecoderStateMachine.h"
    -#include "DASHReader.h"
    -#include "MediaResource.h"
    -#include "DASHRepDecoder.h"
    -#include "WebMReader.h"
    -#include 
    -
    -namespace mozilla {
    -
    -#ifdef PR_LOGGING
    -extern PRLogModuleInfo* gMediaDecoderLog;
    -#define LOG(msg, ...) PR_LOG(gMediaDecoderLog, PR_LOG_DEBUG, \
    -                             ("%p [DASHRepDecoder] " msg, this, __VA_ARGS__))
    -#define LOG1(msg) PR_LOG(gMediaDecoderLog, PR_LOG_DEBUG, \
    -                         ("%p [DASHRepDecoder] " msg, this))
    -#else
    -#define LOG(msg, ...)
    -#define LOG1(msg)
    -#endif
    -
    -MediaDecoderStateMachine*
    -DASHRepDecoder::CreateStateMachine()
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -  // Do not create; just return current state machine.
    -  return mDecoderStateMachine;
    -}
    -
    -nsresult
    -DASHRepDecoder::SetStateMachine(MediaDecoderStateMachine* aSM)
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -  mDecoderStateMachine = aSM;
    -  return NS_OK;
    -}
    -
    -void
    -DASHRepDecoder::SetResource(MediaResource* aResource)
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -  mResource = aResource;
    -}
    -
    -void
    -DASHRepDecoder::SetMPDRepresentation(Representation const * aRep)
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -  mMPDRepresentation = aRep;
    -}
    -
    -void
    -DASHRepDecoder::SetReader(WebMReader* aReader)
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -  mReader = aReader;
    -}
    -
    -nsresult
    -DASHRepDecoder::Load(nsIStreamListener** aListener,
    -                     MediaDecoder* aCloneDonor)
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -  NS_ENSURE_TRUE(mMPDRepresentation, NS_ERROR_NOT_INITIALIZED);
    -
    -  // Get init range and index range from MPD.
    -  SegmentBase const * segmentBase = mMPDRepresentation->GetSegmentBase();
    -  NS_ENSURE_TRUE(segmentBase, NS_ERROR_NULL_POINTER);
    -
    -  // Get and set init range.
    -  segmentBase->GetInitRange(&mInitByteRange.mStart, &mInitByteRange.mEnd);
    -  NS_ENSURE_TRUE(!mInitByteRange.IsNull(), NS_ERROR_NOT_INITIALIZED);
    -  mReader->SetInitByteRange(mInitByteRange);
    -
    -  // Get and set index range.
    -  segmentBase->GetIndexRange(&mIndexByteRange.mStart, &mIndexByteRange.mEnd);
    -  NS_ENSURE_TRUE(!mIndexByteRange.IsNull(), NS_ERROR_NOT_INITIALIZED);
    -  mReader->SetIndexByteRange(mIndexByteRange);
    -
    -  // Determine byte range to Open.
    -  // For small deltas between init and index ranges, we need to bundle the byte
    -  // range requests together in order to deal with |MediaCache|'s control of
    -  // seeking (see |MediaCache|::|Update|). |MediaCache| will not initiate a
    -  // |ChannelMediaResource|::|CacheClientSeek| for the INDEX byte range if the
    -  // delta between it and the INIT byte ranges is less than
    -  // |SEEK_VS_READ_THRESHOLD|. To get around this, request all metadata bytes
    -  // now so |MediaCache| can assume the bytes are en route.
    -  int64_t delta = std::max(mIndexByteRange.mStart, mInitByteRange.mStart)
    -                - std::min(mIndexByteRange.mEnd, mInitByteRange.mEnd);
    -  MediaByteRange byteRange;
    -  if (delta <= SEEK_VS_READ_THRESHOLD) {
    -    byteRange.mStart = std::min(mIndexByteRange.mStart, mInitByteRange.mStart);
    -    byteRange.mEnd = std::max(mIndexByteRange.mEnd, mInitByteRange.mEnd);
    -    // Loading everything in one chunk .
    -    mMetadataChunkCount = 1;
    -  } else {
    -    byteRange = mInitByteRange;
    -    // Loading in two chunks: init and index.
    -    mMetadataChunkCount = 2;
    -  }
    -  mCurrentByteRange = byteRange;
    -  return mResource->OpenByteRange(nullptr, byteRange);
    -}
    -
    -void
    -DASHRepDecoder::NotifyDownloadEnded(nsresult aStatus)
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -
    -  if (!mMainDecoder) {
    -    if (!mShuttingDown) {
    -      LOG("Error! Main Decoder is null before shutdown: mMainDecoder [%p] ",
    -          mMainDecoder.get());
    -      DecodeError();
    -    }
    -    return;
    -  }
    -
    -  if (NS_SUCCEEDED(aStatus)) {
    -    ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
    -    // Decrement counter as metadata chunks are downloaded.
    -    // Note: Reader gets next chunk download via |ChannelMediaResource|:|Seek|.
    -    if (mMetadataChunkCount > 0) {
    -      LOG("Metadata chunk [%d] downloaded: range requested [%lld - %lld] "
    -          "subsegmentIdx [%d]",
    -          mMetadataChunkCount,
    -          mCurrentByteRange.mStart, mCurrentByteRange.mEnd, mSubsegmentIdx);
    -      mMetadataChunkCount--;
    -    } else {
    -      LOG("Byte range downloaded: status [%x] range requested [%lld - %lld] "
    -          "subsegmentIdx [%d]",
    -          aStatus, mCurrentByteRange.mStart, mCurrentByteRange.mEnd,
    -          mSubsegmentIdx);
    -      if ((uint32_t)mSubsegmentIdx == mByteRanges.Length()-1) {
    -        mResource->NotifyLastByteRange();
    -      }
    -      // Notify main decoder that a DATA byte range is downloaded.
    -      mMainDecoder->NotifyDownloadEnded(this, aStatus, mSubsegmentIdx);
    -    }
    -  } else if (aStatus == NS_BINDING_ABORTED) {
    -    LOG("Media download has been cancelled by the user: aStatus [%x].",
    -        aStatus);
    -    if (mMainDecoder) {
    -      mMainDecoder->LoadAborted();
    -    }
    -    return;
    -  } else if (aStatus != NS_BASE_STREAM_CLOSED) {
    -    LOG("Network error trying to download MPD: aStatus [%x].", aStatus);
    -    NetworkError();
    -  }
    -}
    -
    -void
    -DASHRepDecoder::OnReadMetadataCompleted()
    -{
    -  NS_ASSERTION(OnDecodeThread(), "Should be on decode thread.");
    -
    -  // If shutting down, just return silently.
    -  if (mShuttingDown) {
    -    LOG1("Shutting down! Ignoring OnReadMetadataCompleted().");
    -    return;
    -  }
    -
    -  LOG1("Metadata has been read.");
    -
    -  // Metadata loaded and read for this stream; ok to populate byte ranges.
    -  nsresult rv = PopulateByteRanges();
    -  if (NS_FAILED(rv) || mByteRanges.IsEmpty()) {
    -    LOG("Error populating byte ranges [%x]", rv);
    -    DecodeError();
    -    return;
    -  }
    -
    -  mMainDecoder->OnReadMetadataCompleted(this);
    -}
    -
    -nsresult
    -DASHRepDecoder::PopulateByteRanges()
    -{
    -  NS_ASSERTION(OnDecodeThread(), "Should be on decode thread.");
    -
    -  // Should not be called during shutdown.
    -  NS_ENSURE_FALSE(mShuttingDown, NS_ERROR_UNEXPECTED);
    -
    -  ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
    -  if (!mByteRanges.IsEmpty()) {
    -    return NS_OK;
    -  }
    -  NS_ENSURE_TRUE(mReader, NS_ERROR_NULL_POINTER);
    -  LOG1("Populating byte range array.");
    -  return mReader->GetSubsegmentByteRanges(mByteRanges);
    -}
    -
    -void
    -DASHRepDecoder::LoadNextByteRange()
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -  NS_ASSERTION(mResource, "Error: resource is reported as null!");
    -
    -  // Return silently if shutting down.
    -  if (mShuttingDown) {
    -    LOG1("Shutting down! Ignoring LoadNextByteRange().");
    -    return;
    -  }
    -
    -  ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
    -  NS_ASSERTION(mMainDecoder, "Error: main decoder is null!");
    -  NS_ASSERTION(mMainDecoder->IsDecoderAllowedToDownloadData(this),
    -               "Should not be called on non-active decoders!");
    -
    -  // Cannot have empty byte ranges.
    -  if (mByteRanges.IsEmpty()) {
    -    LOG1("Error getting list of subsegment byte ranges.");
    -    DecodeError();
    -    return;
    -  }
    -
    -  // Get byte range for subsegment.
    -  int32_t subsegmentIdx = mMainDecoder->GetSubsegmentIndex(this);
    -  NS_ASSERTION(0 <= subsegmentIdx,
    -               "Subsegment index should be >= 0 for active decoders");
    -  if (subsegmentIdx >= 0 && (uint32_t)subsegmentIdx < mByteRanges.Length()) {
    -    mCurrentByteRange = mByteRanges[subsegmentIdx];
    -    mSubsegmentIdx = subsegmentIdx;
    -  } else {
    -    mCurrentByteRange.Clear();
    -    mSubsegmentIdx = -1;
    -    LOG("End of subsegments: index [%d] out of range.", subsegmentIdx);
    -    return;
    -  }
    -
    -  // Request a seek for the first reader. Required so that the reader is
    -  // primed to start here, and will block subsequent subsegment seeks unless
    -  // the subsegment has been read.
    -  if (subsegmentIdx == 0) {
    -    ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
    -    mReader->RequestSeekToSubsegment(0);
    -  }
    -
    -  // Query resource for cached ranges; only download if it's not there.
    -  if (IsSubsegmentCached(mSubsegmentIdx)) {
    -    LOG("Subsegment [%d] bytes [%lld] to [%lld] already cached. No need to "
    -        "download.", mSubsegmentIdx,
    -        mCurrentByteRange.mStart, mCurrentByteRange.mEnd);
    -    nsCOMPtr event =
    -      NS_NewRunnableMethod(this, &DASHRepDecoder::DoNotifyDownloadEnded);
    -    nsresult rv = NS_DispatchToMainThread(event);
    -    if (NS_FAILED(rv)) {
    -      LOG("Error notifying subsegment [%d] cached: rv[0x%x].",
    -          mSubsegmentIdx, rv);
    -      NetworkError();
    -    }
    -    return;
    -  }
    -
    -  // Open byte range corresponding to subsegment.
    -  nsresult rv = mResource->OpenByteRange(nullptr, mCurrentByteRange);
    -  if (NS_FAILED(rv)) {
    -    LOG("Error opening byte range [%lld - %lld]: subsegmentIdx [%d] rv [%x].",
    -        mCurrentByteRange.mStart, mCurrentByteRange.mEnd, mSubsegmentIdx, rv);
    -    NetworkError();
    -    return;
    -  }
    -}
    -
    -bool
    -DASHRepDecoder::IsSubsegmentCached(int32_t aSubsegmentIdx)
    -{
    -  GetReentrantMonitor().AssertCurrentThreadIn();
    -
    -  MediaByteRange byteRange = mByteRanges[aSubsegmentIdx];
    -  int64_t start = mResource->GetNextCachedData(byteRange.mStart);
    -  int64_t end = mResource->GetCachedDataEnd(byteRange.mStart);
    -  return (start == byteRange.mStart &&
    -          end >= byteRange.mEnd);
    -}
    -
    -void
    -DASHRepDecoder::DoNotifyDownloadEnded()
    -{
    -  NotifyDownloadEnded(NS_OK);
    -}
    -
    -nsresult
    -DASHRepDecoder::GetByteRangeForSeek(int64_t const aOffset,
    -                                    MediaByteRange& aByteRange)
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -
    -  // Only check data ranges if they're available and if this decoder is active,
    -  // i.e. inactive rep decoders should only load metadata.
    -  ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
    -
    -  for (uint32_t i = 0; i < mByteRanges.Length(); i++) {
    -    NS_ENSURE_FALSE(mByteRanges[i].IsNull(), NS_ERROR_NOT_INITIALIZED);
    -    // Check if |aOffset| lies within the current data range.
    -    if (mByteRanges[i].mStart <= aOffset && aOffset <= mByteRanges[i].mEnd) {
    -      if (mMainDecoder->IsDecoderAllowedToDownloadSubsegment(this, i)) {
    -        mCurrentByteRange = aByteRange = mByteRanges[i];
    -        mSubsegmentIdx = i;
    -        // XXX Hack: should be setting subsegment outside this function, but
    -        // need to review seeking for multiple switches anyhow.
    -        mMainDecoder->SetSubsegmentIndex(this, i);
    -        LOG("Getting DATA range [%d] for seek offset [%lld]: "
    -            "bytes [%lld] to [%lld]",
    -            i, aOffset, aByteRange.mStart, aByteRange.mEnd);
    -        return NS_OK;
    -      }
    -      break;
    -    }
    -  }
    -  // Don't allow metadata downloads once they're loaded and byte ranges have
    -  // been populated.
    -  bool canDownloadMetadata = mByteRanges.IsEmpty();
    -  if (canDownloadMetadata) {
    -    // Check metadata ranges; init range.
    -    if (mInitByteRange.mStart <= aOffset && aOffset <= mInitByteRange.mEnd) {
    -      mCurrentByteRange = aByteRange = mInitByteRange;
    -      mSubsegmentIdx = 0;
    -        LOG("Getting INIT range for seek offset [%lld]: bytes [%lld] to "
    -            "[%lld]", aOffset, aByteRange.mStart, aByteRange.mEnd);
    -      return NS_OK;
    -    }
    -    // ... index range.
    -    if (mIndexByteRange.mStart <= aOffset && aOffset <= mIndexByteRange.mEnd) {
    -      mCurrentByteRange = aByteRange = mIndexByteRange;
    -      mSubsegmentIdx = 0;
    -      LOG("Getting INDEXES range for seek offset [%lld]: bytes [%lld] to "
    -          "[%lld]", aOffset, aByteRange.mStart, aByteRange.mEnd);
    -      return NS_OK;
    -    }
    -  } else {
    -    LOG1("Metadata should be read; inhibiting further metadata downloads.");
    -  }
    -
    -  // If no byte range is found by this stage, clear the parameter and return.
    -  aByteRange.Clear();
    -  if (mByteRanges.IsEmpty() || !canDownloadMetadata) {
    -    // Assume mByteRanges will be populated after metadata is read.
    -    LOG("Data ranges not populated [%s]; metadata download restricted [%s]: "
    -        "offset[%lld].",
    -        (mByteRanges.IsEmpty() ? "yes" : "no"),
    -        (canDownloadMetadata ? "no" : "yes"), aOffset);
    -    return NS_ERROR_NOT_AVAILABLE;
    -  } else {
    -    // Cannot seek to an unknown offset.
    -    // XXX Revisit this for dynamic MPD profiles if MPD is regularly updated.
    -    LOG("Error! Offset [%lld] is in an unknown range!", aOffset);
    -    return NS_ERROR_ILLEGAL_VALUE;
    -  }
    -}
    -
    -void
    -DASHRepDecoder::PrepareForSwitch()
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -  // Ensure that the media cache writes any data held in its partial block.
    -  mResource->FlushCache();
    -}
    -
    -void
    -DASHRepDecoder::NetworkError()
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -  if (mMainDecoder) { mMainDecoder->NetworkError(); }
    -}
    -
    -void
    -DASHRepDecoder::SetDuration(double aDuration)
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -  if (mMainDecoder) { mMainDecoder->SetDuration(aDuration); }
    -}
    -
    -void
    -DASHRepDecoder::SetInfinite(bool aInfinite)
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -  if (mMainDecoder) { mMainDecoder->SetInfinite(aInfinite); }
    -}
    -
    -void
    -DASHRepDecoder::SetMediaSeekable(bool aMediaSeekable)
    -{
    -  NS_ASSERTION(NS_IsMainThread() || OnDecodeThread(),
    -               "Should be on main thread or decode thread.");
    -  if (mMainDecoder) { mMainDecoder->SetMediaSeekable(aMediaSeekable); }
    -}
    -
    -void
    -DASHRepDecoder::Progress(bool aTimer)
    -{
    -  if (mMainDecoder) { mMainDecoder->Progress(aTimer); }
    -}
    -
    -void
    -DASHRepDecoder::NotifyDataArrived(const char* aBuffer,
    -                                  uint32_t aLength,
    -                                  int64_t aOffset)
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -
    -  LOG("Data bytes [%lld - %lld] arrived via buffer [%p].",
    -      aOffset, aOffset+aLength, aBuffer);
    -  // Notify reader directly, since call to |MediaDecoderStateMachine|::
    -  // |NotifyDataArrived| will go to |DASHReader|::|NotifyDataArrived|, which
    -  // has no way to forward the notification to the correct sub-reader.
    -  if (mReader) {
    -    mReader->NotifyDataArrived(aBuffer, aLength, aOffset);
    -  }
    -  // Forward to main decoder which will notify state machine.
    -  if (mMainDecoder) {
    -    mMainDecoder->NotifyDataArrived(aBuffer, aLength, aOffset);
    -  }
    -}
    -
    -void
    -DASHRepDecoder::NotifyBytesDownloaded()
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -  if (mMainDecoder) { mMainDecoder->NotifyBytesDownloaded(); }
    -}
    -
    -void
    -DASHRepDecoder::NotifySuspendedStatusChanged()
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -  if (mMainDecoder) { mMainDecoder->NotifySuspendedStatusChanged(); }
    -}
    -
    -bool
    -DASHRepDecoder::OnStateMachineThread() const
    -{
    -  return (mMainDecoder ? mMainDecoder->OnStateMachineThread() : false);
    -}
    -
    -bool
    -DASHRepDecoder::OnDecodeThread() const
    -{
    -  return (mMainDecoder ? mMainDecoder->OnDecodeThread() : false);
    -}
    -
    -ReentrantMonitor&
    -DASHRepDecoder::GetReentrantMonitor()
    -{
    -  NS_ASSERTION(mMainDecoder, "Can't get monitor if main decoder is null!");
    -  if (mMainDecoder) {
    -    return mMainDecoder->GetReentrantMonitor();
    -  } else {
    -    // XXX If mMainDecoder is gone, most likely we're past shutdown and
    -    // a waiting function has been wakened. Just return this decoder's own
    -    // monitor and let the function complete.
    -    return MediaDecoder::GetReentrantMonitor();
    -  }
    -}
    -
    -mozilla::layers::ImageContainer*
    -DASHRepDecoder::GetImageContainer()
    -{
    -  return (mMainDecoder ? mMainDecoder->GetImageContainer() : nullptr);
    -}
    -
    -void
    -DASHRepDecoder::DecodeError()
    -{
    -  if (NS_IsMainThread()) {
    -    MediaDecoder::DecodeError();
    -  } else {
    -    nsCOMPtr event =
    -      NS_NewRunnableMethod(this, &MediaDecoder::DecodeError);
    -    nsresult rv = NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
    -    if (NS_FAILED(rv)) {
    -      LOG("Error dispatching DecodeError event to main thread: rv[%x]", rv);
    -    }
    -  }
    -}
    -
    -void
    -DASHRepDecoder::ReleaseStateMachine()
    -{
    -  NS_ASSERTION(NS_IsMainThread(), "Must be on main thread.");
    -
    -  // Since state machine owns mReader, remove reference to it.
    -  mReader = nullptr;
    -
    -  MediaDecoder::ReleaseStateMachine();
    -}
    -
    -void DASHRepDecoder::StopProgressUpdates()
    -{
    -  NS_ENSURE_TRUE_VOID(mMainDecoder);
    -  MediaDecoder::StopProgressUpdates();
    -}
    -
    -void DASHRepDecoder::StartProgressUpdates()
    -{
    -  NS_ENSURE_TRUE_VOID(mMainDecoder);
    -  MediaDecoder::StartProgressUpdates();
    -}
    -
    -} // namespace mozilla
    diff --git a/content/media/dash/DASHRepDecoder.h b/content/media/dash/DASHRepDecoder.h
    deleted file mode 100644
    index 3634f121c428..000000000000
    --- a/content/media/dash/DASHRepDecoder.h
    +++ /dev/null
    @@ -1,237 +0,0 @@
    -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
    -/* vim:set ts=2 sw=2 sts=2 et cindent: */
    -
    -/* This Source Code Form Is subject to the terms of the Mozilla Public
    - * License, v. 2.0. If a copy of the MPL was not distributed with this file,
    - * You can obtain one at http://mozilla.org/MPL/2.0/. */
    -
    -/* DASH - Dynamic Adaptive Streaming over HTTP
    - *
    - * DASH is an adaptive bitrate streaming technology where a multimedia file is
    - * partitioned into one or more segments and delivered to a client using HTTP.
    - *
    - * see DASHDecoder.cpp for info on DASH interaction with the media engine.*/
    -
    -#if !defined(DASHRepDecoder_h_)
    -#define DASHRepDecoder_h_
    -
    -#include "Representation.h"
    -#include "DASHDecoder.h"
    -#include "WebMDecoder.h"
    -#include "WebMReader.h"
    -#include "MediaDecoder.h"
    -
    -namespace mozilla {
    -
    -namespace layers {
    -class ImageContainer;
    -}
    -
    -class DASHDecoder;
    -class DASHRepReader;
    -
    -class DASHRepDecoder : public MediaDecoder
    -{
    -public:
    -  typedef mozilla::net::Representation Representation;
    -  typedef mozilla::net::SegmentBase SegmentBase;
    -  typedef mozilla::layers::ImageContainer ImageContainer;
    -
    -  // Constructor takes a ptr to the main decoder.
    -  DASHRepDecoder(DASHDecoder* aMainDecoder) :
    -    mMainDecoder(aMainDecoder),
    -    mMPDRepresentation(nullptr),
    -    mMetadataChunkCount(0),
    -    mCurrentByteRange(),
    -    mSubsegmentIdx(-1),
    -    mReader(nullptr)
    -  {
    -    MOZ_COUNT_CTOR(DASHRepDecoder);
    -  }
    -
    -  ~DASHRepDecoder()
    -  {
    -    MOZ_COUNT_DTOR(DASHRepDecoder);
    -  }
    -
    -  // Clone not supported; just return nullptr.
    -  virtual MediaDecoder* Clone() { return nullptr; }
    -
    -  // Called by the main decoder at creation time; points to the main state
    -  // machine managed by the main decoder. Called on the main thread only.
    -  nsresult SetStateMachine(MediaDecoderStateMachine* aSM);
    -
    -private:
    -  // Overridden to return the ptr set by SetStateMachine. Called on the main
    -  // thread only.
    -  MediaDecoderStateMachine* CreateStateMachine();
    -
    -public:
    -  // Called by DASHDecoder at creation time; points to the media resource
    -  // for this decoder's |Representation|. Called on the main thread only.
    -  void SetResource(MediaResource* aResource);
    -
    -  // Sets the |Representation| object for this decoder. Called on the main
    -  // thread.
    -  void SetMPDRepresentation(Representation const * aRep);
    -
    -  // Called from DASHDecoder on main thread; Starts media stream download.
    -  virtual nsresult Load(nsIStreamListener** aListener = nullptr,
    -                        MediaDecoder* aCloneDonor = nullptr) MOZ_OVERRIDE;
    -
    -  // Loads the next byte range (or first one on first call). Called on the main
    -  // thread only.
    -  void LoadNextByteRange();
    -
    -  // Returns true if the subsegment is already in the media cache.
    -  bool IsSubsegmentCached(int32_t aSubsegmentIdx);
    -
    -  // Calls from DASHRepDecoder. Called on the main thread only.
    -  void SetReader(WebMReader* aReader);
    -
    -  // Called if the media file encounters a network error. Call on the main
    -  // thread only.
    -  void NetworkError();
    -
    -  // Called from reader during ReadMetadata. This should be ignored here, and
    -  // instead, duration should be set following MPD parsing.
    -  void SetMediaDuration(int64_t aDuration) MOZ_OVERRIDE { };
    -
    -  // Set the duration of the media resource in units of seconds.
    -  // This is called via a channel listener if it can pick up the duration
    -  // from a content header. Must be called from the main thread only.
    -  virtual void SetDuration(double aDuration);
    -
    -  // Set media stream as infinite. Called on the main thread only.
    -  void SetInfinite(bool aInfinite);
    -
    -  // Sets media stream as seekable. Called on main thread only.
    -  void SetMediaSeekable(bool aSeekable);
    -
    -  // Fire progress events if needed according to the time and byte
    -  // constraints outlined in the specification. aTimer is true
    -  // if the method is called as a result of the progress timer rather
    -  // than the result of downloaded data.
    -  void Progress(bool aTimer);
    -
    -  // Called as data arrives on the stream and is read into the cache.  Called
    -  // on the main thread only.
    -  void NotifyDataArrived(const char* aBuffer,
    -                         uint32_t aLength,
    -                         int64_t aOffset);
    -
    -  // Called by MediaResource when some data has been received.
    -  // Call on the main thread only.
    -  void NotifyBytesDownloaded();
    -
    -  // Notify that a byte range request has been completed by the media resource.
    -  // Called on the main thread only.
    -  void NotifyDownloadEnded(nsresult aStatus);
    -
    -  // Called asynchronously by |LoadNextByteRange| if the data is already in the
    -  // media cache. This will call NotifyDownloadEnded on the main thread with
    -  // |aStatus| of NS_OK.
    -  void DoNotifyDownloadEnded();
    -
    -  // Called by MediaResource when the "cache suspended" status changes.
    -  // If MediaResource::IsSuspendedByCache returns true, then the decoder
    -  // should stop buffering or otherwise waiting for download progress and
    -  // start consuming data, if possible, because the cache is full.
    -  void NotifySuspendedStatusChanged();
    -
    -  // Increments the parsed and decoded frame counters by the passed in counts.
    -  // Can be called on any thread.
    -  void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded) MOZ_OVERRIDE {
    -    if (mMainDecoder) {mMainDecoder->NotifyDecodedFrames(aParsed, aDecoded); }
    -  }
    -
    -  // Gets a byte range containing the byte offset. Call on main thread only.
    -  nsresult GetByteRangeForSeek(int64_t const aOffset,
    -                               MediaByteRange& aByteRange);
    -
    -  // Gets the number of data byte ranges (not inc. metadata).
    -  uint32_t GetNumDataByteRanges() {
    -    return mByteRanges.Length();
    -  }
    -
    -  // Notify that a switch is about to happen. Called on the main thread.
    -  void PrepareForSwitch();
    -
    -  // Returns true if the current thread is the state machine thread.
    -  bool OnStateMachineThread() const MOZ_OVERRIDE;
    -
    -  // Returns true if the current thread is the decode thread.
    -  bool OnDecodeThread() const MOZ_OVERRIDE;
    -
    -  // Returns main decoder's monitor for synchronised access.
    -  ReentrantMonitor& GetReentrantMonitor() MOZ_OVERRIDE;
    -
    -  // Called on the decode thread from WebMReader.
    -  ImageContainer* GetImageContainer() MOZ_OVERRIDE;
    -
    -  // Called when Metadata has been read; notifies that index data is read.
    -  // Called on the decode thread only.
    -  void OnReadMetadataCompleted() MOZ_OVERRIDE;
    -
    -  // Stop updating the bytes downloaded for progress notifications. Called
    -  // when seeking to prevent wild changes to the progress notification.
    -  // Must be called with the decoder monitor held.
    -  void StopProgressUpdates() MOZ_OVERRIDE;
    -
    -  // Allow updating the bytes downloaded for progress notifications. Must
    -  // be called with the decoder monitor held.
    -  void StartProgressUpdates() MOZ_OVERRIDE;
    -
    -  // Overridden to cleanup ref to |DASHDecoder|. Called on main thread only.
    -  void Shutdown() {
    -    NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
    -    // Remove ref to state machine before |MediaDecoder|::|Shutdown|, since
    -    // |DASHDecoder| is responsible for its shutdown.
    -    mDecoderStateMachine = nullptr;
    -    // Call parent class shutdown.
    -    MediaDecoder::Shutdown();
    -    NS_ENSURE_TRUE_VOID(mShuttingDown);
    -    // Cleanup ref to main decoder.
    -    mMainDecoder = nullptr;
    -  }
    -
    -  // Drop reference to state machine and mReader (owned by state machine).
    -  // Only called during shutdown dance.
    -  void ReleaseStateMachine();
    -
    -  // Notifies the element that decoding has failed.
    -  void DecodeError();
    -
    -private:
    -  // Populates |mByteRanges| by calling |GetIndexByteRanges| from |mReader|.
    -  // Called on the main thread only.
    -  nsresult PopulateByteRanges();
    -
    -  // The main decoder.
    -  nsRefPtr mMainDecoder;
    -  // This decoder's MPD |Representation| object.
    -  Representation const * mMPDRepresentation;
    -
    -  // Countdown var for loading metadata byte ranges.
    -  uint16_t        mMetadataChunkCount;
    -
    -  // All the byte ranges for this |Representation|.
    -  nsTArray mByteRanges;
    -
    -  // Byte range for the init and index bytes.
    -  MediaByteRange  mInitByteRange;
    -  MediaByteRange  mIndexByteRange;
    -
    -  // The current byte range being requested.
    -  MediaByteRange  mCurrentByteRange;
    -  // Index of the current byte range. Initialized to -1.
    -  int32_t         mSubsegmentIdx;
    -
    -  // Ptr to the reader object for this |Representation|. Owned by state
    -  // machine.
    -  DASHRepReader* mReader;
    -};
    -
    -} // namespace mozilla
    -
    -#endif //DASHRepDecoder_h_
    diff --git a/content/media/dash/DASHRepReader.h b/content/media/dash/DASHRepReader.h
    deleted file mode 100644
    index 23b4cf22ea57..000000000000
    --- a/content/media/dash/DASHRepReader.h
    +++ /dev/null
    @@ -1,68 +0,0 @@
    -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
    -/* vim:set ts=2 sw=2 sts=2 et cindent: */
    -
    -/* This Source Code Form Is subject to the terms of the Mozilla Public
    - * License, v. 2.0. If a copy of the MPL was not distributed with this file,
    - * You can obtain one at http://mozilla.org/MPL/2.0/. */
    -
    -/* DASH - Dynamic Adaptive Streaming over HTTP
    - *
    - * DASH is an adaptive bitrate streaming technology where a multimedia file is
    - * partitioned into one or more segments and delivered to a client using HTTP.
    - *
    - * see DASHDecoder.cpp for comments on DASH object interaction
    - */
    -
    -#if !defined(DASHRepReader_h_)
    -#define DASHRepReader_h_
    -
    -#include "VideoUtils.h"
    -#include "MediaDecoderReader.h"
    -#include "DASHReader.h"
    -
    -namespace mozilla {
    -
    -class DASHReader;
    -
    -class DASHRepReader : public MediaDecoderReader
    -{
    -public:
    -  DASHRepReader(AbstractMediaDecoder* aDecoder)
    -    : MediaDecoderReader(aDecoder) { }
    -  virtual ~DASHRepReader() { }
    -
    -  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DASHRepReader)
    -
    -  virtual void SetMainReader(DASHReader *aMainReader) = 0;
    -
    -  // Sets range for initialization bytes; used by DASH.
    -  virtual void SetInitByteRange(MediaByteRange &aByteRange) = 0;
    -
    -  // Sets range for index frame bytes; used by DASH.
    -  virtual void SetIndexByteRange(MediaByteRange &aByteRange) = 0;
    -
    -  // Returns the index of the subsegment which contains the seek time (usecs).
    -  virtual int64_t GetSubsegmentForSeekTime(int64_t aSeekToTime) = 0;
    -
    -  // Returns list of ranges for index frame start/end offsets. Used by DASH.
    -  virtual nsresult GetSubsegmentByteRanges(nsTArray& aByteRanges) = 0;
    -
    -  // Returns true if the reader has reached a DASH switch access point.
    -  virtual bool HasReachedSubsegment(uint32_t aSubsegmentIndex) = 0;
    -
    -  // Requests a seek to the start of a particular DASH subsegment.
    -  virtual void RequestSeekToSubsegment(uint32_t aIdx) = 0;
    -
    -  // Reader should stop reading at the start of the specified subsegment, and
    -  // should prepare for the next reader to add data to the video queue.
    -  // Should be implemented by a sub-reader, e.g. |nsDASHWebMReader|.
    -  virtual void RequestSwitchAtSubsegment(int32_t aCluster,
    -                                         MediaDecoderReader* aNextReader) = 0;
    -
    -  // Returns true if data at the end of the final subsegment has been cached.
    -  virtual bool IsDataCachedAtEndOfSubsegments() = 0;
    -};
    -
    -}// namespace mozilla
    -
    -#endif /*DASHRepReader*/
    diff --git a/content/media/dash/Makefile.in b/content/media/dash/Makefile.in
    deleted file mode 100644
    index d17d2cd9c9e4..000000000000
    --- a/content/media/dash/Makefile.in
    +++ /dev/null
    @@ -1,19 +0,0 @@
    -# -*- Mode: makefile; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- #
    -# vim: set ts=2 et sw=2 tw=80: #
    -#
    -# This Source Code Form is subject to the terms of the Mozilla Public
    -# License, v. 2.0. If a copy of the MPL was not distributed with this
    -# file, You can obtain one at http://mozilla.org/MPL/2.0/.
    -#
    -# Contributor(s):
    -#     Steve Workman 
    -
    -include $(topsrcdir)/config/rules.mk
    -
    -LOCAL_INCLUDES := \
    -  -I$(topsrcdir)/netwerk/dash/mpd \
    -  -I$(srcdir)/../webm \
    -  -I$(srcdir)/../../base/src \
    -  -I$(srcdir)/../../html/content/src \
    -  $(MOZ_LIBVPX_INCLUDES) \
    -  $(NULL)
    diff --git a/content/media/dash/moz.build b/content/media/dash/moz.build
    deleted file mode 100644
    index 5bfe1d772020..000000000000
    --- a/content/media/dash/moz.build
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
    -# vim: set filetype=python:
    -# This Source Code Form is subject to the terms of the Mozilla Public
    -# License, v. 2.0. If a copy of the MPL was not distributed with this
    -# file, You can obtain one at http://mozilla.org/MPL/2.0/.
    -
    -MODULE = 'content'
    -
    -EXPORTS += [
    -    'DASHDecoder.h',
    -    'DASHReader.h',
    -    'DASHRepDecoder.h',
    -    'DASHRepReader.h',
    -]
    -
    -SOURCES += [
    -    'DASHDecoder.cpp',
    -    'DASHReader.cpp',
    -    'DASHRepDecoder.cpp',
    -]
    -
    -LIBRARY_NAME = 'gkcondash_s'
    -
    -LIBXUL_LIBRARY = True
    -
    diff --git a/content/media/moz.build b/content/media/moz.build
    index 7e2ce4543260..87b3af69d12b 100644
    --- a/content/media/moz.build
    +++ b/content/media/moz.build
    @@ -26,9 +26,6 @@ if CONFIG['MOZ_WEBM']:
     if CONFIG['MOZ_GSTREAMER']:
         PARALLEL_DIRS += ['gstreamer']
     
    -if CONFIG['MOZ_DASH']:
    -    PARALLEL_DIRS += ['dash']
    -
     if CONFIG['MOZ_DIRECTSHOW']:
         PARALLEL_DIRS += ['directshow']
     
    diff --git a/layout/build/Makefile.in b/layout/build/Makefile.in
    index 972012f0f2c0..95dc5c2c59ae 100644
    --- a/layout/build/Makefile.in
    +++ b/layout/build/Makefile.in
    @@ -199,12 +199,6 @@ SHARED_LIBRARY_LIBS 	+= \
     	$(DEPTH)/content/media/mediasource/$(LIB_PREFIX)gkconmediasource_s.$(LIB_SUFFIX) \
     	$(NULL)
     
    -ifdef MOZ_DASH
    -SHARED_LIBRARY_LIBS += \
    -  $(DEPTH)/content/media/dash/$(LIB_PREFIX)gkcondash_s.$(LIB_SUFFIX) \
    -  $(NULL)
    -endif
    -
     ifdef MOZ_WEBSPEECH
     SHARED_LIBRARY_LIBS += \
       $(DEPTH)/content/media/webspeech/recognition/$(LIB_PREFIX)gkconwebspeechrecognition_s.$(LIB_SUFFIX) \
    diff --git a/layout/build/nsContentDLF.h b/layout/build/nsContentDLF.h
    index 87427478a55f..327915cc7c35 100644
    --- a/layout/build/nsContentDLF.h
    +++ b/layout/build/nsContentDLF.h
    @@ -63,13 +63,6 @@ NS_NewContentDocumentLoaderFactory(nsIDocumentLoaderFactory** aResult);
     #define CONTENTDLF_WEBM_CATEGORIES
     #endif
     
    -#ifdef MOZ_DASH
    -#define CONTENTDLF_DASH_CATEGORIES \
    -    { "Gecko-Content-Viewers", APPLICATION_DASH, "@mozilla.org/content/document-loader-factory;1" },
    -#else
    -#define CONTENTDLF_DASH_CATEGORIES
    -#endif
    -
     #define CONTENTDLF_CATEGORIES \
         { "Gecko-Content-Viewers", TEXT_HTML, "@mozilla.org/content/document-loader-factory;1" }, \
         { "Gecko-Content-Viewers", TEXT_PLAIN, "@mozilla.org/content/document-loader-factory;1" }, \
    @@ -91,8 +84,7 @@ NS_NewContentDocumentLoaderFactory(nsIDocumentLoaderFactory** aResult);
         { "Gecko-Content-Viewers", VIEWSOURCE_CONTENT_TYPE, "@mozilla.org/content/document-loader-factory;1" }, \
         { "Gecko-Content-Viewers", IMAGE_SVG_XML, "@mozilla.org/content/document-loader-factory;1" }, \
         { "Gecko-Content-Viewers", APPLICATION_MATHML_XML, "@mozilla.org/content/document-loader-factory;1" }, \
    -    CONTENTDLF_WEBM_CATEGORIES \
    -    CONTENTDLF_DASH_CATEGORIES
    +    CONTENTDLF_WEBM_CATEGORIES
     
     
     #endif
    diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js
    index 3df16e3f28df..a38e4ee2ec71 100644
    --- a/modules/libpref/src/init/all.js
    +++ b/modules/libpref/src/init/all.js
    @@ -215,9 +215,6 @@ pref("media.wave.enabled", true);
     #ifdef MOZ_WEBM
     pref("media.webm.enabled", true);
     #endif
    -#ifdef MOZ_DASH
    -pref("media.dash.enabled", false);
    -#endif
     #ifdef MOZ_GSTREAMER
     pref("media.gstreamer.enabled", true);
     #endif
    diff --git a/netwerk/build/Makefile.in b/netwerk/build/Makefile.in
    index f81ea6fffce8..2da4b2f3dbdc 100644
    --- a/netwerk/build/Makefile.in
    +++ b/netwerk/build/Makefile.in
    @@ -55,11 +55,6 @@ ifeq (android,$(MOZ_WIDGET_TOOLKIT))
             ../system/android/$(LIB_PREFIX)neckosystem_s.$(LIB_SUFFIX)
     endif
     
    -ifdef MOZ_DASH
    -    SHARED_LIBRARY_LIBS += \
    -        ../dash/mpd/$(LIB_PREFIX)nkdashmpd_s.$(LIB_SUFFIX)
    -endif
    -
     LOCAL_INCLUDES = \
       -I$(srcdir)/../base/src \
       -I$(srcdir)/../dns \
    diff --git a/netwerk/dash/moz.build b/netwerk/dash/moz.build
    deleted file mode 100644
    index 3202d0ff2be8..000000000000
    --- a/netwerk/dash/moz.build
    +++ /dev/null
    @@ -1,7 +0,0 @@
    -# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
    -# vim: set filetype=python:
    -# This Source Code Form is subject to the terms of the Mozilla Public
    -# License, v. 2.0. If a copy of the MPL was not distributed with this
    -# file, You can obtain one at http://mozilla.org/MPL/2.0/.
    -
    -PARALLEL_DIRS += ['mpd']
    diff --git a/netwerk/dash/mpd/AdaptationSet.cpp b/netwerk/dash/mpd/AdaptationSet.cpp
    deleted file mode 100644
    index a871e269d6da..000000000000
    --- a/netwerk/dash/mpd/AdaptationSet.cpp
    +++ /dev/null
    @@ -1,122 +0,0 @@
    -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
    -/* vim: set ts=2 et sw=2 tw=80: */
    -/*
    - * AdaptationSet.cpp
    - *****************************************************************************
    - * Copyright(C) 2010 - 2012 Klagenfurt University
    - *
    - * Created on: Jan 27, 2012
    - * Authors: Christopher Mueller 
    - *          Christian Timmerer  
    - * Contributors:
    - *          Steve Workman 
    - *
    - * This Source Code Form Is subject to the terms of the Mozilla Public
    - * License, v. 2.0. If a copy of the MPL was not distributed with this file,
    - * You can obtain one at http://mozilla.org/MPL/2.0/.
    - *****************************************************************************/
    -
    -/* DASH - Dynamic Adaptive Streaming over HTTP
    - *
    - * DASH is an adaptive bitrate streaming technology where a multimedia file is
    - * partitioned into one or more segments and delivered to a client using HTTP.
    - *
    - * |AdaptationSet|
    - *
    - * Describes a type of media in a |Period| of time in the media presentation,
    - * e.g. an audio or video stream. Direct child of |Period|, which contains 1+
    - * available pieces of media, available during that time period.
    - * |AdaptationSet| itself contains one or more |Representations| which describe
    - * different versions of the media, most commonly different bitrate encodings.
    - *
    - * Common class used by all DASH Profiles.
    - * Populated by implementation of MPD Parser.
    - * Used as data source by implementation of MPD Manager.
    - *
    - * |MPD|
    - *  --> |Period|s of time.
    - *       --> |AdaptationSet|s for each type or group of media content.
    - *            --> |Representation|s of media, encoded with different bitrates.
    - *                 --> |Segment|s of media, identified by URL (+optional byte
    - *                     range.
    - */
    -
    -#include "AdaptationSet.h"
    -
    -namespace mozilla {
    -namespace net {
    -
    -int32_t
    -AdaptationSet::GetWidth() const
    -{
    -  return mWidth;
    -}
    -
    -void
    -AdaptationSet::SetWidth(int32_t const aWidth)
    -{
    -  mWidth = aWidth;
    -}
    -
    -int32_t
    -AdaptationSet::GetHeight() const
    -{
    -  return mHeight;
    -}
    -
    -void
    -AdaptationSet::SetHeight(int32_t const aHeight)
    -{
    -  mHeight = aHeight;
    -}
    -
    -void
    -AdaptationSet::GetMIMEType(nsAString& aMIMEType) const
    -{
    -  aMIMEType = mMIMEType;
    -}
    -
    -void
    -AdaptationSet::SetMIMEType(nsAString const &aMIMEType)
    -{
    -  NS_ENSURE_FALSE_VOID(aMIMEType.IsEmpty());
    -  mMIMEType = aMIMEType;
    -}
    -
    -Representation const *
    -AdaptationSet::GetRepresentation(uint32_t aIndex) const
    -{
    -  NS_ENSURE_TRUE(aIndex < mRepresentations.Length(), nullptr);
    -  return mRepresentations[aIndex];
    -}
    -
    -void
    -AdaptationSet::AddRepresentation(Representation* aRep)
    -{
    -  NS_ENSURE_TRUE_VOID(aRep);
    -  // Only add if it's not already in the array.
    -  if (!mRepresentations.Contains(aRep)) {
    -    mRepresentations.InsertElementSorted(aRep, CompareRepresentationBitrates());
    -  }
    -}
    -
    -uint16_t
    -AdaptationSet::GetNumRepresentations() const
    -{
    -  return mRepresentations.Length();
    -}
    -
    -void
    -AdaptationSet::EnableBitstreamSwitching(bool aEnable)
    -{
    -  mIsBitstreamSwitching = aEnable;
    -}
    -
    -bool
    -AdaptationSet::IsBitstreamSwitchingEnabled() const
    -{
    -  return mIsBitstreamSwitching;
    -}
    -
    -}//namespace net
    -}//namespace mozilla
    diff --git a/netwerk/dash/mpd/AdaptationSet.h b/netwerk/dash/mpd/AdaptationSet.h
    deleted file mode 100644
    index 1067fcf08027..000000000000
    --- a/netwerk/dash/mpd/AdaptationSet.h
    +++ /dev/null
    @@ -1,107 +0,0 @@
    -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
    -/* vim: set ts=2 et sw=2 tw=80: */
    -/*
    - * AdaptationSet.h
    - *****************************************************************************
    - * Copyright(C) 2010 - 2012 Klagenfurt University
    - *
    - * Created on: Jan 27, 2012
    - * Authors: Christopher Mueller 
    - *          Christian Timmerer  
    - * Contributors:
    - *          Steve Workman 
    - *
    - * This Source Code Form Is subject to the terms of the Mozilla Public
    - * License, v. 2.0. If a copy of the MPL was not distributed with this file,
    - * You can obtain one at http://mozilla.org/MPL/2.0/.
    - *****************************************************************************/
    -
    -/* DASH - Dynamic Adaptive Streaming over HTTP
    - *
    - * DASH is an adaptive bitrate streaming technology where a multimedia file is
    - * partitioned into one or more segments and delivered to a client using HTTP.
    - *
    - * |AdaptationSet|
    - *
    - * Describes a type of media in a |Period| of time in the media presentation,
    - * e.g. an audio or video stream. Direct child of |Period|, which contains 1+
    - * available pieces of media, available during that time period.
    - * |AdaptationSet| itself contains one or more |Representations| which describe
    - * different versions of the media, most commonly different bitrate encodings.
    - *
    - * Common class used by all DASH Profiles.
    - * Populated by implementation of MPD Parser.
    - * Used as data source by implementation of MPD Manager.
    - *
    - * |MPD|
    - *  --> |Period|s of time.
    - *       --> |AdaptationSet|s for each type or group of media content.
    - *            --> |Representation|s of media, encoded with different bitrates.
    - *                 --> |Segment|s of media, identified by URL (+optional byte
    - *                     range.
    - */
    -
    -#ifndef ADAPTATIONSET_H_
    -#define ADAPTATIONSET_H_
    -
    -#include "nsAutoPtr.h"
    -#include "nsString.h"
    -#include "nsTArray.h"
    -#include "Representation.h"
    -
    -namespace mozilla {
    -namespace net {
    -
    -class AdaptationSet
    -{
    -public:
    -  AdaptationSet() :
    -    mWidth(0),
    -    mHeight(0),
    -    mIsBitstreamSwitching(false)
    -  {
    -    MOZ_COUNT_CTOR(AdaptationSet);
    -  }
    -  virtual ~AdaptationSet() {
    -    MOZ_COUNT_DTOR(AdaptationSet);
    -  }
    -
    -  // Setters and getters for @width, @height and @mimetype.
    -  int32_t  GetWidth() const;
    -  void     SetWidth(int32_t const aWidth);
    -  int32_t  GetHeight() const;
    -  void     SetHeight(int32_t const aHeight);
    -  void     GetMIMEType(nsAString& aMIMEType) const;
    -  void     SetMIMEType(nsAString const &aMIMEType);
    -
    -  // Gets a list of media |Representation| objects for this |AdaptationSet|.
    -  Representation const * GetRepresentation(uint32_t) const;
    -
    -  // Adds a media |Representation| to this |AdaptationSet|. Takes ownership to
    -  // manage deletion.
    -  void     AddRepresentation(Representation* aRep);
    -
    -  // Returns the number of media |Representations|.
    -  uint16_t GetNumRepresentations() const;
    -
    -  // En/Dis-ables switching between media |Representation|s.
    -  void EnableBitstreamSwitching(bool const aEnable);
    -  bool IsBitstreamSwitchingEnabled() const;
    -
    -private:
    -  // Array of media |Representations| to switch between.
    -  // Ordered list, ascending in order of bitrates.
    -  nsTArray >  mRepresentations;
    -
    -  // @width, height and @mimetype of this media stream.
    -  int32_t                    mWidth;
    -  int32_t                    mHeight;
    -  nsString                   mMIMEType;
    -
    -  // If true, switching between media |Representation|s is allowed.
    -  bool                       mIsBitstreamSwitching;
    -};
    -}
    -}
    -
    -#endif /* ADAPTATIONSET_H_ */
    diff --git a/netwerk/dash/mpd/IMPDManager.cpp b/netwerk/dash/mpd/IMPDManager.cpp
    deleted file mode 100644
    index ae79b5567071..000000000000
    --- a/netwerk/dash/mpd/IMPDManager.cpp
    +++ /dev/null
    @@ -1,54 +0,0 @@
    -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
    -/* vim: set ts=2 et sw=2 tw=80: */
    -/*
    - * IMPDManager.cpp
    - *****************************************************************************
    - * Copyrigh(C) 2010 - 2011 Klagenfurt University
    - *
    - * Created on: Apr 20, 2011
    - * Authors: Christopher Mueller 
    - *          Christian Timmerer  
    - * Contributors:
    - *          Steve Workman 
    - *
    - * This Source Code Form Is subject to the terms of the Mozilla Public
    - * License, v. 2.0. If a copy of the MPL was not distributed with this file,
    - * You can obtain one at http://mozilla.org/MPL/2.0/.
    - *****************************************************************************/
    -
    -#include "nsIDOMElement.h"
    -#include "IMPDManager.h"
    -#include "nsDASHWebMODManager.h"
    -#include "nsDASHWebMODParser.h"
    -
    -
    -namespace mozilla {
    -namespace net {
    -
    -/* static */
    -IMPDManager*
    -IMPDManager::Create(DASHMPDProfile aProfile, nsIDOMElement* aRoot)
    -{
    -  switch(aProfile)
    -  {
    -    case WebMOnDemand:
    -      return CreateWebMOnDemandManager(aRoot);
    -    default:
    -      return nullptr;
    -  }
    -}
    -
    -/* static */
    -IMPDManager*
    -IMPDManager::CreateWebMOnDemandManager(nsIDOMElement* aRoot)
    -{
    -  // Parse DOM elements into MPD objects.
    -  nsDASHWebMODParser parser(aRoot);
    -
    -  return new nsDASHWebMODManager(parser.Parse());
    -}
    -
    -
    -
    -}//namespace net
    -}//namespace mozilla
    diff --git a/netwerk/dash/mpd/IMPDManager.h b/netwerk/dash/mpd/IMPDManager.h
    deleted file mode 100644
    index 3b57f8921592..000000000000
    --- a/netwerk/dash/mpd/IMPDManager.h
    +++ /dev/null
    @@ -1,133 +0,0 @@
    -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
    -/* vim: set ts =2 et sw =2 tw =80: */
    -/*
    - * IMPDManager.h
    - *****************************************************************************
    - * Copyrigh(C) 2010 - 2011 Klagenfurt University
    - *
    - * Created on: Aug 10, 2010
    - * Authors: Christopher Mueller 
    - *          Christian Timmerer  
    - * Contributors:
    - *          Steve Workman 
    - *
    - * This Source Code Form Is subject to the terms of the Mozilla Public
    - * License, v. 2.0. If a copy of the MPL was not distributed with this file,
    - * You can obtain one at http://mozilla.org/MPL/2.0/.
    - *****************************************************************************/
    -
    -/* DASH - Dynamic Adaptive Streaming over HTTP.
    - *
    - * DASH is an adaptive bitrate streaming technology where a multimedia file is
    - * partitioned into one or more segments and delivered to a client using HTTP.
    - *
    - * (see DASHDecoder.cpp for info on DASH interaction with the media engine).
    - *
    - * Media Presentation Description (MPD) Manager.
    - *
    - * Interface to MPD classes, populated with data from MPD XML manifest.
    - * Employs adaptation algorithm to determine best representation of media to
    - * download.
    - *   Adaptation algorithm is separate and passed into manager.
    - *   Interface aims to be an abstracted API for all DASH MPD Profiles
    - *     (e.g. DASH WebM On Demand Profile).
    - */
    -
    -#ifndef IMPDMANAGER_H_
    -#define IMPDMANAGER_H_
    -
    -#include "nsTArray.h"
    -#include "nsIURI.h"
    -#include "nsIDOMElement.h"
    -
    -namespace mozilla {
    -namespace net {
    -
    -// DASH MPD Profile Type
    -enum DASHMPDProfile
    -{
    -  WebMOnDemand,
    -  NotValid
    -  // Extend this for other types.
    -};
    -
    -class Period;
    -class Representation;
    -class Segment;
    -
    -class IMPDManager
    -{
    -public:
    -  // Describes the media type (audio/video) of the |AdaptationSet|.
    -  enum AdaptationSetType {
    -    DASH_ASTYPE_INVALID = 0,
    -    DASH_VIDEO_STREAM,
    -    DASH_AUDIO_STREAM,
    -    DAHS_AUDIO_VIDEO_STREAM
    -  };
    -  IMPDManager()
    -  {
    -    MOZ_COUNT_CTOR(IMPDManager);
    -  }
    -
    -  virtual ~IMPDManager()
    -  {
    -    MOZ_COUNT_DTOR(IMPDManager);
    -  }
    -
    -  // Used to get the first |Period| in the presentation.
    -  virtual Period const * GetFirstPeriod() const = 0;
    -
    -  // Gets the total number of |AdaptationSet|s in the first |Period|.
    -  // Usually, this should be 2 for audio and video.
    -  // XXX Future versions may require a |Period| index.
    -  // XXX Future versions may have multiple tracks for audio.
    -  virtual uint32_t GetNumAdaptationSets() const = 0;
    -
    -  // Returns the media type for the given |AdaptationSet|, audio/video.
    -  virtual AdaptationSetType
    -          GetAdaptationSetType(uint32_t const aAdaptSetIdx) const = 0;
    -
    -  // Gets the number of media |Representation|s for the given |AdaptationSet|.
    -  // e.g how many bitrate encodings are there of the audio stream?
    -  virtual uint32_t
    -          GetNumRepresentations(uint32_t const aAdaptSetIdx) const = 0;
    -
    -  // Gets the specified |Representation| from the specified |AdaptationSet|,
    -  // e.g. get metadata about the 64Kbps encoding of the video stream.
    -  virtual Representation const *
    -          GetRepresentation(uint32_t const aAdaptSetIdx,
    -                            uint32_t const aRepIdx) const = 0;
    -
    -  // Gets the URL of the first media |Segment| for the specific media
    -  // |Representation|, e.g. the url of the first 64Kbps video segment.
    -  virtual nsresult GetFirstSegmentUrl(uint32_t const aAdaptSetIdx,
    -                                      uint32_t const aRepIdx,
    -                                      nsAString &aUrl) const = 0;
    -
    -  // Returns the start time of the presentation in seconds.
    -  virtual double GetStartTime() const = 0;
    -
    -  // Returns the duration of the presentation in seconds.
    -  virtual double GetDuration() const = 0;
    -
    -  // Gets index of the |Representation| with next highest bitrate to the
    -  // estimated bandwidth passed in. Returns true if there is at least one
    -  // |Representation| with a bitrate lower than |aBandwidth|; otherwise returns
    -  // false. Depends on |mRepresentations| being an ordered list.
    -  virtual bool GetBestRepForBandwidth(uint32_t aAdaptSetIdx,
    -                                      uint64_t aBandwidth,
    -                                      uint32_t &aRepIdx) const = 0;
    -public:
    -  // Factory method.
    -  static IMPDManager* Create(DASHMPDProfile Profile, nsIDOMElement* aRoot);
    -
    -private:
    -  // Used by factory method.
    -  static IMPDManager* CreateWebMOnDemandManager(nsIDOMElement* aRoot);
    -};
    -
    -}//namespace net
    -}//namespace mozilla
    -
    -#endif /* IMPDMANAGER_H_ */
    diff --git a/netwerk/dash/mpd/IMPDParser.h b/netwerk/dash/mpd/IMPDParser.h
    deleted file mode 100644
    index c80f1c463b32..000000000000
    --- a/netwerk/dash/mpd/IMPDParser.h
    +++ /dev/null
    @@ -1,53 +0,0 @@
    -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
    -/* vim: set ts=2 et sw=2 tw=80: */
    -/*
    - * IMPDParser.h
    - *****************************************************************************
    - * Copyrigh(C) 2010 - 2011 Klagenfurt University
    - *
    - * Created on: Aug 10, 2010
    - * Authors: Christopher Mueller 
    - *          Christian Timmerer  
    - * Contributors:
    - *          Steve Workman 
    - *
    - * This Source Code Form Is subject to the terms of the Mozilla Public
    - * License, v. 2.0. If a copy of the MPL was not distributed with this file,
    - * You can obtain one at http://mozilla.org/MPL/2.0/.
    - *****************************************************************************/
    -
    -/* DASH - Dynamic Adaptive Streaming over HTTP.
    - *
    - * DASH is an adaptive bitrate streaming technology where a multimedia file is
    - * partitioned into one or more segments and delivered to a client using HTTP.
    - *
    - * (see DASHDecoder.cpp for info on DASH interaction with the media engine).
    - *
    - * Media Presentation Description (MPD) Parser.
    - *
    - * Interface to MPD parser. Derived classes parse MPD XML manifest and populate
    - * MPD classes for use by MPD Manager.
    - * Interface aims to be an abstracted API for all DASH MPD Profiles
    - *     (e.g. DASH WebM On Demand Profile).
    - */
    -
    -#ifndef IMPDPARSER_H_
    -#define IMPDPARSER_H_
    -
    -#include "MPD.h"
    -
    -namespace mozilla {
    -namespace net {
    -
    -class IMPDParser
    -{
    -public:
    -  // Parses XML file to create and populate MPD classes.
    -  // Called by MPD Manager.
    -  virtual MPD* Parse() = 0;
    -};
    -
    -}// namespace net
    -}// namespace mozilla
    -
    -#endif /* IMPDPARSER_H_ */
    diff --git a/netwerk/dash/mpd/MPD.cpp b/netwerk/dash/mpd/MPD.cpp
    deleted file mode 100644
    index 6723da2cd615..000000000000
    --- a/netwerk/dash/mpd/MPD.cpp
    +++ /dev/null
    @@ -1,91 +0,0 @@
    -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
    -/* vim: set ts=2 et sw=2 tw=80: */
    -/*
    - * MPD.cpp
    - *****************************************************************************
    - * Copyright(C) 2010 - 2011 Klagenfurt University
    - *
    - * Created on: Aug 10, 2010
    - * Authors: Christopher Mueller 
    - *          Christian Timmerer  
    - * Contributors:
    - *          Steve Workman 
    - *
    - * This Source Code Form Is subject to the terms of the Mozilla Public
    - * License, v. 2.0. If a copy of the MPL was not distributed with this file,
    - * You can obtain one at http://mozilla.org/MPL/2.0/.
    - *****************************************************************************/
    -
    -/* DASH - Dynamic Adaptive Streaming over HTTP
    - *
    - * DASH is an adaptive bitrate streaming technology where a multimedia file is
    - * partitioned into one or more segments and delivered to a client using HTTP.
    - *
    - * |MPD| - Media Presentation Description
    - *
    - * Describes the media presentation. Top of the hierarchy in an MPD file.
    - * Contains one or a series of contiguous |Period|s, which contain 1+ available
    - * pieces of media, available during that time period, e.g. audio in various
    - * languages, a video component.
    - *
    - * Common class used by all DASH Profiles.
    - * Populated by implementation of MPD Parser.
    - * Used as data source by implementation of MPD Manager.
    - *
    - * |MPD|
    - *  --> |Period|s of time.
    - *       --> |AdaptationSet|s for each type or group of media content.
    - *            --> |Representation|s of media, encoded with different bitrates.
    - *                 --> |Segment|s of media, identified by URL (+optional byte
    - *                     range.
    - */
    -
    -#include "nsTArray.h"
    -#include "MPD.h"
    -
    -
    -namespace mozilla {
    -namespace net {
    -
    -void
    -MPD::AddPeriod(Period* aPeriod)
    -{
    -  NS_ENSURE_TRUE_VOID(aPeriod);
    -  // Only add |Period| if it's not in the array already.
    -  if (!mPeriods.Contains(aPeriod)) {
    -    mPeriods.AppendElement(aPeriod);
    -  }
    -}
    -
    -Period const *
    -MPD::GetPeriod(uint32_t aIndex) const
    -{
    -  NS_ENSURE_TRUE(aIndex < mPeriods.Length(), nullptr);
    -  return mPeriods[aIndex];
    -}
    -
    -uint32_t const
    -MPD::GetNumPeriods() const
    -{
    -  return mPeriods.Length();
    -}
    -
    -void
    -MPD::AddBaseUrl(nsAString const& aUrl)
    -{
    -  NS_ENSURE_FALSE_VOID(aUrl.IsEmpty());
    -  // Only add |BaseUrl| string if it's not in the array already.
    -  if (!mBaseUrls.Contains(aUrl)) {
    -    mBaseUrls.AppendElement(aUrl);
    -  }
    -}
    -
    -nsAString const&
    -MPD::GetBaseUrl(uint32_t aIndex) const
    -{
    -  NS_ENSURE_TRUE(aIndex < mBaseUrls.Length(), NS_LITERAL_STRING(""));
    -  return mBaseUrls[aIndex];
    -}
    -
    -}//namespace net
    -}//namespace mozilla
    diff --git a/netwerk/dash/mpd/MPD.h b/netwerk/dash/mpd/MPD.h
    deleted file mode 100644
    index f82c075e384b..000000000000
    --- a/netwerk/dash/mpd/MPD.h
    +++ /dev/null
    @@ -1,90 +0,0 @@
    -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
    -/* vim: set ts=2 et sw=2 tw=80: */
    -/*
    - * MPD.h
    - *****************************************************************************
    - * Copyright(C) 2010 - 2011 Klagenfurt University
    - *
    - * Created on: Aug 10, 2010
    - * Authors: Christopher Mueller 
    - *          Christian Timmerer  
    - * Contributors:
    - *          Steve Workman 
    - *
    - * This Source Code Form Is subject to the terms of the Mozilla Public
    - * License, v. 2.0. If a copy of the MPL was not distributed with this file,
    - * You can obtain one at http://mozilla.org/MPL/2.0/.
    - *****************************************************************************/
    -
    -/* DASH - Dynamic Adaptive Streaming over HTTP
    - *
    - * DASH is an adaptive bitrate streaming technology where a multimedia file is
    - * partitioned into one or more segments and delivered to a client using HTTP.
    - *
    - * |MPD| - Media Presentation Description
    - *
    - * Describes the media presentation. Top of the hierarchy in an MPD file.
    - * Contains one or a series of contiguous |Period|s, which contain 1+ available
    - * pieces of media, available during that time period, e.g. audio in various
    - * languages, a video component.
    - *
    - * Common class used by all DASH Profiles.
    - * Populated by implementation of MPD Parser.
    - * Used as data source by implementation of MPD Manager.
    - *
    - * |MPD|
    - *  --> |Period|s of time.
    - *       --> |AdaptationSet|s for each type or group of media content.
    - *            --> |Representation|s of media, encoded with different bitrates.
    - *                 --> |Segment|s of media, identified by URL (+optional byte
    - *                     range.
    - */
    -
    -#ifndef MPD_H_
    -#define MPD_H_
    -
    -#include "nsTArray.h"
    -#include "nsString.h"
    -#include "Period.h"
    -
    -namespace mozilla {
    -namespace net {
    -
    -class MPD
    -{
    -public:
    -  MPD()
    -  {
    -    MOZ_COUNT_CTOR(MPD);
    -  }
    -  virtual ~MPD() {
    -    MOZ_COUNT_DTOR(MPD);
    -  }
    -
    -  // At least one media content |Period|s per Media Presentation. The |MPD|
    -  // contains 1+ available pieces of media, available during that time period
    -  // e.g. audio in various languages, a video component.
    -  // |MPD| takes ownership of |Period| in |AddPeriod| and will manage deletion.
    -  void           AddPeriod(Period* aPeriod);
    -  Period const * GetPeriod(uint32_t aIndex) const;
    -  uint32_t const GetNumPeriods() const;
    -
    -  // Adds/Gets an absolute/relative |BaseURL| for the whole document.
    -  // Note: A relative |BaseURL| for the whole document will use the URL for the
    -  // MPD file itself as base.
    -  void             AddBaseUrl(nsAString const& aUrl);
    -  nsAString const& GetBaseUrl(uint32_t aIndex) const;
    -  bool             HasBaseUrls() { return !mBaseUrls.IsEmpty(); }
    -
    -private:
    -  // List of media content |Period|s in this media presentation.
    -  nsTArray > mPeriods;
    -
    -  // List of |BaseURL|s which can be used to access the media.
    -  nsTArray mBaseUrls;
    -};
    -
    -}//namespace net
    -}//namespace mozilla
    -
    -#endif /* MPD_H_ */
    diff --git a/netwerk/dash/mpd/Makefile.in b/netwerk/dash/mpd/Makefile.in
    deleted file mode 100644
    index 993b41e582cf..000000000000
    --- a/netwerk/dash/mpd/Makefile.in
    +++ /dev/null
    @@ -1,15 +0,0 @@
    -# -*- Mode: makefile; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- #
    -# vim: set ts=2 et sw=2 tw=80: #
    -#
    -# This Source Code Form is subject to the terms of the Mozilla Public
    -# License, v. 2.0. If a copy of the MPL was not distributed with this
    -# file, You can obtain one at http://mozilla.org/MPL/2.0/.
    -#
    -# Contributor(s):
    -#     Steve Workman 
    -
    -LOCAL_INCLUDES := \
    -  -I$(topsrcdir)/content/base/src \
    -  -I$(topsrcdir)/content/html/content/public \
    -  -I$(topsrcdir)/content/html/content/src \
    -  $(NULL)
    diff --git a/netwerk/dash/mpd/Period.cpp b/netwerk/dash/mpd/Period.cpp
    deleted file mode 100644
    index aed37e42f649..000000000000
    --- a/netwerk/dash/mpd/Period.cpp
    +++ /dev/null
    @@ -1,98 +0,0 @@
    -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
    -/* vim: set ts=2 et sw=2 tw=80: */
    -/*
    - * Period.cpp
    - *****************************************************************************
    - * Copyright(C) 2010 - 2011 Klagenfurt University
    - *
    - * Created on: Aug 10, 2010
    - * Authors: Christopher Mueller 
    - *          Christian Timmerer  
    - * Contributors:
    - *          Steve Workman 
    - *
    - * This Source Code Form Is subject to the terms of the Mozilla Public
    - * License, v. 2.0. If a copy of the MPL was not distributed with this file,
    - * You can obtain one at http://mozilla.org/MPL/2.0/.
    - *****************************************************************************/
    -
    -/* DASH - Dynamic Adaptive Streaming over HTTP
    - *
    - * DASH is an adaptive bitrate streaming technology where a multimedia file is
    - * partitioned into one or more segments and delivered to a client using HTTP.
    - *
    - * |Period|
    - *
    - * Describes a period of time in the media presentation. Direct child of |MPD|.
    - * Alone, or one of a series of contiguous |Period|s, which contain 1+ available
    - * pieces of media, available during that time period, e.g. audio in various
    - * languages, a video component.
    - *
    - * Common class used by all DASH Profiles.
    - * Populated by implementation of MPD Parser.
    - * Used as data source by implementation of MPD Manager.
    - *
    - * |MPD|
    - *  --> |Period|s of time.
    - *       --> |AdaptationSet|s for each type or group of media content.
    - *            --> |Representation|s of media, encoded with different bitrates.
    - *                 --> |Segment|s of media, identified by URL (+optional byte
    - *                     range.
    - */
    -
    -#include "nsAutoPtr.h"
    -#include "nsTArray.h"
    -#include "Period.h"
    -
    -namespace mozilla {
    -namespace net {
    -
    -AdaptationSet const *
    -Period::GetAdaptationSet(uint32_t aIndex) const
    -{
    -  NS_ENSURE_TRUE(aIndex < mAdaptationSets.Length(), nullptr);
    -  return mAdaptationSets[aIndex];
    -}
    -
    -void
    -Period::AddAdaptationSet(AdaptationSet* aAdaptationSet)
    -{
    -  NS_ENSURE_TRUE_VOID(aAdaptationSet);
    -  // Only add |AdaptationSet| ptr if it's not in the array already.
    -  if (!mAdaptationSets.Contains(aAdaptationSet)) {
    -    mAdaptationSets.AppendElement(aAdaptationSet);
    -  }
    -}
    -
    -uint16_t const
    -Period::GetNumAdaptationSets() const
    -{
    -  return mAdaptationSets.Length();
    -}
    -
    -double const
    -Period::GetStart() const
    -{
    -  return mStart;
    -}
    -
    -double const
    -Period::GetDuration() const
    -{
    -  return mDuration;
    -}
    -
    -void
    -Period::SetStart(double const aStart)
    -{
    -  mStart = aStart;
    -}
    -
    -void
    -Period::SetDuration(double const aDuration)
    -{
    -  mDuration = aDuration;
    -}
    -
    -}//namespace net
    -}//namespace mozilla
    diff --git a/netwerk/dash/mpd/Period.h b/netwerk/dash/mpd/Period.h
    deleted file mode 100644
    index 5f51f417533b..000000000000
    --- a/netwerk/dash/mpd/Period.h
    +++ /dev/null
    @@ -1,96 +0,0 @@
    -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
    -/* vim: set ts=2 et sw=2 tw=80: */
    -/*
    - * Period.h
    - *****************************************************************************
    - * Copyrigh(C) 2010 - 2011 Klagenfurt University
    - *
    - * Created on: Aug 10, 2010
    - * Authors: Christopher Mueller 
    - *          Christian Timmerer  
    - * Contributors:
    - *          Steve Workman 
    - *
    - * This Source Code Form Is subject to the terms of the Mozilla Public
    - * License, v. 2.0. If a copy of the MPL was not distributed with this file,
    - * You can obtain one at http://mozilla.org/MPL/2.0/.
    - *****************************************************************************/
    -#ifndef PERIOD_H_
    -#define PERIOD_H_
    -
    -#include "nsTArray.h"
    -#include "AdaptationSet.h"
    -#include "Representation.h"
    -
    -/* DASH - Dynamic Adaptive Streaming over HTTP
    - *
    - * DASH is an adaptive bitrate streaming technology where a multimedia file is
    - * partitioned into one or more segments and delivered to a client using HTTP.
    - *
    - * |Period|
    - *
    - * Describes a period of time in the media presentation. Direct child of |MPD|.
    - * Alone, or one of a series of contiguous |Period|s, which contain 1+ available
    - * pieces of media, available during that time period, e.g. audio in various
    - * languages, a video component.
    - *
    - * Common class used by all DASH Profiles.
    - * Populated by implementation of MPD Parser.
    - * Used as data source by implementation of MPD Manager.
    - *
    - * |MPD|
    - *  --> |Period|s of time.
    - *       --> |AdaptationSet|s for each type or group of media content.
    - *            --> |Representation|s of media, encoded with different bitrates.
    - *                 --> |Segment|s of media, identified by URL (+optional byte
    - *                     range.
    - */
    -
    -#include "nsAutoPtr.h"
    -
    -namespace mozilla {
    -namespace net {
    -
    -class Period
    -{
    -public:
    -  Period()
    -  {
    -    MOZ_COUNT_CTOR(Period);
    -  }
    -  virtual ~Period() {
    -    MOZ_COUNT_DTOR(Period);
    -  }
    -
    -  // Gets/Adds |AdaptationSet|s of media for this media content |Period|.
    -  AdaptationSet const * GetAdaptationSet(uint32_t aIndex) const;
    -  // |Period| takes ownership of |AdaptationSet| here and will manage deletion.
    -  void                  AddAdaptationSet(AdaptationSet* aAdaptationSet);
    -
    -  // Returns the num. of |AdaptationSet|s in this media content |Period|.
    -  uint16_t const        GetNumAdaptationSets() const;
    -
    -  // Gets/Sets the start time of this media content |Period| in seconds.
    -  double const GetStart() const;
    -  void SetStart(double const aStart);
    -
    -  // Gets/Sets the duration of this media content |Period| in seconds.
    -  double const GetDuration() const;
    -  void SetDuration(double const aDuration);
    -
    -private:
    -  // List of |AdaptationSet|s of media in this |Period|.
    -  nsTArray > mAdaptationSets;
    -
    -  // Start time in seconds for this |Period|.
    -  double mStart;
    -
    -  // Duration in seconds for this |Period|.
    -  double mDuration;
    -};
    -
    -}//namespace net
    -}//namespace mozilla
    -
    -
    -#endif /* PERIOD_H_ */
    diff --git a/netwerk/dash/mpd/Representation.cpp b/netwerk/dash/mpd/Representation.cpp
    deleted file mode 100644
    index efd3d7bbede4..000000000000
    --- a/netwerk/dash/mpd/Representation.cpp
    +++ /dev/null
    @@ -1,120 +0,0 @@
    -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
    -/* vim: set ts=2 et sw=2 tw=80: */
    -/*
    - * Representation.cpp
    - *****************************************************************************
    - * Copyrigh(C) 2010 - 2011 Klagenfurt University
    - *
    - * Created on: Aug 10, 2010
    - * Authors: Christopher Mueller 
    - *          Christian Timmerer  
    - * Contributors:
    - *          Steve Workman 
    - *
    - * This Source Code Form Is subject to the terms of the Mozilla Public
    - * License, v. 2.0. If a copy of the MPL was not distributed with this file,
    - * You can obtain one at http://mozilla.org/MPL/2.0/.
    - *****************************************************************************/
    -
    -/* DASH - Dynamic Adaptive Streaming over HTTP
    - *
    - * DASH is an adaptive bitrate streaming technology where a multimedia file is
    - * partitioned into one or more segments and delivered to a client using HTTP.
    - *
    - * |Representation|
    - *
    - * Describes a particular version of a piece of media described in an
    - * |AdaptationSet|, a common example being a particular bitrate encoding for an
    - * audio or video stream. Direct child of |AdaptationSet|, which contains 1+
    - * available |Representation|s of the media.
    - *
    - * Common class used by all DASH Profiles.
    - * Populated by implementation of MPD Parser.
    - * Used as data source by implementation of MPD Manager.
    - *
    - * |MPD|
    - *  --> |Period|s of time.
    - *       --> |AdaptationSet|s for each type or group of media content.
    - *            --> |Representation|s of media, encoded with different bitrates.
    - *                 --> |Segment|s of media, identified by URL (+optional byte
    - *                     range.
    - */
    -
    -#include "nsTArray.h"
    -#include "Representation.h"
    -
    -namespace mozilla {
    -namespace net {
    -
    -int64_t const
    -Representation::GetBitrate() const
    -{
    -  return mBitrate;
    -}
    -
    -void
    -Representation::SetBitrate(int64_t aBitrate)
    -{
    -  mBitrate = aBitrate;
    -}
    -
    -void
    -Representation::SetWidth(int32_t const aWidth)
    -{
    -  mWidth = aWidth;
    -}
    -
    -int32_t const
    -Representation::GetWidth() const
    -{
    -  return mWidth;
    -}
    -
    -void
    -Representation::SetHeight(int32_t aHeight)
    -{
    -  mHeight = aHeight;
    -}
    -
    -int32_t const
    -Representation::GetHeight() const
    -{
    -  return mHeight;
    -}
    -
    -void
    -Representation::AddBaseUrl(nsAString const& aUrl)
    -{
    -  NS_ENSURE_FALSE_VOID(aUrl.IsEmpty());
    -  // Only add if it's not already in the array.
    -  if (!mBaseUrls.Contains(aUrl)) {
    -    mBaseUrls.AppendElement(aUrl);
    -  }
    -}
    -
    -nsAString const &
    -Representation::GetBaseUrl(uint32_t aIndex) const
    -{
    -  NS_ENSURE_TRUE(aIndex < mBaseUrls.Length(), NS_LITERAL_STRING(""));
    -  return mBaseUrls[aIndex];
    -}
    -
    -SegmentBase const*
    -Representation::GetSegmentBase() const
    -{
    -  return mSegmentBase;
    -}
    -
    -void
    -Representation::SetSegmentBase(SegmentBase* aBase)
    -{
    -  NS_ENSURE_TRUE_VOID(aBase);
    -  // Don't reassign if the ptrs or contents are equal.
    -  if (mSegmentBase != aBase
    -      || (mSegmentBase && (*mSegmentBase != *aBase))) {
    -    mSegmentBase = aBase;
    -  }
    -}
    -
    -}//namespace net
    -}//namespace mozilla
    diff --git a/netwerk/dash/mpd/Representation.h b/netwerk/dash/mpd/Representation.h
    deleted file mode 100644
    index d450e2c58fe5..000000000000
    --- a/netwerk/dash/mpd/Representation.h
    +++ /dev/null
    @@ -1,137 +0,0 @@
    -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
    -/* vim: set ts=2 et sw=2 tw=80: */
    -/*
    - * Representation.h
    - *****************************************************************************
    - * Copyrigh(C) 2010 - 2011 Klagenfurt University
    - *
    - * Created on: Aug 10, 2010
    - * Authors: Christopher Mueller 
    - *          Christian Timmerer  
    - * Contributors:
    - *          Steve Workman 
    - *
    - * This Source Code Form Is subject to the terms of the Mozilla Public
    - * License, v. 2.0. If a copy of the MPL was not distributed with this file,
    - * You can obtain one at http://mozilla.org/MPL/2.0/.
    - *****************************************************************************/
    -
    -/* DASH - Dynamic Adaptive Streaming over HTTP
    - *
    - * DASH is an adaptive bitrate streaming technology where a multimedia file is
    - * partitioned into one or more segments and delivered to a client using HTTP.
    - *
    - * |Representation|
    - *
    - * Describes a particular version of a piece of media described in an
    - * |AdaptationSet|, a common example being a particular bitrate encoding for an
    - * audio or video stream. Direct child of |AdaptationSet|, which contains 1+
    - * available |Representation|s of the media.
    - *
    - * Common class used by all DASH Profiles.
    - * Populated by implementation of MPD Parser.
    - * Used as data source by implementation of MPD Manager.
    - *
    - * |MPD|
    - *  --> |Period|s of time.
    - *       --> |AdaptationSet|s for each type or group of media content.
    - *            --> |Representation|s of media, encoded with different bitrates.
    - *                 --> |Segment|s of media, identified by URL (+optional byte
    - *                     range.
    - */
    -
    -#ifndef REPRESENTATION_H_
    -#define REPRESENTATION_H_
    -
    -#include "nsAutoPtr.h"
    -#include "nsString.h"
    -#include "nsTArray.h"
    -#include "SegmentBase.h"
    -
    -namespace mozilla {
    -namespace net {
    -
    -class Representation
    -{
    -public:
    -  Representation() :
    -    mBitrate(0),
    -    mWidth(0),
    -    mHeight(0),
    -    mSegmentBase(nullptr)
    -  {
    -    MOZ_COUNT_CTOR(Representation);
    -  }
    -  virtual ~Representation() {
    -    MOZ_COUNT_DTOR(Representation);
    -  }
    -
    -  bool operator<(const Representation &other) const {
    -    return this->mBitrate < other.mBitrate;
    -  }
    -
    -  // Gets/Sets @bitrate in kbps.
    -  int64_t const    GetBitrate() const;
    -  void             SetBitrate(int64_t const aBitrate);
    -
    -  // Gets/Sets @width and @height for the media if it's video.
    -  void             SetWidth(int32_t const aWidth);
    -  int32_t const    GetWidth() const;
    -  void             SetHeight(int32_t const aHeight);
    -  int32_t const    GetHeight() const;
    -
    -  // Gets/Adds a |BaseURL| for the media files.
    -  void             AddBaseUrl(nsAString const& aUrl);
    -  nsAString const& GetBaseUrl(uint32_t aIndex) const;
    -  bool             HasBaseUrls() const { return !mBaseUrls.IsEmpty(); }
    -
    -  // Gets/Sets a base |Segment| for the |Representation|.
    -  SegmentBase const* GetSegmentBase() const;
    -  // Takes ownership of |SegmentBase| to manage deletion.
    -  void               SetSegmentBase(SegmentBase* aBase);
    -
    -private:
    -  // Bitrate of the media in kbps.
    -  int64_t mBitrate;
    -
    -  // Width and height of the media if video.
    -  int32_t mWidth;
    -  int32_t mHeight;
    -
    -  // List of absolute/relative |BaseURL|s which may be used to access the media.
    -  nsTArray mBaseUrls;
    -
    -  // The base |Segment| for the |Representation|.
    -  nsAutoPtr mSegmentBase;
    -};
    -
    -// Comparator allows comparing |Representation|s based on media stream bitrate.
    -class CompareRepresentationBitrates
    -{
    -public:
    -  // Returns true if the elements are equals; false otherwise.
    -  // Note: |Representation| is stored as an array of |nsAutoPtr| in
    -  // |AdaptationSet|, but needs to be compared to regular pointers.
    -  // Hence the left hand side of the function being an
    -  // |nsAutoPtr| and the right being a regular pointer.
    -  bool Equals(const nsAutoPtr& a,
    -              const Representation *b) const {
    -    return a == b;
    -  }
    -
    -  // Returns true if (a < b); false otherwise.
    -  // Note: |Representation| is stored as an array of |nsAutoPtr| in
    -  // |AdaptationSet|, but needs to be compared to regular pointers.
    -  // Hence the left hand side of the function being an
    -  // |nsAutoPtr| and the right being a regular pointer.
    -  bool LessThan(const nsAutoPtr& a,
    -                const Representation *b) const {
    -    return *a < *b;
    -  }
    -};
    -
    -}//namespace net
    -}//namespace mozilla
    -
    -
    -#endif /* REPRESENTATION_H_ */
    diff --git a/netwerk/dash/mpd/SegmentBase.cpp b/netwerk/dash/mpd/SegmentBase.cpp
    deleted file mode 100644
    index 12baf6eced5a..000000000000
    --- a/netwerk/dash/mpd/SegmentBase.cpp
    +++ /dev/null
    @@ -1,106 +0,0 @@
    -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
    -/* vim: set ts=2 et sw=2 tw=80: */
    -/*
    - * SegmentBase.cpp
    - *****************************************************************************
    - * Copyrigh(C) 2010 - 2012 Klagenfurt University
    - *
    - * Created on: Jan 27, 2012
    - * Authors: Christopher Mueller 
    - *          Christian Timmerer  
    - * Contributors:
    - *          Steve Workman 
    -
    - *
    - * This Source Code Form Is subject to the terms of the Mozilla Public
    - * License, v. 2.0. If a copy of the MPL was not distributed with this file,
    - * You can obtain one at http://mozilla.org/MPL/2.0/.
    - *****************************************************************************/
    -
    -/* DASH - Dynamic Adaptive Streaming over HTTP
    - *
    - * DASH is an adaptive bitrate streaming technology where a multimedia file is
    - * partitioned into one or more segments and delivered to a client using HTTP.
    - *
    - * |SegmentBase|
    - *
    - * Describes common initialization information for |Segment|s in a
    - * |Representation|.
    - *
    - * Common class used by all DASH Profiles.
    - * Populated by implementation of MPD Parser.
    - * Used as data source by implementation of MPD Manager.
    - *
    - * |MPD|
    - *  --> |Period|s of time.
    - *       --> |AdaptationSet|s for each type or group of media content.
    - *            --> |Representation|s of media, encoded with different bitrates.
    - *                 --> |Segment|s of media, identified by URL (+optional byte
    - *                     range.
    - */
    -
    -#include "nsString.h"
    -#include "SegmentBase.h"
    -
    -
    -namespace mozilla {
    -namespace net {
    -
    -void
    -SegmentBase::GetIndexRange(int64_t* aStartBytes, int64_t* aEndBytes) const
    -{
    -  NS_ENSURE_TRUE_VOID(aStartBytes);
    -  NS_ENSURE_TRUE_VOID(aEndBytes);
    -  *aStartBytes = mIndexRangeStart;
    -  *aEndBytes = mIndexRangeEnd;
    -}
    -
    -void
    -SegmentBase::GetInitRange(int64_t* aStartBytes, int64_t* aEndBytes) const
    -{
    -  NS_ENSURE_TRUE_VOID(aStartBytes);
    -  NS_ENSURE_TRUE_VOID(aEndBytes);
    -  *aStartBytes = mInitRangeStart;
    -  *aEndBytes = mInitRangeEnd;
    -}
    -
    -void
    -SegmentBase::SetIndexRange(nsAString const &aRangeStr)
    -{
    -  SetRange(aRangeStr, mIndexRangeStart, mIndexRangeEnd);
    -}
    -
    -void
    -SegmentBase::SetInitRange(nsAString const &aRangeStr)
    -{
    -  SetRange(aRangeStr, mInitRangeStart, mInitRangeEnd);
    -}
    -
    -void
    -SegmentBase::SetRange(nsAString const &aRangeStr,
    -                      int64_t &aStart,
    -                      int64_t &aEnd)
    -{
    -  NS_ENSURE_TRUE_VOID(!aRangeStr.IsEmpty());
    -
    -  nsAString::const_iterator start, end, dashStart, dashEnd;
    -
    -  aRangeStr.BeginReading(start);
    -  aRangeStr.EndReading(end);
    -  dashStart = start;
    -  dashEnd = end;
    -
    -  if (FindInReadable(NS_LITERAL_STRING("-"), dashStart, dashEnd)) {
    -    nsAutoString temp(Substring(start, dashStart));
    -    nsresult rv;
    -    aStart = temp.ToInteger64(&rv);
    -    NS_ENSURE_SUCCESS_VOID(rv);
    -
    -    temp = Substring(dashEnd, end);
    -    aEnd = temp.ToInteger64(&rv);
    -    NS_ENSURE_SUCCESS_VOID(rv);
    -  }
    -}
    -
    -}//namespace net
    -}//namespace mozilla
    diff --git a/netwerk/dash/mpd/SegmentBase.h b/netwerk/dash/mpd/SegmentBase.h
    deleted file mode 100644
    index 7d7ceb12c85b..000000000000
    --- a/netwerk/dash/mpd/SegmentBase.h
    +++ /dev/null
    @@ -1,100 +0,0 @@
    -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
    -/* vim: set ts=2 et sw=2 tw=80: */
    -/*
    - * SegmentBase.h
    - *****************************************************************************
    - * Copyrigh(C) 2010 - 2012 Klagenfurt University
    - *
    - * Created on: Jan 27, 2012
    - * Authors: Christopher Mueller 
    - *          Christian Timmerer  
    - * Contributors:
    - *          Steve Workman 
    - *
    - * This Source Code Form Is subject to the terms of the Mozilla Public
    - * License, v. 2.0. If a copy of the MPL was not distributed with this file,
    - * You can obtain one at http://mozilla.org/MPL/2.0/.
    - *****************************************************************************/
    -
    -/* DASH - Dynamic Adaptive Streaming over HTTP
    - *
    - * DASH is an adaptive bitrate streaming technology where a multimedia file is
    - * partitioned into one or more segments and delivered to a client using HTTP.
    - *
    - * |SegmentBase|
    - *
    - * Describes common initialization information for |Segment|s in a
    - * |Representation|.
    - *
    - * Common class used by all DASH Profiles.
    - * Populated by implementation of MPD Parser.
    - * Used as data source by implementation of MPD Manager.
    - *
    - * |MPD|
    - *  --> |Period|s of time.
    - *       --> |AdaptationSet|s for each type or group of media content.
    - *            --> |Representation|s of media, encoded with different bitrates.
    - *                 --> |Segment|s of media, identified by URL (+optional byte
    - *                     range.
    - */
    -
    -#ifndef SEGMENTBASE_H_
    -#define SEGMENTBASE_H_
    -
    -#include "nsString.h"
    -
    -namespace mozilla {
    -namespace net {
    -
    -class SegmentBase
    -{
    -public:
    -  SegmentBase() :
    -    mInitRangeStart(0),
    -    mInitRangeEnd(0),
    -    mIndexRangeStart(0),
    -    mIndexRangeEnd(0)
    -  {
    -    MOZ_COUNT_CTOR(SegmentBase);
    -  }
    -  virtual ~SegmentBase()
    -  {
    -    MOZ_COUNT_DTOR(SegmentBase);
    -  }
    -
    -  bool operator==(SegmentBase const & other) const {
    -    return (mInitRangeStart == other.mInitRangeStart
    -            && mInitRangeEnd == other.mInitRangeEnd
    -            && mIndexRangeStart == other.mIndexRangeStart
    -            && mIndexRangeEnd == other.mIndexRangeEnd);
    -  }
    -  bool operator!=(SegmentBase const & other) const {
    -    return !(*this == other);
    -  }
    -
    -  // Get/Set the byte range for the initialization bytes.
    -  void GetInitRange(int64_t* aStartBytes, int64_t* aEndBytes) const;
    -  void SetInitRange(nsAString const &aRangeStr);
    -
    -  // Get/Set the byte range for the index bytes.
    -  void GetIndexRange(int64_t* aStartBytes, int64_t* aEndBytes) const;
    -  void SetIndexRange(nsAString const &aRangeStr);
    -
    -private:
    -  // Parses the string to get a start and end value.
    -  void SetRange(nsAString const &aRangeStr, int64_t &aStart, int64_t &aEnd);
    -
    -  // Start and end values for the init byte range.
    -  int64_t mInitRangeStart;
    -  int64_t mInitRangeEnd;
    -
    -  // Start and end values for the index byte range.
    -  int64_t mIndexRangeStart;
    -  int64_t mIndexRangeEnd;
    -};
    -
    -
    -}//namespace net
    -}//namespace mozilla
    -
    -#endif /* SEGMENTBASE_H_ */
    diff --git a/netwerk/dash/mpd/moz.build b/netwerk/dash/mpd/moz.build
    deleted file mode 100644
    index fd0eea98a886..000000000000
    --- a/netwerk/dash/mpd/moz.build
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
    -# vim: set filetype=python:
    -# This Source Code Form is subject to the terms of the Mozilla Public
    -# License, v. 2.0. If a copy of the MPL was not distributed with this
    -# file, You can obtain one at http://mozilla.org/MPL/2.0/.
    -
    -MODULE = 'necko'
    -
    -SOURCES += [
    -    'AdaptationSet.cpp',
    -    'IMPDManager.cpp',
    -    'MPD.cpp',
    -    'nsDASHMPDParser.cpp',
    -    'nsDASHWebMODManager.cpp',
    -    'nsDASHWebMODParser.cpp',
    -    'Period.cpp',
    -    'Representation.cpp',
    -    'SegmentBase.cpp',
    -]
    -
    -LIBRARY_NAME = 'nkdashmpd_s'
    -
    -LIBXUL_LIBRARY = True
    -
    diff --git a/netwerk/dash/mpd/nsDASHMPDParser.cpp b/netwerk/dash/mpd/nsDASHMPDParser.cpp
    deleted file mode 100644
    index 46d9ccde0275..000000000000
    --- a/netwerk/dash/mpd/nsDASHMPDParser.cpp
    +++ /dev/null
    @@ -1,219 +0,0 @@
    -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
    -/* vim: set ts=2 et sw=2 tw=80: */
    -/*
    - * nsDASHMPDParser.cpp
    - *****************************************************************************
    - * Copyrigh(C) 2010 - 2011 Klagenfurt University
    - *
    - * Created on: Aug 10, 2010
    - * Authors: Christopher Mueller 
    - *          Christian Timmerer  
    - * Contributors:
    - *          Steve Workman 
    - *
    - * This Source Code Form Is subject to the terms of the Mozilla Public
    - * License, v. 2.0. If a copy of the MPL was not distributed with this file,
    - * You can obtain one at http://mozilla.org/MPL/2.0/.
    - *****************************************************************************/
    -
    -/* DASH - Dynamic Adaptive Streaming over HTTP.
    - *
    - * DASH is an adaptive bitrate streaming technology where a multimedia file is
    - * partitioned into one or more segments and delivered to a client using HTTP.
    - *
    - * see DASHDecoder.cpp for info on DASH interaction with the media engine.
    - */
    -
    -#include "prlog.h"
    -#include "nsNetUtil.h"
    -#include "nsIDOMAttr.h"
    -#include "nsIDOMDocument.h"
    -#include "nsIDOMElement.h"
    -#include "nsIDOMParser.h"
    -#include "nsIDOMMozNamedAttrMap.h"
    -#include "nsIDOMNode.h"
    -#include "nsString.h"
    -#include "IMPDManager.h"
    -#include "nsDASHMPDParser.h"
    -
    -#if defined(PR_LOGGING)
    -static PRLogModuleInfo* gDASHMPDParserLog = nullptr;
    -#define LOG(msg, ...) PR_LOG(gDASHMPDParserLog, PR_LOG_DEBUG, \
    -                             ("%p [nsDASHMPDParser] " msg, this, __VA_ARGS__))
    -#define LOG1(msg) PR_LOG(gDASHMPDParserLog, PR_LOG_DEBUG, \
    -                         ("%p [nsDASHMPDParser] " msg, this))
    -#else
    -#define LOG(msg, ...)
    -#define LOG1(msg)
    -#endif
    -
    -namespace mozilla {
    -namespace net {
    -
    -nsDASHMPDParser::nsDASHMPDParser(char*         aMPDData,
    -                                 uint32_t      aDataLength,
    -                                 nsIPrincipal* aPrincipal,
    -                                 nsIURI*       aURI) :
    -  mData(aMPDData),
    -  mDataLength(aDataLength),
    -  mPrincipal(aPrincipal),
    -  mURI(aURI)
    -{
    -  MOZ_COUNT_CTOR(nsDASHMPDParser);
    -#if defined(PR_LOGGING)
    -  if(!gDASHMPDParserLog)
    -    gDASHMPDParserLog = PR_NewLogModule("nsDASHMPDParser");
    -#endif
    -}
    -
    -nsDASHMPDParser::~nsDASHMPDParser()
    -{
    -  MOZ_COUNT_DTOR(nsDASHMPDParser);
    -}
    -
    -
    -nsresult
    -nsDASHMPDParser::Parse(IMPDManager**    aMPDManager,
    -                       DASHMPDProfile*  aProfile)
    -{
    -  NS_ENSURE_ARG(aMPDManager);
    -  NS_ENSURE_ARG(aProfile);
    -  NS_ENSURE_TRUE(mData, NS_ERROR_NOT_INITIALIZED);
    -  NS_ENSURE_TRUE(mPrincipal, NS_ERROR_NOT_INITIALIZED);
    -  NS_ENSURE_TRUE(mURI, NS_ERROR_NOT_INITIALIZED);
    -
    -#ifdef PR_LOGGING
    -  {
    -    nsAutoCString spec;
    -    nsresult rv = mURI->GetSpec(spec);
    -    if (NS_FAILED(rv)) {
    -      LOG1("Preparing to parse MPD: cannot get spec from URI");
    -    } else {
    -      LOG("Preparing to parse MPD: mURI:\"%s\"", spec.get());
    -    }
    -  }
    -#endif
    -
    -  // Get mDoc element from mData buffer using DOMParser.
    -  nsCOMPtr DOMParser;
    -  DOMParser = do_CreateInstance(NS_DOMPARSER_CONTRACTID);
    -  nsresult rv = DOMParser->Init(mPrincipal, mURI, nullptr, nullptr);
    -  NS_ENSURE_SUCCESS(rv, rv);
    -
    -  nsCOMPtr doc;
    -  rv = DOMParser->ParseFromBuffer(reinterpret_cast(mData.get()),
    -                                  mDataLength,
    -                                  "application/xml",
    -                                  getter_AddRefs(doc));
    -  NS_ENSURE_SUCCESS(rv, rv);
    -  if(!doc) {
    -    LOG1("ERROR! Document not parsed as XML!");
    -    return NS_ERROR_NO_INTERFACE;
    -  }
    -  // Use root node to create MPD manager.
    -  nsCOMPtr root;
    -  rv = doc->GetDocumentElement(getter_AddRefs(root));
    -  NS_ENSURE_SUCCESS(rv, rv);
    -  NS_ENSURE_TRUE(root, NS_ERROR_NULL_POINTER);
    -#ifdef PR_LOGGING
    -  PrintDOMElements(root);
    -#endif
    -  rv = GetProfile(root, *aProfile);
    -  NS_ENSURE_SUCCESS(rv, rv);
    -  *aMPDManager = IMPDManager::Create(*aProfile, root);
    -  NS_ENSURE_TRUE(*aMPDManager, NS_ERROR_NULL_POINTER);
    -
    -  // Get profile.
    -  return rv;
    -}
    -
    -void
    -nsDASHMPDParser::PrintDOMElement(nsIDOMElement* aElem, int32_t offset)
    -{
    -  // Populate string ss and then print to LOG().
    -  nsAutoString ss;
    -  // Indent.
    -  for(int32_t i = 0; i < offset; i++)
    -    ss.Append(NS_LITERAL_STRING(" "));
    -  // Tag name.
    -  nsAutoString tagName;
    -  NS_ENSURE_SUCCESS_VOID(aElem->GetTagName(tagName));
    -  ss += NS_LITERAL_STRING("<");
    -  ss += tagName;
    -
    -  // Attributes.
    -  nsCOMPtr attributes;
    -  NS_ENSURE_SUCCESS_VOID(aElem->GetAttributes(getter_AddRefs(attributes)));
    -
    -  uint32_t count;
    -  NS_ENSURE_SUCCESS_VOID(attributes->GetLength(&count));
    -
    -  for(uint32_t i = 0; i < count; i++)
    -  {
    -    ss += NS_LITERAL_STRING(" ");
    -    nsCOMPtr attr;
    -    NS_ENSURE_SUCCESS_VOID(attributes->Item(i, getter_AddRefs(attr)));
    -
    -    nsAutoString name;
    -    NS_ENSURE_SUCCESS_VOID(attr->GetName(name));
    -    ss += name;
    -
    -    nsAutoString value;
    -    NS_ENSURE_SUCCESS_VOID(attr->GetValue(value));
    -    if (!value.IsEmpty()) {
    -      ss += NS_LITERAL_STRING("=");
    -      ss += value;
    -    }
    -  }
    -  ss += NS_LITERAL_STRING(">");
    -  LOG("%s", NS_ConvertUTF16toUTF8(ss).get());
    -
    -  offset++;
    -
    -  // Print for each child.
    -  nsCOMPtr child;
    -  NS_ENSURE_SUCCESS_VOID(aElem->GetFirstElementChild(getter_AddRefs(child)));
    -
    -  while(child)
    -  {
    -    PrintDOMElement(child, offset);
    -    NS_ENSURE_SUCCESS_VOID(child->GetNextElementSibling(getter_AddRefs(child)));
    -  }
    -}
    -
    -
    -void
    -nsDASHMPDParser::PrintDOMElements(nsIDOMElement* aRoot)
    -{
    -  NS_ENSURE_TRUE_VOID(aRoot);
    -
    -  DASHMPDProfile profile;
    -  NS_ENSURE_SUCCESS_VOID(GetProfile(aRoot, profile));
    -  LOG("Profile Is %d",(int32_t)profile);
    -  PrintDOMElement(aRoot, 0);
    -}
    -
    -
    -nsresult
    -nsDASHMPDParser::GetProfile(nsIDOMElement* aRoot,
    -                            DASHMPDProfile &aProfile)
    -{
    -  NS_ENSURE_ARG(aRoot);
    -
    -  nsAutoString profileStr;
    -  nsresult rv = aRoot->GetAttribute(NS_LITERAL_STRING("profiles"), profileStr);
    -  LOG("profileStr: %s", NS_ConvertUTF16toUTF8(profileStr).get());
    -  NS_ENSURE_SUCCESS(rv, rv);
    -
    -  if (profileStr
    -      == NS_LITERAL_STRING("urn:webm:dash:profile:webm-on-demand:2012")) {
    -    aProfile = WebMOnDemand;
    -  } else {
    -    aProfile = NotValid;
    -  }
    -  return NS_OK;
    -}
    -
    -
    -}// namespace net
    -}// namespace mozilla
    diff --git a/netwerk/dash/mpd/nsDASHMPDParser.h b/netwerk/dash/mpd/nsDASHMPDParser.h
    deleted file mode 100644
    index e857ee820dbb..000000000000
    --- a/netwerk/dash/mpd/nsDASHMPDParser.h
    +++ /dev/null
    @@ -1,78 +0,0 @@
    -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
    -/* vim: set ts=2 et sw=2 tw=80: */
    -/*
    - * nsDASHMPDParser.h
    - *****************************************************************************
    - * Copyright(C) 2010 - 2011 Klagenfurt University
    - *
    - * Created on: Aug 10, 2010
    - * Authors: Christopher Mueller 
    - *          Christian Timmerer  
    - * Contributors:
    - *          Steve Workman 
    - *
    - * This Source Code Form Is subject to the terms of the Mozilla Public
    - * License, v. 2.0. If a copy of the MPL was not distributed with this file,
    - * You can obtain one at http://mozilla.org/MPL/2.0/.
    - *****************************************************************************/
    -
    -/* DASH - Dynamic Adaptive Streaming over HTTP.
    - *
    - * DASH is an adaptive bitrate streaming technology where a multimedia file is
    - * partitioned into one or more segments and delivered to a client using HTTP.
    - *
    - * see DASHDecoder.cpp for info on DASH interaction with the media engine.
    - */
    -
    -#ifndef __DASHMPDPARSER_H__
    -#define __DASHMPDPARSER_H__
    -
    -#include "nsAutoPtr.h"
    -#include "nsNetUtil.h"
    -#include "nsIPrincipal.h"
    -#include "nsIDOMElement.h"
    -#include "IMPDManager.h"
    -
    -namespace mozilla {
    -namespace net {
    -
    -class nsDASHMPDParser
    -{
    -public:
    -  // Constructor takes pointer to MPD byte stream and length, as well as the
    -  // current principal and URI from which the MPD download took place.
    -  // Ownership of |aMPDData| should be transferred to this object.
    -  nsDASHMPDParser(char*         aMPDData,
    -                  uint32_t      aDataLength,
    -                  nsIPrincipal* aPrincipal,
    -                  nsIURI*       aURI);
    - 
    -  ~nsDASHMPDParser();
    -
    -  // Parses the MPD byte stream passed in the constructor.
    -  // Returns a pointer to the MPDManager and the MPD profile type.
    -  nsresult  Parse(IMPDManager**   aMPDManager,
    -                  DASHMPDProfile* aProfile);
    -private:
    -  // Returns the MPD profile type given the DOM node for the root.
    -  nsresult  GetProfile(nsIDOMElement* aRoot,
    -                       DASHMPDProfile &profile);
    -  // Debug: Prints the DOM elements.
    -  void      PrintDOMElements(nsIDOMElement* aRoot);
    -  // Debug: Prints a single DOM element.
    -  void      PrintDOMElement(nsIDOMElement* aElem, int32_t aOffset);
    -
    -  // Pointer to the MPD byte stream.
    -  nsAutoPtr   mData;
    -  // Length in bytes of the MPD stream.
    -  uint32_t                mDataLength;
    -  // Principal of the document.
    -  nsCOMPtr  mPrincipal;
    -  // URI of the MPD Document downloaded.
    -  nsCOMPtr        mURI;
    -};
    -
    -}//namespace net
    -}//namespace mozilla
    -
    -#endif /* __DASHMPDPARSER_H__ */
    diff --git a/netwerk/dash/mpd/nsDASHWebMODManager.cpp b/netwerk/dash/mpd/nsDASHWebMODManager.cpp
    deleted file mode 100644
    index 2c337e0f965e..000000000000
    --- a/netwerk/dash/mpd/nsDASHWebMODManager.cpp
    +++ /dev/null
    @@ -1,236 +0,0 @@
    -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
    -/* vim: set ts=2 et sw=2 tw=80: */
    -/*
    - * nsDASHWebMODManager.cpp
    - *****************************************************************************
    - * Copyrigh(C) 2010 - 2012 Klagenfurt University
    - *
    - * Created on: May 1, 2012
    - * Based on IsoffMainManager.cpp by:
    - *          Christopher Mueller 
    - *          Christian Timmerer  
    - * Author:
    - *          Steve Workman 
    - *
    - * This Source Code Form Is subject to the terms of the Mozilla Public
    - * License, v. 2.0. If a copy of the MPL was not distributed with this file,
    - * You can obtain one at http://mozilla.org/MPL/2.0/.
    - *****************************************************************************/
    -
    -/* DASH - Dynamic Adaptive Streaming over HTTP.
    - *
    - * DASH is an adaptive bitrate streaming technology where a multimedia file is
    - * partitioned into one or more segments and delivered to a client using HTTP.
    - *
    - * (see DASHDecoder.cpp for info on DASH interaction with the media engine).
    - *
    - * Media Presentation Description (MPD) Manager for WebM On Demand Profile.
    - *
    - * Implements MPD Manager interface to use Adaptation Algorithm to determine
    - * which stream to download from WebM On Demand-based MPD.
    - *
    - *   Note: Adaptation algorithm is separate and passed into manager.
    - */
    -
    -#include "nsTArray.h"
    -#include "nsMimeTypes.h"
    -#include "nsNetUtil.h"
    -#include "prlog.h"
    -#include "SegmentBase.h"
    -#include "nsDASHWebMODManager.h"
    -
    -namespace mozilla {
    -namespace net {
    -
    -#if defined(PR_LOGGING)
    -static PRLogModuleInfo* gnsDASHWebMODManagerLog = nullptr;
    -#define LOG(msg, ...) \
    -        PR_LOG(gnsDASHWebMODManagerLog, PR_LOG_DEBUG, \
    -               ("%p [nsDASHWebMODManager] " msg, this, __VA_ARGS__))
    -#define LOG1(msg) PR_LOG(gDASHMPDParserLog, PR_LOG_DEBUG, \
    -                         ("%p [nsDASHWebMODManager] " msg, this))
    -#else
    -#define LOG(msg, ...)
    -#define LOG1(msg)
    -#endif
    -
    -nsDASHWebMODManager::nsDASHWebMODManager(MPD* aMpd)
    -{
    -  MOZ_COUNT_CTOR(nsDASHWebMODManager);
    -  NS_ENSURE_TRUE_VOID(aMpd);
    -  mMpd = aMpd;
    -#if defined(PR_LOGGING)
    -  if(!gnsDASHWebMODManagerLog)
    -    gnsDASHWebMODManagerLog = PR_NewLogModule("nsDASHWebMODManager");
    -#endif
    -  LOG("Created nsDASHWebMODManager with mMpd(%p)", mMpd.get());
    -}
    -
    -nsDASHWebMODManager::~nsDASHWebMODManager()
    -{
    -  MOZ_COUNT_DTOR(nsDASHWebMODManager);
    -}
    -
    -
    -Period const *
    -nsDASHWebMODManager::GetFirstPeriod() const
    -{
    -  NS_ENSURE_TRUE(mMpd, nullptr);
    -  NS_ENSURE_TRUE(0 < mMpd->GetNumPeriods(), nullptr);
    -  return mMpd->GetPeriod(0);
    -}
    -
    -nsresult
    -nsDASHWebMODManager::GetFirstSegmentUrl(uint32_t const aAdaptSetIdx,
    -                                        uint32_t const aRepIdx,
    -                                        nsAString &aUrl) const
    -{
    -  NS_ENSURE_TRUE(mMpd, NS_ERROR_NULL_POINTER);
    -  // Append base URL for MPD.
    -  if (mMpd->HasBaseUrls()) {
    -    aUrl.Append(mMpd->GetBaseUrl(0));
    -    LOG("BaseUrl \"%s\"", NS_ConvertUTF16toUTF8(aUrl).get());
    -  }
    -
    -  // Append base URL for Representation.
    -  AdaptationSet const * adaptSet = GetAdaptationSet(aAdaptSetIdx);
    -  NS_ENSURE_TRUE(adaptSet, NS_ERROR_NULL_POINTER);
    -
    -  NS_ENSURE_TRUE(aRepIdx < adaptSet->GetNumRepresentations(),
    -                 NS_ERROR_ILLEGAL_VALUE);
    -  Representation const * rep = adaptSet->GetRepresentation(aRepIdx);
    -  NS_ENSURE_TRUE(rep, NS_ERROR_NULL_POINTER);
    -
    -  if (rep->HasBaseUrls()) {
    -    aUrl.Append(rep->GetBaseUrl(0));
    -    LOG("Appending \"%s\"",
    -        NS_ConvertUTF16toUTF8(rep->GetBaseUrl(0)).get());
    -  }
    -
    -  return NS_OK;
    -}
    -
    -uint32_t
    -nsDASHWebMODManager::GetNumAdaptationSets() const
    -{
    -  Period const * current = GetFirstPeriod();
    -  return current ? current->GetNumAdaptationSets() : 0;
    -}
    -
    -IMPDManager::AdaptationSetType
    -nsDASHWebMODManager::GetAdaptationSetType(uint32_t const aAdaptSetIdx) const
    -{
    -  AdaptationSet const * adaptSet = GetAdaptationSet(aAdaptSetIdx);
    -  NS_ENSURE_TRUE(adaptSet, DASH_ASTYPE_INVALID);
    -
    -  nsAutoString mimeType;
    -  adaptSet->GetMIMEType(mimeType);
    -  NS_ENSURE_TRUE(!mimeType.IsEmpty(), DASH_ASTYPE_INVALID);
    -
    -  return GetAdaptationSetType(mimeType);
    -}
    -
    -IMPDManager::AdaptationSetType
    -nsDASHWebMODManager::GetAdaptationSetType(nsAString const & aMimeType) const
    -{
    -  NS_ENSURE_TRUE(!aMimeType.IsEmpty(), DASH_ASTYPE_INVALID);
    -
    -  if (aMimeType == NS_LITERAL_STRING(VIDEO_WEBM)) {
    -    return DASH_VIDEO_STREAM;
    -  } else if (aMimeType == NS_LITERAL_STRING(AUDIO_WEBM)) {
    -    return DASH_AUDIO_STREAM;
    -  } else {
    -    return DASH_ASTYPE_INVALID;
    -  }
    -}
    -
    -uint32_t
    -nsDASHWebMODManager::GetNumRepresentations(uint32_t const aAdaptSetIdx) const
    -{
    -  AdaptationSet const * adaptSet = GetAdaptationSet(aAdaptSetIdx);
    -  NS_ENSURE_TRUE(adaptSet, DASH_ASTYPE_INVALID);
    -
    -  return adaptSet->GetNumRepresentations();
    -}
    -
    -AdaptationSet const *
    -nsDASHWebMODManager::GetAdaptationSet(uint32_t const aAdaptSetIdx) const
    -{
    -  Period const * current = GetFirstPeriod();
    -  NS_ENSURE_TRUE(current, nullptr);
    -
    -  NS_ENSURE_TRUE(0 < current->GetNumAdaptationSets(), nullptr);
    -  NS_ENSURE_TRUE(aAdaptSetIdx < current->GetNumAdaptationSets(), nullptr);
    -  AdaptationSet const * adaptSet = current->GetAdaptationSet(aAdaptSetIdx);
    -  NS_ENSURE_TRUE(adaptSet, nullptr);
    -  return adaptSet;
    -}
    -
    -Representation const *
    -nsDASHWebMODManager::GetRepresentation(uint32_t const aAdaptSetIdx,
    -                                       uint32_t const aRepIdx) const
    -{
    -  AdaptationSet const * adaptSet = GetAdaptationSet(aAdaptSetIdx);
    -  NS_ENSURE_TRUE(adaptSet, nullptr);
    -
    -  NS_ENSURE_TRUE(aRepIdx < adaptSet->GetNumRepresentations(), nullptr);
    -  Representation const * rep = adaptSet->GetRepresentation(aRepIdx);
    -  NS_ENSURE_TRUE(rep, nullptr);
    -
    -  return rep;
    -}
    -
    -double
    -nsDASHWebMODManager::GetStartTime() const
    -{
    -  Period const * current = GetFirstPeriod();
    -  NS_ENSURE_TRUE(current, -1);
    -
    -  return current->GetStart();
    -}
    -
    -double
    -nsDASHWebMODManager::GetDuration() const
    -{
    -  Period const * current = GetFirstPeriod();
    -  NS_ENSURE_TRUE(current, -1);
    -
    -  return current->GetDuration();
    -}
    -
    -bool
    -nsDASHWebMODManager::GetBestRepForBandwidth(uint32_t aAdaptSetIdx,
    -                                            uint64_t aBandwidth,
    -                                            uint32_t &aRepIdx) const
    -{
    -  NS_ENSURE_TRUE(aAdaptSetIdx < GetNumAdaptationSets(), false);
    -  NS_ENSURE_TRUE(0 < GetNumRepresentations(aAdaptSetIdx), false);
    -  // Return false if there isn't enough bandwidth for even the lowest bitrate.
    -  // Let calling function decide what to do. Use 0.95 multiplier to deal with
    -  // 5% variance in bandwidth.
    -  // XXX Multiplier is a guess at present.
    -  if (aBandwidth*0.95 < GetRepresentation(aAdaptSetIdx, 0)->GetBitrate()) {
    -    aRepIdx = UINT32_MAX;
    -    return false;
    -  }
    -  // Iterate until the current |Representation|'s bitrate is higher than the
    -  // estimated available bandwidth. Use 0.95 multiplier to deal with 5%
    -  // variance in bandwidth.
    -  // XXX Multiplier is a guess at present.
    -  for (uint32_t i = 1; i < GetNumRepresentations(aAdaptSetIdx); i++) {
    -    NS_ENSURE_TRUE(GetRepresentation(aAdaptSetIdx, i), false);
    -    if (aBandwidth*0.95 < GetRepresentation(aAdaptSetIdx, i)->GetBitrate()) {
    -      // Pick the previous one, since this one's bitrate is too high.
    -      aRepIdx = i-1;
    -      return true;
    -    }
    -  }
    -  // If we reach here, all of the |Representation|'s bitrates are lower than the
    -  // available bandwidth. Just pick the highest, i.e. last in the array.
    -  aRepIdx = GetNumRepresentations(aAdaptSetIdx)-1;
    -  return true;
    -}
    -
    -}//namespace net
    -}//namespace mozilla
    -
    diff --git a/netwerk/dash/mpd/nsDASHWebMODManager.h b/netwerk/dash/mpd/nsDASHWebMODManager.h
    deleted file mode 100644
    index c45f67acf3b6..000000000000
    --- a/netwerk/dash/mpd/nsDASHWebMODManager.h
    +++ /dev/null
    @@ -1,104 +0,0 @@
    -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
    -/* vim: set ts=2 et sw=2 tw=80: */
    -/*
    - * nsDASHWebMODManager.h
    - *****************************************************************************
    - *
    - * Created on: May 1, 2012
    - * Based on IsoffMainManager.h by:
    - *          Christopher Mueller 
    - *          Christian Timmerer  
    - * Author:
    - *          Steve Workman 
    - *
    - * This Source Code Form Is subject to the terms of the Mozilla Public
    - * License, v. 2.0. If a copy of the MPL was not distributed with this file,
    - * You can obtain one at http://mozilla.org/MPL/2.0/.
    - *****************************************************************************/
    -
    -/* DASH - Dynamic Adaptive Streaming over HTTP.
    - *
    - * DASH is an adaptive bitrate streaming technology where a multimedia file is
    - * partitioned into one or more segments and delivered to a client using HTTP.
    - *
    - * (see DASHDecoder.cpp for info on DASH interaction with the media engine).
    - *
    - *
    - * Media Presentation Description (MPD) Manager for WebM On Demand Profile.
    - *                                                  ======================
    - *
    - * Implements MPD Manager interface to use Adaptation Algorithm to determine
    - * which stream to download from WebM On Demand-based MPD.
    - *
    - * WebM On Demand describes a static, on demand media presentation using WebM
    - * encoded media files.
    - * Notes:
    - *    1 time |Period| per media presentation |MPD|.
    - *    1 audio stream (1 |Representation| for the audio |AdaptationSet|).
    - *    1 or multiple video streams for stream switching:
    - *         (multiple |Representation|s for the video |AdaptationSet|).
    - *    1 file for each encoding (1 |Segment| per |Representation|).
    - *    Stream switching allowed between clusters (clusters match DASH
    - *         subsegments).
    - *
    - * Note: Adaptation algorithm is separate and passed into manager.
    - * XXX Adaptation not yet implemented.
    - */
    -
    -#ifndef _NSDASHWEBMODMANAGER_H_
    -#define _NSDASHWEBMODMANAGER_H_
    -
    -#include "nsTArray.h"
    -#include "nsIURI.h"
    -#include "nsString.h"
    -#include "MPD.h"
    -#include "Period.h"
    -#include "AdaptationSet.h"
    -#include "Representation.h"
    -#include "IMPDManager.h"
    -
    -namespace mozilla {
    -namespace net {
    -
    -class nsDASHWebMODManager : public IMPDManager
    -{
    -public:
    -  nsDASHWebMODManager(MPD* mpd);
    -  ~nsDASHWebMODManager();
    -
    -  // See IMPDManager.h for descriptions of following inherited functions.
    -  Period const * GetFirstPeriod() const;
    -  uint32_t GetNumAdaptationSets() const;
    -  AdaptationSetType
    -                 GetAdaptationSetType(uint32_t const aAdaptSetIdx) const;
    -  uint32_t GetNumRepresentations(uint32_t const aAdaptSetIdx) const;
    -  Representation const * GetRepresentation(uint32_t const aAdaptSetIdx,
    -                                           uint32_t const aRepIdx) const;
    -  nsresult GetFirstSegmentUrl(uint32_t const aAdaptSetIdx,
    -                              uint32_t const aRepIdx,
    -                              nsAString &aUrl) const;
    -  double GetStartTime() const;
    -  double GetDuration() const;
    -
    -  // Gets index of the |Representation| with next highest bitrate to the
    -  // estimated bandwidth passed in. Returns true if there is at least one
    -  // |Representation| with a bitrate lower than |aBandwidth|; otherwise returns
    -  // false. Depends on |mRepresentations| being an ordered list.
    -  bool GetBestRepForBandwidth(uint32_t aAdaptSetIdx,
    -                              uint64_t aBandwidth,
    -                              uint32_t &aRepIdx) const MOZ_OVERRIDE;
    -
    -private:
    -  // Internal helper functions.
    -  AdaptationSet const * GetAdaptationSet(uint32_t const aAdaptSetIdx) const;
    -  AdaptationSetType GetAdaptationSetType(nsAString const &mimeType) const;
    -  uint32_t GetNumSegments(Representation const* aRep) const;
    -
    -  // Pointer to the MPD class structure; holds data parsed from the MPD file.
    -  nsAutoPtr mMpd;
    -};
    -
    -}//namespace net
    -}//namespace mozilla
    -
    -#endif /* _NSDASHWEBMODMANAGER_H_ */
    diff --git a/netwerk/dash/mpd/nsDASHWebMODParser.cpp b/netwerk/dash/mpd/nsDASHWebMODParser.cpp
    deleted file mode 100644
    index 21f5b921bc9e..000000000000
    --- a/netwerk/dash/mpd/nsDASHWebMODParser.cpp
    +++ /dev/null
    @@ -1,604 +0,0 @@
    -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
    -/* vim: set ts=2 et sw=2 tw=80: */
    -/*
    - * nsDASHWebMODParser.cpp
    - *****************************************************************************
    - * Copyrigh(C) 2010 - 2012 Klagenfurt University
    - *
    - * Created on: May 1, 2012
    - * Based on IsoffMainParser.cpp by:
    - *          Christopher Mueller 
    - *          Christian Timmerer  
    - * Author:
    - *          Steve Workman 
    -
    - *
    - * This Source Code Form Is subject to the terms of the Mozilla Public
    - * License, v. 2.0. If a copy of the MPL was not distributed with this file,
    - * You can obtain one at http://mozilla.org/MPL/2.0/.
    - *****************************************************************************/
    -
    -/* DASH - Dynamic Adaptive Streaming over HTTP.
    - *
    - * DASH is an adaptive bitrate streaming technology where a multimedia file is
    - * partitioned into one or more segments and delivered to a client using HTTP.
    - *
    - * (see DASHDecoder.cpp for info on DASH interaction with the media engine).
    - *
    - * Media Presentation Description (MPD) Parser for WebM On Demand Profile.
    - *
    - * Parses DOM built from MPD XML to verify data and populate MPD classes.
    - * MPD classes used as a metadata source by WebM On Demand Manager.
    - */
    -
    -#include "nsAutoPtr.h"
    -#include "nsTArray.h"
    -#include "nsMimeTypes.h"
    -#include "nsString.h"
    -#include "nsIDOMElement.h"
    -#include "prlog.h"
    -#include "nsDASHWebMODParser.h"
    -
    -#if defined(PR_LOGGING)
    -static PRLogModuleInfo* gnsDASHWebMODParserLog = nullptr;
    -#define LOG(msg, ...) \
    -        PR_LOG(gnsDASHWebMODParserLog, PR_LOG_DEBUG, \
    -               ("%p [nsDASHWebMODParser] " msg, this, __VA_ARGS__))
    -#define LOG1(msg) \
    -        PR_LOG(gnsDASHWebMODParserLog, PR_LOG_DEBUG, \
    -               ("%p [nsDASHWebMODParser] " msg, this))
    -#else
    -#define LOG(msg, ...)
    -#define LOG1(msg)
    -#endif
    -
    -namespace mozilla {
    -namespace net {
    -
    -nsDASHWebMODParser::nsDASHWebMODParser(nsIDOMElement* aRoot) :
    -  mRoot(aRoot)
    -{
    -  MOZ_COUNT_CTOR(nsDASHWebMODParser);
    -#if defined(PR_LOGGING)
    -  if(!gnsDASHWebMODParserLog)
    -    gnsDASHWebMODParserLog = PR_NewLogModule("nsDASHWebMODParser");
    -#endif
    -  LOG1("Created nsDASHWebMODParser");
    -}
    -
    -nsDASHWebMODParser::~nsDASHWebMODParser()
    -{
    -  MOZ_COUNT_DTOR(nsDASHWebMODParser);
    -}
    -
    -MPD*
    -nsDASHWebMODParser::Parse()
    -{
    -  LOG1("Parsing DOM into MPD objects");
    -  nsAutoPtr mpd(new MPD());
    -
    -  nsresult rv = VerifyMPDAttributes();
    -  NS_ENSURE_SUCCESS(rv, nullptr);
    -
    -  rv = SetMPDBaseUrls(mpd);
    -  NS_ENSURE_SUCCESS(rv, nullptr);
    -
    -  rv = SetPeriods(mpd);
    -  NS_ENSURE_SUCCESS(rv, nullptr);
    -
    -  return mpd.forget();
    -}
    -
    -nsresult
    -nsDASHWebMODParser::VerifyMPDAttributes()
    -{
    -  NS_ENSURE_TRUE(mRoot, NS_ERROR_NOT_INITIALIZED);
    -
    -  // @|type| should be "static".
    -  nsAutoString type;
    -  nsresult rv = GetAttribute(mRoot, NS_LITERAL_STRING("type"), type);
    -  NS_ENSURE_SUCCESS(rv, rv);
    -  NS_ENSURE_TRUE(type.EqualsLiteral("static"), NS_ERROR_ILLEGAL_VALUE);
    -
    -  // Note: No attributes to be set in MPD object for DASH-WebM OD. This
    -  // function used for attribute verification only.
    -  return NS_OK;
    -}
    -
    -nsresult
    -nsDASHWebMODParser::SetMPDBaseUrls(MPD* aMpd)
    -{
    -  NS_ENSURE_TRUE(mRoot, NS_ERROR_NOT_INITIALIZED);
    -
    -  nsCOMPtr child, nextChild;
    -  nsresult rv = mRoot->GetFirstElementChild(getter_AddRefs(child));
    -  NS_ENSURE_SUCCESS(rv, rv);
    -
    -#ifdef PR_LOGGING
    -  int i = 0;
    -#endif
    -  while (child) {
    -    nsAutoString tagName;
    -    rv = child->GetTagName(tagName);
    -    NS_ENSURE_SUCCESS(rv, rv);
    -    if (tagName.EqualsLiteral("BaseURL")) {
    -      nsAutoString baseUrlStr;
    -      rv = child->GetTextContent(baseUrlStr);
    -      NS_ENSURE_SUCCESS(rv, rv);
    -
    -      aMpd->AddBaseUrl(baseUrlStr);
    -      LOG("MPD BaseURL #%d: \"%s\"",
    -          i++, NS_ConvertUTF16toUTF8(baseUrlStr).get());
    -    }
    -    rv = child->GetNextElementSibling(getter_AddRefs(nextChild));
    -    NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
    -    child = nextChild;
    -  }
    -  return NS_OK;
    -}
    -
    -nsresult
    -nsDASHWebMODParser::GetTime(nsAString& aTimeStr, double& aTime)
    -{
    -  NS_ENSURE_FALSE(aTimeStr.IsEmpty(), NS_ERROR_NOT_INITIALIZED);
    -  // Fail if time string is not of the format "PT