author | Wes Kocher <wkocher@mozilla.com> |
Fri, 29 Apr 2016 14:54:44 -0700 | |
changeset 334468 | 6ce48a7c22d55187daa471ff10d136b7ab02a5ee |
parent 334288 | 8c3fd523d75bd30f691ca2d6cfdad18d576392a1 (current diff) |
parent 334467 | 1d4795f0b4e28db3ddf6a5751653c179fef68726 (diff) |
child 334469 | e640f0802a806921d0533168e2bdd2b56cd9829a |
push id | 6249 |
push user | jlund@mozilla.com |
push date | Mon, 01 Aug 2016 13:59:36 +0000 |
treeherder | mozilla-beta@bad9d4f5bf7e [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | merge |
milestone | 49.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/CLOBBER +++ b/CLOBBER @@ -17,9 +17,9 @@ # # Modifying this file will now automatically clobber the buildbot machines \o/ # # Are you updating CLOBBER because you think it's needed for your WebIDL # changes to stick? As of bug 928195, this shouldn't be necessary! Please # don't change CLOBBER for WebIDL changes any more. -Merge day clobber \ No newline at end of file +Bug 1265131 - Update Skia to m51 branch
--- a/accessible/base/EventTree.cpp +++ b/accessible/base/EventTree.cpp @@ -178,23 +178,22 @@ TreeMutation::Done() //////////////////////////////////////////////////////////////////////////////// // EventTree void EventTree::Process() { - EventTree* node = mFirst; - while (node) { + while (mFirst) { // Skip a node and its subtree if its container is not in the document. - if (node->mContainer->IsInDocument()) { - node->Process(); + if (mFirst->mContainer->IsInDocument()) { + mFirst->Process(); } - node = node->mNext; + mFirst = mFirst->mNext.forget(); } MOZ_ASSERT(mContainer || mDependentEvents.IsEmpty(), "No container, no events"); MOZ_ASSERT(!mContainer || !mContainer->IsDefunct(), "Processing events for defunct container"); // Fire mutation events.
--- a/accessible/base/NotificationController.cpp +++ b/accessible/base/NotificationController.cpp @@ -397,17 +397,16 @@ NotificationController::WillRefresh(mozi mRelocations.Clear(); // If a generic notification occurs after this point then we may be allowed to // process it synchronously. However we do not want to reenter if fireing // events causes script to run. mObservingState = eRefreshProcessing; mEventTree.Process(); - mEventTree.Clear(); ProcessEventQueue(); if (IPCAccessibilityActive()) { size_t newDocCount = newChildDocs.Length(); for (size_t i = 0; i < newDocCount; i++) { DocAccessible* childDoc = newChildDocs[i]; Accessible* parent = childDoc->Parent();
--- a/accessible/ipc/DocAccessibleParent.h +++ b/accessible/ipc/DocAccessibleParent.h @@ -161,17 +161,17 @@ private: enum { ALLOW_MEMMOVE = true }; ProxyAccessible* mProxy; }; uint32_t AddSubtree(ProxyAccessible* aParent, const nsTArray<AccessibleData>& aNewTree, uint32_t aIdx, uint32_t aIdxInParent); - MOZ_WARN_UNUSED_RESULT bool CheckDocTree() const; + MOZ_MUST_USE bool CheckDocTree() const; xpcAccessibleGeneric* GetXPCAccessible(ProxyAccessible* aProxy); nsTArray<DocAccessibleParent*> mChildDocs; DocAccessibleParent* mParentDoc; /* * Conceptually this is a map from IDs to proxies, but we store the ID in the * proxy object so we can't use a real map.
--- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -522,18 +522,16 @@ pref("b2g.update.apply-prompt-timeout", pref("b2g.update.apply-idle-timeout", 600000); // milliseconds // Amount of time after which connection will be restarted if no progress pref("b2g.update.download-watchdog-timeout", 120000); // milliseconds pref("b2g.update.download-watchdog-max-retries", 5); pref("app.update.enabled", true); pref("app.update.auto", false); pref("app.update.silent", false); -pref("app.update.mode", 0); -pref("app.update.incompatible.mode", 0); pref("app.update.staging.enabled", true); pref("app.update.service.enabled", true); pref("app.update.url", "https://aus5.mozilla.org/update/5/%PRODUCT%/%VERSION%/%BUILD_ID%/%PRODUCT_DEVICE%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/%IMEI%/update.xml"); pref("app.update.channel", "@MOZ_UPDATE_CHANNEL@"); // Interval at which update manifest is fetched. In units of seconds. pref("app.update.interval", 86400); // 1 day @@ -882,23 +880,16 @@ pref("disk_space_watcher.enabled", true) // SNTP preferences. pref("network.sntp.maxRetryCount", 10); pref("network.sntp.refreshPeriod", 86400); // In seconds. pref("network.sntp.pools", // Servers separated by ';'. "0.pool.ntp.org;1.pool.ntp.org;2.pool.ntp.org;3.pool.ntp.org"); pref("network.sntp.port", 123); pref("network.sntp.timeout", 30); // In seconds. -// Enable dataStore -pref("dom.datastore.enabled", true); -// When an entry is changed, use two timers to fire system messages in a more -// moderate pattern. -pref("dom.datastore.sysMsgOnChangeShortTimeoutSec", 10); -pref("dom.datastore.sysMsgOnChangeLongTimeoutSec", 60); - // DOM Inter-App Communication API. pref("dom.inter-app-communication-api.enabled", true); // Allow ADB to run for this many hours before disabling // (only applies when marionette is disabled) // 0 disables the timer. pref("b2g.adb.timeout-hours", 12); @@ -1003,16 +994,19 @@ pref("dom.apps.reviewer_paths", "/review // New implementation to unify touch-caret and selection-carets. pref("layout.accessiblecaret.enabled", true); // Show the selection bars at the two ends of the selection highlight. Required // by the spec in bug 921965. pref("layout.accessiblecaret.bar.enabled", true); +// Hide the caret in cursor mode after 3 seconds. +pref("layout.accessiblecaret.timeout_ms", 3000); + // APZ on real devices supports long tap events. #ifdef MOZ_WIDGET_GONK pref("layout.accessiblecaret.use_long_tap_injector", false); #endif // Hide carets and text selection dialog during scrolling. pref("layout.accessiblecaret.always_show_when_scrolling", false);
--- a/b2g/chrome/content/shell.js +++ b/b2g/chrome/content/shell.js @@ -2,17 +2,16 @@ /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ /* 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/. */ window.performance.mark('gecko-shell-loadstart'); Cu.import('resource://gre/modules/ContactService.jsm'); -Cu.import('resource://gre/modules/DataStoreChangeNotifier.jsm'); Cu.import('resource://gre/modules/AlarmService.jsm'); Cu.import('resource://gre/modules/ActivitiesService.jsm'); Cu.import('resource://gre/modules/NotificationDB.jsm'); Cu.import('resource://gre/modules/Payment.jsm'); Cu.import("resource://gre/modules/AppsUtils.jsm"); Cu.import('resource://gre/modules/UserAgentOverrides.jsm'); Cu.import('resource://gre/modules/Keyboard.jsm'); Cu.import('resource://gre/modules/ErrorPage.jsm');
--- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -927,20 +927,16 @@ bin/libfreebl_32int64_3.so #ifndef MOZ_WIDGET_GONK @RESPATH@/components/SimulatorScreen.js #endif @RESPATH@/components/FxAccountsUIGlue.js @RESPATH@/components/services_fxaccounts.xpt -@RESPATH@/components/DataStore.manifest -@RESPATH@/components/DataStoreImpl.js -@RESPATH@/components/dom_datastore.xpt - @RESPATH@/components/MobileIdentity.manifest @RESPATH@/components/MobileIdentity.js @RESPATH@/components/dom_mobileidentity.xpt @RESPATH@/components/MobileIdentityUIGlue.js @RESPATH@/components/services_mobileidentity.xpt #ifdef MOZ_WEBSPEECH @RESPATH@/components/dom_webspeechsynth.xpt
--- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -142,24 +142,21 @@ pref("app.update.backgroundMaxErrors", 1 // not valid. Bug 1182352 will remove the update xml certificate checks and the // following two preferences. pref("app.update.cert.requireBuiltIn", false); pref("app.update.cert.checkAttributes", false); // Whether or not app updates are enabled pref("app.update.enabled", true); -// This preference turns on app.update.mode and allows automatic download and -// install to take place. We use a separate boolean toggle for this to make -// the UI easier to construct. +// If set to true, the Update Service will automatically download updates when +// app updates are enabled per the app.update.enabled preference and if the user +// can apply updates. pref("app.update.auto", true); -// See chart in nsUpdateService.js source for more details -pref("app.update.mode", 1); - // If set to true, the Update Service will present no UI for any event. pref("app.update.silent", false); // If set to true, the hamburger button will show badges for update events. #ifndef RELEASE_BUILD pref("app.update.badge", true); #else pref("app.update.badge", false); @@ -186,23 +183,16 @@ pref("app.update.idletime", 60); // Whether or not we show a dialog box informing the user that the update was // successfully applied. This is off in Firefox by default since we show a // upgrade start page instead! Other apps may wish to show this UI, and supply // a whatsNewURL field in their brand.properties that contains a link to a page // which tells users what's new in this new update. pref("app.update.showInstalledUI", false); -// 0 = suppress prompting for incompatibilities if there are updates available -// to newer versions of installed addons that resolve them. -// 1 = suppress prompting for incompatibilities only if there are VersionInfo -// updates available to installed addons that resolve them, not newer -// versions. -pref("app.update.incompatible.mode", 0); - // Whether or not to attempt using the service for updates. #ifdef MOZ_MAINTENANCE_SERVICE pref("app.update.service.enabled", true); #endif // Symmetric (can be overridden by individual extensions) update preferences. // e.g. // extensions.{GUID}.update.enabled @@ -1052,17 +1042,16 @@ pref("services.sync.prefs.sync.accessibi pref("services.sync.prefs.sync.accessibility.typeaheadfind", true); pref("services.sync.prefs.sync.accessibility.typeaheadfind.linksonly", true); pref("services.sync.prefs.sync.addons.ignoreUserEnabledChanges", true); // The addons prefs related to repository verification are intentionally // not synced for security reasons. If a system is compromised, a user // could weaken the pref locally, install an add-on from an untrusted // source, and this would propagate automatically to other, // uncompromised Sync-connected devices. -pref("services.sync.prefs.sync.app.update.mode", true); pref("services.sync.prefs.sync.browser.formfill.enable", true); pref("services.sync.prefs.sync.browser.link.open_newwindow", true); pref("services.sync.prefs.sync.browser.newtabpage.enabled", true); pref("services.sync.prefs.sync.browser.newtabpage.enhanced", true); pref("services.sync.prefs.sync.browser.newtabpage.pinned", true); pref("services.sync.prefs.sync.browser.offline-apps.notify", true); pref("services.sync.prefs.sync.browser.safebrowsing.enabled", true); pref("services.sync.prefs.sync.browser.safebrowsing.malware.enabled", true);
--- a/browser/base/content/aboutDialog-appUpdater.js +++ b/browser/base/content/aboutDialog-appUpdater.js @@ -1,17 +1,16 @@ /* 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/. */ // Note: this file is included in aboutDialog.xul if MOZ_UPDATER is defined. Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); Components.utils.import("resource://gre/modules/DownloadUtils.jsm"); -Components.utils.import("resource://gre/modules/AddonManager.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils", "resource://gre/modules/UpdateUtils.jsm"); var gAppUpdater; function onUnload(aEvent) { if (gAppUpdater.isChecking) @@ -186,31 +185,16 @@ appUpdater.prototype = checkForUpdates: function() { this.selectPanel("checkingForUpdates"); this.isChecking = true; this.checker.checkForUpdates(this.updateCheckListener, true); // after checking, onCheckComplete() is called }, /** - * Check for addon compat, or start the download right away - */ - doUpdate: function() { - // skip the compatibility check if the update doesn't provide appVersion, - // or the appVersion is unchanged, e.g. nightly update - if (!this.update.appVersion || - Services.vc.compare(gAppUpdater.update.appVersion, - Services.appinfo.version) == 0) { - this.startDownload(); - } else { - this.checkAddonCompatibility(); - } - }, - - /** * Handles oncommand for the "Restart to Update" button * which is presented after the download has been downloaded. */ buttonRestartAfterDownload: function() { if (!this.isPending && !this.isApplied) return; // Notify all windows that an application quit has been requested. @@ -232,17 +216,17 @@ appUpdater.prototype = } appStartup.quit(Components.interfaces.nsIAppStartup.eAttemptQuit | Components.interfaces.nsIAppStartup.eRestart); }, /** * Handles oncommand for the "Apply Update…" button - * which is presented if we need to show the billboard or license. + * which is presented if we need to show the billboard. */ buttonApplyBillboard: function() { const URI_UPDATE_PROMPT_DIALOG = "chrome://mozapps/content/update/updates.xul"; var ary = null; ary = Components.classes["@mozilla.org/supports-array;1"]. createInstance(Components.interfaces.nsISupportsArray); ary.AppendElement(this.update); var openFeatures = "chrome,centerscreen,dialog=no,resizable=no,titlebar,toolbar=no"; @@ -277,25 +261,23 @@ appUpdater.prototype = return; } if (!gAppUpdater.aus.canApplyUpdates) { gAppUpdater.selectPanel("manualUpdate"); return; } - // Firefox no longer displays a license for updates and the licenseURL - // check is just in case a distibution does. - if (gAppUpdater.update.billboardURL || gAppUpdater.update.licenseURL) { + if (gAppUpdater.update.billboardURL) { gAppUpdater.selectPanel("applyBillboard"); return; } if (gAppUpdater.updateAuto) // automatically download and install - gAppUpdater.doUpdate(); + gAppUpdater.startDownload(); else // ask gAppUpdater.selectPanel("downloadAndInstall"); }, /** * See nsIUpdateService.idl */ onError: function(aRequest, aUpdate) { @@ -313,128 +295,16 @@ appUpdater.prototype = if (!aIID.equals(Components.interfaces.nsIUpdateCheckListener) && !aIID.equals(Components.interfaces.nsISupports)) throw Components.results.NS_ERROR_NO_INTERFACE; return this; } }, /** - * Checks the compatibility of add-ons for the application update. - */ - checkAddonCompatibility: function() { - try { - var hotfixID = Services.prefs.getCharPref(PREF_EM_HOTFIX_ID); - } - catch (e) { } - - var self = this; - AddonManager.getAllAddons(function(aAddons) { - self.addons = []; - self.addonsCheckedCount = 0; - aAddons.forEach(function(aAddon) { - // Protect against code that overrides the add-ons manager and doesn't - // implement the isCompatibleWith or the findUpdates method. - if (!("isCompatibleWith" in aAddon) || !("findUpdates" in aAddon)) { - let errMsg = "Add-on doesn't implement either the isCompatibleWith " + - "or the findUpdates method!"; - if (aAddon.id) - errMsg += " Add-on ID: " + aAddon.id; - Components.utils.reportError(errMsg); - return; - } - - // If an add-on isn't appDisabled and isn't userDisabled then it is - // either active now or the user expects it to be active after the - // restart. If that is the case and the add-on is not installed by the - // application and is not compatible with the new application version - // then the user should be warned that the add-on will become - // incompatible. If an addon's type equals plugin it is skipped since - // checking plugins compatibility information isn't supported and - // getting the scope property of a plugin breaks in some environments - // (see bug 566787). The hotfix add-on is also ignored as it shouldn't - // block the user from upgrading. - try { - if (aAddon.type != "plugin" && aAddon.id != hotfixID && - !aAddon.appDisabled && !aAddon.userDisabled && - aAddon.scope != AddonManager.SCOPE_APPLICATION && - aAddon.isCompatible && - !aAddon.isCompatibleWith(self.update.appVersion, - self.update.platformVersion)) - self.addons.push(aAddon); - } - catch (e) { - Components.utils.reportError(e); - } - }); - self.addonsTotalCount = self.addons.length; - if (self.addonsTotalCount == 0) { - self.startDownload(); - return; - } - - self.checkAddonsForUpdates(); - }); - }, - - /** - * Checks if there are updates for add-ons that are incompatible with the - * application update. - */ - checkAddonsForUpdates: function() { - this.addons.forEach(function(aAddon) { - aAddon.findUpdates(this, AddonManager.UPDATE_WHEN_NEW_APP_DETECTED, - this.update.appVersion, - this.update.platformVersion); - }, this); - }, - - /** - * See XPIProvider.jsm - */ - onCompatibilityUpdateAvailable: function(aAddon) { - for (var i = 0; i < this.addons.length; ++i) { - if (this.addons[i].id == aAddon.id) { - this.addons.splice(i, 1); - break; - } - } - }, - - /** - * See XPIProvider.jsm - */ - onUpdateAvailable: function(aAddon, aInstall) { - if (!Services.blocklist.isAddonBlocklisted(aAddon, - this.update.appVersion, - this.update.platformVersion)) { - // Compatibility or new version updates mean the same thing here. - this.onCompatibilityUpdateAvailable(aAddon); - } - }, - - /** - * See XPIProvider.jsm - */ - onUpdateFinished: function(aAddon) { - ++this.addonsCheckedCount; - - if (this.addonsCheckedCount < this.addonsTotalCount) - return; - - if (this.addons.length == 0) { - // Compatibility updates or new version updates were found for all add-ons - this.startDownload(); - return; - } - - this.selectPanel("applyBillboard"); - }, - - /** * Starts the download of an update mar. */ startDownload: function() { if (!this.update) this.update = this.um.activeUpdate; this.update.QueryInterface(Components.interfaces.nsIWritablePropertyBag); this.update.setProperty("foregroundDownload", "true");
--- a/browser/base/content/aboutDialog.js +++ b/browser/base/content/aboutDialog.js @@ -1,18 +1,16 @@ /* 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/. */ // Services = object with smart getters for common XPCOM services Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/AppConstants.jsm"); -const PREF_EM_HOTFIX_ID = "extensions.hotfix.id"; - function init(aEvent) { if (aEvent.target != document) return; try { var distroId = Services.prefs.getCharPref("distribution.id"); if (distroId) {
--- a/browser/branding/aurora/pref/firefox-branding.js +++ b/browser/branding/aurora/pref/firefox-branding.js @@ -8,18 +8,18 @@ pref("startup.homepage_override_url", "" pref("startup.homepage_welcome_url", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/firstrun/"); pref("startup.homepage_welcome_url.additional", ""); // The time interval between checks for a new version (in seconds) pref("app.update.interval", 28800); // 8 hours // The time interval between the downloading of mar file chunks in the // background (in seconds) // 0 means "download everything at once" pref("app.update.download.backgroundInterval", 0); -// Give the user x seconds to react before showing the big UI. default=168 hours -pref("app.update.promptWaitTime", 604800); +// Give the user x seconds to react before showing the big UI. default=184 hours +pref("app.update.promptWaitTime", 691200); // URL user can browse to manually if for some reason all update installation // attempts fail. pref("app.update.url.manual", "https://www.mozilla.org/firefox/aurora/"); // A default value for the "More information about this update" link // supplied in the "An update is available" page of the update wizard. pref("app.update.url.details", "https://www.mozilla.org/firefox/aurora/"); // The number of days a binary is permitted to be old
--- a/browser/branding/official/pref/firefox-branding.js +++ b/browser/branding/official/pref/firefox-branding.js @@ -5,18 +5,18 @@ pref("startup.homepage_override_url", ""); pref("startup.homepage_welcome_url", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/firstrun/"); pref("startup.homepage_welcome_url.additional", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/firstrun/learnmore/"); // Interval: Time between checks for a new version (in seconds) pref("app.update.interval", 43200); // 12 hours // The time interval between the downloading of mar file chunks in the // background (in seconds) pref("app.update.download.backgroundInterval", 60); -// Give the user x seconds to react before showing the big UI. default=48 hours -pref("app.update.promptWaitTime", 172800); +// Give the user x seconds to react before showing the big UI. default=184 hours +pref("app.update.promptWaitTime", 691200); // URL user can browse to manually if for some reason all update installation // attempts fail. pref("app.update.url.manual", "https://www.mozilla.org/firefox/"); // A default value for the "More information about this update" link // supplied in the "An update is available" page of the update wizard. pref("app.update.url.details", "https://www.mozilla.org/%LOCALE%/firefox/notes"); // The number of days a binary is permitted to be old
--- a/browser/components/preferences/in-content/advanced.js +++ b/browser/components/preferences/in-content/advanced.js @@ -632,60 +632,43 @@ var gAdvancedPane = { // UPDATE TAB /* * Preferences: * * app.update.enabled * - true if updates to the application are enabled, false otherwise + * app.update.auto + * - true if updates should be automatically downloaded and installed and + * false if the user should be asked what he wants to do when an update is + * available * extensions.update.enabled * - true if updates to extensions and themes are enabled, false otherwise * browser.search.update * - true if updates to search engines are enabled, false otherwise - * app.update.auto - * - true if updates should be automatically downloaded and installed, - * possibly with a warning if incompatible extensions are installed (see - * app.update.mode); false if the user should be asked what he wants to do - * when an update is available - * app.update.mode - * - an integer: - * 0 do not warn if an update will disable extensions or themes - * 1 warn if an update will disable extensions or themes - * 2 warn if an update will disable extensions or themes *or* if the - * update is a major update */ #ifdef MOZ_UPDATER /** - * Selects the item of the radiogroup, and sets the warnIncompatible checkbox - * based on the pref values and locked states. + * Selects the item of the radiogroup based on the pref values and locked + * states. * * UI state matrix for update preference conditions * * UI Components: Preferences * Radiogroup i = app.update.enabled - * Warn before disabling extensions checkbox ii = app.update.auto - * iii = app.update.mode + * ii = app.update.auto * * Disabled states: * Element pref value locked disabled * radiogroup i t/f f false * i t/f *t* *true* * ii t/f f false * ii t/f *t* *true* - * iii 0/1/2 t/f false - * warnIncompatible i t f false - * i t *t* *true* - * i *f* t/f *true* - * ii t f false - * ii t *t* *true* - * ii *f* t/f *true* - * iii 0/1/2 f false - * iii 0/1/2 *t* *true* */ updateReadPrefs: function () { var enabledPref = document.getElementById("app.update.enabled"); var autoPref = document.getElementById("app.update.auto"); var radiogroup = document.getElementById("updateRadioGroup"); if (!enabledPref.value) // Don't care for autoPref.value in this case. @@ -698,22 +681,16 @@ var gAdvancedPane = { var canCheck = Components.classes["@mozilla.org/updates/update-service;1"]. getService(Components.interfaces.nsIApplicationUpdateService). canCheckForUpdates; // canCheck is false if the enabledPref is false and locked, // or the binary platform or OS version is not known. // A locked pref is sufficient to disable the radiogroup. radiogroup.disabled = !canCheck || enabledPref.locked || autoPref.locked; - var modePref = document.getElementById("app.update.mode"); - var warnIncompatible = document.getElementById("warnIncompatible"); - // the warnIncompatible checkbox value is set by readAddonWarn - warnIncompatible.disabled = radiogroup.disabled || modePref.locked || - !enabledPref.value || !autoPref.value; - #ifdef MOZ_MAINTENANCE_SERVICE // Check to see if the maintenance service is installed. // If it is don't show the preference at all. var installed; try { var wrk = Components.classes["@mozilla.org/windows-registry-key;1"] .createInstance(Components.interfaces.nsIWindowsRegKey); wrk.open(wrk.ROOT_KEY_LOCAL_MACHINE, @@ -725,84 +702,36 @@ var gAdvancedPane = { } if (installed != 1) { document.getElementById("useService").hidden = true; } #endif }, /** - * Sets the pref values based on the selected item of the radiogroup, - * and sets the disabled state of the warnIncompatible checkbox accordingly. + * Sets the pref values based on the selected item of the radiogroup. */ updateWritePrefs: function () { var enabledPref = document.getElementById("app.update.enabled"); var autoPref = document.getElementById("app.update.auto"); - var modePref = document.getElementById("app.update.mode"); var radiogroup = document.getElementById("updateRadioGroup"); switch (radiogroup.value) { case "auto": // 1. Automatically install updates for Desktop only enabledPref.value = true; autoPref.value = true; break; case "checkOnly": // 2. Check, but let me choose enabledPref.value = true; autoPref.value = false; break; case "manual": // 3. Never check for updates. enabledPref.value = false; autoPref.value = false; } - - var warnIncompatible = document.getElementById("warnIncompatible"); - warnIncompatible.disabled = enabledPref.locked || !enabledPref.value || - autoPref.locked || !autoPref.value || - modePref.locked; - }, - - /** - * Stores the value of the app.update.mode preference, which is a tristate - * integer preference. We store the value here so that we can properly - * restore the preference value if the UI reflecting the preference value - * is in a state which can represent either of two integer values (as - * opposed to only one possible value in the other UI state). - */ - _modePreference: -1, - - /** - * Reads the app.update.mode preference and converts its value into a - * true/false value for use in determining whether the "Warn me if this will - * disable extensions or themes" checkbox is checked. We also save the value - * of the preference so that the preference value can be properly restored if - * the user's preferences cannot adequately be expressed by a single checkbox. - * - * app.update.mode Checkbox State Meaning - * 0 Unchecked Do not warn - * 1 Checked Warn if there are incompatibilities - * 2 Checked Warn if there are incompatibilities, - * or the update is major. - */ - readAddonWarn: function () - { - var preference = document.getElementById("app.update.mode"); - var warn = preference.value != 0; - gAdvancedPane._modePreference = warn ? preference.value : 1; - return warn; - }, - - /** - * Converts the state of the "Warn me if this will disable extensions or - * themes" checkbox into the integer preference which represents it, - * returning that value. - */ - writeAddonWarn: function () - { - var warnIncompatible = document.getElementById("warnIncompatible"); - return !warnIncompatible.checked ? 0 : gAdvancedPane._modePreference; }, /** * Displays the history of installed updates. */ showUpdates: function () { var prompter = Components.classes["@mozilla.org/updates/update-prompt;1"]
--- a/browser/components/preferences/in-content/advanced.xul +++ b/browser/components/preferences/in-content/advanced.xul @@ -70,19 +70,16 @@ <!-- Update tab --> #ifdef MOZ_UPDATER <preference id="app.update.enabled" name="app.update.enabled" type="bool"/> <preference id="app.update.auto" name="app.update.auto" type="bool"/> - <preference id="app.update.mode" - name="app.update.mode" - type="int"/> <preference id="app.update.disable_button.showUpdateHistory" name="app.update.disable_button.showUpdateHistory" type="bool"/> #ifdef MOZ_MAINTENANCE_SERVICE <preference id="app.update.service.enabled" name="app.update.service.enabled" @@ -331,24 +328,16 @@ #ifdef MOZ_UPDATER <groupbox id="updateApp" align="start"> <caption><label>&updateApp.label;</label></caption> <radiogroup id="updateRadioGroup" align="start"> <radio id="autoDesktop" value="auto" label="&updateAuto1.label;" accesskey="&updateAuto1.accesskey;"/> - <hbox class="indent"> - <checkbox id="warnIncompatible" - label="&updateAutoAddonWarn.label;" - accesskey="&updateAutoAddonWarn.accesskey;" - preference="app.update.mode" - onsyncfrompreference="return gAdvancedPane.readAddonWarn();" - onsynctopreference="return gAdvancedPane.writeAddonWarn();"/> - </hbox> <radio value="checkOnly" label="&updateCheck.label;" accesskey="&updateCheck.accesskey;"/> <radio value="manual" label="&updateManual.label;" accesskey="&updateManual.accesskey;"/> </radiogroup> <separator class="thin"/>
--- a/browser/components/sessionstore/test/browser.ini +++ b/browser/components/sessionstore/test/browser.ini @@ -152,17 +152,17 @@ skip-if = true [browser_500328.js] [browser_514751.js] [browser_522375.js] [browser_522545.js] [browser_524745.js] [browser_528776.js] [browser_579868.js] [browser_579879.js] -skip-if = os == "linux" && e10s && debug # Bug 1234404 - Intermittent | Found an unexpected tab at the end of test run about:blank +skip-if = (os == 'linux' && e10s && (debug||asan)) # Bug 1234404 [browser_581937.js] [browser_586147.js] [browser_586068-apptabs.js] [browser_586068-apptabs_ondemand.js] [browser_586068-browser_state_interrupted.js] [browser_586068-cascade.js] [browser_586068-multi_window.js] [browser_586068-reload.js]
--- a/browser/extensions/moz.build +++ b/browser/extensions/moz.build @@ -4,9 +4,10 @@ # 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/. DIRS += [ 'e10srollout', 'loop', 'pdfjs', 'pocket', + 'webcompat', ]
new file mode 100644 --- /dev/null +++ b/browser/extensions/webcompat/bootstrap.js @@ -0,0 +1,10 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* 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/. */ + +// for now we ship a stub, that can be upgraded as-needed after release +function startup() {} +function shutdown() {} +function install() {} +function uninstall() {}
new file mode 100644 --- /dev/null +++ b/browser/extensions/webcompat/install.rdf.in @@ -0,0 +1,31 @@ +<?xml version="1.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/. --> + +#filter substitution + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>webcompat@mozilla.org</em:id> + <em:version>1.0</em:version> + <em:type>2</em:type> + <em:bootstrap>true</em:bootstrap> + + <!-- Target Application this theme can install into, + with minimum and maximum supported versions. --> + <em:targetApplication> + <Description> + <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> + <em:minVersion>@FIREFOX_VERSION@</em:minVersion> + <em:maxVersion>@FIREFOX_VERSION@</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Web Compat</em:name> + <em:description>Urgent post-release fixes for web compatibility.</em:description> + </Description> +</RDF>
new file mode 100644 --- /dev/null +++ b/browser/extensions/webcompat/moz.build @@ -0,0 +1,15 @@ +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +FINAL_TARGET_FILES.features['webcompat@mozilla.org'] += [ + 'bootstrap.js' +] + +FINAL_TARGET_PP_FILES.features['webcompat@mozilla.org'] += [ + 'install.rdf.in' +] + +BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
new file mode 100644 --- /dev/null +++ b/browser/extensions/webcompat/test/browser.ini @@ -0,0 +1,3 @@ +[DEFAULT] + +[browser_webcompat_stub_check.js]
new file mode 100644 --- /dev/null +++ b/browser/extensions/webcompat/test/browser_webcompat_stub_check.js @@ -0,0 +1,15 @@ +"use strict"; + +// make sure that the stub is present and enabled +add_task(function* stub_enabled() { + let addon = yield new Promise( + resolve => AddonManager.getAddonByID("webcompat@mozilla.org", resolve) + ); + isnot(addon, null, "Webcompat stub addon should exist"); + is(addon.version, "1.0"); + is(addon.name, "Web Compat"); + ok(addon.isCompatible, "Webcompat stub addon is compatible with Firefox"); + ok(!addon.appDisabled, "Webcompat stub addon is not app disabled"); + ok(addon.isActive, "Webcompat stub addon is active"); + is(addon.type, "extension", "Webcompat stub addon is type extension"); +});
--- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -827,20 +827,16 @@ bin/libfreebl_32int64_3.so #endif #endif @RESPATH@/browser/crashreporter-override.ini #ifdef MOZ_CRASHREPORTER_INJECTOR @BINPATH@/breakpadinjector.dll #endif #endif -@RESPATH@/components/DataStore.manifest -@RESPATH@/components/DataStoreImpl.js -@RESPATH@/components/dom_datastore.xpt - @RESPATH@/components/dom_audiochannel.xpt ; Shutdown Terminator @RESPATH@/components/nsTerminatorTelemetry.js @RESPATH@/components/terminator.manifest #if defined(CLANG_CXX) #if defined(MOZ_ASAN) || defined(MOZ_TSAN)
--- a/browser/locales/en-US/chrome/browser/preferences/advanced.dtd +++ b/browser/locales/en-US/chrome/browser/preferences/advanced.dtd @@ -78,19 +78,16 @@ <!ENTITY updateApp.label "&brandShortName; updates:"> <!ENTITY updateAuto1.label "Automatically install updates (recommended: improved security)"> <!ENTITY updateAuto1.accesskey "A"> <!ENTITY updateCheck.label "Check for updates, but let me choose whether to install them"> <!ENTITY updateCheck.accesskey "C"> <!ENTITY updateManual.label "Never check for updates (not recommended: security risk)"> <!ENTITY updateManual.accesskey "N"> -<!ENTITY updateAutoAddonWarn.label "Warn me if this will disable any of my add-ons"> -<!ENTITY updateAutoAddonWarn.accesskey "W"> - <!ENTITY updateHistory.label "Show Update History"> <!ENTITY updateHistory.accesskey "p"> <!ENTITY useService.label "Use a background service to install updates"> <!ENTITY useService.accesskey "b"> <!ENTITY updateOthers.label "Automatically update:"> <!ENTITY enableSearchUpdate.label "Search Engines">
--- a/browser/modules/WindowsPreviewPerTab.jsm +++ b/browser/modules/WindowsPreviewPerTab.jsm @@ -45,48 +45,44 @@ this.EXPORTED_SYMBOLS = ["AeroPeek"]; const Cc = Components.classes; const Ci = Components.interfaces; const Cu = Components.utils; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/NetUtil.jsm"); Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/PageThumbs.jsm"); // Pref to enable/disable preview-per-tab const TOGGLE_PREF_NAME = "browser.taskbar.previews.enable"; // Pref to determine the magic auto-disable threshold const DISABLE_THRESHOLD_PREF_NAME = "browser.taskbar.previews.max"; // Pref to control the time in seconds that tab contents live in the cache const CACHE_EXPIRATION_TIME_PREF_NAME = "browser.taskbar.previews.cachetime"; const WINTASKBAR_CONTRACTID = "@mozilla.org/windows-taskbar;1"; //////////////////////////////////////////////////////////////////////////////// //// Various utility properties -XPCOMUtils.defineLazyServiceGetter(this, "ioSvc", - "@mozilla.org/network/io-service;1", - "nsIIOService"); XPCOMUtils.defineLazyServiceGetter(this, "imgTools", "@mozilla.org/image/tools;1", "imgITools"); XPCOMUtils.defineLazyServiceGetter(this, "faviconSvc", "@mozilla.org/browser/favicon-service;1", "nsIFaviconService"); // nsIURI -> imgIContainer function _imageFromURI(doc, uri, privateMode, callback) { - let channel = ioSvc.newChannelFromURI2(uri, - null, - Services.scriptSecurityManager.getSystemPrincipal(), - null, - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE); + let channel = NetUtil.newChannel({ + uri: uri, + loadUsingSystemPrincipal: true, + contentPolicyType: Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE + }); + try { channel.QueryInterface(Ci.nsIPrivateBrowsingChannel); channel.setPrivate(privateMode); } catch (e) { // Ignore channels which do not support nsIPrivateBrowsingChannel } NetUtil.asyncFetch(channel, function(inputStream, resultCode) { if (!Components.isSuccessCode(resultCode))
--- a/build/clang-plugin/clang-plugin.cpp +++ b/build/clang-plugin/clang-plugin.cpp @@ -331,17 +331,17 @@ static CustomTypeAnnotation GlobalClass CustomTypeAnnotation("moz_global_class", "global"); static CustomTypeAnnotation NonHeapClass = CustomTypeAnnotation("moz_nonheap_class", "non-heap"); static CustomTypeAnnotation HeapClass = CustomTypeAnnotation("moz_heap_class", "heap"); static CustomTypeAnnotation NonTemporaryClass = CustomTypeAnnotation("moz_non_temporary_class", "non-temporary"); static CustomTypeAnnotation MustUse = - CustomTypeAnnotation("moz_must_use", "must-use"); + CustomTypeAnnotation("moz_must_use_type", "must-use"); class MemMoveAnnotation final : public CustomTypeAnnotation { public: MemMoveAnnotation() : CustomTypeAnnotation("moz_non_memmovable", "non-memmove()able") {} virtual ~MemMoveAnnotation() {}
--- a/build/clang-plugin/tests/TestMultipleAnnotations.cpp +++ b/build/clang-plugin/tests/TestMultipleAnnotations.cpp @@ -1,12 +1,12 @@ -#define MOZ_MUST_USE __attribute__((annotate("moz_must_use"))) +#define MOZ_MUST_USE_TYPE __attribute__((annotate("moz_must_use_type"))) #define MOZ_STACK_CLASS __attribute__((annotate("moz_stack_class"))) -class MOZ_MUST_USE MOZ_STACK_CLASS TestClass {}; +class MOZ_MUST_USE_TYPE MOZ_STACK_CLASS TestClass {}; TestClass foo; // expected-error {{variable of type 'TestClass' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}} TestClass f() { TestClass bar; return bar; }
--- a/build/clang-plugin/tests/TestMustUse.cpp +++ b/build/clang-plugin/tests/TestMustUse.cpp @@ -1,12 +1,12 @@ -#define MOZ_MUST_USE __attribute__((annotate("moz_must_use"))) +#define MOZ_MUST_USE_TYPE __attribute__((annotate("moz_must_use_type"))) struct Temporary { ~Temporary(); }; -class MOZ_MUST_USE MustUse {}; +class MOZ_MUST_USE_TYPE MustUse {}; class MayUse {}; MustUse producesMustUse(); MustUse *producesMustUsePointer(); MustUse &producesMustUseRef(); MustUse producesMustUse(const Temporary& t); MustUse *producesMustUsePointer(const Temporary& t);
--- a/dom/animation/Animation.cpp +++ b/dom/animation/Animation.cpp @@ -3,20 +3,20 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "Animation.h" #include "AnimationUtils.h" #include "mozilla/dom/AnimationBinding.h" #include "mozilla/dom/AnimationPlaybackEvent.h" +#include "mozilla/AnimationTarget.h" #include "mozilla/AutoRestore.h" #include "mozilla/AsyncEventDispatcher.h" // For AsyncEventDispatcher #include "mozilla/Maybe.h" // For Maybe -#include "mozilla/NonOwningAnimationTarget.h" #include "nsAnimationManager.h" // For CSSAnimation #include "nsDOMMutationObserver.h" // For nsAutoAnimationMutationBatch #include "nsIDocument.h" // For nsIDocument #include "nsIPresShell.h" // For nsIPresShell #include "nsLayoutUtils.h" // For PostRestyleEvent (remove after bug 1073336) #include "nsThreadUtils.h" // For nsRunnableMethod and nsRevocableEventPtr #include "nsTransitionManager.h" // For CSSTransition #include "PendingAnimationTracker.h" // For PendingAnimationTracker
rename from dom/animation/NonOwningAnimationTarget.h rename to dom/animation/AnimationTarget.h --- a/dom/animation/NonOwningAnimationTarget.h +++ b/dom/animation/AnimationTarget.h @@ -1,32 +1,78 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef mozilla_NonOwningAnimationTarget_h -#define mozilla_NonOwningAnimationTarget_h +#ifndef mozilla_AnimationTarget_h +#define mozilla_AnimationTarget_h #include "mozilla/Attributes.h" // For MOZ_NON_OWNING_REF +#include "mozilla/Maybe.h" +#include "mozilla/RefPtr.h" #include "nsCSSPseudoElements.h" namespace mozilla { namespace dom { class Element; } // namespace dom +struct OwningAnimationTarget +{ + OwningAnimationTarget(dom::Element* aElement, CSSPseudoElementType aType) + : mElement(aElement), mPseudoType(aType) { } + + explicit OwningAnimationTarget(dom::Element* aElement) + : mElement(aElement) { } + + bool operator==(const OwningAnimationTarget& aOther) const + { + return mElement == aOther.mElement && + mPseudoType == aOther.mPseudoType; + } + + // mElement represents the parent element of a pseudo-element, not the + // generated content element. + RefPtr<dom::Element> mElement; + CSSPseudoElementType mPseudoType = CSSPseudoElementType::NotPseudo; +}; + struct NonOwningAnimationTarget { NonOwningAnimationTarget(dom::Element* aElement, CSSPseudoElementType aType) : mElement(aElement), mPseudoType(aType) { } + explicit NonOwningAnimationTarget(const OwningAnimationTarget& aOther) + : mElement(aOther.mElement), mPseudoType(aOther.mPseudoType) { } + // mElement represents the parent element of a pseudo-element, not the // generated content element. dom::Element* MOZ_NON_OWNING_REF mElement = nullptr; CSSPseudoElementType mPseudoType = CSSPseudoElementType::NotPseudo; }; + +// Helper functions for cycle-collecting Maybe<OwningAnimationTarget> +inline void +ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, + Maybe<OwningAnimationTarget>& aTarget, + const char* aName, + uint32_t aFlags = 0) +{ + if (aTarget) { + ImplCycleCollectionTraverse(aCallback, aTarget->mElement, aName, aFlags); + } +} + +inline void +ImplCycleCollectionUnlink(Maybe<OwningAnimationTarget>& aTarget) +{ + if (aTarget) { + ImplCycleCollectionUnlink(aTarget->mElement); + } +} + } // namespace mozilla -#endif // mozilla_NonOwningAnimationTarget_h +#endif // mozilla_AnimationTarget_h
--- a/dom/animation/EffectCompositor.cpp +++ b/dom/animation/EffectCompositor.cpp @@ -4,18 +4,19 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "EffectCompositor.h" #include "mozilla/dom/Animation.h" #include "mozilla/dom/Element.h" #include "mozilla/dom/KeyframeEffect.h" // For KeyframeEffectReadOnly +#include "mozilla/AnimationPerformanceWarning.h" +#include "mozilla/AnimationTarget.h" #include "mozilla/AnimationUtils.h" -#include "mozilla/AnimationPerformanceWarning.h" #include "mozilla/EffectSet.h" #include "mozilla/InitializerList.h" #include "mozilla/LayerAnimationInfo.h" #include "mozilla/RestyleManagerHandle.h" #include "mozilla/RestyleManagerHandleInlines.h" #include "nsComputedDOMStyle.h" // nsComputedDOMStyle::GetPresShellForContent #include "nsCSSPropertySet.h" #include "nsCSSProps.h"
--- a/dom/animation/EffectCompositor.h +++ b/dom/animation/EffectCompositor.h @@ -5,17 +5,16 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_EffectCompositor_h #define mozilla_EffectCompositor_h #include "mozilla/EnumeratedArray.h" #include "mozilla/Maybe.h" #include "mozilla/OwningNonNull.h" -#include "mozilla/NonOwningAnimationTarget.h" #include "mozilla/PseudoElementHashEntry.h" #include "mozilla/RefPtr.h" #include "nsCSSProperty.h" #include "nsCycleCollectionParticipant.h" #include "nsDataHashtable.h" #include "nsIStyleRuleProcessor.h" #include "nsTArray.h" @@ -25,16 +24,17 @@ class nsIStyleRule; class nsPresContext; class nsStyleContext; namespace mozilla { class EffectSet; class RestyleTracker; struct AnimationPerformanceWarning; +struct NonOwningAnimationTarget; namespace dom { class Animation; class Element; } class EffectCompositor {
--- a/dom/animation/KeyframeEffect.cpp +++ b/dom/animation/KeyframeEffect.cpp @@ -4,17 +4,16 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/dom/KeyframeEffect.h" #include "mozilla/dom/AnimatableBinding.h" #include "mozilla/dom/KeyframeEffectBinding.h" #include "mozilla/AnimationUtils.h" -#include "mozilla/EffectCompositor.h" #include "mozilla/FloatingPoint.h" #include "mozilla/LookAndFeel.h" // For LookAndFeel::GetInt #include "mozilla/KeyframeUtils.h" #include "mozilla/StyleAnimationValue.h" #include "Layers.h" // For Layer #include "nsComputedDOMStyle.h" // nsComputedDOMStyle::GetStyleContextForElement #include "nsCSSPropertySet.h" #include "nsCSSProps.h" // For nsCSSProps::PropHasFlags @@ -71,38 +70,34 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(KeyframeEffectReadOnly) NS_INTERFACE_MAP_END_INHERITING(AnimationEffectReadOnly) NS_IMPL_ADDREF_INHERITED(KeyframeEffectReadOnly, AnimationEffectReadOnly) NS_IMPL_RELEASE_INHERITED(KeyframeEffectReadOnly, AnimationEffectReadOnly) KeyframeEffectReadOnly::KeyframeEffectReadOnly( nsIDocument* aDocument, - Element* aTarget, - CSSPseudoElementType aPseudoType, + const Maybe<OwningAnimationTarget>& aTarget, const TimingParams& aTiming) - : KeyframeEffectReadOnly(aDocument, aTarget, aPseudoType, + : KeyframeEffectReadOnly(aDocument, aTarget, new AnimationEffectTimingReadOnly(aDocument, aTiming)) { } KeyframeEffectReadOnly::KeyframeEffectReadOnly( nsIDocument* aDocument, - Element* aTarget, - CSSPseudoElementType aPseudoType, + const Maybe<OwningAnimationTarget>& aTarget, AnimationEffectTimingReadOnly* aTiming) : AnimationEffectReadOnly(aDocument) , mTarget(aTarget) , mTiming(aTiming) - , mPseudoType(aPseudoType) , mInEffectOnLastAnimationTimingUpdate(false) { MOZ_ASSERT(aTiming); - MOZ_ASSERT(aTarget, "null animation target is not yet supported"); } JSObject* KeyframeEffectReadOnly::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) { return KeyframeEffectReadOnlyBinding::Wrap(aCx, this, aGivenProto); } @@ -157,17 +152,18 @@ KeyframeEffectReadOnly::NotifyAnimationT ResetIsRunningOnCompositor(); } // Detect changes to "in effect" status since we need to recalculate the // animation cascade for this element whenever that changes. bool inEffect = IsInEffect(); if (inEffect != mInEffectOnLastAnimationTimingUpdate) { if (mTarget) { - EffectSet* effectSet = EffectSet::GetEffectSet(mTarget, mPseudoType); + EffectSet* effectSet = EffectSet::GetEffectSet(mTarget->mElement, + mTarget->mPseudoType); if (effectSet) { effectSet->MarkCascadeNeedsUpdate(); } } mInEffectOnLastAnimationTimingUpdate = inEffect; } // Request restyle if necessary. @@ -183,22 +179,17 @@ KeyframeEffectReadOnly::NotifyAnimationT // // Bug 1216843: When we implement iteration composite modes, we need to // also detect if the current iteration has changed. if (mAnimation && GetComputedTiming().mProgress != mProgressOnLastCompose) { EffectCompositor::RestyleType restyleType = CanThrottle() ? EffectCompositor::RestyleType::Throttled : EffectCompositor::RestyleType::Standard; - nsPresContext* presContext = GetPresContext(); - if (presContext) { - presContext->EffectCompositor()-> - RequestRestyle(mTarget, mPseudoType, restyleType, - mAnimation->CascadeLevel()); - } + RequestRestyle(restyleType); // If we're not relevant, we will have been removed from the EffectSet. // As a result, when the restyle we requested above is fulfilled, our // ComposeStyle will not get called and mProgressOnLastCompose will not // be updated. Instead, we need to manually clear it. if (!isRelevant) { mProgressOnLastCompose.SetNull(); } @@ -455,20 +446,21 @@ KeyframeEffectReadOnly::SetFrames(JSCont if (aRv.Failed()) { return; } RefPtr<nsStyleContext> styleContext; nsIPresShell* shell = doc->GetShell(); if (shell && mTarget) { nsIAtom* pseudo = - mPseudoType < CSSPseudoElementType::Count ? - nsCSSPseudoElements::GetPseudoAtom(mPseudoType) : nullptr; + mTarget->mPseudoType < CSSPseudoElementType::Count ? + nsCSSPseudoElements::GetPseudoAtom(mTarget->mPseudoType) : nullptr; styleContext = - nsComputedDOMStyle::GetStyleContextForElement(mTarget, pseudo, shell); + nsComputedDOMStyle::GetStyleContextForElement(mTarget->mElement, + pseudo, shell); } SetFrames(Move(keyframes), styleContext); } void KeyframeEffectReadOnly::SetFrames(nsTArray<Keyframe>&& aFrames, nsStyleContext* aStyleContext) @@ -522,18 +514,18 @@ void KeyframeEffectReadOnly::UpdateProperties(nsStyleContext* aStyleContext) { MOZ_ASSERT(aStyleContext); nsTArray<AnimationProperty> properties; if (mTarget) { properties = KeyframeUtils::GetAnimationPropertiesFromKeyframes(aStyleContext, - mTarget, - mPseudoType, + mTarget->mElement, + mTarget->mPseudoType, mFrames); } if (mProperties == properties) { return; } // Preserve the state of mWinsInCascade and mIsRunningOnCompositor flags. @@ -554,30 +546,23 @@ KeyframeEffectReadOnly::UpdateProperties for (AnimationProperty& property : mProperties) { property.mWinsInCascade = winningInCascadeProperties.HasProperty(property.mProperty); property.mIsRunningOnCompositor = runningOnCompositorProperties.HasProperty(property.mProperty); } if (mTarget) { - EffectSet* effectSet = EffectSet::GetEffectSet(mTarget, mPseudoType); + EffectSet* effectSet = EffectSet::GetEffectSet(mTarget->mElement, + mTarget->mPseudoType); if (effectSet) { effectSet->MarkCascadeNeedsUpdate(); } - } - if (mAnimation) { - nsPresContext* presContext = GetPresContext(); - if (presContext) { - presContext->EffectCompositor()-> - RequestRestyle(mTarget, mPseudoType, - EffectCompositor::RestyleType::Layer, - mAnimation->CascadeLevel()); - } + RequestRestyle(EffectCompositor::RestyleType::Layer); } } void KeyframeEffectReadOnly::ComposeStyle(RefPtr<AnimValuesStyleRule>& aStyleRule, nsCSSPropertySet& aSetProperties) { ComputedTiming computedTiming = GetComputedTiming(); @@ -711,16 +696,39 @@ KeyframeEffectReadOnly::SetIsRunningOnCo } } } KeyframeEffectReadOnly::~KeyframeEffectReadOnly() { } +static Maybe<OwningAnimationTarget> +ConvertTarget(const Nullable<ElementOrCSSPseudoElement>& aTarget) +{ + // Return value optimization. + Maybe<OwningAnimationTarget> result; + + if (aTarget.IsNull()) { + return result; + } + + const ElementOrCSSPseudoElement& target = aTarget.Value(); + MOZ_ASSERT(target.IsElement() || target.IsCSSPseudoElement(), + "Uninitialized target"); + + if (target.IsElement()) { + result.emplace(&target.GetAsElement()); + } else { + RefPtr<Element> elem = target.GetAsCSSPseudoElement().ParentElement(); + result.emplace(elem, target.GetAsCSSPseudoElement().GetType()); + } + return result; +} + template <class KeyframeEffectType, class OptionsType> /* static */ already_AddRefed<KeyframeEffectType> KeyframeEffectReadOnly::ConstructKeyframeEffect( const GlobalObject& aGlobal, const Nullable<ElementOrCSSPseudoElement>& aTarget, JS::Handle<JSObject*> aFrames, const OptionsType& aOptions, ErrorResult& aRv) @@ -732,38 +740,20 @@ KeyframeEffectReadOnly::ConstructKeyfram } TimingParams timingParams = TimingParams::FromOptionsUnion(aOptions, doc, aRv); if (aRv.Failed()) { return nullptr; } - if (aTarget.IsNull()) { - // We don't support null targets yet. - aRv.Throw(NS_ERROR_DOM_ANIM_NO_TARGET_ERR); - return nullptr; - } - - const ElementOrCSSPseudoElement& target = aTarget.Value(); - MOZ_ASSERT(target.IsElement() || target.IsCSSPseudoElement(), - "Uninitialized target"); + Maybe<OwningAnimationTarget> target = ConvertTarget(aTarget); + RefPtr<KeyframeEffectType> effect = + new KeyframeEffectType(doc, target, timingParams); - RefPtr<Element> targetElement; - CSSPseudoElementType pseudoType = CSSPseudoElementType::NotPseudo; - if (target.IsElement()) { - targetElement = &target.GetAsElement(); - } else { - targetElement = target.GetAsCSSPseudoElement().ParentElement(); - pseudoType = target.GetAsCSSPseudoElement().GetType(); - } - - RefPtr<KeyframeEffectType> effect = - new KeyframeEffectType(targetElement->OwnerDoc(), targetElement, - pseudoType, timingParams); effect->SetFrames(aGlobal.Context(), aFrames, aRv); if (aRv.Failed()) { return nullptr; } return effect.forget(); } @@ -771,46 +761,73 @@ void KeyframeEffectReadOnly::ResetIsRunningOnCompositor() { for (AnimationProperty& property : mProperties) { property.mIsRunningOnCompositor = false; } } void +KeyframeEffectReadOnly::ResetWinsInCascade() +{ + for (AnimationProperty& property : mProperties) { + property.mWinsInCascade = false; + } +} + +void KeyframeEffectReadOnly::UpdateTargetRegistration() { if (!mTarget) { return; } bool isRelevant = mAnimation && mAnimation->IsRelevant(); // Animation::IsRelevant() returns a cached value. It only updates when // something calls Animation::UpdateRelevance. Whenever our timing changes, // we should be notifying our Animation before calling this, so // Animation::IsRelevant() should be up-to-date by the time we get here. MOZ_ASSERT(isRelevant == IsCurrent() || IsInEffect(), "Out of date Animation::IsRelevant value"); if (isRelevant) { - EffectSet* effectSet = EffectSet::GetOrCreateEffectSet(mTarget, - mPseudoType); + EffectSet* effectSet = + EffectSet::GetOrCreateEffectSet(mTarget->mElement, mTarget->mPseudoType); effectSet->AddEffect(*this); } else { - EffectSet* effectSet = EffectSet::GetEffectSet(mTarget, mPseudoType); - if (effectSet) { - effectSet->RemoveEffect(*this); - if (effectSet->IsEmpty()) { - EffectSet::DestroyEffectSet(mTarget, mPseudoType); - } + UnregisterTarget(); + } +} + +void +KeyframeEffectReadOnly::UnregisterTarget() +{ + EffectSet* effectSet = + EffectSet::GetEffectSet(mTarget->mElement, mTarget->mPseudoType); + if (effectSet) { + effectSet->RemoveEffect(*this); + if (effectSet->IsEmpty()) { + EffectSet::DestroyEffectSet(mTarget->mElement, mTarget->mPseudoType); } } } +void +KeyframeEffectReadOnly::RequestRestyle( + EffectCompositor::RestyleType aRestyleType) +{ + nsPresContext* presContext = GetPresContext(); + if (presContext && mTarget && mAnimation) { + presContext->EffectCompositor()-> + RequestRestyle(mTarget->mElement, mTarget->mPseudoType, + aRestyleType, mAnimation->CascadeLevel()); + } +} + #ifdef DEBUG void DumpAnimationProperties(nsTArray<AnimationProperty>& aAnimationProperties) { for (auto& p : aAnimationProperties) { printf("%s\n", nsCSSProps::GetStringValue(p.mProperty).get()); for (auto& s : p.mSegments) { nsString fromValue, toValue; @@ -854,25 +871,26 @@ void KeyframeEffectReadOnly::GetTarget( Nullable<OwningElementOrCSSPseudoElement>& aRv) const { if (!mTarget) { aRv.SetNull(); return; } - switch (mPseudoType) { + switch (mTarget->mPseudoType) { case CSSPseudoElementType::before: case CSSPseudoElementType::after: aRv.SetValue().SetAsCSSPseudoElement() = - CSSPseudoElement::GetCSSPseudoElement(mTarget, mPseudoType); + CSSPseudoElement::GetCSSPseudoElement(mTarget->mElement, + mTarget->mPseudoType); break; case CSSPseudoElementType::NotPseudo: - aRv.SetValue().SetAsElement() = mTarget; + aRv.SetValue().SetAsElement() = mTarget->mElement; break; default: NS_NOTREACHED("Animation of unsupported pseudo-type"); aRv.SetNull(); } } @@ -1068,17 +1086,18 @@ KeyframeEffectReadOnly::CanThrottle() co LayerAnimationInfo::sRecords) { // Skip properties that are overridden in the cascade. // (GetAnimationOfProperty, as called by HasAnimationOfProperty, // only returns an animation if it currently wins in the cascade.) if (!HasAnimationOfProperty(record.mProperty)) { continue; } - EffectSet* effectSet = EffectSet::GetEffectSet(mTarget, mPseudoType); + EffectSet* effectSet = EffectSet::GetEffectSet(mTarget->mElement, + mTarget->mPseudoType); MOZ_ASSERT(effectSet, "CanThrottle should be called on an effect " "associated with a target element"); layers::Layer* layer = FrameLayerBuilder::GetDedicatedLayer(frame, record.mLayerType); // Unthrottle if the layer needs to be brought up to date if (!layer || effectSet->GetAnimationGeneration() != layer->GetAnimationGeneration()) { @@ -1116,17 +1135,18 @@ KeyframeEffectReadOnly::CanThrottleTrans nsPresContext* presContext = GetPresContext(); // CanThrottleTransformChanges is only called as part of a refresh driver tick // in which case we expect to has a pres context. MOZ_ASSERT(presContext); TimeStamp now = presContext->RefreshDriver()->MostRecentRefresh(); - EffectSet* effectSet = EffectSet::GetEffectSet(mTarget, mPseudoType); + EffectSet* effectSet = EffectSet::GetEffectSet(mTarget->mElement, + mTarget->mPseudoType); MOZ_ASSERT(effectSet, "CanThrottleTransformChanges is expected to be called" " on an effect in an effect set"); MOZ_ASSERT(mAnimation, "CanThrottleTransformChanges is expected to be called" " on an effect with a parent animation"); TimeStamp animationRuleRefreshTime = effectSet->AnimationRuleRefreshTime(mAnimation->CascadeLevel()); // If this animation can cause overflow, we can throttle some of the ticks. if (!animationRuleRefreshTime.IsNull() && @@ -1154,43 +1174,43 @@ KeyframeEffectReadOnly::CanThrottleTrans nsIFrame* KeyframeEffectReadOnly::GetAnimationFrame() const { if (!mTarget) { return nullptr; } - nsIFrame* frame = mTarget->GetPrimaryFrame(); + nsIFrame* frame = mTarget->mElement->GetPrimaryFrame(); if (!frame) { return nullptr; } - if (mPseudoType == CSSPseudoElementType::before) { + if (mTarget->mPseudoType == CSSPseudoElementType::before) { frame = nsLayoutUtils::GetBeforeFrame(frame); - } else if (mPseudoType == CSSPseudoElementType::after) { + } else if (mTarget->mPseudoType == CSSPseudoElementType::after) { frame = nsLayoutUtils::GetAfterFrame(frame); } else { - MOZ_ASSERT(mPseudoType == CSSPseudoElementType::NotPseudo, - "unknown mPseudoType"); + MOZ_ASSERT(mTarget->mPseudoType == CSSPseudoElementType::NotPseudo, + "unknown mTarget->mPseudoType"); } if (!frame) { return nullptr; } return nsLayoutUtils::GetStyleFrame(frame); } nsIDocument* KeyframeEffectReadOnly::GetRenderedDocument() const { if (!mTarget) { return nullptr; } - return mTarget->GetComposedDoc(); + return mTarget->mElement->GetComposedDoc(); } nsPresContext* KeyframeEffectReadOnly::GetPresContext() const { nsIDocument* doc = GetRenderedDocument(); if (!doc) { return nullptr; @@ -1298,34 +1318,33 @@ KeyframeEffectReadOnly::SetPerformanceWa (!property.mPerformanceWarning || *property.mPerformanceWarning != aWarning)) { property.mPerformanceWarning = Some(aWarning); nsXPIDLString localizedString; if (nsLayoutUtils::IsAnimationLoggingEnabled() && property.mPerformanceWarning->ToLocalizedString(localizedString)) { nsAutoCString logMessage = NS_ConvertUTF16toUTF8(localizedString); - AnimationUtils::LogAsyncAnimationFailure(logMessage, mTarget); + AnimationUtils::LogAsyncAnimationFailure(logMessage, mTarget->mElement); } return; } } } //--------------------------------------------------------------------- // // KeyframeEffect // //--------------------------------------------------------------------- KeyframeEffect::KeyframeEffect(nsIDocument* aDocument, - Element* aTarget, - CSSPseudoElementType aPseudoType, + const Maybe<OwningAnimationTarget>& aTarget, const TimingParams& aTiming) - : KeyframeEffectReadOnly(aDocument, aTarget, aPseudoType, + : KeyframeEffectReadOnly(aDocument, aTarget, new AnimationEffectTiming(aDocument, aTiming, this)) { } JSObject* KeyframeEffect::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) { @@ -1351,41 +1370,100 @@ KeyframeEffect::Constructor( JS::Handle<JSObject*> aFrames, const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions, ErrorResult& aRv) { return ConstructKeyframeEffect<KeyframeEffect>(aGlobal, aTarget, aFrames, aOptions, aRv); } -void KeyframeEffect::NotifySpecifiedTimingUpdated() +void +KeyframeEffect::NotifySpecifiedTimingUpdated() { // Use the same document for a pseudo element and its parent element. - nsAutoAnimationMutationBatch mb(mTarget->OwnerDoc()); + // Use nullptr if we don't have mTarget, so disable the mutation batch. + nsAutoAnimationMutationBatch mb(mTarget ? mTarget->mElement->OwnerDoc() + : nullptr); if (mAnimation) { mAnimation->NotifyEffectTimingUpdated(); if (mAnimation->IsRelevant()) { nsNodeUtils::AnimationChanged(mAnimation); } - nsPresContext* presContext = GetPresContext(); - if (presContext) { - presContext->EffectCompositor()-> - RequestRestyle(mTarget, mPseudoType, - EffectCompositor::RestyleType::Layer, - mAnimation->CascadeLevel()); + RequestRestyle(EffectCompositor::RestyleType::Layer); + } +} + +void +KeyframeEffect::SetTarget(const Nullable<ElementOrCSSPseudoElement>& aTarget) +{ + Maybe<OwningAnimationTarget> newTarget = ConvertTarget(aTarget); + if (mTarget == newTarget) { + // Assign the same target, skip it. + return; + } + + if (mTarget) { + UnregisterTarget(); + ResetIsRunningOnCompositor(); + ResetWinsInCascade(); + + RequestRestyle(EffectCompositor::RestyleType::Layer); + + nsAutoAnimationMutationBatch mb(mTarget->mElement->OwnerDoc()); + if (mAnimation) { + nsNodeUtils::AnimationRemoved(mAnimation); + } + } + + mTarget = newTarget; + + if (mTarget) { + UpdateTargetRegistration(); + MaybeUpdateProperties(); + + RequestRestyle(EffectCompositor::RestyleType::Layer); + + nsAutoAnimationMutationBatch mb(mTarget->mElement->OwnerDoc()); + if (mAnimation) { + nsNodeUtils::AnimationAdded(mAnimation); } } } KeyframeEffect::~KeyframeEffect() { // mTiming is cycle collected, so we have to do null check first even though // mTiming shouldn't be null during the lifetime of KeyframeEffect. if (mTiming) { mTiming->Unlink(); } } +void +KeyframeEffect::MaybeUpdateProperties() +{ + if (!mTarget) { + return; + } + + nsIDocument* doc = mTarget->mElement->OwnerDoc(); + if (!doc) { + return; + } + + nsIAtom* pseudo = mTarget->mPseudoType < CSSPseudoElementType::Count ? + nsCSSPseudoElements::GetPseudoAtom(mTarget->mPseudoType) : + nullptr; + RefPtr<nsStyleContext> styleContext = + nsComputedDOMStyle::GetStyleContextForElement(mTarget->mElement, pseudo, + doc->GetShell()); + if (!styleContext) { + return; + } + + UpdateProperties(styleContext); +} + } // namespace dom } // namespace mozilla
--- a/dom/animation/KeyframeEffect.h +++ b/dom/animation/KeyframeEffect.h @@ -9,22 +9,23 @@ #include "nsAutoPtr.h" #include "nsCSSProperty.h" #include "nsCSSValue.h" #include "nsCycleCollectionParticipant.h" #include "nsTArray.h" #include "nsWrapperCache.h" #include "mozilla/AnimationPerformanceWarning.h" +#include "mozilla/AnimationTarget.h" #include "mozilla/Attributes.h" #include "mozilla/ComputedTiming.h" #include "mozilla/ComputedTimingFunction.h" +#include "mozilla/EffectCompositor.h" #include "mozilla/LayerAnimationInfo.h" // LayerAnimations::kRecords #include "mozilla/Maybe.h" -#include "mozilla/NonOwningAnimationTarget.h" #include "mozilla/OwningNonNull.h" // OwningNonNull<...> #include "mozilla/StickyTimeDuration.h" #include "mozilla/StyleAnimationValue.h" #include "mozilla/TimeStamp.h" #include "mozilla/TimingParams.h" #include "mozilla/dom/AnimationEffectReadOnly.h" #include "mozilla/dom/AnimationEffectTimingReadOnly.h" #include "mozilla/dom/Element.h" @@ -185,18 +186,17 @@ struct ElementPropertyTransition; namespace dom { class Animation; class KeyframeEffectReadOnly : public AnimationEffectReadOnly { public: KeyframeEffectReadOnly(nsIDocument* aDocument, - Element* aTarget, - CSSPseudoElementType aPseudoType, + const Maybe<OwningAnimationTarget>& aTarget, const TimingParams& aTiming); NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(KeyframeEffectReadOnly, AnimationEffectReadOnly) virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; @@ -215,17 +215,17 @@ public: const UnrestrictedDoubleOrKeyframeEffectOptions& aOptions, ErrorResult& aRv); void GetTarget(Nullable<OwningElementOrCSSPseudoElement>& aRv) const; Maybe<NonOwningAnimationTarget> GetTarget() const { Maybe<NonOwningAnimationTarget> result; if (mTarget) { - result.emplace(mTarget, mPseudoType); + result.emplace(*mTarget); } return result; } void GetFrames(JSContext*& aCx, nsTArray<JSObject*>& aResult, ErrorResult& aRv); void GetProperties(nsTArray<AnimationPropertyDetails>& aProperties, ErrorResult& aRv) const; @@ -332,48 +332,52 @@ public: // compositor. |aParams| and |aParamsLength| are optional parameters which // will be used to generate a localized message for devtools. void SetPerformanceWarning( nsCSSProperty aProperty, const AnimationPerformanceWarning& aWarning); protected: KeyframeEffectReadOnly(nsIDocument* aDocument, - Element* aTarget, - CSSPseudoElementType aPseudoType, + const Maybe<OwningAnimationTarget>& aTarget, AnimationEffectTimingReadOnly* aTiming); virtual ~KeyframeEffectReadOnly(); template<class KeyframeEffectType, class OptionsType> static already_AddRefed<KeyframeEffectType> ConstructKeyframeEffect(const GlobalObject& aGlobal, const Nullable<ElementOrCSSPseudoElement>& aTarget, JS::Handle<JSObject*> aFrames, const OptionsType& aOptions, ErrorResult& aRv); void ResetIsRunningOnCompositor(); + void ResetWinsInCascade(); // This effect is registered with its target element so long as: // // (a) It has a target element, and // (b) It is "relevant" (i.e. yet to finish but not idle, or finished but // filling forwards) // // As a result, we need to make sure this gets called whenever anything // changes with regards to this effects's timing including changes to the // owning Animation's timing. void UpdateTargetRegistration(); - nsCOMPtr<Element> mTarget; + // Remove the current effect target from its EffectSet. + void UnregisterTarget(); + + void RequestRestyle(EffectCompositor::RestyleType aRestyleType); + + Maybe<OwningAnimationTarget> mTarget; RefPtr<Animation> mAnimation; RefPtr<AnimationEffectTimingReadOnly> mTiming; - CSSPseudoElementType mPseudoType; // The specified keyframes. nsTArray<Keyframe> mFrames; // A set of per-property value arrays, derived from |mFrames|. nsTArray<AnimationProperty> mProperties; // The computed progress last time we composed the style rule. This is @@ -401,18 +405,17 @@ private: static const TimeDuration OverflowRegionRefreshInterval(); }; class KeyframeEffect : public KeyframeEffectReadOnly { public: KeyframeEffect(nsIDocument* aDocument, - Element* aTarget, - CSSPseudoElementType aPseudoType, + const Maybe<OwningAnimationTarget>& aTarget, const TimingParams& aTiming); JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; static already_AddRefed<KeyframeEffect> Constructor(const GlobalObject& aGlobal, const Nullable<ElementOrCSSPseudoElement>& aTarget, @@ -427,16 +430,29 @@ public: Constructor(const GlobalObject& aGlobal, const Nullable<ElementOrCSSPseudoElement>& aTarget, JS::Handle<JSObject*> aFrames, const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions, ErrorResult& aRv); void NotifySpecifiedTimingUpdated(); + // This method calls MaybeUpdateProperties which is not safe to use when + // we are in the middle of updating style. If we need to use this when + // updating style, we should pass the nsStyleContext into this method and use + // that to update the properties rather than calling + // GetStyleContextForElement. + void SetTarget(const Nullable<ElementOrCSSPseudoElement>& aTarget); + protected: ~KeyframeEffect() override; + + // We need to be careful to *not* call this when we are updating the style + // context. That's because calling GetStyleContextForElement when we are in + // the process of building a style context may trigger various forms of + // infinite recursion. + void MaybeUpdateProperties(); }; } // namespace dom } // namespace mozilla #endif // mozilla_dom_KeyframeEffect_h
--- a/dom/animation/PseudoElementHashEntry.h +++ b/dom/animation/PseudoElementHashEntry.h @@ -3,18 +3,18 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_PseudoElementHashEntry_h #define mozilla_PseudoElementHashEntry_h #include "mozilla/dom/Element.h" +#include "mozilla/AnimationTarget.h" #include "mozilla/HashFunctions.h" -#include "mozilla/NonOwningAnimationTarget.h" #include "PLDHashTable.h" namespace mozilla { // A hash entry that uses a RefPtr<dom::Element>, CSSPseudoElementType pair class PseudoElementHashEntry : public PLDHashEntryHdr { public:
--- a/dom/animation/moz.build +++ b/dom/animation/moz.build @@ -16,24 +16,24 @@ EXPORTS.mozilla.dom += [ 'CSSPseudoElement.h', 'DocumentTimeline.h', 'KeyframeEffect.h', ] EXPORTS.mozilla += [ 'AnimationComparator.h', 'AnimationPerformanceWarning.h', + 'AnimationTarget.h', 'AnimationUtils.h', 'AnimValuesStyleRule.h', 'ComputedTiming.h', 'ComputedTimingFunction.h', 'EffectCompositor.h', 'EffectSet.h', 'KeyframeUtils.h', - 'NonOwningAnimationTarget.h', 'PendingAnimationTracker.h', 'PseudoElementHashEntry.h', 'TimingParams.h', ] UNIFIED_SOURCES += [ 'Animation.cpp', 'AnimationEffectReadOnly.cpp',
--- a/dom/animation/test/chrome/test_animation_observers.html +++ b/dom/animation/test/chrome/test_animation_observers.html @@ -1713,16 +1713,91 @@ addAsyncAnimTest("exclude_animations_tar anim.finish(); pAnim.finish(); yield await_frame(); assert_records([{ added: [], changed: [], removed: [anim] }], "records after animation is finished"); }); +addAsyncAnimTest("create_animation_without_target", + { observe: document, subtree: true }, function*() { + var effect = new KeyframeEffectReadOnly(null, + { opacity: [ 0, 1 ] }, + { duration: 10000 }); + var anim = new Animation(effect, document.timeline); + anim.play(); + yield await_frame(); + assert_records([], "no records after animation is added"); + + anim.cancel(); + yield await_frame(); + assert_records([], "no records after animation is removed"); +}); + +addAsyncAnimTest("set_animation_target", + { observe: document, subtree: true }, function*() { + var anim = div.animate({ opacity: [ 0, 1 ] }, + { duration: 100 * MS_PER_SEC }); + + yield await_frame(); + assert_records([{ added: [anim], changed: [], removed: [] }], + "records after animation is added"); + + anim.effect.target = null; + yield await_frame(); + assert_records([{ added: [], changed: [], removed: [anim] }], + "records after setting null"); + + anim.effect.target = div; + yield await_frame(); + assert_records([{ added: [anim], changed: [], removed: [] }], + "records after setting a target"); + + var newTarget = document.createElement("div"); + document.body.appendChild(newTarget); + anim.effect.target = newTarget; + yield await_frame(); + assert_records([{ added: [], changed: [], removed: [anim] }, + { added: [anim], changed: [], removed: [] }], + "records after setting a different target"); + + anim.cancel(); + yield await_frame(); + assert_records([{ added: [], changed: [], removed: [anim] }], + "records after animation ends"); + + newTarget.remove(); +}); + +addAsyncAnimTest("set_redundant_animation_target", + { observe: div, subtree: true }, function*() { + var anim = div.animate({ opacity: [ 0, 1 ] }, + { duration: 100 * MS_PER_SEC }); + yield await_frame(); + assert_records([{ added: [anim], changed: [], removed: [] }], + "records after animation is added"); + + anim.effect.target = div; + yield await_frame(); + assert_records([], "no records after setting the same target"); + + anim.effect.target = null; + yield await_frame(); + assert_records([{ added: [], changed: [], removed: [anim] }], + "records after setting null"); + + anim.effect.target = null; + yield await_frame(); + assert_records([], "records after setting redundant null"); + + anim.cancel(); + yield await_frame(); +}); + // Run the tests. SimpleTest.requestLongerTimeout(2); SimpleTest.waitForExplicitFinish(); runAllAsyncTests().then(function() { SimpleTest.finish(); }, function(aError) { ok(false, "Something failed: " + aError);
--- a/dom/animation/test/chrome/test_running_on_compositor.html +++ b/dom/animation/test/chrome/test_running_on_compositor.html @@ -404,11 +404,49 @@ promise_test(function(t) { }).then(function() { assert_equals(animation.isRunningOnCompositor, false, 'Animation reports that it is NOT running on the compositor' + ' when currentTime is after endTime'); }); }, 'animation is NOT running on compositor' + ' when endTime is positive and endDelay is negative'); -</script> +promise_test(function(t) { + var effect = new KeyframeEffect(null, + { opacity: [ 0, 1 ] }, + 100 * MS_PER_SEC); + var animation = new Animation(effect, document.timeline); + animation.play(); + + var div = addDiv(t); + + return animation.ready.then(function() { + assert_equals(animation.isRunningOnCompositor, false, + 'Animation with null target reports that it is not running ' + + 'on the compositor'); + + animation.effect.target = div; + return waitForFrame(); + }).then(function() { + assert_equals(animation.isRunningOnCompositor, omtaEnabled, + 'Animation reports that it is running on the compositor ' + + 'after setting a valid target'); + }); +}, 'animation is added to the compositor when setting a valid target'); + +promise_test(function(t) { + var div = addDiv(t); + var animation = div.animate({ opacity: [ 0, 1 ] }, 100 * MS_PER_SEC); + + return animation.ready.then(function() { + assert_equals(animation.isRunningOnCompositor, omtaEnabled, + 'Animation reports that it is running on the compositor'); + + animation.effect.target = null; + assert_equals(animation.isRunningOnCompositor, false, + 'Animation reports that it is NOT running on the ' + + 'compositor after setting null target'); + }); +}, 'animation is removed from the compositor when setting null target'); + + </script> </body>
--- a/dom/apps/AppsService.js +++ b/dom/apps/AppsService.js @@ -165,17 +165,13 @@ AppsService.prototype = { // properly in child processes. if (Services.appinfo.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT) { throw Cr.NS_ERROR_FAILURE; } return UserCustomizations.isFromExtension(aURI); }, - updateDataStoreEntriesFromLocalId: function(aLocalId) { - return DOMApplicationRegistry.updateDataStoreEntriesFromLocalId(aLocalId); - }, - classID : APPS_SERVICE_CID, QueryInterface : XPCOMUtils.generateQI([Ci.nsIAppsService]) } this.NSGetFactory = XPCOMUtils.generateNSGetFactory([AppsService])
--- a/dom/apps/AppsServiceChild.jsm +++ b/dom/apps/AppsServiceChild.jsm @@ -413,16 +413,12 @@ this.DOMApplicationRegistry = { }, areAnyAppsInstalled: function() { return AppsUtils.areAnyAppsInstalled(this.webapps); }, getAppInfo: function getAppInfo(aAppId) { return AppsUtils.getAppInfo(this.webapps, aAppId); - }, - - updateDataStoreEntriesFromLocalId: function(aLocalId) { - debug("updateDataStoreEntriesFromLocalId() not yet supported on child!"); } } DOMApplicationRegistry.init();
--- a/dom/apps/Webapps.jsm +++ b/dom/apps/Webapps.jsm @@ -142,20 +142,16 @@ XPCOMUtils.defineLazyServiceGetter(this, "@mozilla.org/childprocessmessagemanager;1", "nsIMessageSender"); XPCOMUtils.defineLazyGetter(this, "interAppCommService", function() { return Cc["@mozilla.org/inter-app-communication-service;1"] .getService(Ci.nsIInterAppCommService); }); -XPCOMUtils.defineLazyServiceGetter(this, "dataStoreService", - "@mozilla.org/datastore-service;1", - "nsIDataStoreService"); - XPCOMUtils.defineLazyServiceGetter(this, "appsService", "@mozilla.org/AppsService;1", "nsIAppsService"); XPCOMUtils.defineLazyGetter(this, "msgmgr", function() { return Cc["@mozilla.org/system-message-internal;1"] .getService(Ci.nsISystemMessagesInternal); }); @@ -445,28 +441,16 @@ this.DOMApplicationRegistry = { Langpacks.register(app, aResult.manifest); }); // Nothing else to do but notifying we're ready. this.notifyAppsRegistryReady(); } }), - updateDataStoreForApp: Task.async(function*(aId) { - if (!this.webapps[aId]) { - return; - } - - // Create or Update the DataStore for this app - let results = yield this._readManifests([{ id: aId }]); - let app = this.webapps[aId]; - this.updateDataStore(app.localId, app.origin, app.manifestURL, - results[0].manifest, app.appStatus); - }), - appKind: function(aApp, aManifest) { if (aApp.origin.startsWith("android://")) { return this.kAndroid; } if (aApp.origin.startsWith("app://")) { return this.kPackaged; } else { // Hosted apps, can be appcached or not. let kind = this.kHosted; @@ -808,62 +792,20 @@ this.DOMApplicationRegistry = { } // Need to update the persisted list of apps since // installPreinstalledApp() removes the ones failing to install. yield this._saveApps(); Services.prefs.setBoolPref("dom.apps.reset-permissions", true); } - // DataStores must be initialized at startup. - for (let id in this.webapps) { - yield this.updateDataStoreForApp(id); - } - yield this.registerAppsHandlers(runUpdate); }.bind(this)).then(null, Cu.reportError); }, - updateDataStore: function(aId, aOrigin, aManifestURL, aManifest) { - if (!aManifest) { - debug("updateDataStore: no manifest for " + aOrigin); - return; - } - - let uri = Services.io.newURI(aOrigin, null, null); - let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"] - .getService(Ci.nsIScriptSecurityManager); - let principal = secMan.createCodebasePrincipal(uri, {appId: aId}); - if (!dataStoreService.checkPermission(principal)) { - return; - } - - if ('datastores-owned' in aManifest) { - for (let name in aManifest['datastores-owned']) { - let readonly = "access" in aManifest['datastores-owned'][name] - ? aManifest['datastores-owned'][name].access == 'readonly' - : false; - - dataStoreService.installDataStore(aId, name, aOrigin, aManifestURL, - readonly); - } - } - - if ('datastores-access' in aManifest) { - for (let name in aManifest['datastores-access']) { - let readonly = ("readonly" in aManifest['datastores-access'][name]) && - !aManifest['datastores-access'][name].readonly - ? false : true; - - dataStoreService.installAccessDataStore(aId, name, aOrigin, - aManifestURL, readonly); - } - } - }, - // |aEntryPoint| is either the entry_point name or the null in which case we // use the root of the manifest. // // TODO Bug 908094 Refine _registerSystemMessagesForEntryPoint(...). _registerSystemMessagesForEntryPoint: function(aManifest, aApp, aEntryPoint) { let root = aManifest; if (aEntryPoint && aManifest.entry_points[aEntryPoint]) { root = aManifest.entry_points[aEntryPoint]; @@ -1964,18 +1906,16 @@ this.DOMApplicationRegistry = { if (supportUseCurrentProfile()) { PermissionsInstaller.installPermissions( { manifest: newManifest, origin: app.origin, manifestURL: app.manifestURL }, true); } - this.updateDataStore(this.webapps[id].localId, app.origin, - app.manifestURL, newManifest); MessageBroadcaster.broadcastMessage("Webapps:UpdateState", { app: app, manifest: newManifest, id: app.id }); MessageBroadcaster.broadcastMessage("Webapps:FireEvent", { eventType: "downloadapplied", manifestURL: app.manifestURL @@ -2414,19 +2354,16 @@ this.DOMApplicationRegistry = { // Update the permissions for this app. PermissionsInstaller.installPermissions({ manifest: aApp.manifest, origin: aApp.origin, manifestURL: aData.manifestURL }, true); } - this.updateDataStore(this.webapps[aId].localId, aApp.origin, - aApp.manifestURL, aApp.manifest); - aApp.name = aNewManifest.name; aApp.csp = manifest.csp || ""; aApp.updateTime = Date.now(); } // Update the registry. this.webapps[aId] = aApp; yield this._saveApps(); @@ -3071,19 +3008,16 @@ this.DOMApplicationRegistry = { manifestURL: appObject.manifestURL, manifest: jsonManifest, kind: appObject.kind }, isReinstall, this.doUninstall.bind(this, aData, aData.mm) ); } - - this.updateDataStore(this.webapps[id].localId, this.webapps[id].origin, - this.webapps[id].manifestURL, jsonManifest); } for (let prop of ["installState", "downloadAvailable", "downloading", "downloadSize", "readyToApplyDownload"]) { aData.app[prop] = appObject[prop]; } let dontNeedNetwork = false; @@ -3212,19 +3146,16 @@ this.DOMApplicationRegistry = { PermissionsInstaller.installPermissions({ manifest: aManifest, origin: aNewApp.origin, manifestURL: aNewApp.manifestURL, kind: this.webapps[aId].kind }, true); } - this.updateDataStore(this.webapps[aId].localId, aNewApp.origin, - aNewApp.manifestURL, aManifest); - if (aInstallSuccessCallback) { yield aInstallSuccessCallback(aNewApp, aManifest, zipFile.path); } MessageBroadcaster.broadcastMessage("Webapps:UpdateState", { app: app, manifest: aManifest, manifestURL: aNewApp.manifestURL @@ -4750,23 +4681,16 @@ this.DOMApplicationRegistry = { getWebAppsBasePath: function() { return OS.Path.dirname(this.appsFile); }, areAnyAppsInstalled: function() { return AppsUtils.areAnyAppsInstalled(this.webapps); }, - updateDataStoreEntriesFromLocalId: function(aLocalId) { - let app = appsService.getAppByLocalId(aLocalId); - if (app) { - this.updateDataStoreForApp(app.id); - } - }, - _notifyCategoryAndObservers: function(subject, topic, data, msg) { const serviceMarker = "service,"; // First create observers from the category manager. let cm = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager); let enumerator = cm.enumerateCategory(topic);
--- a/dom/apps/tests/test_widget_browser.html +++ b/dom/apps/tests/test_widget_browser.html @@ -1,13 +1,13 @@ <!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> - <title>Test for DataStore - basic operation on a readonly db</title> + <title>?!?</title> <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> <script type="application/javascript" src="file_test_widget.js"></script> <script type="application/javascript" src="common.js"></script> <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> </head> <body> <div id="container"></div> <script type="application/javascript;version=1.7">
--- a/dom/base/FragmentOrElement.h +++ b/dom/base/FragmentOrElement.h @@ -137,17 +137,17 @@ public: { return SetText(aStr.BeginReading(), aStr.Length(), aNotify); } virtual nsresult AppendText(const char16_t* aBuffer, uint32_t aLength, bool aNotify) override; virtual bool TextIsOnlyWhitespace() override; virtual bool HasTextForTranslation() override; virtual void AppendTextTo(nsAString& aResult) override; - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE virtual bool AppendTextTo(nsAString& aResult, const mozilla::fallible_t&) override; virtual nsIContent *GetBindingParent() const override; virtual nsXBLBinding *GetXBLBinding() const override; virtual void SetXBLBinding(nsXBLBinding* aBinding, nsBindingManager* aOldBindingManager = nullptr) override; virtual ShadowRoot *GetShadowRoot() const override; virtual ShadowRoot *GetContainingShadow() const override; virtual nsTArray<nsIContent*> &DestInsertionPoints() override;
--- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -91,17 +91,16 @@ #include "AudioChannelManager.h" #endif #ifdef MOZ_B2G_FM #include "mozilla/dom/FMRadio.h" #endif #include "nsIDOMGlobalPropertyInitializer.h" -#include "mozilla/dom/DataStoreService.h" #include "nsJSUtils.h" #include "nsScriptNameSpaceManager.h" #include "mozilla/dom/NavigatorBinding.h" #include "mozilla/dom/Promise.h" #include "nsIUploadChannel2.h" @@ -1514,48 +1513,16 @@ Navigator::GetDeprecatedBattery(ErrorRes mBatteryManager = new battery::BatteryManager(mWindow); mBatteryManager->Init(); } return mBatteryManager; } -/* static */ already_AddRefed<Promise> -Navigator::GetDataStores(nsPIDOMWindowInner* aWindow, - const nsAString& aName, - const nsAString& aOwner, - ErrorResult& aRv) -{ - if (!aWindow || !aWindow->GetDocShell()) { - aRv.Throw(NS_ERROR_UNEXPECTED); - return nullptr; - } - - RefPtr<DataStoreService> service = DataStoreService::GetOrCreate(); - if (!service) { - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - - nsCOMPtr<nsISupports> promise; - aRv = service->GetDataStores(aWindow, aName, aOwner, getter_AddRefs(promise)); - - RefPtr<Promise> p = static_cast<Promise*>(promise.get()); - return p.forget(); -} - -already_AddRefed<Promise> -Navigator::GetDataStores(const nsAString& aName, - const nsAString& aOwner, - ErrorResult& aRv) -{ - return GetDataStores(mWindow, aName, aOwner, aRv); -} - already_AddRefed<Promise> Navigator::GetFeature(const nsAString& aName, ErrorResult& aRv) { nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(mWindow); RefPtr<Promise> p = Promise::Create(go, aRv); if (aRv.Failed()) { return nullptr; } @@ -2305,85 +2272,16 @@ bool Navigator::HasUserMediaSupport(JSContext* /* unused */, JSObject* /* unused */) { // Make enabling peerconnection enable getUserMedia() as well return Preferences::GetBool("media.navigator.enabled", false) || Preferences::GetBool("media.peerconnection.enabled", false); } -/* static */ -bool -Navigator::HasDataStoreSupport(nsIPrincipal* aPrincipal) -{ - workers::AssertIsOnMainThread(); - - return DataStoreService::CheckPermission(aPrincipal); -} - -// A WorkerMainThreadRunnable to synchronously dispatch the call of -// HasDataStoreSupport() from the worker thread to the main thread. -class HasDataStoreSupportRunnable final - : public workers::WorkerCheckAPIExposureOnMainThreadRunnable -{ -public: - bool mResult; - - explicit HasDataStoreSupportRunnable(workers::WorkerPrivate* aWorkerPrivate) - : workers::WorkerCheckAPIExposureOnMainThreadRunnable(aWorkerPrivate) - , mResult(false) - { - MOZ_ASSERT(aWorkerPrivate); - aWorkerPrivate->AssertIsOnWorkerThread(); - } - -protected: - virtual bool - MainThreadRun() override - { - workers::AssertIsOnMainThread(); - - mResult = Navigator::HasDataStoreSupport(mWorkerPrivate->GetPrincipal()); - - return true; - } -}; - -/* static */ -bool -Navigator::HasDataStoreSupport(JSContext* aCx, JSObject* aGlobal) -{ - // If the caller is on the worker thread, dispatch this to the main thread. - if (!NS_IsMainThread()) { - workers::WorkerPrivate* workerPrivate = - workers::GetWorkerPrivateFromContext(aCx); - workerPrivate->AssertIsOnWorkerThread(); - - RefPtr<HasDataStoreSupportRunnable> runnable = - new HasDataStoreSupportRunnable(workerPrivate); - return runnable->Dispatch() && runnable->mResult; - } - - workers::AssertIsOnMainThread(); - - JS::Rooted<JSObject*> global(aCx, aGlobal); - - nsCOMPtr<nsPIDOMWindowInner> win = GetWindowFromGlobal(global); - if (!win) { - return false; - } - - nsIDocument* doc = win->GetExtantDoc(); - if (!doc || !doc->NodePrincipal()) { - return false; - } - - return HasDataStoreSupport(doc->NodePrincipal()); -} - #ifdef MOZ_B2G /* static */ bool Navigator::HasMobileIdSupport(JSContext* aCx, JSObject* aGlobal) { nsCOMPtr<nsPIDOMWindowInner> win = GetWindowFromGlobal(aGlobal); if (!win) { return false;
--- a/dom/base/Navigator.h +++ b/dom/base/Navigator.h @@ -162,21 +162,16 @@ public: nsMimeTypeArray* GetMimeTypes(ErrorResult& aRv); nsPluginArray* GetPlugins(ErrorResult& aRv); Permissions* GetPermissions(ErrorResult& aRv); // The XPCOM GetDoNotTrack is ok Geolocation* GetGeolocation(ErrorResult& aRv); Promise* GetBattery(ErrorResult& aRv); battery::BatteryManager* GetDeprecatedBattery(ErrorResult& aRv); - static already_AddRefed<Promise> GetDataStores(nsPIDOMWindowInner* aWindow, - const nsAString& aName, - const nsAString& aOwner, - ErrorResult& aRv); - static void AppName(nsAString& aAppName, bool aUsePrefOverriddenValue); static nsresult GetPlatform(nsAString& aPlatform, bool aUsePrefOverriddenValue); static nsresult GetAppVersion(nsAString& aAppVersion, bool aUsePrefOverriddenValue); @@ -184,20 +179,16 @@ public: nsIURI* aURI, bool aIsCallerChrome, nsAString& aUserAgent); // Clears the user agent cache by calling: // NavigatorBinding::ClearCachedUserAgentValue(this); void ClearUserAgentCache(); - already_AddRefed<Promise> GetDataStores(const nsAString& aName, - const nsAString& aOwner, - ErrorResult& aRv); - // Feature Detection API already_AddRefed<Promise> GetFeature(const nsAString& aName, ErrorResult& aRv); already_AddRefed<Promise> HasFeature(const nsAString &aName, ErrorResult& aRv); bool Vibrate(uint32_t aDuration); @@ -324,20 +315,16 @@ public: static bool HasWifiManagerSupport(JSContext* /* unused */, JSObject* aGlobal); #ifdef MOZ_NFC static bool HasNFCSupport(JSContext* /* unused */, JSObject* aGlobal); #endif // MOZ_NFC static bool HasUserMediaSupport(JSContext* /* unused */, JSObject* /* unused */); - static bool HasDataStoreSupport(nsIPrincipal* aPrincipal); - - static bool HasDataStoreSupport(JSContext* cx, JSObject* aGlobal); - #ifdef MOZ_B2G static bool HasMobileIdSupport(JSContext* aCx, JSObject* aGlobal); #endif static bool HasPresentationSupport(JSContext* aCx, JSObject* aGlobal); static bool IsE10sEnabled(JSContext* aCx, JSObject* aGlobal);
--- a/dom/base/domerr.msg +++ b/dom/base/domerr.msg @@ -113,17 +113,16 @@ DOM4_MSG_DEF(BtParmInvalidError, "Inval DOM4_MSG_DEF(BtUnhandledError, "Unhandled", NS_ERROR_DOM_BLUETOOTH_UNHANDLED) DOM4_MSG_DEF(BtAuthFailureError, "Authentication failure", NS_ERROR_DOM_BLUETOOTH_AUTH_FAILURE) DOM4_MSG_DEF(BtRmtDevDownError, "Remote device down", NS_ERROR_DOM_BLUETOOTH_RMT_DEV_DOWN) DOM4_MSG_DEF(BtAuthRejectedError, "Authentication rejected", NS_ERROR_DOM_BLUETOOTH_AUTH_REJECTED) /* Web Animations errors */ DOM4_MSG_DEF(NotSupportedError, "Animation to or from an underlying value is not yet supported.", NS_ERROR_DOM_ANIM_MISSING_PROPS_ERR) -DOM4_MSG_DEF(NotSupportedError, "Animation with no target is not yet supported.", NS_ERROR_DOM_ANIM_NO_TARGET_ERR) DOM4_MSG_DEF(NotSupportedError, "Animation with no timeline is not yet supported.", NS_ERROR_DOM_ANIM_NO_TIMELINE_ERR) DOM4_MSG_DEF(NotSupportedError, "Animation with no effect is not yet supported.", NS_ERROR_DOM_ANIM_NO_EFFECT_ERR) /* common global codes (from nsError.h) */ DOM_MSG_DEF(NS_OK , "Success") DOM_MSG_DEF(NS_ERROR_NOT_INITIALIZED , "Component not initialized") DOM_MSG_DEF(NS_ERROR_ALREADY_INITIALIZED , "Component already initialized")
--- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -1387,17 +1387,17 @@ public: * @see nsLayoutUtils::GetFrameTextContent * * @param aNode Node to get textual contents of. * @param aDeep If true child elements of aNode are recursivly descended * into to find text children. * @param aResult the result. Out param. * @return false on out of memory errors, true otherwise. */ - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE static bool GetNodeTextContent(nsINode* aNode, bool aDeep, nsAString& aResult, const mozilla::fallible_t&); static void GetNodeTextContent(nsINode* aNode, bool aDeep, nsAString& aResult); /** * Same as GetNodeTextContents but appends the result rather than sets it. @@ -1759,34 +1759,34 @@ public: /** * The method checks whether the caller can access native anonymous content. * If there is no JS in the stack or privileged JS is running, this * method returns true, otherwise false. */ static bool CanAccessNativeAnon(); - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE static nsresult WrapNative(JSContext *cx, nsISupports *native, const nsIID* aIID, JS::MutableHandle<JS::Value> vp, bool aAllowWrapping = true) { return WrapNative(cx, native, nullptr, aIID, vp, aAllowWrapping); } // Same as the WrapNative above, but use this one if aIID is nsISupports' IID. - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE static nsresult WrapNative(JSContext *cx, nsISupports *native, JS::MutableHandle<JS::Value> vp, bool aAllowWrapping = true) { return WrapNative(cx, native, nullptr, nullptr, vp, aAllowWrapping); } - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE static nsresult WrapNative(JSContext *cx, nsISupports *native, nsWrapperCache *cache, JS::MutableHandle<JS::Value> vp, bool aAllowWrapping = true) { return WrapNative(cx, native, cache, nullptr, vp, aAllowWrapping); } @@ -1809,17 +1809,17 @@ public: */ static void RemoveNewlines(nsString &aString); /** * Convert Windows and Mac platform linebreaks to \n. * @param aString the string to convert the newlines inside [in/out] */ static void PlatformToDOMLineBreaks(nsString &aString); - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE static bool PlatformToDOMLineBreaks(nsString &aString, const mozilla::fallible_t&); /** * Populates aResultString with the contents of the string-buffer aBuf, up * to aBuf's null-terminator. aBuf must not be null. Ownership of the string * is not transferred. */
--- a/dom/base/nsGenericDOMDataNode.h +++ b/dom/base/nsGenericDOMDataNode.h @@ -133,17 +133,17 @@ public: { return SetText(aStr.BeginReading(), aStr.Length(), aNotify); } virtual nsresult AppendText(const char16_t* aBuffer, uint32_t aLength, bool aNotify) override; virtual bool TextIsOnlyWhitespace() override; virtual bool HasTextForTranslation() override; virtual void AppendTextTo(nsAString& aResult) override; - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE virtual bool AppendTextTo(nsAString& aResult, const mozilla::fallible_t&) override; virtual void SaveSubtreeState() override; #ifdef DEBUG virtual void List(FILE* out, int32_t aIndent) const override; virtual void DumpContent(FILE* out, int32_t aIndent, bool aDumpAll) const override; #endif
--- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -7715,24 +7715,16 @@ nsGlobalWindow::FirePopupBlockedEvent(ns init); event->SetTrusted(true); bool defaultActionEnabled; aDoc->DispatchEvent(event, &defaultActionEnabled); } -static void FirePopupWindowEvent(nsIDocument* aDoc) -{ - // Fire a "PopupWindow" event - nsContentUtils::DispatchTrustedEvent(aDoc, aDoc, - NS_LITERAL_STRING("PopupWindow"), - true, true); -} - // static bool nsGlobalWindow::CanSetProperty(const char *aPrefName) { // Chrome can set any property. if (nsContentUtils::LegacyIsCallerChromeOrNativeCode()) { return true; } @@ -7792,23 +7784,19 @@ nsGlobalWindow::RevisePopupAbuseLevel(Po int32_t popupMax = Preferences::GetInt("dom.popup_maximum", -1); if (popupMax >= 0 && gOpenPopupSpamCount >= popupMax) abuse = openOverridden; } return abuse; } -/* If a window open is blocked, fire the appropriate DOM events. - aBlocked signifies we just blocked a popup. - aWindow signifies we just opened what is probably a popup. -*/ -void -nsGlobalWindow::FireAbuseEvents(bool aBlocked, bool aWindow, - const nsAString &aPopupURL, +/* If a window open is blocked, fire the appropriate DOM events. */ +void +nsGlobalWindow::FireAbuseEvents(const nsAString &aPopupURL, const nsAString &aPopupWindowName, const nsAString &aPopupWindowFeatures) { // fetch the URI of the window requesting the opened window nsCOMPtr<nsPIDOMWindowOuter> window = GetTop(); if (!window) { return; @@ -7830,22 +7818,18 @@ nsGlobalWindow::FireAbuseEvents(bool aBl // use the base URI to build what would have been the popup's URI nsCOMPtr<nsIIOService> ios(do_GetService(NS_IOSERVICE_CONTRACTID)); if (ios) ios->NewURI(NS_ConvertUTF16toUTF8(aPopupURL), 0, baseURL, getter_AddRefs(popupURI)); // fire an event chock full of informative URIs - if (aBlocked) { - FirePopupBlockedEvent(topDoc, popupURI, aPopupWindowName, - aPopupWindowFeatures); - } - if (aWindow) - FirePopupWindowEvent(topDoc); + FirePopupBlockedEvent(topDoc, popupURI, aPopupWindowName, + aPopupWindowFeatures); } already_AddRefed<nsPIDOMWindowOuter> nsGlobalWindow::OpenOuter(const nsAString& aUrl, const nsAString& aName, const nsAString& aOptions, ErrorResult& aError) { MOZ_RELEASE_ASSERT(IsOuterWindow()); nsCOMPtr<nsPIDOMWindowOuter> window; @@ -11586,17 +11570,17 @@ nsGlobalWindow::OpenInternal(const nsASt // prevent this window from closing until after this script terminates // so that whatever popup blocker UI the app has will be visible. if (mContext == GetScriptContextFromJSContext(aJSCallerContext)) { mBlockScriptedClosingFlag = true; closeUnblocker.emplace(this); } } - FireAbuseEvents(true, false, aUrl, aName, aOptions); + FireAbuseEvents(aUrl, aName, aOptions); return aDoJSFixups ? NS_OK : NS_ERROR_FAILURE; } } nsCOMPtr<mozIDOMWindowProxy> domReturn; nsCOMPtr<nsIWindowWatcher> wwatch = do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv); @@ -11668,25 +11652,25 @@ nsGlobalWindow::OpenInternal(const nsASt // XXXbz should this just use EnsureInnerWindow()? // Force document creation. nsCOMPtr<nsIDocument> doc = (*aReturn)->GetDoc(); } } if (checkForPopup) { + MOZ_ASSERT(abuseLevel < openAbused, "Why didn't we take the early return?"); + if (abuseLevel >= openControlled) { nsGlobalWindow *opened = nsGlobalWindow::Cast(*aReturn); if (!opened->IsPopupSpamWindow()) { opened->SetPopupSpamWindow(true); ++gOpenPopupSpamCount; } } - if (abuseLevel >= openAbused) - FireAbuseEvents(false, true, aUrl, aName, aOptions); } return rv; } //***************************************************************************** // nsGlobalWindow: Timeout Functions //*****************************************************************************
--- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -1462,18 +1462,17 @@ public: already_AddRefed<nsIDocShellTreeOwner> GetTreeOwner(); already_AddRefed<nsIBaseWindow> GetTreeOwnerWindow(); already_AddRefed<nsIWebBrowserChrome> GetWebBrowserChrome(); nsresult SecurityCheckURL(const char *aURL); bool IsPrivateBrowsing(); bool PopupWhitelisted(); PopupControlState RevisePopupAbuseLevel(PopupControlState); - void FireAbuseEvents(bool aBlocked, bool aWindow, - const nsAString &aPopupURL, + void FireAbuseEvents(const nsAString &aPopupURL, const nsAString &aPopupWindowName, const nsAString &aPopupWindowFeatures); void FireOfflineStatusEventIfChanged(); bool GetIsPrerendered(); // Inner windows only. nsresult ScheduleNextIdleObserverCallback();
--- a/dom/base/nsHTMLContentSerializer.h +++ b/dom/base/nsHTMLContentSerializer.h @@ -32,26 +32,26 @@ class nsHTMLContentSerializer final : pu NS_IMETHOD AppendElementEnd(mozilla::dom::Element* aElement, nsAString& aStr) override; NS_IMETHOD AppendDocumentStart(nsIDocument *aDocument, nsAString& aStr) override; protected: - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE virtual bool SerializeHTMLAttributes(nsIContent* aContent, nsIContent *aOriginalElement, nsAString& aTagPrefix, const nsAString& aTagNamespaceURI, nsIAtom* aTagName, int32_t aNamespace, nsAString& aStr); - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE virtual bool AppendAndTranslateEntities(const nsAString& aStr, nsAString& aOutputStr) override; }; nsresult NS_NewHTMLContentSerializer(nsIContentSerializer** aSerializer);
--- a/dom/base/nsIContent.h +++ b/dom/base/nsIContent.h @@ -541,17 +541,17 @@ public: * NOTE: This asserts and returns for elements */ virtual void AppendTextTo(nsAString& aResult) = 0; /** * Append the text content to aResult. * NOTE: This asserts and returns for elements */ - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE virtual bool AppendTextTo(nsAString& aResult, const mozilla::fallible_t&) = 0; /** * Check if this content is focusable and in the current tab order. * Note: most callers should use nsIFrame::IsFocusable() instead as it * checks visibility and other layout factors as well. * Tabbable is indicated by a nonnegative tabindex & is a subset of focusable. * For example, only the selected radio button in a group is in the
--- a/dom/base/nsIDocument.h +++ b/dom/base/nsIDocument.h @@ -1042,16 +1042,27 @@ public: nsIURI* aSheetURI) = 0; virtual nsresult AddAdditionalStyleSheet(additionalSheetType aType, mozilla::StyleSheetHandle aSheet) = 0; virtual void RemoveAdditionalStyleSheet(additionalSheetType aType, nsIURI* sheetURI) = 0; virtual mozilla::StyleSheetHandle GetFirstAdditionalAuthorSheet() = 0; /** + * Assuming that aDocSheets is an array of document-level style + * sheets for this document, returns the index that aSheet should + * be inserted at to maintain document ordering. + * + * Defined in nsIDocumentInlines.h. + */ + template<typename T> + size_t FindDocStyleSheetInsertionPoint(const nsTArray<RefPtr<T>>& aDocSheets, + T* aSheet); + + /** * Get this document's CSSLoader. This is guaranteed to not return null. */ mozilla::css::Loader* CSSLoader() const { return mCSSLoader; } mozilla::StyleBackendType GetStyleBackendType() const;
--- a/dom/base/nsIDocumentInlines.h +++ b/dom/base/nsIDocumentInlines.h @@ -3,16 +3,58 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nsIDocumentInlines_h #define nsIDocumentInlines_h #include "nsIDocument.h" #include "mozilla/dom/HTMLBodyElement.h" +#include "nsStyleSheetService.h" inline mozilla::dom::HTMLBodyElement* nsIDocument::GetBodyElement() { return static_cast<mozilla::dom::HTMLBodyElement*>(GetHtmlChildElement(nsGkAtoms::body)); } +template<typename T> +size_t +nsIDocument::FindDocStyleSheetInsertionPoint( + const nsTArray<RefPtr<T>>& aDocSheets, + T* aSheet) +{ + nsStyleSheetService* sheetService = nsStyleSheetService::GetInstance(); + + // lowest index first + int32_t newDocIndex = GetIndexOfStyleSheet(aSheet); + + int32_t count = aDocSheets.Length(); + int32_t index; + for (index = 0; index < count; index++) { + T* sheet = aDocSheets[index]; + int32_t sheetDocIndex = GetIndexOfStyleSheet(sheet); + if (sheetDocIndex > newDocIndex) + break; + + mozilla::StyleSheetHandle sheetHandle = sheet; + + // If the sheet is not owned by the document it can be an author + // sheet registered at nsStyleSheetService or an additional author + // sheet on the document, which means the new + // doc sheet should end up before it. + if (sheetDocIndex < 0) { + if (sheetService) { + auto& authorSheets = *sheetService->AuthorStyleSheets(); + if (authorSheets.IndexOf(sheetHandle) != authorSheets.NoIndex) { + break; + } + } + if (sheetHandle == GetFirstAdditionalAuthorSheet()) { + break; + } + } + } + + return size_t(index); +} + #endif // nsIDocumentInlines_h
--- a/dom/base/nsNodeUtils.cpp +++ b/dom/base/nsNodeUtils.cpp @@ -19,16 +19,17 @@ #include "nsCOMArray.h" #include "nsPIDOMWindow.h" #include "nsDocument.h" #ifdef MOZ_XUL #include "nsXULElement.h" #endif #include "nsBindingManager.h" #include "nsGenericHTMLElement.h" +#include "mozilla/AnimationTarget.h" #include "mozilla/Assertions.h" #include "mozilla/dom/Animation.h" #include "mozilla/dom/HTMLImageElement.h" #include "mozilla/dom/HTMLMediaElement.h" #include "mozilla/dom/KeyframeEffect.h" #include "nsWrapperCacheInlines.h" #include "nsObjectLoadingContent.h" #include "nsDOMMutationObserver.h"
--- a/dom/base/nsNodeUtils.h +++ b/dom/base/nsNodeUtils.h @@ -3,26 +3,26 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nsNodeUtils_h___ #define nsNodeUtils_h___ #include "mozilla/Maybe.h" -#include "mozilla/NonOwningAnimationTarget.h" #include "nsIContent.h" // for use in inline function (ParentChainChanged) #include "nsIMutationObserver.h" // for use in inline function (ParentChainChanged) #include "js/TypeDecls.h" #include "nsCOMArray.h" struct CharacterDataChangeInfo; template<class E> class nsCOMArray; class nsCycleCollectionTraversalCallback; namespace mozilla { +struct NonOwningAnimationTarget; namespace dom { class Animation; } // namespace dom } // namespace mozilla class nsNodeUtils { public:
--- a/dom/base/nsScriptLoader.h +++ b/dom/base/nsScriptLoader.h @@ -174,24 +174,24 @@ public: void AppendElement(nsScriptLoadRequest* aElem) { MOZ_ASSERT(!aElem->isInList()); NS_ADDREF(aElem); insertBack(aElem); } - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE already_AddRefed<nsScriptLoadRequest> Steal(nsScriptLoadRequest* aElem) { aElem->removeFrom(*this); return dont_AddRef(aElem); } - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE already_AddRefed<nsScriptLoadRequest> StealFirst() { MOZ_ASSERT(!isEmpty()); return Steal(getFirst()); } }; //////////////////////////////////////////////////////////////
--- a/dom/base/nsTextFragment.h +++ b/dom/base/nsTextFragment.h @@ -130,17 +130,17 @@ public: aString.AllocFailed(aString.Length() + GetLength()); } } /** * Append the contents of this string fragment to aString * @return false if an out of memory condition is detected, true otherwise */ - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE bool AppendTo(nsAString& aString, const mozilla::fallible_t& aFallible) const { if (mState.mIs2b) { bool ok = aString.Append(m2b, mState.mLength, aFallible); if (!ok) { return false; } @@ -164,17 +164,17 @@ public: /** * Append a substring of the contents of this string fragment to aString. * @param aString the string in which to append * @param aOffset where to start the substring in this text fragment * @param aLength the length of the substring * @return false if an out of memory condition is detected, true otherwise */ - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE bool AppendTo(nsAString& aString, int32_t aOffset, int32_t aLength, const mozilla::fallible_t& aFallible) const { if (mState.mIs2b) { bool ok = aString.Append(m2b + aOffset, aLength, aFallible); if (!ok) { return false; }
--- a/dom/base/nsXHTMLContentSerializer.h +++ b/dom/base/nsXHTMLContentSerializer.h @@ -42,17 +42,17 @@ class nsXHTMLContentSerializer : public protected: virtual bool CheckElementStart(nsIContent * aContent, bool & aForceFormat, nsAString& aStr, nsresult& aResult) override; - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE virtual bool AfterElementStart(nsIContent* aContent, nsIContent* aOriginalElement, nsAString& aStr) override; virtual bool CheckElementEnd(mozilla::dom::Element* aContent, bool& aForceFormat, nsAString& aStr) override; @@ -65,35 +65,35 @@ class nsXHTMLContentSerializer : public virtual bool LineBreakAfterClose(int32_t aNamespaceID, nsIAtom* aName) override; bool HasLongLines(const nsString& text, int32_t& aLastNewlineOffset); // functions to check if we enter in or leave from a preformated content virtual void MaybeEnterInPreContent(nsIContent* aNode) override; virtual void MaybeLeaveFromPreContent(nsIContent* aNode) override; - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE virtual bool SerializeAttributes(nsIContent* aContent, nsIContent *aOriginalElement, nsAString& aTagPrefix, const nsAString& aTagNamespaceURI, nsIAtom* aTagName, nsAString& aStr, uint32_t aSkipAttr, bool aAddNSAttr) override; bool IsFirstChildOfOL(nsIContent* aElement); - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE bool SerializeLIValueAttribute(nsIContent* aElement, nsAString& aStr); bool IsShorthandAttr(const nsIAtom* aAttrName, const nsIAtom* aElementName); - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE virtual bool AppendAndTranslateEntities(const nsAString& aStr, nsAString& aOutputStr) override; nsresult EscapeURI(nsIContent* aContent, const nsAString& aURI, nsAString& aEscapedURI); private:
--- a/dom/base/nsXMLContentSerializer.h +++ b/dom/base/nsXMLContentSerializer.h @@ -67,92 +67,92 @@ class nsXMLContentSerializer : public ns nsAString& aStr) override; protected: virtual ~nsXMLContentSerializer(); /** * Appends a char16_t character and increments the column position */ - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE bool AppendToString(const char16_t aChar, nsAString& aOutputStr); /** * Appends a nsAString string and increments the column position */ - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE bool AppendToString(const nsAString& aStr, nsAString& aOutputStr); /** * Appends a string by replacing all line-endings * by mLineBreak, except in the case of raw output. * It increments the column position. */ - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE bool AppendToStringConvertLF(const nsAString& aStr, nsAString& aOutputStr); /** * Appends a string by wrapping it when necessary. * It updates the column position. */ - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE bool AppendToStringWrapped(const nsASingleFragmentString& aStr, nsAString& aOutputStr); /** * Appends a string by formating and wrapping it when necessary * It updates the column position. */ - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE bool AppendToStringFormatedWrapped(const nsASingleFragmentString& aStr, nsAString& aOutputStr); // used by AppendToStringWrapped - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE bool AppendWrapped_WhitespaceSequence( nsASingleFragmentString::const_char_iterator &aPos, const nsASingleFragmentString::const_char_iterator aEnd, const nsASingleFragmentString::const_char_iterator aSequenceStart, nsAString &aOutputStr); // used by AppendToStringFormatedWrapped - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE bool AppendFormatedWrapped_WhitespaceSequence( nsASingleFragmentString::const_char_iterator &aPos, const nsASingleFragmentString::const_char_iterator aEnd, const nsASingleFragmentString::const_char_iterator aSequenceStart, bool &aMayIgnoreStartOfLineWhitespaceSequence, nsAString &aOutputStr); // used by AppendToStringWrapped and AppendToStringFormatedWrapped - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE bool AppendWrapped_NonWhitespaceSequence( nsASingleFragmentString::const_char_iterator &aPos, const nsASingleFragmentString::const_char_iterator aEnd, const nsASingleFragmentString::const_char_iterator aSequenceStart, bool &aMayIgnoreStartOfLineWhitespaceSequence, bool &aSequenceStartAfterAWhiteSpace, nsAString &aOutputStr); /** * add mLineBreak to the string * It updates the column position and other flags. */ - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE bool AppendNewLineToString(nsAString& aOutputStr); /** * Appends a string by translating entities * It doesn't increment the column position */ - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE virtual bool AppendAndTranslateEntities(const nsAString& aStr, nsAString& aOutputStr); /** * retrieve the text content of the node and append it to the given string * It doesn't increment the column position */ nsresult AppendTextData(nsIContent* aNode, @@ -192,27 +192,27 @@ class nsXMLContentSerializer : public ns * GenerateNewPrefix generates a new prefix and writes it to aPrefix */ void GenerateNewPrefix(nsAString& aPrefix); uint32_t ScanNamespaceDeclarations(nsIContent* aContent, nsIContent *aOriginalElement, const nsAString& aTagNamespaceURI); - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE virtual bool SerializeAttributes(nsIContent* aContent, nsIContent *aOriginalElement, nsAString& aTagPrefix, const nsAString& aTagNamespaceURI, nsIAtom* aTagName, nsAString& aStr, uint32_t aSkipAttr, bool aAddNSAttr); - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE bool SerializeAttr(const nsAString& aPrefix, const nsAString& aName, const nsAString& aValue, nsAString& aStr, bool aDoEscapeEntities); bool IsJavaScript(nsIContent * aContent, nsIAtom* aAttrNameAtom, @@ -234,27 +234,27 @@ class nsXMLContentSerializer : public ns /** * This method is responsible for appending the '>' at the end of the start * tag, possibly preceded by '/' and maybe a ' ' before that too. * * aElement and aOriginalElement are the same as the corresponding arguments * to AppendElementStart. */ - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE bool AppendEndOfElementStart(mozilla::dom::Element* aEleemnt, mozilla::dom::Element* aOriginalElement, nsAString& aStr); /** * This method can be redefine to serialize additional things just after * after the serialization ot the start tag. * (called at the end of AppendElementStart) */ - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE virtual bool AfterElementStart(nsIContent* aContent, nsIContent* aOriginalElement, nsAString& aStr) { return true; }; /** * This method can be redefined to check if the element can be serialized. * It is called when the serialization of the end tag is asked * (AppendElementEnd) @@ -293,26 +293,26 @@ class nsXMLContentSerializer : public ns * Returns true if a line break should be inserted after an element close tag */ virtual bool LineBreakAfterClose(int32_t aNamespaceID, nsIAtom* aName); /** * add intendation. Call only in the case of formating and if the current * position is at 0. It updates the column position. */ - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE bool AppendIndentation(nsAString& aStr); - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE bool IncrIndentation(nsIAtom* aName); void DecrIndentation(nsIAtom* aName); // Functions to check for newlines that needs to be added between nodes in // the root of a document. See mAddNewlineForRootNode - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE bool MaybeAddNewlineForRootNode(nsAString& aStr); void MaybeFlagNewlineForRootNode(nsINode* aNode); // Functions to check if we enter in or leave from a preformated content virtual void MaybeEnterInPreContent(nsIContent* aNode); virtual void MaybeLeaveFromPreContent(nsIContent* aNode); bool ShouldMaintainPreLevel() const;
--- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -357,35 +357,16 @@ DOMInterfaces = { 'CSSValueList': { 'nativeType': 'nsDOMCSSValueList' }, 'DataChannel': { 'nativeType': 'nsDOMDataChannel', }, -'DataStore': [{ - 'workers': False -}, { - 'workers': True, - 'nativeType': 'mozilla::dom::workers::WorkerDataStore', - 'implicitJSContext': ['name', 'owner', 'readOnly', 'get', 'remove', - 'clear', 'revisionId', 'getLength', 'sync'] -}], - -'DataStoreCursor': [{ - 'workers': False, - 'wrapperCache': False -}, { - 'workers': True, - 'nativeType': 'mozilla::dom::workers::WorkerDataStoreCursor', - 'wrapperCache': False, - 'implicitJSContext': ['store', 'next', 'close'] -}], - 'DedicatedWorkerGlobalScope': { 'headerFile': 'mozilla/dom/WorkerScope.h', 'workers': True, }, 'DeviceAcceleration': { 'headerFile': 'mozilla/dom/DeviceMotionEvent.h', }, @@ -1607,20 +1588,16 @@ DOMInterfaces = { ], # Rename a few things so we don't have both classes and methods # with the same name 'binaryNames': { 'performance': 'getPerformance', }, }, -'WorkerNavigator': { - 'implicitJSContext': ['getDataStores'], -}, - 'XMLHttpRequest': [ { 'nativeType': 'nsXMLHttpRequest', 'implicitJSContext': [ 'send'], }, { 'workers': True, }],
--- a/dom/bindings/MozMap.h +++ b/dom/bindings/MozMap.h @@ -99,17 +99,17 @@ public: typedef void (* Enumerator)(DataType* aValue, void* aClosure); void EnumerateValues(Enumerator aEnumerator, void *aClosure) { for (auto iter = this->Iter(); !iter.Done(); iter.Next()) { aEnumerator(&iter.Get()->mData, aClosure); } } - MOZ_WARN_UNUSED_RESULT + MOZ_MUST_USE DataType* AddEntry(const nsAString& aKey) { EntryType* ent = this->PutEntry(aKey, fallible); if (!ent) { return nullptr; } return &ent->mData; }
--- a/dom/bindings/ToJSValue.h +++ b/dom/bindings/ToJSValue.h @@ -20,28 +20,28 @@ namespace mozilla { namespace dom { class Promise; // If ToJSValue returns false, it must set an exception on the // JSContext. // Accept strings. -MOZ_WARN_UNUSED_RESULT bool +MOZ_MUST_USE bool ToJSValue(JSContext* aCx, const nsAString& aArgument, JS::MutableHandle<JS::Value> aValue); // Accept booleans. But be careful here: if we just have a function that takes // a boolean argument, then any pointer that doesn't match one of our other // signatures/templates will get treated as a boolean, which is clearly not // desirable. So make this a template that only gets used if the argument type // is actually boolean template<typename T> -MOZ_WARN_UNUSED_RESULT +MOZ_MUST_USE typename EnableIf<IsSame<T, bool>::value, bool>::Type ToJSValue(JSContext* aCx, T aArgument, JS::MutableHandle<JS::Value> aValue) { // Make sure we're called in a compartment MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx)); @@ -119,49 +119,49 @@ ToJSValue(JSContext* aCx, // Make sure we're called in a compartment MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx)); aValue.setNumber(aArgument); return true; } // Accept CallbackObjects -MOZ_WARN_UNUSED_RESULT inline bool +MOZ_MUST_USE inline bool ToJSValue(JSContext* aCx, CallbackObject& aArgument, JS::MutableHandle<JS::Value> aValue) { // Make sure we're called in a compartment MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx)); aValue.setObject(*aArgument.Callback()); return MaybeWrapValue(aCx, aValue); } // Accept objects that inherit from nsWrapperCache (e.g. most // DOM objects). template <class T> -MOZ_WARN_UNUSED_RESULT +MOZ_MUST_USE typename EnableIf<IsBaseOf<nsWrapperCache, T>::value, bool>::Type ToJSValue(JSContext* aCx, T& aArgument, JS::MutableHandle<JS::Value> aValue) { // Make sure we're called in a compartment MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx)); // Make sure non-webidl objects don't sneak in here MOZ_ASSERT(aArgument.IsDOMBinding()); return GetOrCreateDOMReflector(aCx, aArgument, aValue); } // Accept typed arrays built from appropriate nsTArray values template<typename T> -MOZ_WARN_UNUSED_RESULT +MOZ_MUST_USE typename EnableIf<IsBaseOf<AllTypedArraysBase, T>::value, bool>::Type ToJSValue(JSContext* aCx, const TypedArrayCreator<T>& aArgument, JS::MutableHandle<JS::Value> aValue) { // Make sure we're called in a compartment MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx)); @@ -171,17 +171,17 @@ ToJSValue(JSContext* aCx, } aValue.setObject(*obj); return true; } // Accept objects that inherit from nsISupports but not nsWrapperCache (e.g. // DOM File). template <class T> -MOZ_WARN_UNUSED_RESULT +MOZ_MUST_USE typename EnableIf<!IsBaseOf<nsWrapperCache, T>::value && !IsBaseOf<CallbackObject, T>::value && IsBaseOf<nsISupports, T>::value, bool>::Type ToJSValue(JSContext* aCx, T& aArgument, JS::MutableHandle<JS::Value> aValue) { // Make sure we're called in a compartment @@ -189,139 +189,139 @@ ToJSValue(JSContext* aCx, qsObjectHelper helper(ToSupports(&aArgument), nullptr); JS::Rooted<JSObject*> scope(aCx, JS::CurrentGlobalOrNull(aCx)); return XPCOMObjectToJsval(aCx, scope, helper, nullptr, true, aValue); } // Accept nsRefPtr/nsCOMPtr template <typename T> -MOZ_WARN_UNUSED_RESULT bool +MOZ_MUST_USE bool ToJSValue(JSContext* aCx, const nsCOMPtr<T>& aArgument, JS::MutableHandle<JS::Value> aValue) { return ToJSValue(aCx, *aArgument.get(), aValue); } template <typename T> -MOZ_WARN_UNUSED_RESULT bool +MOZ_MUST_USE bool ToJSValue(JSContext* aCx, const RefPtr<T>& aArgument, JS::MutableHandle<JS::Value> aValue) { return ToJSValue(aCx, *aArgument.get(), aValue); } template <typename T> -MOZ_WARN_UNUSED_RESULT bool +MOZ_MUST_USE bool ToJSValue(JSContext* aCx, const NonNull<T>& aArgument, JS::MutableHandle<JS::Value> aValue) { return ToJSValue(aCx, *aArgument.get(), aValue); } // Accept WebIDL dictionaries template <class T> -MOZ_WARN_UNUSED_RESULT +MOZ_MUST_USE typename EnableIf<IsBaseOf<DictionaryBase, T>::value, bool>::Type ToJSValue(JSContext* aCx, const T& aArgument, JS::MutableHandle<JS::Value> aValue) { return aArgument.ToObjectInternal(aCx, aValue); } // Accept existing JS values (which may not be same-compartment with us -MOZ_WARN_UNUSED_RESULT inline bool +MOZ_MUST_USE inline bool ToJSValue(JSContext* aCx, JS::Handle<JS::Value> aArgument, JS::MutableHandle<JS::Value> aValue) { aValue.set(aArgument); return MaybeWrapValue(aCx, aValue); } // Accept existing JS values on the Heap (which may not be same-compartment with us -MOZ_WARN_UNUSED_RESULT inline bool +MOZ_MUST_USE inline bool ToJSValue(JSContext* aCx, const JS::Heap<JS::Value>& aArgument, JS::MutableHandle<JS::Value> aValue) { aValue.set(aArgument); return MaybeWrapValue(aCx, aValue); } // Accept existing rooted JS values (which may not be same-compartment with us -MOZ_WARN_UNUSED_RESULT inline bool +MOZ_MUST_USE inline bool ToJSValue(JSContext* aCx, const JS::Rooted<JS::Value>& aArgument, JS::MutableHandle<JS::Value> aValue) { aValue.set(aArgument); return MaybeWrapValue(aCx, aValue); } // Accept existing rooted JS objects (which may not be same-compartment with // us). -MOZ_WARN_UNUSED_RESULT inline bool +MOZ_MUST_USE inline bool ToJSValue(JSContext* aCx, const JS::Rooted<JSObject*>& aArgument, JS::MutableHandle<JS::Value> aValue) { aValue.setObjectOrNull(aArgument); return MaybeWrapObjectOrNullValue(aCx, aValue); } // Accept nsresult, for use in rejections, and create an XPCOM // exception object representing that nsresult. -MOZ_WARN_UNUSED_RESULT bool +MOZ_MUST_USE bool ToJSValue(JSContext* aCx, nsresult aArgument, JS::MutableHandle<JS::Value> aValue); // Accept ErrorResult, for use in rejections, and create an exception // representing the failure. Note, the ErrorResult must indicate a failure // with aArgument.Failure() returning true. -MOZ_WARN_UNUSED_RESULT bool +MOZ_MUST_USE bool ToJSValue(JSContext* aCx, ErrorResult& aArgument, JS::MutableHandle<JS::Value> aValue); // Accept owning WebIDL unions. template <typename T> -MOZ_WARN_UNUSED_RESULT +MOZ_MUST_USE typename EnableIf<IsBaseOf<AllOwningUnionBase, T>::value, bool>::Type ToJSValue(JSContext* aCx, const T& aArgument, JS::MutableHandle<JS::Value> aValue) { JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx)); return aArgument.ToJSVal(aCx, global, aValue); } // Accept pointers to other things we accept template <typename T> -MOZ_WARN_UNUSED_RESULT +MOZ_MUST_USE typename EnableIf<IsPointer<T>::value, bool>::Type ToJSValue(JSContext* aCx, T aArgument, JS::MutableHandle<JS::Value> aValue) { return ToJSValue(aCx, *aArgument, aValue); } #ifdef SPIDERMONKEY_PROMISE // Accept Promise objects, which need special handling. -MOZ_WARN_UNUSED_RESULT bool +MOZ_MUST_USE bool ToJSValue(JSContext* aCx, Promise& aArgument, JS::MutableHandle<JS::Value> aValue); #endif // SPIDERMONKEY_PROMISE // Accept arrays of other things we accept template <typename T> -MOZ_WARN_UNUSED_RESULT bool +MOZ_MUST_USE bool ToJSValue(JSContext* aCx, T* aArguments, size_t aLength, JS::MutableHandle<JS::Value> aValue) { // Make sure we're called in a compartment MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx)); @@ -338,37 +338,37 @@ ToJSValue(JSContext* aCx, if (!arrayObj) { return false; } aValue.setObject(*arrayObj); return true; } template <typename T> -MOZ_WARN_UNUSED_RESULT bool +MOZ_MUST_USE bool ToJSValue(JSContext* aCx, const nsTArray<T>& aArgument, JS::MutableHandle<JS::Value> aValue) { return ToJSValue(aCx, aArgument.Elements(), aArgument.Length(), aValue); } template <typename T> -MOZ_WARN_UNUSED_RESULT bool +MOZ_MUST_USE bool ToJSValue(JSContext* aCx, const FallibleTArray<T>& aArgument, JS::MutableHandle<JS::Value> aValue) { return ToJSValue(aCx, aArgument.Elements(), aArgument.Length(), aValue); } template <typename T, int N> -MOZ_WARN_UNUSED_RESULT bool +MOZ_MUST_USE bool ToJSValue(JSContext* aCx, const T(&aArgument)[N], JS::MutableHandle<JS::Value> aValue) { return ToJSValue(aCx, aArgument, N, aValue); } } // namespace dom
--- a/dom/canvas/ImageBitmap.cpp +++ b/dom/canvas/ImageBitmap.cpp @@ -466,56 +466,51 @@ ImageBitmap::PrepareForDrawTarget(gfx::D target->GetFormat()); if (!target) { mSurface = nullptr; RefPtr<gfx::SourceSurface> surface(mSurface); return surface.forget(); } - // We need to fall back to generic copying and cropping for the Windows8.1, - // D2D1 backend. - // In the Windows8.1 D2D1 backend, it might trigger "partial upload" from a - // non-SourceSurfaceD2D1 surface to a D2D1Image in the following - // CopySurface() step. However, the "partial upload" only supports uploading - // a rectangle starts from the upper-left point, which means it cannot - // upload an arbitrary part of the source surface and this causes problems - // if the mPictureRect is not starts from the upper-left point. - if (target->GetBackendType() == BackendType::DIRECT2D1_1 && - mSurface->GetType() != SurfaceType::D2D1_1_IMAGE) { - RefPtr<DataSourceSurface> dataSurface = mSurface->GetDataSurface(); - if (NS_WARN_IF(!dataSurface)) { - mSurface = nullptr; - RefPtr<gfx::SourceSurface> surface(mSurface); - return surface.forget(); - } - - mSurface = CropAndCopyDataSourceSurface(dataSurface, mPictureRect); - } else { - target->CopySurface(mSurface, surfPortion, dest); - mSurface = target->Snapshot(); - } + target->CopySurface(mSurface, surfPortion, dest); + mSurface = target->Snapshot(); // Make mCropRect match new surface we've cropped to mPictureRect.MoveTo(0, 0); } // Pre-multiply alpha here. // Apply pre-multiply alpha only if mIsPremultipliedAlpha is false. if (!mIsPremultipliedAlpha) { MOZ_ASSERT(mSurface->GetFormat() == SurfaceFormat::R8G8B8A8 || mSurface->GetFormat() == SurfaceFormat::B8G8R8A8 || mSurface->GetFormat() == SurfaceFormat::A8R8G8B8); - RefPtr<DataSourceSurface> dataSourceSurface = mSurface->GetDataSurface(); - MOZ_ASSERT(dataSourceSurface); + RefPtr<DataSourceSurface> dstSurface = mSurface->GetDataSurface(); + MOZ_ASSERT(dstSurface); + + RefPtr<DataSourceSurface> srcSurface; + DataSourceSurface::MappedSurface srcMap; + DataSourceSurface::MappedSurface dstMap; - DataSourceSurface::ScopedMap map(dataSourceSurface, DataSourceSurface::READ_WRITE); - if (NS_WARN_IF(!map.IsMapped())) { - return nullptr; + if (!dstSurface->Map(DataSourceSurface::MapType::READ_WRITE, &dstMap)) { + srcSurface = dstSurface; + if (!srcSurface->Map(DataSourceSurface::READ, &srcMap)) { + gfxCriticalError() << "Failed to map source surface for premultiplying alpha."; + return nullptr; + } + + dstSurface = Factory::CreateDataSourceSurface(srcSurface->GetSize(), srcSurface->GetFormat()); + + if (!dstSurface || !dstSurface->Map(DataSourceSurface::MapType::WRITE, &dstMap)) { + gfxCriticalError() << "Failed to map destination surface for premultiplying alpha."; + srcSurface->Unmap(); + return nullptr; + } } uint8_t rIndex = 0; uint8_t gIndex = 0; uint8_t bIndex = 0; uint8_t aIndex = 0; if (mSurface->GetFormat() == SurfaceFormat::R8G8B8A8) { @@ -530,34 +525,41 @@ ImageBitmap::PrepareForDrawTarget(gfx::D aIndex = 3; } else if (mSurface->GetFormat() == SurfaceFormat::A8R8G8B8) { rIndex = 1; gIndex = 2; bIndex = 3; aIndex = 0; } - for (int i = 0; i < dataSourceSurface->GetSize().height; ++i) { - uint8_t* bufferPtr = map.GetData() + map.GetStride() * i; - for (int i = 0; i < dataSourceSurface->GetSize().width; ++i) { - uint8_t r = *(bufferPtr+rIndex); - uint8_t g = *(bufferPtr+gIndex); - uint8_t b = *(bufferPtr+bIndex); - uint8_t a = *(bufferPtr+aIndex); + for (int i = 0; i < dstSurface->GetSize().height; ++i) { + uint8_t* bufferPtr = dstMap.mData + dstMap.mStride * i; + uint8_t* srcBufferPtr = srcSurface ? srcMap.mData + srcMap.mStride * i : bufferPtr; + for (int i = 0; i < dstSurface->GetSize().width; ++i) { + uint8_t r = *(srcBufferPtr+rIndex); + uint8_t g = *(srcBufferPtr+gIndex); + uint8_t b = *(srcBufferPtr+bIndex); + uint8_t a = *(srcBufferPtr+aIndex); *(bufferPtr+rIndex) = gfxUtils::sPremultiplyTable[a * 256 + r]; *(bufferPtr+gIndex) = gfxUtils::sPremultiplyTable[a * 256 + g]; *(bufferPtr+bIndex) = gfxUtils::sPremultiplyTable[a * 256 + b]; *(bufferPtr+aIndex) = a; bufferPtr += 4; + srcBufferPtr += 4; } } - mSurface = dataSourceSurface; + dstSurface->Unmap(); + if (srcSurface) { + srcSurface->Unmap(); + } + + mSurface = dstSurface; } // Replace our surface with one optimized for the target we're about to draw // to, under the assumption it'll likely be drawn again to that target. // This call should be a no-op for already-optimized surfaces mSurface = target->OptimizeSourceSurface(mSurface); RefPtr<gfx::SourceSurface> surface(mSurface); @@ -878,17 +880,17 @@ ImageBitmap::CreateInternal(nsIGlobalObj const Maybe<IntRect>& aCropRect, ErrorResult& aRv) { if (!aImageBitmap.mData) { aRv.Throw(NS_ERROR_NOT_AVAILABLE); return nullptr; } RefPtr<layers::Image> data = aImageBitmap.mData; - RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data); + RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, aImageBitmap.mIsPremultipliedAlpha); // Set the picture rectangle. if (ret && aCropRect.isSome()) { ret->SetPictureRect(aCropRect.ref(), aRv); } return ret.forget(); }
--- a/dom/canvas/WebGLProgram.cpp +++ b/dom/canvas/WebGLProgram.cpp @@ -950,17 +950,29 @@ WebGLProgram::LinkProgram() // This can't be done trivially, because we have to deal with mapped names too. mVertShader->ApplyTransformFeedbackVaryings(mGLName, mTransformFeedbackVaryings, mTransformFeedbackBufferMode, &mTempMappedVaryings); } LinkAndUpdate(); - if (IsLinked()) + if (IsLinked()) { + // Check if the attrib name conflicting to uniform name + for (const auto& uniform : mMostRecentLinkInfo->uniformMap) { + if (mMostRecentLinkInfo->attribMap.find(uniform.first) != mMostRecentLinkInfo->attribMap.end()) { + mLinkLog = nsPrintfCString("The uniform name (%s) conflicts with attribute name.", + uniform.first.get()); + mMostRecentLinkInfo = nullptr; + break; + } + } + } + + if (mMostRecentLinkInfo) return; // Failed link. if (mContext->ShouldGenerateWarnings()) { // report shader/program infoLogs as warnings. // note that shader compilation errors can be deferred to linkProgram, // which is why we can't do anything in compileShader. In practice we could // report in compileShader the translation errors generated by ANGLE,
--- a/dom/canvas/test/reftest/reftest.list +++ b/dom/canvas/test/reftest/reftest.list @@ -153,12 +153,12 @@ skip-if(!winWidget) pref(webgl.disable-a # focus rings pref(canvas.focusring.enabled,true) skip-if(B2G) skip-if(cocoaWidget) skip-if(winWidget) needs-focus == drawFocusIfNeeded.html drawFocusIfNeeded-ref.html pref(canvas.customfocusring.enabled,true) skip-if(B2G) skip-if(cocoaWidget) skip-if(Android) skip-if(winWidget) fuzzy-if(gtkWidget,64,410) needs-focus == drawCustomFocusRing.html drawCustomFocusRing-ref.html # Check that captureStream() displays in a local video element == capturestream.html wrapper.html?green.png -fuzzy-if(azureSkiaGL,1,2) fuzzy-if(Android,3,40) fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),1,1) == 1177726-text-stroke-bounds.html 1177726-text-stroke-bounds-ref.html +fuzzy-if(azureSkia,16,2) fuzzy-if(Android,3,40) fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),1,1) == 1177726-text-stroke-bounds.html 1177726-text-stroke-bounds-ref.html # Canvas Filter Reftests include filters/reftest.list
--- a/dom/canvas/test/test_canvas.html +++ b/dom/canvas/test/test_canvas.html @@ -14305,21 +14305,17 @@ ctx.lineCap = 'round'; ctx.lineJoin = 'round'; ctx.beginPath(); ctx.moveTo(50, 25); ctx.lineTo(50, 25); ctx.closePath(); ctx.stroke(); -if (IsAzureSkia()) { - isPixel(ctx, 50,25, 0,255,0,255, 0); -} else { - todo_isPixel(ctx, 50,25, 0,255,0,255, 0); -} +todo_isPixel(ctx, 50,25, 0,255,0,255, 0); } </script> <!-- [[[ test_2d.path.stroke.prune.corner.html ]]] --> <p>Canvas test: 2d.path.stroke.prune.corner</p> <!-- Testing: Zero-length line segments are removed before stroking with miters --> @@ -14446,21 +14442,17 @@ ctx.lineCap = 'round'; ctx.lineJoin = 'round'; ctx.beginPath(); ctx.rect(50, 25, 0, 0); ctx.stroke(); ctx.strokeRect(50, 25, 0, 0); -if (IsAzureSkia()) { - isPixel(ctx, 50,25, 0,255,0,255, 0); -} else { - todo_isPixel(ctx, 50,25, 0,255,0,255, 0); -} +todo_isPixel(ctx, 50,25, 0,255,0,255, 0); } </script> <!-- [[[ test_2d.path.stroke.scale1.html ]]] --> <p>Canvas test: 2d.path.stroke.scale1</p> <!-- Testing: Stroke line widths are scaled by the current transformation matrix -->
--- a/dom/canvas/test/webgl-conf/generated-mochitest.ini +++ b/dom/canvas/test/webgl-conf/generated-mochitest.ini @@ -2738,17 +2738,16 @@ fail-if = (os == 'android') [generated/test_conformance__glsl__misc__shader-without-precision.frag.html] [generated/test_conformance__glsl__misc__shaders-with-constant-expression-loop-conditions.html] [generated/test_conformance__glsl__misc__shaders-with-invariance.html] fail-if = 1 [generated/test_conformance__glsl__misc__shaders-with-mis-matching-uniforms.html] [generated/test_conformance__glsl__misc__shaders-with-mis-matching-varyings.html] [generated/test_conformance__glsl__misc__shaders-with-missing-varyings.html] [generated/test_conformance__glsl__misc__shaders-with-name-conflicts.html] -fail-if = 1 [generated/test_conformance__glsl__misc__shaders-with-uniform-structs.html] [generated/test_conformance__glsl__misc__shaders-with-varyings.html] [generated/test_conformance__glsl__misc__shared.html] [generated/test_conformance__glsl__misc__struct-equals.html] [generated/test_conformance__glsl__misc__struct-mixed-array-declarators.html] [generated/test_conformance__glsl__misc__struct-nesting-exceeds-maximum.html] [generated/test_conformance__glsl__misc__struct-nesting-of-variable-names.html] fail-if = (os == 'mac' && os_version == '10.10')
--- a/dom/canvas/test/webgl-conf/mochitest-errata.ini +++ b/dom/canvas/test/webgl-conf/mochitest-errata.ini @@ -32,17 +32,16 @@ skip-if = os == 'b2g' || ((os == 'linux' [generated/test_..__always-fail.html] fail-if = 1 [generated/test_conformance__context__context-lost.html] fail-if = 1 [generated/test_conformance__glsl__misc__shaders-with-invariance.html] fail-if = 1 [generated/test_conformance__glsl__misc__shaders-with-name-conflicts.html] -fail-if = 1 [generated/test_conformance__renderbuffers__feedback-loop.html] fail-if = 1 [generated/test_conformance__textures__texture-copying-feedback-loops.html] fail-if = 1 #################### # Tests requesting non-local network connections.
deleted file mode 100644 --- a/dom/datastore/DataStore.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/dom/DataStore.h" -#include "mozilla/dom/DataStoreCursor.h" -#include "mozilla/dom/DataStoreBinding.h" -#include "mozilla/dom/DataStoreImplBinding.h" -#include "mozilla/dom/Navigator.h" -#include "mozilla/dom/Promise.h" -#include "mozilla/ErrorResult.h" -#include "mozilla/Preferences.h" -#include "AccessCheck.h" -#include "nsContentUtils.h" - -namespace mozilla { -namespace dom { - -NS_IMPL_ADDREF_INHERITED(DataStore, DOMEventTargetHelper) -NS_IMPL_RELEASE_INHERITED(DataStore, DOMEventTargetHelper) - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DataStore) - NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) - -NS_IMPL_CYCLE_COLLECTION_INHERITED(DataStore, DOMEventTargetHelper, mStore) - -DataStore::DataStore(nsPIDOMWindowInner* aWindow) - : DOMEventTargetHelper(aWindow) -{ -} - -DataStore::~DataStore() -{ -} - -already_AddRefed<DataStore> -DataStore::Constructor(GlobalObject& aGlobal, ErrorResult& aRv) -{ - nsCOMPtr<nsPIDOMWindowInner> window = - do_QueryInterface(aGlobal.GetAsSupports()); - if (!window) { - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - - RefPtr<DataStore> store = new DataStore(window); - return store.forget(); -} - -JSObject* -DataStore::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) -{ - return DataStoreBinding::Wrap(aCx, this, aGivenProto); -} - -/*static*/ bool -DataStore::EnabledForScope(JSContext* aCx, JS::Handle<JSObject*> aObj) -{ - // Only expose the interface when it is: - // 1. enabled by the preference and - // 2. accessed by the chrome codes in Gecko. - return (Navigator::HasDataStoreSupport(aCx, aObj) && - nsContentUtils::ThreadsafeIsCallerChrome()); -} - -void -DataStore::GetName(nsAString& aName, ErrorResult& aRv) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mStore); - - nsAutoString name; - mStore->GetName(name, aRv); - aName.Assign(name); -} - -void -DataStore::GetOwner(nsAString& aOwner, ErrorResult& aRv) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mStore); - - nsAutoString owner; - mStore->GetOwner(owner, aRv); - aOwner.Assign(owner); -} - -bool -DataStore::GetReadOnly(ErrorResult& aRv) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mStore); - - return mStore->GetReadOnly(aRv); -} - -already_AddRefed<Promise> -DataStore::Get(const Sequence<OwningStringOrUnsignedLong>& aId, - ErrorResult& aRv) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mStore); - - return mStore->Get(aId, aRv); -} - -already_AddRefed<Promise> -DataStore::Put(JSContext* aCx, - JS::Handle<JS::Value> aObj, - const StringOrUnsignedLong& aId, - const nsAString& aRevisionId, - ErrorResult& aRv) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mStore); - - return mStore->Put(aObj, aId, aRevisionId, aRv); -} - -already_AddRefed<Promise> -DataStore::Add(JSContext* aCx, - JS::Handle<JS::Value> aObj, - const Optional<StringOrUnsignedLong>& aId, - const nsAString& aRevisionId, - ErrorResult& aRv) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mStore); - - return mStore->Add(aObj, aId, aRevisionId, aRv); -} - -already_AddRefed<Promise> -DataStore::Remove(const StringOrUnsignedLong& aId, - const nsAString& aRevisionId, - ErrorResult& aRv) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mStore); - - return mStore->Remove(aId, aRevisionId, aRv); -} - -already_AddRefed<Promise> -DataStore::Clear(const nsAString& aRevisionId, ErrorResult& aRv) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mStore); - - return mStore->Clear(aRevisionId, aRv); -} - -void -DataStore::GetRevisionId(nsAString& aRevisionId, ErrorResult& aRv) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mStore); - - nsAutoString revisionId; - mStore->GetRevisionId(revisionId, aRv); - aRevisionId.Assign(revisionId); -} - -already_AddRefed<Promise> -DataStore::GetLength(ErrorResult& aRv) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mStore); - - return mStore->GetLength(aRv); -} - -already_AddRefed<DataStoreCursor> -DataStore::Sync(const nsAString& aRevisionId, ErrorResult& aRv) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mStore); - - return mStore->Sync(aRevisionId, aRv); -} - -void -DataStore::SetDataStoreImpl(DataStoreImpl& aStore, ErrorResult& aRv) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(!mStore); - - mStore = &aStore; - mStore->SetEventTarget(*this, aRv); -} - -} //namespace dom -} //namespace mozilla
deleted file mode 100644 --- a/dom/datastore/DataStore.h +++ /dev/null @@ -1,96 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_DataStore_h -#define mozilla_dom_DataStore_h - -#include "mozilla/DOMEventTargetHelper.h" - -namespace mozilla { - -class ErrorResult; - -namespace dom { - -class Promise; -class DataStoreCursor; -class DataStoreImpl; -class StringOrUnsignedLong; -class OwningStringOrUnsignedLong; - -class DataStore final : public DOMEventTargetHelper -{ -public: - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DataStore, - DOMEventTargetHelper) - - explicit DataStore(nsPIDOMWindowInner* aWindow); - - // WebIDL (internal functions) - - static already_AddRefed<DataStore> Constructor(GlobalObject& aGlobal, - ErrorResult& aRv); - - virtual JSObject* WrapObject(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override; - - static bool EnabledForScope(JSContext* aCx, JS::Handle<JSObject*> aObj); - - // WebIDL (public APIs) - - void GetName(nsAString& aName, ErrorResult& aRv); - - void GetOwner(nsAString& aOwner, ErrorResult& aRv); - - bool GetReadOnly(ErrorResult& aRv); - - already_AddRefed<Promise> Get(const Sequence<OwningStringOrUnsignedLong>& aId, - ErrorResult& aRv); - - already_AddRefed<Promise> Put(JSContext* aCx, - JS::Handle<JS::Value> aObj, - const StringOrUnsignedLong& aId, - const nsAString& aRevisionId, - ErrorResult& aRv); - - already_AddRefed<Promise> Add(JSContext* aCx, - JS::Handle<JS::Value> aObj, - const Optional<StringOrUnsignedLong>& aId, - const nsAString& aRevisionId, - ErrorResult& aRv); - - already_AddRefed<Promise> Remove(const StringOrUnsignedLong& aId, - const nsAString& aRevisionId, - ErrorResult& aRv); - - already_AddRefed<Promise> Clear(const nsAString& aRevisionId, - ErrorResult& aRv); - - void GetRevisionId(nsAString& aRevisionId, ErrorResult& aRv); - - already_AddRefed<Promise> GetLength(ErrorResult& aRv); - - already_AddRefed<DataStoreCursor> Sync(const nsAString& aRevisionId, - ErrorResult& aRv); - - IMPL_EVENT_HANDLER(change) - - // This internal function (ChromeOnly) is aimed to make the DataStore keep a - // reference to the DataStoreImpl which really implements the API's logic in - // JS. We also need to let the DataStoreImpl implementation keep the event - // target of DataStore, so that it can know where to fire the events. - void SetDataStoreImpl(DataStoreImpl& aStore, ErrorResult& aRv); - -private: - ~DataStore(); - - RefPtr<DataStoreImpl> mStore; -}; - -} //namespace dom -} //namespace mozilla - -#endif
deleted file mode 100644 --- a/dom/datastore/DataStore.manifest +++ /dev/null @@ -1,2 +0,0 @@ -component {db5c9602-030f-4bff-a3de-881a8de370f2} DataStoreImpl.js -contract @mozilla.org/dom/datastore;1 {db5c9602-030f-4bff-a3de-881a8de370f2}
deleted file mode 100644 --- a/dom/datastore/DataStoreCallbacks.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_DataStoreCallbacks_h -#define mozilla_dom_DataStoreCallbacks_h - -#include "nsISupports.h" - -namespace mozilla { -namespace dom { - -class DataStoreDB; - -class DataStoreDBCallback -{ -public: - NS_IMETHOD_(MozExternalRefCountType) AddRef(void) = 0; - NS_IMETHOD_(MozExternalRefCountType) Release(void) = 0; - - enum RunStatus { - Success, - CreatedSchema, - Error - }; - - virtual void Run(DataStoreDB* aDb, RunStatus aStatus) = 0; - -protected: - virtual ~DataStoreDBCallback() - { - } -}; - -class DataStoreRevisionCallback -{ -public: - NS_IMETHOD_(MozExternalRefCountType) AddRef(void) = 0; - NS_IMETHOD_(MozExternalRefCountType) Release(void) = 0; - - virtual void Run(const nsAString& aRevisionID) = 0; - -protected: - virtual ~DataStoreRevisionCallback() - { - } -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_DataStoreCallbacks_h
deleted file mode 100644 --- a/dom/datastore/DataStoreChangeNotifier.jsm +++ /dev/null @@ -1,223 +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" - -const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; - -this.EXPORTED_SYMBOLS = ["DataStoreChangeNotifier"]; - -function debug(s) { - //dump('DEBUG DataStoreChangeNotifier: ' + s + '\n'); -} - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); - -XPCOMUtils.defineLazyServiceGetter(this, "ppmm", - "@mozilla.org/parentprocessmessagemanager;1", - "nsIMessageBroadcaster"); - -XPCOMUtils.defineLazyServiceGetter(this, "dataStoreService", - "@mozilla.org/datastore-service;1", - "nsIDataStoreService"); - -XPCOMUtils.defineLazyServiceGetter(this, "systemMessenger", - "@mozilla.org/system-message-internal;1", - "nsISystemMessagesInternal"); - -var kSysMsgOnChangeShortTimeoutSec = - Services.prefs.getIntPref("dom.datastore.sysMsgOnChangeShortTimeoutSec"); -var kSysMsgOnChangeLongTimeoutSec = - Services.prefs.getIntPref("dom.datastore.sysMsgOnChangeLongTimeoutSec"); - -this.DataStoreChangeNotifier = { - children: [], - messages: [ "DataStore:Changed", "DataStore:RegisterForMessages", - "DataStore:UnregisterForMessages", - "child-process-shutdown" ], - - // These hashes are used for storing the mapping between the datastore - // identifiers (name | owner manifest URL) and their correspondent timers. - // The object literal is defined as below: - // - // { - // "datastore name 1|owner manifest URL 1": timer1, - // "datastore name 2|owner manifest URL 2": timer2, - // ... - // } - sysMsgOnChangeShortTimers: {}, - sysMsgOnChangeLongTimers: {}, - - init: function() { - debug("init"); - - this.messages.forEach((function(msgName) { - ppmm.addMessageListener(msgName, this); - }).bind(this)); - - Services.obs.addObserver(this, 'xpcom-shutdown', false); - }, - - observe: function(aSubject, aTopic, aData) { - debug("observe"); - - switch (aTopic) { - case 'xpcom-shutdown': - this.messages.forEach((function(msgName) { - ppmm.removeMessageListener(msgName, this); - }).bind(this)); - - Services.obs.removeObserver(this, 'xpcom-shutdown'); - ppmm = null; - break; - - default: - debug("Wrong observer topic: " + aTopic); - break; - } - }, - - broadcastMessage: function broadcastMessage(aData) { - debug("broadcast"); - - this.children.forEach(function(obj) { - if (obj.store == aData.store && obj.owner == aData.owner) { - obj.mm.sendAsyncMessage("DataStore:Changed:Return:OK", aData); - } - }); - }, - - broadcastSystemMessage: function(aStore, aOwner) { - debug("broadcastSystemMessage"); - - // Clear relevant timers. - var storeKey = aStore + "|" + aOwner; - var shortTimer = this.sysMsgOnChangeShortTimers[storeKey]; - if (shortTimer) { - shortTimer.cancel(); - delete this.sysMsgOnChangeShortTimers[storeKey]; - } - var longTimer = this.sysMsgOnChangeLongTimers[storeKey]; - if (longTimer) { - longTimer.cancel(); - delete this.sysMsgOnChangeLongTimers[storeKey]; - } - - systemMessenger.broadcastMessage("datastore-update-" + aStore, - { owner: aOwner }); - }, - - // Use the following logic to broadcast system messages in a moderate pattern. - // 1. When an entry is changed, start a short timer and a long timer. - // 2. If an entry is changed while the short timer is running, reset it. - // Do not reset the long timer. - // 3. Once either fires, broadcast the system message and cancel both timers. - setSystemMessageTimeout: function(aStore, aOwner) { - debug("setSystemMessageTimeout"); - - var storeKey = aStore + "|" + aOwner; - - // Reset the short timer. - var shortTimer = this.sysMsgOnChangeShortTimers[storeKey]; - if (!shortTimer) { - shortTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); - this.sysMsgOnChangeShortTimers[storeKey] = shortTimer; - } else { - shortTimer.cancel(); - } - shortTimer.initWithCallback({ notify: this.broadcastSystemMessage.bind(this, aStore, aOwner) }, - kSysMsgOnChangeShortTimeoutSec * 1000, - Ci.nsITimer.TYPE_ONE_SHOT); - - // Set the long timer if necessary. - if (!this.sysMsgOnChangeLongTimers[storeKey]) { - var longTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); - this.sysMsgOnChangeLongTimers[storeKey] = longTimer; - longTimer.initWithCallback({ notify: this.broadcastSystemMessage.bind(this, aStore, aOwner) }, - kSysMsgOnChangeLongTimeoutSec * 1000, - Ci.nsITimer.TYPE_ONE_SHOT); - } - }, - - receiveMessage: function(aMessage) { - debug("receiveMessage "); - - // No check has to be done when the message is 'child-process-shutdown'. - if (aMessage.name != "child-process-shutdown") { - let principal = aMessage.principal; - if (!principal || !dataStoreService.checkPermission(principal)) { - return; - } - } - - switch (aMessage.name) { - case "DataStore:Changed": - this.broadcastMessage(aMessage.data); - if (Services.prefs.getBoolPref("dom.sysmsg.enabled")) { - this.setSystemMessageTimeout(aMessage.data.store, aMessage.data.owner); - } - break; - - case "DataStore:RegisterForMessages": - debug("Register!"); - - for (let i = 0; i < this.children.length; ++i) { - if (this.children[i].mm == aMessage.target && - this.children[i].store == aMessage.data.store && - this.children[i].owner == aMessage.data.owner) { - debug("Register on existing index: " + i); - this.children[i].windows.push(aMessage.data.innerWindowID); - return; - } - } - - this.children.push({ mm: aMessage.target, - store: aMessage.data.store, - owner: aMessage.data.owner, - windows: [ aMessage.data.innerWindowID ]}); - break; - - case "DataStore:UnregisterForMessages": - debug("Unregister"); - - for (let i = 0; i < this.children.length; ++i) { - if (this.children[i].mm == aMessage.target) { - debug("Unregister index: " + i); - - var pos = this.children[i].windows.indexOf(aMessage.data.innerWindowID); - if (pos != -1) { - this.children[i].windows.splice(pos, 1); - } - - if (this.children[i].windows.length) { - continue; - } - - debug("Unregister delete index: " + i); - this.children.splice(i, 1); - --i; - } - } - break; - - case "child-process-shutdown": - debug("Child process shutdown"); - - for (let i = 0; i < this.children.length; ++i) { - if (this.children[i].mm == aMessage.target) { - debug("Unregister index: " + i); - this.children.splice(i, 1); - --i; - } - } - break; - - default: - debug("Wrong message: " + aMessage.name); - } - } -} - -DataStoreChangeNotifier.init();
deleted file mode 100644 --- a/dom/datastore/DataStoreCursor.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/dom/DataStore.h" -#include "mozilla/dom/DataStoreCursor.h" -#include "mozilla/dom/DataStoreBinding.h" -#include "mozilla/dom/DataStoreImplBinding.h" -#include "mozilla/dom/Promise.h" -#include "mozilla/ErrorResult.h" -#include "nsPIDOMWindow.h" - -namespace mozilla { -namespace dom { - -NS_IMPL_CYCLE_COLLECTING_ADDREF(DataStoreCursor) -NS_IMPL_CYCLE_COLLECTING_RELEASE(DataStoreCursor) - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DataStoreCursor) - NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END - -NS_IMPL_CYCLE_COLLECTION(DataStoreCursor, mCursor) - -already_AddRefed<DataStoreCursor> -DataStoreCursor::Constructor(GlobalObject& aGlobal, ErrorResult& aRv) -{ - RefPtr<DataStoreCursor> cursor = new DataStoreCursor(); - return cursor.forget(); -} - -bool -DataStoreCursor::WrapObject(JSContext* aCx, - JS::Handle<JSObject*> aGivenProto, - JS::MutableHandle<JSObject*> aReflector) -{ - return DataStoreCursorBinding::Wrap(aCx, this, aGivenProto, aReflector); -} - -already_AddRefed<DataStore> -DataStoreCursor::GetStore(ErrorResult& aRv) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mCursor); - - return mCursor->GetStore(aRv); -} - -already_AddRefed<Promise> -DataStoreCursor::Next(ErrorResult& aRv) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mCursor); - - return mCursor->Next(aRv); -} - -void -DataStoreCursor::Close(ErrorResult& aRv) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mCursor); - - mCursor->Close(aRv); -} - -void -DataStoreCursor::SetDataStoreCursorImpl(DataStoreCursorImpl& aCursor) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(!mCursor); - - mCursor = &aCursor; -} - -} //namespace dom -} //namespace mozilla
deleted file mode 100644 --- a/dom/datastore/DataStoreCursor.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_DataStoreCursor_h -#define mozilla_dom_DataStoreCursor_h - -#include "nsAutoPtr.h" -#include "nsCOMPtr.h" -#include "nsCycleCollectionParticipant.h" - -namespace mozilla { - -class ErrorResult; - -namespace dom { - -class Promise; -class DataStore; -class GlobalObject; -class DataStoreCursorImpl; - -class DataStoreCursor final : public nsISupports -{ -public: - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_CLASS(DataStoreCursor) - - // WebIDL (internal functions) - - static already_AddRefed<DataStoreCursor> Constructor(GlobalObject& aGlobal, - ErrorResult& aRv); - - bool WrapObject(JSContext *aCx, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector); - - // WebIDL (public APIs) - - already_AddRefed<DataStore> GetStore(ErrorResult& aRv); - - already_AddRefed<Promise> Next(ErrorResult& aRv); - - void Close(ErrorResult& aRv); - - // This internal function (ChromeOnly) is aimed to make the DataStoreCursor - // keep a reference to the DataStoreCursorImpl which really implements the - // API's logic in JS. - void SetDataStoreCursorImpl(DataStoreCursorImpl& aCursor); - -private: - ~DataStoreCursor() {} - RefPtr<DataStoreCursorImpl> mCursor; -}; - -} //namespace dom -} //namespace mozilla - -#endif
deleted file mode 100644 --- a/dom/datastore/DataStoreCursorImpl.jsm +++ /dev/null @@ -1,444 +0,0 @@ -/* -*- js-indent-level: 2; indent-tabs-mode: nil -*- */ -/* vim: set ft=javascript ts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -'use strict' - -this.EXPORTED_SYMBOLS = ['DataStoreCursor']; - -function debug(s) { - //dump('DEBUG DataStoreCursor: ' + s + '\n'); -} - -const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; - -const STATE_INIT = 0; -const STATE_REVISION_INIT = 1; -const STATE_REVISION_CHECK = 2; -const STATE_SEND_ALL = 3; -const STATE_REVISION_SEND = 4; -const STATE_DONE = 5; - -const REVISION_ADDED = 'added'; -const REVISION_UPDATED = 'updated'; -const REVISION_REMOVED = 'removed'; -const REVISION_VOID = 'void'; -const REVISION_SKIP = 'skip' - -Cu.import('resource://gre/modules/Services.jsm'); -Cu.import('resource://gre/modules/XPCOMUtils.jsm'); - -/** - * legend: - * - RID = revision ID - * - R = revision object (with the internalRevisionId that is a number) - * - X = current object ID. - * - L = the list of revisions that we have to send - * - * State: init: do you have RID ? - * YES: state->initRevision; loop - * NO: get R; X=0; state->sendAll; send a 'clear' - * - * State: initRevision. Get R from RID. Done? - * YES: state->revisionCheck; loop - * NO: RID = null; state->init; loop - * - * State: revisionCheck: get all the revisions between R and NOW. Done? - * YES and R == NOW: state->done; loop - * YES and R != NOW: Store this revisions in L; state->revisionSend; loop - * NO: R = NOW; X=0; state->sendAll; send a 'clear' - * - * State: sendAll: is R still the last revision? - * YES get the first object with id > X. Done? - * YES: X = object.id; send 'add' - * NO: state->revisionCheck; loop - * NO: R = NOW; X=0; send a 'clear' - * - * State: revisionSend: do you have something from L to send? - * YES and L[0] == 'removed': R=L[0]; send 'remove' with ID - * YES and L[0] == 'added': R=L[0]; get the object; found? - * NO: loop - * YES: send 'add' with ID and object - * YES and L[0] == 'updated': R=L[0]; get the object; found? - * NO: loop - * YES and object.R > R: continue - * YES and object.R <= R: send 'update' with ID and object - * YES L[0] == 'void': R=L[0]; state->init; loop - * NO: state->revisionCheck; loop - * - * State: done: send a 'done' with R - */ - -/* Helper functions */ -function createDOMError(aWindow, aEvent) { - return new aWindow.DOMError(aEvent); -} - -/* DataStoreCursor object */ -this.DataStoreCursor = function(aWindow, aDataStore, aRevisionId) { - debug("DataStoreCursor created"); - this.init(aWindow, aDataStore, aRevisionId); -} - -this.DataStoreCursor.prototype = { - classDescription: 'DataStoreCursor XPCOM Component', - classID: Components.ID('{b6d14349-1eab-46b8-8513-584a7328a26b}'), - contractID: '@mozilla.org/dom/datastore-cursor-impl;1', - QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsISupports]), - - _shuttingdown: false, - - _window: null, - _dataStore: null, - _revisionId: null, - _revision: null, - _revisionsList: null, - _objectId: 0, - - _state: STATE_INIT, - - init: function(aWindow, aDataStore, aRevisionId) { - debug('DataStoreCursor init'); - - this._window = aWindow; - this._dataStore = aDataStore; - this._revisionId = aRevisionId; - - Services.obs.addObserver(this, "inner-window-destroyed", false); - - let util = aWindow.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils); - this._innerWindowID = util.currentInnerWindowID; - }, - - observe: function(aSubject, aTopic, aData) { - let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data; - if (wId == this._innerWindowID) { - Services.obs.removeObserver(this, "inner-window-destroyed"); - this._shuttingdown = true; - } - }, - - // This is the implementation of the state machine. - // Read the comments at the top of this file in order to follow what it does. - stateMachine: function(aStore, aRevisionStore, aResolve, aReject) { - debug('StateMachine: ' + this._state); - - // If the window has been destroyed we cannot create the Promise object. - if (this._shuttingdown) { - return; - } - - switch (this._state) { - case STATE_INIT: - this.stateMachineInit(aStore, aRevisionStore, aResolve, aReject); - break; - - case STATE_REVISION_INIT: - this.stateMachineRevisionInit(aStore, aRevisionStore, aResolve, aReject); - break; - - case STATE_REVISION_CHECK: - this.stateMachineRevisionCheck(aStore, aRevisionStore, aResolve, aReject); - break; - - case STATE_SEND_ALL: - this.stateMachineSendAll(aStore, aRevisionStore, aResolve, aReject); - break; - - case STATE_REVISION_SEND: - this.stateMachineRevisionSend(aStore, aRevisionStore, aResolve, aReject); - break; - - case STATE_DONE: - this.stateMachineDone(aStore, aRevisionStore, aResolve, aReject); - break; - } - }, - - stateMachineInit: function(aStore, aRevisionStore, aResolve, aReject) { - debug('StateMachineInit'); - - if (this._revisionId) { - this._state = STATE_REVISION_INIT; - this.stateMachine(aStore, aRevisionStore, aResolve, aReject); - return; - } - - let self = this; - let request = aRevisionStore.openCursor(null, 'prev'); - request.onsuccess = function(aEvent) { - if (aEvent.target.result === undefined) { - aReject(self._window.DOMError("InvalidRevision", - "The DataStore is corrupted")); - return; - } - - self._revision = aEvent.target.result.value; - self._objectId = 0; - self._state = STATE_SEND_ALL; - aResolve(self.createTask('clear', null, '', null)); - } - }, - - stateMachineRevisionInit: function(aStore, aRevisionStore, aResolve, aReject) { - debug('StateMachineRevisionInit'); - - let self = this; - let request = this._dataStore._db.getInternalRevisionId( - self._revisionId, - aRevisionStore, - function(aInternalRevisionId) { - // This revision doesn't exist. - if (aInternalRevisionId == undefined) { - self._revisionId = null; - self._objectId = 0; - self._state = STATE_INIT; - self.stateMachine(aStore, aRevisionStore, aResolve, aReject); - return; - } - - self._revision = { revisionId: self._revisionId, - internalRevisionId: aInternalRevisionId }; - self._state = STATE_REVISION_CHECK; - self.stateMachine(aStore, aRevisionStore, aResolve, aReject); - } - ); - }, - - stateMachineRevisionCheck: function(aStore, aRevisionStore, aResolve, aReject) { - debug('StateMachineRevisionCheck'); - - let changes = { - addedIds: {}, - updatedIds: {}, - removedIds: {} - }; - - let self = this; - let request = aRevisionStore.mozGetAll( - self._window.IDBKeyRange.lowerBound(this._revision.internalRevisionId, true)); - request.onsuccess = function(aEvent) { - - // Optimize the operations. - for (let i = 0; i < aEvent.target.result.length; ++i) { - let data = aEvent.target.result[i]; - - switch (data.operation) { - case REVISION_ADDED: - changes.addedIds[data.objectId] = data.internalRevisionId; - break; - - case REVISION_UPDATED: - // We don't consider an update if this object has been added - // or if it has been already modified by a previous - // operation. - if (!(data.objectId in changes.addedIds) && - !(data.objectId in changes.updatedIds)) { - changes.updatedIds[data.objectId] = data.internalRevisionId; - } - break; - - case REVISION_REMOVED: - let id = data.objectId; - - // If the object has been added in this range of revisions - // we can ignore it and remove it from the list. - if (id in changes.addedIds) { - delete changes.addedIds[id]; - } else { - changes.removedIds[id] = data.internalRevisionId; - } - - if (id in changes.updatedIds) { - delete changes.updatedIds[id]; - } - break; - - case REVISION_VOID: - if (i != 0) { - dump('Internal error: Revision "' + REVISION_VOID + '" should not be found!!!\n'); - return; - } - - self._revisionId = null; - self._objectId = 0; - self._state = STATE_INIT; - self.stateMachine(aStore, aRevisionStore, aResolve, aReject); - return; - } - } - - // From changes to a map of internalRevisionId. - let revisions = {}; - function addRevisions(obj) { - for (let key in obj) { - revisions[obj[key]] = true; - } - } - - addRevisions(changes.addedIds); - addRevisions(changes.updatedIds); - addRevisions(changes.removedIds); - - // Create the list of revisions. - let list = []; - for (let i = 0; i < aEvent.target.result.length; ++i) { - let data = aEvent.target.result[i]; - - // If this revision doesn't contain useful data, we still need to keep - // it in the list because we need to update the internal revision ID. - if (!(data.internalRevisionId in revisions)) { - data.operation = REVISION_SKIP; - } - - list.push(data); - } - - if (list.length == 0) { - self._state = STATE_DONE; - self.stateMachine(aStore, aRevisionStore, aResolve, aReject); - return; - } - - // Some revision has to be sent. - self._revisionsList = list; - self._state = STATE_REVISION_SEND; - self.stateMachine(aStore, aRevisionStore, aResolve, aReject); - }; - }, - - stateMachineSendAll: function(aStore, aRevisionStore, aResolve, aReject) { - debug('StateMachineSendAll'); - - let self = this; - let request = aRevisionStore.openCursor(null, 'prev'); - request.onsuccess = function(aEvent) { - if (self._revision.revisionId != aEvent.target.result.value.revisionId) { - self._revision = aEvent.target.result.value; - self._objectId = 0; - aResolve(self.createTask('clear', null, '', null)); - return; - } - - let request = aStore.openCursor(self._window.IDBKeyRange.lowerBound(self._objectId, true)); - request.onsuccess = function(aEvent) { - let cursor = aEvent.target.result; - if (!cursor) { - self._state = STATE_REVISION_CHECK; - self.stateMachine(aStore, aRevisionStore, aResolve, aReject); - return; - } - - self._objectId = cursor.key; - aResolve(self.createTask('add', self._objectId, '', cursor.value)); - }; - }; - }, - - stateMachineRevisionSend: function(aStore, aRevisionStore, aResolve, aReject) { - debug('StateMachineRevisionSend'); - - if (!this._revisionsList.length) { - this._state = STATE_REVISION_CHECK; - this.stateMachine(aStore, aRevisionStore, aResolve, aReject); - return; - } - - this._revision = this._revisionsList.shift(); - - switch (this._revision.operation) { - case REVISION_REMOVED: - aResolve(this.createTask('remove', this._revision.objectId, '', null)); - break; - - case REVISION_ADDED: { - let request = aStore.get(this._revision.objectId); - let self = this; - request.onsuccess = function(aEvent) { - if (aEvent.target.result == undefined) { - self.stateMachine(aStore, aRevisionStore, aResolve, aReject); - return; - } - - aResolve(self.createTask('add', self._revision.objectId, '', - aEvent.target.result)); - } - break; - } - - case REVISION_UPDATED: { - let request = aStore.get(this._revision.objectId); - let self = this; - request.onsuccess = function(aEvent) { - if (aEvent.target.result == undefined) { - self.stateMachine(aStore, aRevisionStore, aResolve, aReject); - return; - } - - if (aEvent.target.result.revisionId > self._revision.internalRevisionId) { - self.stateMachine(aStore, aRevisionStore, aResolve, aReject); - return; - } - - aResolve(self.createTask('update', self._revision.objectId, '', - aEvent.target.result)); - } - break; - } - - case REVISION_VOID: - // Internal error! - dump('Internal error: Revision "' + REVISION_VOID + '" should not be found!!!\n'); - break; - - case REVISION_SKIP: - // This revision contains data that has already been sent by another one. - this.stateMachine(aStore, aRevisionStore, aResolve, aReject); - break; - } - }, - - stateMachineDone: function(aStore, aRevisionStore, aResolve, aReject) { - this.close(); - aResolve(this.createTask('done', null, this._revision.revisionId, null)); - }, - - // public interface - - get store() { - return this._dataStore.exposedObject; - }, - - next: function() { - debug('Next'); - - // If the window has been destroyed we cannot create the Promise object. - if (this._shuttingdown) { - throw Cr.NS_ERROR_FAILURE; - } - - let self = this; - return new this._window.Promise(function(aResolve, aReject) { - self._dataStore._db.cursorTxn( - function(aTxn, aStore, aRevisionStore) { - self.stateMachine(aStore, aRevisionStore, aResolve, aReject); - }, - function(aEvent) { - aReject(createDOMError(self._window, aEvent)); - } - ); - }); - }, - - close: function() { - this._dataStore.syncTerminated(this); - }, - - createTask: function(aOperation, aId, aRevisionId, aData) { - return Cu.cloneInto({ operation: aOperation, id: aId, - revisionId: aRevisionId, data: aData }, this._window); - } -};
deleted file mode 100644 --- a/dom/datastore/DataStoreDB.cpp +++ /dev/null @@ -1,439 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "DataStoreDB.h" - -#include "DataStoreCallbacks.h" -#include "jsapi.h" -#include "mozilla/dom/IDBDatabaseBinding.h" -#include "mozilla/dom/IDBDatabase.h" -#include "mozilla/dom/IDBEvents.h" -#include "mozilla/dom/IDBFactory.h" -#include "mozilla/dom/IDBFactoryBinding.h" -#include "mozilla/dom/IDBIndex.h" -#include "mozilla/dom/IDBObjectStore.h" -#include "mozilla/dom/IDBObjectStoreBinding.h" -#include "mozilla/dom/IDBRequest.h" -#include "mozilla/dom/IDBTransaction.h" -#include "nsComponentManagerUtils.h" -#include "nsContentUtils.h" -#include "nsIDOMEvent.h" -#include "nsIPrincipal.h" -#include "nsIXPConnect.h" -#include "nsNullPrincipal.h" - -#define DATASTOREDB_VERSION 1 -#define DATASTOREDB_NAME "DataStoreDB" -#define DATASTOREDB_REVISION_INDEX "revisionIndex" - -using namespace mozilla::dom::indexedDB; - -namespace mozilla { -namespace dom { - -class VersionChangeListener final : public nsIDOMEventListener -{ -public: - NS_DECL_ISUPPORTS - - explicit VersionChangeListener(IDBDatabase* aDatabase) - : mDatabase(aDatabase) - {} - - // nsIDOMEventListener - NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) override - { - nsString type; - nsresult rv = aEvent->GetType(type); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - if (!type.EqualsASCII("versionchange")) { - MOZ_ASSERT_UNREACHABLE("Expected a versionchange event"); - return NS_ERROR_FAILURE; - } - - rv = mDatabase->RemoveEventListener(NS_LITERAL_STRING("versionchange"), - this, false); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - -#ifdef DEBUG - nsCOMPtr<IDBVersionChangeEvent> event = do_QueryInterface(aEvent); - MOZ_ASSERT(event); - - Nullable<uint64_t> version = event->GetNewVersion(); - MOZ_ASSERT(version.IsNull()); -#endif - - mDatabase->Close(); - - return NS_OK; - } - -private: - IDBDatabase* mDatabase; - - ~VersionChangeListener() {} -}; - -NS_IMPL_ISUPPORTS(VersionChangeListener, nsIDOMEventListener) - -NS_IMPL_ISUPPORTS(DataStoreDB, nsIDOMEventListener) - -DataStoreDB::DataStoreDB(const nsAString& aManifestURL, const nsAString& aName) - : mState(Inactive) - , mCreatedSchema(false) -{ - mDatabaseName.Assign(aName); - mDatabaseName.Append('|'); - mDatabaseName.Append(aManifestURL); -} - -DataStoreDB::~DataStoreDB() -{ -} - -nsresult -DataStoreDB::CreateFactoryIfNeeded() -{ - if (!mFactory) { - nsresult rv; - nsCOMPtr<nsIPrincipal> principal = nsNullPrincipal::Create(); - - nsIXPConnect* xpc = nsContentUtils::XPConnect(); - MOZ_ASSERT(xpc); - - AutoJSAPI jsapi; - jsapi.Init(); - JSContext* cx = jsapi.cx(); - JS::Rooted<JSObject*> global(cx); - rv = xpc->CreateSandbox(cx, principal, global.address()); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - // The CreateSandbox call returns a proxy to the actual sandbox object. We - // don't need a proxy here. - global = js::UncheckedUnwrap(global); - - JSAutoCompartment ac(cx, global); - - rv = IDBFactory::CreateForDatastore(cx, global, getter_AddRefs(mFactory)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - } - - return NS_OK; -} - -nsresult -DataStoreDB::Open(IDBTransactionMode aMode, const Sequence<nsString>& aDbs, - DataStoreDBCallback* aCallback) -{ - MOZ_ASSERT(mState == Inactive); - - nsresult rv = CreateFactoryIfNeeded(); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - // We only need a JSContext here to get a stack from, so just init our - // AutoJSAPI without a global. - AutoJSAPI jsapi; - jsapi.Init(); - ErrorResult error; - mRequest = mFactory->Open(jsapi.cx(), mDatabaseName, DATASTOREDB_VERSION, - error); - if (NS_WARN_IF(error.Failed())) { - return error.StealNSResult(); - } - - rv = AddEventListeners(); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - mState = Active; - mTransactionMode = aMode; - mObjectStores = aDbs; - mCallback = aCallback; - return NS_OK; -} - -NS_IMETHODIMP -DataStoreDB::HandleEvent(nsIDOMEvent* aEvent) -{ - nsString type; - nsresult rv = aEvent->GetType(type); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - if (type.EqualsASCII("success")) { - RemoveEventListeners(); - mState = Inactive; - - rv = DatabaseOpened(); - if (NS_WARN_IF(NS_FAILED(rv))) { - mCallback->Run(this, DataStoreDBCallback::Error); - } else { - mCallback->Run(this, mCreatedSchema - ? DataStoreDBCallback::CreatedSchema : - DataStoreDBCallback::Success); - } - - mRequest = nullptr; - return NS_OK; - } - - if (type.EqualsASCII("upgradeneeded")) { - return UpgradeSchema(aEvent); - } - - if (type.EqualsASCII("error") || type.EqualsASCII("blocked")) { - RemoveEventListeners(); - mState = Inactive; - mCallback->Run(this, DataStoreDBCallback::Error); - mRequest = nullptr; - return NS_OK; - } - - MOZ_CRASH("This should not happen"); -} - -nsresult -DataStoreDB::UpgradeSchema(nsIDOMEvent* aEvent) -{ - MOZ_ASSERT(NS_IsMainThread()); - - // This DB has been just created and we have to inform the callback about - // this. - mCreatedSchema = true; - -#ifdef DEBUG - nsCOMPtr<IDBVersionChangeEvent> event = do_QueryInterface(aEvent); - MOZ_ASSERT(event); - - Nullable<uint64_t> version = event->GetNewVersion(); - MOZ_ASSERT(!version.IsNull()); - MOZ_ASSERT(version.Value() == DATASTOREDB_VERSION); -#endif - - ErrorResult error; - JS::Rooted<JS::Value> result(nsContentUtils::RootingCx()); - mRequest->GetResult(&result, error); - if (NS_WARN_IF(error.Failed())) { - return error.StealNSResult(); - } - - MOZ_ASSERT(result.isObject()); - - IDBDatabase* database = nullptr; - nsresult rv = UNWRAP_OBJECT(IDBDatabase, &result.toObject(), database); - if (NS_FAILED(rv)) { - NS_WARNING("Didn't get the object we expected!"); - return rv; - } - - { - IDBObjectStoreParameters params; - params.Init(NS_LITERAL_STRING("{ \"autoIncrement\": true }")); - RefPtr<IDBObjectStore> store = - database->CreateObjectStore(NS_LITERAL_STRING(DATASTOREDB_NAME), - params, error); - if (NS_WARN_IF(error.Failed())) { - return error.StealNSResult(); - } - } - - RefPtr<IDBObjectStore> store; - - { - IDBObjectStoreParameters params; - params.Init(NS_LITERAL_STRING("{ \"autoIncrement\": true, \"keyPath\": \"internalRevisionId\" }")); - - store = - database->CreateObjectStore(NS_LITERAL_STRING(DATASTOREDB_REVISION), - params, error); - if (NS_WARN_IF(error.Failed())) { - return error.StealNSResult(); - } - } - - { - IDBIndexParameters params; - params.Init(NS_LITERAL_STRING("{ \"unique\": true }")); - RefPtr<IDBIndex> index = - store->CreateIndex(NS_LITERAL_STRING(DATASTOREDB_REVISION_INDEX), - NS_LITERAL_STRING("revisionId"), params, error); - if (NS_WARN_IF(error.Failed())) { - return error.StealNSResult(); - } - } - - return NS_OK; -} - -nsresult -DataStoreDB::DatabaseOpened() -{ - MOZ_ASSERT(NS_IsMainThread()); - - ErrorResult error; - JS::Rooted<JS::Value> result(nsContentUtils::RootingCx()); - mRequest->GetResult(&result, error); - if (NS_WARN_IF(error.Failed())) { - return error.StealNSResult(); - } - - MOZ_ASSERT(result.isObject()); - - nsresult rv = UNWRAP_OBJECT(IDBDatabase, &result.toObject(), mDatabase); - if (NS_FAILED(rv)) { - NS_WARNING("Didn't get the object we expected!"); - return rv; - } - - RefPtr<VersionChangeListener> listener = - new VersionChangeListener(mDatabase); - rv = mDatabase->EventTarget::AddEventListener( - NS_LITERAL_STRING("versionchange"), listener, false); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - StringOrStringSequence objectStores; - if (!objectStores.RawSetAsStringSequence().AppendElements(mObjectStores, - fallible)) { - return NS_ERROR_OUT_OF_MEMORY; - } - - // We init with the global of our result, just for consistency. - AutoJSAPI jsapi; - if (!jsapi.Init(&result.toObject())) { - return NS_ERROR_UNEXPECTED; - } - RefPtr<IDBTransaction> txn; - error = mDatabase->Transaction(jsapi.cx(), - objectStores, - mTransactionMode, - getter_AddRefs(txn)); - if (NS_WARN_IF(error.Failed())) { - return error.StealNSResult(); - } - - mTransaction = txn.forget(); - return NS_OK; -} - -nsresult -DataStoreDB::Delete() -{ - MOZ_ASSERT(mState == Inactive); - - nsresult rv = CreateFactoryIfNeeded(); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - mTransaction = nullptr; - - if (mDatabase) { - mDatabase->Close(); - mDatabase = nullptr; - } - - // We only need a JSContext here to get a stack from, so just init our - // AutoJSAPI without a global. - AutoJSAPI jsapi; - jsapi.Init(); - ErrorResult error; - RefPtr<IDBOpenDBRequest> request = - mFactory->DeleteDatabase(jsapi.cx(), mDatabaseName, IDBOpenDBOptions(), - error); - if (NS_WARN_IF(error.Failed())) { - return error.StealNSResult(); - } - - return NS_OK; -} - -IDBTransaction* -DataStoreDB::Transaction() const -{ - MOZ_ASSERT(mTransaction); - MOZ_ASSERT(mTransaction->IsOpen()); - return mTransaction; -} - -nsresult -DataStoreDB::AddEventListeners() -{ - nsresult rv; - rv = mRequest->EventTarget::AddEventListener(NS_LITERAL_STRING("success"), - this, false); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = mRequest->EventTarget::AddEventListener(NS_LITERAL_STRING("upgradeneeded"), - this, false); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = mRequest->EventTarget::AddEventListener(NS_LITERAL_STRING("error"), - this, false); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = mRequest->EventTarget::AddEventListener(NS_LITERAL_STRING("blocked"), - this, false); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - return NS_OK; -} - -nsresult -DataStoreDB::RemoveEventListeners() -{ - nsresult rv; - rv = mRequest->RemoveEventListener(NS_LITERAL_STRING("success"), - this, false); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = mRequest->RemoveEventListener(NS_LITERAL_STRING("upgradeneeded"), - this, false); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = mRequest->RemoveEventListener(NS_LITERAL_STRING("error"), - this, false); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = mRequest->RemoveEventListener(NS_LITERAL_STRING("blocked"), - this, false); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - return NS_OK; -} - -} // namespace dom -} // namespace mozilla
deleted file mode 100644 --- a/dom/datastore/DataStoreDB.h +++ /dev/null @@ -1,80 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_DataStoreDB_h -#define mozilla_dom_DataStoreDB_h - -#include "mozilla/dom/IDBTransactionBinding.h" -#include "nsAutoPtr.h" -#include "nsIDOMEventListener.h" -#include "nsISupportsImpl.h" -#include "nsString.h" - -#define DATASTOREDB_REVISION "revision" - -namespace mozilla { -namespace dom { - -class DataStoreDBCallback; -class IDBDatabase; -class IDBFactory; -class IDBOpenDBRequest; -class IDBTransaction; - -class DataStoreDB final : public nsIDOMEventListener -{ -public: - NS_DECL_ISUPPORTS - - DataStoreDB(const nsAString& aManifestURL, const nsAString& aName); - - nsresult Open(IDBTransactionMode aMode, const Sequence<nsString>& aDb, - DataStoreDBCallback* aCallback); - - nsresult Delete(); - - IDBTransaction* Transaction() const; - - // nsIDOMEventListener - NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) override; - -private: - ~DataStoreDB(); - - nsresult CreateFactoryIfNeeded(); - - nsresult UpgradeSchema(nsIDOMEvent* aEvent); - - nsresult DatabaseOpened(); - - nsresult AddEventListeners(); - - nsresult RemoveEventListeners(); - - nsString mDatabaseName; - - RefPtr<IDBFactory> mFactory; - RefPtr<IDBOpenDBRequest> mRequest; - RefPtr<IDBDatabase> mDatabase; - RefPtr<IDBTransaction> mTransaction; - - RefPtr<DataStoreDBCallback> mCallback; - - // Internal state to avoid strange use of this class. - enum StateType { - Inactive, - Active - } mState; - - IDBTransactionMode mTransactionMode; - Sequence<nsString> mObjectStores; - bool mCreatedSchema; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_DataStoreDB_h
deleted file mode 100644 --- a/dom/datastore/DataStoreDB.jsm +++ /dev/null @@ -1,118 +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'; - -const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; - -this.EXPORTED_SYMBOLS = ['DataStoreDB']; - -function debug(s) { - //dump('DEBUG DataStoreDB: ' + s + '\n'); -} - -const DATASTOREDB_VERSION = 1; -const DATASTOREDB_OBJECTSTORE_NAME = 'DataStoreDB'; -const DATASTOREDB_REVISION = 'revision'; -const DATASTOREDB_REVISION_INDEX = 'revisionIndex'; - -Cu.import('resource://gre/modules/IndexedDBHelper.jsm'); -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.importGlobalProperties(["indexedDB"]); - -XPCOMUtils.defineLazyServiceGetter(this, "uuidgen", - "@mozilla.org/uuid-generator;1", - "nsIUUIDGenerator"); - -this.DataStoreDB = function DataStoreDB() {} - -DataStoreDB.prototype = { - - __proto__: IndexedDBHelper.prototype, - - upgradeSchema: function(aTransaction, aDb, aOldVersion, aNewVersion) { - debug('updateSchema'); - aDb.createObjectStore(DATASTOREDB_OBJECTSTORE_NAME, { autoIncrement: true }); - let store = aDb.createObjectStore(DATASTOREDB_REVISION, - { autoIncrement: true, - keyPath: 'internalRevisionId' }); - store.createIndex(DATASTOREDB_REVISION_INDEX, 'revisionId', { unique: true }); - }, - - init: function(aOwner, aName) { - let dbName = aName + '|' + aOwner; - this.initDBHelper(dbName, DATASTOREDB_VERSION, - [DATASTOREDB_OBJECTSTORE_NAME, DATASTOREDB_REVISION]); - }, - - txn: function(aType, aCallback, aErrorCb) { - debug('Transaction request'); - this.newTxn( - aType, - aType == 'readonly' - ? [ DATASTOREDB_OBJECTSTORE_NAME ] : [ DATASTOREDB_OBJECTSTORE_NAME, DATASTOREDB_REVISION ], - function(aTxn, aStores) { - aType == 'readonly' ? aCallback(aTxn, aStores[0], null) : aCallback(aTxn, aStores[0], aStores[1]); - }, - function() {}, - aErrorCb - ); - }, - - cursorTxn: function(aCallback, aErrorCb) { - debug('Cursor transaction request'); - this.newTxn( - 'readonly', - [ DATASTOREDB_OBJECTSTORE_NAME, DATASTOREDB_REVISION ], - function(aTxn, aStores) { - aCallback(aTxn, aStores[0], aStores[1]); - }, - function() {}, - aErrorCb - ); - }, - - revisionTxn: function(aType, aCallback, aErrorCb) { - debug("Transaction request"); - this.newTxn( - aType, - DATASTOREDB_REVISION, - aCallback, - function() {}, - aErrorCb - ); - }, - - addRevision: function(aStore, aKey, aType, aSuccessCb) { - debug("AddRevision: " + aKey + " - " + aType); - let revisionId = uuidgen.generateUUID().toString(); - let request = aStore.put({ revisionId: revisionId, objectId: aKey, operation: aType }); - request.onsuccess = function() { - aSuccessCb(revisionId); - } - }, - - getInternalRevisionId: function(aRevisionId, aStore, aSuccessCb) { - debug('GetInternalRevisionId'); - let request = aStore.index(DATASTOREDB_REVISION_INDEX).getKey(aRevisionId); - request.onsuccess = function(aEvent) { - aSuccessCb(aEvent.target.result); - } - }, - - clearRevisions: function(aStore, aSuccessCb) { - debug("ClearRevisions"); - let request = aStore.clear(); - request.onsuccess = function() { - aSuccessCb(); - } - }, - - delete: function() { - debug('delete'); - this.close(); - indexedDB.deleteDatabase(this.dbName); - debug('database deleted'); - } -}
deleted file mode 100644 --- a/dom/datastore/DataStoreImpl.js +++ /dev/null @@ -1,549 +0,0 @@ -/* -*- js-indent-level: 2; indent-tabs-mode: nil -*- */ -/* vim: set ft=javascript ts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -'use strict' - -function debug(s) { - //dump('DEBUG DataStore: ' + s + '\n'); -} - -const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; - -const REVISION_ADDED = "added"; -const REVISION_UPDATED = "updated"; -const REVISION_REMOVED = "removed"; -const REVISION_VOID = "void"; - -// This value has to be tuned a bit. Currently it's just a guess -// and yet we don't know if it's too low or too high. -const MAX_REQUESTS = 25; - -Cu.import("resource://gre/modules/DataStoreCursorImpl.jsm"); -Cu.import("resource://gre/modules/DataStoreDB.jsm"); -Cu.import('resource://gre/modules/Services.jsm'); -Cu.import('resource://gre/modules/XPCOMUtils.jsm'); -Cu.importGlobalProperties(["indexedDB"]); - -XPCOMUtils.defineLazyServiceGetter(this, "cpmm", - "@mozilla.org/childprocessmessagemanager;1", - "nsIMessageSender"); - -/* Helper functions */ -function createDOMError(aWindow, aEvent) { - return new aWindow.DOMError(aEvent); -} - -function throwInvalidArg(aWindow) { - return aWindow.Promise.reject( - new aWindow.DOMError("SyntaxError", "Non-numeric or invalid id")); -} - -function throwReadOnly(aWindow) { - return aWindow.Promise.reject( - new aWindow.DOMError("ReadOnlyError", "DataStore in readonly mode")); -} - -function validateId(aId) { - // If string, it cannot be empty. - if (typeof(aId) == 'string') { - return aId.length; - } - - aId = parseInt(aId); - return (!isNaN(aId) && aId > 0); -} - -/* DataStore object */ -function DataStore() { - debug("DataStore created"); -} - -DataStore.prototype = { - classDescription: "DataStore XPCOM Component", - classID: Components.ID("{db5c9602-030f-4bff-a3de-881a8de370f2}"), - contractID: "@mozilla.org/dom/datastore-impl;1", - QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataStore, Ci.nsISupports, - Ci.nsIObserver]), - - callbacks: [], - - _window: null, - _name: null, - _owner: null, - _readOnly: null, - _revisionId: null, - _exposedObject: null, - _cursor: null, - _shuttingdown: false, - _eventTarget: null, - - init: function(aWindow, aName, aOwner, aReadOnly) { - debug("DataStore init"); - - this._window = aWindow; - this._name = aName; - this._owner = aOwner; - this._readOnly = aReadOnly; - - this._db = new DataStoreDB(); - this._db.init(aOwner, aName); - - Services.obs.addObserver(this, "inner-window-destroyed", false); - - let util = aWindow.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils); - this._innerWindowID = util.currentInnerWindowID; - - cpmm.addMessageListener("DataStore:Changed:Return:OK", this); - cpmm.sendAsyncMessage("DataStore:RegisterForMessages", - { store: this._name, owner: this._owner, - innerWindowID: this._innerWindowID }, - null, - this._window.document.nodePrincipal); - }, - - observe: function(aSubject, aTopic, aData) { - let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data; - if (wId == this._innerWindowID) { - Services.obs.removeObserver(this, "inner-window-destroyed"); - - cpmm.removeMessageListener("DataStore:Changed:Return:OK", this); - cpmm.sendAsyncMessage("DataStore:UnregisterForMessages", - { innerWindowID: this._innerWindowID }, - null, - this._window.document.nodePrincipal); - this._shuttingdown = true; - this._db.close(); - } - }, - - setEventTarget: function(aEventTarget) { - this._eventTarget = aEventTarget; - }, - - newDBPromise: function(aTxnType, aFunction) { - let self = this; - return new this._window.Promise(function(aResolve, aReject) { - debug("DBPromise started"); - self._db.txn( - aTxnType, - function(aTxn, aStore, aRevisionStore) { - debug("DBPromise success"); - aFunction(aResolve, aReject, aTxn, aStore, aRevisionStore); - }, - function(aEvent) { - debug("DBPromise error"); - aReject(createDOMError(self._window, aEvent)); - } - ); - }); - }, - - checkRevision: function(aReject, aRevisionStore, aRevisionId, aCallback) { - if (!aRevisionId) { - aCallback(); - return; - } - - let self = this; - - let request = aRevisionStore.openCursor(null, 'prev'); - request.onsuccess = function(aEvent) { - let cursor = aEvent.target.result; - if (!cursor) { - dump("This cannot really happen."); - return; - } - - if (cursor.value.revisionId != aRevisionId) { - aReject(new self._window.DOMError("ConstraintError", - "RevisionId is not up-to-date")); - return; - } - - aCallback(); - } - }, - - getInternal: function(aStore, aIds, aCallback) { - debug("GetInternal: " + aIds.toSource()); - - // Creation of the results array. - let results = new this._window.Array(aIds.length); - - // We're going to create this amount of requests. - let pendingIds = aIds.length; - let indexPos = 0; - - let self = this; - - function getInternalSuccess(aEvent, aPos) { - debug("GetInternal success. Record: " + aEvent.target.result); - results[aPos] = Cu.cloneInto(aEvent.target.result, self._window); - if (!--pendingIds) { - aCallback(results); - return; - } - - if (indexPos < aIds.length) { - // Just MAX_REQUESTS requests at the same time. - let count = 0; - while (indexPos < aIds.length && ++count < MAX_REQUESTS) { - getInternalRequest(); - } - } - } - - function getInternalRequest() { - let currentPos = indexPos++; - let request = aStore.get(aIds[currentPos]); - request.onsuccess = function(aEvent) { - getInternalSuccess(aEvent, currentPos); - } - } - - getInternalRequest(); - }, - - putInternal: function(aResolve, aStore, aRevisionStore, aObj, aId) { - debug("putInternal " + aId); - - let self = this; - let request = aStore.put(aObj, aId); - request.onsuccess = function(aEvent) { - debug("putInternal success"); - - self.addRevision(aRevisionStore, aId, REVISION_UPDATED, - function() { - debug("putInternal - revisionId increased"); - // No wrap here because the result is always a int. - aResolve(aEvent.target.result); - } - ); - }; - }, - - addInternal: function(aResolve, aStore, aRevisionStore, aObj, aId) { - debug("AddInternal"); - - let self = this; - let request = aStore.add(aObj, aId); - request.onsuccess = function(aEvent) { - debug("Request successful. Id: " + aEvent.target.result); - self.addRevision(aRevisionStore, aEvent.target.result, REVISION_ADDED, - function() { - debug("AddInternal - revisionId increased"); - // No wrap here because the result is always a int. - aResolve(aEvent.target.result); - } - ); - }; - }, - - removeInternal: function(aResolve, aStore, aRevisionStore, aId) { - debug("RemoveInternal"); - - let self = this; - let request = aStore.get(aId); - request.onsuccess = function(aEvent) { - debug("RemoveInternal success. Record: " + aEvent.target.result); - if (aEvent.target.result === undefined) { - aResolve(false); - return; - } - - let deleteRequest = aStore.delete(aId); - deleteRequest.onsuccess = function() { - debug("RemoveInternal success"); - self.addRevision(aRevisionStore, aId, REVISION_REMOVED, - function() { - aResolve(true); - } - ); - }; - }; - }, - - clearInternal: function(aResolve, aStore, aRevisionStore) { - debug("ClearInternal"); - - let self = this; - let request = aStore.clear(); - request.onsuccess = function() { - debug("ClearInternal success"); - self._db.clearRevisions(aRevisionStore, - function() { - debug("Revisions cleared"); - - self.addRevision(aRevisionStore, null, REVISION_VOID, - function() { - debug("ClearInternal - revisionId increased"); - aResolve(); - } - ); - } - ); - }; - }, - - getLengthInternal: function(aResolve, aStore) { - debug("GetLengthInternal"); - - let request = aStore.count(); - request.onsuccess = function(aEvent) { - debug("GetLengthInternal success: " + aEvent.target.result); - // No wrap here because the result is always a int. - aResolve(aEvent.target.result); - }; - }, - - addRevision: function(aRevisionStore, aId, aType, aSuccessCb) { - let self = this; - this._db.addRevision(aRevisionStore, aId, aType, - function(aRevisionId) { - self._revisionId = aRevisionId; - self.sendNotification(aId, aType, aRevisionId); - aSuccessCb(); - } - ); - }, - - retrieveRevisionId: function(aSuccessCb) { - let self = this; - this._db.revisionTxn( - 'readonly', - function(aTxn, aRevisionStore) { - debug("RetrieveRevisionId transaction success"); - - let request = aRevisionStore.openCursor(null, 'prev'); - request.onsuccess = function(aEvent) { - let cursor = aEvent.target.result; - if (cursor) { - self._revisionId = cursor.value.revisionId; - } - - aSuccessCb(self._revisionId); - }; - } - ); - }, - - sendNotification: function(aId, aOperation, aRevisionId) { - debug("SendNotification"); - if (aOperation == REVISION_VOID) { - aOperation = "cleared"; - } - - cpmm.sendAsyncMessage("DataStore:Changed", - { store: this.name, owner: this._owner, - message: { revisionId: aRevisionId, id: aId, - operation: aOperation, owner: this._owner } }, - null, - this._window.document.nodePrincipal); - }, - - receiveMessage: function(aMessage) { - debug("receiveMessage"); - - if (aMessage.name != "DataStore:Changed:Return:OK") { - debug("Wrong message: " + aMessage.name); - return; - } - - // If this message is not for this DataStore, let's ignore it. - if (aMessage.data.owner != this._owner || - aMessage.data.store != this._name) { - return; - } - - let self = this; - - this.retrieveRevisionId( - function() { - // If the window has been destroyed we don't emit the events. - if (self._shuttingdown) { - return; - } - - // If we have an active cursor we don't emit events. - if (self._cursor) { - return; - } - - let event = new self._window.DataStoreChangeEvent('change', - aMessage.data.message); - self._eventTarget.dispatchEvent(event); - } - ); - }, - - get exposedObject() { - debug("get exposedObject"); - return this._exposedObject; - }, - - set exposedObject(aObject) { - debug("set exposedObject"); - this._exposedObject = aObject; - }, - - syncTerminated: function(aCursor) { - // This checks is to avoid that an invalid cursor stops a sync. - if (this._cursor == aCursor) { - this._cursor = null; - } - }, - - // Public interface : - - get name() { - return this._name; - }, - - get owner() { - return this._owner; - }, - - get readOnly() { - return this._readOnly; - }, - - get: function() { - let ids = Array.prototype.slice.call(arguments); - for (let i = 0; i < ids.length; ++i) { - if (!validateId(ids[i])) { - return throwInvalidArg(this._window); - } - } - - if (ids.length == 0) { - return this._window.Promise.resolve(new this._window.Array()); - } - - let self = this; - - // Promise<Object> - return this.newDBPromise("readonly", - function(aResolve, aReject, aTxn, aStore, aRevisionStore) { - self.getInternal(aStore, ids, - function(aResults) { - aResolve(ids.length > 1 ? aResults : aResults[0]); - }); - } - ); - }, - - put: function(aObj, aId, aRevisionId) { - if (!validateId(aId)) { - return throwInvalidArg(this._window); - } - - if (this._readOnly) { - return throwReadOnly(this._window); - } - - let self = this; - - // Promise<void> - return this.newDBPromise("readwrite", - function(aResolve, aReject, aTxn, aStore, aRevisionStore) { - self.checkRevision(aReject, aRevisionStore, aRevisionId, function() { - self.putInternal(aResolve, aStore, aRevisionStore, aObj, aId); - }); - } - ); - }, - - add: function(aObj, aId, aRevisionId) { - if (aId) { - if (!validateId(aId)) { - return throwInvalidArg(this._window); - } - } - - if (this._readOnly) { - return throwReadOnly(this._window); - } - - let self = this; - - // Promise<int> - return this.newDBPromise("readwrite", - function(aResolve, aReject, aTxn, aStore, aRevisionStore) { - self.checkRevision(aReject, aRevisionStore, aRevisionId, function() { - self.addInternal(aResolve, aStore, aRevisionStore, aObj, aId); - }); - } - ); - }, - - remove: function(aId, aRevisionId) { - if (!validateId(aId)) { - return throwInvalidArg(this._window); - } - - if (this._readOnly) { - return throwReadOnly(this._window); - } - - let self = this; - - // Promise<void> - return this.newDBPromise("readwrite", - function(aResolve, aReject, aTxn, aStore, aRevisionStore) { - self.checkRevision(aReject, aRevisionStore, aRevisionId, function() { - self.removeInternal(aResolve, aStore, aRevisionStore, aId); - }); - } - ); - }, - - clear: function(aRevisionId) { - if (this._readOnly) { - return throwReadOnly(this._window); - } - - let self = this; - - // Promise<void> - return this.newDBPromise("readwrite", - function(aResolve, aReject, aTxn, aStore, aRevisionStore) { - self.checkRevision(aReject, aRevisionStore, aRevisionId, function() { - self.clearInternal(aResolve, aStore, aRevisionStore); - }); - } - ); - }, - - get revisionId() { - return this._revisionId; - }, - - getLength: function() { - let self = this; - - // Promise<int> - return this.newDBPromise("readonly", - function(aResolve, aReject, aTxn, aStore, aRevisionStore) { - self.getLengthInternal(aResolve, aStore); - } - ); - }, - - sync: function(aRevisionId) { - debug("Sync"); - this._cursor = new DataStoreCursor(this._window, this, aRevisionId); - - let cursorImpl = this._window.DataStoreCursorImpl. - _create(this._window, this._cursor); - - let exposedCursor = new this._window.DataStoreCursor(); - exposedCursor.setDataStoreCursorImpl(cursorImpl); - return exposedCursor; - } -}; - -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DataStore]);
deleted file mode 100644 --- a/dom/datastore/DataStoreRevision.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "DataStoreRevision.h" - -#include "DataStoreCallbacks.h" -#include "DataStoreService.h" -#include "mozilla/dom/DataStoreBinding.h" -#include "mozilla/dom/IDBObjectStore.h" -#include "mozilla/dom/IDBRequest.h" -#include "mozilla/dom/ToJSValue.h" -#include "nsIDOMEvent.h" - -namespace mozilla { -namespace dom { - -NS_IMPL_ISUPPORTS(DataStoreRevision, nsIDOMEventListener) - -// Note: this code in it must not assume anything about the compartment cx is -// in. -nsresult -DataStoreRevision::AddRevision(JSContext* aCx, - IDBObjectStore* aStore, - uint32_t aObjectId, - RevisionType aRevisionType, - DataStoreRevisionCallback* aCallback) -{ - MOZ_ASSERT(aStore); - MOZ_ASSERT(aCallback); - - RefPtr<DataStoreService> service = DataStoreService::Get(); - if (!service) { - return NS_ERROR_FAILURE; - } - - nsString id; - nsresult rv = service->GenerateUUID(mRevisionID); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - DataStoreRevisionData data; - data.mRevisionId = mRevisionID; - data.mObjectId = aObjectId; - - switch (aRevisionType) { - case RevisionVoid: - data.mOperation = NS_LITERAL_STRING("void"); - break; - - default: - MOZ_CRASH("This should not happen"); - } - - JS::Rooted<JS::Value> value(aCx); - if (!ToJSValue(aCx, data, &value)) { - return NS_ERROR_FAILURE; - } - - ErrorResult error; - mRequest = aStore->Put(aCx, value, JS::UndefinedHandleValue, error); - if (NS_WARN_IF(error.Failed())) { - return error.StealNSResult(); - } - - rv = mRequest->EventTarget::AddEventListener(NS_LITERAL_STRING("success"), - this, false); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - mCallback = aCallback; - return NS_OK; -} - -NS_IMETHODIMP -DataStoreRevision::HandleEvent(nsIDOMEvent* aEvent) -{ - nsString type; - nsresult rv = aEvent->GetType(type); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - if (!type.EqualsASCII("success")) { - MOZ_CRASH("This should not happen"); - } - - mRequest->RemoveEventListener(NS_LITERAL_STRING("success"), this, false); - mRequest = nullptr; - - mCallback->Run(mRevisionID); - return NS_OK; -} - -} // namespace dom -} // namespace mozilla
deleted file mode 100644 --- a/dom/datastore/DataStoreRevision.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_DataStoreRevision_h -#define mozilla_dom_DataStoreRevision_h - -#include "jsapi.h" -#include "nsAutoPtr.h" -#include "nsIDOMEventListener.h" -#include "nsString.h" - -namespace mozilla { -namespace dom { - -class DataStoreRevisionCallback; -class IDBObjectStore; -class IDBRequest; - -class DataStoreRevision final : public nsIDOMEventListener -{ -public: - NS_DECL_ISUPPORTS - - enum RevisionType { - RevisionVoid - }; - - nsresult AddRevision(JSContext* aCx, - IDBObjectStore* aStore, - uint32_t aObjectId, - RevisionType aRevisionType, - DataStoreRevisionCallback* aCallback); - - // nsIDOMEventListener - NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) override; - -private: - ~DataStoreRevision() {} - RefPtr<DataStoreRevisionCallback> mCallback; - RefPtr<IDBRequest> mRequest; - nsString mRevisionID; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_DataStoreRevision_h
deleted file mode 100644 --- a/dom/datastore/DataStoreService.cpp +++ /dev/null @@ -1,1522 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "DataStoreService.h" - -#include "DataStoreCallbacks.h" -#include "DataStoreDB.h" -#include "DataStoreRevision.h" -#include "mozilla/dom/DataStore.h" -#include "mozilla/dom/DataStoreBinding.h" -#include "mozilla/dom/DataStoreImplBinding.h" -#include "nsIDataStore.h" - -#include "mozilla/BasePrincipal.h" -#include "mozilla/Preferences.h" -#include "mozilla/Services.h" -#include "mozilla/StaticPtr.h" -#include "mozilla/dom/ContentChild.h" -#include "mozilla/dom/ContentParent.h" -#include "mozilla/dom/DOMError.h" -#include "mozilla/dom/IDBCursor.h" -#include "mozilla/dom/IDBObjectStore.h" -#include "mozilla/dom/IDBRequest.h" -#include "mozilla/dom/IDBTransaction.h" -#include "mozilla/dom/PermissionMessageUtils.h" -#include "mozilla/dom/Promise.h" -#include "mozilla/dom/ScriptSettings.h" -#include "mozilla/unused.h" - -#include "mozIApplication.h" -#include "mozIApplicationClearPrivateDataParams.h" -#include "nsIAppsService.h" -#include "nsIDOMEvent.h" -#include "nsIDocument.h" -#include "nsIDOMGlobalPropertyInitializer.h" -#include "nsIIOService.h" -#include "nsIMutableArray.h" -#include "nsIObserverService.h" -#include "nsIPermissionManager.h" -#include "nsIScriptSecurityManager.h" -#include "nsISupportsPrimitives.h" -#include "nsIUUIDGenerator.h" -#include "nsPIDOMWindow.h" -#include "nsIURI.h" - -#include "nsContentUtils.h" -#include "nsNetCID.h" -#include "nsServiceManagerUtils.h" -#include "nsThreadUtils.h" -#include "nsXULAppAPI.h" - -#define ASSERT_PARENT_PROCESS() \ - MOZ_ASSERT(XRE_IsParentProcess()); \ - if (NS_WARN_IF(!XRE_IsParentProcess())) { \ - return NS_ERROR_FAILURE; \ - } - -using mozilla::BasePrincipal; -using mozilla::PrincipalOriginAttributes; - -namespace mozilla { -namespace dom { - -// This class contains all the information about a DataStore. -class DataStoreInfo -{ -public: - DataStoreInfo() - : mReadOnly(true) - , mEnabled(false) - {} - - DataStoreInfo(const nsAString& aName, - const nsAString& aOriginURL, - const nsAString& aManifestURL, - bool aReadOnly, - bool aEnabled) - : mReadOnly(true) - , mEnabled(false) - { - Init(aName, aOriginURL, aManifestURL, aReadOnly, aEnabled); - } - - void Init(const nsAString& aName, - const nsAString& aOriginURL, - const nsAString& aManifestURL, - bool aReadOnly, - bool aEnabled) - { - mName = aName; - mOriginURL = aOriginURL; - mManifestURL = aManifestURL; - mReadOnly = aReadOnly; - mEnabled = aEnabled; - } - - void Update(const nsAString& aName, - const nsAString& aOriginURL, - const nsAString& aManifestURL, - bool aReadOnly) - { - mName = aName; - mOriginURL = aOriginURL; - mManifestURL = aManifestURL; - mReadOnly = aReadOnly; - } - - void Enable() - { - mEnabled = true; - } - - nsString mName; - nsString mOriginURL; - nsString mManifestURL; - bool mReadOnly; - - // A DataStore is enabled when it has its first revision. - bool mEnabled; -}; - -namespace { - -// Singleton for DataStoreService. -StaticRefPtr<DataStoreService> gDataStoreService; -nsString gHomeScreenManifestURL; -static uint64_t gCounterID = 0; - -typedef nsClassHashtable<nsUint32HashKey, DataStoreInfo> HashApp; - -void -RejectPromise(nsPIDOMWindowInner* aWindow, Promise* aPromise, nsresult aRv) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(NS_FAILED(aRv)); - - RefPtr<DOMError> error; - if (aRv == NS_ERROR_DOM_SECURITY_ERR) { - error = new DOMError(aWindow, NS_LITERAL_STRING("SecurityError"), - NS_LITERAL_STRING("Access denied")); - } else { - error = new DOMError(aWindow, NS_LITERAL_STRING("InternalError"), - NS_LITERAL_STRING("An error occurred")); - } - - aPromise->MaybeRejectBrokenly(error); -} - -void -DeleteDatabase(const nsAString& aName, - const nsAString& aManifestURL) -{ - MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread()); - - RefPtr<DataStoreDB> db = new DataStoreDB(aManifestURL, aName); - db->Delete(); -} - -static void -DeleteDataStoresHelper(nsClassHashtable<nsStringHashKey, HashApp>& aStores, - uint32_t aAppId) -{ - MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread()); - - for (auto iter1 = aStores.Iter(); !iter1.Done(); iter1.Next()) { - nsAutoPtr<HashApp>& apps = iter1.Data(); - for (auto iter2 = apps->Iter(); !iter2.Done(); iter2.Next()) { - if (aAppId == iter2.Key()) { - nsAutoPtr<DataStoreInfo>& info = iter2.Data(); - DeleteDatabase(info->mName, info->mManifestURL); - iter2.Remove(); - } - } - - if (apps->Count() == 0) { - iter1.Remove(); - } - } -} - -void -GeneratePermissionName(nsAString& aPermission, - const nsAString& aName, - const nsAString& aManifestURL) -{ - aPermission.AssignLiteral("indexedDB-chrome-"); - aPermission.Append(aName); - aPermission.Append('|'); - aPermission.Append(aManifestURL); -} - -nsresult -ResetPermission(uint32_t aAppId, const nsAString& aOriginURL, - const nsAString& aManifestURL, - const nsAString& aPermission, - bool aReadOnly) -{ - MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread()); - - nsresult rv; - nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - nsCOMPtr<nsIURI> uri; - rv = ioService->NewURI(NS_ConvertUTF16toUTF8(aOriginURL), nullptr, nullptr, - getter_AddRefs(uri)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - PrincipalOriginAttributes attrs(aAppId, false); - nsCOMPtr<nsIPrincipal> principal = - BasePrincipal::CreateCodebasePrincipal(uri, attrs); - NS_ENSURE_TRUE(principal, NS_ERROR_FAILURE); - - nsCOMPtr<nsIPermissionManager> pm = - do_GetService(NS_PERMISSIONMANAGER_CONTRACTID); - if (!pm) { - return NS_ERROR_FAILURE; - } - - nsCString basePermission; - basePermission.Append(NS_ConvertUTF16toUTF8(aPermission)); - - // Write permission - { - nsCString permission; - permission.Append(basePermission); - permission.AppendLiteral("-write"); - - uint32_t perm = nsIPermissionManager::UNKNOWN_ACTION; - rv = pm->TestExactPermissionFromPrincipal(principal, permission.get(), - &perm); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - if (aReadOnly && perm == nsIPermissionManager::ALLOW_ACTION) { - rv = pm->RemoveFromPrincipal(principal, permission.get()); - } - else if (!aReadOnly && perm != nsIPermissionManager::ALLOW_ACTION) { - rv = pm->AddFromPrincipal(principal, permission.get(), - nsIPermissionManager::ALLOW_ACTION, - nsIPermissionManager::EXPIRE_NEVER, 0); - } - - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - } - - // Read permission - { - nsCString permission; - permission.Append(basePermission); - permission.AppendLiteral("-read"); - - uint32_t perm = nsIPermissionManager::UNKNOWN_ACTION; - rv = pm->TestExactPermissionFromPrincipal(principal, permission.get(), - &perm); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - if (perm != nsIPermissionManager::ALLOW_ACTION) { - rv = pm->AddFromPrincipal(principal, permission.get(), - nsIPermissionManager::ALLOW_ACTION, - nsIPermissionManager::EXPIRE_NEVER, 0); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - } - } - - // Generic permission - uint32_t perm = nsIPermissionManager::UNKNOWN_ACTION; - rv = pm->TestExactPermissionFromPrincipal(principal, basePermission.get(), - &perm); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - if (perm != nsIPermissionManager::ALLOW_ACTION) { - rv = pm->AddFromPrincipal(principal, basePermission.get(), - nsIPermissionManager::ALLOW_ACTION, - nsIPermissionManager::EXPIRE_NEVER, 0); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - } - - return NS_OK; -} - -void -HomeScreenPrefCallback(const char* aPrefName, void* /* aClosure */) -{ - MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread()); - RefPtr<DataStoreService> service = DataStoreService::Get(); - if (!service) { - return; - } - - service->HomeScreenPrefChanged(); -} - -} /* anonymous namespace */ - -// A PendingRequest is created when a content code wants a list of DataStores -// but some of them are not enabled yet. -class PendingRequest -{ -public: - void Init(nsPIDOMWindowInner* aWindow, Promise* aPromise, - const nsTArray<DataStoreInfo>& aStores, - const nsTArray<nsString>& aPendingDataStores) - { - mWindow = aWindow; - mPromise = aPromise; - mStores = aStores; - mPendingDataStores = aPendingDataStores; - } - - nsCOMPtr<nsPIDOMWindowInner> mWindow; - RefPtr<Promise> mPromise; - nsTArray<DataStoreInfo> mStores; - - // This array contains the list of manifestURLs of the DataStores that are - // not enabled yet. - nsTArray<nsString> mPendingDataStores; -}; - -// This callback is used to enable a DataStore when its first revisionID is -// created. -class RevisionAddedEnableStoreCallback final : - public DataStoreRevisionCallback -{ -private: - ~RevisionAddedEnableStoreCallback() {} -public: - NS_INLINE_DECL_REFCOUNTING(RevisionAddedEnableStoreCallback); - - RevisionAddedEnableStoreCallback(uint32_t aAppId, - const nsAString& aName, - const nsAString& aManifestURL) - : mAppId(aAppId) - , mName(aName) - , mManifestURL(aManifestURL) - { - MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread()); - } - - void - Run(const nsAString& aRevisionId) - { - MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread()); - - RefPtr<DataStoreService> service = DataStoreService::Get(); - MOZ_ASSERT(service); - - service->EnableDataStore(mAppId, mName, mManifestURL); - } - -private: - uint32_t mAppId; - nsString mName; - nsString mManifestURL; -}; - -// This DataStoreDBCallback is called when DataStoreDB opens the DataStore DB. -// Then the first revision will be created if it's needed. -class FirstRevisionIdCallback final : public DataStoreDBCallback - , public nsIDOMEventListener -{ -public: - NS_DECL_ISUPPORTS - - FirstRevisionIdCallback(uint32_t aAppId, const nsAString& aName, - const nsAString& aManifestURL) - : mAppId(aAppId) - , mName(aName) - , mManifestURL(aManifestURL) - { - MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread()); - } - - void - Run(DataStoreDB* aDb, RunStatus aStatus) override - { - MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread()); - MOZ_ASSERT(aDb); - - if (aStatus == Error) { - NS_WARNING("Failed to create the first revision."); - return; - } - - ErrorResult error; - - if (aStatus == Success) { - mTxn = aDb->Transaction(); - - RefPtr<IDBObjectStore> store = - mTxn->ObjectStore(NS_LITERAL_STRING(DATASTOREDB_REVISION), error); - if (NS_WARN_IF(error.Failed())) { - return; - } - - AutoJSAPI jsapi; - jsapi.Init(); - mRequest = store->OpenCursor(jsapi.cx(), IDBCursorDirection::Prev, error); - if (NS_WARN_IF(error.Failed())) { - return; - } - - nsresult rv; - rv = mRequest->EventTarget::AddEventListener(NS_LITERAL_STRING("success"), - this, false); - if (NS_FAILED(rv)) { - NS_WARNING("Failed to add an EventListener."); - return; - } - - return; - } - - // The DB has just been created. - - error = CreateFirstRevision(aDb->Transaction()); - if (error.Failed()) { - NS_WARNING("Failed to add a revision to a DataStore."); - } - } - - nsresult - CreateFirstRevision(IDBTransaction* aTxn) - { - MOZ_ASSERT(aTxn); - - ErrorResult error; - RefPtr<IDBObjectStore> store = - aTxn->ObjectStore(NS_LITERAL_STRING(DATASTOREDB_REVISION), error); - if (NS_WARN_IF(error.Failed())) { - return error.StealNSResult(); - } - MOZ_ASSERT(store); - - RefPtr<RevisionAddedEnableStoreCallback> callback = - new RevisionAddedEnableStoreCallback(mAppId, mName, mManifestURL); - - // Note: this cx is only used for rooting and AddRevision, neither of which - // actually care which compartment we're in. - AutoSafeJSContext cx; - - // If the revision doesn't exist, let's create it. - RefPtr<DataStoreRevision> revision = new DataStoreRevision(); - nsresult rv = revision->AddRevision(cx, store, 0, - DataStoreRevision::RevisionVoid, - callback); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - return NS_OK; - } - - // nsIDOMEventListener - NS_IMETHOD - HandleEvent(nsIDOMEvent* aEvent) override - { - MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread()); - - RefPtr<IDBRequest> request; - request.swap(mRequest); - - RefPtr<IDBTransaction> txn; - txn.swap(mTxn); - - request->RemoveEventListener(NS_LITERAL_STRING("success"), this, false); - - nsString type; - nsresult rv = aEvent->GetType(type); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - -#ifdef DEBUG - MOZ_ASSERT(type.EqualsASCII("success")); -#endif - - ErrorResult error; - JS::Rooted<JS::Value> result(nsContentUtils::RootingCx()); - request->GetResult(&result, error); - if (NS_WARN_IF(error.Failed())) { - return error.StealNSResult(); - } - - // This means that the content is a IDBCursor, so the first revision already - // exists. - if (result.isObject()) { -#ifdef DEBUG - IDBCursor* cursor = nullptr; - error = UNWRAP_OBJECT(IDBCursor, &result.toObject(), cursor); - MOZ_ASSERT(!error.Failed()); -#endif - - RefPtr<DataStoreService> service = DataStoreService::Get(); - MOZ_ASSERT(service); - - return service->EnableDataStore(mAppId, mName, mManifestURL); - } - - rv = CreateFirstRevision(txn); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - return NS_OK; - } - -private: - ~FirstRevisionIdCallback() {} - - RefPtr<IDBRequest> mRequest; - RefPtr<IDBTransaction> mTxn; - - uint32_t mAppId; - nsString mName; - nsString mManifestURL; -}; - -NS_IMPL_ISUPPORTS(FirstRevisionIdCallback, nsIDOMEventListener) - -// This class calls the 'retrieveRevisionId' method of the DataStore object for -// any DataStore in the 'mResults' array. When all of them are called, the -// promise is resolved with 'mResults'. -// The reson why this has to be done is because DataStore are object that can be -// created in any thread and in any process. The first revision has been -// created, but they don't know its value yet. -class RetrieveRevisionsCounter -{ -private: - ~RetrieveRevisionsCounter() {} -public: - NS_INLINE_DECL_REFCOUNTING(RetrieveRevisionsCounter); - - RetrieveRevisionsCounter(uint32_t aId, Promise* aPromise, uint32_t aCount) - : mPromise(aPromise) - , mId(aId) - , mCount(aCount) - { - MOZ_ASSERT(NS_IsMainThread()); - } - - void - AppendDataStore(JSContext* aCx, DataStore* aDataStore, - nsIDataStore* aDataStoreIf) - { - MOZ_ASSERT(NS_IsMainThread()); - - mResults.AppendElement(aDataStore); - - // DataStore will run this callback when the revisionID is retrieved. - JSFunction* func = js::NewFunctionWithReserved(aCx, JSCallback, - 0 /* nargs */, 0 /* flags */, - nullptr); - if (!func) { - return; - } - - JS::Rooted<JSObject*> obj(aCx, JS_GetFunctionObject(func)); - if (!obj) { - return; - } - - // We use the ID to know which counter is this. The service keeps all of - // these counters alive with their own IDs in an hashtable. - js::SetFunctionNativeReserved(obj, 0, JS::Int32Value(mId)); - - JS::Rooted<JS::Value> value(aCx, JS::ObjectValue(*obj)); - nsresult rv = aDataStoreIf->RetrieveRevisionId(value); - if (NS_WARN_IF(NS_FAILED(rv))) { - return; - } - } - -private: - static bool - JSCallback(JSContext* aCx, unsigned aArgc, JS::Value* aVp) - { - MOZ_ASSERT(NS_IsMainThread()); - - JS::CallArgs args = CallArgsFromVp(aArgc, aVp); - - JS::Rooted<JS::Value> value(aCx, - js::GetFunctionNativeReserved(&args.callee(), 0)); - uint32_t id = value.toInt32(); - - RefPtr<DataStoreService> service = DataStoreService::Get(); - MOZ_ASSERT(service); - - RefPtr<RetrieveRevisionsCounter> counter = service->GetCounter(id); - MOZ_ASSERT(counter); - - // When all the callbacks are called, we can resolve the promise and remove - // the counter from the service. - --counter->mCount; - if (!counter->mCount) { - service->RemoveCounter(id); - counter->mPromise->MaybeResolve(counter->mResults); - } - - return true; - } - - RefPtr<Promise> mPromise; - nsTArray<RefPtr<DataStore>> mResults; - - uint32_t mId; - uint32_t mCount; -}; - -/* static */ already_AddRefed<DataStoreService> -DataStoreService::GetOrCreate() -{ - MOZ_ASSERT(NS_IsMainThread()); - - if (!gDataStoreService) { - RefPtr<DataStoreService> service = new DataStoreService(); - if (NS_WARN_IF(NS_FAILED(service->Init()))) { - return nullptr; - } - - gDataStoreService = service; - } - - RefPtr<DataStoreService> service = gDataStoreService.get(); - return service.forget(); -} - -/* static */ already_AddRefed<DataStoreService> -DataStoreService::Get() -{ - MOZ_ASSERT(NS_IsMainThread()); - - RefPtr<DataStoreService> service = gDataStoreService.get(); - return service.forget(); -} - -/* static */ void -DataStoreService::Shutdown() -{ - MOZ_ASSERT(NS_IsMainThread()); - - if (gDataStoreService) { - if (XRE_IsParentProcess()) { - nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); - if (obs) { - obs->RemoveObserver(gDataStoreService, "webapps-clear-data"); - } - - nsresult rv = - Preferences::UnregisterCallback(HomeScreenPrefCallback, - "dom.mozApps.homescreenURL", - nullptr); - NS_WARN_IF(NS_FAILED(rv)); - } - - gDataStoreService = nullptr; - } -} - -NS_INTERFACE_MAP_BEGIN(DataStoreService) - NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDataStoreService) - NS_INTERFACE_MAP_ENTRY(nsIDataStoreService) - NS_INTERFACE_MAP_ENTRY(nsIObserver) -NS_INTERFACE_MAP_END - -NS_IMPL_ADDREF(DataStoreService) -NS_IMPL_RELEASE(DataStoreService) - -DataStoreService::DataStoreService() -{ - MOZ_ASSERT(NS_IsMainThread()); -} - -DataStoreService::~DataStoreService() -{ - MOZ_ASSERT(NS_IsMainThread()); -} - -nsresult -DataStoreService::Init() -{ - if (!XRE_IsParentProcess()) { - return NS_OK; - } - - nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); - if (!obs) { - return NS_ERROR_FAILURE; - } - - nsresult rv = obs->AddObserver(this, "webapps-clear-data", false); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = Preferences::RegisterCallback(HomeScreenPrefCallback, - "dom.mozApps.homescreenURL", - nullptr); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - return NS_OK; -} - -NS_IMETHODIMP -DataStoreService::InstallDataStore(uint32_t aAppId, - const nsAString& aName, - const nsAString& aOriginURL, - const nsAString& aManifestURL, - bool aReadOnly) -{ - ASSERT_PARENT_PROCESS() - MOZ_ASSERT(NS_IsMainThread()); - - HashApp* apps = nullptr; - if (!mStores.Get(aName, &apps)) { - apps = new HashApp(); - mStores.Put(aName, apps); - } - - DataStoreInfo* info = nullptr; - if (!apps->Get(aAppId, &info)) { - info = new DataStoreInfo(aName, aOriginURL, aManifestURL, aReadOnly, false); - apps->Put(aAppId, info); - } else { - info->Update(aName, aOriginURL, aManifestURL, aReadOnly); - } - - nsresult rv = AddPermissions(aAppId, aName, aOriginURL, aManifestURL, - aReadOnly); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - // Immediately create the first revision. - return CreateFirstRevisionId(aAppId, aName, aManifestURL); -} - -NS_IMETHODIMP -DataStoreService::InstallAccessDataStore(uint32_t aAppId, - const nsAString& aName, - const nsAString& aOriginURL, - const nsAString& aManifestURL, - bool aReadOnly) -{ - ASSERT_PARENT_PROCESS() - MOZ_ASSERT(NS_IsMainThread()); - - HashApp* apps = nullptr; - if (!mAccessStores.Get(aName, &apps)) { - apps = new HashApp(); - mAccessStores.Put(aName, apps); - } - - DataStoreInfo* info = nullptr; - if (!apps->Get(aAppId, &info)) { - info = new DataStoreInfo(aName, aOriginURL, aManifestURL, aReadOnly, false); - apps->Put(aAppId, info); - } else { - info->Update(aName, aOriginURL, aManifestURL, aReadOnly); - } - - return AddAccessPermissions(aAppId, aName, aOriginURL, aManifestURL, - aReadOnly); -} - -NS_IMETHODIMP -DataStoreService::GetDataStores(mozIDOMWindow* aWindow, - const nsAString& aName, - const nsAString& aOwner, - nsISupports** aDataStores) -{ - // FIXME This will be a thread-safe method. - MOZ_ASSERT(NS_IsMainThread()); - - nsCOMPtr<nsPIDOMWindowInner> window = nsPIDOMWindowInner::From(aWindow); - if (!window) { - return NS_ERROR_FAILURE; - } - - nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(window); - ErrorResult rv; - RefPtr<Promise> promise = Promise::Create(global, rv); - if (rv.Failed()) { - return rv.StealNSResult(); - } - - nsCOMPtr<nsIDocument> document = window->GetDoc(); - MOZ_ASSERT(document); - - nsCOMPtr<nsIPrincipal> principal = document->NodePrincipal(); - MOZ_ASSERT(principal); - - nsTArray<DataStoreInfo> stores; - - // If this request comes from the main process, we have access to the - // window, so we can skip the ipc communication. - if (XRE_IsParentProcess()) { - uint32_t appId; - rv = principal->GetAppId(&appId); - if (NS_WARN_IF(rv.Failed())) { - RejectPromise(window, promise, rv.StealNSResult()); - promise.forget(aDataStores); - return NS_OK; - } - - rv = GetDataStoreInfos(aName, aOwner, appId, principal, stores); - if (NS_WARN_IF(rv.Failed())) { - RejectPromise(window, promise, rv.StealNSResult()); - promise.forget(aDataStores); - return NS_OK; - } - } else { - // This method can be called in the child so we need to send a request - // to the parent and create DataStore object here. - ContentChild* contentChild = ContentChild::GetSingleton(); - - nsTArray<DataStoreSetting> array; - if (!contentChild->SendDataStoreGetStores(nsAutoString(aName), - nsAutoString(aOwner), - IPC::Principal(principal), - &array)) { - RejectPromise(window, promise, NS_ERROR_FAILURE); - promise.forget(aDataStores); - return NS_OK; - } - - for (uint32_t i = 0; i < array.Length(); ++i) { - DataStoreInfo* info = stores.AppendElement(); - info->Init(array[i].name(), array[i].originURL(), - array[i].manifestURL(), array[i].readOnly(), - array[i].enabled()); - } - } - - GetDataStoresCreate(window, promise, stores); - promise.forget(aDataStores); - return NS_OK; -} - -void -DataStoreService::GetDataStoresCreate(nsPIDOMWindowInner* aWindow, - Promise* aPromise, - const nsTArray<DataStoreInfo>& aStores) -{ - MOZ_ASSERT(NS_IsMainThread()); - - if (!aStores.Length()) { - GetDataStoresResolve(aWindow, aPromise, aStores); - return; - } - - nsTArray<nsString> pendingDataStores; - for (uint32_t i = 0; i < aStores.Length(); ++i) { - if (!aStores[i].mEnabled) { - pendingDataStores.AppendElement(aStores[i].mManifestURL); - } - } - - if (!pendingDataStores.Length()) { - GetDataStoresResolve(aWindow, aPromise, aStores); - return; - } - - PendingRequests* requests; - if (!mPendingRequests.Get(aStores[0].mName, &requests)) { - requests = new PendingRequests(); - mPendingRequests.Put(aStores[0].mName, requests); - } - - PendingRequest* request = requests->AppendElement(); - request->Init(aWindow, aPromise, aStores, pendingDataStores); -} - -void -DataStoreService::GetDataStoresResolve(nsPIDOMWindowInner* aWindow, - Promise* aPromise, - const nsTArray<DataStoreInfo>& aStores) -{ - MOZ_ASSERT(NS_IsMainThread()); - - if (!aStores.Length()) { - nsTArray<RefPtr<DataStore>> results; - aPromise->MaybeResolve(results); - return; - } - - AutoSafeJSContext cx; - - // The counter will finish this task once all the DataStores will know their - // first revision Ids. - RefPtr<RetrieveRevisionsCounter> counter = - new RetrieveRevisionsCounter(++gCounterID, aPromise, aStores.Length()); - mPendingCounters.Put(gCounterID, counter); - - for (uint32_t i = 0; i < aStores.Length(); ++i) { - nsCOMPtr<nsIDataStore> dataStore = - do_CreateInstance("@mozilla.org/dom/datastore;1"); - if (NS_WARN_IF(!dataStore)) { - return; - } - - nsresult rv = dataStore->Init(aWindow, aStores[i].mName, - aStores[i].mManifestURL, - aStores[i].mReadOnly); - if (NS_WARN_IF(NS_FAILED(rv))) { - return; - } - - nsCOMPtr<nsIXPConnectWrappedJS> xpcwrappedjs = do_QueryInterface(dataStore); - if (NS_WARN_IF(!xpcwrappedjs)) { - return; - } - - JS::Rooted<JSObject*> dataStoreJS(cx, xpcwrappedjs->GetJSObject()); - if (NS_WARN_IF(!dataStoreJS)) { - return; - } - - nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aWindow); - MOZ_ASSERT(global); - - JSAutoCompartment ac(cx, dataStoreJS); - RefPtr<DataStoreImpl> dataStoreObj = new DataStoreImpl(dataStoreJS, - global); - - RefPtr<DataStore> exposedStore = new DataStore(aWindow); - - ErrorResult error; - exposedStore->SetDataStoreImpl(*dataStoreObj, error); - if (error.Failed()) { - return; - } - - JS::Rooted<JS::Value> exposedObject(cx); - if (!GetOrCreateDOMReflector(cx, exposedStore, &exposedObject)) { - JS_ClearPendingException(cx); - return; - } - - dataStore->SetExposedObject(exposedObject); - - counter->AppendDataStore(cx, exposedStore, dataStore); - } -} - -// This method populates 'aStores' with the list of DataStores with 'aName' as -// name and available for this 'aAppId'. -nsresult -DataStoreService::GetDataStoreInfos(const nsAString& aName, - const nsAString& aOwner, - uint32_t aAppId, - nsIPrincipal* aPrincipal, - nsTArray<DataStoreInfo>& aStores) -{ - MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread()); - - nsCOMPtr<nsIAppsService> appsService = - do_GetService("@mozilla.org/AppsService;1"); - if (NS_WARN_IF(!appsService)) { - return NS_ERROR_FAILURE; - } - - nsCOMPtr<mozIApplication> app; - nsresult rv = appsService->GetAppByLocalId(aAppId, getter_AddRefs(app)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - if (!app) { - return NS_ERROR_DOM_SECURITY_ERR; - } - - if (!DataStoreService::CheckPermission(aPrincipal)) { - return NS_ERROR_DOM_SECURITY_ERR; - } - - aStores.Clear(); - - HashApp* apps = nullptr; - if (!mStores.Get(aName, &apps)) { - return NS_OK; - } - - DataStoreInfo* appsInfo = nullptr; - if (apps->Get(aAppId, &appsInfo) && - (aOwner.IsEmpty() || aOwner.Equals(appsInfo->mManifestURL))) { - DataStoreInfo* owned = aStores.AppendElement(); - owned->Init(appsInfo->mName, appsInfo->mOriginURL, appsInfo->mManifestURL, - false, appsInfo->mEnabled); - } - - for (auto iter = apps->ConstIter(); !iter.Done(); iter.Next()) { - if (iter.Key() == aAppId) { - continue; - } - - DataStoreInfo* appInfo = iter.UserData(); - MOZ_ASSERT(appInfo); - - HashApp* accessApp; - if (!mAccessStores.Get(aName, &accessApp)) { - continue; - } - - if (!aOwner.IsEmpty() && - !aOwner.Equals(appInfo->mManifestURL)) { - continue; - } - - DataStoreInfo* accessInfo = nullptr; - if (!accessApp->Get(aAppId, &accessInfo)) { - continue; - } - - bool readOnly = appInfo->mReadOnly || accessInfo->mReadOnly; - DataStoreInfo* accessStore = aStores.AppendElement(); - accessStore->Init(aName, appInfo->mOriginURL, - appInfo->mManifestURL, readOnly, - appInfo->mEnabled); - } - - return NS_OK; -} - -NS_IMETHODIMP -DataStoreService::GetAppManifestURLsForDataStore(const nsAString& aName, - nsIArray** aManifestURLs) -{ - ASSERT_PARENT_PROCESS() - MOZ_ASSERT(NS_IsMainThread()); - - nsCOMPtr<nsIMutableArray> manifestURLs = do_CreateInstance(NS_ARRAY_CONTRACTID); - if (!manifestURLs) { - return NS_ERROR_OUT_OF_MEMORY; - } - - HashApp* apps = nullptr; - if (mStores.Get(aName, &apps)) { - for (auto iter = apps->ConstIter(); !iter.Done(); iter.Next()) { - nsCOMPtr<nsISupportsString> manifestURL(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID)); - if (manifestURL) { - manifestURL->SetData(iter.UserData()->mManifestURL); - manifestURLs->AppendElement(manifestURL, false); - } - } - } - if (mAccessStores.Get(aName, &apps)) { - for (auto iter = apps->ConstIter(); !iter.Done(); iter.Next()) { - nsCOMPtr<nsISupportsString> manifestURL(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID)); - if (manifestURL) { - manifestURL->SetData(iter.UserData()->mManifestURL); - manifestURLs->AppendElement(manifestURL, false); - } - } - } - - manifestURLs.forget(aManifestURLs); - return NS_OK; -} - -bool -DataStoreService::CheckPermission(nsIPrincipal* aPrincipal) -{ - // First of all, the general pref has to be turned on. - bool enabled = false; - Preferences::GetBool("dom.datastore.enabled", &enabled); - if (!enabled) { - return false; - } - - // Just for testing, we can enable DataStore for any kind of app. - if (Preferences::GetBool("dom.testing.datastore_enabled_for_hosted_apps", false)) { - return true; - } - - if (!aPrincipal) { - return false; - } - - uint16_t status; - if (NS_FAILED(aPrincipal->GetAppStatus(&status))) { - return false; - } - - // Certified apps are always allowed. - if (status == nsIPrincipal::APP_STATUS_CERTIFIED) { - return true; - } - - if (status != nsIPrincipal::APP_STATUS_PRIVILEGED) { - return false; - } - - // Privileged apps are allowed if they are the homescreen. - nsAdoptingString homescreen = - Preferences::GetString("dom.mozApps.homescreenURL"); - if (!homescreen) { - return false; - } - - uint32_t appId; - nsresult rv = aPrincipal->GetAppId(&appId); - if (NS_WARN_IF(NS_FAILED(rv))) { - return false; - } - - nsCOMPtr<nsIAppsService> appsService = - do_GetService("@mozilla.org/AppsService;1"); - if (NS_WARN_IF(!appsService)) { - return false; - } - - nsAutoString manifestURL; - rv = appsService->GetManifestURLByLocalId(appId, manifestURL); - if (NS_WARN_IF(NS_FAILED(rv))) { - return false; - } - - return manifestURL.Equals(homescreen); -} - -NS_IMETHODIMP -DataStoreService::CheckPermission(nsIPrincipal* aPrincipal, - bool* aResult) -{ - MOZ_ASSERT(NS_IsMainThread()); - - *aResult = DataStoreService::CheckPermission(aPrincipal); - - return NS_OK; -} - -// This method is called when an app with DataStores is deleted. -void -DataStoreService::DeleteDataStores(uint32_t aAppId) -{ - MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread()); - - DeleteDataStoresHelper(mStores, aAppId); - DeleteDataStoresHelper(mAccessStores, aAppId); -} - -NS_IMETHODIMP -DataStoreService::Observe(nsISupports* aSubject, - const char* aTopic, - const char16_t* aData) -{ - MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread()); - - if (strcmp(aTopic, "webapps-clear-data")) { - return NS_OK; - } - - nsCOMPtr<mozIApplicationClearPrivateDataParams> params = - do_QueryInterface(aSubject); - MOZ_ASSERT(params); - - // DataStore is explosed to apps, not browser content. - bool browserOnly; - nsresult rv = params->GetBrowserOnly(&browserOnly); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - if (browserOnly) { - return NS_OK; - } - - uint32_t appId; - rv = params->GetAppId(&appId); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - DeleteDataStores(appId); - - return NS_OK; -} - -nsresult -DataStoreService::AddPermissions(uint32_t aAppId, - const nsAString& aName, - const nsAString& aOriginURL, - const nsAString& aManifestURL, - bool aReadOnly) -{ - MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread()); - - // This is the permission name. - nsString permission; - GeneratePermissionName(permission, aName, aManifestURL); - - // When a new DataStore is installed, the permissions must be set for the - // owner app. - nsresult rv = ResetPermission(aAppId, aOriginURL, aManifestURL, permission, - aReadOnly); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - // For any app that wants to have access to this DataStore we add the - // permissions. - HashApp* apps; - if (!mAccessStores.Get(aName, &apps)) { - return NS_OK; - } - - for (auto iter = apps->ConstIter(); !iter.Done(); iter.Next()) { - DataStoreInfo* info = iter.UserData(); - MOZ_ASSERT(info); - - bool readOnly = aReadOnly || info->mReadOnly; - - rv = ResetPermission(iter.Key(), info->mOriginURL, - info->mManifestURL, - permission, readOnly); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - } - - return NS_OK; -} - -nsresult -DataStoreService::AddAccessPermissions(uint32_t aAppId, const nsAString& aName, - const nsAString& aOriginURL, - const nsAString& aManifestURL, - bool aReadOnly) -{ - MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread()); - - // When an app wants to have access to a DataStore, the permissions must be - // set. - HashApp* apps = nullptr; - if (!mStores.Get(aName, &apps)) { - return NS_OK; - } - - for (auto iter = apps->ConstIter(); !iter.Done(); iter.Next()) { - DataStoreInfo* info = iter.UserData(); - MOZ_ASSERT(info); - - nsAutoString permission; - GeneratePermissionName(permission, aName, info->mManifestURL); - - // ReadOnly is decided by the owner first. - bool readOnly = info->mReadOnly || aReadOnly; - - nsresult rv = ResetPermission(aAppId, aOriginURL, - info->mManifestURL, - permission, readOnly); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - } - - return NS_OK; -} - -// This method starts the operation to create the first revision for a DataStore -// if needed. -nsresult -DataStoreService::CreateFirstRevisionId(uint32_t aAppId, - const nsAString& aName, - const nsAString& aManifestURL) -{ - MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread()); - - RefPtr<DataStoreDB> db = new DataStoreDB(aManifestURL, aName); - - RefPtr<FirstRevisionIdCallback> callback = - new FirstRevisionIdCallback(aAppId, aName, aManifestURL); - - Sequence<nsString> dbs; - if (!dbs.AppendElement(NS_LITERAL_STRING(DATASTOREDB_REVISION), fallible)) { - return NS_ERROR_OUT_OF_MEMORY; - } - - return db->Open(IDBTransactionMode::Readwrite, dbs, callback); -} - -nsresult -DataStoreService::EnableDataStore(uint32_t aAppId, const nsAString& aName, - const nsAString& aManifestURL) -{ - MOZ_ASSERT(NS_IsMainThread()); - - { - HashApp* apps = nullptr; - DataStoreInfo* info = nullptr; - if (mStores.Get(aName, &apps) && apps->Get(aAppId, &info)) { - info->Enable(); - } - } - - // Notify the child processes. - if (XRE_IsParentProcess()) { - nsTArray<ContentParent*> children; - ContentParent::GetAll(children); - for (uint32_t i = 0; i < children.Length(); i++) { - if (children[i]->NeedsDataStoreInfos()) { - Unused << children[i]->SendDataStoreNotify(aAppId, nsAutoString(aName), - nsAutoString(aManifestURL)); - } - } - } - - // Maybe we have some pending request waiting for this DataStore. - PendingRequests* requests; - if (!mPendingRequests.Get(aName, &requests)) { - return NS_OK; - } - - for (uint32_t i = 0; i < requests->Length();) { - PendingRequest& request = requests->ElementAt(i); - nsTArray<nsString>::index_type pos = - request.mPendingDataStores.IndexOf(aManifestURL); - if (pos != request.mPendingDataStores.NoIndex) { - request.mPendingDataStores.RemoveElementAt(pos); - - // No other pending dataStores. - if (request.mPendingDataStores.IsEmpty()) { - GetDataStoresResolve(request.mWindow, request.mPromise, - request.mStores); - requests->RemoveElementAt(i); - continue; - } - } - - ++i; - } - - // No other pending requests for this name. - if (requests->IsEmpty()) { - mPendingRequests.Remove(aName); - } - - return NS_OK; -} - -already_AddRefed<RetrieveRevisionsCounter> -DataStoreService::GetCounter(uint32_t aId) const -{ - MOZ_ASSERT(NS_IsMainThread()); - - RefPtr<RetrieveRevisionsCounter> counter; - return mPendingCounters.Get(aId, getter_AddRefs(counter)) - ? counter.forget() : nullptr; -} - -void -DataStoreService::RemoveCounter(uint32_t aId) -{ - MOZ_ASSERT(NS_IsMainThread()); - mPendingCounters.Remove(aId); -} - -nsresult -DataStoreService::GetDataStoresFromIPC(const nsAString& aName, - const nsAString& aOwner, - nsIPrincipal* aPrincipal, - nsTArray<DataStoreSetting>* aValue) -{ - MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread()); - - uint32_t appId; - nsresult rv = aPrincipal->GetAppId(&appId); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - nsTArray<DataStoreInfo> stores; - rv = GetDataStoreInfos(aName, aOwner, appId, aPrincipal, stores); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - for (uint32_t i = 0; i < stores.Length(); ++i) { - DataStoreSetting* data = aValue->AppendElement(); - data->name() = stores[i].mName; - data->originURL() = stores[i].mOriginURL; - data->manifestURL() = stores[i].mManifestURL; - data->readOnly() = stores[i].mReadOnly; - data->enabled() = stores[i].mEnabled; - } - - return NS_OK; -} - -nsresult -DataStoreService::GenerateUUID(nsAString& aID) -{ - nsresult rv; - - if (!mUUIDGenerator) { - mUUIDGenerator = do_GetService("@mozilla.org/uuid-generator;1", &rv); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - } - - nsID id; - rv = mUUIDGenerator->GenerateUUIDInPlace(&id); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - char chars[NSID_LENGTH]; - id.ToProvidedString(chars); - CopyASCIItoUTF16(chars, aID); - - return NS_OK; -} - -void -DataStoreService::HomeScreenPrefChanged() -{ - MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread()); - - nsAdoptingString homescreen = - Preferences::GetString("dom.mozApps.homescreenURL"); - if (homescreen == gHomeScreenManifestURL) { - return; - } - - // Remove datastores of the old homescreen. - if (!gHomeScreenManifestURL.IsEmpty()) { - DeleteDataStoresIfNotAllowed(gHomeScreenManifestURL); - } - - gHomeScreenManifestURL = homescreen; - if (gHomeScreenManifestURL.IsEmpty()) { - return; - } - - // Add datastores for the new homescreen. - AddDataStoresIfAllowed(gHomeScreenManifestURL); -} - -void -DataStoreService::DeleteDataStoresIfNotAllowed(const nsAString& aManifestURL) -{ - nsCOMPtr<nsIAppsService> appsService = - do_GetService("@mozilla.org/AppsService;1"); - if (NS_WARN_IF(!appsService)) { - return; - } - - nsCOMPtr<mozIApplication> app; - nsresult rv = appsService->GetAppByManifestURL(aManifestURL, - getter_AddRefs(app)); - if (NS_WARN_IF(NS_FAILED(rv)) || !app) { - return; - } - - uint32_t localId; - rv = app->GetLocalId(&localId); - if (NS_WARN_IF(NS_FAILED(rv))) { - return; - } - - nsCOMPtr<nsIPrincipal> principal; - rv = app->GetPrincipal(getter_AddRefs(principal)); - - // We delete all the dataStores for this app here. - if (NS_WARN_IF(NS_FAILED(rv)) || !principal || - !CheckPermission(principal)) { - DeleteDataStores(localId); - } -} - -void -DataStoreService::AddDataStoresIfAllowed(const nsAString& aManifestURL) -{ - nsCOMPtr<nsIAppsService> appsService = - do_GetService("@mozilla.org/AppsService;1"); - if (NS_WARN_IF(!appsService)) { - return; - } - - nsCOMPtr<mozIApplication> app; - nsresult rv = appsService->GetAppByManifestURL(aManifestURL, - getter_AddRefs(app)); - if (NS_WARN_IF(NS_FAILED(rv)) || !app) { - return; - } - - uint32_t localId; - rv = app->GetLocalId(&localId); - if (NS_WARN_IF(NS_FAILED(rv))) { - return; - } - - rv = appsService->UpdateDataStoreEntriesFromLocalId(localId); - if (NS_WARN_IF(NS_FAILED(rv))) { - return; - } -} - -} // namespace dom -} // namespace mozilla
deleted file mode 100644 --- a/dom/datastore/DataStoreService.h +++ /dev/null @@ -1,119 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_DataStoreService_h -#define mozilla_dom_DataStoreService_h - -#include "mozilla/dom/PContent.h" -#include "nsClassHashtable.h" -#include "nsIDataStoreService.h" -#include "nsIObserver.h" -#include "nsRefPtrHashtable.h" - -class nsIPrincipal; -class nsIUUIDGenerator; -class nsPIDOMWindowInner; - -namespace mozilla { -namespace dom { - -class DataStoreInfo; -class FirstRevisionIdCallback; -class PendingRequest; -class Promise; -class RetrieveRevisionsCounter; -class RevisionAddedEnableStoreCallback; - -class DataStoreService final : public nsIDataStoreService - , public nsIObserver -{ - friend class ContentChild; - friend class FirstRevisionIdCallback; - friend class RetrieveRevisionsCounter; - friend class RevisionAddedEnableStoreCallback; - -public: - NS_DECL_ISUPPORTS - NS_DECL_NSIOBSERVER - NS_DECL_NSIDATASTORESERVICE - - // Returns the DataStoreService singleton. Only to be called from main - // thread. - static already_AddRefed<DataStoreService> GetOrCreate(); - - static already_AddRefed<DataStoreService> Get(); - - static void Shutdown(); - - static bool CheckPermission(nsIPrincipal* principal); - - nsresult GenerateUUID(nsAString& aID); - - nsresult GetDataStoresFromIPC(const nsAString& aName, - const nsAString& aOwner, - nsIPrincipal* aPrincipal, - nsTArray<DataStoreSetting>* aValue); - - void HomeScreenPrefChanged(); - -private: - DataStoreService(); - ~DataStoreService(); - - nsresult Init(); - - typedef nsClassHashtable<nsUint32HashKey, DataStoreInfo> HashApp; - - nsresult AddPermissions(uint32_t aAppId, const nsAString& aName, - const nsAString& aOriginURL, - const nsAString& aManifestURL, - bool aReadOnly); - - nsresult AddAccessPermissions(uint32_t aAppId, const nsAString& aName, - const nsAString& aOriginURL, - const nsAString& aManifestURL, - bool aReadOnly); - - nsresult CreateFirstRevisionId(uint32_t aAppId, const nsAString& aName, - const nsAString& aManifestURL); - - void GetDataStoresCreate(nsPIDOMWindowInner* aWindow, Promise* aPromise, - const nsTArray<DataStoreInfo>& aStores); - - void GetDataStoresResolve(nsPIDOMWindowInner* aWindow, Promise* aPromise, - const nsTArray<DataStoreInfo>& aStores); - - nsresult GetDataStoreInfos(const nsAString& aName, const nsAString& aOwner, - uint32_t aAppId, nsIPrincipal* aPrincipal, - nsTArray<DataStoreInfo>& aStores); - - void DeleteDataStores(uint32_t aAppId); - - nsresult EnableDataStore(uint32_t aAppId, const nsAString& aName, - const nsAString& aManifestURL); - - already_AddRefed<RetrieveRevisionsCounter> GetCounter(uint32_t aId) const; - - void RemoveCounter(uint32_t aId); - - void DeleteDataStoresIfNotAllowed(const nsAString& aManifestURL); - void AddDataStoresIfAllowed(const nsAString& aManifestURL); - - nsClassHashtable<nsStringHashKey, HashApp> mStores; - nsClassHashtable<nsStringHashKey, HashApp> mAccessStores; - - typedef nsTArray<PendingRequest> PendingRequests; - nsClassHashtable<nsStringHashKey, PendingRequests> mPendingRequests; - - nsRefPtrHashtable<nsUint32HashKey, RetrieveRevisionsCounter> mPendingCounters; - - nsCOMPtr<nsIUUIDGenerator> mUUIDGenerator; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_DataStoreService_h
deleted file mode 100644 --- a/dom/datastore/moz.build +++ /dev/null @@ -1,50 +0,0 @@ -# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -XPIDL_SOURCES += [ - 'nsIDataStore.idl', - 'nsIDataStoreService.idl', -] - -XPIDL_MODULE = 'dom_datastore' - -EXPORTS.mozilla.dom += [ - 'DataStore.h', - 'DataStoreCursor.h', - 'DataStoreService.h', -] - -UNIFIED_SOURCES += [ - 'DataStore.cpp', - 'DataStoreCursor.cpp', - 'DataStoreDB.cpp', - 'DataStoreRevision.cpp', - 'DataStoreService.cpp', -] - -LOCAL_INCLUDES += [ - '/js/xpconnect/wrappers', -] - -EXTRA_COMPONENTS += [ - 'DataStore.manifest', - 'DataStoreImpl.js', -] - -EXTRA_JS_MODULES += [ - 'DataStoreChangeNotifier.jsm', - 'DataStoreCursorImpl.jsm', - 'DataStoreDB.jsm', -] - -MOCHITEST_MANIFESTS += ['tests/mochitest.ini'] - -include('/ipc/chromium/chromium-config.mozbuild') - -FINAL_LIBRARY = 'xul' - -if CONFIG['GNU_CXX']: - CXXFLAGS += ['-Wshadow']
deleted file mode 100644 --- a/dom/datastore/nsIDataStore.idl +++ /dev/null @@ -1,23 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsISupports.idl" - -interface mozIDOMWindow; - -// NOTE: This is a temporary interface. -// It will be removed in the next patches for rewriting DataStore in C++. -[scriptable, uuid(14f4bae7-dd01-4d1d-81e1-f8fd1e463b5f)] -interface nsIDataStore : nsISupports -{ - void init(in mozIDOMWindow window, - in DOMString name, - in DOMString manifestURL, - in boolean readOnly); - - attribute jsval exposedObject; - - void retrieveRevisionId(in jsval cb); -};
deleted file mode 100644 --- a/dom/datastore/nsIDataStoreService.idl +++ /dev/null @@ -1,34 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsISupports.idl" - -interface mozIDOMWindow; -interface nsIPrincipal; -interface nsIArray; - -[scriptable, uuid(44a8de94-d3dd-4a3a-a582-41027d36ceb5)] -interface nsIDataStoreService : nsISupports -{ - void installDataStore(in unsigned long appId, - in DOMString name, - in DOMString originURL, - in DOMString manifestURL, - in boolean readOnly); - - void installAccessDataStore(in unsigned long appId, - in DOMString name, - in DOMString originURL, - in DOMString manifestURL, - in boolean readOnly); - - nsISupports getDataStores(in mozIDOMWindow window, - in DOMString name, - in DOMString owner); - - nsIArray getAppManifestURLsForDataStore(in DOMString name); - - boolean checkPermission(in nsIPrincipal principal); -};
deleted file mode 100644 --- a/dom/datastore/tests/file_app.sjs +++ /dev/null @@ -1,55 +0,0 @@ -var gBasePath = "tests/dom/datastore/tests/"; - -function handleRequest(request, response) { - var query = getQuery(request); - - var testToken = ''; - if ('testToken' in query) { - testToken = query.testToken; - } - - var template = 'file_app.template.webapp'; - if ('template' in query) { - template = query.template; - } - var template = gBasePath + template; - response.setHeader("Content-Type", "application/x-web-app-manifest+json", false); - response.write(readTemplate(template).replace(/TESTTOKEN/g, testToken)); -} - -// Copy-pasted incantations. There ought to be a better way to synchronously read -// a file into a string, but I guess we're trying to discourage that. -function readTemplate(path) { - var file = Components.classes["@mozilla.org/file/directory_service;1"]. - getService(Components.interfaces.nsIProperties). - get("CurWorkD", Components.interfaces.nsILocalFile); - var fis = Components.classes['@mozilla.org/network/file-input-stream;1']. - createInstance(Components.interfaces.nsIFileInputStream); - var cis = Components.classes["@mozilla.org/intl/converter-input-stream;1"]. - createInstance(Components.interfaces.nsIConverterInputStream); - var split = path.split("/"); - for(var i = 0; i < split.length; ++i) { - file.append(split[i]); - } - fis.init(file, -1, -1, false); - cis.init(fis, "UTF-8", 0, 0); - - var data = ""; - let str = {}; - let read = 0; - do { - read = cis.readString(0xffffffff, str); // read as much as we can and put it in str.value - data += str.value; - } while (read != 0); - cis.close(); - return data; -} - -function getQuery(request) { - var query = {}; - request.queryString.split('&').forEach(function (val) { - var [name, value] = val.split('='); - query[name] = unescape(value); - }); - return query; -}
deleted file mode 100644 --- a/dom/datastore/tests/file_app.template.webapp +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "Really Rapid Release (hosted)", - "description": "Updated even faster than <a href='http://mozilla.org'>Firefox</a>, just to annoy slashdotters.", - "launch_path": "/tests/dom/datastore/tests/TESTTOKEN",