mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-11 12:25:53 +00:00
Merge mozilla-central and mozilla-inbound
This commit is contained in:
commit
41186fd050
1
.hgtags
1
.hgtags
@ -69,3 +69,4 @@ a95d426422816513477e5863add1b00ac7041dcb AURORA_BASE_20110412
|
||||
5eb553dd2ceae5f88d80f27afc5ef3935c5d43b0 AURORA_BASE_20110705
|
||||
41b84b87c816403e1b74963d8094cff0406c989e AURORA_BASE_20110816
|
||||
c0983049bcaa9551e5f276d5a77ce154c151e0b0 AURORA_BASE_20110927
|
||||
462c726144bc1fb45b61e774f64ac5d61b4e047c UPDATE_PACKAGING_R15
|
||||
|
@ -4159,7 +4159,7 @@ var XULBrowserWindow = {
|
||||
startTime: 0,
|
||||
statusText: "",
|
||||
isBusy: false,
|
||||
inContentWhitelist: ["about:addons", "about:permissions"],
|
||||
inContentWhitelist: ["about:addons", "about:permissions", "about:sync-progress"],
|
||||
|
||||
QueryInterface: function (aIID) {
|
||||
if (aIID.equals(Ci.nsIWebProgressListener) ||
|
||||
|
72
browser/base/content/syncProgress.js
Normal file
72
browser/base/content/syncProgress.js
Normal file
@ -0,0 +1,72 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Firefox Sync.
|
||||
*
|
||||
* The Initial Developer of the Original Code is the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Allison Naaktgeboren <ally@mozilla.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://services-sync/main.js");
|
||||
|
||||
let gProgressBar;
|
||||
let gCounter = 0;
|
||||
|
||||
function onLoad(event) {
|
||||
Services.obs.addObserver(increaseProgressBar, "weave:engine:sync:finish", false);
|
||||
Services.obs.addObserver(increaseProgressBar, "weave:engine:sync:error", false);
|
||||
gProgressBar = document.getElementById('uploadProgressBar');
|
||||
|
||||
if (Services.prefs.getPrefType("services.sync.firstSync") != Ci.nsIPrefBranch.PREF_INVALID) {
|
||||
gProgressBar.max = Weave.Engines.getEnabled().length;
|
||||
gProgressBar.style.display = "inline";
|
||||
}
|
||||
else {
|
||||
gProgressBar.style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
function onUnload(event) {
|
||||
Services.obs.removeObserver(increaseProgressBar, "weave:engine:sync:finish");
|
||||
Services.obs.removeObserver(increaseProgressBar, "weave:engine:sync:error");
|
||||
}
|
||||
|
||||
function increaseProgressBar(){
|
||||
gCounter += 1;
|
||||
gProgressBar.setAttribute("value", gCounter);
|
||||
}
|
||||
|
||||
function closeTab() {
|
||||
window.close();
|
||||
}
|
86
browser/base/content/syncProgress.xhtml
Normal file
86
browser/base/content/syncProgress.xhtml
Normal file
@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License
|
||||
# Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is Firefox Sync.
|
||||
#
|
||||
# The Initial Developer of the Original Code is the Mozilla Foundation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2011
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Allison Naaktgeboren <ally@mozilla.com> (original author)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
<!DOCTYPE html [
|
||||
<!ENTITY % htmlDTD
|
||||
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"DTD/xhtml1-strict.dtd">
|
||||
%htmlDTD;
|
||||
<!ENTITY % syncProgressDTD
|
||||
SYSTEM "chrome://browser/locale/syncProgress.dtd">
|
||||
%syncProgressDTD;
|
||||
<!ENTITY % syncSetupDTD
|
||||
SYSTEM "chrome://browser/locale/syncSetup.dtd">
|
||||
%syncSetupDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>&syncProgress.pageTitle;</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" media="all"
|
||||
href="chrome://browser/skin/syncProgress.css"/>
|
||||
|
||||
<link rel="icon" type="image/png" id="favicon"
|
||||
href="chrome://browser/skin/sync-16.png"/>
|
||||
|
||||
<script type="text/javascript;version=1.8"
|
||||
src="chrome://browser/content/syncProgress.js"/>
|
||||
</head>
|
||||
<body onload="onLoad(event)" onunload="onUnload(event)">
|
||||
<title>&setup.successPage.title;</title>
|
||||
<div id="floatingBox" class="main-content">
|
||||
<div id="title">
|
||||
<h1>&setup.successPage.title;</h1>
|
||||
</div>
|
||||
<div id="successLogo">
|
||||
<img id="brandSyncLogo" src="chrome://browser/skin/sync-128.png" alt="&syncProgress.logoAltText;" />
|
||||
</div>
|
||||
<div id="loadingText">
|
||||
<p id="blurb">&syncProgress.textBlurb; </p>
|
||||
</div>
|
||||
<div id="progressBar">
|
||||
<progress id="uploadProgressBar" value="0"/>
|
||||
</div>
|
||||
<div id="bottomRow">
|
||||
<button id="closeButton" onclick="closeTab()">&syncProgress.closeButton; </button>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -24,6 +24,7 @@
|
||||
* Philipp von Weitershausen <philipp@weitershausen.de>
|
||||
* Paul O’Shannessy <paul@oshannessy.com>
|
||||
* Richard Newman <rnewman@mozilla.com>
|
||||
* Allison Naaktgeboren <ally@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -53,7 +54,6 @@ const EXISTING_ACCOUNT_CONNECT_PAGE = 3;
|
||||
const EXISTING_ACCOUNT_LOGIN_PAGE = 4;
|
||||
const OPTIONS_PAGE = 5;
|
||||
const OPTIONS_CONFIRM_PAGE = 6;
|
||||
const SETUP_SUCCESS_PAGE = 7;
|
||||
|
||||
// Broader than we'd like, but after this changed from api-secure.recaptcha.net
|
||||
// we had no choice. At least we only do this for the duration of setup.
|
||||
@ -411,6 +411,7 @@ var gSyncSetup = {
|
||||
this.checkFields();
|
||||
break;
|
||||
case EXISTING_ACCOUNT_CONNECT_PAGE:
|
||||
Weave.Svc.Prefs.set("firstSync", "existingAccount");
|
||||
this.wizard.getButton("next").hidden = false;
|
||||
this.wizard.getButton("back").hidden = false;
|
||||
this.wizard.getButton("extra1").hidden = false;
|
||||
@ -425,18 +426,6 @@ var gSyncSetup = {
|
||||
this.wizard.canRewind = true;
|
||||
this.checkFields();
|
||||
break;
|
||||
case SETUP_SUCCESS_PAGE:
|
||||
this.wizard.canRewind = false;
|
||||
this.wizard.canAdvance = true;
|
||||
this.wizard.getButton("back").hidden = true;
|
||||
this.wizard.getButton("next").hidden = true;
|
||||
this.wizard.getButton("cancel").hidden = true;
|
||||
this.wizard.getButton("finish").hidden = false;
|
||||
this._handleSuccess();
|
||||
if (this.wizardType == "pair") {
|
||||
this.completePairing();
|
||||
}
|
||||
break;
|
||||
case OPTIONS_PAGE:
|
||||
this.wizard.canRewind = false;
|
||||
this.wizard.canAdvance = true;
|
||||
@ -473,7 +462,7 @@ var gSyncSetup = {
|
||||
!Weave.Utils.ensureMPUnlocked()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
switch (this.wizard.pageIndex) {
|
||||
case PAIR_PAGE:
|
||||
this.startPairing();
|
||||
@ -519,7 +508,8 @@ var gSyncSetup = {
|
||||
Weave.Service.password = password;
|
||||
Weave.Service.passphrase = Weave.Utils.generatePassphrase();
|
||||
this._handleNoScript(false);
|
||||
this.wizard.pageIndex = SETUP_SUCCESS_PAGE;
|
||||
Weave.Svc.Prefs.set("firstSync", "newAccount");
|
||||
this.wizardFinish();
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -532,8 +522,9 @@ var gSyncSetup = {
|
||||
Weave.Service.password = document.getElementById("existingPassword").value;
|
||||
let pp = document.getElementById("existingPassphrase").value;
|
||||
Weave.Service.passphrase = Weave.Utils.normalizePassphrase(pp);
|
||||
if (Weave.Service.login())
|
||||
this.wizard.pageIndex = SETUP_SUCCESS_PAGE;
|
||||
if (Weave.Service.login()) {
|
||||
this.wizardFinish();
|
||||
}
|
||||
return false;
|
||||
case OPTIONS_PAGE:
|
||||
let desc = document.getElementById("mergeChoiceRadio").selectedIndex;
|
||||
@ -544,8 +535,7 @@ var gSyncSetup = {
|
||||
return this._handleChoice();
|
||||
case OPTIONS_CONFIRM_PAGE:
|
||||
if (this._resettingSync) {
|
||||
this.onWizardFinish();
|
||||
window.close();
|
||||
this.wizardFinish();
|
||||
return false;
|
||||
}
|
||||
return this.returnFromOptions();
|
||||
@ -580,9 +570,13 @@ var gSyncSetup = {
|
||||
return true;
|
||||
},
|
||||
|
||||
onWizardFinish: function () {
|
||||
wizardFinish: function () {
|
||||
this.setupInitialSync();
|
||||
|
||||
if (this.wizardType == "pair") {
|
||||
this.completePairing();
|
||||
}
|
||||
|
||||
if (!this._resettingSync) {
|
||||
function isChecked(element) {
|
||||
return document.getElementById(element).hasAttribute("checked");
|
||||
@ -598,22 +592,17 @@ var gSyncSetup = {
|
||||
|
||||
Weave.Service.persistLogin();
|
||||
Weave.Svc.Obs.notify("weave:service:setup-complete");
|
||||
if (this._settingUpNew)
|
||||
gSyncUtils.openFirstClientFirstrun();
|
||||
else
|
||||
gSyncUtils.openAddedClientFirstrun();
|
||||
|
||||
gSyncUtils.openFirstSyncProgressPage();
|
||||
}
|
||||
Weave.Utils.nextTick(Weave.Service.sync, Weave.Service);
|
||||
window.close();
|
||||
},
|
||||
|
||||
onWizardCancel: function () {
|
||||
if (this._resettingSync)
|
||||
return;
|
||||
|
||||
if (this.wizard.pageIndex == SETUP_SUCCESS_PAGE) {
|
||||
this.onWizardFinish();
|
||||
return;
|
||||
}
|
||||
this.abortEasySetup();
|
||||
this._handleNoScript(false);
|
||||
Weave.Service.startOver();
|
||||
@ -714,7 +703,7 @@ var gSyncSetup = {
|
||||
Weave.Service.password = credentials.password;
|
||||
Weave.Service.passphrase = credentials.synckey;
|
||||
Weave.Service.serverURL = credentials.serverURL;
|
||||
self.wizard.pageIndex = SETUP_SUCCESS_PAGE;
|
||||
gSyncSetup.wizardFinish();
|
||||
},
|
||||
|
||||
onAbort: function onAbort(error) {
|
||||
@ -906,25 +895,6 @@ var gSyncSetup = {
|
||||
return valid;
|
||||
},
|
||||
|
||||
_handleSuccess: function() {
|
||||
let self = this;
|
||||
function fill(id, string)
|
||||
document.getElementById(id).firstChild.nodeValue =
|
||||
string ? self._stringBundle.GetStringFromName(string) : "";
|
||||
|
||||
fill("firstSyncAction", "");
|
||||
fill("firstSyncActionWarning", "");
|
||||
if (this._settingUpNew) {
|
||||
fill("firstSyncAction", "newAccount.action.label");
|
||||
fill("firstSyncActionChange", "newAccount.change.label");
|
||||
return;
|
||||
}
|
||||
fill("firstSyncActionChange", "existingAccount.change.label");
|
||||
let action = document.getElementById("mergeChoiceRadio").selectedItem.id;
|
||||
let id = action == "resetClient" ? "firstSyncAction" : "firstSyncActionWarning";
|
||||
fill(id, action + ".change.label");
|
||||
},
|
||||
|
||||
_handleChoice: function () {
|
||||
let desc = document.getElementById("mergeChoiceRadio").selectedIndex;
|
||||
document.getElementById("chosenActionDeck").selectedIndex = desc;
|
||||
|
@ -25,6 +25,7 @@
|
||||
# Mike Connor <mconnor@mozilla.com>
|
||||
# Paul O’Shannessy <paul@oshannessy.com>
|
||||
# Philipp von Weitershausen <philipp@weitershausen.de>
|
||||
# Allison Naaktgeboren <ally@mozilla.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -60,7 +61,6 @@
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
onwizardnext="return gSyncSetup.onWizardAdvance()"
|
||||
onwizardback="return gSyncSetup.onWizardBack()"
|
||||
onwizardfinish="gSyncSetup.onWizardFinish()"
|
||||
onwizardcancel="gSyncSetup.onWizardCancel()"
|
||||
onload="gSyncSetup.init()">
|
||||
|
||||
@ -511,24 +511,11 @@
|
||||
</vbox>
|
||||
</deck>
|
||||
</wizardpage>
|
||||
|
||||
<wizardpage label="&setup.successPage.title;"
|
||||
id="successfulSetup"
|
||||
onextra1="gSyncSetup.onSyncOptions()"
|
||||
onpageshow="gSyncSetup.onPageShow()">
|
||||
<vbox align="center">
|
||||
<image id="successPageIcon"/>
|
||||
</vbox>
|
||||
<separator/>
|
||||
<description class="normal">
|
||||
<html:span id="firstSyncAction">replace me</html:span>
|
||||
<html:strong id="firstSyncActionWarning">replace me</html:strong>
|
||||
<html:span id="firstSyncActionChange">replace me</html:span>
|
||||
</description>
|
||||
<description>
|
||||
&continueUsing.label;
|
||||
</description>
|
||||
<separator flex="1"/>
|
||||
# In terms of the wizard flow shown to the user, the 'syncOptionsConfirm'
|
||||
# page above is not the last wizard page. To prevent the wizard binding from
|
||||
# assuming that it is, we're inserting this dummy page here. This also means
|
||||
# that the wizard needs to always be closed manually via wizardFinish().
|
||||
<wizardpage>
|
||||
</wizardpage>
|
||||
</wizard>
|
||||
|
||||
|
@ -109,17 +109,8 @@ let gSyncUtils = {
|
||||
this._openLink(Weave.Svc.Prefs.get("privacyURL"));
|
||||
},
|
||||
|
||||
// xxxmpc - fix domain before 1.3 final (bug 583652)
|
||||
_baseURL: "http://www.mozilla.com/firefox/sync/",
|
||||
|
||||
openFirstClientFirstrun: function () {
|
||||
let url = this._baseURL + "firstrun.html";
|
||||
this._openLink(url);
|
||||
},
|
||||
|
||||
openAddedClientFirstrun: function () {
|
||||
let url = this._baseURL + "secondrun.html";
|
||||
this._openLink(url);
|
||||
openFirstSyncProgressPage: function () {
|
||||
this._openLink("about:sync-progress");
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -245,6 +245,7 @@ _BROWSER_FILES = \
|
||||
test_wyciwyg_copying.html \
|
||||
authenticate.sjs \
|
||||
browser_minimize.js \
|
||||
browser_aboutSyncProgress.js \
|
||||
browser_middleMouse_inherit.js \
|
||||
$(NULL)
|
||||
|
||||
|
101
browser/base/content/test/browser_aboutSyncProgress.js
Normal file
101
browser/base/content/test/browser_aboutSyncProgress.js
Normal file
@ -0,0 +1,101 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://services-sync/main.js");
|
||||
|
||||
let gTests = [ {
|
||||
desc: "Makes sure the progress bar appears if firstSync pref is set",
|
||||
setup: function () {
|
||||
Services.prefs.setCharPref("services.sync.firstSync", "newAccount");
|
||||
},
|
||||
run: function () {
|
||||
let doc = gBrowser.selectedTab.linkedBrowser.contentDocument;
|
||||
let progressBar = doc.getElementById("uploadProgressBar");
|
||||
|
||||
isnot(progressBar.style.display, "none", "progress bar should be visible");
|
||||
executeSoon(runNextTest);
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Makes sure the progress bar is hidden if firstSync pref is not set",
|
||||
setup: function () {
|
||||
Services.prefs.clearUserPref("services.sync.firstSync");
|
||||
is(Services.prefs.getPrefType("services.sync.firstSync"),
|
||||
Ci.nsIPrefBranch.PREF_INVALID, "pref DNE" );
|
||||
},
|
||||
run: function () {
|
||||
let doc = gBrowser.selectedTab.linkedBrowser.contentDocument;
|
||||
let progressBar = doc.getElementById("uploadProgressBar");
|
||||
|
||||
is(progressBar.style.display, "none",
|
||||
"progress bar should not be visible");
|
||||
executeSoon(runNextTest);
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "Makes sure the observer updates are reflected in the progress bar",
|
||||
setup: function () {
|
||||
},
|
||||
run: function () {
|
||||
let doc = gBrowser.selectedTab.linkedBrowser.contentDocument;
|
||||
let progressBar = doc.getElementById("uploadProgressBar");
|
||||
|
||||
Services.obs.notifyObservers(null, "weave:engine:sync:finish", null);
|
||||
Services.obs.notifyObservers(null, "weave:engine:sync:error", null);
|
||||
|
||||
let received = progressBar.getAttribute("value");
|
||||
|
||||
is(received, 2, "progress bar received correct notifications");
|
||||
executeSoon(runNextTest);
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "Close button should close tab",
|
||||
setup: function (){
|
||||
},
|
||||
run: function () {
|
||||
function onTabClosed() {
|
||||
ok(true, "received TabClose notification");
|
||||
gBrowser.tabContainer.removeEventListener("TabClose", onTabClosed, false);
|
||||
executeSoon(runNextTest);
|
||||
}
|
||||
let doc = gBrowser.selectedTab.linkedBrowser.contentDocument;
|
||||
let button = doc.getElementById('closeButton');
|
||||
let window = doc.defaultView;
|
||||
gBrowser.tabContainer.addEventListener("TabClose", onTabClosed, false);
|
||||
EventUtils.sendMouseEvent({type: "click"}, button, window);
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
function test () {
|
||||
waitForExplicitFinish();
|
||||
executeSoon(runNextTest);
|
||||
}
|
||||
|
||||
function runNextTest()
|
||||
{
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
gBrowser.removeCurrentTab();
|
||||
}
|
||||
|
||||
if (gTests.length) {
|
||||
let test = gTests.shift();
|
||||
info(test.desc);
|
||||
test.setup();
|
||||
let tab = gBrowser.selectedTab = gBrowser.addTab("about:sync-progress");
|
||||
tab.linkedBrowser.addEventListener("load", function (event) {
|
||||
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
// Some part of the page is populated on load, so enqueue on it.
|
||||
executeSoon(test.run);
|
||||
}, true);
|
||||
}
|
||||
else {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
@ -71,6 +71,8 @@ browser.jar:
|
||||
* content/browser/syncQuota.xul (content/syncQuota.xul)
|
||||
content/browser/syncQuota.js (content/syncQuota.js)
|
||||
content/browser/syncUtils.js (content/syncUtils.js)
|
||||
content/browser/syncProgress.js (content/syncProgress.js)
|
||||
* content/browser/syncProgress.xhtml (content/syncProgress.xhtml)
|
||||
#endif
|
||||
# XXX: We should exclude this one as well (bug 71895)
|
||||
* content/browser/hiddenWindow.xul (content/hiddenWindow.xul)
|
||||
|
@ -97,6 +97,8 @@ static RedirEntry kRedirMap[] = {
|
||||
{ "sessionrestore", "chrome://browser/content/aboutSessionRestore.xhtml",
|
||||
nsIAboutModule::ALLOW_SCRIPT },
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
{ "sync-progress", "chrome://browser/content/syncProgress.xhtml",
|
||||
nsIAboutModule::ALLOW_SCRIPT },
|
||||
{ "sync-tabs", "chrome://browser/content/aboutSyncTabs.xul",
|
||||
nsIAboutModule::ALLOW_SCRIPT },
|
||||
#endif
|
||||
|
@ -156,6 +156,7 @@ static const mozilla::Module::ContractIDEntry kBrowserContracts[] = {
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "sessionrestore", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "sync-tabs", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "sync-progress", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
#endif
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "home", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "permissions", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
|
11
browser/locales/en-US/chrome/browser/syncProgress.dtd
Normal file
11
browser/locales/en-US/chrome/browser/syncProgress.dtd
Normal file
@ -0,0 +1,11 @@
|
||||
<!ENTITY % brandDTD
|
||||
SYSTEM "chrome://branding/locale/brand.dtd">
|
||||
%brandDTD;
|
||||
|
||||
<!-- These strings are used in the sync progress upload page -->
|
||||
<!ENTITY syncProgress.pageTitle "Your First Sync">
|
||||
<!ENTITY syncProgress.textBlurb "Your data is now being encrypted and uploaded in the background. You can close this tab and continue using &brandShortName;.">
|
||||
<!ENTITY syncProgress.closeButton "Close">
|
||||
<!ENTITY syncProgress.logoAltText "&brandShortName; logo">
|
||||
<!ENTITY syncProgress.diffText "&brandShortName; will now automatically sync in the background. You can close this tab and continue using &brandShortName;.">
|
||||
|
@ -9,6 +9,7 @@
|
||||
locale/browser/aboutHome.dtd (%chrome/browser/aboutHome.dtd)
|
||||
locale/browser/aboutSessionRestore.dtd (%chrome/browser/aboutSessionRestore.dtd)
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
locale/browser/syncProgress.dtd (%chrome/browser/syncProgress.dtd)
|
||||
locale/browser/aboutSyncTabs.dtd (%chrome/browser/aboutSyncTabs.dtd)
|
||||
#endif
|
||||
* locale/browser/browser.dtd (%chrome/browser/browser.dtd)
|
||||
|
@ -93,10 +93,12 @@ browser.jar:
|
||||
skin/classic/browser/sync-24-throbber.png
|
||||
skin/classic/browser/sync-32.png
|
||||
skin/classic/browser/sync-bg.png
|
||||
skin/classic/browser/sync-128.png
|
||||
skin/classic/browser/sync-desktopIcon.png
|
||||
skin/classic/browser/sync-mobileIcon.png
|
||||
skin/classic/browser/sync-notification-24.png
|
||||
skin/classic/browser/syncSetup.css
|
||||
skin/classic/browser/syncCommon.css
|
||||
skin/classic/browser/syncQuota.css
|
||||
skin/classic/browser/syncProgress.css
|
||||
#endif
|
||||
|
BIN
browser/themes/gnomestripe/browser/sync-128.png
Normal file
BIN
browser/themes/gnomestripe/browser/sync-128.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
79
browser/themes/gnomestripe/browser/syncProgress.css
Normal file
79
browser/themes/gnomestripe/browser/syncProgress.css
Normal file
@ -0,0 +1,79 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Firefox Sync.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Allison Naaktgeboren <ally@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
@import url(chrome://global/skin/inContentUI.css);
|
||||
|
||||
:root {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0 2em;
|
||||
}
|
||||
|
||||
#floatingBox {
|
||||
margin: 4em auto;
|
||||
max-width: 40em;
|
||||
min-width: 23em;
|
||||
padding: 1em 1.5em;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#successLogo {
|
||||
margin: 1em 2em;
|
||||
}
|
||||
|
||||
#loadingText {
|
||||
margin: 2em 6em;
|
||||
}
|
||||
|
||||
#progressBar {
|
||||
margin: 2em 10em;
|
||||
}
|
||||
|
||||
#uploadProgressBar{
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#bottomRow {
|
||||
margin-top: 2em;
|
||||
padding: 0;
|
||||
text-align: end;
|
||||
}
|
@ -131,12 +131,14 @@ browser.jar:
|
||||
skin/classic/browser/sync-16.png
|
||||
skin/classic/browser/sync-32.png
|
||||
skin/classic/browser/sync-bg.png
|
||||
skin/classic/browser/sync-128.png
|
||||
skin/classic/browser/sync-desktopIcon.png
|
||||
skin/classic/browser/sync-mobileIcon.png
|
||||
skin/classic/browser/sync-notification-24.png
|
||||
skin/classic/browser/syncSetup.css
|
||||
skin/classic/browser/syncCommon.css
|
||||
skin/classic/browser/syncQuota.css
|
||||
skin/classic/browser/syncProgress.css
|
||||
#endif
|
||||
skin/classic/browser/lion/keyhole-circle.png (keyhole-circle-lion.png)
|
||||
skin/classic/browser/lion/Toolbar.png (Toolbar-lion.png)
|
||||
|
BIN
browser/themes/pinstripe/browser/sync-128.png
Normal file
BIN
browser/themes/pinstripe/browser/sync-128.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
79
browser/themes/pinstripe/browser/syncProgress.css
Normal file
79
browser/themes/pinstripe/browser/syncProgress.css
Normal file
@ -0,0 +1,79 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Firefox Sync.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Allison Naaktgeboren <ally@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
@import url(chrome://global/skin/inContentUI.css);
|
||||
|
||||
:root {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0 2em;
|
||||
}
|
||||
|
||||
#floatingBox {
|
||||
margin: 4em auto;
|
||||
max-width: 40em;
|
||||
min-width: 23em;
|
||||
padding: 1em 1.5em;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#successLogo {
|
||||
margin: 1em 2em;
|
||||
}
|
||||
|
||||
#loadingText {
|
||||
margin: 2em 6em;
|
||||
}
|
||||
|
||||
#progressBar {
|
||||
margin: 2em 10em;
|
||||
}
|
||||
|
||||
#uploadProgressBar{
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#bottomRow {
|
||||
margin-top: 2em;
|
||||
padding: 0;
|
||||
text-align: end;
|
||||
}
|
@ -114,6 +114,7 @@ browser.jar:
|
||||
skin/classic/browser/sync-throbber.png
|
||||
skin/classic/browser/sync-16.png
|
||||
skin/classic/browser/sync-32.png
|
||||
skin/classic/browser/sync-128.png
|
||||
skin/classic/browser/sync-bg.png
|
||||
skin/classic/browser/sync-desktopIcon.png
|
||||
skin/classic/browser/sync-mobileIcon.png
|
||||
@ -121,6 +122,7 @@ browser.jar:
|
||||
skin/classic/browser/syncSetup.css
|
||||
skin/classic/browser/syncCommon.css
|
||||
skin/classic/browser/syncQuota.css
|
||||
skin/classic/browser/syncProgress.css
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
@ -238,6 +240,7 @@ browser.jar:
|
||||
skin/classic/aero/browser/sync-throbber.png
|
||||
skin/classic/aero/browser/sync-16.png
|
||||
skin/classic/aero/browser/sync-32.png
|
||||
skin/classic/aero/browser/sync-128.png
|
||||
skin/classic/aero/browser/sync-bg.png
|
||||
skin/classic/aero/browser/sync-desktopIcon.png
|
||||
skin/classic/aero/browser/sync-mobileIcon.png
|
||||
@ -245,5 +248,6 @@ browser.jar:
|
||||
skin/classic/aero/browser/syncSetup.css
|
||||
skin/classic/aero/browser/syncCommon.css
|
||||
skin/classic/aero/browser/syncQuota.css
|
||||
skin/classic/aero/browser/syncProgress.css
|
||||
#endif
|
||||
#endif
|
||||
|
BIN
browser/themes/winstripe/browser/sync-128.png
Normal file
BIN
browser/themes/winstripe/browser/sync-128.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
79
browser/themes/winstripe/browser/syncProgress.css
Normal file
79
browser/themes/winstripe/browser/syncProgress.css
Normal file
@ -0,0 +1,79 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Firefox Sync.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Allison Naaktgeboren <ally@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
@import url(chrome://global/skin/inContentUI.css);
|
||||
|
||||
:root {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0 2em;
|
||||
}
|
||||
|
||||
#floatingBox {
|
||||
margin: 4em auto;
|
||||
max-width: 40em;
|
||||
min-width: 23em;
|
||||
padding: 1em 1.5em;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#successLogo {
|
||||
margin: 1em 2em;
|
||||
}
|
||||
|
||||
#loadingText {
|
||||
margin: 2em 6em;
|
||||
}
|
||||
|
||||
#progressBar {
|
||||
margin: 2em 10em;
|
||||
}
|
||||
|
||||
#uploadProgressBar{
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#bottomRow {
|
||||
margin-top: 2em;
|
||||
padding: 0;
|
||||
text-align: end;
|
||||
}
|
@ -560,8 +560,8 @@ TransactionPoolEventTarget::Dispatch(nsIRunnable* aRunnable,
|
||||
NS_ASSERTION(aRunnable, "Null pointer!");
|
||||
NS_ASSERTION(aFlags == NS_DISPATCH_NORMAL, "Unsupported!");
|
||||
|
||||
TransactionThreadPool* pool = TransactionThreadPool::GetOrCreate();
|
||||
NS_ENSURE_TRUE(pool, NS_ERROR_FAILURE);
|
||||
TransactionThreadPool* pool = TransactionThreadPool::Get();
|
||||
NS_ASSERTION(pool, "This should never be null!");
|
||||
|
||||
return pool->Dispatch(mTransaction, aRunnable, false, nsnull);
|
||||
}
|
||||
|
@ -125,6 +125,11 @@ public:
|
||||
|
||||
static IDBTransaction* GetCurrentTransaction();
|
||||
|
||||
bool HasTransaction()
|
||||
{
|
||||
return mTransaction;
|
||||
}
|
||||
|
||||
nsISupports* GetSource()
|
||||
{
|
||||
return mRequest ? mRequest->Source() : nsnull;
|
||||
|
@ -85,7 +85,8 @@ EnumerateObjectStoreNames(const nsAString& aKey,
|
||||
DatabaseInfo::DatabaseInfo()
|
||||
: id(0),
|
||||
nextObjectStoreId(1),
|
||||
nextIndexId(1)
|
||||
nextIndexId(1),
|
||||
runningVersionChange(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(DatabaseInfo);
|
||||
}
|
||||
|
@ -54,7 +54,8 @@ struct DatabaseInfo
|
||||
~DatabaseInfo();
|
||||
#else
|
||||
DatabaseInfo()
|
||||
: id(0), nextObjectStoreId(1), nextIndexId(1) { }
|
||||
: id(0), nextObjectStoreId(1), nextIndexId(1), runningVersionChange(false)
|
||||
{ }
|
||||
#endif
|
||||
|
||||
static bool Get(PRUint32 aId,
|
||||
@ -73,6 +74,7 @@ struct DatabaseInfo
|
||||
nsString filePath;
|
||||
PRInt64 nextObjectStoreId;
|
||||
PRInt64 nextIndexId;
|
||||
bool runningVersionChange;
|
||||
|
||||
nsAutoRefCnt referenceCount;
|
||||
};
|
||||
|
@ -428,6 +428,34 @@ IDBDatabase::IsClosed()
|
||||
return mClosed;
|
||||
}
|
||||
|
||||
void
|
||||
IDBDatabase::EnterSetVersionTransaction()
|
||||
{
|
||||
DatabaseInfo* dbInfo;
|
||||
if (!DatabaseInfo::Get(mDatabaseId, &dbInfo)) {
|
||||
NS_ERROR("This should never fail!");
|
||||
}
|
||||
|
||||
NS_ASSERTION(!dbInfo->runningVersionChange, "How did that happen?");
|
||||
dbInfo->runningVersionChange = true;
|
||||
}
|
||||
|
||||
void
|
||||
IDBDatabase::ExitSetVersionTransaction()
|
||||
{
|
||||
DatabaseInfo* dbInfo;
|
||||
if (!DatabaseInfo::Get(mDatabaseId, &dbInfo)) {
|
||||
NS_ERROR("This should never fail!");
|
||||
}
|
||||
|
||||
NS_ASSERTION(dbInfo->runningVersionChange, "How did that happen?");
|
||||
dbInfo->runningVersionChange = false;
|
||||
|
||||
IndexedDatabaseManager* manager = IndexedDatabaseManager::Get();
|
||||
NS_ASSERTION(manager, "We should always have a manager here");
|
||||
manager->UnblockSetVersionRunnable(this);
|
||||
}
|
||||
|
||||
void
|
||||
IDBDatabase::OnUnlink()
|
||||
{
|
||||
@ -710,6 +738,10 @@ IDBDatabase::Transaction(nsIVariant* aStoreNames,
|
||||
NS_ERROR("This should never fail!");
|
||||
}
|
||||
|
||||
if (info->runningVersionChange) {
|
||||
return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
|
||||
}
|
||||
|
||||
nsTArray<nsString> storesToOpen;
|
||||
|
||||
switch (type) {
|
||||
|
@ -135,6 +135,9 @@ public:
|
||||
// Whether or not the database has had Close called on it.
|
||||
bool IsClosed();
|
||||
|
||||
void EnterSetVersionTransaction();
|
||||
void ExitSetVersionTransaction();
|
||||
|
||||
private:
|
||||
IDBDatabase();
|
||||
~IDBDatabase();
|
||||
|
@ -693,19 +693,15 @@ IndexedDatabaseManager::OnDatabaseClosed(IDBDatabase* aDatabase)
|
||||
|
||||
// Now run the helper if there are no more live databases.
|
||||
if (runnable->mHelper && runnable->mDatabases.IsEmpty()) {
|
||||
// Don't hold the callback alive longer than necessary.
|
||||
nsRefPtr<AsyncConnectionHelper> helper;
|
||||
helper.swap(runnable->mHelper);
|
||||
// At this point, all databases are closed, so no new transactions can
|
||||
// be started. There may, however, still be outstanding transactions
|
||||
// that have not completed. We need to wait for those before we
|
||||
// dispatch the helper.
|
||||
|
||||
if (NS_FAILED(helper->DispatchToTransactionPool())) {
|
||||
NS_WARNING("Failed to dispatch to thread pool!");
|
||||
}
|
||||
TransactionThreadPool* pool = TransactionThreadPool::GetOrCreate();
|
||||
|
||||
// Now wait for the transaction to complete. Completing the transaction
|
||||
// will be our cue to remove the SetVersionRunnable from our list and
|
||||
// therefore allow other SetVersion requests to begin.
|
||||
TransactionThreadPool* pool = TransactionThreadPool::Get();
|
||||
NS_ASSERTION(pool, "This should never be null!");
|
||||
nsRefPtr<WaitForTransactionsToFinishRunnable> waitRunnable =
|
||||
new WaitForTransactionsToFinishRunnable(runnable);
|
||||
|
||||
// All other databases should be closed, so we only need to wait on this
|
||||
// one.
|
||||
@ -714,8 +710,8 @@ IndexedDatabaseManager::OnDatabaseClosed(IDBDatabase* aDatabase)
|
||||
NS_ERROR("This should never fail!");
|
||||
}
|
||||
|
||||
// Use the SetVersionRunnable as the callback.
|
||||
if (!pool->WaitForAllDatabasesToComplete(array, runnable)) {
|
||||
// Use the WaitForTransactionsToFinishRunnable as the callback.
|
||||
if (!pool->WaitForAllDatabasesToComplete(array, waitRunnable)) {
|
||||
NS_WARNING("Failed to wait for transaction to complete!");
|
||||
}
|
||||
}
|
||||
@ -724,6 +720,27 @@ IndexedDatabaseManager::OnDatabaseClosed(IDBDatabase* aDatabase)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
IndexedDatabaseManager::UnblockSetVersionRunnable(IDBDatabase* aDatabase)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aDatabase, "Null pointer!");
|
||||
|
||||
// Check through the list of SetVersionRunnables to find the one we're seeking.
|
||||
for (PRUint32 index = 0; index < mSetVersionRunnables.Length(); index++) {
|
||||
nsRefPtr<SetVersionRunnable>& runnable = mSetVersionRunnables[index];
|
||||
|
||||
if (runnable->mRequestingDatabase->Id() == aDatabase->Id()) {
|
||||
NS_ASSERTION(!runnable->mHelper,
|
||||
"Why are we unblocking a runnable if the helper didn't run?");
|
||||
NS_DispatchToCurrentThread(runnable);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
NS_NOTREACHED("How did we get here!");
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
IndexedDatabaseManager::SetCurrentDatabase(IDBDatabase* aDatabase)
|
||||
@ -1283,3 +1300,39 @@ IndexedDatabaseManager::SetVersionRunnable::Run()
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(IndexedDatabaseManager::WaitForTransactionsToFinishRunnable,
|
||||
nsIRunnable)
|
||||
|
||||
NS_IMETHODIMP
|
||||
IndexedDatabaseManager::WaitForTransactionsToFinishRunnable::Run()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
// Don't hold the callback alive longer than necessary.
|
||||
nsRefPtr<AsyncConnectionHelper> helper;
|
||||
helper.swap(mRunnable->mHelper);
|
||||
|
||||
nsRefPtr<SetVersionRunnable> runnable;
|
||||
runnable.swap(mRunnable);
|
||||
|
||||
// If the helper has a transaction, dispatch it to the transaction
|
||||
// threadpool.
|
||||
if (helper->HasTransaction()) {
|
||||
if (NS_FAILED(helper->DispatchToTransactionPool())) {
|
||||
NS_WARNING("Failed to dispatch to thread pool!");
|
||||
}
|
||||
}
|
||||
// Otherwise, dispatch it to the IO thread.
|
||||
else {
|
||||
IndexedDatabaseManager* manager = IndexedDatabaseManager::Get();
|
||||
NS_ASSERTION(manager, "We should definitely have a manager here");
|
||||
|
||||
helper->Dispatch(manager->IOThread());
|
||||
}
|
||||
|
||||
// The helper is responsible for calling
|
||||
// IndexedDatabaseManager::UnblockSetVersionRunnable.
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -204,6 +204,8 @@ private:
|
||||
// Called when AsyncUsageRunnable has finished its Run() method.
|
||||
inline void OnUsageCheckComplete(AsyncUsageRunnable* aRunnable);
|
||||
|
||||
void UnblockSetVersionRunnable(IDBDatabase* aDatabase);
|
||||
|
||||
// Responsible for waiting until all databases have been closed before running
|
||||
// the version change transaction. Created when
|
||||
// IndexedDatabaseManager::SetDatabaseVersion is called. Runs only once on the
|
||||
@ -227,6 +229,26 @@ private:
|
||||
// Called when SetVersionRunnable has finished its Run() method.
|
||||
inline void OnSetVersionRunnableComplete(SetVersionRunnable* aRunnable);
|
||||
|
||||
|
||||
// A callback runnable used by the TransactionPool when it's safe to proceed
|
||||
// with a SetVersion/DeleteDatabase/etc.
|
||||
class WaitForTransactionsToFinishRunnable : public nsIRunnable
|
||||
{
|
||||
public:
|
||||
WaitForTransactionsToFinishRunnable(SetVersionRunnable* aRunnable)
|
||||
: mRunnable(aRunnable)
|
||||
{
|
||||
NS_ASSERTION(mRunnable, "Why don't we have a runnable?");
|
||||
NS_ASSERTION(mRunnable->mDatabases.IsEmpty(), "We're here too early!");
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
private:
|
||||
nsRefPtr<SetVersionRunnable> mRunnable;
|
||||
};
|
||||
|
||||
// Maintains a list of live databases per origin.
|
||||
nsClassHashtable<nsCStringHashKey, nsTArray<IDBDatabase*> > mLiveDatabases;
|
||||
|
||||
|
@ -495,10 +495,13 @@ public:
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
nsresult DoDatabaseWork(mozIStorageConnection* aConnection);
|
||||
nsresult GetSuccessResult(JSContext* aCx,
|
||||
jsval* aVal);
|
||||
|
||||
protected:
|
||||
nsresult DoDatabaseWork(mozIStorageConnection* aConnection);
|
||||
nsresult Init();
|
||||
|
||||
// SetVersionHelper never fires an error event at the request. It hands that
|
||||
// responsibility back to the OpenDatabaseHelper
|
||||
void OnError() { }
|
||||
@ -554,6 +557,8 @@ OpenDatabaseHelper::DoDatabaseWork()
|
||||
}
|
||||
#endif
|
||||
|
||||
mState = eFiringEvents; // In case we fail somewhere along the line.
|
||||
|
||||
if (IndexedDatabaseManager::IsShuttingDown()) {
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
@ -646,9 +651,10 @@ OpenDatabaseHelper::DoDatabaseWork()
|
||||
return NS_ERROR_DOM_INDEXEDDB_VERSION_ERR;
|
||||
}
|
||||
|
||||
mState = mCurrentVersion != mRequestedVersion ?
|
||||
eSetVersionPending :
|
||||
eFiringEvents;
|
||||
if (mCurrentVersion != mRequestedVersion) {
|
||||
mState = eSetVersionPending;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -684,6 +690,7 @@ OpenDatabaseHelper::StartSetVersion()
|
||||
// The SetVersionHelper is responsible for dispatching us back to the
|
||||
// main thread again and changing the state to eSetVersionCompleted.
|
||||
mState = eSetVersionPending;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -711,6 +718,12 @@ OpenDatabaseHelper::Run()
|
||||
mState == eSetVersionCompleted, "Why are we here?");
|
||||
|
||||
if (mState == eSetVersionCompleted) {
|
||||
// Allow transaction creation/other version change transactions to proceed
|
||||
// before we fire events. Other version changes will be postd to the end
|
||||
// of the event loop, and will be behind whatever the page does in
|
||||
// its error/success event handlers.
|
||||
mDatabase->ExitSetVersionTransaction();
|
||||
|
||||
mState = eFiringEvents;
|
||||
} else {
|
||||
// Notify the request that we're done, but only if we didn't just finish
|
||||
@ -865,6 +878,15 @@ OpenDatabaseHelper::NotifySetVersionFinished()
|
||||
return NS_DispatchToCurrentThread(this);
|
||||
}
|
||||
|
||||
void
|
||||
OpenDatabaseHelper::BlockDatabase()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(mDatabase, "This is going bad fast.");
|
||||
|
||||
mDatabase->EnterSetVersionTransaction();
|
||||
}
|
||||
|
||||
void
|
||||
OpenDatabaseHelper::DispatchSuccessEvent()
|
||||
{
|
||||
@ -916,6 +938,15 @@ OpenDatabaseHelper::ReleaseMainThreadObjects()
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(SetVersionHelper, AsyncConnectionHelper);
|
||||
|
||||
nsresult
|
||||
SetVersionHelper::Init()
|
||||
{
|
||||
// Block transaction creation until we are done.
|
||||
mOpenHelper->BlockDatabase();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SetVersionHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||
{
|
||||
|
@ -82,6 +82,7 @@ public:
|
||||
}
|
||||
|
||||
nsresult NotifySetVersionFinished();
|
||||
void BlockDatabase();
|
||||
|
||||
protected:
|
||||
// Methods only called on the main thread
|
||||
|
@ -238,7 +238,6 @@ TransactionThreadPool::FinishTransaction(IDBTransaction* aTransaction)
|
||||
|
||||
#ifdef DEBUG
|
||||
if (aTransaction->mMode == IDBTransaction::VERSION_CHANGE) {
|
||||
NS_ASSERTION(dbTransactionInfo->locked, "Should be locked!");
|
||||
NS_ASSERTION(transactionCount == 1,
|
||||
"More transactions running than should be!");
|
||||
}
|
||||
@ -344,10 +343,6 @@ TransactionThreadPool::TransactionCanRun(IDBTransaction* aTransaction,
|
||||
PRUint32 transactionCount = transactionsInProgress.Length();
|
||||
NS_ASSERTION(transactionCount, "Should never be 0!");
|
||||
|
||||
if (mode == IDBTransaction::VERSION_CHANGE) {
|
||||
dbTransactionInfo->lockPending = true;
|
||||
}
|
||||
|
||||
for (PRUint32 index = 0; index < transactionCount; index++) {
|
||||
// See if this transaction is in out list of current transactions.
|
||||
const TransactionInfo& info = transactionsInProgress[index];
|
||||
@ -358,11 +353,7 @@ TransactionThreadPool::TransactionCanRun(IDBTransaction* aTransaction,
|
||||
}
|
||||
}
|
||||
|
||||
if (dbTransactionInfo->locked || dbTransactionInfo->lockPending) {
|
||||
*aCanRun = false;
|
||||
*aExistingQueue = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_ASSERTION(mode != IDBTransaction::VERSION_CHANGE, "How did we get here?");
|
||||
|
||||
bool writeOverlap;
|
||||
nsresult rv =
|
||||
@ -448,11 +439,6 @@ TransactionThreadPool::Dispatch(IDBTransaction* aTransaction,
|
||||
dbTransactionInfo = autoDBTransactionInfo;
|
||||
}
|
||||
|
||||
if (aTransaction->mMode == IDBTransaction::VERSION_CHANGE) {
|
||||
NS_ASSERTION(!dbTransactionInfo->locked, "Already locked?!");
|
||||
dbTransactionInfo->locked = true;
|
||||
}
|
||||
|
||||
const nsTArray<nsString>& objectStoreNames = aTransaction->mObjectStoreNames;
|
||||
|
||||
nsTArray<nsString>& storesInUse =
|
||||
|
@ -123,12 +123,6 @@ protected:
|
||||
|
||||
struct DatabaseTransactionInfo
|
||||
{
|
||||
DatabaseTransactionInfo()
|
||||
: locked(false), lockPending(false)
|
||||
{ }
|
||||
|
||||
bool locked;
|
||||
bool lockPending;
|
||||
nsTArray<TransactionInfo> transactions;
|
||||
nsTArray<nsString> storesReading;
|
||||
nsTArray<nsString> storesWriting;
|
||||
|
@ -98,6 +98,7 @@ TEST_FILES = \
|
||||
test_setVersion.html \
|
||||
test_setVersion_abort.html \
|
||||
test_setVersion_events.html \
|
||||
test_setVersion_exclusion.html \
|
||||
test_writer_starvation.html \
|
||||
third_party_iframe1.html \
|
||||
third_party_iframe2.html \
|
||||
|
@ -69,6 +69,9 @@
|
||||
|
||||
db.createObjectStore("foo", { autoIncrement: true });
|
||||
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
yield;
|
||||
|
||||
setTimeout(testFinishedCallback, 0, "ready");
|
||||
yield;
|
||||
}
|
||||
|
@ -104,7 +104,7 @@
|
||||
db.onerror = errorEventCounter;
|
||||
db.addEventListener("error", errorEventCounter, true);
|
||||
|
||||
event.target.transaction.oncomplete = grabEventAndContinueHandler;
|
||||
event.target.onsuccess = grabEventAndContinueHandler;
|
||||
|
||||
db.createObjectStore("foo", { autoIncrement: true });
|
||||
yield;
|
||||
|
@ -12,7 +12,7 @@ function startDBWork() {
|
||||
}
|
||||
var store = db.createObjectStore("mystore");
|
||||
store.add({ hello: "world" }, 42);
|
||||
trans.oncomplete = madeMod;
|
||||
e.target.onsuccess = madeMod;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,9 @@
|
||||
|
||||
let key = event.target.result;
|
||||
ok(key, "Added entry");
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
|
||||
event = yield;
|
||||
|
||||
let objectStore = db.transaction("foo").objectStore("foo");
|
||||
let first = objectStore.index("first");
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
let db = request.result;
|
||||
|
||||
event.target.transaction.oncomplete = continueToNextStep;
|
||||
event.target.onsuccess = continueToNextStep;
|
||||
|
||||
let objectStore = db.createObjectStore("foo", { autoIncrement: true });
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
let db = event.target.result;
|
||||
db.onerror = errorHandler;
|
||||
|
||||
event.target.transaction.oncomplete = continueToNextStep;
|
||||
event.target.onsuccess = continueToNextStep;
|
||||
|
||||
// Make object store, add data.
|
||||
let objectStore = db.createObjectStore("foo", { keyPath: "id" });
|
||||
@ -39,7 +39,7 @@
|
||||
let db2 = event.target.result;
|
||||
db2.onerror = errorHandler;
|
||||
|
||||
event.target.transaction.oncomplete = continueToNextStep;
|
||||
event.target.onsuccess = continueToNextStep;
|
||||
|
||||
// Create index.
|
||||
event.target.transaction.objectStore("foo").createIndex("foo", "num");
|
||||
|
@ -35,7 +35,7 @@
|
||||
let event = yield;
|
||||
|
||||
let db = event.target.result;
|
||||
event.target.transaction.oncomplete = continueToNextStep;
|
||||
event.target.onsuccess = continueToNextStep;
|
||||
|
||||
let objectStore = db.createObjectStore("foo", { keyPath: "ss" });
|
||||
objectStore.createIndex("name", "name", { unique: true });
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
let objectStore = db.createObjectStore("foo", { autoIncrement: true });
|
||||
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
request = objectStore.getAll();
|
||||
request.onerror = errorHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
@ -46,6 +47,7 @@
|
||||
}
|
||||
}
|
||||
yield;
|
||||
yield;
|
||||
|
||||
request = db.transaction("foo").objectStore("foo").getAll();
|
||||
request.onerror = errorHandler;
|
||||
|
@ -60,6 +60,7 @@
|
||||
let request = mozIndexedDB.open(name, 1, description);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
let event = yield;
|
||||
|
||||
let db = event.target.result;
|
||||
@ -78,7 +79,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
event = yield;
|
||||
yield;
|
||||
ok(true, "1");
|
||||
|
||||
// Now create the indexes.
|
||||
@ -88,7 +89,6 @@
|
||||
}
|
||||
|
||||
is(objectStore.indexNames.length, indexData.length, "Good index count");
|
||||
continueToNextStep();
|
||||
yield;
|
||||
|
||||
ok(true, "2");
|
||||
|
@ -60,6 +60,7 @@
|
||||
let request = mozIndexedDB.open(name, 1, description);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
let event = yield;
|
||||
|
||||
let db = event.target.result;
|
||||
@ -87,7 +88,6 @@
|
||||
}
|
||||
|
||||
is(objectStore.indexNames.length, indexData.length, "Good index count");
|
||||
continueToNextStep();
|
||||
yield;
|
||||
|
||||
objectStore = db.transaction(objectStoreName)
|
||||
|
@ -37,7 +37,7 @@
|
||||
let db = event.target.result;
|
||||
db.onerror = errorHandler;
|
||||
|
||||
event.target.transaction.oncomplete = continueToNextStep;
|
||||
event.target.onsuccess = continueToNextStep;
|
||||
|
||||
for (let objectStoreIndex in objectStoreData) {
|
||||
const objectStoreInfo = objectStoreData[objectStoreIndex];
|
||||
|
@ -71,6 +71,7 @@
|
||||
let request = mozIndexedDB.open(name, 1, description);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
let event = yield;
|
||||
|
||||
let db = event.target.result;
|
||||
@ -97,7 +98,6 @@
|
||||
indexData[i].options);
|
||||
}
|
||||
is(objectStore.indexNames.length, indexData.length, "Good index count");
|
||||
continueToNextStep();
|
||||
yield;
|
||||
|
||||
objectStore = db.transaction(objectStoreName)
|
||||
|
@ -51,6 +51,7 @@
|
||||
let request = mozIndexedDB.open(name, 1, description);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
let event = yield;
|
||||
|
||||
let db = event.target.result;
|
||||
@ -87,6 +88,7 @@
|
||||
}
|
||||
}
|
||||
yield;
|
||||
yield;
|
||||
|
||||
objectStore = db.transaction(objectStoreName)
|
||||
.objectStore(objectStoreName);
|
||||
|
@ -28,7 +28,7 @@
|
||||
let index2 = objectStore2.index("bar");
|
||||
ok(index1 === index2, "Got same indexes");
|
||||
|
||||
transaction.oncomplete = continueToNextStep;
|
||||
request.onsuccess = continueToNextStep;
|
||||
yield;
|
||||
|
||||
transaction = db.transaction("foo");
|
||||
|
@ -29,7 +29,7 @@
|
||||
autoIncrement: true });
|
||||
let index = objectStore.createIndex("foo", "index");
|
||||
|
||||
event.target.transaction.oncomplete = continueToNextStep;
|
||||
event.target.onsuccess = continueToNextStep;
|
||||
yield;
|
||||
|
||||
objectStore = db.transaction("foo", IDBTransaction.READ_WRITE)
|
||||
|
@ -20,6 +20,7 @@
|
||||
let request = mozIndexedDB.open(name, 1, description);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
let event = yield;
|
||||
|
||||
let db = event.target.result;
|
||||
@ -31,7 +32,6 @@
|
||||
is(db.objectStoreNames.length, 1, "Bad objectStores list");
|
||||
is(db.objectStoreNames.item(0), objectStoreName, "Bad name");
|
||||
|
||||
continueToNextStep();
|
||||
yield;
|
||||
|
||||
objectStore = db.transaction(objectStoreName).objectStore(objectStoreName);
|
||||
|
@ -26,7 +26,7 @@
|
||||
let db = event.target.result;
|
||||
is(db.objectStoreNames.length, 0, "Correct objectStoreNames list");
|
||||
|
||||
event.target.transaction.oncomplete = grabEventAndContinueHandler;
|
||||
event.target.onsuccess = grabEventAndContinueHandler;
|
||||
for (let i in objectStores) {
|
||||
db.createObjectStore(objectStores[i], { autoIncrement: true });
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
let request = mozIndexedDB.open(name, 1, description);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
let event = yield;
|
||||
|
||||
let db = event.target.result;
|
||||
@ -29,6 +30,8 @@
|
||||
|
||||
db.createObjectStore(osName, { autoIncrement: "true" });
|
||||
|
||||
yield;
|
||||
|
||||
let key1, key2;
|
||||
|
||||
request = db.transaction([osName], READ_WRITE)
|
||||
|
90
dom/indexedDB/test/test_setVersion_exclusion.html
Normal file
90
dom/indexedDB/test/test_setVersion_exclusion.html
Normal file
@ -0,0 +1,90 @@
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Indexed Database Property Test</title>
|
||||
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
|
||||
<script type="text/javascript;version=1.7">
|
||||
function testSteps()
|
||||
{
|
||||
const name = window.location.pathname;
|
||||
|
||||
let request = mozIndexedDB.open(name, 1);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
|
||||
let request2 = mozIndexedDB.open(name, 2);
|
||||
request2.onerror = errorHandler;
|
||||
request2.onupgradeneeded = unexpectedSuccessHandler;
|
||||
|
||||
let event = yield;
|
||||
is(event.type, "upgradeneeded", "Expect an upgradeneeded event");
|
||||
is(event.target, request, "Event should be fired on the request");
|
||||
ok(event.target.result instanceof IDBDatabase, "Expect a database here");
|
||||
|
||||
let db = event.target.result;
|
||||
is(db.version, 1, "Database has correct version");
|
||||
|
||||
db.onupgradeneeded = function() {
|
||||
ok(false, "our ongoing VERSION_CHANGE transaction should exclude any others!");
|
||||
}
|
||||
|
||||
db.createObjectStore("foo");
|
||||
|
||||
try {
|
||||
db.transaction("foo");
|
||||
ok(false, "Transactions should be disallowed now!");
|
||||
} catch (e) {
|
||||
ok(e instanceof IDBDatabaseException, "Expect an IDBException");
|
||||
is(e.code, IDBDatabaseException.NOT_ALLOWED_ERR, "Expect a NOT_ALLOWED_ERR");
|
||||
}
|
||||
|
||||
request.transaction.oncomplete = grabEventAndContinueHandler;
|
||||
|
||||
yield;
|
||||
|
||||
// The database is still not fully open here.
|
||||
try {
|
||||
db.transaction("foo");
|
||||
ok(false, "Transactions should be disallowed now!");
|
||||
} catch (e) {
|
||||
ok(e instanceof IDBDatabaseException, "Expect an IDBException");
|
||||
is(e.code, IDBDatabaseException.NOT_ALLOWED_ERR, "Expect a NOT_ALLOWED_ERR");
|
||||
}
|
||||
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
|
||||
yield;
|
||||
|
||||
db.onversionchange = function() {
|
||||
ok(true, "next setVersion was unblocked appropriately");
|
||||
db.close();
|
||||
}
|
||||
|
||||
try {
|
||||
db.transaction("foo");
|
||||
ok(true, "Transactions should be allowed now!");
|
||||
} catch (e) {
|
||||
ok(false, "Transactions should be allowed now!");
|
||||
}
|
||||
|
||||
request2.onupgradeneeded = null;
|
||||
|
||||
finishTest();
|
||||
yield;
|
||||
}
|
||||
|
||||
</script>
|
||||
<script type="text/javascript;version=1.7" src="helpers.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body onload="runTest();"></body>
|
||||
|
||||
</html>
|
@ -19,7 +19,7 @@
|
||||
|
||||
let db = event.target.result;
|
||||
|
||||
event.target.transaction.oncomplete = continueToNextStep;
|
||||
event.target.onsuccess = continueToNextStep;
|
||||
|
||||
let objectStore = db.createObjectStore("foo");
|
||||
objectStore.add({}, 1).onerror = errorHandler;
|
||||
|
@ -29,6 +29,7 @@
|
||||
let request = mozIndexedDB.open(name, 1, description);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
let event = yield;
|
||||
|
||||
let db = event.target.result;
|
||||
@ -157,6 +158,8 @@
|
||||
ok(true, "RemoveIndex threw");
|
||||
}
|
||||
|
||||
yield;
|
||||
|
||||
request = db.transaction("foo", READ_WRITE).objectStore("foo").add({});
|
||||
request.onerror = errorHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
|
@ -20,7 +20,7 @@
|
||||
let db = event.target.result;
|
||||
db.onerror = errorHandler;
|
||||
|
||||
event.target.transaction.oncomplete = continueToNextStep;
|
||||
event.target.onsuccess = continueToNextStep;
|
||||
|
||||
db.createObjectStore("foo", { autoIncrement: true });
|
||||
yield;
|
||||
|
@ -20,7 +20,7 @@
|
||||
let db = event.target.result;
|
||||
db.onerror = errorHandler;
|
||||
|
||||
event.target.transaction.oncomplete = continueToNextStep;
|
||||
event.target.onsuccess = continueToNextStep;
|
||||
db.createObjectStore("foo");
|
||||
yield;
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
let request = mozIndexedDB.open(name, 1, description);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
let event = yield;
|
||||
|
||||
let db = event.target.result;
|
||||
@ -39,7 +40,6 @@
|
||||
let key = event.target.result;
|
||||
ok(key, "Got a key");
|
||||
|
||||
SimpleTest.executeSoon(function() { testGenerator.next(); });
|
||||
yield;
|
||||
|
||||
let continueReading = true;
|
||||
|
@ -6043,7 +6043,17 @@ PresShell::HandleEvent(nsIView *aView,
|
||||
// still get sent to the window properly if nothing is focused or if a
|
||||
// frame goes away while it is focused.
|
||||
if (!eventTarget || !eventTarget->GetPrimaryFrame()) {
|
||||
eventTarget = mDocument->GetRootElement();
|
||||
nsCOMPtr<nsIDOMHTMLDocument> htmlDoc = do_QueryInterface(mDocument);
|
||||
if (htmlDoc) {
|
||||
nsCOMPtr<nsIDOMHTMLElement> body;
|
||||
htmlDoc->GetBody(getter_AddRefs(body));
|
||||
eventTarget = do_QueryInterface(body);
|
||||
if (!eventTarget) {
|
||||
eventTarget = mDocument->GetRootElement();
|
||||
}
|
||||
} else {
|
||||
eventTarget = mDocument->GetRootElement();
|
||||
}
|
||||
}
|
||||
|
||||
if (aEvent->message == NS_KEY_DOWN) {
|
||||
|
@ -346,6 +346,7 @@ _TEST_FILES += \
|
||||
test_bug607529.html \
|
||||
file_bug607529.html \
|
||||
test_bug644768.html \
|
||||
test_bug696020.html \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
|
47
layout/base/tests/test_bug696020.html
Normal file
47
layout/base/tests/test_bug696020.html
Normal file
@ -0,0 +1,47 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=696020
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 696020</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=696020">Mozilla Bug 696020</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 696020 **/
|
||||
|
||||
|
||||
function startTest() {
|
||||
var testFrame = document.getElementById("tf").contentWindow;
|
||||
testFrame.focus();
|
||||
var didHandleKeyEvent = false;
|
||||
testFrame.addEventListener("keypress",
|
||||
function(e) {
|
||||
is(e.target, testFrame.document.body,
|
||||
"Body element should be event target for key events!");
|
||||
didHandleKeyEvent = true;
|
||||
});
|
||||
synthesizeKey("A", {}, testFrame);
|
||||
ok(didHandleKeyEvent, "Should have handled a key event!");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(startTest)
|
||||
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
<iframe id="tf"></iframe>
|
||||
</body>
|
||||
</html>
|
@ -103,7 +103,10 @@ class TPSTestRunner(object):
|
||||
'services.sync.log.appender.console': 'Trace',
|
||||
'services.sync.log.appender.debugLog.enabled': True,
|
||||
'browser.dom.window.dump.enabled': True,
|
||||
'extensions.checkCompatibility.4.0': False,
|
||||
# Allow installing extensions dropped into the profile folder
|
||||
'extensions.autoDisableScopes': 10,
|
||||
# Don't open a dialog to show available add-on updates
|
||||
'extensions.update.notifyUser' : False,
|
||||
}
|
||||
syncVerRe = re.compile(
|
||||
r"Sync version: (?P<syncversion>.*)\n")
|
||||
|
@ -25,7 +25,7 @@ function test()
|
||||
|
||||
function onKey(aEvent)
|
||||
{
|
||||
if (aEvent.target != root) {
|
||||
if (aEvent.target != root && aEvent.target != root.ownerDocument.body) {
|
||||
ok(false, "unknown target: " + aEvent.target.tagName);
|
||||
return;
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
*
|
||||
* Contributor(s):
|
||||
* Blair McBride <bmcbride@mozilla.com>
|
||||
* Philipp von Weitershausen <philipp@weitershausen.de>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -35,11 +36,16 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* The default namespace for this file is XUL. Be sure to prefix rules that
|
||||
* are applicable to both XUL and HTML with '*|'.
|
||||
*/
|
||||
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
|
||||
@namespace html url("http://www.w3.org/1999/xhtml");
|
||||
|
||||
|
||||
/* Page background */
|
||||
:root {
|
||||
*|*:root {
|
||||
-moz-appearance: none;
|
||||
padding: 18px;
|
||||
background-color: Window;
|
||||
@ -48,8 +54,12 @@
|
||||
color: WindowText;
|
||||
}
|
||||
|
||||
html|html {
|
||||
font: message-box;
|
||||
}
|
||||
|
||||
/* Content */
|
||||
.main-content {
|
||||
*|*.main-content {
|
||||
/* Needed to allow the radius to clip the inner content, see bug 595656 */
|
||||
/* Disabled because of bug 623615
|
||||
overflow: hidden;
|
||||
|
@ -20,6 +20,7 @@
|
||||
*
|
||||
* Contributor(s):
|
||||
* Blair McBride <bmcbride@mozilla.com>
|
||||
* Philipp von Weitershausen <philipp@weitershausen.de>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -37,11 +38,15 @@
|
||||
|
||||
%include shared.inc
|
||||
|
||||
/*
|
||||
* The default namespace for this file is XUL. Be sure to prefix rules that
|
||||
* are applicable to both XUL and HTML with '*|'.
|
||||
*/
|
||||
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
|
||||
@namespace html url("http://www.w3.org/1999/xhtml");
|
||||
|
||||
/* Page background */
|
||||
:root {
|
||||
*|*:root {
|
||||
-moz-appearance: none;
|
||||
padding: 18px;
|
||||
background-image: /* Texture */
|
||||
@ -50,8 +55,12 @@
|
||||
-moz-linear-gradient(top, #ADB5C2, #BFC6D1);
|
||||
}
|
||||
|
||||
html|html {
|
||||
font: message-box;
|
||||
}
|
||||
|
||||
/* Content */
|
||||
.main-content {
|
||||
*|*.main-content {
|
||||
/* Needed to allow the radius to clip the inner content, see bug 595656 */
|
||||
/* Disabled because of bug 623615
|
||||
overflow: hidden;
|
||||
@ -62,7 +71,7 @@
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
button,
|
||||
*|button,
|
||||
menulist,
|
||||
colorpicker[type="button"] {
|
||||
-moz-appearance: none;
|
||||
@ -84,6 +93,7 @@ colorpicker[type="button"]:-moz-focusring:not([open="true"]) > .colorpicker-butt
|
||||
outline: 1px dotted #252F3B;
|
||||
}
|
||||
|
||||
html|button[disabled],
|
||||
button[disabled="true"],
|
||||
menulist[disabled="true"],
|
||||
colorpicker[type="button"][disabled="true"] {
|
||||
@ -91,6 +101,7 @@ colorpicker[type="button"][disabled="true"] {
|
||||
color: #505050;
|
||||
}
|
||||
|
||||
html|button:not([disabled]):active:hover,
|
||||
button:not([disabled="true"]):active:hover,
|
||||
menulist[open="true"]:not([disabled="true"]),
|
||||
colorpicker[type="button"][open="true"]:not([disabled="true"]) {
|
||||
|
@ -20,6 +20,7 @@
|
||||
*
|
||||
* Contributor(s):
|
||||
* Blair McBride <bmcbride@mozilla.com>
|
||||
* Philipp von Weitershausen <philipp@weitershausen.de>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -35,10 +36,15 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* The default namespace for this file is XUL. Be sure to prefix rules that
|
||||
* are applicable to both XUL and HTML with '*|'.
|
||||
*/
|
||||
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
|
||||
@namespace html url("http://www.w3.org/1999/xhtml");
|
||||
|
||||
/* Page background */
|
||||
:root {
|
||||
*|*:root {
|
||||
-moz-appearance: none;
|
||||
padding: 18px;
|
||||
background-repeat: repeat;
|
||||
@ -50,9 +56,13 @@
|
||||
url("chrome://global/skin/inContentUI/background-texture.png");
|
||||
}
|
||||
|
||||
html|html {
|
||||
font: message-box;
|
||||
}
|
||||
|
||||
%ifdef WINSTRIPE_AERO
|
||||
@media all and (-moz-windows-default-theme) {
|
||||
:root {
|
||||
*|*:root {
|
||||
color: #000;
|
||||
background-color: #CCD9EA;
|
||||
background-image: /* Fade-out texture at the top */
|
||||
@ -63,7 +73,7 @@
|
||||
}
|
||||
|
||||
@media all and (-moz-windows-compositor) {
|
||||
:root {
|
||||
*|*:root {
|
||||
color: #000;
|
||||
/* Blame shorlander for this monstrosity. */
|
||||
background-image: /* Fade-out texture and light beams at the top */
|
||||
@ -93,7 +103,7 @@
|
||||
%endif
|
||||
|
||||
/* Content */
|
||||
.main-content {
|
||||
*|*.main-content {
|
||||
/* Needed to allow the radius to clip the inner content, see bug 595656 */
|
||||
/* Disabled because of bug 623615
|
||||
overflow: hidden;
|
||||
@ -109,7 +119,7 @@
|
||||
%ifdef WINSTRIPE_AERO
|
||||
@media all and (-moz-windows-compositor) {
|
||||
/* Buttons */
|
||||
button,
|
||||
*|button,
|
||||
menulist,
|
||||
colorpicker[type="button"] {
|
||||
-moz-appearance: none;
|
||||
@ -133,6 +143,7 @@
|
||||
outline: 1px dotted ThreeDDarkShadow;
|
||||
}
|
||||
|
||||
html|button[disabled],
|
||||
button[disabled="true"],
|
||||
menulist[disabled="true"],
|
||||
colorpicker[type="button"][disabled="true"] {
|
||||
@ -144,6 +155,7 @@
|
||||
color: #505050;
|
||||
}
|
||||
|
||||
html|button:not([disabled]):active:hover,
|
||||
button:not([disabled="true"]):active:hover,
|
||||
menulist[open="true"]:not([disabled="true"]),
|
||||
colorpicker[type="button"][open="true"]:not([disabled="true"]) {
|
||||
|
@ -148,59 +148,6 @@ typedef NTSTATUS (NTAPI *LdrLoadDll_func) (PWCHAR filePath, PULONG flags, PUNICO
|
||||
|
||||
static LdrLoadDll_func stub_LdrLoadDll = 0;
|
||||
|
||||
namespace {
|
||||
|
||||
template <class T>
|
||||
struct RVAMap {
|
||||
RVAMap(HANDLE map, unsigned offset) {
|
||||
mMappedView = reinterpret_cast<T*>
|
||||
(::MapViewOfFile(map, FILE_MAP_READ, 0, offset, sizeof(T)));
|
||||
}
|
||||
~RVAMap() {
|
||||
if (mMappedView) {
|
||||
::UnmapViewOfFile(mMappedView);
|
||||
}
|
||||
}
|
||||
operator const T*() const { return mMappedView; }
|
||||
const T* operator->() const { return mMappedView; }
|
||||
private:
|
||||
const T* mMappedView;
|
||||
};
|
||||
|
||||
void
|
||||
ForceASLR(const wchar_t* path)
|
||||
{
|
||||
HANDLE file = ::CreateFileW(path, GENERIC_READ, FILE_SHARE_READ,
|
||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if (file != INVALID_HANDLE_VALUE) {
|
||||
HANDLE map = ::CreateFileMappingW(file, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||
if (map) {
|
||||
RVAMap<IMAGE_DOS_HEADER> peHeader(map, 0);
|
||||
if (peHeader) {
|
||||
RVAMap<IMAGE_NT_HEADERS> ntHeader(map, peHeader->e_lfanew);
|
||||
if (ntHeader) {
|
||||
// If we're dealing with a DLL which has code inside it, but does not have the
|
||||
// ASLR bit set, allocate a page at its base address.
|
||||
if (((ntHeader->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) == 0) &&
|
||||
(ntHeader->OptionalHeader.SizeOfCode > 0)) {
|
||||
void* page = ::VirtualAlloc((LPVOID)ntHeader->OptionalHeader.ImageBase, 1,
|
||||
MEM_RESERVE, PAGE_NOACCESS);
|
||||
// Note that we will leak this page, but it's ok since it's just one page in
|
||||
// the virtual address space, with no physical page backing it.
|
||||
|
||||
// We're done at this point!
|
||||
}
|
||||
}
|
||||
}
|
||||
::CloseHandle(map);
|
||||
}
|
||||
::CloseHandle(file);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static NTSTATUS NTAPI
|
||||
patched_LdrLoadDll (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileName, PHANDLE handle)
|
||||
{
|
||||
@ -210,32 +157,9 @@ patched_LdrLoadDll (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileNam
|
||||
wchar_t *dll_part;
|
||||
DllBlockInfo *info;
|
||||
|
||||
// In Windows 8, the first parameter seems to be used for more than just the
|
||||
// path name. For example, its numerical value can be 1. Passing a non-valid
|
||||
// pointer to SearchPathW will cause a crash, so we need to check to see if we
|
||||
// are handed a valid pointer, and otherwise just pass NULL to SearchPathW.
|
||||
PWCHAR sanitizedFilePath = (intptr_t(filePath) < 1024) ? NULL : filePath;
|
||||
|
||||
int len = moduleFileName->Length / 2;
|
||||
wchar_t *fname = moduleFileName->Buffer;
|
||||
|
||||
// figure out the length of the string that we need
|
||||
DWORD pathlen = SearchPathW(sanitizedFilePath, fname, L".dll", 0, NULL, NULL);
|
||||
if (pathlen == 0) {
|
||||
// uh, we couldn't find the DLL at all, so...
|
||||
printf_stderr("LdrLoadDll: Blocking load of '%s' (SearchPathW didn't find it?)\n", dllName);
|
||||
return STATUS_DLL_NOT_FOUND;
|
||||
}
|
||||
|
||||
nsAutoArrayPtr<wchar_t> full_fname(new wchar_t[pathlen+1]);
|
||||
if (!full_fname) {
|
||||
// couldn't allocate memory?
|
||||
return STATUS_DLL_NOT_FOUND;
|
||||
}
|
||||
|
||||
// now actually grab it
|
||||
SearchPathW(sanitizedFilePath, fname, L".dll", pathlen+1, full_fname, NULL);
|
||||
|
||||
// The filename isn't guaranteed to be null terminated, but in practice
|
||||
// it always will be; ensure that this is so, and bail if not.
|
||||
// This is done instead of the more robust approach because of bug 527122,
|
||||
@ -311,6 +235,29 @@ patched_LdrLoadDll (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileNam
|
||||
#endif
|
||||
|
||||
if (info->maxVersion != ALL_VERSIONS) {
|
||||
// In Windows 8, the first parameter seems to be used for more than just the
|
||||
// path name. For example, its numerical value can be 1. Passing a non-valid
|
||||
// pointer to SearchPathW will cause a crash, so we need to check to see if we
|
||||
// are handed a valid pointer, and otherwise just pass NULL to SearchPathW.
|
||||
PWCHAR sanitizedFilePath = (intptr_t(filePath) < 1024) ? NULL : filePath;
|
||||
|
||||
// figure out the length of the string that we need
|
||||
DWORD pathlen = SearchPathW(sanitizedFilePath, fname, L".dll", 0, NULL, NULL);
|
||||
if (pathlen == 0) {
|
||||
// uh, we couldn't find the DLL at all, so...
|
||||
printf_stderr("LdrLoadDll: Blocking load of '%s' (SearchPathW didn't find it?)\n", dllName);
|
||||
return STATUS_DLL_NOT_FOUND;
|
||||
}
|
||||
|
||||
wchar_t *full_fname = (wchar_t*) malloc(sizeof(wchar_t)*(pathlen+1));
|
||||
if (!full_fname) {
|
||||
// couldn't allocate memory?
|
||||
return STATUS_DLL_NOT_FOUND;
|
||||
}
|
||||
|
||||
// now actually grab it
|
||||
SearchPathW(sanitizedFilePath, fname, L".dll", pathlen+1, full_fname, NULL);
|
||||
|
||||
DWORD zero;
|
||||
DWORD infoSize = GetFileVersionInfoSizeW(full_fname, &zero);
|
||||
|
||||
@ -334,6 +281,8 @@ patched_LdrLoadDll (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileNam
|
||||
load_ok = true;
|
||||
}
|
||||
}
|
||||
|
||||
free(full_fname);
|
||||
}
|
||||
|
||||
if (!load_ok) {
|
||||
@ -349,8 +298,6 @@ continue_loading:
|
||||
|
||||
NS_SetHasLoadedNewDLLs();
|
||||
|
||||
ForceASLR(full_fname);
|
||||
|
||||
return stub_LdrLoadDll(filePath, flags, moduleFileName, handle);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user