diff --git a/accessible/base/nsAccessibilityService.cpp b/accessible/base/nsAccessibilityService.cpp index eb5e028312f..a765bb92d2f 100644 --- a/accessible/base/nsAccessibilityService.cpp +++ b/accessible/base/nsAccessibilityService.cpp @@ -1480,7 +1480,8 @@ nsAccessibilityService::CreateHTMLAccessibleByMarkup(nsIFrame* aFrame, tag == nsGkAtoms::h6 || tag == nsGkAtoms::nav || tag == nsGkAtoms::q || - tag == nsGkAtoms::section) { + tag == nsGkAtoms::section || + tag == nsGkAtoms::time) { nsRefPtr accessible = new HyperTextAccessibleWrap(aContent, document); return accessible.forget(); diff --git a/accessible/generic/HyperTextAccessible.cpp b/accessible/generic/HyperTextAccessible.cpp index 5e8718e432b..a9de7f3ad02 100644 --- a/accessible/generic/HyperTextAccessible.cpp +++ b/accessible/generic/HyperTextAccessible.cpp @@ -982,6 +982,15 @@ HyperTextAccessible::NativeAttributes() } else if (tag == nsGkAtoms::main) { nsAccUtils::SetAccAttr(attributes, nsGkAtoms::xmlroles, NS_LITERAL_STRING("main")); + } else if (tag == nsGkAtoms::time) { + nsAccUtils::SetAccAttr(attributes, nsGkAtoms::xmlroles, + NS_LITERAL_STRING("time")); + + if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::datetime)) { + nsAutoString datetime; + mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::datetime, datetime); + nsAccUtils::SetAccAttr(attributes, nsGkAtoms::datetime, datetime); + } } return attributes.forget(); diff --git a/accessible/tests/mochitest/actions/test_link.html b/accessible/tests/mochitest/actions/test_link.html index 49fc7d911b2..2b690451758 100644 --- a/accessible/tests/mochitest/actions/test_link.html +++ b/accessible/tests/mochitest/actions/test_link.html @@ -22,8 +22,17 @@ var thisTabDocAcc = getTabDocAccessible(); var thisDocTabPanelAcc = thisTabDocAcc.parent.parent; var tabPanelsAcc = thisDocTabPanelAcc.parent; - var newDocTabPanelAcc = tabPanelsAcc.lastChild.firstChild; - return newDocTabPanelAcc.firstChild; + var newDocTabPanelAcc = tabPanelsAcc.firstChild; + var nextAcc = newDocTabPanelAcc; + + while (nextAcc = nextAcc.nextSibling) { + // Find the last accessible for a browser with about:mozilla loaded. + if (nextAcc.firstChild.DOMNode.currentURI.spec == "about:mozilla") { + newDocTabPanelAcc = nextAcc; + } + } + + return newDocTabPanelAcc.firstChild.firstChild; } function linkChecker(aID) diff --git a/accessible/tests/mochitest/elm/test_HTMLSpec.html b/accessible/tests/mochitest/elm/test_HTMLSpec.html index b2978a1f979..867b334ab9f 100644 --- a/accessible/tests/mochitest/elm/test_HTMLSpec.html +++ b/accessible/tests/mochitest/elm/test_HTMLSpec.html @@ -1232,7 +1232,12 @@ ////////////////////////////////////////////////////////////////////////// // HTML:time - ok(!isAccessible("time"), "time element is not accessible"); + obj = { + role: ROLE_TEXT_CONTAINER, + attributes: { "xml-roles": "time", "datetime": "2001-05-15 19:00" }, + interfaces: [ nsIAccessibleText, nsIAccessibleHyperText ] + }; + testElm("time", obj); ////////////////////////////////////////////////////////////////////////// // HTML:u contained by paragraph diff --git a/accessible/tests/mochitest/events/test_docload.html b/accessible/tests/mochitest/events/test_docload.html index 7d3d515430b..01abeb32d76 100644 --- a/accessible/tests/mochitest/events/test_docload.html +++ b/accessible/tests/mochitest/events/test_docload.html @@ -15,25 +15,6 @@ src="../role.js"> - - - @@ -193,12 +174,6 @@ var accTree = { role: ROLE_APP_ROOT, children: [ - { - role: ROLE_CHROME_WINDOW - }, - { - role: ROLE_CHROME_WINDOW - }, { role: ROLE_CHROME_WINDOW }, diff --git a/accessible/tests/mochitest/tree/test_dochierarchy.html b/accessible/tests/mochitest/tree/test_dochierarchy.html index 0bc9686aabe..0104c6abadb 100644 --- a/accessible/tests/mochitest/tree/test_dochierarchy.html +++ b/accessible/tests/mochitest/tree/test_dochierarchy.html @@ -31,10 +31,15 @@ is(root.parentDocument, null, "Wrong parent document of root accessible"); - is(root.childDocumentCount, 1, + ok(root.childDocumentCount >= 1, "Wrong child document count of root accessible"); - is(root.getChildDocumentAt(0), tabDoc, - "Wrong child document at index 0 of root accessible"); + + var tabDocumentFound = false; + for (var i = 0; i < root.childDocumentCount && !tabDocumentFound; i++) { + tabDocumentFound = root.getChildDocumentAt(i) == tabDoc; + } + ok(tabDocumentFound, + "Tab document not found in children of the root accessible"); is(tabDoc.parentDocument, root, "Wrong parent document of tab document"); diff --git a/accessible/tests/mochitest/tree/test_tabbrowser.xul b/accessible/tests/mochitest/tree/test_tabbrowser.xul index d4755c120fc..e957c10658f 100644 --- a/accessible/tests/mochitest/tree/test_tabbrowser.xul +++ b/accessible/tests/mochitest/tree/test_tabbrowser.xul @@ -169,6 +169,23 @@ ] } ] + }, + { + // notificationbox + role: ROLE_PROPERTYPAGE, + children: [ + { + // browser + role: ROLE_INTERNAL_FRAME, + children: [ + { + // #document ("about:newtab" preloaded) + role: ROLE_APPLICATION + // children: [ ... ] // Ignore document content. + } + ] + } + ] } ] }; diff --git a/browser/base/content/browser-fxaccounts.js b/browser/base/content/browser-fxaccounts.js index 18fc0e35e0e..28b544fa4ab 100644 --- a/browser/base/content/browser-fxaccounts.js +++ b/browser/base/content/browser-fxaccounts.js @@ -11,6 +11,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "fxaMigrator", const PREF_SYNC_START_DOORHANGER = "services.sync.ui.showSyncStartDoorhanger"; const DOORHANGER_ACTIVATE_DELAY_MS = 5000; +const SYNC_MIGRATION_NOTIFICATION_TITLE = "fxa-migration"; let gFxAccounts = { @@ -157,7 +158,7 @@ let gFxAccounts = { setTimeout(() => this.onSyncStart(), DOORHANGER_ACTIVATE_DELAY_MS); } else { this._inCustomizationMode = event.type == "customizationstarting"; - this.updateUI(); + this.updateAppMenuItem(); } }, @@ -182,8 +183,13 @@ let gFxAccounts = { }, updateUI: function () { + this.updateAppMenuItem(); + this.updateMigrationNotification(); + }, + + updateAppMenuItem: function () { if (this._migrationInfo) { - this.showMigrationUI(); + this.updateAppMenuItemForMigration(); return; } @@ -241,32 +247,74 @@ let gFxAccounts = { }); }, - showMigrationUI: Task.async(function* () { + updateAppMenuItemForMigration: Task.async(function* () { let status = null; let label = null; switch (this._migrationInfo.state) { case fxaMigrator.STATE_USER_FXA: status = "migrate-signup"; - label = this.strings.formatStringFromName("needUser", + label = this.strings.formatStringFromName("needUserShort", [this.button.getAttribute("fxabrandname")], 1); break; case fxaMigrator.STATE_USER_FXA_VERIFIED: - if (this._migrationInfo.email) { - status = "migrate-verify"; - label = this.strings.formatStringFromName("needVerifiedUser", - [this._migrationInfo.email], - 1); - } + status = "migrate-verify"; + label = this.strings.formatStringFromName("needVerifiedUserShort", + [this._migrationInfo.email], + 1); break; } - if (label && status) { - this.button.label = label; - this.button.hidden = false; - this.button.setAttribute("fxastatus", status); - } else { - Cu.reportError("Could not update menu panel button given migration " + - "state: " + this._migrationInfo.state); + this.button.label = label; + this.button.hidden = false; + this.button.setAttribute("fxastatus", status); + }), + + updateMigrationNotification: Task.async(function* () { + if (!this._migrationInfo) { + Weave.Notifications.removeAll(SYNC_MIGRATION_NOTIFICATION_TITLE); + return; } + if (gBrowser.currentURI.spec.split("?")[0] == "about:accounts") { + // If the current tab is about:accounts, assume the user just completed a + // migration step and don't bother them with a redundant notification. + return; + } + let note = null; + switch (this._migrationInfo.state) { + case fxaMigrator.STATE_USER_FXA: { + let msg = this.strings.GetStringFromName("needUserLong"); + let upgradeLabel = + this.strings.GetStringFromName("upgradeToFxA.label"); + let upgradeAccessKey = + this.strings.GetStringFromName("upgradeToFxA.accessKey"); + note = new Weave.Notification( + undefined, msg, undefined, Weave.Notifications.PRIORITY_WARNING, [ + new Weave.NotificationButton(upgradeLabel, upgradeAccessKey, () => { + fxaMigrator.createFxAccount(window); + }), + ] + ); + break; + } + case fxaMigrator.STATE_USER_FXA_VERIFIED: { + let msg = + this.strings.formatStringFromName("needVerifiedUserLong", + [this._migrationInfo.email], 1); + let resendLabel = + this.strings.GetStringFromName("resendVerificationEmail.label"); + let resendAccessKey = + this.strings.GetStringFromName("resendVerificationEmail.accessKey"); + note = new Weave.Notification( + undefined, msg, undefined, Weave.Notifications.PRIORITY_INFO, [ + new Weave.NotificationButton(resendLabel, resendAccessKey, () => { + fxaMigrator.resendVerificationMail(); + }), + ] + ); + break; + } + } + note.title = SYNC_MIGRATION_NOTIFICATION_TITLE; + Weave.Notifications.replaceTitle(note); }), onMenuPanelCommand: function (event) { diff --git a/browser/base/content/browser-syncui.js b/browser/base/content/browser-syncui.js index 48d39d77980..e93ec1a8a9f 100644 --- a/browser/base/content/browser-syncui.js +++ b/browser/base/content/browser-syncui.js @@ -13,8 +13,6 @@ let CloudSync = null; // gSyncUI handles updating the tools menu and displaying notifications. let gSyncUI = { - DEFAULT_EOL_URL: "https://www.mozilla.org/firefox/?utm_source=synceol", - _obs: ["weave:service:sync:start", "weave:service:quota:remaining", "weave:service:setup-complete", @@ -27,7 +25,6 @@ let gSyncUI = { "weave:ui:sync:error", "weave:ui:sync:finish", "weave:ui:clear-error", - "weave:eol", ], _unloaded: false, @@ -260,32 +257,6 @@ let gSyncUI = { return brand.get("brandShortName"); }, - onEOLNotice: function (data) { - let code = data.code; - let kind = (code == "hard-eol") ? "error" : "warning"; - let url = data.url || gSyncUI.DEFAULT_EOL_URL; - - let title = this._stringBundle.GetStringFromName(kind + ".sync.eol.label"); - let description = this._stringBundle.formatStringFromName(kind + ".sync.eol.description", - [this._getAppName()], - 1); - - let buttons = []; - buttons.push(new Weave.NotificationButton( - this._stringBundle.GetStringFromName("sync.eol.learnMore.label"), - this._stringBundle.GetStringFromName("sync.eol.learnMore.accesskey"), - function() { - window.openUILinkIn(url, "tab"); - return true; - } - )); - - let priority = (kind == "error") ? Weave.Notifications.PRIORITY_WARNING : - Weave.Notifications.PRIORITY_INFO; - let notification = new Weave.Notification(title, description, null, priority, buttons); - Weave.Notifications.replaceTitle(notification); - }, - openServerStatus: function () { let statusURL = Services.prefs.getCharPref("services.sync.statusURL"); window.openUILinkIn(statusURL, "tab"); @@ -551,9 +522,6 @@ let gSyncUI = { case "weave:ui:clear-error": this.clearError(); break; - case "weave:eol": - this.onEOLNotice(subject); - break; } }, diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 18990542ff1..a81f5542c10 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -154,9 +154,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "SafeBrowsing", "resource://gre/modules/SafeBrowsing.jsm"); #endif -XPCOMUtils.defineLazyModuleGetter(this, "gBrowserNewTabPreloader", - "resource:///modules/BrowserNewTabPreloader.jsm", "BrowserNewTabPreloader"); - XPCOMUtils.defineLazyModuleGetter(this, "gCustomizationTabPreloader", "resource:///modules/CustomizationTabPreloader.jsm", "CustomizationTabPreloader"); diff --git a/browser/base/content/socialchat.xml b/browser/base/content/socialchat.xml index 6355429fcd3..83ac01569c1 100644 --- a/browser/base/content/socialchat.xml +++ b/browser/base/content/socialchat.xml @@ -669,6 +669,12 @@ if (event.target != otherWin.document) return; + let detachEvent = new aChatbox.contentWindow.CustomEvent("socialFrameDetached", { + bubbles: true, + cancelable: true, + }); + aChatbox.contentDocument.dispatchEvent(detachEvent); + otherWin.removeEventListener("load", _chatLoad, true); let otherChatbox = otherWin.document.getElementById("chatter"); aChatbox.swapDocShells(otherChatbox); diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index 1b8a8fe27f6..db66d0fdfc3 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -1513,6 +1513,134 @@ + null + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1583,55 +1711,23 @@ if (aOwner) t.owner = aOwner; - var b = document.createElementNS( - "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", - "browser"); - b.setAttribute("type", "content-targetable"); - b.setAttribute("message", "true"); - b.setAttribute("messagemanagergroup", "browsers"); - b.setAttribute("contextmenu", this.getAttribute("contentcontextmenu")); - b.setAttribute("tooltip", this.getAttribute("contenttooltip")); + let b; + let usingPreloadedContent = false; + let isPrivateWindow = PrivateBrowsingUtils.isWindowPrivate(window); - if (remote) - b.setAttribute("remote", "true"); - - if (window.gShowPageResizers && window.windowState == window.STATE_NORMAL) { - b.setAttribute("showresizer", "true"); + // If we open a new tab with the newtab URL, + // check if there is a preloaded browser ready. + if (aURI == BROWSER_NEW_TAB_URL && !isPrivateWindow) { + b = this._getPreloadedBrowser(); + usingPreloadedContent = !!b; } - if (this.hasAttribute("autocompletepopup")) - b.setAttribute("autocompletepopup", this.getAttribute("autocompletepopup")); - - if (this.hasAttribute("selectpopup")) - b.setAttribute("selectpopup", this.getAttribute("selectpopup")); - - b.setAttribute("autoscrollpopup", this._autoScrollPopup.id); - - // Create the browserStack container - var stack = document.createElementNS(NS_XUL, "stack"); - stack.className = "browserStack"; - stack.appendChild(b); - stack.setAttribute("flex", "1"); - - // Create the browserContainer - var browserContainer = document.createElementNS(NS_XUL, "vbox"); - browserContainer.className = "browserContainer"; - browserContainer.appendChild(stack); - browserContainer.setAttribute("flex", "1"); - - // Create the sidebar container - var browserSidebarContainer = document.createElementNS(NS_XUL, - "hbox"); - browserSidebarContainer.className = "browserSidebarContainer"; - browserSidebarContainer.appendChild(browserContainer); - browserSidebarContainer.setAttribute("flex", "1"); - - // Add the Message and the Browser to the box - var notificationbox = document.createElementNS(NS_XUL, - "notificationbox"); - notificationbox.setAttribute("flex", "1"); - notificationbox.appendChild(browserSidebarContainer); + if (!b) { + // No preloaded browser found, create one. + b = this._createBrowser({remote, uriIsAboutBlank}); + } + let notificationbox = this.getNotificationBox(b); var position = this.tabs.length - 1; var uniqueId = this._generateUniquePanelID(); notificationbox.id = uniqueId; @@ -1642,19 +1738,16 @@ t.lastAccessed = Date.now(); this.tabContainer._setPositionalAttributes(); - // Prevent the superfluous initial load of a blank document - // if we're going to load something other than about:blank. - if (!uriIsAboutBlank) { - b.setAttribute("nodefaultsrc", "true"); + // Inject the into the DOM if necessary. + if (!notificationbox.parentNode) { + // NB: this appendChild call causes us to run constructors for the + // browser element, which fires off a bunch of notifications. Some + // of those notifications can cause code to run that inspects our + // state, so it is important that the tab element is fully + // initialized by this point. + this.mPanelContainer.appendChild(notificationbox); } - // NB: this appendChild call causes us to run constructors for the - // browser element, which fires off a bunch of notifications. Some - // of those notifications can cause code to run that inspects our - // state, so it is important that the tab element is fully - // initialized by this point. - this.mPanelContainer.appendChild(notificationbox); - // We've waited until the tab is in the DOM to set the label. This // allows the TabLabelModified event to be properly dispatched. if (!aURI || isBlankPageURL(aURI)) { @@ -1677,16 +1770,9 @@ b.droppedLinkHandler = handleDroppedLink; - // If we just created a new tab that loads the default - // newtab url, swap in a preloaded page if possible. - // Do nothing if we're a private window. - let docShellsSwapped = false; - if (aURI == BROWSER_NEW_TAB_URL && - !PrivateBrowsingUtils.isWindowPrivate(window) && - !gMultiProcessBrowser) { - docShellsSwapped = gBrowserNewTabPreloader.newTab(t); - } else if (aURI == "about:customizing") { - docShellsSwapped = gCustomizationTabPreloader.newTab(t); + // Swap in a preloaded customize tab, if available. + if (aURI == "about:customizing") { + usingPreloadedContent = gCustomizationTabPreloader.newTab(t); } // Dispatch a new tab notification. We do this once we're @@ -1698,7 +1784,7 @@ // If we didn't swap docShells with a preloaded browser // then let's just continue loading the page normally. - if (!docShellsSwapped && !uriIsAboutBlank) { + if (!usingPreloadedContent && !uriIsAboutBlank) { // pretend the user typed this so it'll be available till // the document successfully loads if (aURI && gInitialPages.indexOf(aURI) == -1) @@ -4279,6 +4365,9 @@ // without any scrolling and when the tabbar has already // overflowed. this.mTabstrip._updateScrollButtonsDisabledState(); + + // Preload the next about:newtab if there isn't one already. + this.tabbrowser._createPreloadBrowser(); ]]> diff --git a/browser/base/content/test/general/browser_fxa_migrate.js b/browser/base/content/test/general/browser_fxa_migrate.js index 2e28cbecc0e..d631a4ea53d 100644 --- a/browser/base/content/test/general/browser_fxa_migrate.js +++ b/browser/base/content/test/general/browser_fxa_migrate.js @@ -2,6 +2,7 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ const STATE_CHANGED_TOPIC = "fxa-migration:state-changed"; +const NOTIFICATION_TITLE = "fxa-migration"; let imports = {}; Cu.import("resource://services-sync/FxaMigrator.jsm", imports); @@ -9,30 +10,42 @@ Cu.import("resource://services-sync/FxaMigrator.jsm", imports); add_task(function* test() { // Fake the state where we need an FxA user. let buttonPromise = promiseButtonMutation(); - Services.obs.notifyObservers(null, "fxa-migration:state-changed", + Services.obs.notifyObservers(null, STATE_CHANGED_TOPIC, fxaMigrator.STATE_USER_FXA); let buttonState = yield buttonPromise; assertButtonState(buttonState, "migrate-signup", true); + Assert.ok(Weave.Notifications.notifications.some(n => { + return n.title == NOTIFICATION_TITLE; + }), "Needs-user notification should be present"); // Fake the state where we need a verified FxA user. buttonPromise = promiseButtonMutation(); let email = Cc["@mozilla.org/supports-string;1"]. createInstance(Ci.nsISupportsString); email.data = "foo@example.com"; - Services.obs.notifyObservers(email, "fxa-migration:state-changed", + Services.obs.notifyObservers(email, STATE_CHANGED_TOPIC, fxaMigrator.STATE_USER_FXA_VERIFIED); buttonState = yield buttonPromise; assertButtonState(buttonState, "migrate-verify", true, "foo@example.com not verified"); + let note = Weave.Notifications.notifications.find(n => { + return n.title == NOTIFICATION_TITLE; + }); + Assert.ok(!!note, "Needs-verification notification should be present"); + Assert.ok(note.description.contains(email.data), + "Needs-verification notification should include email"); // Fake the state where no migration is needed. buttonPromise = promiseButtonMutation(); - Services.obs.notifyObservers(null, "fxa-migration:state-changed", null); + Services.obs.notifyObservers(null, STATE_CHANGED_TOPIC, null); buttonState = yield buttonPromise; // In this case, the front end has called fxAccounts.getSignedInUser() to // update the button label and status. But since there isn't actually a user, // the button is left with no fxastatus. assertButtonState(buttonState, "", true); + Assert.ok(!Weave.Notifications.notifications.some(n => { + return n.title == NOTIFICATION_TITLE; + }), "Migration notifications should no longer be present"); }); function assertButtonState(buttonState, expectedStatus, expectedVisible, diff --git a/browser/base/content/test/newtab/browser_newtab_background_captures.js b/browser/base/content/test/newtab/browser_newtab_background_captures.js index f8ea7f982fb..5b372482ebf 100644 --- a/browser/base/content/test/newtab/browser_newtab_background_captures.js +++ b/browser/base/content/test/newtab/browser_newtab_background_captures.js @@ -11,7 +11,6 @@ const CAPTURE_PREF = "browser.pagethumbnails.capturing_disabled"; function runTests() { let imports = {}; Cu.import("resource://gre/modules/PageThumbs.jsm", imports); - Cu.import("resource:///modules/BrowserNewTabPreloader.jsm", imports); // Disable captures. let originalDisabledState = Services.prefs.getBoolPref(CAPTURE_PREF); @@ -31,32 +30,15 @@ function runTests() { yield setLinks("-1"); // We need a handle to a hidden, pre-loaded newtab so we can verify that it - // doesn't allow background captures. Add a newtab, which triggers creation - // of a hidden newtab, and then keep calling BrowserNewTabPreloader.newTab - // until it returns true, meaning that it swapped the passed-in tab's docshell - // for the hidden newtab docshell. - let tab = gWindow.gBrowser.addTab("about:blank"); - yield addNewTabPageTab(); + // doesn't allow background captures. Ensure we have a preloaded browser. + gBrowser._createPreloadBrowser(); - // When newtab is loaded very quickly (which is what happens in 99% of cases) - // there is no need to wait so no tests are run. Because each test requires - // either a pass, fail or todo we run a dummy test here. - ok(true, "Each test requires at least one pass, fail or todo so here is a pass."); + // Wait for the preloaded browser to load. + yield waitForBrowserLoad(gBrowser._preloadedBrowser); - let swapWaitCount = 0; - let swapped = imports.BrowserNewTabPreloader.newTab(tab); - while (!swapped) { - if (++swapWaitCount == 10) { - ok(false, "Timed out waiting for newtab docshell swap."); - return; - } - // Give the hidden newtab some time to finish loading. - yield wait(2000); - info("Checking newtab swap " + swapWaitCount); - swapped = imports.BrowserNewTabPreloader.newTab(tab); - } - - // The tab's docshell is now the previously hidden newtab docshell. + // We're now ready to use the preloaded browser. + BrowserOpenTab(); + let tab = gBrowser.selectedTab; let doc = tab.linkedBrowser.contentDocument; // Enable captures. @@ -67,8 +49,11 @@ function runTests() { if (data != url) return; Services.obs.removeObserver(onCreate, "page-thumbnail:create"); + ok(true, "thumbnail created after preloaded tab was shown"); + // Test finished! Services.prefs.setBoolPref(CAPTURE_PREF, originalDisabledState); + gBrowser.removeTab(tab); file.remove(false); TestRunner.next(); }, "page-thumbnail:create", false); @@ -76,7 +61,3 @@ function runTests() { info("Waiting for thumbnail capture"); yield true; } - -function wait(ms) { - setTimeout(TestRunner.next, ms); -} diff --git a/browser/base/content/test/newtab/head.js b/browser/base/content/test/newtab/head.js index d07e6b92d47..d823085242b 100644 --- a/browser/base/content/test/newtab/head.js +++ b/browser/base/content/test/newtab/head.js @@ -374,21 +374,27 @@ function addNewTabPageTabPromise() { } } - // The new tab page might have been preloaded in the background. - if (browser.contentDocument.readyState == "complete") { - waitForCondition(() => !browser.contentDocument.hidden).then(whenNewTabLoaded); - return deferred.promise; - } - // Wait for the new tab page to be loaded. - browser.addEventListener("load", function onLoad() { - browser.removeEventListener("load", onLoad, true); - whenNewTabLoaded(); - }, true); + waitForBrowserLoad(browser, function () { + // Wait for the document to become visible in case it was preloaded. + waitForCondition(() => !browser.contentDocument.hidden).then(whenNewTabLoaded); + }); return deferred.promise; } +function waitForBrowserLoad(browser, callback = TestRunner.next) { + if (browser.contentDocument.readyState == "complete") { + executeSoon(callback); + return; + } + + browser.addEventListener("load", function onLoad() { + browser.removeEventListener("load", onLoad, true); + executeSoon(callback); + }, true); +} + /** * Compares the current grid arrangement with the given pattern. * @param the pattern (see below) diff --git a/browser/components/loop/MozLoopService.jsm b/browser/components/loop/MozLoopService.jsm index a3f034be0eb..6c30bf43835 100644 --- a/browser/components/loop/MozLoopService.jsm +++ b/browser/components/loop/MozLoopService.jsm @@ -828,9 +828,15 @@ let MozLoopServiceInternal = { let window = chatbox.contentWindow; - window.addEventListener("unload", function onUnloadChat(evt) { - UITour.notify("Loop:ChatWindowClosed"); - }); + function socialFrameChanged(eventName) { + UITour.availableTargetsCache.clear(); + UITour.notify(eventName); + } + + window.addEventListener("socialFrameHide", socialFrameChanged.bind(null, "Loop:ChatWindowHidden")); + window.addEventListener("socialFrameShow", socialFrameChanged.bind(null, "Loop:ChatWindowShown")); + window.addEventListener("socialFrameDetached", socialFrameChanged.bind(null, "Loop:ChatWindowDetached")); + window.addEventListener("unload", socialFrameChanged.bind(null, "Loop:ChatWindowClosed")); injectLoopAPI(window); diff --git a/browser/components/nsBrowserGlue.js b/browser/components/nsBrowserGlue.js index 047bcf22d82..0b8241317e6 100644 --- a/browser/components/nsBrowserGlue.js +++ b/browser/components/nsBrowserGlue.js @@ -53,9 +53,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "PageThumbs", XPCOMUtils.defineLazyModuleGetter(this, "NewTabUtils", "resource://gre/modules/NewTabUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "BrowserNewTabPreloader", - "resource:///modules/BrowserNewTabPreloader.jsm"); - XPCOMUtils.defineLazyModuleGetter(this, "CustomizationTabPreloader", "resource:///modules/CustomizationTabPreloader.jsm"); @@ -791,7 +788,6 @@ BrowserGlue.prototype = { Cu.reportError("Could not end startup crash tracking in quit-application-granted: " + e); } - BrowserNewTabPreloader.uninit(); CustomizationTabPreloader.uninit(); WebappManager.uninit(); #ifdef NIGHTLY_BUILD diff --git a/browser/locales/en-US/chrome/browser/accounts.properties b/browser/locales/en-US/chrome/browser/accounts.properties index 7805167f2d3..18dff0aaa66 100644 --- a/browser/locales/en-US/chrome/browser/accounts.properties +++ b/browser/locales/en-US/chrome/browser/accounts.properties @@ -1,7 +1,19 @@ -# LOCALIZATION NOTE (needUser) -# %S = Firefox Accounts brand name from syncBrand.dtd -needUser = %S required for sync +# 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/. -# LOCALIZATION NOTE (needVerifiedUser) +# LOCALIZATION NOTE (needUserShort) +# %S = Firefox Accounts brand name from syncBrand.dtd +needUserShort = %S required for sync +needUserLong = We've rebuilt Sync to make it easier for everyone. Please upgrade to a Firefox Account to continue syncing. + +upgradeToFxA.label = Upgrade +upgradeToFxA.accessKey = U + +# LOCALIZATION NOTE (needVerifiedUserShort, needVerifiedUserLong) # %S = Email address of user's Firefox Account -needVerifiedUser = %S not verified +needVerifiedUserShort = %S not verified +needVerifiedUserLong = Please click the verification link in the email sent to %S + +resendVerificationEmail.label = Resend +resendVerificationEmail.accessKey = R diff --git a/browser/modules/BrowserNewTabPreloader.jsm b/browser/modules/BrowserNewTabPreloader.jsm deleted file mode 100644 index 41e86883d96..00000000000 --- a/browser/modules/BrowserNewTabPreloader.jsm +++ /dev/null @@ -1,379 +0,0 @@ -/* 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/. */ - -"use strict"; - -this.EXPORTED_SYMBOLS = ["BrowserNewTabPreloader"]; - -const Cu = Components.utils; -const Cc = Components.classes; -const Ci = Components.interfaces; - -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Promise.jsm"); - -const HTML_NS = "http://www.w3.org/1999/xhtml"; -const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; -const XUL_PAGE = "data:application/vnd.mozilla.xul+xml;charset=utf-8,"; -const NEWTAB_URL = "about:newtab"; - -const PREF_NEWTAB_URL = "browser.newtab.url"; -const PREF_NEWTAB_PRELOAD = "browser.newtab.preload"; - -// The interval between swapping in a preload docShell and kicking off the -// next preload in the background. -const PRELOADER_INTERVAL_MS = 600; -// The number of miliseconds we'll wait after we received a notification that -// causes us to update our list of browsers and tabbrowser sizes. This acts as -// kind of a damper when too many events are occuring in quick succession. -const PRELOADER_UPDATE_DELAY_MS = 3000; - -const TOPIC_TIMER_CALLBACK = "timer-callback"; -const TOPIC_DELAYED_STARTUP = "browser-delayed-startup-finished"; -const TOPIC_XUL_WINDOW_CLOSED = "xul-window-destroyed"; - -const BROWSER_CONTENT_SCRIPT = "chrome://browser/content/content.js"; - -function isPreloadingEnabled() { - return Services.prefs.getBoolPref(PREF_NEWTAB_PRELOAD) && - !Services.prefs.prefHasUserValue(PREF_NEWTAB_URL); -} - -function createTimer(obj, delay) { - let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); - timer.init(obj, delay, Ci.nsITimer.TYPE_ONE_SHOT); - return timer; -} - -function clearTimer(timer) { - if (timer) { - timer.cancel(); - } - return null; -} - -this.BrowserNewTabPreloader = { - uninit: function Preloader_uninit() { - HostFrame.destroy(); - HiddenBrowsers.uninit(); - }, - - newTab: function Preloader_newTab(aTab) { - if (!isPreloadingEnabled()) { - return false; - } - - let win = aTab.ownerDocument.defaultView; - if (win.gBrowser) { - let utils = win.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils); - - let {width, height} = utils.getBoundsWithoutFlushing(win.gBrowser); - let hiddenBrowser = HiddenBrowsers.get(width, height) - if (hiddenBrowser) { - return hiddenBrowser.swapWithNewTab(aTab); - } - } - - return false; - } -}; - -Object.freeze(BrowserNewTabPreloader); - -let HiddenBrowsers = { - _browsers: null, - _updateTimer: null, - - _topics: [ - TOPIC_DELAYED_STARTUP, - TOPIC_XUL_WINDOW_CLOSED - ], - - _init: function () { - this._browsers = new Map(); - this._updateBrowserSizes(); - this._topics.forEach(t => Services.obs.addObserver(this, t, false)); - }, - - uninit: function () { - if (this._browsers) { - this._topics.forEach(t => Services.obs.removeObserver(this, t, false)); - this._updateTimer = clearTimer(this._updateTimer); - - for (let [key, browser] of this._browsers) { - browser.destroy(); - } - this._browsers = null; - } - }, - - get: function (width, height) { - // Initialize if this is the first call. - if (!this._browsers) { - this._init(); - } - - let key = width + "x" + height; - if (!this._browsers.has(key)) { - // Update all browsers' sizes if we can't find a matching one. - this._updateBrowserSizes(); - } - - // We should now have a matching browser. - if (this._browsers.has(key)) { - return this._browsers.get(key); - } - - // We should never be here. Return the first browser we find. - Cu.reportError("NewTabPreloader: no matching browser found after updating"); - for (let [size, browser] of this._browsers) { - return browser; - } - - // We should really never be here. - Cu.reportError("NewTabPreloader: not even a single browser was found?"); - return null; - }, - - observe: function (subject, topic, data) { - if (topic === TOPIC_TIMER_CALLBACK) { - this._updateTimer = null; - this._updateBrowserSizes(); - } else { - this._updateTimer = clearTimer(this._updateTimer); - this._updateTimer = createTimer(this, PRELOADER_UPDATE_DELAY_MS); - } - }, - - _updateBrowserSizes: function () { - let sizes = this._collectTabBrowserSizes(); - let toRemove = []; - - // Iterate all browsers and check that they - // each can be assigned to one of the sizes. - for (let [key, browser] of this._browsers) { - if (sizes.has(key)) { - // We already have a browser for that size, great! - sizes.delete(key); - } else { - // This browser is superfluous or needs to be resized. - toRemove.push(browser); - this._browsers.delete(key); - } - } - - // Iterate all sizes that we couldn't find a browser for. - for (let [key, {width, height}] of sizes) { - let browser; - if (toRemove.length) { - // Let's just resize one of the superfluous - // browsers and put it back into the map. - browser = toRemove.shift(); - browser.resize(width, height); - } else { - // No more browsers to reuse, create a new one. - browser = new HiddenBrowser(width, height); - } - - this._browsers.set(key, browser); - } - - // Finally, remove all browsers we don't need anymore. - toRemove.forEach(b => b.destroy()); - }, - - _collectTabBrowserSizes: function () { - let sizes = new Map(); - - function tabBrowserBounds() { - let wins = Services.ww.getWindowEnumerator("navigator:browser"); - while (wins.hasMoreElements()) { - let win = wins.getNext(); - if (win.gBrowser) { - let utils = win.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils); - yield utils.getBoundsWithoutFlushing(win.gBrowser); - } - } - } - - // Collect the sizes of all s out there. - for (let {width, height} of tabBrowserBounds()) { - if (width > 0 && height > 0) { - let key = width + "x" + height; - if (!sizes.has(key)) { - sizes.set(key, {width: width, height: height}); - } - } - } - - return sizes; - } -}; - -function HiddenBrowser(width, height) { - this.resize(width, height); - this._createBrowser(); -} - -HiddenBrowser.prototype = { - _width: null, - _height: null, - _timer: null, - - get isPreloaded() { - return this._browser && - this._browser.contentDocument && - this._browser.contentDocument.readyState === "complete" && - this._browser.currentURI.spec === NEWTAB_URL; - }, - - swapWithNewTab: function (aTab) { - if (!this.isPreloaded || this._timer) { - return false; - } - - let win = aTab.ownerDocument.defaultView; - let tabbrowser = win.gBrowser; - - if (!tabbrowser) { - return false; - } - - // Swap docShells. - tabbrowser.swapNewTabWithBrowser(aTab, this._browser); - - // Load all delayed frame scripts attached to the "browers" message manager. - // The browser content script was already loaded, so don't load it again. - let mm = aTab.linkedBrowser.messageManager; - let scripts = win.getGroupMessageManager("browsers").getDelayedFrameScripts(); - Array.forEach(scripts, ([script, runGlobal]) => { - if (script != BROWSER_CONTENT_SCRIPT) { - mm.loadFrameScript(script, true, runGlobal); - } - }); - - // Remove the browser, it will be recreated by a timer. - this._removeBrowser(); - - // Start a timer that will kick off preloading the next newtab page. - this._timer = createTimer(this, PRELOADER_INTERVAL_MS); - - // Signal that we swapped docShells. - return true; - }, - - observe: function () { - this._timer = null; - - // Start pre-loading the new tab page. - this._createBrowser(); - }, - - resize: function (width, height) { - this._width = width; - this._height = height; - this._applySize(); - }, - - destroy: function () { - this._removeBrowser(); - this._timer = clearTimer(this._timer); - }, - - _applySize: function () { - if (this._browser) { - this._browser.style.width = this._width + "px"; - this._browser.style.height = this._height + "px"; - } - }, - - _createBrowser: function () { - HostFrame.get().then(aFrame => { - let doc = aFrame.document; - this._browser = doc.createElementNS(XUL_NS, "browser"); - this._browser.setAttribute("type", "content"); - this._browser.setAttribute("src", NEWTAB_URL); - this._applySize(); - doc.getElementById("win").appendChild(this._browser); - - // The browser might not have a docShell here if the HostFrame was - // destroyed while the promise was resolved. Simply bail out. - if (!this._browser.docShell) { - return; - } - - // Let the docShell be inactive so that document.hidden=true. - this._browser.docShell.isActive = false; - - this._browser.messageManager.loadFrameScript(BROWSER_CONTENT_SCRIPT, - true); - }); - }, - - _removeBrowser: function () { - if (this._browser) { - this._browser.remove(); - this._browser = null; - } - } -}; - -let HostFrame = { - _frame: null, - _deferred: null, - - get hiddenDOMDocument() { - return Services.appShell.hiddenDOMWindow.document; - }, - - get isReady() { - return this.hiddenDOMDocument.readyState === "complete"; - }, - - get: function () { - if (!this._deferred) { - this._deferred = Promise.defer(); - this._create(); - } - - return this._deferred.promise; - }, - - destroy: function () { - if (this._frame) { - if (!Cu.isDeadWrapper(this._frame)) { - this._frame.removeEventListener("load", this, true); - this._frame.remove(); - } - - this._frame = null; - this._deferred = null; - } - }, - - handleEvent: function () { - let contentWindow = this._frame.contentWindow; - if (contentWindow.location.href === XUL_PAGE) { - this._frame.removeEventListener("load", this, true); - this._deferred.resolve(contentWindow); - } else { - contentWindow.location = XUL_PAGE; - } - }, - - _create: function () { - if (this.isReady) { - let doc = this.hiddenDOMDocument; - this._frame = doc.createElementNS(HTML_NS, "iframe"); - this._frame.addEventListener("load", this, true); - doc.documentElement.appendChild(this._frame); - } else { - let flags = Ci.nsIThread.DISPATCH_NORMAL; - Services.tm.currentThread.dispatch(() => this._create(), flags); - } - } -}; diff --git a/browser/modules/UITour.jsm b/browser/modules/UITour.jsm index 7534fd4b4b8..48448e8c337 100644 --- a/browser/modules/UITour.jsm +++ b/browser/modules/UITour.jsm @@ -142,6 +142,16 @@ this.UITour = { return loopBrowser.contentDocument.querySelector(".room-list"); }, }], + ["loop-selectedRoomButtons", { + infoPanelPosition: "leftcenter bottomright", + query: (aDocument) => { + let chatbox = aDocument.querySelector("chatbox[src^='about\:loopconversation'][selected]"); + if (!chatbox || !chatbox.contentDocument) { + return null; + } + return chatbox.contentDocument.querySelector(".call-action-group"); + }, + }], ["loop-signInUpLink", { query: (aDocument) => { let loopBrowser = aDocument.querySelector("#loop-notification-panel > #loop"); @@ -1375,8 +1385,7 @@ this.UITour = { hideLoopPanelAnnotations: function(aEvent) { UITour.hideAnnotationsForPanel(aEvent, (aTarget) => { - // TODO: Bug 1104927 - Handle the conversation targets separately. - return aTarget.targetName.startsWith("loop-"); + return aTarget.targetName.startsWith("loop-") && aTarget.targetName != "loop-selectedRoomButtons"; }); }, diff --git a/browser/modules/moz.build b/browser/modules/moz.build index 0cc21c5dd24..d708b5fc970 100644 --- a/browser/modules/moz.build +++ b/browser/modules/moz.build @@ -11,7 +11,6 @@ XPCSHELL_TESTS_MANIFESTS += [ ] EXTRA_JS_MODULES += [ - 'BrowserNewTabPreloader.jsm', 'BrowserUITelemetry.jsm', 'CastingApps.jsm', 'Chat.jsm', diff --git a/browser/modules/test/browser_UITour_loop.js b/browser/modules/test/browser_UITour_loop.js index ac2e6b7aa9c..25a18232a44 100644 --- a/browser/modules/test/browser_UITour_loop.js +++ b/browser/modules/test/browser_UITour_loop.js @@ -90,9 +90,12 @@ let tests = [ gContentAPI.observe((event, params) => { is(event, "Loop:ChatWindowOpened", "Check Loop:ChatWindowOpened notification"); gContentAPI.observe((event, params) => { - is(event, "Loop:ChatWindowClosed", "Check Loop:ChatWindowClosed notification"); + is(event, "Loop:ChatWindowShown", "Check Loop:ChatWindowShown notification"); gContentAPI.observe((event, params) => { - ok(false, "No more notifications should have arrived"); + is(event, "Loop:ChatWindowClosed", "Check Loop:ChatWindowClosed notification"); + gContentAPI.observe((event, params) => { + ok(false, "No more notifications should have arrived"); + }); }); done(); }); diff --git a/docshell/base/LoadInfo.cpp b/docshell/base/LoadInfo.cpp index 79ac48e51aa..068408c9f35 100644 --- a/docshell/base/LoadInfo.cpp +++ b/docshell/base/LoadInfo.cpp @@ -122,4 +122,10 @@ LoadInfo::GetBaseURI(nsIURI** aBaseURI) return NS_OK; } +nsIURI* +LoadInfo::BaseURI() +{ + return mBaseURI; +} + } // namespace mozilla diff --git a/docshell/base/nsILoadInfo.idl b/docshell/base/nsILoadInfo.idl index 4ca48c2b195..2e516d82138 100644 --- a/docshell/base/nsILoadInfo.idl +++ b/docshell/base/nsILoadInfo.idl @@ -17,7 +17,7 @@ typedef unsigned long nsSecurityFlags; /** * An nsILoadOwner represents per-load information about who started the load. */ -[scriptable, builtinclass, uuid(da363267-236d-49bf-83a2-33da8d892728)] +[scriptable, builtinclass, uuid(768a1f20-57d4-462a-812a-41c04e5d1e19)] interface nsILoadInfo : nsISupports { /** @@ -156,7 +156,7 @@ interface nsILoadInfo : nsISupports * The contentPolicyType of the channel, used for security checks * like Mixed Content Blocking and Content Security Policy. */ - readonly attribute nsContentPolicyType contentPolicyType; + readonly attribute nsContentPolicyType contentPolicyType; %{ C++ inline nsContentPolicyType GetContentPolicyType() @@ -173,5 +173,11 @@ interface nsILoadInfo : nsISupports * This attribute may be null. The value of this attribute may be * ignored if the base URI can be inferred by the channel's URI. */ - readonly attribute nsIURI baseURI; + readonly attribute nsIURI baseURI; + + /** + * A C++-friendly version of baseURI. + */ + [noscript, notxpcom, nostdcall, binaryname(BaseURI)] + nsIURI binaryBaseURI(); }; diff --git a/dom/indexedDB/ActorsChild.cpp b/dom/indexedDB/ActorsChild.cpp index 5043d426521..bebcbab12be 100644 --- a/dom/indexedDB/ActorsChild.cpp +++ b/dom/indexedDB/ActorsChild.cpp @@ -56,6 +56,37 @@ namespace mozilla { namespace dom { namespace indexedDB { +/******************************************************************************* + * ThreadLocal + ******************************************************************************/ + +ThreadLocal::ThreadLocal(const nsID& aBackgroundChildLoggingId) + : mLoggingInfo(aBackgroundChildLoggingId, 1, -1, 1) + , mCurrentTransaction(0) +#ifdef DEBUG + , mOwningThread(PR_GetCurrentThread()) +#endif +{ + MOZ_ASSERT(mOwningThread); + + MOZ_COUNT_CTOR(mozilla::dom::indexedDB::ThreadLocal); +} + +ThreadLocal::~ThreadLocal() +{ + MOZ_COUNT_DTOR(mozilla::dom::indexedDB::ThreadLocal); +} + +#ifdef DEBUG + +void +ThreadLocal::AssertIsOnOwningThread() const +{ + MOZ_ASSERT(PR_GetCurrentThread() == mOwningThread); +} + +#endif // DEBUG + /******************************************************************************* * Helpers ******************************************************************************/ @@ -104,39 +135,40 @@ class MOZ_STACK_CLASS AutoSetCurrentTransaction MOZ_FINAL IDBTransaction* const mTransaction; IDBTransaction* mPreviousTransaction; - IDBTransaction** mThreadLocalSlot; + ThreadLocal* mThreadLocal; public: explicit AutoSetCurrentTransaction(IDBTransaction* aTransaction) : mTransaction(aTransaction) , mPreviousTransaction(nullptr) - , mThreadLocalSlot(nullptr) + , mThreadLocal(nullptr) { if (aTransaction) { BackgroundChildImpl::ThreadLocal* threadLocal = BackgroundChildImpl::GetThreadLocalForCurrentThread(); MOZ_ASSERT(threadLocal); - // Hang onto this location for resetting later. - mThreadLocalSlot = &threadLocal->mCurrentTransaction; + // Hang onto this for resetting later. + mThreadLocal = threadLocal->mIndexedDBThreadLocal; + MOZ_ASSERT(mThreadLocal); // Save the current value. - mPreviousTransaction = *mThreadLocalSlot; + mPreviousTransaction = mThreadLocal->GetCurrentTransaction(); // Set the new value. - *mThreadLocalSlot = aTransaction; + mThreadLocal->SetCurrentTransaction(aTransaction); } } ~AutoSetCurrentTransaction() { - MOZ_ASSERT_IF(mThreadLocalSlot, mTransaction); - - if (mThreadLocalSlot) { - MOZ_ASSERT(*mThreadLocalSlot == mTransaction); + MOZ_ASSERT_IF(mThreadLocal, mTransaction); + MOZ_ASSERT_IF(mThreadLocal, + mThreadLocal->GetCurrentTransaction() == mTransaction); + if (mThreadLocal) { // Reset old value. - *mThreadLocalSlot = mPreviousTransaction; + mThreadLocal->SetCurrentTransaction(mPreviousTransaction); } } @@ -589,6 +621,25 @@ DispatchErrorEvent(IDBRequest* aRequest, asct.emplace(aTransaction); } + if (transaction) { + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "Firing %s event with error 0x%x", + "IndexedDB %s: C T[%lld] R[%llu]: %s (0x%x)", + IDB_LOG_ID_STRING(), + transaction->LoggingSerialNumber(), + request->LoggingSerialNumber(), + IDB_LOG_STRINGIFY(aEvent, kErrorEventType), + aErrorCode); + } else { + IDB_LOG_MARK("IndexedDB %s: Child Request[%llu]: " + "Firing %s event with error 0x%x", + "IndexedDB %s: C R[%llu]: %s (0x%x)", + IDB_LOG_ID_STRING(), + request->LoggingSerialNumber(), + IDB_LOG_STRINGIFY(aEvent, kErrorEventType), + aErrorCode); + } + bool doDefault; nsresult rv = request->DispatchEvent(aEvent, &doDefault); if (NS_WARN_IF(NS_FAILED(rv))) { @@ -648,6 +699,22 @@ DispatchSuccessEvent(ResultHelper* aResultHelper, MOZ_ASSERT(aEvent); MOZ_ASSERT_IF(transaction, transaction->IsOpen()); + if (transaction) { + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "Firing %s event", + "IndexedDB %s: C T[%lld] R[%llu]: %s", + IDB_LOG_ID_STRING(), + transaction->LoggingSerialNumber(), + request->LoggingSerialNumber(), + IDB_LOG_STRINGIFY(aEvent, kSuccessEventType)); + } else { + IDB_LOG_MARK("IndexedDB %s: Child Request[%llu]: Firing %s event", + "IndexedDB %s: C R[%llu]: %s", + IDB_LOG_ID_STRING(), + request->LoggingSerialNumber(), + IDB_LOG_STRINGIFY(aEvent, kSuccessEventType)); + } + bool dummy; nsresult rv = request->DispatchEvent(aEvent, &dummy); if (NS_WARN_IF(NS_FAILED(rv))) { @@ -1068,6 +1135,11 @@ BackgroundFactoryRequestChild::RecvBlocked(const uint64_t& aCurrentVersion) nsRefPtr kungFuDeathGrip = mRequest; + IDB_LOG_MARK("IndexedDB %s: Child Request[%llu]: Firing \"blocked\" event", + "IndexedDB %s: C R[%llu]: \"blocked\"", + IDB_LOG_ID_STRING(), + mRequest->LoggingSerialNumber()); + bool dummy; if (NS_FAILED(mRequest->DispatchEvent(blockedEvent, &dummy))) { NS_WARNING("Failed to dispatch event!"); @@ -1357,6 +1429,10 @@ BackgroundDatabaseChild::RecvVersionChange(const uint64_t& aOldVersion, return false; } + IDB_LOG_MARK("IndexedDB %s: Child : Firing \"versionchange\" event", + "IndexedDB %s: C: IDBDatabase \"versionchange\" event", + IDB_LOG_ID_STRING()); + bool dummy; if (NS_FAILED(mDatabase->DispatchEvent(versionChangeEvent, &dummy))) { NS_WARNING("Failed to dispatch event!"); diff --git a/dom/indexedDB/ActorsChild.h b/dom/indexedDB/ActorsChild.h index d77ff27db1b..f93cbc89e84 100644 --- a/dom/indexedDB/ActorsChild.h +++ b/dom/indexedDB/ActorsChild.h @@ -5,6 +5,7 @@ #ifndef mozilla_dom_indexeddb_actorschild_h__ #define mozilla_dom_indexeddb_actorschild_h__ +#include "IDBTransaction.h" #include "js/RootingAPI.h" #include "mozilla/Attributes.h" #include "mozilla/dom/indexedDB/PBackgroundIDBCursorChild.h" @@ -12,6 +13,7 @@ #include "mozilla/dom/indexedDB/PBackgroundIDBFactoryChild.h" #include "mozilla/dom/indexedDB/PBackgroundIDBFactoryRequestChild.h" #include "mozilla/dom/indexedDB/PBackgroundIDBRequestChild.h" +#include "mozilla/dom/indexedDB/PBackgroundIDBSharedTypes.h" #include "mozilla/dom/indexedDB/PBackgroundIDBTransactionChild.h" #include "mozilla/dom/indexedDB/PBackgroundIDBVersionChangeTransactionChild.h" #include "nsAutoPtr.h" @@ -19,6 +21,7 @@ #include "nsTArray.h" class nsIEventTarget; +struct nsID; struct PRThread; namespace mozilla { @@ -38,13 +41,97 @@ class IDBFactory; class IDBMutableFile; class IDBOpenDBRequest; class IDBRequest; -class IDBTransaction; class Key; class PBackgroundIDBFileChild; class PermissionRequestChild; class PermissionRequestParent; class SerializedStructuredCloneReadInfo; +class ThreadLocal +{ + friend class nsAutoPtr; + friend class IDBFactory; + + LoggingInfo mLoggingInfo; + IDBTransaction* mCurrentTransaction; + +#ifdef DEBUG + PRThread* mOwningThread; +#endif + +public: + void + AssertIsOnOwningThread() const +#ifdef DEBUG + ; +#else + { } +#endif + + const LoggingInfo& + GetLoggingInfo() const + { + AssertIsOnOwningThread(); + + return mLoggingInfo; + } + + const nsID& + Id() const + { + AssertIsOnOwningThread(); + + return mLoggingInfo.backgroundChildLoggingId(); + } + + int64_t + NextTransactionSN(IDBTransaction::Mode aMode) + { + AssertIsOnOwningThread(); + MOZ_ASSERT(mLoggingInfo.nextTransactionSerialNumber() < INT64_MAX); + MOZ_ASSERT(mLoggingInfo.nextVersionChangeTransactionSerialNumber() > + INT64_MIN); + + if (aMode == IDBTransaction::VERSION_CHANGE) { + return mLoggingInfo.nextVersionChangeTransactionSerialNumber()--; + } + + return mLoggingInfo.nextTransactionSerialNumber()++; + } + + uint64_t + NextRequestSN() + { + AssertIsOnOwningThread(); + MOZ_ASSERT(mLoggingInfo.nextRequestSerialNumber() < UINT64_MAX); + + return mLoggingInfo.nextRequestSerialNumber()++; + } + + void + SetCurrentTransaction(IDBTransaction* aCurrentTransaction) + { + AssertIsOnOwningThread(); + + mCurrentTransaction = aCurrentTransaction; + } + + IDBTransaction* + GetCurrentTransaction() const + { + AssertIsOnOwningThread(); + + return mCurrentTransaction; + } + +private: + ThreadLocal(const nsID& aBackgroundChildLoggingId); + ~ThreadLocal(); + + ThreadLocal() MOZ_DELETE; + ThreadLocal(const ThreadLocal& aOther) MOZ_DELETE; +}; + class BackgroundFactoryChild MOZ_FINAL : public PBackgroundIDBFactoryChild { diff --git a/dom/indexedDB/ActorsParent.cpp b/dom/indexedDB/ActorsParent.cpp index 8944be1f04f..620b04da179 100644 --- a/dom/indexedDB/ActorsParent.cpp +++ b/dom/indexedDB/ActorsParent.cpp @@ -107,6 +107,7 @@ namespace { class Cursor; class Database; struct DatabaseActorInfo; +class DatabaseLoggingInfo; class DatabaseFile; class DatabaseOfflineStorage; class Factory; @@ -2553,17 +2554,14 @@ class DatabaseOperationBase : public nsRunnable , public mozIStorageProgressHandler { - // Uniquely tracks each operation for logging purposes. Only modified on the - // PBackground thread. - static uint64_t sNextSerialNumber; - protected: class AutoSetProgressHandler; typedef nsDataHashtable UniqueIndexTable; nsCOMPtr mOwningThread; - const uint64_t mSerialNumber; + const nsID mBackgroundChildLoggingId; + const uint64_t mLoggingSerialNumber; nsresult mResultCode; private: @@ -2610,10 +2608,16 @@ public: return mOperationMayProceed; } - uint64_t - SerialNumber() const + const nsID& + BackgroundChildLoggingId() const { - return mSerialNumber; + return mBackgroundChildLoggingId; + } + + uint64_t + LoggingSerialNumber() const + { + return mLoggingSerialNumber; } nsresult @@ -2632,9 +2636,11 @@ public: } protected: - DatabaseOperationBase() + DatabaseOperationBase(const nsID& aBackgroundChildLoggingId, + uint64_t aLoggingSerialNumber) : mOwningThread(NS_GetCurrentThread()) - , mSerialNumber(++sNextSerialNumber) + , mBackgroundChildLoggingId(aBackgroundChildLoggingId) + , mLoggingSerialNumber(aLoggingSerialNumber) , mResultCode(NS_OK) , mOperationMayProceed(true) , mActorDestroyed(false) @@ -2709,6 +2715,7 @@ class TransactionDatabaseOperationBase : public DatabaseOperationBase { nsRefPtr mTransaction; + const int64_t mTransactionLoggingSerialNumber; const bool mTransactionIsAborted; public: @@ -2736,7 +2743,11 @@ public: Cleanup(); protected: - explicit TransactionDatabaseOperationBase(TransactionBase* aTransaction); + explicit + TransactionDatabaseOperationBase(TransactionBase* aTransaction); + + TransactionDatabaseOperationBase(TransactionBase* aTransaction, + uint64_t aLoggingSerialNumber); virtual ~TransactionDatabaseOperationBase(); @@ -2779,17 +2790,29 @@ class Factory MOZ_FINAL // ActorDestroy called. static uint64_t sFactoryInstanceCount; + nsRefPtr mLoggingInfo; + DebugOnly mActorDestroyed; public: static already_AddRefed - Create(); + Create(const LoggingInfo& aLoggingInfo); + + DatabaseLoggingInfo* + GetLoggingInfo() const + { + AssertIsOnBackgroundThread(); + MOZ_ASSERT(mLoggingInfo); + + return mLoggingInfo; + } NS_INLINE_DECL_THREADSAFE_REFCOUNTING(mozilla::dom::indexedDB::Factory) private: // Only constructed in Create(). - explicit Factory(); + explicit + Factory(already_AddRefed aLoggingInfo); // Reference counted. ~Factory(); @@ -2801,6 +2824,9 @@ private: virtual bool RecvDeleteMe() MOZ_OVERRIDE; + virtual bool + RecvIncrementLoggingRequestSerialNumber() MOZ_OVERRIDE; + virtual PBackgroundIDBFactoryRequestParent* AllocPBackgroundIDBFactoryRequestParent(const FactoryRequestParams& aParams) MOZ_OVERRIDE; @@ -2924,6 +2950,15 @@ public: return Manager()->Manager(); } + DatabaseLoggingInfo* + GetLoggingInfo() const + { + AssertIsOnBackgroundThread(); + MOZ_ASSERT(mFactory); + + return mFactory->GetLoggingInfo(); + } + bool RegisterTransaction(TransactionBase* aTransaction); @@ -3130,6 +3165,7 @@ private: mModifiedAutoIncrementObjectStoreMetadataArray; const uint64_t mTransactionId; const nsCString mDatabaseId; + const int64_t mLoggingSerialNumber; uint64_t mActiveRequestCount; Atomic mInvalidatedOnAnyThread; Mode mMode; @@ -3248,6 +3284,21 @@ public: return mDatabase; } + DatabaseLoggingInfo* + GetLoggingInfo() const + { + AssertIsOnBackgroundThread(); + MOZ_ASSERT(mDatabase); + + return mDatabase->GetLoggingInfo(); + } + + int64_t + LoggingSerialNumber() const + { + return mLoggingSerialNumber; + } + bool IsAborted() const { @@ -3297,8 +3348,7 @@ public: Invalidate(); protected: - TransactionBase(Database* aDatabase, - Mode aMode); + TransactionBase(Database* aDatabase, Mode aMode); virtual ~TransactionBase(); @@ -3420,13 +3470,7 @@ class TransactionBase::CommitOp MOZ_FINAL nsresult mResultCode; private: - CommitOp(TransactionBase* aTransaction, - nsresult aResultCode) - : mTransaction(aTransaction) - , mResultCode(aResultCode) - { - MOZ_ASSERT(aTransaction); - } + CommitOp(TransactionBase* aTransaction, nsresult aResultCode); ~CommitOp() { } @@ -3670,8 +3714,8 @@ class NormalTransaction MOZ_FINAL private: // This constructor is only called by Database. NormalTransaction(Database* aDatabase, - nsTArray>& aObjectStores, - TransactionBase::Mode aMode); + TransactionBase::Mode aMode, + nsTArray>& aObjectStores); // Reference counted. ~NormalTransaction() @@ -4133,9 +4177,11 @@ class OpenDatabaseOp::VersionChangeOp MOZ_FINAL uint64_t mPreviousVersion; private: - explicit VersionChangeOp(OpenDatabaseOp* aOpenDatabaseOp) + explicit + VersionChangeOp(OpenDatabaseOp* aOpenDatabaseOp) : TransactionDatabaseOperationBase( - aOpenDatabaseOp->mVersionChangeTransaction) + aOpenDatabaseOp->mVersionChangeTransaction, + aOpenDatabaseOp->LoggingSerialNumber()) , mOpenDatabaseOp(aOpenDatabaseOp) , mRequestedVersion(aOpenDatabaseOp->mRequestedVersion) , mPreviousVersion(aOpenDatabaseOp->mMetadata->mCommonMetadata.version()) @@ -4214,8 +4260,11 @@ class DeleteDatabaseOp::VersionChangeOp MOZ_FINAL nsRefPtr mDeleteDatabaseOp; private: - explicit VersionChangeOp(DeleteDatabaseOp* aDeleteDatabaseOp) - : mDeleteDatabaseOp(aDeleteDatabaseOp) + explicit + VersionChangeOp(DeleteDatabaseOp* aDeleteDatabaseOp) + : DatabaseOperationBase(aDeleteDatabaseOp->BackgroundChildLoggingId(), + aDeleteDatabaseOp->LoggingSerialNumber()) + , mDeleteDatabaseOp(aDeleteDatabaseOp) { MOZ_ASSERT(aDeleteDatabaseOp); MOZ_ASSERT(!aDeleteDatabaseOp->mDatabaseDirectoryPath.IsEmpty()); @@ -4991,7 +5040,7 @@ private: * Other class declarations ******************************************************************************/ -struct DatabaseActorInfo +struct DatabaseActorInfo MOZ_FINAL { friend class nsAutoPtr; @@ -5021,6 +5070,60 @@ private: } }; +class DatabaseLoggingInfo MOZ_FINAL +{ +#ifdef DEBUG + // Just for potential warnings. + friend class Factory; +#endif + + LoggingInfo mLoggingInfo; + +public: + DatabaseLoggingInfo(const LoggingInfo& aLoggingInfo) + : mLoggingInfo(aLoggingInfo) + { + AssertIsOnBackgroundThread(); + } + + const nsID& + Id() const + { + AssertIsOnBackgroundThread(); + + return mLoggingInfo.backgroundChildLoggingId(); + } + + int64_t + NextTransactionSN(IDBTransaction::Mode aMode) + { + AssertIsOnBackgroundThread(); + MOZ_ASSERT(mLoggingInfo.nextTransactionSerialNumber() < INT64_MAX); + MOZ_ASSERT(mLoggingInfo.nextVersionChangeTransactionSerialNumber() > + INT64_MIN); + + if (aMode == IDBTransaction::VERSION_CHANGE) { + return mLoggingInfo.nextVersionChangeTransactionSerialNumber()--; + } + + return mLoggingInfo.nextTransactionSerialNumber()++; + } + + uint64_t + NextRequestSN() + { + AssertIsOnBackgroundThread(); + MOZ_ASSERT(mLoggingInfo.nextRequestSerialNumber() < UINT64_MAX); + + return mLoggingInfo.nextRequestSerialNumber()++; + } + + NS_INLINE_DECL_REFCOUNTING(DatabaseLoggingInfo) + +private: + ~DatabaseLoggingInfo(); +}; + class NonMainThreadHackBlobImpl MOZ_FINAL : public FileImplFile { @@ -5524,6 +5627,11 @@ StaticRefPtr gStartTransactionRunnable; StaticRefPtr gTransactionThreadPool; +typedef nsDataHashtable + DatabaseLoggingInfoHashtable; + +StaticAutoPtr gLoggingInfoHashtable; + #ifdef DEBUG StaticRefPtr gDEBUGThreadSlower; @@ -5537,7 +5645,7 @@ StaticRefPtr gDEBUGThreadSlower; ******************************************************************************/ PBackgroundIDBFactoryParent* -AllocPBackgroundIDBFactoryParent() +AllocPBackgroundIDBFactoryParent(const LoggingInfo& aLoggingInfo) { AssertIsOnBackgroundThread(); @@ -5545,12 +5653,15 @@ AllocPBackgroundIDBFactoryParent() return nullptr; } - nsRefPtr actor = Factory::Create(); + nsRefPtr actor = Factory::Create(aLoggingInfo); + MOZ_ASSERT(actor); + return actor.forget().take(); } bool -RecvPBackgroundIDBFactoryConstructor(PBackgroundIDBFactoryParent* aActor) +RecvPBackgroundIDBFactoryConstructor(PBackgroundIDBFactoryParent* aActor, + const LoggingInfo& /* aLoggingInfo */) { AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); @@ -5727,14 +5838,29 @@ FullDatabaseMetadata::Duplicate() const return newMetadata.forget(); } +DatabaseLoggingInfo::~DatabaseLoggingInfo() +{ + AssertIsOnBackgroundThread(); + + if (gLoggingInfoHashtable) { + const nsID& backgroundChildLoggingId = + mLoggingInfo.backgroundChildLoggingId(); + + MOZ_ASSERT(gLoggingInfoHashtable->Get(backgroundChildLoggingId) == this); + + gLoggingInfoHashtable->Remove(backgroundChildLoggingId); + } +} + /******************************************************************************* * Factory ******************************************************************************/ uint64_t Factory::sFactoryInstanceCount = 0; -Factory::Factory() - : mActorDestroyed(false) +Factory::Factory(already_AddRefed aLoggingInfo) + : mLoggingInfo(Move(aLoggingInfo)) + , mActorDestroyed(false) { AssertIsOnBackgroundThread(); MOZ_ASSERT(!QuotaClient::IsShuttingDownOnNonMainThread()); @@ -5747,7 +5873,7 @@ Factory::~Factory() // static already_AddRefed -Factory::Create() +Factory::Create(const LoggingInfo& aLoggingInfo) { AssertIsOnBackgroundThread(); MOZ_ASSERT(!QuotaClient::IsShuttingDownOnNonMainThread()); @@ -5770,6 +5896,9 @@ Factory::Create() MOZ_ASSERT(!gStartTransactionRunnable); gStartTransactionRunnable = new nsRunnable(); + MOZ_ASSERT(!gLoggingInfoHashtable); + gLoggingInfoHashtable = new DatabaseLoggingInfoHashtable(); + #ifdef DEBUG if (kDEBUGThreadPriority != nsISupportsPriority::PRIORITY_NORMAL) { NS_WARNING("PBackground thread debugging enabled, priority has been " @@ -5795,7 +5924,29 @@ Factory::Create() #endif // DEBUG } - nsRefPtr actor = new Factory(); + nsRefPtr loggingInfo = + gLoggingInfoHashtable->Get(aLoggingInfo.backgroundChildLoggingId()); + if (loggingInfo) { + MOZ_ASSERT(aLoggingInfo.backgroundChildLoggingId() == loggingInfo->Id()); +#if !DISABLE_ASSERTS_FOR_FUZZING + NS_WARN_IF_FALSE(aLoggingInfo.nextTransactionSerialNumber() == + loggingInfo->mLoggingInfo.nextTransactionSerialNumber(), + "NextTransactionSerialNumber doesn't match!"); + NS_WARN_IF_FALSE(aLoggingInfo.nextVersionChangeTransactionSerialNumber() == + loggingInfo->mLoggingInfo. + nextVersionChangeTransactionSerialNumber(), + "NextVersionChangeTransactionSerialNumber doesn't match!"); + NS_WARN_IF_FALSE(aLoggingInfo.nextRequestSerialNumber() == + loggingInfo->mLoggingInfo.nextRequestSerialNumber(), + "NextRequestSerialNumber doesn't match!"); +#endif // !DISABLE_ASSERTS_FOR_FUZZING + } else { + loggingInfo = new DatabaseLoggingInfo(aLoggingInfo); + gLoggingInfoHashtable->Put(aLoggingInfo.backgroundChildLoggingId(), + loggingInfo); + } + + nsRefPtr actor = new Factory(loggingInfo.forget()); sFactoryInstanceCount++; @@ -5812,6 +5963,9 @@ Factory::ActorDestroy(ActorDestroyReason aWhy) // Clean up if there are no more instances. if (!(--sFactoryInstanceCount)) { + MOZ_ASSERT(gLoggingInfoHashtable); + gLoggingInfoHashtable = nullptr; + MOZ_ASSERT(gStartTransactionRunnable); gStartTransactionRunnable = nullptr; @@ -5853,6 +6007,16 @@ Factory::RecvDeleteMe() return PBackgroundIDBFactoryParent::Send__delete__(this); } +bool +Factory::RecvIncrementLoggingRequestSerialNumber() +{ + AssertIsOnBackgroundThread(); + MOZ_ASSERT(mLoggingInfo); + + mLoggingInfo->NextRequestSN(); + return true; +} + PBackgroundIDBFactoryRequestParent* Factory::AllocPBackgroundIDBFactoryRequestParent( const FactoryRequestParams& aParams) @@ -6077,7 +6241,7 @@ Database::Invalidate() mInvalidated = true; - if (!mActorDestroyed) { + if (mActorWasAlive && !mActorDestroyed) { unused << SendInvalidate(); } @@ -6329,6 +6493,15 @@ Database::AllocPBackgroundIDBTransactionParent( for (uint32_t nameIndex = 0; nameIndex < nameCount; nameIndex++) { const nsString& name = aObjectStoreNames[nameIndex]; + + if (nameIndex) { + // Make sure that this name is sorted properly and not a duplicate. + if (NS_WARN_IF(name <= aObjectStoreNames[nameIndex - 1])) { + ASSERT_UNLESS_FUZZING(); + return nullptr; + } + } + const uint32_t oldLength = fallibleObjectStores.Length(); Closure closure(name, fallibleObjectStores); @@ -6343,7 +6516,7 @@ Database::AllocPBackgroundIDBTransactionParent( infallibleObjectStores.SwapElements(fallibleObjectStores); nsRefPtr transaction = - new NormalTransaction(this, infallibleObjectStores, aMode); + new NormalTransaction(this, aMode, infallibleObjectStores); MOZ_ASSERT(infallibleObjectStores.IsEmpty()); @@ -6372,13 +6545,13 @@ Database::RecvPBackgroundIDBTransactionConstructor( auto* transaction = static_cast(aActor); // Add a placeholder for this transaction immediately. - gTransactionThreadPool->Dispatch(transaction->TransactionId(), - mMetadata->mDatabaseId, - aObjectStoreNames, - aMode, - gStartTransactionRunnable, - /* aFinish */ false, - /* aFinishCallback */ nullptr); + gTransactionThreadPool->Start(transaction->TransactionId(), + mMetadata->mDatabaseId, + aObjectStoreNames, + aMode, + GetLoggingInfo()->Id(), + transaction->LoggingSerialNumber(), + gStartTransactionRunnable); transaction->SetActive(); @@ -6472,11 +6645,11 @@ Database::RecvClose() * TransactionBase ******************************************************************************/ -TransactionBase::TransactionBase(Database* aDatabase, - Mode aMode) +TransactionBase::TransactionBase(Database* aDatabase, Mode aMode) : mDatabase(aDatabase) , mTransactionId(gTransactionThreadPool->NextTransactionId()) , mDatabaseId(aDatabase->Id()) + , mLoggingSerialNumber(aDatabase->GetLoggingInfo()->NextTransactionSN(aMode)) , mActiveRequestCount(0) , mInvalidatedOnAnyThread(false) , mMode(aMode) @@ -6492,6 +6665,8 @@ TransactionBase::TransactionBase(Database* aDatabase, { AssertIsOnBackgroundThread(); MOZ_ASSERT(aDatabase); + MOZ_ASSERT(mTransactionId); + MOZ_ASSERT(mLoggingSerialNumber); } TransactionBase::~TransactionBase() @@ -7621,8 +7796,8 @@ TransactionBase::ReleaseBackgroundThreadObjects() NormalTransaction::NormalTransaction( Database* aDatabase, - nsTArray>& aObjectStores, - TransactionBase::Mode aMode) + TransactionBase::Mode aMode, + nsTArray>& aObjectStores) : TransactionBase(aDatabase, aMode) { AssertIsOnBackgroundThread(); @@ -9919,8 +10094,6 @@ DatabaseOfflineStorage::Invalidate() NS_IMPL_ISUPPORTS(CompressDataBlobsFunction, mozIStorageFunction) NS_IMPL_ISUPPORTS(EncodeKeysFunction, mozIStorageFunction) -uint64_t DatabaseOperationBase::sNextSerialNumber = 0; - // static void DatabaseOperationBase::GetBindingClauseForKeyRange( @@ -10329,7 +10502,9 @@ FactoryOp::FactoryOp(Factory* aFactory, already_AddRefed aContentParent, const CommonFactoryRequestParams& aCommonParams, bool aDeleting) - : mFactory(aFactory) + : DatabaseOperationBase(aFactory->GetLoggingInfo()->Id(), + aFactory->GetLoggingInfo()->NextRequestSN()) + , mFactory(aFactory) , mContentParent(Move(aContentParent)) , mCommonParams(aCommonParams) , mState(State_Initial) @@ -11076,7 +11251,7 @@ OpenDatabaseOp::DoDatabaseWork() MOZ_ASSERT(mState == State_DatabaseWorkOpen); PROFILER_LABEL("IndexedDB", - "OpenDatabaseHelper::DoDatabaseWork", + "OpenDatabaseOp::DoDatabaseWork", js::ProfileEntry::Category::STORAGE); if (NS_WARN_IF(QuotaClient::IsShuttingDownOnNonMainThread()) || @@ -11649,6 +11824,8 @@ OpenDatabaseOp::DispatchToWorkThread() AssertIsOnOwningThread(); MOZ_ASSERT(mState == State_WaitingForTransactionsToComplete); MOZ_ASSERT(mVersionChangeTransaction); + MOZ_ASSERT(mVersionChangeTransaction->GetMode() == + IDBTransaction::VERSION_CHANGE); MOZ_ASSERT(mMaybeBlockedDatabases.IsEmpty()); if (IsActorDestroyed()) { @@ -11661,15 +11838,20 @@ OpenDatabaseOp::DispatchToWorkThread() // Intentionally empty. nsTArray objectStoreNames; + const int64_t loggingSerialNumber = + mVersionChangeTransaction->LoggingSerialNumber(); + const nsID& backgroundChildLoggingId = + mVersionChangeTransaction->GetLoggingInfo()->Id(); + nsRefPtr versionChangeOp = new VersionChangeOp(this); - gTransactionThreadPool->Dispatch(mVersionChangeTransaction->TransactionId(), - mVersionChangeTransaction->DatabaseId(), - objectStoreNames, - mVersionChangeTransaction->GetMode(), - versionChangeOp, - /* aFinish */ false, - /* aFinishCallback */ nullptr); + gTransactionThreadPool->Start(mVersionChangeTransaction->TransactionId(), + mVersionChangeTransaction->DatabaseId(), + objectStoreNames, + mVersionChangeTransaction->GetMode(), + backgroundChildLoggingId, + loggingSerialNumber, + versionChangeOp); mVersionChangeTransaction->SetActive(); @@ -12109,7 +12291,7 @@ VersionChangeOp::DoDatabaseWork(TransactionBase* aTransaction) } PROFILER_LABEL("IndexedDB", - "VersionChangeOp::DoDatabaseWork", + "OpenDatabaseOp::VersionChangeOp::DoDatabaseWork", js::ProfileEntry::Category::STORAGE); mozIStorageConnection* connection = aTransaction->Connection(); @@ -12797,10 +12979,27 @@ VersionChangeOp::Run() TransactionDatabaseOperationBase::TransactionDatabaseOperationBase( TransactionBase* aTransaction) - : mTransaction(aTransaction) + : DatabaseOperationBase(aTransaction->GetLoggingInfo()->Id(), + aTransaction->GetLoggingInfo()->NextRequestSN()) + , mTransaction(aTransaction) + , mTransactionLoggingSerialNumber(aTransaction->LoggingSerialNumber()) , mTransactionIsAborted(aTransaction->IsAborted()) { MOZ_ASSERT(aTransaction); + MOZ_ASSERT(LoggingSerialNumber()); +} + +TransactionDatabaseOperationBase::TransactionDatabaseOperationBase( + TransactionBase* aTransaction, + uint64_t aLoggingSerialNumber) + : DatabaseOperationBase(aTransaction->GetLoggingInfo()->Id(), + aLoggingSerialNumber) + , mTransaction(aTransaction) + , mTransactionLoggingSerialNumber(aTransaction->LoggingSerialNumber()) + , mTransactionIsAborted(aTransaction->IsAborted()) +{ + MOZ_ASSERT(aTransaction); + MOZ_ASSERT(LoggingSerialNumber()); } TransactionDatabaseOperationBase::~TransactionDatabaseOperationBase() @@ -12842,6 +13041,10 @@ TransactionDatabaseOperationBase::RunOnTransactionThread() MOZ_ASSERT(mTransaction); MOZ_ASSERT(NS_SUCCEEDED(mResultCode)); + PROFILER_LABEL("IndexedDB", + "TransactionDatabaseOperationBase::RunOnTransactionThread", + js::ProfileEntry::Category::STORAGE); + // There are several cases where we don't actually have to to any work here. if (mTransactionIsAborted) { @@ -12868,7 +13071,22 @@ TransactionDatabaseOperationBase::RunOnTransactionThread() if (NS_WARN_IF(NS_FAILED(rv))) { mResultCode = rv; } else { + IDB_LOG_MARK("IndexedDB %s: Parent Transaction[%lld] Request[%llu]: " + "Beginning database work", + "IndexedDB %s: P T[%lld] R[%llu]: DB Start", + IDB_LOG_ID_STRING(mBackgroundChildLoggingId), + mTransactionLoggingSerialNumber, + mLoggingSerialNumber); + rv = DoDatabaseWork(mTransaction); + + IDB_LOG_MARK("IndexedDB %s: Parent Transaction[%lld] Request[%llu]: " + "Finished database work", + "IndexedDB %s: P T[%lld] R[%llu]: DB End", + IDB_LOG_ID_STRING(mBackgroundChildLoggingId), + mTransactionLoggingSerialNumber, + mLoggingSerialNumber); + if (NS_FAILED(rv)) { mResultCode = rv; } @@ -12950,6 +13168,18 @@ TransactionDatabaseOperationBase::Run() return NS_OK; } +TransactionBase:: + +CommitOp::CommitOp(TransactionBase* aTransaction, nsresult aResultCode) + : DatabaseOperationBase(aTransaction->GetLoggingInfo()->Id(), + aTransaction->GetLoggingInfo()->NextRequestSN()) + , mTransaction(aTransaction) + , mResultCode(aResultCode) +{ + MOZ_ASSERT(aTransaction); + MOZ_ASSERT(LoggingSerialNumber()); +} + nsresult TransactionBase:: CommitOp::WriteAutoIncrementCounts() @@ -13055,6 +13285,13 @@ CommitOp::Run() AssertIsOnTransactionThread(); + IDB_LOG_MARK("IndexedDB %s: Parent Transaction[%lld] Request[%llu]: " + "Beginning database work", + "IndexedDB %s: P T[%lld] R[%llu]: DB Start", + IDB_LOG_ID_STRING(mBackgroundChildLoggingId), + mTransaction->LoggingSerialNumber(), + mLoggingSerialNumber); + if (NS_SUCCEEDED(mResultCode) && mTransaction->mUpdateFileRefcountFunction) { mResultCode = mTransaction-> mUpdateFileRefcountFunction->WillCommit(connection); @@ -13095,6 +13332,13 @@ CommitOp::Run() mTransaction->ReleaseTransactionThreadObjects(); + IDB_LOG_MARK("IndexedDB %s: Parent Transaction[%lld] Request[%llu]: " + "Finished database work", + "IndexedDB %s: P T[%lld] R[%llu]: DB End", + IDB_LOG_ID_STRING(mBackgroundChildLoggingId), + mTransaction->LoggingSerialNumber(), + mLoggingSerialNumber); + return NS_OK; } @@ -13121,13 +13365,14 @@ CommitOp::TransactionFinishedAfterUnblock() AssertIsOnBackgroundThread(); MOZ_ASSERT(mTransaction); - PROFILER_LABEL("IndexedDB", - "CommitOp::TransactionFinishedAfterUnblock", - js::ProfileEntry::Category::STORAGE); - - IDB_PROFILER_MARK("IndexedDB Transaction %llu: Complete (rv = %lu)", - "IDBTransaction[%llu] MT Complete", - mTransaction->TransactionId(), mResultCode); + if (!mTransaction->IsActorDestroyed()) { + IDB_LOG_MARK("IndexedDB %s: Parent Transaction[%lld]: " + "Finished with result 0x%x", + "IndexedDB %s: P T[%lld]: Transaction finished (0x%x)", + IDB_LOG_ID_STRING(mTransaction->GetLoggingInfo()->Id()), + mTransaction->LoggingSerialNumber(), + mResultCode); + } mTransaction->ReleaseBackgroundThreadObjects(); @@ -16604,6 +16849,10 @@ OpenOp::DoDatabaseWork(TransactionBase* aTransaction) MOZ_ASSERT(mCursor->mKey.IsUnset()); MOZ_ASSERT(mCursor->mRangeKey.IsUnset()); + PROFILER_LABEL("IndexedDB", + "Cursor::OpenOp::DoDatabaseWork", + js::ProfileEntry::Category::STORAGE); + nsresult rv; switch (mCursor->mType) { diff --git a/dom/indexedDB/ActorsParent.h b/dom/indexedDB/ActorsParent.h index 75f1417f96d..ad42be4ee93 100644 --- a/dom/indexedDB/ActorsParent.h +++ b/dom/indexedDB/ActorsParent.h @@ -7,6 +7,7 @@ template struct already_AddRefed; class nsCString; +struct nsID; class nsIPrincipal; class nsPIDOMWindow; @@ -23,14 +24,16 @@ class Client; namespace indexedDB { +class LoggingInfo; class PBackgroundIDBFactoryParent; class PIndexedDBPermissionRequestParent; PBackgroundIDBFactoryParent* -AllocPBackgroundIDBFactoryParent(); +AllocPBackgroundIDBFactoryParent(const LoggingInfo& aLoggingInfo); bool -RecvPBackgroundIDBFactoryConstructor(PBackgroundIDBFactoryParent* aActor); +RecvPBackgroundIDBFactoryConstructor(PBackgroundIDBFactoryParent* aActor, + const LoggingInfo& aLoggingInfo); bool DeallocPBackgroundIDBFactoryParent(PBackgroundIDBFactoryParent* aActor); diff --git a/dom/indexedDB/IDBCursor.cpp b/dom/indexedDB/IDBCursor.cpp index e12af8154b7..6e9842607f3 100644 --- a/dom/indexedDB/IDBCursor.cpp +++ b/dom/indexedDB/IDBCursor.cpp @@ -426,36 +426,41 @@ IDBCursor::Continue(JSContext* aCx, } } + const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber(); + mRequest->SetLoggingSerialNumber(requestSerialNumber); + + if (mType == Type_ObjectStore || mType == Type_ObjectStoreKey) { + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).objectStore(%s)." + "cursor(%s).continue(%s)", + "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.continue()", + IDB_LOG_ID_STRING(), + mTransaction->LoggingSerialNumber(), + requestSerialNumber, + IDB_LOG_STRINGIFY(mTransaction->Database()), + IDB_LOG_STRINGIFY(mTransaction), + IDB_LOG_STRINGIFY(mSourceObjectStore), + IDB_LOG_STRINGIFY(mDirection), + IDB_LOG_STRINGIFY(key)); + } else { + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).objectStore(%s)." + "index(%s).cursor(%s).continue(%s)", + "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.continue()", + IDB_LOG_ID_STRING(), + mTransaction->LoggingSerialNumber(), + requestSerialNumber, + IDB_LOG_STRINGIFY(mTransaction->Database()), + IDB_LOG_STRINGIFY(mTransaction), + IDB_LOG_STRINGIFY(mSourceIndex->ObjectStore()), + IDB_LOG_STRINGIFY(mSourceIndex), + IDB_LOG_STRINGIFY(mDirection), + IDB_LOG_STRINGIFY(key)); + } + mBackgroundActor->SendContinueInternal(ContinueParams(key)); mContinueCalled = true; - -#ifdef IDB_PROFILER_USE_MARKS - if (mType == Type_ObjectStore || mType == Type_ObjectStoreKey) { - IDB_PROFILER_MARK("IndexedDB Request %llu: " - "database(%s).transaction(%s).objectStore(%s).cursor(%s)." - "continue(%s)", - "IDBRequest[%llu] MT IDBCursor.continue()", - Request()->GetSerialNumber(), - IDB_PROFILER_STRING(Transaction()->Database()), - IDB_PROFILER_STRING(Transaction()), - IDB_PROFILER_STRING(mSourceObjectStore), - IDB_PROFILER_STRING(mDirection), - key.IsUnset() ? "" : IDB_PROFILER_STRING(key)); - } else { - IDB_PROFILER_MARK("IndexedDB Request %llu: " - "database(%s).transaction(%s).objectStore(%s).index(%s)." - "cursor(%s).continue(%s)", - "IDBRequest[%llu] MT IDBCursor.continue()", - Request()->GetSerialNumber(), - IDB_PROFILER_STRING(Transaction()->Database()), - IDB_PROFILER_STRING(Transaction()), - IDB_PROFILER_STRING(mSourceIndex->ObjectStore()), - IDB_PROFILER_STRING(mSourceIndex), - IDB_PROFILER_STRING(mDirection), - key.IsUnset() ? "" : IDB_PROFILER_STRING(key)); - } -#endif } void @@ -478,36 +483,41 @@ IDBCursor::Advance(uint32_t aCount, ErrorResult &aRv) return; } + const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber(); + mRequest->SetLoggingSerialNumber(requestSerialNumber); + + if (mType == Type_ObjectStore || mType == Type_ObjectStoreKey) { + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).objectStore(%s)." + "cursor(%s).advance(%ld)", + "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.advance()", + IDB_LOG_ID_STRING(), + mTransaction->LoggingSerialNumber(), + requestSerialNumber, + IDB_LOG_STRINGIFY(mTransaction->Database()), + IDB_LOG_STRINGIFY(mTransaction), + IDB_LOG_STRINGIFY(mSourceObjectStore), + IDB_LOG_STRINGIFY(mDirection), + aCount); + } else { + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).objectStore(%s)." + "index(%s).cursor(%s).advance(%ld)", + "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.advance()", + IDB_LOG_ID_STRING(), + mTransaction->LoggingSerialNumber(), + requestSerialNumber, + IDB_LOG_STRINGIFY(mTransaction->Database()), + IDB_LOG_STRINGIFY(mTransaction), + IDB_LOG_STRINGIFY(mSourceIndex->ObjectStore()), + IDB_LOG_STRINGIFY(mSourceIndex), + IDB_LOG_STRINGIFY(mDirection), + aCount); + } + mBackgroundActor->SendContinueInternal(AdvanceParams(aCount)); mContinueCalled = true; - -#ifdef IDB_PROFILER_USE_MARKS - { - if (mType == Type_ObjectStore || mType == Type_ObjectStoreKey) { - IDB_PROFILER_MARK("IndexedDB Request %llu: " - "database(%s).transaction(%s).objectStore(%s)." - "cursor(%s).advance(%ld)", - "IDBRequest[%llu] MT IDBCursor.advance()", - Request()->GetSerialNumber(), - IDB_PROFILER_STRING(Transaction()->Database()), - IDB_PROFILER_STRING(Transaction()), - IDB_PROFILER_STRING(mSourceObjectStore), - IDB_PROFILER_STRING(mDirection), aCount); - } else { - IDB_PROFILER_MARK("IndexedDB Request %llu: " - "database(%s).transaction(%s).objectStore(%s)." - "index(%s).cursor(%s).advance(%ld)", - "IDBRequest[%llu] MT IDBCursor.advance()", - Request()->GetSerialNumber(), - IDB_PROFILER_STRING(Transaction()->Database()), - IDB_PROFILER_STRING(Transaction()), - IDB_PROFILER_STRING(mSourceIndex->ObjectStore()), - IDB_PROFILER_STRING(mSourceIndex), - IDB_PROFILER_STRING(mDirection), aCount); - } - } -#endif } already_AddRefed @@ -563,7 +573,12 @@ IDBCursor::Update(JSContext* aCx, JS::Handle aValue, return nullptr; } - request = objectStore->Put(aCx, aValue, JS::UndefinedHandleValue, aRv); + request = objectStore->AddOrPut(aCx, + aValue, + /* aKey */ JS::UndefinedHandleValue, + /* aOverwrite */ true, + /* aFromCursor */ true, + aRv); if (aRv.Failed()) { return nullptr; } @@ -575,7 +590,12 @@ IDBCursor::Update(JSContext* aCx, JS::Handle aValue, return nullptr; } - request = objectStore->Put(aCx, aValue, keyVal, aRv); + request = objectStore->AddOrPut(aCx, + aValue, + keyVal, + /* aOverwrite */ true, + /* aFromCursor */ true, + aRv); if (aRv.Failed()) { return nullptr; } @@ -583,37 +603,34 @@ IDBCursor::Update(JSContext* aCx, JS::Handle aValue, request->SetSource(this); -#ifdef IDB_PROFILER_USE_MARKS - { - uint64_t requestSerial = request->GetSerialNumber(); - if (mType == Type_ObjectStore) { - IDB_PROFILER_MARK("IndexedDB Request %llu: " - "database(%s).transaction(%s).objectStore(%s)." - "cursor(%s).update(%s)", - "IDBRequest[%llu] MT IDBCursor.update()", - requestSerial, - IDB_PROFILER_STRING(mTransaction->Database()), - IDB_PROFILER_STRING(mTransaction), - IDB_PROFILER_STRING(objectStore), - IDB_PROFILER_STRING(mDirection), - mObjectStore->HasValidKeyPath() ? "" : - IDB_PROFILER_STRING(primaryKey)); - } else { - IDB_PROFILER_MARK("IndexedDB Request %llu: " - "database(%s).transaction(%s).objectStore(%s)." - "index(%s).cursor(%s).update(%s)", - "IDBRequest[%llu] MT IDBCursor.update()", - requestSerial, - IDB_PROFILER_STRING(mTransaction->Database()), - IDB_PROFILER_STRING(mTransaction), - IDB_PROFILER_STRING(objectStore), - IDB_PROFILER_STRING(mSourceIndex), - IDB_PROFILER_STRING(mDirection), - mObjectStore->HasValidKeyPath() ? "" : - IDB_PROFILER_STRING(primaryKey)); - } + if (mType == Type_ObjectStore) { + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).objectStore(%s)." + "cursor(%s).update(%s)", + "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.update()", + IDB_LOG_ID_STRING(), + mTransaction->LoggingSerialNumber(), + request->LoggingSerialNumber(), + IDB_LOG_STRINGIFY(mTransaction->Database()), + IDB_LOG_STRINGIFY(mTransaction), + IDB_LOG_STRINGIFY(objectStore), + IDB_LOG_STRINGIFY(mDirection), + IDB_LOG_STRINGIFY(objectStore, primaryKey)); + } else { + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).objectStore(%s)." + "index(%s).cursor(%s).update(%s)", + "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.update()", + IDB_LOG_ID_STRING(), + mTransaction->LoggingSerialNumber(), + request->LoggingSerialNumber(), + IDB_LOG_STRINGIFY(mTransaction->Database()), + IDB_LOG_STRINGIFY(mTransaction), + IDB_LOG_STRINGIFY(objectStore), + IDB_LOG_STRINGIFY(mSourceIndex), + IDB_LOG_STRINGIFY(mDirection), + IDB_LOG_STRINGIFY(objectStore, primaryKey)); } -#endif return request.forget(); } @@ -658,44 +675,42 @@ IDBCursor::Delete(JSContext* aCx, ErrorResult& aRv) return nullptr; } - nsRefPtr request = objectStore->Delete(aCx, key, aRv); + nsRefPtr request = + objectStore->DeleteInternal(aCx, key, /* aFromCursor */ true, aRv); if (aRv.Failed()) { return nullptr; } request->SetSource(this); -#ifdef IDB_PROFILER_USE_MARKS - { - uint64_t requestSerial = request->GetSerialNumber(); - if (mType == Type_ObjectStore) { - IDB_PROFILER_MARK("IndexedDB Request %llu: " - "database(%s).transaction(%s).objectStore(%s)." - "cursor(%s).delete(%s)", - "IDBRequest[%llu] MT IDBCursor.delete()", - requestSerial, - IDB_PROFILER_STRING(mTransaction->Database()), - IDB_PROFILER_STRING(mTransaction), - IDB_PROFILER_STRING(objectStore), - IDB_PROFILER_STRING(mDirection), - mObjectStore->HasValidKeyPath() ? "" : - IDB_PROFILER_STRING(primaryKey)); - } else { - IDB_PROFILER_MARK("IndexedDB Request %llu: " - "database(%s).transaction(%s).objectStore(%s)." - "index(%s).cursor(%s).delete(%s)", - "IDBRequest[%llu] MT IDBCursor.delete()", - requestSerial, - IDB_PROFILER_STRING(mTransaction->Database()), - IDB_PROFILER_STRING(mTransaction), - IDB_PROFILER_STRING(objectStore), - IDB_PROFILER_STRING(mSourceIndex), - IDB_PROFILER_STRING(mDirection), - mObjectStore->HasValidKeyPath() ? "" : - IDB_PROFILER_STRING(primaryKey)); - } + if (mType == Type_ObjectStore) { + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).objectStore(%s)." + "cursor(%s).delete(%s)", + "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.delete()", + IDB_LOG_ID_STRING(), + mTransaction->LoggingSerialNumber(), + request->LoggingSerialNumber(), + IDB_LOG_STRINGIFY(mTransaction->Database()), + IDB_LOG_STRINGIFY(mTransaction), + IDB_LOG_STRINGIFY(objectStore), + IDB_LOG_STRINGIFY(mDirection), + IDB_LOG_STRINGIFY(objectStore, primaryKey)); + } else { + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).objectStore(%s)." + "index(%s).cursor(%s).delete(%s)", + "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.delete()", + IDB_LOG_ID_STRING(), + mTransaction->LoggingSerialNumber(), + request->LoggingSerialNumber(), + IDB_LOG_STRINGIFY(mTransaction->Database()), + IDB_LOG_STRINGIFY(mTransaction), + IDB_LOG_STRINGIFY(objectStore), + IDB_LOG_STRINGIFY(mSourceIndex), + IDB_LOG_STRINGIFY(mDirection), + IDB_LOG_STRINGIFY(objectStore, primaryKey)); } -#endif return request.forget(); } diff --git a/dom/indexedDB/IDBDatabase.cpp b/dom/indexedDB/IDBDatabase.cpp index 9c305c827c0..9cd86c7bc2a 100644 --- a/dom/indexedDB/IDBDatabase.cpp +++ b/dom/indexedDB/IDBDatabase.cpp @@ -506,12 +506,20 @@ IDBDatabase::CreateObjectStore( transaction->CreateObjectStore(*newSpec); MOZ_ASSERT(objectStore); - IDB_PROFILER_MARK("IndexedDB Pseudo-request: " - "database(%s).transaction(%s).createObjectStore(%s)", - "MT IDBDatabase.createObjectStore()", - IDB_PROFILER_STRING(this), - IDB_PROFILER_STRING(aTransaction), - IDB_PROFILER_STRING(objectStore)); + // Don't do this in the macro because we always need to increment the serial + // number to keep in sync with the parent. + const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber(); + + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).createObjectStore(%s)", + "IndexedDB %s: C T[%lld] R[%llu]: " + "IDBDatabase.createObjectStore()", + IDB_LOG_ID_STRING(), + transaction->LoggingSerialNumber(), + requestSerialNumber, + IDB_LOG_STRINGIFY(this), + IDB_LOG_STRINGIFY(transaction), + IDB_LOG_STRINGIFY(objectStore)); return objectStore.forget(); } @@ -559,12 +567,20 @@ IDBDatabase::DeleteObjectStore(const nsAString& aName, ErrorResult& aRv) return; } - IDB_PROFILER_MARK("IndexedDB Pseudo-request: " - "database(%s).transaction(%s).deleteObjectStore(\"%s\")", - "MT IDBDatabase.deleteObjectStore()", - IDB_PROFILER_STRING(this), - IDB_PROFILER_STRING(transaction), - NS_ConvertUTF16toUTF8(aName).get()); + // Don't do this in the macro because we always need to increment the serial + // number to keep in sync with the parent. + const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber(); + + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).deleteObjectStore(\"%s\")", + "IndexedDB %s: C T[%lld] R[%llu]: " + "IDBDatabase.deleteObjectStore()", + IDB_LOG_ID_STRING(), + transaction->LoggingSerialNumber(), + requestSerialNumber, + IDB_LOG_STRINGIFY(this), + IDB_LOG_STRINGIFY(transaction), + NS_ConvertUTF16toUTF8(aName).get()); } already_AddRefed @@ -669,6 +685,14 @@ IDBDatabase::Transaction(const Sequence& aStoreNames, BackgroundTransactionChild* actor = new BackgroundTransactionChild(transaction); + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld]: " + "database(%s).transaction(%s)", + "IndexedDB %s: C T[%lld]: IDBDatabase.transaction()", + IDB_LOG_ID_STRING(), + transaction->LoggingSerialNumber(), + IDB_LOG_STRINGIFY(this), + IDB_LOG_STRINGIFY(transaction)); + MOZ_ALWAYS_TRUE( mBackgroundActor->SendPBackgroundIDBTransactionConstructor(actor, sortedStoreNames, @@ -676,11 +700,6 @@ IDBDatabase::Transaction(const Sequence& aStoreNames, transaction->SetBackgroundActor(actor); - IDB_PROFILER_MARK("IndexedDB Transaction %llu: database(%s).transaction(%s)", - "IDBTransaction[%llu] MT Started", - transaction->GetSerialNumber(), IDB_PROFILER_STRING(this), - IDB_PROFILER_STRING(transaction)); - return transaction.forget(); } @@ -722,6 +741,8 @@ IDBDatabase::CreateMutableFile(const nsAString& aName, type = aType.Value(); } + mFactory->IncrementParentLoggingRequestSerialNumber(); + aRv = CreateFileHelper::CreateAndDispatch(this, request, aName, type); if (NS_WARN_IF(aRv.Failed())) { return nullptr; diff --git a/dom/indexedDB/IDBFactory.cpp b/dom/indexedDB/IDBFactory.cpp index be9fccb8041..2019b446f3c 100644 --- a/dom/indexedDB/IDBFactory.cpp +++ b/dom/indexedDB/IDBFactory.cpp @@ -6,6 +6,7 @@ #include "IDBFactory.h" +#include "BackgroundChildImpl.h" #include "IDBRequest.h" #include "IndexedDatabaseManager.h" #include "mozilla/ErrorResult.h" @@ -21,7 +22,9 @@ #include "nsIIPCBackgroundChildCreateCallback.h" #include "nsILoadContext.h" #include "nsIPrincipal.h" +#include "nsIUUIDGenerator.h" #include "nsIWebNavigation.h" +#include "nsServiceManagerUtils.h" #include "ProfilerHelpers.h" #include "ReportInternalError.h" @@ -76,10 +79,14 @@ class IDBFactory::BackgroundCreateCallback MOZ_FINAL : public nsIIPCBackgroundChildCreateCallback { nsRefPtr mFactory; + LoggingInfo mLoggingInfo; public: - explicit BackgroundCreateCallback(IDBFactory* aFactory) - : mFactory(aFactory) + explicit + BackgroundCreateCallback(IDBFactory* aFactory, + const LoggingInfo& aLoggingInfo) + : mFactory(aFactory) + , mLoggingInfo(aLoggingInfo) { MOZ_ASSERT(aFactory); } @@ -306,6 +313,15 @@ IDBFactory::SetBackgroundActor(BackgroundFactoryChild* aBackgroundActor) mBackgroundActor = aBackgroundActor; } +void +IDBFactory::IncrementParentLoggingRequestSerialNumber() +{ + AssertIsOnOwningThread(); + MOZ_ASSERT(mBackgroundActor); + + mBackgroundActor->SendIncrementLoggingRequestSerialNumber(); +} + already_AddRefed IDBFactory::Open(const nsAString& aName, uint64_t aVersion, @@ -501,27 +517,44 @@ IDBFactory::OpenInternal(nsIPrincipal* aPrincipal, params = OpenDatabaseRequestParams(commonParams); } - if (!mBackgroundActor) { - // If another consumer has already created a background actor for this - // thread then we can start this request immediately. - if (PBackgroundChild* bgActor = BackgroundChild::GetForCurrentThread()) { - nsresult rv = BackgroundActorCreated(bgActor); - if (NS_WARN_IF(NS_FAILED(rv))) { - IDB_REPORT_INTERNAL_ERR(); - aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - return nullptr; - } - MOZ_ASSERT(mBackgroundActor); - } else if (mPendingRequests.IsEmpty()) { - // We need to start the sequence to create a background actor for this - // thread. - nsRefPtr cb = - new BackgroundCreateCallback(this); - if (NS_WARN_IF(!BackgroundChild::GetOrCreateForCurrentThread(cb))) { - IDB_REPORT_INTERNAL_ERR(); - aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - return nullptr; + if (!mBackgroundActor && mPendingRequests.IsEmpty()) { + // We need to start the sequence to create a background actor for this + // thread. + BackgroundChildImpl::ThreadLocal* threadLocal = + BackgroundChildImpl::GetThreadLocalForCurrentThread(); + + nsAutoPtr newIDBThreadLocal; + ThreadLocal* idbThreadLocal; + + if (threadLocal && threadLocal->mIndexedDBThreadLocal) { + idbThreadLocal = threadLocal->mIndexedDBThreadLocal; + } else { + nsCOMPtr uuidGen = + do_GetService("@mozilla.org/uuid-generator;1"); + MOZ_ASSERT(uuidGen); + + nsID id; + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(uuidGen->GenerateUUIDInPlace(&id))); + + newIDBThreadLocal = idbThreadLocal = new ThreadLocal(id); + } + + nsRefPtr cb = + new BackgroundCreateCallback(this, idbThreadLocal->GetLoggingInfo()); + if (NS_WARN_IF(!BackgroundChild::GetOrCreateForCurrentThread(cb))) { + IDB_REPORT_INTERNAL_ERR(); + aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + return nullptr; + } + + if (newIDBThreadLocal) { + if (!threadLocal) { + threadLocal = BackgroundChildImpl::GetThreadLocalForCurrentThread(); } + MOZ_ASSERT(threadLocal); + MOZ_ASSERT(!threadLocal->mIndexedDBThreadLocal); + + threadLocal->mIndexedDBThreadLocal = newIDBThreadLocal.forget(); } } @@ -550,6 +583,23 @@ IDBFactory::OpenInternal(nsIPrincipal* aPrincipal, MOZ_ASSERT(request); + if (aDeleting) { + IDB_LOG_MARK("IndexedDB %s: Child Request[%llu]: " + "indexedDB.deleteDatabase(\"%s\")", + "IndexedDB %s: C R[%llu]: IDBFactory.deleteDatabase()", + IDB_LOG_ID_STRING(), + request->LoggingSerialNumber(), + NS_ConvertUTF16toUTF8(aName).get()); + } else { + IDB_LOG_MARK("IndexedDB %s: Child Request[%llu]: " + "indexedDB.open(\"%s\", %s)", + "IndexedDB %s: C R[%llu]: IDBFactory.open()", + IDB_LOG_ID_STRING(), + request->LoggingSerialNumber(), + NS_ConvertUTF16toUTF8(aName).get(), + IDB_LOG_STRINGIFY(aVersion)); + } + // If we already have a background actor then we can start this request now. if (mBackgroundActor) { nsresult rv = InitiateRequest(request, params); @@ -562,27 +612,12 @@ IDBFactory::OpenInternal(nsIPrincipal* aPrincipal, mPendingRequests.AppendElement(new PendingRequestInfo(request, params)); } -#ifdef IDB_PROFILER_USE_MARKS - { - NS_ConvertUTF16toUTF8 profilerName(aName); - if (aDeleting) { - IDB_PROFILER_MARK("IndexedDB Request %llu: deleteDatabase(\"%s\")", - "MT IDBFactory.deleteDatabase()", - request->GetSerialNumber(), profilerName.get()); - } else { - IDB_PROFILER_MARK("IndexedDB Request %llu: open(\"%s\", %lld)", - "MT IDBFactory.open()", - request->GetSerialNumber(), profilerName.get(), - aVersion); - } - } -#endif - return request.forget(); } nsresult -IDBFactory::BackgroundActorCreated(PBackgroundChild* aBackgroundActor) +IDBFactory::BackgroundActorCreated(PBackgroundChild* aBackgroundActor, + const LoggingInfo& aLoggingInfo) { MOZ_ASSERT(aBackgroundActor); MOZ_ASSERT(!mBackgroundActor); @@ -595,7 +630,8 @@ IDBFactory::BackgroundActorCreated(PBackgroundChild* aBackgroundActor) mBackgroundActor = static_cast( - aBackgroundActor->SendPBackgroundIDBFactoryConstructor(actor)); + aBackgroundActor->SendPBackgroundIDBFactoryConstructor(actor, + aLoggingInfo)); } if (NS_WARN_IF(!mBackgroundActor)) { @@ -735,7 +771,7 @@ IDBFactory::BackgroundCreateCallback::ActorCreated(PBackgroundChild* aActor) nsRefPtr factory; mFactory.swap(factory); - factory->BackgroundActorCreated(aActor); + factory->BackgroundActorCreated(aActor, mLoggingInfo); } void diff --git a/dom/indexedDB/IDBFactory.h b/dom/indexedDB/IDBFactory.h index b88d055195b..d4f15ffe3f1 100644 --- a/dom/indexedDB/IDBFactory.h +++ b/dom/indexedDB/IDBFactory.h @@ -42,6 +42,7 @@ namespace indexedDB { class BackgroundFactoryChild; class FactoryRequestParams; class IDBOpenDBRequest; +class LoggingInfo; class IDBFactory MOZ_FINAL : public nsISupports @@ -112,6 +113,9 @@ public: mBackgroundActor = nullptr; } + void + IncrementParentLoggingRequestSerialNumber(); + nsPIDOMWindow* GetParentObject() const { @@ -208,7 +212,8 @@ private: ErrorResult& aRv); nsresult - BackgroundActorCreated(PBackgroundChild* aBackgroundActor); + BackgroundActorCreated(PBackgroundChild* aBackgroundActor, + const LoggingInfo& aLoggingInfo); void BackgroundActorFailed(); diff --git a/dom/indexedDB/IDBIndex.cpp b/dom/indexedDB/IDBIndex.cpp index a8a3e74bc67..ff4af101379 100644 --- a/dom/indexedDB/IDBIndex.cpp +++ b/dom/indexedDB/IDBIndex.cpp @@ -264,33 +264,38 @@ IDBIndex::GetInternal(bool aKeyOnly, nsRefPtr request = GenerateRequest(this); MOZ_ASSERT(request); + if (aKeyOnly) { + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).objectStore(%s).index(%s)." + "getKey(%s)", + "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.getKey()", + IDB_LOG_ID_STRING(), + transaction->LoggingSerialNumber(), + request->LoggingSerialNumber(), + IDB_LOG_STRINGIFY(transaction->Database()), + IDB_LOG_STRINGIFY(transaction), + IDB_LOG_STRINGIFY(mObjectStore), + IDB_LOG_STRINGIFY(this), + IDB_LOG_STRINGIFY(keyRange)); + } else { + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).objectStore(%s).index(%s)." + "get(%s)", + "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.get()", + IDB_LOG_ID_STRING(), + transaction->LoggingSerialNumber(), + request->LoggingSerialNumber(), + IDB_LOG_STRINGIFY(transaction->Database()), + IDB_LOG_STRINGIFY(transaction), + IDB_LOG_STRINGIFY(mObjectStore), + IDB_LOG_STRINGIFY(this), + IDB_LOG_STRINGIFY(keyRange)); + } + BackgroundRequestChild* actor = new BackgroundRequestChild(request); transaction->StartRequest(actor, params); - if (aKeyOnly) { - IDB_PROFILER_MARK("IndexedDB Request %llu: " - "database(%s).transaction(%s).objectStore(%s).index(%s)." - "getKey(%s)", - "IDBRequest[%llu] MT IDBIndex.getKey()", - request->GetSerialNumber(), - IDB_PROFILER_STRING(transaction->Database()), - IDB_PROFILER_STRING(transaction), - IDB_PROFILER_STRING(mObjectStore), - IDB_PROFILER_STRING(this), - IDB_PROFILER_STRING(aKey)); - } else { - IDB_PROFILER_MARK("IndexedDB Request %llu: " - "database(%s).transaction(%s).objectStore(%s).index(%s)." - "get(%s)", - "IDBRequest[%llu] MT IDBIndex.get()", - request->GetSerialNumber(), - IDB_PROFILER_STRING(transaction->Database()), - IDB_PROFILER_STRING(transaction), - IDB_PROFILER_STRING(mObjectStore), - IDB_PROFILER_STRING(this), - IDB_PROFILER_STRING(aKey)); - } return request.forget(); } @@ -340,36 +345,40 @@ IDBIndex::GetAllInternal(bool aKeysOnly, nsRefPtr request = GenerateRequest(this); MOZ_ASSERT(request); + if (aKeysOnly) { + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).objectStore(%s).index(%s)." + "getAllKeys(%s, %s)", + "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.getAllKeys()", + IDB_LOG_ID_STRING(), + transaction->LoggingSerialNumber(), + request->LoggingSerialNumber(), + IDB_LOG_STRINGIFY(transaction->Database()), + IDB_LOG_STRINGIFY(transaction), + IDB_LOG_STRINGIFY(mObjectStore), + IDB_LOG_STRINGIFY(this), + IDB_LOG_STRINGIFY(keyRange), + IDB_LOG_STRINGIFY(aLimit)); + } else { + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).objectStore(%s).index(%s)." + "getAll(%s, %s)", + "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.getAll()", + IDB_LOG_ID_STRING(), + transaction->LoggingSerialNumber(), + request->LoggingSerialNumber(), + IDB_LOG_STRINGIFY(transaction->Database()), + IDB_LOG_STRINGIFY(transaction), + IDB_LOG_STRINGIFY(mObjectStore), + IDB_LOG_STRINGIFY(this), + IDB_LOG_STRINGIFY(keyRange), + IDB_LOG_STRINGIFY(aLimit)); + } + BackgroundRequestChild* actor = new BackgroundRequestChild(request); transaction->StartRequest(actor, params); - if (aKeysOnly) { - IDB_PROFILER_MARK("IndexedDB Request %llu: " - "database(%s).transaction(%s).objectStore(%s).index(%s)." - "getAllKeys(%s, %lu)", - "IDBRequest[%llu] MT IDBIndex.getAllKeys()", - request->GetSerialNumber(), - IDB_PROFILER_STRING(transaction->Database()), - IDB_PROFILER_STRING(transaction), - IDB_PROFILER_STRING(mObjectStore), - IDB_PROFILER_STRING(this), - IDB_PROFILER_STRING(aKeyRange), - aLimit); - } else { - IDB_PROFILER_MARK("IndexedDB Request %llu: " - "database(%s).transaction(%s).objectStore(%s).index(%s)." - "getAll(%s, %lu)", - "IDBRequest[%llu] MT IDBIndex.getAll()", - request->GetSerialNumber(), - IDB_PROFILER_STRING(transaction->Database()), - IDB_PROFILER_STRING(transaction), - IDB_PROFILER_STRING(mObjectStore), - IDB_PROFILER_STRING(this), - IDB_PROFILER_STRING(aKeyRange), - aLimit); - } - return request.forget(); } @@ -432,6 +441,37 @@ IDBIndex::OpenCursorInternal(bool aKeysOnly, nsRefPtr request = GenerateRequest(this); MOZ_ASSERT(request); + if (aKeysOnly) { + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).objectStore(%s).index(%s)." + "openKeyCursor(%s, %s)", + "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.openKeyCursor()", + IDB_LOG_ID_STRING(), + transaction->LoggingSerialNumber(), + request->LoggingSerialNumber(), + IDB_LOG_STRINGIFY(transaction->Database()), + IDB_LOG_STRINGIFY(transaction), + IDB_LOG_STRINGIFY(mObjectStore), + IDB_LOG_STRINGIFY(this), + IDB_LOG_STRINGIFY(keyRange), + IDB_LOG_STRINGIFY(direction)); + } else { + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).objectStore(%s).index(%s)." + "openCursor(%s, %s)", + "IndexedDB %s: C T[%lld] R[%llu]: " + "IDBObjectStore.openKeyCursor()", + IDB_LOG_ID_STRING(), + transaction->LoggingSerialNumber(), + request->LoggingSerialNumber(), + IDB_LOG_STRINGIFY(transaction->Database()), + IDB_LOG_STRINGIFY(transaction), + IDB_LOG_STRINGIFY(mObjectStore), + IDB_LOG_STRINGIFY(this), + IDB_LOG_STRINGIFY(keyRange), + IDB_LOG_STRINGIFY(direction)); + } + BackgroundCursorChild* actor = new BackgroundCursorChild(request, this, direction); @@ -474,21 +514,23 @@ IDBIndex::Count(JSContext* aCx, nsRefPtr request = GenerateRequest(this); MOZ_ASSERT(request); + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).objectStore(%s).index(%s)." + "count(%s)", + "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.count()", + IDB_LOG_ID_STRING(), + transaction->LoggingSerialNumber(), + request->LoggingSerialNumber(), + IDB_LOG_STRINGIFY(transaction->Database()), + IDB_LOG_STRINGIFY(transaction), + IDB_LOG_STRINGIFY(mObjectStore), + IDB_LOG_STRINGIFY(this), + IDB_LOG_STRINGIFY(keyRange)); + BackgroundRequestChild* actor = new BackgroundRequestChild(request); transaction->StartRequest(actor, params); - IDB_PROFILER_MARK("IndexedDB Request %llu: " - "database(%s).transaction(%s).objectStore(%s).index(%s)." - "count(%s)", - "IDBRequest[%llu] MT IDBObjectStore.count()", - request->GetSerialNumber(), - IDB_PROFILER_STRING(transaction->Database()), - IDB_PROFILER_STRING(transaction), - IDB_PROFILER_STRING(mObjectStore), - IDB_PROFILER_STRING(this), - IDB_PROFILER_STRING(aKey)); - return request.forget(); } diff --git a/dom/indexedDB/IDBObjectStore.cpp b/dom/indexedDB/IDBObjectStore.cpp index 5d5410f9cfc..f8e35c10100 100644 --- a/dom/indexedDB/IDBObjectStore.cpp +++ b/dom/indexedDB/IDBObjectStore.cpp @@ -1143,10 +1143,12 @@ IDBObjectStore::AddOrPut(JSContext* aCx, JS::Handle aValue, JS::Handle aKey, bool aOverwrite, + bool aFromCursor, ErrorResult& aRv) { AssertIsOnOwningThread(); MOZ_ASSERT(aCx); + MOZ_ASSERT_IF(aFromCursor, aOverwrite); if (!mTransaction->IsOpen()) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR); @@ -1249,6 +1251,32 @@ IDBObjectStore::AddOrPut(JSContext* aCx, nsRefPtr request = GenerateRequest(this); MOZ_ASSERT(request); + if (!aFromCursor) { + if (aOverwrite) { + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).objectStore(%s).put(%s)", + "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.put()", + IDB_LOG_ID_STRING(), + mTransaction->LoggingSerialNumber(), + request->LoggingSerialNumber(), + IDB_LOG_STRINGIFY(mTransaction->Database()), + IDB_LOG_STRINGIFY(mTransaction), + IDB_LOG_STRINGIFY(this), + IDB_LOG_STRINGIFY(key)); + } else { + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).objectStore(%s).add(%s)", + "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.add()", + IDB_LOG_ID_STRING(), + mTransaction->LoggingSerialNumber(), + request->LoggingSerialNumber(), + IDB_LOG_STRINGIFY(mTransaction->Database()), + IDB_LOG_STRINGIFY(mTransaction), + IDB_LOG_STRINGIFY(this), + IDB_LOG_STRINGIFY(key)); + } + } + BackgroundRequestChild* actor = new BackgroundRequestChild(request); mTransaction->StartRequest(actor, params); @@ -1261,28 +1289,6 @@ IDBObjectStore::AddOrPut(JSContext* aCx, MOZ_ASSERT(fileInfos.IsEmpty()); } -#ifdef IDB_PROFILER_USE_MARKS - if (aOverwrite) { - IDB_PROFILER_MARK("IndexedDB Request %llu: " - "database(%s).transaction(%s).objectStore(%s).%s(%s)", - "IDBRequest[%llu] MT IDBObjectStore.put()", - request->GetSerialNumber(), - IDB_PROFILER_STRING(Transaction()->Database()), - IDB_PROFILER_STRING(Transaction()), - IDB_PROFILER_STRING(this), - key.IsUnset() ? "" : IDB_PROFILER_STRING(key)); - } else { - IDB_PROFILER_MARK("IndexedDB Request %llu: " - "database(%s).transaction(%s).objectStore(%s).add(%s)", - "IDBRequest[%llu] MT IDBObjectStore.add()", - request->GetSerialNumber(), - IDB_PROFILER_STRING(Transaction()->Database()), - IDB_PROFILER_STRING(Transaction()), - IDB_PROFILER_STRING(this), - key.IsUnset() ? "" : IDB_PROFILER_STRING(key)); - } -#endif - return request.forget(); } @@ -1329,36 +1335,38 @@ IDBObjectStore::GetAllInternal(bool aKeysOnly, nsRefPtr request = GenerateRequest(this); MOZ_ASSERT(request); + if (aKeysOnly) { + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).objectStore(%s)." + "getAllKeys(%s, %s)", + "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.getAllKeys()", + IDB_LOG_ID_STRING(), + mTransaction->LoggingSerialNumber(), + request->LoggingSerialNumber(), + IDB_LOG_STRINGIFY(mTransaction->Database()), + IDB_LOG_STRINGIFY(mTransaction), + IDB_LOG_STRINGIFY(this), + IDB_LOG_STRINGIFY(keyRange), + IDB_LOG_STRINGIFY(aLimit)); + } else { + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).objectStore(%s)." + "getAll(%s, %s)", + "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.getAll()", + IDB_LOG_ID_STRING(), + mTransaction->LoggingSerialNumber(), + request->LoggingSerialNumber(), + IDB_LOG_STRINGIFY(mTransaction->Database()), + IDB_LOG_STRINGIFY(mTransaction), + IDB_LOG_STRINGIFY(this), + IDB_LOG_STRINGIFY(keyRange), + IDB_LOG_STRINGIFY(aLimit)); + } + BackgroundRequestChild* actor = new BackgroundRequestChild(request); mTransaction->StartRequest(actor, params); -#ifdef IDB_PROFILER_USE_MARKS - if (aKeysOnly) { - IDB_PROFILER_MARK("IndexedDB Request %llu: " - "database(%s).transaction(%s).objectStore(%s)." - "getAllKeys(%s, %lu)", - "IDBRequest[%llu] MT IDBObjectStore.getAllKeys()", - request->GetSerialNumber(), - IDB_PROFILER_STRING(Transaction()->Database()), - IDB_PROFILER_STRING(Transaction()), - IDB_PROFILER_STRING(this), - IDB_PROFILER_STRING(aKeyRange), - aLimit); - } else { - IDB_PROFILER_MARK("IndexedDB Request %llu: " - "database(%s).transaction(%s).objectStore(%s)." - "getAll(%s, %lu)", - "IDBRequest[%llu] MT IDBObjectStore.getAll()", - request->GetSerialNumber(), - IDB_PROFILER_STRING(Transaction()->Database()), - IDB_PROFILER_STRING(Transaction()), - IDB_PROFILER_STRING(this), - IDB_PROFILER_STRING(aKeyRange), - aLimit); - } -#endif - return request.forget(); } @@ -1383,18 +1391,20 @@ IDBObjectStore::Clear(ErrorResult& aRv) nsRefPtr request = GenerateRequest(this); MOZ_ASSERT(request); + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).objectStore(%s).clear()", + "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.clear()", + IDB_LOG_ID_STRING(), + mTransaction->LoggingSerialNumber(), + request->LoggingSerialNumber(), + IDB_LOG_STRINGIFY(mTransaction->Database()), + IDB_LOG_STRINGIFY(mTransaction), + IDB_LOG_STRINGIFY(this)); + BackgroundRequestChild* actor = new BackgroundRequestChild(request); mTransaction->StartRequest(actor, params); - IDB_PROFILER_MARK("IndexedDB Request %llu: " - "database(%s).transaction(%s).objectStore(%s).clear()", - "IDBRequest[%llu] MT IDBObjectStore.clear()", - request->GetSerialNumber(), - IDB_PROFILER_STRING(Transaction()->Database()), - IDB_PROFILER_STRING(Transaction()), - IDB_PROFILER_STRING(this)); - return request.forget(); } @@ -1579,25 +1589,29 @@ IDBObjectStore::Get(JSContext* aCx, nsRefPtr request = GenerateRequest(this); MOZ_ASSERT(request); + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).objectStore(%s).get(%s)", + "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.get()", + IDB_LOG_ID_STRING(), + mTransaction->LoggingSerialNumber(), + request->LoggingSerialNumber(), + IDB_LOG_STRINGIFY(mTransaction->Database()), + IDB_LOG_STRINGIFY(mTransaction), + IDB_LOG_STRINGIFY(this), + IDB_LOG_STRINGIFY(keyRange)); + BackgroundRequestChild* actor = new BackgroundRequestChild(request); mTransaction->StartRequest(actor, params); - IDB_PROFILER_MARK("IndexedDB Request %llu: " - "database(%s).transaction(%s).objectStore(%s).get(%s)", - "IDBRequest[%llu] MT IDBObjectStore.get()", - request->GetSerialNumber(), - IDB_PROFILER_STRING(Transaction()->Database()), - IDB_PROFILER_STRING(Transaction()), - IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(aKeyRange)); - return request.forget(); } already_AddRefed -IDBObjectStore::Delete(JSContext* aCx, - JS::Handle aKey, - ErrorResult& aRv) +IDBObjectStore::DeleteInternal(JSContext* aCx, + JS::Handle aKey, + bool aFromCursor, + ErrorResult& aRv) { AssertIsOnOwningThread(); @@ -1630,18 +1644,23 @@ IDBObjectStore::Delete(JSContext* aCx, nsRefPtr request = GenerateRequest(this); MOZ_ASSERT(request); + if (!aFromCursor) { + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).objectStore(%s).delete(%s)", + "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.delete()", + IDB_LOG_ID_STRING(), + mTransaction->LoggingSerialNumber(), + request->LoggingSerialNumber(), + IDB_LOG_STRINGIFY(mTransaction->Database()), + IDB_LOG_STRINGIFY(mTransaction), + IDB_LOG_STRINGIFY(this), + IDB_LOG_STRINGIFY(keyRange)); + } + BackgroundRequestChild* actor = new BackgroundRequestChild(request); mTransaction->StartRequest(actor, params); - IDB_PROFILER_MARK("IndexedDB Request %llu: " - "database(%s).transaction(%s).objectStore(%s).delete(%s)", - "IDBRequest[%llu] MT IDBObjectStore.delete()", - request->GetSerialNumber(), - IDB_PROFILER_STRING(Transaction()->Database()), - IDB_PROFILER_STRING(Transaction()), - IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(aKeyRange)); - return request.forget(); } @@ -1748,13 +1767,20 @@ IDBObjectStore::CreateIndexInternal( mIndexes.AppendElement(index); - IDB_PROFILER_MARK("IndexedDB Pseudo-request: " - "database(%s).transaction(%s).objectStore(%s)." - "createIndex(%s)", - "MT IDBObjectStore.createIndex()", - IDB_PROFILER_STRING(Transaction()->Database()), - IDB_PROFILER_STRING(Transaction()), - IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(index)); + // Don't do this in the macro because we always need to increment the serial + // number to keep in sync with the parent. + const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber(); + + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).objectStore(%s).createIndex(%s)", + "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.createIndex()", + IDB_LOG_ID_STRING(), + mTransaction->LoggingSerialNumber(), + requestSerialNumber, + IDB_LOG_STRINGIFY(mTransaction->Database()), + IDB_LOG_STRINGIFY(mTransaction), + IDB_LOG_STRINGIFY(this), + IDB_LOG_STRINGIFY(index)); return index.forget(); } @@ -1813,16 +1839,23 @@ IDBObjectStore::DeleteIndex(const nsAString& aName, ErrorResult& aRv) return; } - transaction->DeleteIndex(this, foundId); + // Don't do this in the macro because we always need to increment the serial + // number to keep in sync with the parent. + const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber(); - IDB_PROFILER_MARK("IndexedDB Pseudo-request: " - "database(%s).transaction(%s).objectStore(%s)." - "deleteIndex(\"%s\")", - "MT IDBObjectStore.deleteIndex()", - IDB_PROFILER_STRING(Transaction()->Database()), - IDB_PROFILER_STRING(Transaction()), - IDB_PROFILER_STRING(this), - NS_ConvertUTF16toUTF8(aName).get()); + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).objectStore(%s)." + "deleteIndex(\"%s\")", + "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.deleteIndex()", + IDB_LOG_ID_STRING(), + mTransaction->LoggingSerialNumber(), + requestSerialNumber, + IDB_LOG_STRINGIFY(mTransaction->Database()), + IDB_LOG_STRINGIFY(mTransaction), + IDB_LOG_STRINGIFY(this), + NS_ConvertUTF16toUTF8(aName).get()); + + transaction->DeleteIndex(this, foundId); } already_AddRefed @@ -1855,18 +1888,21 @@ IDBObjectStore::Count(JSContext* aCx, nsRefPtr request = GenerateRequest(this); MOZ_ASSERT(request); + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).objectStore(%s).count(%s)", + "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.count()", + IDB_LOG_ID_STRING(), + mTransaction->LoggingSerialNumber(), + request->LoggingSerialNumber(), + IDB_LOG_STRINGIFY(mTransaction->Database()), + IDB_LOG_STRINGIFY(mTransaction), + IDB_LOG_STRINGIFY(this), + IDB_LOG_STRINGIFY(keyRange)); + BackgroundRequestChild* actor = new BackgroundRequestChild(request); mTransaction->StartRequest(actor, params); - IDB_PROFILER_MARK("IndexedDB Request %llu: " - "database(%s).transaction(%s).objectStore(%s).count(%s)", - "IDBRequest[%llu] MT IDBObjectStore.count()", - request->GetSerialNumber(), - IDB_PROFILER_STRING(Transaction()->Database()), - IDB_PROFILER_STRING(Transaction()), - IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(aKeyRange)); - return request.forget(); } @@ -1925,34 +1961,40 @@ IDBObjectStore::OpenCursorInternal(bool aKeysOnly, nsRefPtr request = GenerateRequest(this); MOZ_ASSERT(request); + if (aKeysOnly) { + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).objectStore(%s)." + "openKeyCursor(%s, %s)", + "IndexedDB %s: C T[%lld] R[%llu]: " + "IDBObjectStore.openKeyCursor()", + IDB_LOG_ID_STRING(), + mTransaction->LoggingSerialNumber(), + request->LoggingSerialNumber(), + IDB_LOG_STRINGIFY(mTransaction->Database()), + IDB_LOG_STRINGIFY(mTransaction), + IDB_LOG_STRINGIFY(this), + IDB_LOG_STRINGIFY(keyRange), + IDB_LOG_STRINGIFY(direction)); + } else { + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "database(%s).transaction(%s).objectStore(%s)." + "openCursor(%s, %s)", + "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.openCursor()", + IDB_LOG_ID_STRING(), + mTransaction->LoggingSerialNumber(), + request->LoggingSerialNumber(), + IDB_LOG_STRINGIFY(mTransaction->Database()), + IDB_LOG_STRINGIFY(mTransaction), + IDB_LOG_STRINGIFY(this), + IDB_LOG_STRINGIFY(keyRange), + IDB_LOG_STRINGIFY(direction)); + } + BackgroundCursorChild* actor = new BackgroundCursorChild(request, this, direction); mTransaction->OpenCursor(actor, params); -#ifdef IDB_PROFILER_USE_MARKS - if (aKeysOnly) { - IDB_PROFILER_MARK("IndexedDB Request %llu: " - "database(%s).transaction(%s).objectStore(%s)." - "openKeyCursor(%s, %s)", - "IDBRequest[%llu] MT IDBObjectStore.openKeyCursor()", - request->GetSerialNumber(), - IDB_PROFILER_STRING(Transaction()->Database()), - IDB_PROFILER_STRING(Transaction()), - IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(aKeyRange), - IDB_PROFILER_STRING(direction)); - } else { - IDB_PROFILER_MARK("IndexedDB Request %llu: " - "database(%s).transaction(%s).objectStore(%s)." - "openCursor(%s, %s)", - "IDBRequest[%llu] MT IDBObjectStore.openKeyCursor()", - request->GetSerialNumber(), - IDB_PROFILER_STRING(Transaction()->Database()), - IDB_PROFILER_STRING(Transaction()), - IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(aKeyRange), - IDB_PROFILER_STRING(direction)); - } -#endif return request.forget(); } diff --git a/dom/indexedDB/IDBObjectStore.h b/dom/indexedDB/IDBObjectStore.h index ccb12baf035..2e43b068f51 100644 --- a/dom/indexedDB/IDBObjectStore.h +++ b/dom/indexedDB/IDBObjectStore.h @@ -33,6 +33,7 @@ template class Sequence; namespace indexedDB { class FileManager; +class IDBCursor; class IDBKeyRange; class IDBRequest; class IDBTransaction; @@ -47,6 +48,9 @@ class IDBObjectStore MOZ_FINAL : public nsISupports , public nsWrapperCache { + // For AddOrPut() and DeleteInternal(). + friend class IDBCursor; + static const JSClass sDummyPropJSClass; nsRefPtr mTransaction; @@ -160,7 +164,7 @@ public: { AssertIsOnOwningThread(); - return AddOrPut(aCx, aValue, aKey, false, aRv); + return AddOrPut(aCx, aValue, aKey, false, /* aFromCursor */ false, aRv); } already_AddRefed @@ -171,11 +175,18 @@ public: { AssertIsOnOwningThread(); - return AddOrPut(aCx, aValue, aKey, true, aRv); + return AddOrPut(aCx, aValue, aKey, true, /* aFromCursor */ false, aRv); } already_AddRefed - Delete(JSContext* aCx, JS::Handle aKey, ErrorResult& aRv); + Delete(JSContext* aCx, + JS::Handle aKey, + ErrorResult& aRv) + { + AssertIsOnOwningThread(); + + return DeleteInternal(aCx, aKey, /* aFromCursor */ false, aRv); + } already_AddRefed Get(JSContext* aCx, JS::Handle aKey, ErrorResult& aRv); @@ -286,8 +297,15 @@ private: JS::Handle aValue, JS::Handle aKey, bool aOverwrite, + bool aFromCursor, ErrorResult& aRv); + already_AddRefed + DeleteInternal(JSContext* aCx, + JS::Handle aKey, + bool aFromCursor, + ErrorResult& aRv); + already_AddRefed GetAllInternal(bool aKeysOnly, JSContext* aCx, diff --git a/dom/indexedDB/IDBRequest.cpp b/dom/indexedDB/IDBRequest.cpp index 388e8046131..7ddd08d4b99 100644 --- a/dom/indexedDB/IDBRequest.cpp +++ b/dom/indexedDB/IDBRequest.cpp @@ -29,6 +29,9 @@ #include "nsString.h" #include "ReportInternalError.h" +// Include this last to avoid path problems on Windows. +#include "ActorsChild.h" + namespace mozilla { namespace dom { namespace indexedDB { @@ -75,19 +78,10 @@ IDBRequest::InitMembers() AssertIsOnOwningThread(); mResultVal.setUndefined(); + mLoggingSerialNumber = NextSerialNumber(); mErrorCode = NS_OK; mLineNo = 0; mHaveResultOrErrorCode = false; - -#ifdef MOZ_ENABLE_PROFILER_SPS - { - BackgroundChildImpl::ThreadLocal* threadLocal = - BackgroundChildImpl::GetThreadLocalForCurrentThread(); - MOZ_ASSERT(threadLocal); - - mSerialNumber = threadLocal->mNextRequestSerialNumber++; - } -#endif } // static @@ -140,6 +134,28 @@ IDBRequest::Create(IDBIndex* aSourceAsIndex, } // static +uint64_t +IDBRequest::NextSerialNumber() +{ + BackgroundChildImpl::ThreadLocal* threadLocal = + BackgroundChildImpl::GetThreadLocalForCurrentThread(); + MOZ_ASSERT(threadLocal); + + ThreadLocal* idbThreadLocal = threadLocal->mIndexedDBThreadLocal; + MOZ_ASSERT(idbThreadLocal); + + return idbThreadLocal->NextRequestSN(); +} + +void +IDBRequest::SetLoggingSerialNumber(uint64_t aLoggingSerialNumber) +{ + AssertIsOnOwningThread(); + MOZ_ASSERT(aLoggingSerialNumber > mLoggingSerialNumber); + + mLoggingSerialNumber = aLoggingSerialNumber; +} + void IDBRequest::CaptureCaller(nsAString& aFilename, uint32_t* aLineNo) { diff --git a/dom/indexedDB/IDBRequest.h b/dom/indexedDB/IDBRequest.h index 170dc0e2562..af3e1e929fd 100644 --- a/dom/indexedDB/IDBRequest.h +++ b/dom/indexedDB/IDBRequest.h @@ -58,9 +58,7 @@ protected: nsRefPtr mError; nsString mFilename; -#ifdef MOZ_ENABLE_PROFILER_SPS - uint64_t mSerialNumber; -#endif + uint64_t mLoggingSerialNumber; nsresult mErrorCode; uint32_t mLineNo; bool mHaveResultOrErrorCode; @@ -84,6 +82,9 @@ public: static void CaptureCaller(nsAString& aFilename, uint32_t* aLineNo); + static uint64_t + NextSerialNumber(); + // nsIDOMEventTarget virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) MOZ_OVERRIDE; @@ -125,13 +126,16 @@ public: return !mHaveResultOrErrorCode; } -#ifdef MOZ_ENABLE_PROFILER_SPS uint64_t - GetSerialNumber() const + LoggingSerialNumber() const { - return mSerialNumber; + AssertIsOnOwningThread(); + + return mLoggingSerialNumber; } -#endif + + void + SetLoggingSerialNumber(uint64_t aLoggingSerialNumber); nsPIDOMWindow* GetParentObject() const diff --git a/dom/indexedDB/IDBTransaction.cpp b/dom/indexedDB/IDBTransaction.cpp index a914dc1b2f8..07c99596bbd 100644 --- a/dom/indexedDB/IDBTransaction.cpp +++ b/dom/indexedDB/IDBTransaction.cpp @@ -32,6 +32,8 @@ namespace mozilla { namespace dom { namespace indexedDB { +using namespace mozilla::ipc; + namespace { NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); @@ -44,6 +46,7 @@ IDBTransaction::IDBTransaction(IDBDatabase* aDatabase, : IDBWrapperCache(aDatabase) , mDatabase(aDatabase) , mObjectStoreNames(aObjectStoreNames) + , mLoggingSerialNumber(0) , mNextObjectStoreId(0) , mNextIndexId(0) , mAbortCode(NS_OK) @@ -63,16 +66,15 @@ IDBTransaction::IDBTransaction(IDBDatabase* aDatabase, mBackgroundActor.mNormalBackgroundActor = nullptr; -#ifdef MOZ_ENABLE_PROFILER_SPS - { - using namespace mozilla::ipc; - BackgroundChildImpl::ThreadLocal* threadLocal = - BackgroundChildImpl::GetThreadLocalForCurrentThread(); - MOZ_ASSERT(threadLocal); + BackgroundChildImpl::ThreadLocal* threadLocal = + BackgroundChildImpl::GetThreadLocalForCurrentThread(); + MOZ_ASSERT(threadLocal); - mSerialNumber = threadLocal->mNextTransactionSerialNumber++; - } -#endif + ThreadLocal* idbThreadLocal = threadLocal->mIndexedDBThreadLocal; + MOZ_ASSERT(idbThreadLocal); + + const_cast(mLoggingSerialNumber) = + idbThreadLocal->NextTransactionSN(aMode); #ifdef DEBUG if (!aObjectStoreNames.IsEmpty()) { @@ -111,13 +113,15 @@ IDBTransaction::~IDBTransaction() mDatabase->UnregisterTransaction(this); if (mMode == VERSION_CHANGE) { - if (mBackgroundActor.mVersionChangeBackgroundActor) { - mBackgroundActor.mVersionChangeBackgroundActor->SendDeleteMeInternal(); + if (auto* actor = mBackgroundActor.mVersionChangeBackgroundActor) { + actor->SendDeleteMeInternal(); + MOZ_ASSERT(!mBackgroundActor.mVersionChangeBackgroundActor, "SendDeleteMeInternal should have cleared!"); } - } else if (mBackgroundActor.mNormalBackgroundActor) { - mBackgroundActor.mNormalBackgroundActor->SendDeleteMeInternal(); + } else if (auto* actor = mBackgroundActor.mNormalBackgroundActor) { + actor->SendDeleteMeInternal(); + MOZ_ASSERT(!mBackgroundActor.mNormalBackgroundActor, "SendDeleteMeInternal should have cleared!"); } @@ -212,7 +216,10 @@ IDBTransaction::GetCurrent() BackgroundChildImpl::GetThreadLocalForCurrentThread(); MOZ_ASSERT(threadLocal); - return threadLocal->mCurrentTransaction; + ThreadLocal* idbThreadLocal = threadLocal->mIndexedDBThreadLocal; + MOZ_ASSERT(idbThreadLocal); + + return idbThreadLocal->GetCurrentTransaction(); } #ifdef DEBUG @@ -339,6 +346,18 @@ IDBTransaction::SendCommit() MOZ_ASSERT(NS_SUCCEEDED(mAbortCode)); MOZ_ASSERT(IsFinished()); MOZ_ASSERT(!mSentCommitOrAbort); + MOZ_ASSERT(!mPendingRequestCount); + + // Don't do this in the macro because we always need to increment the serial + // number to keep in sync with the parent. + const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber(); + + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "All requests complete, committing transaction", + "IndexedDB %s: C T[%lld] R[%llu]: IDBTransaction commit", + IDB_LOG_ID_STRING(), + LoggingSerialNumber(), + requestSerialNumber); if (mMode == VERSION_CHANGE) { MOZ_ASSERT(mBackgroundActor.mVersionChangeBackgroundActor); @@ -361,6 +380,18 @@ IDBTransaction::SendAbort(nsresult aResultCode) MOZ_ASSERT(IsFinished()); MOZ_ASSERT(!mSentCommitOrAbort); + // Don't do this in the macro because we always need to increment the serial + // number to keep in sync with the parent. + const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber(); + + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " + "Aborting transaction with result 0x%x", + "IndexedDB %s: C T[%lld] R[%llu]: IDBTransaction abort (0x%x)", + IDB_LOG_ID_STRING(), + LoggingSerialNumber(), + requestSerialNumber, + aResultCode); + if (mMode == VERSION_CHANGE) { MOZ_ASSERT(mBackgroundActor.mVersionChangeBackgroundActor); mBackgroundActor.mVersionChangeBackgroundActor->SendAbort(aResultCode); @@ -517,11 +548,14 @@ IDBTransaction::AbortInternal(nsresult aAbortCode, const bool isInvalidated = mDatabase->IsInvalidated(); bool needToSendAbort = mReadyState == INITIAL && !isInvalidated; -#ifdef DEBUG if (isInvalidated) { +#ifdef DEBUG mSentCommitOrAbort = true; - } #endif + // Increment the serial number counter here to account for the aborted + // transaction and keep the parent in sync. + IDBRequest::NextSerialNumber(); + } mAbortCode = aAbortCode; mReadyState = DONE; @@ -639,10 +673,6 @@ IDBTransaction::FireCompleteOrAbortEvents(nsresult aResult) AssertIsOnOwningThread(); MOZ_ASSERT(!mFiredCompleteOrAbort); - IDB_PROFILER_MARK("IndexedDB Transaction %llu: Complete (rv = %lu)", - "IDBTransaction[%llu] MT Complete", - mTransaction->GetSerialNumber(), mAbortCode); - mReadyState = DONE; #ifdef DEBUG @@ -670,6 +700,21 @@ IDBTransaction::FireCompleteOrAbortEvents(nsresult aResult) return; } + if (NS_SUCCEEDED(mAbortCode)) { + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld]: " + "Firing 'complete' event", + "IndexedDB %s: C T[%lld]: IDBTransaction 'complete' event", + IDB_LOG_ID_STRING(), + mLoggingSerialNumber); + } else { + IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld]: " + "Firing 'abort' event with error 0x%x", + "IndexedDB %s: C T[%lld]: IDBTransaction 'abort' event (0x%x)", + IDB_LOG_ID_STRING(), + mLoggingSerialNumber, + mAbortCode); + } + bool dummy; if (NS_FAILED(DispatchEvent(event, &dummy))) { NS_WARNING("DispatchEvent failed!"); diff --git a/dom/indexedDB/IDBTransaction.h b/dom/indexedDB/IDBTransaction.h index 73771c4f37c..07c2b9acc82 100644 --- a/dom/indexedDB/IDBTransaction.h +++ b/dom/indexedDB/IDBTransaction.h @@ -83,15 +83,12 @@ private: BackgroundVersionChangeTransactionChild* mVersionChangeBackgroundActor; } mBackgroundActor; + const int64_t mLoggingSerialNumber; // Only used for VERSION_CHANGE transactions. int64_t mNextObjectStoreId; int64_t mNextIndexId; -#ifdef MOZ_ENABLE_PROFILER_SPS - uint64_t mSerialNumber; -#endif - nsresult mAbortCode; uint32_t mPendingRequestCount; @@ -245,14 +242,13 @@ public: void Abort(nsresult aAbortCode); -#ifdef MOZ_ENABLE_PROFILER_SPS - uint32_t - GetSerialNumber() const + int64_t + LoggingSerialNumber() const { AssertIsOnOwningThread(); - return mSerialNumber; + + return mLoggingSerialNumber; } -#endif nsPIDOMWindow* GetParentObject() const; diff --git a/dom/indexedDB/IndexedDatabaseManager.cpp b/dom/indexedDB/IndexedDatabaseManager.cpp index 7d41156cd85..f3823a9bd0f 100644 --- a/dom/indexedDB/IndexedDatabaseManager.cpp +++ b/dom/indexedDB/IndexedDatabaseManager.cpp @@ -32,11 +32,13 @@ #include "mozilla/storage.h" #include "nsContentUtils.h" #include "nsThreadUtils.h" +#include "prlog.h" #include "IDBEvents.h" #include "IDBFactory.h" #include "IDBKeyRange.h" #include "IDBRequest.h" +#include "ProfilerHelpers.h" // Bindings for ResolveConstructors #include "mozilla/dom/IDBCursorBinding.h" @@ -111,7 +113,22 @@ private: namespace { -const char kTestingPref[] = "dom.indexedDB.testing"; +#define IDB_PREF_BRANCH_ROOT "dom.indexedDB." + +const char kTestingPref[] = IDB_PREF_BRANCH_ROOT "testing"; + +#define IDB_PREF_LOGGING_BRANCH_ROOT IDB_PREF_BRANCH_ROOT "logging." + +const char kPrefLoggingEnabled[] = IDB_PREF_LOGGING_BRANCH_ROOT "enabled"; +const char kPrefLoggingDetails[] = IDB_PREF_LOGGING_BRANCH_ROOT "details"; + +#if defined(DEBUG) || defined(MOZ_ENABLE_PROFILER_SPS) +const char kPrefLoggingProfiler[] = + IDB_PREF_LOGGING_BRANCH_ROOT "profiler-marks"; +#endif + +#undef IDB_PREF_LOGGING_BRANCH_ROOT +#undef IDB_PREF_BRANCH_ROOT mozilla::StaticRefPtr gDBManager; @@ -205,6 +222,13 @@ IndexedDatabaseManager::~IndexedDatabaseManager() bool IndexedDatabaseManager::sIsMainProcess = false; bool IndexedDatabaseManager::sFullSynchronousMode = false; + +PRLogModuleInfo* IndexedDatabaseManager::sLoggingModule; + +Atomic + IndexedDatabaseManager::sLoggingMode( + IndexedDatabaseManager::Logging_Disabled); + mozilla::Atomic IndexedDatabaseManager::sLowDiskSpaceMode(false); // static @@ -221,6 +245,10 @@ IndexedDatabaseManager::GetOrCreate() if (!gDBManager) { sIsMainProcess = XRE_GetProcessType() == GeckoProcessType_Default; + if (!sLoggingModule) { + sLoggingModule = PR_NewLogModule("IndexedDB"); + } + if (sIsMainProcess && Preferences::GetBool("disk_space_watcher.enabled", false)) { // See if we're starting up in low disk space conditions. nsCOMPtr watcher = @@ -300,6 +328,15 @@ IndexedDatabaseManager::Init() // hit. sFullSynchronousMode = Preferences::GetBool("dom.indexedDB.fullSynchronous"); + Preferences::RegisterCallback(LoggingModePrefChangedCallback, + kPrefLoggingDetails); +#ifdef MOZ_ENABLE_PROFILER_SPS + Preferences::RegisterCallback(LoggingModePrefChangedCallback, + kPrefLoggingProfiler); +#endif + Preferences::RegisterCallbackAndCall(LoggingModePrefChangedCallback, + kPrefLoggingEnabled); + return NS_OK; } @@ -314,6 +351,15 @@ IndexedDatabaseManager::Destroy() Preferences::UnregisterCallback(TestingPrefChangedCallback, kTestingPref); + Preferences::UnregisterCallback(LoggingModePrefChangedCallback, + kPrefLoggingDetails); +#ifdef MOZ_ENABLE_PROFILER_SPS + Preferences::UnregisterCallback(LoggingModePrefChangedCallback, + kPrefLoggingProfiler); +#endif + Preferences::UnregisterCallback(LoggingModePrefChangedCallback, + kPrefLoggingEnabled); + delete this; } @@ -491,7 +537,30 @@ IndexedDatabaseManager::InLowDiskSpaceMode() "initialized!"); return sLowDiskSpaceMode; } -#endif + +// static +IndexedDatabaseManager::LoggingMode +IndexedDatabaseManager::GetLoggingMode() +{ + MOZ_ASSERT(gDBManager, + "GetLoggingMode called before IndexedDatabaseManager has been " + "initialized!"); + + return sLoggingMode; +} + +// static +PRLogModuleInfo* +IndexedDatabaseManager::GetLoggingModule() +{ + MOZ_ASSERT(gDBManager, + "GetLoggingModule called before IndexedDatabaseManager has been " + "initialized!"); + + return sLoggingModule; +} + +#endif // DEBUG // static bool @@ -687,6 +756,44 @@ IndexedDatabaseManager::BlockAndGetFileReferences( return NS_OK; } +// static +void +IndexedDatabaseManager::LoggingModePrefChangedCallback( + const char* /* aPrefName */, + void* /* aClosure */) +{ + MOZ_ASSERT(NS_IsMainThread()); + + if (!Preferences::GetBool(kPrefLoggingEnabled)) { + sLoggingMode = Logging_Disabled; + return; + } + + bool useProfiler = +#if defined(DEBUG) || defined(MOZ_ENABLE_PROFILER_SPS) + Preferences::GetBool(kPrefLoggingProfiler); +#if !defined(MOZ_ENABLE_PROFILER_SPS) + if (useProfiler) { + NS_WARNING("IndexedDB cannot create profiler marks because this build does " + "not have profiler extensions enabled!"); + useProfiler = false; + } +#endif +#else + false; +#endif + + const bool logDetails = Preferences::GetBool(kPrefLoggingDetails); + + if (useProfiler) { + sLoggingMode = logDetails ? + Logging_DetailedProfilerMarks : + Logging_ConciseProfilerMarks; + } else { + sLoggingMode = logDetails ? Logging_Detailed : Logging_Concise; + } +} + NS_IMPL_ADDREF(IndexedDatabaseManager) NS_IMPL_RELEASE_WITH_DESTROY(IndexedDatabaseManager, Destroy()) NS_IMPL_QUERY_INTERFACE(IndexedDatabaseManager, nsIObserver) diff --git a/dom/indexedDB/IndexedDatabaseManager.h b/dom/indexedDB/IndexedDatabaseManager.h index 71bea9f7f78..6621b74a1b6 100644 --- a/dom/indexedDB/IndexedDatabaseManager.h +++ b/dom/indexedDB/IndexedDatabaseManager.h @@ -17,6 +17,7 @@ #include "nsHashKeys.h" class nsPIDOMWindow; +struct PRLogModuleInfo; namespace mozilla { @@ -36,6 +37,15 @@ class IndexedDatabaseManager MOZ_FINAL : public nsIObserver typedef mozilla::dom::quota::PersistenceType PersistenceType; public: + enum LoggingMode + { + Logging_Disabled = 0, + Logging_Concise, + Logging_Detailed, + Logging_ConciseProfilerMarks, + Logging_DetailedProfilerMarks + }; + NS_DECL_ISUPPORTS NS_DECL_NSIOBSERVER @@ -76,6 +86,26 @@ public: static bool FullSynchronous(); + static LoggingMode + GetLoggingMode() +#ifdef DEBUG + ; +#else + { + return sLoggingMode; + } +#endif + + static PRLogModuleInfo* + GetLoggingModule() +#ifdef DEBUG + ; +#else + { + return sLoggingModule; + } +#endif + already_AddRefed GetFileManager(PersistenceType aPersistenceType, const nsACString& aOrigin, @@ -143,6 +173,9 @@ private: void Destroy(); + static void + LoggingModePrefChangedCallback(const char* aPrefName, void* aClosure); + // Maintains a list of all file managers per origin. This list isn't // protected by any mutex but it is only ever touched on the IO thread. nsClassHashtable mFileManagerInfos; @@ -154,6 +187,8 @@ private: static bool sIsMainProcess; static bool sFullSynchronousMode; + static PRLogModuleInfo* sLoggingModule; + static Atomic sLoggingMode; static mozilla::Atomic sLowDiskSpaceMode; }; diff --git a/dom/indexedDB/PBackgroundIDBFactory.ipdl b/dom/indexedDB/PBackgroundIDBFactory.ipdl index 1fac81f93b1..b44eccf7dc8 100644 --- a/dom/indexedDB/PBackgroundIDBFactory.ipdl +++ b/dom/indexedDB/PBackgroundIDBFactory.ipdl @@ -51,6 +51,8 @@ parent: PBackgroundIDBFactoryRequest(FactoryRequestParams params); + IncrementLoggingRequestSerialNumber(); + child: __delete__(); diff --git a/dom/indexedDB/PBackgroundIDBSharedTypes.ipdlh b/dom/indexedDB/PBackgroundIDBSharedTypes.ipdlh index 5402b256f3d..58f9f42241c 100644 --- a/dom/indexedDB/PBackgroundIDBSharedTypes.ipdlh +++ b/dom/indexedDB/PBackgroundIDBSharedTypes.ipdlh @@ -5,6 +5,8 @@ include protocol PBlob; include protocol PBackgroundIDBDatabaseFile; +include DOMTypes; + include "mozilla/dom/indexedDB/SerializationHelpers.h"; using struct mozilla::void_t @@ -253,6 +255,14 @@ union RequestParams IndexCountParams; }; +struct LoggingInfo +{ + nsID backgroundChildLoggingId; + int64_t nextTransactionSerialNumber; + int64_t nextVersionChangeTransactionSerialNumber; + uint64_t nextRequestSerialNumber; +}; + } // namespace indexedDB } // namespace dom } // namespace mozilla diff --git a/dom/indexedDB/ProfilerHelpers.h b/dom/indexedDB/ProfilerHelpers.h index 4afab8469c6..60356d2c713 100644 --- a/dom/indexedDB/ProfilerHelpers.h +++ b/dom/indexedDB/ProfilerHelpers.h @@ -7,40 +7,76 @@ #ifndef mozilla_dom_indexeddb_profilerhelpers_h__ #define mozilla_dom_indexeddb_profilerhelpers_h__ +// This file is not exported and is only meant to be included in IndexedDB +// source files. + +#include "BackgroundChildImpl.h" #include "GeckoProfiler.h" - -// Uncomment this if you want IndexedDB operations to be marked in the profiler. -//#define IDB_PROFILER_USE_MARKS - -// Uncomment this if you want extended details to appear in profiler marks. -//#define IDB_PROFILER_MARK_DETAILS 0 - -// Sanity check the options above. -#if defined(IDB_PROFILER_USE_MARKS) && !defined(MOZ_ENABLE_PROFILER_SPS) -#error Cannot use IDB_PROFILER_USE_MARKS without MOZ_ENABLE_PROFILER_SPS! -#endif - -#if defined(IDB_PROFILER_MARK_DETAILS) && !defined(IDB_PROFILER_USE_MARKS) -#error Cannot use IDB_PROFILER_MARK_DETAILS without IDB_PROFILER_USE_MARKS! -#endif - -#ifdef IDB_PROFILER_USE_MARKS - -#ifdef IDB_PROFILER_MARK_DETAILS - #include "IDBCursor.h" #include "IDBDatabase.h" #include "IDBIndex.h" #include "IDBKeyRange.h" #include "IDBObjectStore.h" #include "IDBTransaction.h" +#include "IndexedDatabaseManager.h" #include "Key.h" +#include "mozilla/Assertions.h" +#include "mozilla/Attributes.h" +#include "mozilla/dom/BindingDeclarations.h" +#include "nsDebug.h" +#include "nsID.h" +#include "nsIDOMEvent.h" +#include "nsString.h" +#include "prlog.h" + +// Include this last to avoid path problems on Windows. +#include "ActorsChild.h" namespace mozilla { namespace dom { namespace indexedDB { -class ProfilerString : public nsAutoCString +class MOZ_STACK_CLASS LoggingIdString MOZ_FINAL + : public nsAutoCString +{ +public: + LoggingIdString() + { + using mozilla::ipc::BackgroundChildImpl; + + BackgroundChildImpl::ThreadLocal* threadLocal = + BackgroundChildImpl::GetThreadLocalForCurrentThread(); + MOZ_ASSERT(threadLocal); + + ThreadLocal* idbThreadLocal = threadLocal->mIndexedDBThreadLocal; + MOZ_ASSERT(idbThreadLocal); + + Init(idbThreadLocal->Id()); + } + + explicit + LoggingIdString(const nsID& aID) + { + Init(aID); + } + +private: + void + Init(const nsID& aID) + { + static_assert(NSID_LENGTH > 1, "NSID_LENGTH is set incorrectly!"); + MOZ_ASSERT(Capacity() > NSID_LENGTH); + + // NSID_LENGTH counts the null terminator, SetLength() does not. + SetLength(NSID_LENGTH - 1); + + aID.ToProvidedString( + *reinterpret_cast(BeginWriting())); + } +}; + +class MOZ_STACK_CLASS LoggingString MOZ_FINAL + : public nsAutoCString { static const char kQuote = '\"'; static const char kOpenBracket = '['; @@ -50,20 +86,38 @@ class ProfilerString : public nsAutoCString public: explicit - ProfilerString(IDBDatabase* aDatabase) + LoggingString(IDBDatabase* aDatabase) + : nsAutoCString(kQuote) { MOZ_ASSERT(aDatabase); - Append(kQuote); AppendUTF16toUTF8(aDatabase->Name(), *this); Append(kQuote); } explicit - ProfilerString(IDBTransaction* aTransaction) + LoggingString(IDBTransaction* aTransaction) + : nsAutoCString(kOpenBracket) { MOZ_ASSERT(aTransaction); + NS_NAMED_LITERAL_CSTRING(kCommaSpace, ", "); + + const nsTArray& stores = aTransaction->ObjectStoreNamesInternal(); + + for (uint32_t count = stores.Length(), index = 0; index < count; index++) { + Append(kQuote); + AppendUTF16toUTF8(stores[index], *this); + Append(kQuote); + + if (index != count - 1) { + Append(kCommaSpace); + } + } + + Append(kCloseBracket); + Append(kCommaSpace); + switch (aTransaction->GetMode()) { case IDBTransaction::READ_ONLY: AppendLiteral("\"readonly\""); @@ -80,128 +134,198 @@ public: } explicit - ProfilerString(IDBObjectStore* aObjectStore) + LoggingString(IDBObjectStore* aObjectStore) + : nsAutoCString(kQuote) { MOZ_ASSERT(aObjectStore); - Append(kQuote); AppendUTF16toUTF8(aObjectStore->Name(), *this); Append(kQuote); } explicit - ProfilerString(IDBIndex* aIndex) + LoggingString(IDBIndex* aIndex) + : nsAutoCString(kQuote) { MOZ_ASSERT(aIndex); - Append(kQuote); AppendUTF16toUTF8(aIndex->Name(), *this); Append(kQuote); } explicit - ProfilerString(IDBKeyRange* aKeyRange) + LoggingString(IDBKeyRange* aKeyRange) { if (aKeyRange) { if (aKeyRange->IsOnly()) { - Append(ProfilerString(aKeyRange->Lower())); - } - else { - Append(aKeyRange->IsLowerOpen() ? kOpenParen : kOpenBracket); - Append(ProfilerString(aKeyRange->Lower())); + Assign(LoggingString(aKeyRange->Lower())); + } else { + Assign(aKeyRange->LowerOpen() ? kOpenParen : kOpenBracket); + Append(LoggingString(aKeyRange->Lower())); AppendLiteral(", "); - Append(ProfilerString(aKeyRange->Upper())); - Append(aKeyRange->IsUpperOpen() ? kCloseParen : kCloseBracket); + Append(LoggingString(aKeyRange->Upper())); + Append(aKeyRange->UpperOpen() ? kCloseParen : kCloseBracket); } + } else { + AssignLiteral(""); } } explicit - ProfilerString(const Key& aKey) + LoggingString(const Key& aKey) { if (aKey.IsUnset()) { - AssignLiteral("null"); - } - else if (aKey.IsFloat()) { + AssignLiteral(""); + } else if (aKey.IsFloat()) { AppendPrintf("%g", aKey.ToFloat()); - } - else if (aKey.IsDate()) { + } else if (aKey.IsDate()) { AppendPrintf("", aKey.ToDateMsec()); - } - else if (aKey.IsString()) { + } else if (aKey.IsString()) { nsAutoString str; aKey.ToString(str); AppendPrintf("\"%s\"", NS_ConvertUTF16toUTF8(str).get()); - } - else { + } else { MOZ_ASSERT(aKey.IsArray()); - AppendLiteral(""); + AssignLiteral("[...]"); } } explicit - ProfilerString(const IDBCursor::Direction aDirection) + LoggingString(const IDBCursor::Direction aDirection) { switch (aDirection) { case IDBCursor::NEXT: - AppendLiteral("\"next\""); + AssignLiteral("\"next\""); break; case IDBCursor::NEXT_UNIQUE: - AppendLiteral("\"nextunique\""); + AssignLiteral("\"nextunique\""); break; case IDBCursor::PREV: - AppendLiteral("\"prev\""); + AssignLiteral("\"prev\""); break; case IDBCursor::PREV_UNIQUE: - AppendLiteral("\"prevunique\""); + AssignLiteral("\"prevunique\""); break; default: MOZ_CRASH("Unknown direction!"); }; } + + explicit + LoggingString(const Optional& aVersion) + { + if (aVersion.WasPassed()) { + AppendInt(aVersion.Value()); + } else { + AssignLiteral(""); + } + } + + explicit + LoggingString(const Optional& aLimit) + { + if (aLimit.WasPassed()) { + AppendInt(aLimit.Value()); + } else { + AssignLiteral(""); + } + } + + LoggingString(IDBObjectStore* aObjectStore, const Key& aKey) + { + MOZ_ASSERT(aObjectStore); + + if (!aObjectStore->HasValidKeyPath()) { + Append(LoggingString(aKey)); + } + } + + LoggingString(nsIDOMEvent* aEvent, const char16_t* aDefault) + : nsAutoCString(kQuote) + { + MOZ_ASSERT(aDefault); + + nsString eventType; + + if (aEvent) { + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(aEvent->GetType(eventType))); + } else { + eventType = nsDependentString(aDefault); + } + + AppendUTF16toUTF8(eventType, *this); + Append(kQuote); + } }; +inline void +LoggingHelper(bool aUseProfiler, const char* aFmt, ...) +{ + MOZ_ASSERT(IndexedDatabaseManager::GetLoggingMode() != + IndexedDatabaseManager::Logging_Disabled); + MOZ_ASSERT(aFmt); + + PRLogModuleInfo* logModule = IndexedDatabaseManager::GetLoggingModule(); + MOZ_ASSERT(logModule); + + static const PRLogModuleLevel logLevel = PR_LOG_DEBUG; + + if (PR_LOG_TEST(logModule, logLevel) || + (aUseProfiler && profiler_is_active())) { + nsAutoCString message; + + { + va_list args; + va_start(args, aFmt); + + message.AppendPrintf(aFmt, args); + + va_end(args); + } + + PR_LOG(logModule, logLevel, ("%s", message.get())); + + if (aUseProfiler) { + PROFILER_MARKER(message.get()); + } + } +} + } // namespace indexedDB } // namespace dom } // namespace mozilla -#define IDB_PROFILER_MARK(_detailedFmt, _conciseFmt, ...) \ +#define IDB_LOG_MARK(_detailedFmt, _conciseFmt, ...) \ do { \ - nsAutoCString _mark; \ - _mark.AppendPrintf(_detailedFmt, ##__VA_ARGS__); \ - PROFILER_MARKER(_mark.get()); \ - } while (0) - -#define IDB_PROFILER_STRING(_arg) \ - mozilla::dom::indexedDB::ProfilerString((_arg)).get() - -#else // IDB_PROFILER_MARK_DETAILS - -#define IDB_PROFILER_MARK(_detailedFmt, _conciseFmt, ...) \ - do { \ - nsAutoCString _mark; \ - _mark.AppendPrintf(_conciseFmt, ##__VA_ARGS__); \ - PROFILER_MARKER(_mark.get()); \ - } while (0) - -#define IDB_PROFILER_STRING(_arg) "" - -#endif // IDB_PROFILER_MARK_DETAILS - -#define IDB_PROFILER_MARK_IF(_cond, _detailedFmt, _conciseFmt, ...) \ - do { \ - if (_cond) { \ - IDB_PROFILER_MARK(_detailedFmt, _conciseFmt, __VA_ARGS__); \ + using namespace mozilla::dom::indexedDB; \ + \ + const IndexedDatabaseManager::LoggingMode mode = \ + IndexedDatabaseManager::GetLoggingMode(); \ + \ + if (mode != IndexedDatabaseManager::Logging_Disabled) { \ + const char* _fmt; \ + if (mode == IndexedDatabaseManager::Logging_Concise || \ + mode == IndexedDatabaseManager::Logging_ConciseProfilerMarks) { \ + _fmt = _conciseFmt; \ + } else { \ + MOZ_ASSERT( \ + mode == IndexedDatabaseManager::Logging_Detailed || \ + mode == IndexedDatabaseManager::Logging_DetailedProfilerMarks); \ + _fmt = _detailedFmt; \ + } \ + \ + const bool _useProfiler = \ + mode == IndexedDatabaseManager::Logging_ConciseProfilerMarks || \ + mode == IndexedDatabaseManager::Logging_DetailedProfilerMarks; \ + \ + LoggingHelper(_useProfiler, _fmt, ##__VA_ARGS__); \ } \ } while (0) -#else // IDB_PROFILER_USE_MARKS +#define IDB_LOG_ID_STRING(...) \ + mozilla::dom::indexedDB::LoggingIdString(__VA_ARGS__).get() -#define IDB_PROFILER_MARK(...) do { } while(0) -#define IDB_PROFILER_MARK_IF(_cond, ...) do { } while(0) -#define IDB_PROFILER_MARK2(_detailedFmt, _notdetailedFmt, ...) do { } while(0) -#define IDB_PROFILER_STRING(_arg) "" - -#endif // IDB_PROFILER_USE_MARKS +#define IDB_LOG_STRINGIFY(...) \ + mozilla::dom::indexedDB::LoggingString(__VA_ARGS__).get() #endif // mozilla_dom_indexeddb_profilerhelpers_h__ diff --git a/dom/indexedDB/TransactionThreadPool.cpp b/dom/indexedDB/TransactionThreadPool.cpp index f8af510471b..3cd668b13da 100644 --- a/dom/indexedDB/TransactionThreadPool.cpp +++ b/dom/indexedDB/TransactionThreadPool.cpp @@ -144,7 +144,9 @@ class TransactionThreadPool::TransactionQueue MOZ_FINAL Monitor mMonitor; nsRefPtr mOwningThreadPool; - uint64_t mTransactionId; + const uint64_t mTransactionId; + const nsID mBackgroundChildLoggingId; + const int64_t mLoggingSerialNumber; const nsCString mDatabaseId; const nsTArray mObjectStoreNames; uint16_t mMode; @@ -155,10 +157,12 @@ class TransactionThreadPool::TransactionQueue MOZ_FINAL public: TransactionQueue(TransactionThreadPool* aThreadPool, - uint64_t aTransactionId, - const nsACString& aDatabaseId, - const nsTArray& aObjectStoreNames, - uint16_t aMode); + uint64_t aTransactionId, + const nsACString& aDatabaseId, + const nsTArray& aObjectStoreNames, + uint16_t aMode, + const nsID& aBackgroundChildLoggingId, + int64_t aLoggingSerialNumber); NS_DECL_ISUPPORTS_INHERITED @@ -187,13 +191,21 @@ struct TransactionThreadPool::TransactionInfo MOZ_FINAL uint64_t aTransactionId, const nsACString& aDatabaseId, const nsTArray& aObjectStoreNames, - uint16_t aMode) + uint16_t aMode, + const nsID& aBackgroundChildLoggingId, + int64_t aLoggingSerialNumber) : transactionId(aTransactionId), databaseId(aDatabaseId) { MOZ_COUNT_CTOR(TransactionInfo); - queue = new TransactionQueue(aThreadPool, aTransactionId, aDatabaseId, - aObjectStoreNames, aMode); + queue = + new TransactionQueue(aThreadPool, + aTransactionId, + aDatabaseId, + aObjectStoreNames, + aMode, + aBackgroundChildLoggingId, + aLoggingSerialNumber); } ~TransactionInfo() @@ -302,7 +314,6 @@ TransactionThreadPool::Shutdown() } } -// static uint64_t TransactionThreadPool::NextTransactionId() { @@ -548,20 +559,17 @@ TransactionThreadPool::GetQueueForTransaction(uint64_t aTransactionId, } TransactionThreadPool::TransactionQueue& -TransactionThreadPool::GetQueueForTransaction( +TransactionThreadPool::CreateQueueForTransaction( uint64_t aTransactionId, const nsACString& aDatabaseId, const nsTArray& aObjectStoreNames, - uint16_t aMode) + uint16_t aMode, + const nsID& aBackgroundChildLoggingId, + int64_t aLoggingSerialNumber) { AssertIsOnOwningThread(); MOZ_ASSERT(aTransactionId <= mNextTransactionId); - - TransactionQueue* existingQueue = - GetQueueForTransaction(aTransactionId, aDatabaseId); - if (existingQueue) { - return *existingQueue; - } + MOZ_ASSERT(!GetQueueForTransaction(aTransactionId, aDatabaseId)); // See if we can run this transaction now. DatabaseTransactionInfo* dbTransactionInfo; @@ -579,11 +587,14 @@ TransactionThreadPool::GetQueueForTransaction( return *info->queue; } - TransactionInfo* transactionInfo = new TransactionInfo(this, - aTransactionId, - aDatabaseId, - aObjectStoreNames, - aMode); + TransactionInfo* transactionInfo = + new TransactionInfo(this, + aTransactionId, + aDatabaseId, + aObjectStoreNames, + aMode, + aBackgroundChildLoggingId, + aLoggingSerialNumber); dbTransactionInfo->transactions.Put(aTransactionId, transactionInfo);; @@ -633,26 +644,27 @@ TransactionThreadPool::GetQueueForTransaction( } void -TransactionThreadPool::Dispatch(uint64_t aTransactionId, - const nsACString& aDatabaseId, - const nsTArray& aObjectStoreNames, - uint16_t aMode, - nsIRunnable* aRunnable, - bool aFinish, - FinishCallback* aFinishCallback) +TransactionThreadPool::Start(uint64_t aTransactionId, + const nsACString& aDatabaseId, + const nsTArray& aObjectStoreNames, + uint16_t aMode, + const nsID& aBackgroundChildLoggingId, + int64_t aLoggingSerialNumber, + nsIRunnable* aRunnable) { + AssertIsOnOwningThread(); MOZ_ASSERT(aTransactionId <= mNextTransactionId); + MOZ_ASSERT(aRunnable); MOZ_ASSERT(!mShutdownRequested); - TransactionQueue& queue = GetQueueForTransaction(aTransactionId, - aDatabaseId, - aObjectStoreNames, - aMode); + TransactionQueue& queue = CreateQueueForTransaction(aTransactionId, + aDatabaseId, + aObjectStoreNames, + aMode, + aBackgroundChildLoggingId, + aLoggingSerialNumber); queue.Dispatch(aRunnable); - if (aFinish) { - queue.Finish(aFinishCallback); - } } void @@ -765,14 +777,18 @@ TransactionQueue::TransactionQueue(TransactionThreadPool* aThreadPool, uint64_t aTransactionId, const nsACString& aDatabaseId, const nsTArray& aObjectStoreNames, - uint16_t aMode) -: mMonitor("TransactionQueue::mMonitor"), - mOwningThreadPool(aThreadPool), - mTransactionId(aTransactionId), - mDatabaseId(aDatabaseId), - mObjectStoreNames(aObjectStoreNames), - mMode(aMode), - mShouldFinish(false) + uint16_t aMode, + const nsID& aBackgroundChildLoggingId, + int64_t aLoggingSerialNumber) + : mMonitor("TransactionQueue::mMonitor") + , mOwningThreadPool(aThreadPool) + , mTransactionId(aTransactionId) + , mBackgroundChildLoggingId(aBackgroundChildLoggingId) + , mLoggingSerialNumber(aLoggingSerialNumber) + , mDatabaseId(aDatabaseId) + , mObjectStoreNames(aObjectStoreNames) + , mMode(aMode) + , mShouldFinish(false) { MOZ_ASSERT(aThreadPool); aThreadPool->AssertIsOnOwningThread(); @@ -824,9 +840,11 @@ TransactionThreadPool::TransactionQueue::Run() "TransactionThreadPool::TransactionQueue""Run", js::ProfileEntry::Category::STORAGE); - IDB_PROFILER_MARK("IndexedDB Transaction %llu: Beginning database work", - "IDBTransaction[%llu] DT Start", - mTransaction->GetSerialNumber()); + IDB_LOG_MARK("IndexedDB %s: Parent Transaction[%lld]: " + "Beginning database work", + "IndexedDB %s: P T[%lld]: DB Start", + IDB_LOG_ID_STRING(mBackgroundChildLoggingId), + mLoggingSerialNumber); nsAutoTArray, 10> queue; nsRefPtr finishCallback; @@ -877,9 +895,11 @@ TransactionThreadPool::TransactionQueue::Run() } #endif // DEBUG - IDB_PROFILER_MARK("IndexedDB Transaction %llu: Finished database work", - "IDBTransaction[%llu] DT Done", - mTransaction->GetSerialNumber()); + IDB_LOG_MARK("IndexedDB %s: Parent Transaction[%lld]: " + "Finished database work", + "IndexedDB %s: P T[%lld]: DB End", + IDB_LOG_ID_STRING(mBackgroundChildLoggingId), + mLoggingSerialNumber); nsRefPtr finishTransactionRunnable = new FinishTransactionRunnable(mOwningThreadPool.forget(), diff --git a/dom/indexedDB/TransactionThreadPool.h b/dom/indexedDB/TransactionThreadPool.h index 61c4fa0051e..33c3c3e2d4c 100644 --- a/dom/indexedDB/TransactionThreadPool.h +++ b/dom/indexedDB/TransactionThreadPool.h @@ -15,6 +15,7 @@ #include "nsISupportsImpl.h" #include "nsTArray.h" +struct nsID; class nsIEventTarget; class nsIRunnable; class nsIThreadPool; @@ -55,13 +56,13 @@ public: uint64_t NextTransactionId(); - void Dispatch(uint64_t aTransactionId, - const nsACString& aDatabaseId, - const nsTArray& aObjectStoreNames, - uint16_t aMode, - nsIRunnable* aRunnable, - bool aFinish, - FinishCallback* aFinishCallback); + void Start(uint64_t aTransactionId, + const nsACString& aDatabaseId, + const nsTArray& aObjectStoreNames, + uint16_t aMode, + const nsID& aBackgroundChildLoggingId, + int64_t aLoggingSerialNumber, + nsIRunnable* aRunnable); void Dispatch(uint64_t aTransactionId, const nsACString& aDatabaseId, @@ -114,11 +115,13 @@ private: TransactionQueue* GetQueueForTransaction(uint64_t aTransactionId, const nsACString& aDatabaseId); - TransactionQueue& GetQueueForTransaction( + TransactionQueue& CreateQueueForTransaction( uint64_t aTransactionId, const nsACString& aDatabaseId, const nsTArray& aObjectStoreNames, - uint16_t aMode); + uint16_t aMode, + const nsID& aBackgroundChildLoggingId, + int64_t aLoggingSerialNumber); bool MaybeFireCallback(DatabasesCompleteCallback* aCallback); diff --git a/dom/media/mediasource/MediaSourceReader.cpp b/dom/media/mediasource/MediaSourceReader.cpp index c4ae0cc4045..663b8e80da6 100644 --- a/dom/media/mediasource/MediaSourceReader.cpp +++ b/dom/media/mediasource/MediaSourceReader.cpp @@ -268,7 +268,7 @@ MediaSourceReader::OnVideoNotDecoded(NotDecodedReason aReason) // switching to the end of the buffered range. MOZ_ASSERT(aReason == END_OF_STREAM); if (mVideoReader) { - AdjustEndTime(&mLastVideoTime, mAudioReader); + AdjustEndTime(&mLastVideoTime, mVideoReader); } // See if we can find a different reader that can pick up where we left off. We use the diff --git a/gfx/layers/FrameMetrics.h b/gfx/layers/FrameMetrics.h index 3cc5fc0bfca..5c9c6e87802 100644 --- a/gfx/layers/FrameMetrics.h +++ b/gfx/layers/FrameMetrics.h @@ -234,8 +234,8 @@ public: // The following metrics are all in widget space/device pixels. // - // This is the area within the widget that we're compositing to. It is relative - // to the layer tree origin. + // This is the area within the widget that we're compositing to. It is in the + // same coordinate space as the reference frame for the scrolled frame. // // This is useful because, on mobile, the viewport and composition dimensions // are not always the same. In this case, we calculate the displayport using @@ -256,11 +256,8 @@ public: // space, so each is explained separately. // - // The area of a frame's contents that has been painted, relative to the - // viewport. It is in the same coordinate space as |mViewport|. For example, - // if it is at 0,0, then it's at the same place at the viewport, which is at - // the top-left in the layer, and at the same place as the scroll offset of - // the document. + // The area of a frame's contents that has been painted, relative to + // mCompositionBounds. // // Note that this is structured in such a way that it doesn't depend on the // method layout uses to scroll content. diff --git a/gfx/layers/apz/src/InputQueue.cpp b/gfx/layers/apz/src/InputQueue.cpp index 8b10fe998ca..3cc424aafe1 100644 --- a/gfx/layers/apz/src/InputQueue.cpp +++ b/gfx/layers/apz/src/InputQueue.cpp @@ -127,7 +127,12 @@ InputQueue::ReceiveScrollWheelInput(const nsRefPtr& aTar uint64_t* aOutInputBlockId) { WheelBlockState* block = nullptr; if (!mInputBlockQueue.IsEmpty()) { - block = mInputBlockQueue.LastElement().get()->AsWheelBlock(); + block = mInputBlockQueue.LastElement()->AsWheelBlock(); + + // If the block's APZC has been destroyed, request a new block. + if (block && block->GetTargetApzc()->IsDestroyed()) { + block = nullptr; + } } if (!block) { diff --git a/gfx/layers/apz/util/APZCCallbackHelper.cpp b/gfx/layers/apz/util/APZCCallbackHelper.cpp index 478852cf9fe..8dfede7c20a 100644 --- a/gfx/layers/apz/util/APZCCallbackHelper.cpp +++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp @@ -164,8 +164,7 @@ APZCCallbackHelper::UpdateRootFrame(nsIDOMWindowUtils* aUtils, margins.bottom, element, 0); CSSRect baseCSS = aMetrics.CalculateCompositedRectInCssPixels(); - nsRect base(baseCSS.x * nsPresContext::AppUnitsPerCSSPixel(), - baseCSS.y * nsPresContext::AppUnitsPerCSSPixel(), + nsRect base(0, 0, baseCSS.width * nsPresContext::AppUnitsPerCSSPixel(), baseCSS.height * nsPresContext::AppUnitsPerCSSPixel()); nsLayoutUtils::SetDisplayPortBaseIfNotSet(content, base); @@ -208,8 +207,7 @@ APZCCallbackHelper::UpdateSubFrame(nsIContent* aContent, margins.bottom, element, 0); CSSRect baseCSS = aMetrics.CalculateCompositedRectInCssPixels(); - nsRect base(baseCSS.x * nsPresContext::AppUnitsPerCSSPixel(), - baseCSS.y * nsPresContext::AppUnitsPerCSSPixel(), + nsRect base(0, 0, baseCSS.width * nsPresContext::AppUnitsPerCSSPixel(), baseCSS.height * nsPresContext::AppUnitsPerCSSPixel()); nsLayoutUtils::SetDisplayPortBaseIfNotSet(aContent, base); diff --git a/ipc/glue/BackgroundChildImpl.cpp b/ipc/glue/BackgroundChildImpl.cpp index 0a991a7c1f1..5a270e50fcc 100644 --- a/ipc/glue/BackgroundChildImpl.cpp +++ b/ipc/glue/BackgroundChildImpl.cpp @@ -4,12 +4,14 @@ #include "BackgroundChildImpl.h" +#include "ActorsChild.h" // IndexedDB #include "FileDescriptorSetChild.h" #include "mozilla/Assertions.h" #include "mozilla/dom/PBlobChild.h" #include "mozilla/dom/indexedDB/PBackgroundIDBFactoryChild.h" #include "mozilla/dom/ipc/BlobChild.h" #include "mozilla/ipc/PBackgroundTestChild.h" +#include "nsID.h" #include "nsTraceRefcnt.h" namespace { @@ -48,11 +50,6 @@ namespace ipc { BackgroundChildImpl:: ThreadLocal::ThreadLocal() - : mCurrentTransaction(nullptr) -#ifdef MOZ_ENABLE_PROFILER_SPS - , mNextTransactionSerialNumber(1) - , mNextRequestSerialNumber(1) -#endif { // May happen on any thread! MOZ_COUNT_CTOR(mozilla::ipc::BackgroundChildImpl::ThreadLocal); @@ -136,7 +133,8 @@ BackgroundChildImpl::DeallocPBackgroundTestChild(PBackgroundTestChild* aActor) } BackgroundChildImpl::PBackgroundIDBFactoryChild* -BackgroundChildImpl::AllocPBackgroundIDBFactoryChild() +BackgroundChildImpl::AllocPBackgroundIDBFactoryChild( + const LoggingInfo& aLoggingInfo) { MOZ_CRASH("PBackgroundIDBFactoryChild actors should be manually " "constructed!"); diff --git a/ipc/glue/BackgroundChildImpl.h b/ipc/glue/BackgroundChildImpl.h index afdb52e8993..0fedb67944a 100644 --- a/ipc/glue/BackgroundChildImpl.h +++ b/ipc/glue/BackgroundChildImpl.h @@ -7,14 +7,13 @@ #include "mozilla/Attributes.h" #include "mozilla/ipc/PBackgroundChild.h" - -template class nsAutoPtr; +#include "nsAutoPtr.h" namespace mozilla { namespace dom { namespace indexedDB { -class IDBTransaction; +class ThreadLocal; } // namespace indexedDB } // namespace dom @@ -53,7 +52,7 @@ protected: DeallocPBackgroundTestChild(PBackgroundTestChild* aActor) MOZ_OVERRIDE; virtual PBackgroundIDBFactoryChild* - AllocPBackgroundIDBFactoryChild() MOZ_OVERRIDE; + AllocPBackgroundIDBFactoryChild(const LoggingInfo& aLoggingInfo) MOZ_OVERRIDE; virtual bool DeallocPBackgroundIDBFactoryChild(PBackgroundIDBFactoryChild* aActor) @@ -78,12 +77,7 @@ class BackgroundChildImpl::ThreadLocal MOZ_FINAL friend class nsAutoPtr; public: - mozilla::dom::indexedDB::IDBTransaction* mCurrentTransaction; - -#ifdef MOZ_ENABLE_PROFILER_SPS - uint64_t mNextTransactionSerialNumber; - uint64_t mNextRequestSerialNumber; -#endif + nsAutoPtr mIndexedDBThreadLocal; public: ThreadLocal(); diff --git a/ipc/glue/BackgroundParentImpl.cpp b/ipc/glue/BackgroundParentImpl.cpp index 1dd7cbedb56..0d5eeb2d5a3 100644 --- a/ipc/glue/BackgroundParentImpl.cpp +++ b/ipc/glue/BackgroundParentImpl.cpp @@ -119,7 +119,8 @@ BackgroundParentImpl::DeallocPBackgroundTestParent( } auto -BackgroundParentImpl::AllocPBackgroundIDBFactoryParent() +BackgroundParentImpl::AllocPBackgroundIDBFactoryParent( + const LoggingInfo& aLoggingInfo) -> PBackgroundIDBFactoryParent* { using mozilla::dom::indexedDB::AllocPBackgroundIDBFactoryParent; @@ -127,12 +128,13 @@ BackgroundParentImpl::AllocPBackgroundIDBFactoryParent() AssertIsInMainProcess(); AssertIsOnBackgroundThread(); - return AllocPBackgroundIDBFactoryParent(); + return AllocPBackgroundIDBFactoryParent(aLoggingInfo); } bool BackgroundParentImpl::RecvPBackgroundIDBFactoryConstructor( - PBackgroundIDBFactoryParent* aActor) + PBackgroundIDBFactoryParent* aActor, + const LoggingInfo& aLoggingInfo) { using mozilla::dom::indexedDB::RecvPBackgroundIDBFactoryConstructor; @@ -140,18 +142,20 @@ BackgroundParentImpl::RecvPBackgroundIDBFactoryConstructor( AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); - return RecvPBackgroundIDBFactoryConstructor(aActor); + return RecvPBackgroundIDBFactoryConstructor(aActor, aLoggingInfo); } bool BackgroundParentImpl::DeallocPBackgroundIDBFactoryParent( PBackgroundIDBFactoryParent* aActor) { + using mozilla::dom::indexedDB::DeallocPBackgroundIDBFactoryParent; + AssertIsInMainProcess(); AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); - return mozilla::dom::indexedDB::DeallocPBackgroundIDBFactoryParent(aActor); + return DeallocPBackgroundIDBFactoryParent(aActor); } auto diff --git a/ipc/glue/BackgroundParentImpl.h b/ipc/glue/BackgroundParentImpl.h index ba9e78bd07e..e0a6d7240e0 100644 --- a/ipc/glue/BackgroundParentImpl.h +++ b/ipc/glue/BackgroundParentImpl.h @@ -33,10 +33,12 @@ protected: DeallocPBackgroundTestParent(PBackgroundTestParent* aActor) MOZ_OVERRIDE; virtual PBackgroundIDBFactoryParent* - AllocPBackgroundIDBFactoryParent() MOZ_OVERRIDE; + AllocPBackgroundIDBFactoryParent(const LoggingInfo& aLoggingInfo) + MOZ_OVERRIDE; virtual bool - RecvPBackgroundIDBFactoryConstructor(PBackgroundIDBFactoryParent* aActor) + RecvPBackgroundIDBFactoryConstructor(PBackgroundIDBFactoryParent* aActor, + const LoggingInfo& aLoggingInfo) MOZ_OVERRIDE; virtual bool diff --git a/ipc/glue/PBackground.ipdl b/ipc/glue/PBackground.ipdl index 89756c3410a..4f4a155589e 100644 --- a/ipc/glue/PBackground.ipdl +++ b/ipc/glue/PBackground.ipdl @@ -8,6 +8,7 @@ include protocol PBlob; include protocol PFileDescriptorSet; include DOMTypes; +include PBackgroundIDBSharedTypes; namespace mozilla { namespace ipc { @@ -23,7 +24,7 @@ parent: // Only called at startup during mochitests to check the basic infrastructure. PBackgroundTest(nsCString testArg); - PBackgroundIDBFactory(); + PBackgroundIDBFactory(LoggingInfo loggingInfo); both: PBlob(BlobConstructorParams params); diff --git a/ipc/glue/moz.build b/ipc/glue/moz.build index b4e2b68ca37..6ea3abfd87b 100644 --- a/ipc/glue/moz.build +++ b/ipc/glue/moz.build @@ -130,6 +130,7 @@ SOURCES += [ ] LOCAL_INCLUDES += [ + '/dom/indexedDB', '/xpcom/build', ] diff --git a/media/libcubeb/src/cubeb_wasapi.cpp b/media/libcubeb/src/cubeb_wasapi.cpp index 8a272b0d89c..b22b3b44ba2 100644 --- a/media/libcubeb/src/cubeb_wasapi.cpp +++ b/media/libcubeb/src/cubeb_wasapi.cpp @@ -831,6 +831,7 @@ void wasapi_stream_destroy(cubeb_stream * stm) SafeRelease(stm->client); SafeRelease(stm->render_client); SafeRelease(stm->audio_clock); + SafeRelease(stm->audio_stream_volume); cubeb_resampler_destroy(stm->resampler); diff --git a/mfbt/SegmentedVector.h b/mfbt/SegmentedVector.h index 1223bedea6c..e583e4e4482 100644 --- a/mfbt/SegmentedVector.h +++ b/mfbt/SegmentedVector.h @@ -32,12 +32,24 @@ namespace mozilla { -// IdealSegmentSize is how big each segment will be in bytes (or as close as is -// possible). It's best to choose a size that's a power-of-two (to avoid slop) -// and moderately large (not too small so segment allocations are infrequent, -// and not too large so that not too much space is wasted when the final -// segment is not full). Something like 4096 or 8192 is probably good. -template class SegmentedVector : private AllocPolicy { diff --git a/mfbt/tests/TestSegmentedVector.cpp b/mfbt/tests/TestSegmentedVector.cpp index 265e7cde3ff..c426f6d927c 100644 --- a/mfbt/tests/TestSegmentedVector.cpp +++ b/mfbt/tests/TestSegmentedVector.cpp @@ -147,7 +147,7 @@ void TestSegmentCapacitiesAndAlignments() SegmentedVector v3(999); SegmentedVector v4(10); SegmentedVector v5(1234); - SegmentedVector v6(4096); + SegmentedVector v6(4096); // 4096 is the default segment size SegmentedVector, 100> v7(100); } diff --git a/mobile/android/base/overlays/service/OverlayActionService.java b/mobile/android/base/overlays/service/OverlayActionService.java index fea82cf3f20..1f0937dac1f 100644 --- a/mobile/android/base/overlays/service/OverlayActionService.java +++ b/mobile/android/base/overlays/service/OverlayActionService.java @@ -135,7 +135,7 @@ public class OverlayActionService extends Service { OverlayToastHelper.showFailureToast(getApplicationContext(), shareMethod.getFailureMessage()); break; default: - Assert.isTrue(false, "Unknown share method result code: " + result); + Assert.fail("Unknown share method result code: " + result); break; } } diff --git a/mobile/android/base/overlays/ui/SendTabDeviceListArrayAdapter.java b/mobile/android/base/overlays/ui/SendTabDeviceListArrayAdapter.java index 32c6054ad88..1f885af6767 100644 --- a/mobile/android/base/overlays/ui/SendTabDeviceListArrayAdapter.java +++ b/mobile/android/base/overlays/ui/SendTabDeviceListArrayAdapter.java @@ -163,7 +163,7 @@ public class SendTabDeviceListArrayAdapter extends ArrayAdapter { private class Submitter extends AbstractCommunicator { private static final String SUBMIT_URL = "https://location.services.mozilla.com/v1/submit"; - public Submitter() { - super(Prefs.getInstance().getUserAgent()); - } - @Override public String getUrlString() { return SUBMIT_URL; diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/uploadthread/UploadAlarmReceiver.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/uploadthread/UploadAlarmReceiver.java index b46400c2ef6..9292cee5bb0 100644 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/uploadthread/UploadAlarmReceiver.java +++ b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/uploadthread/UploadAlarmReceiver.java @@ -48,7 +48,8 @@ public class UploadAlarmReceiver extends BroadcastReceiver { @Override protected void onHandleIntent(Intent intent) { - boolean isRepeating = intent.getBooleanExtra(EXTRA_IS_REPEATING, true); + // Default to a repeating alarm, which is what Fennec Stumbler uses + boolean isRepeating = (intent == null)? true : intent.getBooleanExtra(EXTRA_IS_REPEATING, true); if (DataStorageManager.getInstance() == null) { DataStorageManager.createGlobalInstance(this, null); } @@ -77,9 +78,9 @@ public class UploadAlarmReceiver extends BroadcastReceiver { !AsyncUploader.isUploading()) { Log.d(LOG_TAG, "Alarm upload(), call AsyncUploader"); AsyncUploader.UploadSettings settings = - new AsyncUploader.UploadSettings(Prefs.getInstance().getWifiScanAlways(), Prefs.getInstance().getUseWifiOnly()); + new AsyncUploader.UploadSettings(Prefs.getInstance(this).getWifiScanAlways(), Prefs.getInstance(this).getUseWifiOnly()); AsyncUploader uploader = new AsyncUploader(settings, null); - uploader.setNickname(Prefs.getInstance().getNickname()); + uploader.setNickname(Prefs.getInstance(this).getNickname()); uploader.execute(); // we could listen for completion and cancel, instead, cancel on next alarm when db empty } diff --git a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/utils/AbstractCommunicator.java b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/utils/AbstractCommunicator.java index 59ee78e979b..70816371a39 100644 --- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/utils/AbstractCommunicator.java +++ b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/utils/AbstractCommunicator.java @@ -61,14 +61,16 @@ public abstract class AbstractCommunicator { return null; } - public AbstractCommunicator(String userAgent) { - mUserAgent = userAgent; + public AbstractCommunicator() { + Prefs prefs = Prefs.getInstanceWithoutContext(); + mUserAgent = (prefs != null)? prefs.getUserAgent() : "fennec-stumbler-unset-user-agent"; } private void openConnectionAndSetHeaders() { try { - if (sMozApiKey == null) { - sMozApiKey = Prefs.getInstance().getMozApiKey(); + Prefs prefs = Prefs.getInstanceWithoutContext(); + if (sMozApiKey == null || prefs != null) { + sMozApiKey = prefs.getMozApiKey(); } URL url = new URL(getUrlString() + "?key=" + sMozApiKey); mHttpURLConnection = (HttpURLConnection) url.openConnection(); diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index c800658c83e..a0e314b69e8 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -119,6 +119,12 @@ pref("dom.indexedDB.enabled", true); pref("dom.indexedDB.warningQuota", 50); // Whether or not indexedDB experimental features are enabled. pref("dom.indexedDB.experimental", false); +// Enable indexedDB logging. +pref("dom.indexedDB.logging.enabled", true); +// Detailed output in log messages. +pref("dom.indexedDB.logging.details", true); +// Enable profiler marks for indexedDB events. +pref("dom.indexedDB.logging.profiler-marks", false); // Whether or not Web Workers are enabled. pref("dom.workers.enabled", true); diff --git a/netwerk/base/public/nsNetUtil.h b/netwerk/base/public/nsNetUtil.h index b58f043b57c..9fe75cf5489 100644 --- a/netwerk/base/public/nsNetUtil.h +++ b/netwerk/base/public/nsNetUtil.h @@ -200,13 +200,17 @@ NS_NewFileURI(nsIURI* *result, inline nsresult NS_NewChannelInternal(nsIChannel** outChannel, nsIURI* aUri, - nsILoadInfo* aLoadInfo, + nsINode* aRequestingNode, + nsIPrincipal* aRequestingPrincipal, + nsIPrincipal* aTriggeringPrincipal, + nsSecurityFlags aSecurityFlags, + nsContentPolicyType aContentPolicyType, + nsIURI* aBaseURI = nullptr, nsILoadGroup* aLoadGroup = nullptr, nsIInterfaceRequestor* aCallbacks = nullptr, nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL, nsIIOService* aIoService = nullptr) { - NS_ASSERTION(aLoadInfo, "Can not create channel without aLoadInfo!"); NS_ENSURE_ARG_POINTER(outChannel); nsCOMPtr grip; @@ -234,11 +238,31 @@ NS_NewChannelInternal(nsIChannel** outChannel, rv = channel->SetLoadFlags(aLoadFlags | (normalLoadFlags & nsIChannel::LOAD_REPLACE)); NS_ENSURE_SUCCESS(rv, rv); } - channel->SetLoadInfo(aLoadInfo); + + // Some channels might already have a loadInfo attached at this + // point (see bug 1104623). We have to make sure to update + // security flags in such cases before we set the loadinfo. + // Once bug 1087442 lands, this problem disappears because we + // attach the loadinfo in each individual protocol handler. + nsCOMPtr loadInfo; + channel->GetLoadInfo(getter_AddRefs(loadInfo)); + if (loadInfo) { + aSecurityFlags |= loadInfo->GetSecurityFlags(); + } + + // create a new Loadinfo with the potentially updated securityFlags + loadInfo = + new mozilla::LoadInfo(aRequestingPrincipal, aTriggeringPrincipal, + aRequestingNode, aSecurityFlags, + aContentPolicyType, aBaseURI); + if (!loadInfo) { + return NS_ERROR_UNEXPECTED; + } + channel->SetLoadInfo(loadInfo); // If we're sandboxed, make sure to clear any owner the channel // might already have. - if (aLoadInfo->GetLoadingSandboxed()) { + if (loadInfo->GetLoadingSandboxed()) { channel->SetOwner(nullptr); } @@ -249,31 +273,27 @@ NS_NewChannelInternal(nsIChannel** outChannel, inline nsresult NS_NewChannelInternal(nsIChannel** outChannel, nsIURI* aUri, - nsINode* aRequestingNode, - nsIPrincipal* aRequestingPrincipal, - nsIPrincipal* aTriggeringPrincipal, - nsSecurityFlags aSecurityFlags, - nsContentPolicyType aContentPolicyType, + nsILoadInfo* aLoadInfo, nsILoadGroup* aLoadGroup = nullptr, nsIInterfaceRequestor* aCallbacks = nullptr, nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL, nsIIOService* aIoService = nullptr) { - NS_ASSERTION(aRequestingPrincipal, "Can not create channel without a requesting Principal!"); - - nsCOMPtr loadInfo = - new mozilla::LoadInfo(aRequestingPrincipal, aTriggeringPrincipal, - aRequestingNode, aSecurityFlags, aContentPolicyType); - if (!loadInfo) { - return NS_ERROR_UNEXPECTED; - } - return NS_NewChannelInternal(outChannel, - aUri, - loadInfo, - aLoadGroup, - aCallbacks, - aLoadFlags, - aIoService); + MOZ_ASSERT(aLoadInfo, "Can not create a channel without a loadInfo"); + nsresult rv = NS_NewChannelInternal(outChannel, + aUri, + aLoadInfo->LoadingNode(), + aLoadInfo->LoadingPrincipal(), + aLoadInfo->TriggeringPrincipal(), + aLoadInfo->GetSecurityFlags(), + aLoadInfo->GetContentPolicyType(), + aLoadInfo->BaseURI(), + aLoadGroup, + aCallbacks, + aLoadFlags, + aIoService); + NS_ENSURE_SUCCESS(rv, rv); + return NS_OK; } inline nsresult /*NS_NewChannelWithNodeAndTriggeringPrincipal */ @@ -297,6 +317,7 @@ NS_NewChannelWithTriggeringPrincipal(nsIChannel** outChannel, aTriggeringPrincipal, aSecurityFlags, aContentPolicyType, + nullptr, // aBaseURI aLoadGroup, aCallbacks, aLoadFlags, @@ -323,6 +344,7 @@ NS_NewChannelWithTriggeringPrincipal(nsIChannel** outChannel, aTriggeringPrincipal, aSecurityFlags, aContentPolicyType, + nullptr, // aBaseURI aLoadGroup, aCallbacks, aLoadFlags, @@ -348,6 +370,7 @@ NS_NewChannel(nsIChannel** outChannel, nullptr, // aTriggeringPrincipal aSecurityFlags, aContentPolicyType, + nullptr, // aBaseURI aLoadGroup, aCallbacks, aLoadFlags, @@ -372,6 +395,7 @@ NS_NewChannel(nsIChannel** outChannel, nullptr, // aTriggeringPrincipal aSecurityFlags, aContentPolicyType, + nullptr, // aBaseURI aLoadGroup, aCallbacks, aLoadFlags, @@ -406,6 +430,7 @@ NS_OpenURIInternal(nsIInputStream** outStream, aTriggeringPrincipal, aSecurityFlags, aContentPolicyType, + nullptr, // aBaseURI aLoadGroup, aCallbacks, aLoadFlags, @@ -962,6 +987,7 @@ NS_NewStreamLoaderInternal(nsIStreamLoader** outStream, nullptr, // aTriggeringPrincipal aSecurityFlags, aContentPolicyType, + nullptr, // aBaseURI aLoadGroup, aCallbacks, aLoadFlags); diff --git a/testing/mochitest/browser-test.js b/testing/mochitest/browser-test.js index a989d156c0f..9d4c638cb0c 100644 --- a/testing/mochitest/browser-test.js +++ b/testing/mochitest/browser-test.js @@ -15,9 +15,6 @@ Cu.import("resource://gre/modules/Task.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Services", "resource://gre/modules/Services.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "BrowserNewTabPreloader", - "resource:///modules/BrowserNewTabPreloader.jsm"); - XPCOMUtils.defineLazyModuleGetter(this, "CustomizationTabPreloader", "resource:///modules/CustomizationTabPreloader.jsm"); @@ -504,7 +501,13 @@ Tester.prototype = { Cu.import("resource://gre/modules/BackgroundPageThumbs.jsm", {}); BackgroundPageThumbs._destroy(); - BrowserNewTabPreloader.uninit(); + // Destroy preloaded browsers. + if (gBrowser._preloadedBrowser) { + let browser = gBrowser._preloadedBrowser; + gBrowser._preloadedBrowser = null; + gBrowser.getNotificationBox(browser).remove(); + } + CustomizationTabPreloader.uninit(); SocialFlyout.unload(); SocialShare.uninit(); diff --git a/toolkit/devtools/server/actors/highlighter.js b/toolkit/devtools/server/actors/highlighter.js index bc9ea1da67e..dc47bf74d59 100644 --- a/toolkit/devtools/server/actors/highlighter.js +++ b/toolkit/devtools/server/actors/highlighter.js @@ -684,16 +684,15 @@ AutoRefreshHighlighter.prototype = { _startRefreshLoop: function() { let win = this.currentNode.ownerDocument.defaultView; this.rafID = win.requestAnimationFrame(this._startRefreshLoop.bind(this)); + this.rafWin = win; this.update(); }, _stopRefreshLoop: function() { - if (!this.rafID) { - return; + if (this.rafID && !Cu.isDeadWrapper(this.rafWin)) { + this.rafWin.cancelAnimationFrame(this.rafID); } - let win = this.currentNode.ownerDocument.defaultView; - win.cancelAnimationFrame(this.rafID); - this.rafID = null; + this.rafID = this.rafWin = null; }, destroy: function() {