Backing out part 5 of bug 617152. a=blocking

This commit is contained in:
Robert O'Callahan 2010-12-24 15:15:11 +13:00
Родитель a7ecb74728 fc6e0beb41
Коммит 0a31156e28
425 изменённых файлов: 7323 добавлений и 2878 удалений

Просмотреть файл

@ -53,3 +53,4 @@ dba2abb7db57078c5a4810884834d3056a5d56c2 last-mozilla-central
0327e126ea245112c0aa7283fee154e084866fb5 bsmedberg-static-xpcom-registration-base
2f83edbbeef0de7dd901411d270da61106c8afae bsmedberg-static-xpcom-registration-base
138f593553b66c9f815e8f57870c19d6347f7702 UPDATE_PACKAGING_R12
138f593553b66c9f815e8f57870c19d6347f7702 UPDATE_PACKAGING_R13

Просмотреть файл

@ -907,7 +907,7 @@ nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTe
PRBool needsStart = PR_FALSE;
switch (aBoundaryType) {
case BOUNDARY_CHAR:
amount = eSelectCharacter;
amount = eSelectCluster;
if (aType == eGetAt)
aType = eGetAfter; // Avoid returning 2 characters
break;

Просмотреть файл

@ -78,6 +78,12 @@ let TabView = {
}
},
// ----------
uninit: function TabView_uninit() {
if (this._window)
Services.obs.removeObserver(this, "quit-application-requested");
},
// ----------
// Creates the frame and calls the callback once it's loaded.
// If the frame already exists, calls the callback immediately.
@ -103,14 +109,7 @@ let TabView = {
this._window = iframe.contentWindow;
// ___ visibility storage handler
let self = this;
function observer(subject, topic, data) {
if (topic == "quit-application-requested") {
let data = (self.isVisible() ? "true" : "false");
self._sessionstore.setWindowValue(window, self._visibilityID, data);
}
}
Services.obs.addObserver(observer, "quit-application-requested", false);
Services.obs.addObserver(this, "quit-application-requested", false);
if (this._tabShowEventListener) {
gBrowser.tabContainer.removeEventListener(
@ -119,6 +118,14 @@ let TabView = {
}
},
// ----------
observe: function TabView_observe(subject, topic, data) {
if (topic == "quit-application-requested") {
let data = (this.isVisible() ? "true" : "false");
this._sessionstore.setWindowValue(window, this._visibilityID, data);
}
},
// ----------
getContentWindow: function TabView_getContentWindow() {
return this._window;

Просмотреть файл

@ -1646,6 +1646,7 @@ function BrowserShutdown()
Components.utils.reportError(ex);
}
TabView.uninit();
BrowserOffline.uninit();
OfflineApps.uninit();
gPrivateBrowsingUI.uninit();

Просмотреть файл

@ -1455,6 +1455,13 @@
this._blurTab(aTab);
aTab.removeAttribute("fadein");
setTimeout(function (tab, tabbrowser) {
if (tab.parentNode) {
NS_ASSERT(false, "Giving up waiting for the tab closing animation to finish (bug 608589)");
tabbrowser._endRemoveTab(tab);
}
}, 2000, aTab, this);
]]>
</body>
</method>
@ -1601,8 +1608,6 @@
if (browser == this.mCurrentBrowser)
this.mCurrentBrowser = null;
var wasPinned = aTab.pinned;
// Invalidate browsers cache, as the tab is removed from the
// tab container.
this._browsers = null;
@ -1615,7 +1620,6 @@
this.tabs[i]._tPos = i;
if (!this._windowIsClosing) {
if (wasPinned)
this.tabContainer._positionPinnedTabs();
// update tab close buttons state

Просмотреть файл

@ -750,6 +750,7 @@ let TabItems = {
_heartbeatTiming: 100, // milliseconds between _checkHeartbeat() calls
_lastUpdateTime: Date.now(),
_eventListeners: [],
_pauseUpdateForTest: false,
tempCanvas: null,
// ----------
@ -874,6 +875,9 @@ let TabItems = {
// Takes in a xul:tab.
_update: function TabItems__update(tab) {
try {
if (this._pauseUpdateForTest)
return;
Utils.assertThrow(tab, "tab");
// ___ remove from waiting list if needed

Просмотреть файл

@ -203,18 +203,20 @@ let UI = {
});
// ___ setup observer to save canvas images
var observer = {
observe : function(subject, topic, data) {
function quitObserver(subject, topic, data) {
if (topic == "quit-application-requested") {
if (self.isTabViewVisible()) {
if (self.isTabViewVisible())
GroupItems.removeHiddenGroups();
TabItems.saveAll(true);
}
self._save();
}
}
};
Services.obs.addObserver(observer, "quit-application-requested", false);
Services.obs.addObserver(
quitObserver, "quit-application-requested", false);
this._cleanupFunctions.push(function() {
Services.obs.removeObserver(quitObserver, "quit-application-requested");
});
// ___ Done
this._frameInitialized = true;
@ -237,7 +239,6 @@ let UI = {
this._cleanupFunctions.forEach(function(func) {
func();
});
this._cleanupFunctions = [];
// additional clean up

Просмотреть файл

@ -96,6 +96,18 @@ function setupTwo() {
restoredWin.removeEventListener("load", arguments.callee, false);
// execute code when the frame is initialized.
let onTabViewFrameInitialized = function() {
restoredWin.removeEventListener(
"tabviewframeinitialized", onTabViewFrameInitialized, false);
let restoredContentWindow =
restoredWin.document.getElementById("tab-view").contentWindow;
// prevent TabItems._update being called before checking cached images
restoredContentWindow.TabItems._pauseUpdateForTest = true;
}
restoredWin.addEventListener(
"tabviewframeinitialized", onTabViewFrameInitialized, false);
restoredWin.addEventListener("tabviewshown", onTabViewShown, false);
is(restoredWin.gBrowser.tabs.length, 2, "The total number of tabs is 2");
@ -214,6 +226,8 @@ function updateAndCheck() {
let contentWindow =
restoredWin.document.getElementById("tab-view").contentWindow;
contentWindow.TabItems._pauseUpdateForTest = false;
let tabItems = contentWindow.TabItems.getItems();
tabItems.forEach(function(tabItem) {
contentWindow.TabItems._update(tabItem.tab);

Просмотреть файл

@ -50,7 +50,7 @@ tier_app_dirs += $(MOZ_BRANDING_DIRECTORY)
tier_app_dirs += toolkit/components/console/hudservice
ifdef MOZ_SERVICES_SYNC
tier_app_dirs += services/sync
tier_app_dirs += services
endif
tier_app_dirs += browser

Просмотреть файл

@ -257,7 +257,9 @@ BrowserGlue.prototype = {
if (data == "post-update-notification") {
if (Services.prefs.prefHasUserValue("app.update.postupdate"))
this._showUpdateNotification();
break;
}
else if (data == "force-ui-migration") {
this._migrateUI();
}
break;
}
@ -997,7 +999,8 @@ BrowserGlue.prototype = {
},
_migrateUI: function BG__migrateUI() {
const UI_VERSION = 4;
const UI_VERSION = 5;
const BROWSER_DOCURL = "chrome://browser/content/browser.xul#";
let currentUIVersion = 0;
try {
currentUIVersion = Services.prefs.getIntPref("browser.migration.version");
@ -1014,7 +1017,7 @@ BrowserGlue.prototype = {
let currentsetResource = this._rdf.GetResource("currentset");
let toolbars = ["nav-bar", "toolbar-menubar", "PersonalToolbar"];
for (let i = 0; i < toolbars.length; i++) {
let toolbar = this._rdf.GetResource("chrome://browser/content/browser.xul#" + toolbars[i]);
let toolbar = this._rdf.GetResource(BROWSER_DOCURL + toolbars[i]);
let currentset = this._getPersist(toolbar, currentsetResource);
if (!currentset) {
// toolbar isn't customized
@ -1039,7 +1042,7 @@ BrowserGlue.prototype = {
if (currentUIVersion < 2) {
// This code adds the customizable bookmarks button.
let currentsetResource = this._rdf.GetResource("currentset");
let toolbarResource = this._rdf.GetResource("chrome://browser/content/browser.xul#nav-bar");
let toolbarResource = this._rdf.GetResource(BROWSER_DOCURL + "nav-bar");
let currentset = this._getPersist(toolbarResource, currentsetResource);
// Need to migrate only if toolbar is customized and the element is not found.
if (currentset &&
@ -1058,7 +1061,7 @@ BrowserGlue.prototype = {
if (currentUIVersion < 3) {
// This code merges the reload/stop/go button into the url bar.
let currentsetResource = this._rdf.GetResource("currentset");
let toolbarResource = this._rdf.GetResource("chrome://browser/content/browser.xul#nav-bar");
let toolbarResource = this._rdf.GetResource(BROWSER_DOCURL + "nav-bar");
let currentset = this._getPersist(toolbarResource, currentsetResource);
// Need to migrate only if toolbar is customized and all 3 elements are found.
if (currentset &&
@ -1077,7 +1080,7 @@ BrowserGlue.prototype = {
if (currentUIVersion < 4) {
// This code moves the home button to the immediate left of the bookmarks menu button.
let currentsetResource = this._rdf.GetResource("currentset");
let toolbarResource = this._rdf.GetResource("chrome://browser/content/browser.xul#nav-bar");
let toolbarResource = this._rdf.GetResource(BROWSER_DOCURL + "nav-bar");
let currentset = this._getPersist(toolbarResource, currentsetResource);
// Need to migrate only if toolbar is customized and the elements are found.
if (currentset &&
@ -1090,6 +1093,34 @@ BrowserGlue.prototype = {
}
}
if (currentUIVersion < 5) {
// This code uncollapses PersonalToolbar if its collapsed status is not
// persisted, and user customized it or changed default bookmarks.
let toolbarResource = this._rdf.GetResource(BROWSER_DOCURL + "PersonalToolbar");
let collapsedResource = this._rdf.GetResource("collapsed");
let collapsed = this._getPersist(toolbarResource, collapsedResource);
// If the user does not have a persisted value for the toolbar's
// "collapsed" attribute, try to determine whether it's customized.
if (collapsed === null) {
// We consider the toolbar customized if it has more than
// 3 children, or if it has a persisted currentset value.
let currentsetResource = this._rdf.GetResource("currentset");
let toolbarIsCustomized = !!this._getPersist(toolbarResource,
currentsetResource);
function getToolbarFolderCount() {
let toolbarFolder =
PlacesUtils.getFolderContents(PlacesUtils.toolbarFolderId).root;
let toolbarChildCount = toolbarFolder.childCount;
toolbarFolder.containerOpen = false;
return toolbarChildCount;
}
if (toolbarIsCustomized || getToolbarFolderCount() > 3) {
this._setPersist(toolbarResource, collapsedResource, "false");
}
}
}
if (this._dirty)
this._dataSource.QueryInterface(Ci.nsIRDFRemoteDataSource).Flush();
@ -1120,6 +1151,15 @@ BrowserGlue.prototype = {
else {
this._dataSource.Assert(aSource, aProperty, this._rdf.GetLiteral(aTarget), true);
}
// Add the entry to the persisted set for this document if it's not there.
// This code is mostly borrowed from nsXULDocument::Persist.
let docURL = aSource.ValueUTF8.split("#")[0];
let docResource = this._rdf.GetResource(docURL);
let persistResource = this._rdf.GetResource("http://home.netscape.com/NC-rdf#persist");
if (!this._dataSource.HasAssertion(docResource, persistResource, aSource, true)) {
this._dataSource.Assert(docResource, persistResource, aSource, true);
}
}
catch(ex) {}
},

Просмотреть файл

@ -70,6 +70,7 @@ _BROWSER_TEST_FILES = \
framedPage.html \
frameLeft.html \
frameRight.html \
browser_toolbar_migration.js \
$(NULL)
libs:: $(_BROWSER_TEST_FILES)

Просмотреть файл

@ -0,0 +1,134 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
/**
* Tests PersonalToolbar migration path.
*/
let bg = Cc["@mozilla.org/browser/browserglue;1"].getService(Ci.nsIObserver);
let gOriginalMigrationVersion;
let localStore = {
get RDF() Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService),
get store() this.RDF.GetDataSource("rdf:local-store"),
get toolbar()
{
delete this.toolbar;
let toolbar = this.RDF.GetResource("chrome://browser/content/browser.xul#PersonalToolbar");
// Add the entry to the persisted set for this document if it's not there.
// See nsXULDocument::Persist.
let doc = this.RDF.GetResource("chrome://browser/content/browser.xul");
let persist = this.RDF.GetResource("http://home.netscape.com/NC-rdf#persist");
if (!this.store.HasAssertion(doc, persist, toolbar, true)) {
this.store.Assert(doc, persist, toolbar, true);
}
return this.toolbar = toolbar;
},
getPersist: function getPersist(aProperty)
{
let property = this.RDF.GetResource(aProperty);
let target = this.store.GetTarget(this.toolbar, property, true);
if (target instanceof Ci.nsIRDFLiteral)
return target.Value;
return null;
},
setPersist: function setPersist(aProperty, aValue)
{
let property = this.RDF.GetResource(aProperty);
let value = aValue ? this.RDF.GetLiteral(aValue) : null;
try {
let oldTarget = this.store.GetTarget(this.toolbar, property, true);
if (oldTarget && value) {
this.store.Change(this.toolbar, property, oldTarget, value);
}
else if (value) {
this.store.Assert(this.toolbar, property, value, true);
}
else if (oldTarget) {
this.store.Unassert(this.toolbar, property, oldTarget);
}
else {
return;
}
}
catch(ex) {
return;
}
this.store.QueryInterface(Ci.nsIRDFRemoteDataSource).Flush();
}
};
let gTests = [
function test_explicitly_collapsed_toolbar()
{
info("An explicitly collapsed toolbar should not be uncollapsed.");
localStore.setPersist("collapsed", "true");
bg.observe(null, "browser-glue-test", "force-ui-migration");
is(localStore.getPersist("collapsed"), "true", "Toolbar is collapsed");
},
function test_customized_toolbar()
{
info("A customized toolbar should be uncollapsed.");
localStore.setPersist("currentset", "splitter");
bg.observe(null, "browser-glue-test", "force-ui-migration");
is(localStore.getPersist("collapsed"), "false", "Toolbar has been uncollapsed");
},
function test_many_bookmarks_toolbar()
{
info("A toolbar with added bookmarks should be uncollapsed.");
let ids = [];
ids.push(
PlacesUtils.bookmarks.insertSeparator(PlacesUtils.toolbarFolderId,
PlacesUtils.bookmarks.DEFAULT_INDEX)
);
ids.push(
PlacesUtils.bookmarks.insertSeparator(PlacesUtils.toolbarFolderId,
PlacesUtils.bookmarks.DEFAULT_INDEX)
);
ids.push(
PlacesUtils.bookmarks.insertSeparator(PlacesUtils.toolbarFolderId,
PlacesUtils.bookmarks.DEFAULT_INDEX)
);
bg.observe(null, "browser-glue-test", "force-ui-migration");
is(localStore.getPersist("collapsed"), "false", "Toolbar has been uncollapsed");
},
];
function test()
{
gOriginalMigrationVersion = Services.prefs.getIntPref("browser.migration.version");
registerCleanupFunction(clean);
if (localStore.getPersist("currentset") !== null) {
info("Toolbar currentset was persisted by a previous test, fixing it.");
localStore.setPersist("currentset", null);
}
if (localStore.getPersist("collapsed") !== null) {
info("Toolbar collapsed status was persisted by a previous test, fixing it.");
localStore.setPersist("collapsed", null);
}
while (gTests.length) {
clean();
Services.prefs.setIntPref("browser.migration.version", 4);
gTests.shift().call();
}
}
function clean()
{
Services.prefs.setIntPref("browser.migration.version", gOriginalMigrationVersion);
localStore.setPersist("currentset", null);
localStore.setPersist("collapsed", null);
}

Просмотреть файл

@ -103,6 +103,7 @@ var SelectBookmarkDialog = {
names.push(node.title);
}
}
contents.containerOpen = false;
}
else {
urls.push(selectedNode.uri);

Просмотреть файл

@ -251,19 +251,19 @@ function test() {
is(browser.userTypedValue, null, "userTypedValue is empty to start");
is(browser.userTypedClear, 0, "userTypedClear is 0 to start");
gURLBar.value = "mozilla.org";
gURLBar.value = "example.org";
let event = document.createEvent("Events");
event.initEvent("input", true, false);
gURLBar.dispatchEvent(event);
is(browser.userTypedValue, "mozilla.org",
is(browser.userTypedValue, "example.org",
"userTypedValue was set when changing gURLBar.value");
is(browser.userTypedClear, 0,
"userTypedClear was not changed when changing gURLBar.value");
// Now make sure ss gets these values too
let newState = JSON.parse(ss.getBrowserState());
is(newState.windows[0].tabs[0].userTypedValue, "mozilla.org",
is(newState.windows[0].tabs[0].userTypedValue, "example.org",
"sessionstore got correct userTypedValue");
is(newState.windows[0].tabs[0].userTypedClear, 0,
"sessionstore got correct userTypedClear");

Просмотреть файл

@ -230,6 +230,7 @@
#ifdef MOZ_SERVICES_SYNC
@BINPATH@/components/services-crypto.xpt
#endif
@BINPATH@/components/services-crypto-component.xpt
@BINPATH@/components/shellservice.xpt
@BINPATH@/components/shistory.xpt
@BINPATH@/components/spellchecker.xpt

Просмотреть файл

@ -596,6 +596,14 @@ Function CheckExistingInstall
Quit
${If} ${FileExists} "$INSTDIR\${FileMainEXE}"
; Disable the next, cancel, and back buttons
GetDlgItem $0 $HWNDPARENT 1 ; Next button
EnableWindow $0 0
GetDlgItem $0 $HWNDPARENT 2 ; Cancel button
EnableWindow $0 0
GetDlgItem $0 $HWNDPARENT 3 ; Back button
EnableWindow $0 0
Banner::show /NOUNLOAD "$(BANNER_CHECK_EXISTING)"
${If} "$TmpVal" == "FoundMessageWindow"
@ -610,6 +618,14 @@ Function CheckExistingInstall
Banner::destroy
; Enable the next, cancel, and back buttons
GetDlgItem $0 $HWNDPARENT 1 ; Next button
EnableWindow $0 1
GetDlgItem $0 $HWNDPARENT 2 ; Cancel button
EnableWindow $0 1
GetDlgItem $0 $HWNDPARENT 3 ; Back button
EnableWindow $0 1
${If} "$TmpVal" == "true"
StrCpy $TmpVal "FoundMessageWindow"
${ManualCloseAppPrompt} "${WindowClass}" "$(WARN_MANUALLY_CLOSE_APP_INSTALL)"

Просмотреть файл

@ -723,6 +723,10 @@ toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button {
-moz-image-region: rect(0px 168px 24px 144px);
}
#feed-button[disabled="true"] > .toolbarbutton-icon {
opacity: .3;
}
/* 16px primary toolbar buttons */
toolbar[iconsize="small"] .toolbarbutton-1:not([type="menu-button"]) {
-moz-box-orient: vertical;
@ -1108,7 +1112,6 @@ toolbar[iconsize="small"] #feed-button {
/* Identity popup bounding box */
#identity-popup-container {
min-width: 280px;
padding: 10px;
}
/* Invalid form popup */
@ -1121,9 +1124,7 @@ toolbar[iconsize="small"] #feed-button {
/* Notification popup */
#notification-popup {
margin: 4px 0;
min-width: 280px;
padding: 10px;
}
.popup-notification-icon {
@ -1330,10 +1331,6 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
}
/* Bookmarking panel */
#editBookmarkPanel {
padding: 4px;
}
#editBookmarkPanelStarIcon {
list-style-image: url("chrome://browser/skin/places/starred48.png");
width: 48px;

Просмотреть файл

@ -79,29 +79,47 @@
#navigator-toolbox > toolbar:not(#toolbar-menubar):not(#TabsToolbar) {
-moz-box-align: center;
padding: 2px 4px 4px;
padding: 2px 4px;
}
#PersonalToolbar:not(:-moz-lwtheme),
#navigator-toolbox[tabsontop="true"] > toolbar:not(#TabsToolbar):not(:-moz-lwtheme) {
#nav-bar {
padding-bottom: 4px !important;
}
#PersonalToolbar {
-moz-appearance: none;
margin-top: -1px; /* overlay the bottom border of the toolbar above us */
padding-top: 0 !important;
background-color: -moz-mac-chrome-active;
border-bottom: 1px solid rgba(0, 0, 0, 0.57);
}
#PersonalToolbar:not(:-moz-lwtheme):-moz-window-inactive,
#navigator-toolbox[tabsontop="true"] > toolbar:not(#TabsToolbar):not(:-moz-lwtheme):-moz-window-inactive {
background-color: -moz-mac-chrome-inactive;
border-bottom-color: rgba(0, 0, 0, 0.32);
}
#navigator-toolbox[tabsontop="true"] > #nav-bar,
#navigator-toolbox[tabsontop="true"]:not([customizing]) > #nav-bar[collapsed="true"] + toolbar,
#navigator-toolbox[tabsontop="true"]:not([customizing]) > #nav-bar[collapsed="true"] + #customToolbars + #PersonalToolbar {
margin-top: 0 !important; /* don't overlay the bottom border of the tabs toolbar */
-moz-appearance: none;
margin-top: 0; /* don't overlay the bottom border of the tabs toolbar */
padding-top: 4px !important;
border-bottom: 1px solid rgba(0, 0, 0, 0.57);
background-color: -moz-mac-chrome-active;
background-image: -moz-linear-gradient(rgba(255,255,255,.43), rgba(255,255,255,0)) !important; /* override lwtheme style */
background-origin: border-box !important;
}
#PersonalToolbar:-moz-lwtheme,
#navigator-toolbox[tabsontop="true"] > #nav-bar:-moz-lwtheme,
#navigator-toolbox[tabsontop="true"]:not([customizing]) > #nav-bar[collapsed="true"] + toolbar:-moz-lwtheme,
#navigator-toolbox[tabsontop="true"]:not([customizing]) > #nav-bar[collapsed="true"] + #customToolbars + #PersonalToolbar:-moz-lwtheme {
background-color: transparent;
border-bottom-color: transparent;
}
#PersonalToolbar:not(:-moz-lwtheme):-moz-window-inactive,
#navigator-toolbox[tabsontop="true"] > #nav-bar:not(:-moz-lwtheme):-moz-window-inactive,
#navigator-toolbox[tabsontop="true"]:not([customizing]) > #nav-bar[collapsed="true"] + toolbar:not(:-moz-lwtheme):-moz-window-inactive,
#navigator-toolbox[tabsontop="true"]:not([customizing]) > #nav-bar[collapsed="true"] + #customToolbars + #PersonalToolbar:not(:-moz-lwtheme):-moz-window-inactive {
background-color: -moz-mac-chrome-inactive;
border-bottom-color: rgba(0, 0, 0, 0.32);
}
/* ----- BOOKMARK TOOLBAR ----- */
@ -1784,15 +1802,11 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
.tabbrowser-arrowscrollbox > .scrollbutton-up:-moz-locale-dir(ltr),
.tabbrowser-arrowscrollbox > .scrollbutton-down:-moz-locale-dir(rtl) {
border-right: 2px solid;
-moz-border-right-colors: rgba(0,0,0,0.25) rgba(255,255,255,0.15);
list-style-image: url("chrome://browser/skin/tabbrowser/tab-arrow-left.png");
}
.tabbrowser-arrowscrollbox > .scrollbutton-down:-moz-locale-dir(ltr),
.tabbrowser-arrowscrollbox > .scrollbutton-up:-moz-locale-dir(rtl) {
border-left: 2px solid;
-moz-border-left-colors: rgba(0,0,0,0.25) rgba(255,255,255,0.15);
list-style-image: url("chrome://browser/skin/tabbrowser/tab-arrow-right.png");
}
@ -1823,18 +1837,14 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
padding: 0;
border: none;
border-radius: 0;
background: none;
box-shadow: none;
/* !important flags needed because of bug 561154: */
background: none !important;
box-shadow: none !important;
}
:-moz-any(#TabsToolbar, #addon-bar) .toolbarbutton-1:not([type="menu-button"]),
:-moz-any(#TabsToolbar, #addon-bar) .toolbarbutton-1 > .toolbarbutton-menubutton-button,
:-moz-any(#TabsToolbar, #addon-bar) .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
-moz-border-start: 2px solid !important;
-moz-border-end: none !important;
-moz-border-left-colors: rgba(0,0,0,0.25) rgba(255,255,255,0.15) !important;
-moz-border-right-colors: rgba(0,0,0,0.25) rgba(255,255,255,0.15) !important;
background-clip: padding-box;
margin: 0;
padding: 0 1px;
}
@ -2280,7 +2290,7 @@ panel[dimmed="true"] {
-moz-appearance: none;
}
#addon-bar {
#addon-bar:not(:-moz-lwtheme) {
-moz-appearance: statusbar;
}

Просмотреть файл

@ -158,9 +158,9 @@
-moz-binding: url("chrome://global/content/bindings/toolbar.xml#toolbar-drag");
}
#browser:not(:-moz-lwtheme),
#browser-bottombox:not(:-moz-lwtheme) {
background-color: -moz-dialog;
background-clip: padding-box;
}
#main-menubar:not(:-moz-lwtheme):not(:-moz-window-inactive) {

Просмотреть файл

@ -90,6 +90,18 @@ _LEAKTEST_FILES = \
leaktest.py \
bloatcycle.html \
$(topsrcdir)/build/pgo/server-locations.txt \
$(topsrcdir)/build/pgo/favicon.ico \
$(topsrcdir)/build/pgo/blueprint/sample.html \
$(topsrcdir)/build/pgo/blueprint/elements.html \
$(topsrcdir)/build/pgo/blueprint/forms.html \
$(topsrcdir)/build/pgo/blueprint/grid.html \
$(topsrcdir)/build/pgo/blueprint/test.jpg \
$(topsrcdir)/build/pgo/blueprint/test-small.jpg \
$(topsrcdir)/build/pgo/blueprint/valid.png \
$(topsrcdir)/build/pgo/blueprint/screen.css \
$(topsrcdir)/build/pgo/blueprint/print.css \
$(topsrcdir)/build/pgo/blueprint/grid.png \
$(topsrcdir)/build/pgo/blueprint/fancytype-screen.css \
$(NULL)
leaktest.py: leaktest.py.in

Просмотреть файл

@ -163,14 +163,13 @@ function goQuitApplication()
var list =
[
"http://www.mozilla.org",
"http://www.mozilla.org",
"http://www.mozilla.org/newlayout/samples/test2.html",
"http://www.mozilla.org/newlayout/samples/test8.html",
"http://www.mozilla.org/newlayout/samples/test6.html",
"http://www.mozilla.org/newlayout/samples/test8.html"
"sample.html",
"forms.html",
"grid.html",
"forms.html",
"elements.html"
];
var interval = 3000; // 15000
var interval = 5000; // 15000
var idx = 0;
var w;

Просмотреть файл

@ -75,11 +75,9 @@ interface nsIPrincipal : nsISerializable
* explicitly granted or denied by a pref. isTrusted is a boolean that
* indicates whether this is a codebaseTrusted certificate.
*/
[noscript] void getPreferences(out string prefBranch, out string id,
out string subjectName,
out string grantedList,
out string deniedList,
out boolean isTrusted);
void getPreferences(out string prefBranch, out string id,
out string subjectName, out string grantedList,
out string deniedList, out boolean isTrusted);
/**
* Returns whether the other principal is equivalent to this principal.
@ -133,7 +131,7 @@ interface nsIPrincipal : nsISerializable
* The codebase URI to which this principal pertains. This is
* generally the document URI.
*/
[noscript] readonly attribute nsIURI URI;
readonly attribute nsIURI URI;
/**
* The domain URI to which this principal pertains.
@ -149,7 +147,7 @@ interface nsIPrincipal : nsISerializable
// XXXcaa this should probably be turned into an nsIURI.
// The system principal's origin should be some caps namespace
// with a chrome URI. All of chrome should probably be the same.
[noscript] readonly attribute string origin;
readonly attribute string origin;
/**
* Whether this principal is associated with a certificate.
@ -201,7 +199,7 @@ interface nsIPrincipal : nsISerializable
* sure what the immediate benefit would be, but I think the setup could
* make some code (e.g. MaybeDowngradeToCodebase) clearer.
*/
[noscript] boolean subsumes(in nsIPrincipal other);
boolean subsumes(in nsIPrincipal other);
/**
* Checks whether this principal is allowed to load the network resource
@ -224,7 +222,7 @@ interface nsIPrincipal : nsISerializable
* if the load is not allowed.
* @throws NS_ERROR_DOM_BAD_URI if the load is not allowed.
*/
[noscript] void checkMayLoad(in nsIURI uri, in boolean report);
void checkMayLoad(in nsIURI uri, in boolean report);
/**
* The subject name for the certificate. This actually identifies the

Просмотреть файл

@ -865,6 +865,11 @@ nsScriptSecurityManager::CheckPropertyAccessImpl(PRUint32 aAction,
stringName.AssignLiteral("CallMethodDeniedOrigins");
}
// Null out objectPrincipal for now, so we don't leak information about
// it. Whenever we can report different error strings to content and
// the UI we can take this out again.
objectPrincipal = nsnull;
NS_ConvertUTF8toUTF16 className(classInfoData.GetName());
nsCAutoString subjectOrigin;
nsCAutoString subjectDomain;

Просмотреть файл

@ -705,6 +705,8 @@ ANDROID_SDK = @ANDROID_SDK@
ANDROID_PLATFORM_TOOLS = @ANDROID_PLATFORM_TOOLS@
ANDROID_VERSION = @ANDROID_VERSION@
ANDROID_PACKAGE_NAME = @ANDROID_PACKAGE_NAME@
JS_SHARED_LIBRARY = @JS_SHARED_LIBRARY@
# We only want to do the pymake sanity on Windows, other os's can cope

Просмотреть файл

@ -326,6 +326,9 @@ if test "$target" = "arm-android-eabi" ; then
ANDROID_SDK="${android_sdk}"
ANDROID_PLATFORM_TOOLS="${android_platform_tools}"
ANDROID_VERSION="${android_version}"
if test -z "$ANDROID_PACKAGE_NAME" ; then
ANDROID_PACKAGE_NAME='org.mozilla.$(MOZ_APP_NAME)'
fi
AC_DEFINE(ANDROID)
AC_DEFINE_UNQUOTED(ANDROID_VERSION, $android_version)
@ -340,6 +343,7 @@ AC_SUBST(ANDROID_TOOLCHAIN)
AC_SUBST(ANDROID_PLATFORM)
AC_SUBST(ANDROID_SDK)
AC_SUBST(ANDROID_PLATFORM_TOOLS)
AC_SUBST(ANDROID_PACKAGE_NAME)
dnl ========================================================
dnl Checks for compilers.

Просмотреть файл

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<script type="text/javascript">
function boom()
{
iframe = document.getElementById("iframe");
iframeBody = iframe.contentDocument.body;
iframeBody.appendChild(makeNamedSpan("w"));
remove(iframe);
iframeBody.appendChild(makeNamedSpan("w"));
remove(iframeBody);
document.documentElement.className = "";
}
function makeNamedSpan(i)
{
var s = document.createElement("span");
s.id = i;
return s;
}
function remove(n) { n.parentNode.removeChild(n); }
</script>
</head>
<body onload="boom();">
<iframe id="iframe" src="data:text/html,S"></iframe>
</body>
</html>

Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<body>
<!-- This test should not leak. -->
<iframe src="data:text/html,
<script>
var elem = document.createElement('span');
document.mozSetImageElement('foo', elem);
elem.foo = document;
</script>"></iframe>
</body>
</html>

Просмотреть файл

@ -80,3 +80,5 @@ load 590395-1.html
load 595606-1.html
load 595606-2.html
load 606729-1.html
load 593302-1.html
load 593302-2.html

Просмотреть файл

@ -807,6 +807,8 @@ public:
* @param aColumnNumber Column number within resource containing error.
* @param aErrorFlags See nsIScriptError.
* @param aCategory Name of module reporting error.
* @param [aWindowId=0] (Optional) The window ID of the outer window the
* message originates from.
*/
enum PropertiesFile {
eCSS_PROPERTIES,
@ -832,7 +834,36 @@ public:
PRUint32 aLineNumber,
PRUint32 aColumnNumber,
PRUint32 aErrorFlags,
const char *aCategory);
const char *aCategory,
PRUint64 aWindowId = 0);
/**
* Report a localized error message to the error console.
* @param aFile Properties file containing localized message.
* @param aMessageName Name of localized message.
* @param aParams Parameters to be substituted into localized message.
* @param aParamsLength Length of aParams.
* @param aURI URI of resource containing error (may be null).
* @param aSourceLine The text of the line that contains the error (may be
empty).
* @param aLineNumber Line number within resource containing error.
* @param aColumnNumber Column number within resource containing error.
* @param aErrorFlags See nsIScriptError.
* @param aCategory Name of module reporting error.
* @param aDocument Reference to the document which triggered the message.
If aURI is null, then aDocument->GetDocumentURI() is used.
*/
static nsresult ReportToConsole(PropertiesFile aFile,
const char *aMessageName,
const PRUnichar **aParams,
PRUint32 aParamsLength,
nsIURI* aURI,
const nsAFlatString& aSourceLine,
PRUint32 aLineNumber,
PRUint32 aColumnNumber,
PRUint32 aErrorFlags,
const char *aCategory,
nsIDocument* aDocument);
/**
* Get the localized string named |aKey| in properties file |aFile|.

Просмотреть файл

@ -700,6 +700,15 @@ public:
return mRemovedFromDocShell ? GetInnerWindowInternal() : mWindow;
}
/**
* Return the outer window ID.
*/
PRUint64 OuterWindowID()
{
nsPIDOMWindow *window = GetWindow();
return window ? window->WindowID() : 0;
}
/**
* Get the script loader for this document
*/

Просмотреть файл

@ -59,11 +59,11 @@ ThirdPartyUtil::Init()
// Get the base domain for aHostURI; e.g. for "www.bbc.co.uk", this would be
// "bbc.co.uk". Only properly-formed URI's are tolerated, though a trailing
// dot may be present (and will be stripped). If aHostURI is an IP address,
// an alias such as 'localhost', an eTLD such as 'co.uk', or the empty string,
// aBaseDomain will be the exact host. The result of this function should only
// be used in exact string comparisons, since substring comparisons will not
// be valid for the special cases elided above.
// dot may be present. If aHostURI is an IP address, an alias such as
// 'localhost', an eTLD such as 'co.uk', or the empty string, aBaseDomain will
// be the exact host. The result of this function should only be used in exact
// string comparisons, since substring comparisons will not be valid for the
// special cases elided above.
nsresult
ThirdPartyUtil::GetBaseDomain(nsIURI* aHostURI,
nsCString& aBaseDomain)
@ -80,9 +80,9 @@ ThirdPartyUtil::GetBaseDomain(nsIURI* aHostURI,
}
NS_ENSURE_SUCCESS(rv, rv);
// aHostURI (and thus aBaseDomain) may contain a trailing dot; if so, trim it.
if (!aBaseDomain.IsEmpty() && aBaseDomain.Last() == '.')
aBaseDomain.Truncate(aBaseDomain.Length() - 1);
// aHostURI (and thus aBaseDomain) may be the string '.'. If so, fail.
if (aBaseDomain.Length() == 1 && aBaseDomain.Last() == '.')
return NS_ERROR_INVALID_ARG;
// Reject any URIs without a host that aren't file:// URIs. This makes it the
// only way we can get a base domain consisting of the empty string, which

Просмотреть файл

@ -3115,7 +3115,8 @@ nsContentUtils::ReportToConsole(PropertiesFile aFile,
PRUint32 aLineNumber,
PRUint32 aColumnNumber,
PRUint32 aErrorFlags,
const char *aCategory)
const char *aCategory,
PRUint64 aWindowId)
{
NS_ASSERTION((aParams && aParamsLength) || (!aParams && !aParamsLength),
"Supply either both parameters and their number or no"
@ -3141,17 +3142,46 @@ nsContentUtils::ReportToConsole(PropertiesFile aFile,
if (aURI)
aURI->GetSpec(spec);
nsCOMPtr<nsIScriptError> errorObject =
nsCOMPtr<nsIScriptError2> errorObject =
do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = errorObject->Init(errorText.get(),
rv = errorObject->InitWithWindowID(errorText.get(),
NS_ConvertUTF8toUTF16(spec).get(), // file name
aSourceLine.get(),
aLineNumber, aColumnNumber,
aErrorFlags, aCategory);
aErrorFlags, aCategory, aWindowId);
NS_ENSURE_SUCCESS(rv, rv);
return sConsoleService->LogMessage(errorObject);
nsCOMPtr<nsIScriptError> logError = do_QueryInterface(errorObject);
return sConsoleService->LogMessage(logError);
}
/* static */ nsresult
nsContentUtils::ReportToConsole(PropertiesFile aFile,
const char *aMessageName,
const PRUnichar **aParams,
PRUint32 aParamsLength,
nsIURI* aURI,
const nsAFlatString& aSourceLine,
PRUint32 aLineNumber,
PRUint32 aColumnNumber,
PRUint32 aErrorFlags,
const char *aCategory,
nsIDocument* aDocument)
{
nsIURI* uri = aURI;
PRUint64 windowID = 0;
if (aDocument) {
if (!uri) {
uri = aDocument->GetDocumentURI();
}
windowID = aDocument->OuterWindowID();
}
return ReportToConsole(aFile, aMessageName, aParams, aParamsLength, uri,
aSourceLine, aLineNumber, aColumnNumber, aErrorFlags,
aCategory, windowID);
}
PRBool

Просмотреть файл

@ -1934,6 +1934,8 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
// manually.
tmp->mInUnlinkOrDeletion = PR_FALSE;
tmp->mIdentifierMap.Clear();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@ -3990,7 +3992,6 @@ nsDocument::BeginLoad()
NS_DOCUMENT_NOTIFY_OBSERVERS(BeginLoad, (this));
}
// static
void
nsDocument::ReportEmptyGetElementByIdArg()
{
@ -4000,7 +4001,7 @@ nsDocument::ReportEmptyGetElementByIdArg()
nsnull,
EmptyString(), 0, 0,
nsIScriptError::warningFlag,
"DOM");
"DOM", this);
}
Element*
@ -5296,11 +5297,10 @@ nsDocument::GetBoxObjectFor(nsIDOMElement* aElement, nsIBoxObject** aResult)
nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
"UseOfGetBoxObjectForWarning",
nsnull, 0,
static_cast<nsIDocument*>(this)->
GetDocumentURI(),
nsnull,
EmptyString(), 0, 0,
nsIScriptError::warningFlag,
"BoxObjects");
"BoxObjects", this);
}
*aResult = nsnull;
@ -7084,10 +7084,6 @@ nsDocument::Destroy()
// XXX We really should let cycle collection do this, but that currently still
// leaks (see https://bugzilla.mozilla.org/show_bug.cgi?id=406684).
nsContentUtils::ReleaseWrapper(static_cast<nsINode*>(this), this);
// Try really really hard to make sure we don't leak things through
// mIdentifierMap
mIdentifierMap.Clear();
}
void

Просмотреть файл

@ -992,7 +992,7 @@ protected:
* service if it is.
* @returns PR_TRUE if aId looks correct, PR_FALSE otherwise.
*/
static inline PRBool CheckGetElementByIdArg(const nsAString& aId)
inline PRBool CheckGetElementByIdArg(const nsAString& aId)
{
if (aId.IsEmpty()) {
ReportEmptyGetElementByIdArg();
@ -1001,7 +1001,7 @@ protected:
return PR_TRUE;
}
static void ReportEmptyGetElementByIdArg();
void ReportEmptyGetElementByIdArg();
void DispatchContentLoadedEvents();

Просмотреть файл

@ -140,10 +140,10 @@ nsReferencedElement::Reset(nsIContent* aFromContent, nsIURI* aURI,
}
nsCOMPtr<nsIURL> documentURL = do_QueryInterface(doc->GetDocumentURI());
if (!documentURL)
return;
if (!EqualExceptRef(url, documentURL)) {
// We've already checked that |url| is an nsIURL. So if the document URI is
// not an nsIURL then |url| is certainly not going to be pointing to the same
// document as the document URI.
if (!documentURL || !EqualExceptRef(url, documentURL)) {
nsRefPtr<nsIDocument::ExternalResourceLoad> load;
doc = doc->RequestExternalResource(url, aFromContent, getter_AddRefs(load));
if (!doc) {

Просмотреть файл

@ -88,6 +88,10 @@
#include "mozilla/Mutex.h"
#include "nsIDOMCloseEvent.h"
#include "nsICryptoHash.h"
#include "jsdbgapi.h"
#include "nsIJSContextStack.h"
#include "nsJSUtils.h"
#include "nsIScriptError.h"
using namespace mozilla;
@ -1953,6 +1957,10 @@ nsWebSocketEstablishedConnection::PrintErrorOnConsole(const char *aBundleURI,
do_GetService(NS_CONSOLESERVICE_CONTRACTID, &rv));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIScriptError2> errorObject(
do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv));
NS_ENSURE_SUCCESS(rv, rv);
// Localize the error message
nsXPIDLString message;
if (aFormatStrings) {
@ -1964,8 +1972,17 @@ nsWebSocketEstablishedConnection::PrintErrorOnConsole(const char *aBundleURI,
}
NS_ENSURE_SUCCESS(rv, rv);
errorObject->InitWithWindowID
(message.get(),
NS_ConvertUTF8toUTF16(mOwner->GetScriptFile()).get(),
nsnull,
mOwner->GetScriptLine(), 0, nsIScriptError::errorFlag,
"Web Socket", mOwner->WindowID()
);
// print the error message directly to the JS console
rv = console->LogStringMessage(message.get());
nsCOMPtr<nsIScriptError> logError(do_QueryInterface(errorObject));
rv = console->LogMessage(logError);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
@ -2850,7 +2867,9 @@ nsWebSocket::nsWebSocket() : mKeepingAlive(PR_FALSE),
mCheckMustKeepAlive(PR_TRUE),
mTriggeredCloseEvent(PR_FALSE),
mReadyState(nsIWebSocket::CONNECTING),
mOutgoingBufferedAmount(0)
mOutgoingBufferedAmount(0),
mScriptLine(0),
mWindowID(0)
{
}
@ -3522,6 +3541,26 @@ nsWebSocket::Init(nsIPrincipal* aPrincipal,
mOwner = nsnull;
}
nsCOMPtr<nsIJSContextStack> stack =
do_GetService("@mozilla.org/js/xpc/ContextStack;1");
JSContext* cx = nsnull;
if (stack && NS_SUCCEEDED(stack->Peek(&cx)) && cx) {
JSStackFrame *fp = JS_GetScriptedCaller(cx, NULL);
if (fp) {
JSScript *script = JS_GetFrameScript(cx, fp);
if (script) {
mScriptFile = JS_GetScriptFilename(cx, script);
}
jsbytecode *pc = JS_GetFramePC(cx, fp);
if (script && pc) {
mScriptLine = JS_PCToLineNumber(cx, script, pc);
}
}
mWindowID = nsJSUtils::GetCurrentlyRunningCodeWindowID(cx);
}
// parses the url
rv = ParseURL(PromiseFlatString(aURL));
NS_ENSURE_SUCCESS(rv, rv);

Просмотреть файл

@ -106,6 +106,10 @@ public:
// Determine if preferences allow WebSocket
static PRBool PrefEnabled();
const PRUint64 WindowID() const { return mWindowID; }
const nsCString& GetScriptFile() const { return mScriptFile; }
const PRUint32 GetScriptLine() const { return mScriptLine; }
protected:
nsresult ParseURL(const nsString& aURL);
nsresult SetProtocol(const nsString& aProtocol);
@ -156,6 +160,16 @@ protected:
// mConnection when we are connected,
// but we need this one after disconnecting.
// Web Socket owner information:
// - the script file name, UTF8 encoded.
// - source code line number where the Web Socket object was constructed.
// - the window ID of the outer window where the script lives. Note that this
// may not be the same as the Web Socket owner window.
// These attributes are used for error reporting.
nsCString mScriptFile;
PRUint32 mScriptLine;
PRUint64 mWindowID;
private:
nsWebSocket(const nsWebSocket& x); // prevent bad usage
nsWebSocket& operator=(const nsWebSocket& x);

Просмотреть файл

@ -2555,6 +2555,10 @@ WebGLContext::ReadPixels_base(WebGLint x, WebGLint y, WebGLsizei width, WebGLsiz
if (width < 0 || height < 0)
return ErrorInvalidValue("ReadPixels: negative size passed");
// there's nothing to do in this case, since we won't read any pixels
if (width == 0 || height == 0)
return NS_OK;
WebGLsizei boundWidth = mBoundFramebuffer ? mBoundFramebuffer->width() : mWidth;
WebGLsizei boundHeight = mBoundFramebuffer ? mBoundFramebuffer->height() : mHeight;
@ -2670,7 +2674,8 @@ WebGLContext::ReadPixels_base(WebGLint x, WebGLint y, WebGLsizei width, WebGLsiz
delete [] subrect_data;
}
// if we're reading alpha, we may need to do fixup
// if we're reading alpha, we may need to do fixup. Note that we don't allow
// GL_ALPHA to readpixels currently, but we had the code written for it already.
if (format == LOCAL_GL_ALPHA ||
format == LOCAL_GL_RGBA)
{

Просмотреть файл

@ -1,4 +1,5 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim:set ts=4 sw=4 et tw=78: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
@ -867,7 +868,12 @@ nsCanvasRenderingContext2D::SetStyleFromStringOrInterface(const nsAString& aStr,
nscolor color;
if (!aStr.IsVoid()) {
nsCSSParser parser;
nsIDocument* document = mCanvasElement ?
HTMLCanvasElement()->GetOwnerDoc() : nsnull;
// Pass the CSS Loader object to the parser, to allow parser error
// reports to include the outer window ID.
nsCSSParser parser(document ? document->CSSLoader() : nsnull);
rv = parser.ParseColorString(aStr, nsnull, 0, &color);
if (NS_FAILED(rv)) {
// Error reporting happens inside the CSS parser
@ -903,7 +909,8 @@ nsCanvasRenderingContext2D::SetStyleFromStringOrInterface(const nsAString& aStr,
nsnull,
EmptyString(), 0, 0,
nsIScriptError::warningFlag,
"Canvas");
"Canvas",
mCanvasElement ? HTMLCanvasElement()->GetOwnerDoc() : nsnull);
return NS_OK;
}
@ -1722,7 +1729,12 @@ nsCanvasRenderingContext2D::GetShadowBlur(float *blur)
NS_IMETHODIMP
nsCanvasRenderingContext2D::SetShadowColor(const nsAString& colorstr)
{
nsCSSParser parser;
nsIDocument* document = mCanvasElement ?
HTMLCanvasElement()->GetOwnerDoc() : nsnull;
// Pass the CSS Loader object to the parser, to allow parser error reports
// to include the outer window ID.
nsCSSParser parser(document ? document->CSSLoader() : nsnull);
nscolor color;
nsresult rv = parser.ParseColorString(colorstr, nsnull, 0, &color);
if (NS_FAILED(rv)) {
@ -2168,9 +2180,6 @@ CreateFontStyleRule(const nsAString& aFont,
nsINode* aNode,
nsICSSStyleRule** aResult)
{
nsCSSParser parser;
NS_ENSURE_TRUE(parser, NS_ERROR_OUT_OF_MEMORY);
nsCOMPtr<nsICSSStyleRule> rule;
PRBool changed;
@ -2180,6 +2189,11 @@ CreateFontStyleRule(const nsAString& aFont,
nsIURI* docURL = document->GetDocumentURI();
nsIURI* baseURL = document->GetDocBaseURI();
// Pass the CSS Loader object to the parser, to allow parser error reports
// to include the outer window ID.
nsCSSParser parser(document->CSSLoader());
NS_ENSURE_TRUE(parser, NS_ERROR_OUT_OF_MEMORY);
nsresult rv = parser.ParseStyleAttribute(EmptyString(), docURL, baseURL,
principal, getter_AddRefs(rule));
if (NS_FAILED(rv))
@ -3605,7 +3619,13 @@ nsCanvasRenderingContext2D::DrawWindow(nsIDOMWindow* aWindow, float aX, float aY
return NS_ERROR_FAILURE;
nscolor bgColor;
nsCSSParser parser;
nsIDocument* elementDoc = mCanvasElement ?
HTMLCanvasElement()->GetOwnerDoc() : nsnull;
// Pass the CSS Loader object to the parser, to allow parser error reports
// to include the outer window ID.
nsCSSParser parser(elementDoc ? elementDoc->CSSLoader() : nsnull);
NS_ENSURE_TRUE(parser, NS_ERROR_OUT_OF_MEMORY);
nsresult rv = parser.ParseColorString(PromiseFlatString(aBGColor),
nsnull, 0, &bgColor);

Просмотреть файл

@ -60,7 +60,6 @@ function init()
gl = initWebGL("example", "vshader", "fshader", [ "vPosition", "texCoord0"],
[ 0, 0, 0, 1 ], 1);
gl = WebGLDebugUtils.makeDebugContext(gl);
gl.disable(gl.DEPTH_TEST);
gl.disable(gl.BLEND);

Просмотреть файл

@ -440,10 +440,10 @@ ReportUseOfDeprecatedMethod(nsEvent* aEvent, nsIDOMEvent* aDOMEvent,
nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
aWarning,
strings, NS_ARRAY_LENGTH(strings),
doc ? doc->GetDocumentURI() : nsnull,
nsnull,
EmptyString(), 0, 0,
nsIScriptError::warningFlag,
"DOM Events");
"DOM Events", doc);
}
NS_IMETHODIMP

Просмотреть файл

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<script>
function boom()
{
var frame = document.getElementById("f");
var frameRoot = frame.contentDocument.documentElement;
document.body.removeChild(frame);
var i = document.createElementNS("http://www.w3.org/1999/xhtml", "input");
i.setAttribute("autofocus", "true");
frameRoot.appendChild(i);
}
</script>
</head>
<body onload="boom();"><iframe id="f" src="data:text/html,"></iframe></body>
</html>

Просмотреть файл

@ -0,0 +1,6 @@
<!DOCTYPE html>
<html>
<body onload='document.cloneNode(1)'>
<button autofocus></button>
</body>
</html>

Просмотреть файл

@ -26,3 +26,5 @@ load 602117.html
load 613027.html
load 614279.html
load 614988-1.html
load 620078-1.html
load 620078-2.html

Просмотреть файл

@ -78,11 +78,10 @@ SendJSWarning(nsIDocument* aDocument,
nsContentUtils::ReportToConsole(nsContentUtils::eFORMS_PROPERTIES,
aWarningName,
aWarningArgs, aWarningArgsLen,
aDocument ? aDocument->GetDocumentURI() :
nsnull,
EmptyString(), 0, 0,
nsIScriptError::warningFlag,
"HTML");
"HTML", aDocument);
}
// --------------------------------------------------------------------------

Просмотреть файл

@ -198,8 +198,10 @@ public:
return NS_OK;
}
// Do not autofocus if an sub-window is focused.
nsPIDOMWindow* window = document->GetWindow();
if (!window) {
return NS_OK;
}
// Trying to found the top window (equivalent to window.top).
nsCOMPtr<nsIDOMWindow> top;
@ -208,12 +210,12 @@ public:
window = static_cast<nsPIDOMWindow*>(top.get());
}
nsCOMPtr<nsIDocument> topDoc = do_QueryInterface(window->GetExtantDocument());
if (topDoc && topDoc->GetReadyStateEnum() == nsIDocument::READYSTATE_COMPLETE) {
if (window->GetFocusedNode()) {
return NS_OK;
}
if (window && window->GetFocusedNode()) {
nsCOMPtr<nsIDocument> topDoc = do_QueryInterface(window->GetExtantDocument());
if (topDoc && topDoc->GetReadyStateEnum() == nsIDocument::READYSTATE_COMPLETE) {
return NS_OK;
}

Просмотреть файл

@ -249,6 +249,7 @@ _TEST_FILES = \
test_bug615833.html \
test_bug601030.html \
test_bug610687.html \
test_bug618948.html \
$(NULL)
libs:: $(_TEST_FILES)

Просмотреть файл

@ -0,0 +1,89 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=618948
-->
<head>
<title>Test for Bug 618948</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<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=618948">Mozilla Bug 618948</a>
<p id="display"></p>
<div id="content">
<form>
<input type='email' id='i'>
<button>submit</button>
</form>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 618948 **/
var events = ["focus", "input", "change", "invalid" ];
var handled = ({});
function eventHandler(event)
{
dump("\n" + event.type + "\n");
handled[event.type] = true;
}
function beginTest()
{
for each (var e in events) {
handled[e] = false;
}
i.focus();
}
function endTest()
{
for each (var e in events) {
ok(handled[e], "on" + e + " should have been called");
}
SimpleTest.finish();
}
var i = document.getElementsByTagName('input')[0];
var b = document.getElementsByTagName('button')[0];
i.onfocus = function(event) {
eventHandler(event);
synthesizeKey('f', {});
i.onfocus = null;
};
i.oninput = function(event) {
eventHandler(event);
b.focus();
i.oninput = null;
};
i.onchange = function(event) {
eventHandler(event);
i.onchange = null;
synthesizeMouseAtCenter(b, {});
};
i.oninvalid = function(event) {
eventHandler(event);
i.oninvad = null;
endTest();
};
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(beginTest);
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -213,11 +213,10 @@ ReportUseOfDeprecatedMethod(nsHTMLDocument* aDoc, const char* aWarning)
nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
aWarning,
nsnull, 0,
static_cast<nsIDocument*>(aDoc)->
GetDocumentURI(),
nsnull,
EmptyString(), 0, 0,
nsIScriptError::warningFlag,
"DOM Events");
"DOM Events", aDoc);
}
static nsresult
@ -2151,7 +2150,7 @@ nsHTMLDocument::WriteCommon(const nsAString& aText,
mDocumentURI,
EmptyString(), 0, 0,
nsIScriptError::warningFlag,
"DOM Events");
"DOM Events", this);
return NS_OK;
}
mWriteState = eDocumentClosed;
@ -2168,7 +2167,7 @@ nsHTMLDocument::WriteCommon(const nsAString& aText,
mDocumentURI,
EmptyString(), 0, 0,
nsIScriptError::warningFlag,
"DOM Events");
"DOM Events", this);
return NS_OK;
}
rv = Open();
@ -2525,11 +2524,10 @@ nsHTMLDocument::GetSelection(nsAString& aReturn)
{
aReturn.Truncate();
nsCOMPtr<nsIConsoleService> consoleService
(do_GetService("@mozilla.org/consoleservice;1"));
if (consoleService) {
consoleService->LogStringMessage(NS_LITERAL_STRING("Deprecated method document.getSelection() called. Please use window.getSelection() instead.").get());
nsCOMPtr<nsIJSContextStack> stack = do_GetService("@mozilla.org/js/xpc/ContextStack;1");
JSContext* ccx = nsnull;
if (stack && NS_SUCCEEDED(stack->Peek(&ccx)) && ccx) {
JS_ReportWarning(ccx, "Deprecated method document.getSelection() called. Please use window.getSelection() instead.");
}
nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(GetScopeObject());

Просмотреть файл

@ -1046,7 +1046,10 @@ nsHTMLParanoidFragmentSink::AddAttributes(const nsIParserNode& aNode,
if (!baseURI) {
baseURI = aContent->GetBaseURI();
}
nsCSSParser parser;
// Pass the CSS Loader object to the parser, to allow parser error reports
// to include the outer window ID.
nsCSSParser parser(mTargetDocument->CSSLoader());
nsCOMPtr<nsICSSStyleRule> rule;
rv = parser.ParseStyleAttribute(aNode.GetValueAt(i),
mTargetDocument->GetDocumentURI(),

Просмотреть файл

@ -0,0 +1,21 @@
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg"><script>
<![CDATA[
function boom()
{
var r = document.documentElement;
var s = document.createElementNS("http://www.w3.org/2000/svg", "set");
s.setAttributeNS(null, "begin", "1s");
r.appendChild(s);
r.setCurrentTime(2);
document.removeChild(r);
r.setCurrentTime(0);
s.beginElementAt(0);
}
window.addEventListener("load", boom, false);
]]>
</script></svg>

После

Ширина:  |  Высота:  |  Размер: 437 B

Просмотреть файл

@ -33,3 +33,4 @@ load 608549-1.svg
load 608295-1.html
load 611927-1.svg
load 615002-1.svg
load 615872-1.svg

Просмотреть файл

@ -113,10 +113,10 @@ nsSMILCSSProperty::GetBaseValue() const
// doing so involves clearing and resetting the property which can cause
// frames to be recreated which we'd like to avoid.
//
// In either case, simply returning a null-typed nsSMILValue to indicate
// failure is acceptable because the caller only uses base values when
// there's interpolation or addition, and for both the shorthand properties
// we know about and the display property those operations aren't supported.
// In either case, just return a dummy value (initialized with the right
// type, so as not to indicate failure).
nsSMILValue tmpVal(&nsSMILCSSValueType::sSingleton);
baseValue.Swap(tmpVal);
return baseValue;
}

Просмотреть файл

@ -264,39 +264,6 @@ nsSMILTimedElement::BeginElementAt(double aOffsetSeconds)
nsSMILTime currentTime = container->GetCurrentTime();
AddInstanceTimeFromCurrentTime(currentTime, aOffsetSeconds, PR_TRUE);
// After we've added the instance time we must do a local resample.
//
// The reason for this can be explained by considering the following sequence
// of calls in a script block
//
// BeginElementAt(0)
// BeginElementAt(-1)
// GetStartTime() <-- should return the time from the first call to
// BeginElementAt
//
// After BeginElementAt(0) is called a new begin instance time is added to the
// list. Depending on the restart mode this may generate a new interval,
// possiblying ending the current interval early.
//
// Intuitively this change should take effect before the subsequent call to
// BeginElementAt however to get this to take effect we need to drive the
// state engine through its sequence active-waiting-active by calling Sample.
//
// When we get the second call to BeginElementAt the element should be in the
// active state and hence the new begin instance time will be ignored because
// it is before the beginning of the (new) current interval. SMIL says we do
// not change the begin of a current interval once it is active.
//
// See also:
// http://www.w3.org/TR/SMIL3/smil-timing.html#Timing-BeginEnd-Restart
// If we haven't started yet, then there's no point in trying to force the
// sample. A series of calls to BeginElementAt before the document starts
// should probably just add a series of instance times.
if (mElementState != STATE_STARTUP) {
DoSampleAt(currentTime, PR_FALSE); // Regular sample, not end sample
}
return NS_OK;
}
@ -309,9 +276,6 @@ nsSMILTimedElement::EndElementAt(double aOffsetSeconds)
nsSMILTime currentTime = container->GetCurrentTime();
AddInstanceTimeFromCurrentTime(currentTime, aOffsetSeconds, PR_FALSE);
if (mElementState != STATE_STARTUP) {
DoSampleAt(currentTime, PR_FALSE); // Regular sample, not end sample
}
return NS_OK;
}

Просмотреть файл

@ -249,15 +249,11 @@ function testOkSyntax(anim) {
testAnim.setAttribute('calcMode', 'spline');
testAnim.setAttribute('keySplines', okStrs[i]);
checkSample(4, 20);
removeElement(testAnim);
}
}
function testBadSyntaxA(anim) {
anim.setAttribute('dur','4s');
anim.setAttribute('from', '0');
anim.setAttribute('to', '20');
anim.setAttribute('calcMode', 'spline');
var badStrs = ['', // empty
' ', // whitespace only
'0,1.1,0,0', // bad range
@ -279,6 +275,7 @@ function testBadSyntaxA(anim) {
testAnim.setAttribute('calcMode', 'spline');
testAnim.setAttribute('keySplines', badStrs[i]);
checkSample(4, -100);
removeElement(testAnim);
}
}

Просмотреть файл

@ -70,7 +70,7 @@ SVGAnimatedLengthList::SetBaseValueString(const nsAString& aValue)
// which takes care of notifying.
rv = mBaseVal.CopyFrom(newBaseValue);
if (NS_FAILED(rv)) {
if (NS_FAILED(rv) && domWrapper) {
// Attempting to increase mBaseVal's length failed - reduce domWrapper
// back to the same length:
domWrapper->InternalBaseValListWillChangeTo(mBaseVal);

Просмотреть файл

@ -70,7 +70,7 @@ SVGAnimatedNumberList::SetBaseValueString(const nsAString& aValue)
// which takes care of notifying.
rv = mBaseVal.CopyFrom(newBaseValue);
if (NS_FAILED(rv)) {
if (NS_FAILED(rv) && domWrapper) {
// Attempting to increase mBaseVal's length failed - reduce domWrapper
// back to the same length:
domWrapper->InternalBaseValListWillChangeTo(mBaseVal);

Просмотреть файл

@ -70,7 +70,7 @@ SVGAnimatedPathSegList::SetBaseValueString(const nsAString& aValue)
baseValWrapper->InternalListWillChangeTo(newBaseValue);
}
DOMSVGPathSegList *animValWrapper;
DOMSVGPathSegList* animValWrapper = nsnull;
if (!IsAnimating()) { // DOM anim val wraps our base val too!
animValWrapper = DOMSVGPathSegList::GetDOMWrapperIfExists(GetAnimValKey());
if (animValWrapper) {

Просмотреть файл

@ -70,7 +70,7 @@ SVGAnimatedPointList::SetBaseValueString(const nsAString& aValue)
baseValWrapper->InternalListWillChangeTo(newBaseValue);
}
DOMSVGPointList *animValWrapper;
DOMSVGPointList* animValWrapper = nsnull;
if (!IsAnimating()) { // DOM anim val wraps our base val too!
animValWrapper = DOMSVGPointList::GetDOMWrapperIfExists(GetAnimValKey());
if (animValWrapper) {

Просмотреть файл

@ -255,8 +255,7 @@ SVGMotionSMILAnimationFunction::
PRBool ok =
path.GetDistancesFromOriginToEndsOfVisibleSegments(&mPathVertices);
if (ok && mPathVertices.Length()) {
mPath = pathElem->GetFlattenedPath(
pathElem->PrependLocalTransformTo(gfxMatrix()));
mPath = pathElem->GetFlattenedPath(gfxMatrix());
}
}
}

Просмотреть файл

@ -455,21 +455,25 @@ SVGPathData::GetMarkerPositioningData(nsTArray<nsSVGMark> *aMarks) const
// It should also assume that segments such as M and Z can appear in weird
// places, and repeat multiple times consecutively.
gfxPoint pathStart, segStart, segEnd;
gfxPoint cp1, cp2; // control points for current bezier curve
gfxPoint prevCP; // last control point of previous bezier curve
// info on current [sub]path (reset every M command):
gfxPoint pathStart(0.0, 0.0);
float pathStartAngle = 0.0f;
PRUint16 segType, prevSegType = nsIDOMSVGPathSeg::PATHSEG_UNKNOWN;
// info on the current [sub]path (reset every M command):
gfxPoint pathStartPoint(0, 0);
float pathStartAngle = 0;
float prevSegEndAngle = 0, segStartAngle = 0, segEndAngle = 0;
// info on previous segment:
PRUint16 prevSegType = nsIDOMSVGPathSeg::PATHSEG_UNKNOWN;
gfxPoint prevSegEnd(0.0, 0.0);
float prevSegEndAngle = 0.0f;
gfxPoint prevCP; // if prev seg was a bezier, this was its last control point
PRUint32 i = 0;
while (i < mData.Length()) {
segType = SVGPathSegUtils::DecodeType(mData[i++]); // advances i to args
// info on current segment:
PRUint16 segType =
SVGPathSegUtils::DecodeType(mData[i++]); // advances i to args
gfxPoint &segStart = prevSegEnd;
gfxPoint segEnd;
float segStartAngle, segEndAngle;
switch (segType) // to find segStartAngle, segEnd and segEndAngle
{
@ -505,6 +509,8 @@ SVGPathData::GetMarkerPositioningData(nsTArray<nsSVGMark> *aMarks) const
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS:
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_REL:
{
gfxPoint cp1, cp2; // control points
if (segType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS) {
cp1 = gfxPoint(mData[i], mData[i+1]);
cp2 = gfxPoint(mData[i+2], mData[i+3]);
@ -525,9 +531,12 @@ SVGPathData::GetMarkerPositioningData(nsTArray<nsSVGMark> *aMarks) const
segEndAngle = AngleOfVector(segEnd - cp2);
i += 6;
break;
}
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_ABS:
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_REL:
{
gfxPoint cp1, cp2; // control points
if (segType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_ABS) {
cp1 = gfxPoint(mData[i], mData[i+1]);
segEnd = gfxPoint(mData[i+2], mData[i+3]);
@ -540,6 +549,7 @@ SVGPathData::GetMarkerPositioningData(nsTArray<nsSVGMark> *aMarks) const
segEndAngle = AngleOfVector(segEnd - cp1);
i += 4;
break;
}
case nsIDOMSVGPathSeg::PATHSEG_ARC_ABS:
case nsIDOMSVGPathSeg::PATHSEG_ARC_REL:
@ -665,7 +675,10 @@ SVGPathData::GetMarkerPositioningData(nsTArray<nsSVGMark> *aMarks) const
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
cp1 = SVGPathSegUtils::IsCubicType(prevSegType) ? segStart * 2 - prevCP : segStart;
{
gfxPoint cp1 = SVGPathSegUtils::IsCubicType(prevSegType) ?
segStart * 2 - prevCP : segStart;
gfxPoint cp2;
if (segType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_ABS) {
cp2 = gfxPoint(mData[i], mData[i+1]);
segEnd = gfxPoint(mData[i+2], mData[i+3]);
@ -684,11 +697,15 @@ SVGPathData::GetMarkerPositioningData(nsTArray<nsSVGMark> *aMarks) const
segEndAngle = AngleOfVector(segEnd - cp2);
i += 4;
break;
}
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
cp1 = SVGPathSegUtils::IsQuadraticType(prevSegType) ? segStart * 2 - prevCP : segStart;
if (segType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_ABS) {
{
gfxPoint cp1 = SVGPathSegUtils::IsQuadraticType(prevSegType) ?
segStart * 2 - prevCP : segStart;
gfxPoint cp2;
if (segType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS) {
segEnd = gfxPoint(mData[i], mData[i+1]);
} else {
segEnd = segStart + gfxPoint(mData[i], mData[i+1]);
@ -698,6 +715,7 @@ SVGPathData::GetMarkerPositioningData(nsTArray<nsSVGMark> *aMarks) const
segEndAngle = AngleOfVector(segEnd - cp1);
i += 2;
break;
}
default:
// Leave any existing marks in aMarks so we have a visual indication of
@ -737,8 +755,8 @@ SVGPathData::GetMarkerPositioningData(nsTArray<nsSVGMark> *aMarks) const
}
prevSegType = segType;
prevSegEnd = segEnd;
prevSegEndAngle = segEndAngle;
segStart = segEnd;
}
NS_ABORT_IF_FALSE(i == mData.Length(), "Very, very bad - mData corrupt");

Просмотреть файл

@ -107,23 +107,34 @@ SVGPointList::SetValueFromString(const nsAString& aValue)
while (tokenizer.hasMoreTokens()) {
CopyUTF16toUTF8(tokenizer.nextToken(), str1);
const char *token1 = str1.get();
if (*token1 == '\0' || !tokenizer.hasMoreTokens()) {
if (*token1 == '\0') {
rv = NS_ERROR_DOM_SYNTAX_ERR;
break;
}
char *end;
float x = float(PR_strtod(token1, &end));
if (end == token1 || !NS_FloatIsFinite(x)) {
rv = NS_ERROR_DOM_SYNTAX_ERR;
break;
}
const char *token2;
if (*end == '-') {
// It's possible for the token to be 10-30 which has
// no separator but needs to be parsed as 10, -30
token2 = end;
} else {
if (!tokenizer.hasMoreTokens()) {
rv = NS_ERROR_DOM_SYNTAX_ERR;
break;
}
CopyUTF16toUTF8(tokenizer.nextToken(), str2);
const char *token2 = str2.get();
token2 = str2.get();
if (*token2 == '\0') {
rv = NS_ERROR_DOM_SYNTAX_ERR;
break;
}
char *end;
float x = float(PR_strtod(token1, &end));
if (*end != '\0' || !NS_FloatIsFinite(x)) {
rv = NS_ERROR_DOM_SYNTAX_ERR;
break;
}
float y = float(PR_strtod(token2, &end));
if (*end != '\0' || !NS_FloatIsFinite(y)) {
rv = NS_ERROR_DOM_SYNTAX_ERR;

Просмотреть файл

@ -82,8 +82,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
#endif
nsSVGAnimationElement::nsSVGAnimationElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsSVGAnimationElementBase(aNodeInfo),
mHrefTarget(this),
mTimedDocumentRoot(nsnull)
mHrefTarget(this)
#ifdef _MSC_VER
#pragma warning(pop)
#endif
@ -282,13 +281,6 @@ nsSVGAnimationElement::BindToTree(nsIDocument* aDocument,
// piece by piece via script)
return NS_OK;
mTimedDocumentRoot = GetTimeContainer();
if (!mTimedDocumentRoot)
// Timed document root hasn't been created yet. This will be created when
// the SVG parent is bound. This happens when we create SVG trees entirely
// by script.
return NS_OK;
// Add myself to the animation controller's master set of animation elements.
if (aDocument) {
nsSMILAnimationController *controller = aDocument->GetAnimationController();
@ -326,10 +318,6 @@ nsSVGAnimationElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
}
}
if (mTimedDocumentRoot) {
mTimedDocumentRoot = nsnull;
}
mHrefTarget.Unlink();
mTimedElement.DissolveReferences();
@ -460,6 +448,9 @@ nsSVGAnimationElement::BeginElementAt(float offset)
{
NS_ENSURE_FINITE(offset, NS_ERROR_ILLEGAL_VALUE);
// Make sure the timegraph is up-to-date
FlushAnimations();
// This will fail if we're not attached to a time container (SVG document
// fragment).
nsresult rv = mTimedElement.BeginElementAt(offset);
@ -467,6 +458,9 @@ nsSVGAnimationElement::BeginElementAt(float offset)
return rv;
AnimationNeedsResample();
// Force synchronous sample so that events resulting from this call arrive in
// the expected order and we get an up-to-date paint.
FlushAnimations();
return NS_OK;
}
@ -484,11 +478,16 @@ nsSVGAnimationElement::EndElementAt(float offset)
{
NS_ENSURE_FINITE(offset, NS_ERROR_ILLEGAL_VALUE);
// Make sure the timegraph is up-to-date
FlushAnimations();
nsresult rv = mTimedElement.EndElementAt(offset);
if (NS_FAILED(rv))
return rv;
AnimationNeedsResample();
// Force synchronous sample
FlushAnimations();
return NS_OK;
}

Просмотреть файл

@ -47,8 +47,6 @@
#include "nsISMILAnimationElement.h"
#include "nsSMILTimedElement.h"
class nsSMILTimeContainer;
typedef nsSVGElement nsSVGAnimationElementBase;
class nsSVGAnimationElement : public nsSVGAnimationElementBase,
@ -130,7 +128,6 @@ protected:
TargetReference mHrefTarget;
nsSMILTimedElement mTimedElement;
nsSMILTimeContainer* mTimedDocumentRoot;
};
#endif // NS_SVGANIMATIONELEMENT_H_

Просмотреть файл

@ -650,9 +650,6 @@ nsSVGFEGaussianBlurElement::GetDXY(PRUint32 *aDX, PRUint32 *aDY,
if (stdX < 0 || stdY < 0)
return NS_ERROR_FAILURE;
if (stdX == 0 || stdY == 0)
return NS_ERROR_UNEXPECTED;
// If the box size is greater than twice the temporary surface size
// in an axis, then each pixel will be set to the average of all the
// other pixel values.
@ -775,8 +772,6 @@ nsSVGFEGaussianBlurElement::Filter(nsSVGFilterInstance* aInstance,
{
PRUint32 dx, dy;
nsresult rv = GetDXY(&dx, &dy, *aInstance);
if (rv == NS_ERROR_UNEXPECTED) // zero std deviation
return NS_OK;
if (NS_FAILED(rv))
return rv;

Просмотреть файл

@ -539,25 +539,20 @@ nsSVGSVGElement::SetCurrentTime(float seconds)
#ifdef MOZ_SMIL
if (NS_SMILEnabled()) {
if (mTimedDocumentRoot) {
// Make sure the timegraph is up-to-date
FlushAnimations();
double fMilliseconds = double(seconds) * PR_MSEC_PER_SEC;
// Round to nearest whole number before converting, to avoid precision
// errors
nsSMILTime lMilliseconds = PRInt64(NS_round(fMilliseconds));
mTimedDocumentRoot->SetCurrentTime(lMilliseconds);
// Force a resample now
//
// It's not sufficient to just request a resample here because calls to
// BeginElement etc. expect to operate on an up-to-date timegraph or else
// instance times may be incorrectly discarded.
//
// See the mochitest: test_smilSync.xhtml:testSetCurrentTime()
nsIDocument* doc = GetCurrentDoc();
if (doc) {
nsSMILAnimationController* smilController = doc->GetAnimationController();
if (smilController) {
smilController->Resample();
}
}
AnimationNeedsResample();
// Trigger synchronous sample now, to:
// - Make sure we get an up-to-date paint after this method
// - re-enable event firing (it got disabled during seeking, and it
// doesn't get re-enabled until the first sample after the seek -- so
// let's make that happen now.)
FlushAnimations();
} // else we're not the outermost <svg> or not bound to a tree, so silently
// fail
return NS_OK;

Просмотреть файл

@ -247,11 +247,12 @@ nsXBLContentSink::ReportUnexpectedElement(nsIAtom* aElementName,
return nsContentUtils::ReportToConsole(nsContentUtils::eXBL_PROPERTIES,
"UnexpectedElement",
params, NS_ARRAY_LENGTH(params),
mDocumentURI,
nsnull,
EmptyString() /* source line */,
aLineNumber, 0 /* column number */,
nsIScriptError::errorFlag,
"XBL Content Sink");
"XBL Content Sink",
mDocument);
}
void
@ -664,11 +665,12 @@ nsXBLContentSink::ConstructHandler(const PRUnichar **aAtts, PRUint32 aLineNumber
mState = eXBL_Error;
nsContentUtils::ReportToConsole(nsContentUtils::eXBL_PROPERTIES,
"CommandNotInChrome", nsnull, 0,
mDocumentURI,
nsnull,
EmptyString() /* source line */,
aLineNumber, 0 /* column number */,
nsIScriptError::errorFlag,
"XBL Content Sink");
"XBL Content Sink",
mDocument);
return; // Don't even make this handler.
}

Просмотреть файл

@ -973,16 +973,23 @@ nsXBLPrototypeHandler::ConstructPrototype(nsIContent* aKeyElement,
void
nsXBLPrototypeHandler::ReportKeyConflict(const PRUnichar* aKey, const PRUnichar* aModifiers, nsIContent* aKeyElement, const char *aMessageName)
{
nsIURI* uri = mPrototypeBinding ? mPrototypeBinding->DocURI() :
aKeyElement ? aKeyElement->GetOwnerDoc()->GetDocumentURI() :
nsnull;
nsCOMPtr<nsIDocument> doc;
if (mPrototypeBinding) {
nsXBLDocumentInfo* docInfo = mPrototypeBinding->XBLDocumentInfo();
if (docInfo) {
doc = docInfo->GetDocument();
}
} else if (aKeyElement) {
doc = aKeyElement->GetOwnerDoc();
}
const PRUnichar* params[] = { aKey, aModifiers };
nsContentUtils::ReportToConsole(nsContentUtils::eXBL_PROPERTIES,
aMessageName,
params, NS_ARRAY_LENGTH(params),
uri, EmptyString(), mLineNumber, 0,
nsnull, EmptyString(), mLineNumber, 0,
nsIScriptError::warningFlag,
"XBL Prototype Handler");
"XBL Prototype Handler", doc);
}
PRBool

Просмотреть файл

@ -134,10 +134,10 @@ IsAncestorBinding(nsIDocument* aDocument,
nsContentUtils::ReportToConsole(nsContentUtils::eXBL_PROPERTIES,
"TooDeepBindingRecursion",
params, NS_ARRAY_LENGTH(params),
aDocument->GetDocumentURI(),
nsnull,
EmptyString(), 0, 0,
nsIScriptError::warningFlag,
"XBL");
"XBL", aDocument);
return PR_TRUE;
}
}
@ -978,10 +978,10 @@ nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
nsContentUtils::ReportToConsole(nsContentUtils::eXBL_PROPERTIES,
"InvalidExtendsBinding",
params, NS_ARRAY_LENGTH(params),
doc->GetDocumentURI(),
nsnull,
EmptyString(), 0, 0,
nsIScriptError::errorFlag,
"XBL");
"XBL", doc);
NS_ASSERTION(!IsChromeOrResourceURI(aURI),
"Invalid extends value");
return NS_ERROR_ILLEGAL_VALUE;
@ -1014,10 +1014,10 @@ nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
nsContentUtils::ReportToConsole(nsContentUtils::eXBL_PROPERTIES,
"CircularExtendsBinding",
params, NS_ARRAY_LENGTH(params),
boundDocument->GetDocumentURI(),
nsnull,
EmptyString(), 0, 0,
nsIScriptError::warningFlag,
"XBL");
"XBL", boundDocument);
return NS_ERROR_ILLEGAL_VALUE;
}
}

Просмотреть файл

@ -325,10 +325,10 @@ ReportUseOfDeprecatedMethod(nsIDocument *aDoc, const char* aWarning)
nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
aWarning,
nsnull, 0,
aDoc->GetDocumentURI(),
nsnull,
EmptyString(), 0, 0,
nsIScriptError::warningFlag,
"DOM3 Load");
"DOM3 Load", aDoc);
}
NS_IMETHODIMP
@ -398,18 +398,24 @@ nsXMLDocument::Load(const nsAString& aUrl, PRBool *aReturn)
nsAutoString error;
error.AssignLiteral("Cross site loading using document.load is no "
"longer supported. Use XMLHttpRequest instead.");
nsCOMPtr<nsIScriptError> errorObject =
nsCOMPtr<nsIScriptError2> errorObject =
do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = errorObject->Init(error.get(), NS_ConvertUTF8toUTF16(spec).get(),
rv = errorObject->InitWithWindowID(error.get(), NS_ConvertUTF8toUTF16(spec).get(),
nsnull, 0, 0, nsIScriptError::warningFlag,
"DOM");
"DOM",
callingDoc ?
callingDoc->OuterWindowID() :
this->OuterWindowID());
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIConsoleService> consoleService =
do_GetService(NS_CONSOLESERVICE_CONTRACTID);
if (consoleService) {
consoleService->LogMessage(errorObject);
nsCOMPtr<nsIScriptError> logError = do_QueryInterface(errorObject);
if (consoleService && logError) {
consoleService->LogMessage(logError);
}
return NS_ERROR_DOM_SECURITY_ERR;

Просмотреть файл

@ -3330,16 +3330,15 @@ nsXULDocument::ReportMissingOverlay(nsIURI* aURI)
NS_ConvertUTF8toUTF16 utfSpec(spec);
const PRUnichar* params[] = { utfSpec.get() };
nsContentUtils::ReportToConsole(nsContentUtils::eXUL_PROPERTIES,
"MissingOverlay",
params, NS_ARRAY_LENGTH(params),
mDocumentURI,
nsnull,
EmptyString(), /* source line */
0, /* line number */
0, /* column number */
nsIScriptError::warningFlag,
"XUL Document");
"XUL Document", this);
}
nsresult

Просмотреть файл

@ -1403,7 +1403,7 @@ static nsDOMClassInfoData sClassInfoData[] = {
NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ChromeWorker, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(WebGLRenderingContext, nsDOMGenericSH,
NS_DEFINE_CLASSINFO_DATA(WebGLRenderingContext, nsWebGLViewportHandlerSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(WebGLBuffer, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
@ -1566,6 +1566,8 @@ jsid nsDOMClassInfo::sOnblur_id = JSID_VOID;
jsid nsDOMClassInfo::sOnsubmit_id = JSID_VOID;
jsid nsDOMClassInfo::sOnreset_id = JSID_VOID;
jsid nsDOMClassInfo::sOnchange_id = JSID_VOID;
jsid nsDOMClassInfo::sOninput_id = JSID_VOID;
jsid nsDOMClassInfo::sOninvalid_id = JSID_VOID;
jsid nsDOMClassInfo::sOnselect_id = JSID_VOID;
jsid nsDOMClassInfo::sOnload_id = JSID_VOID;
jsid nsDOMClassInfo::sOnpopstate_id = JSID_VOID;
@ -1636,6 +1638,9 @@ jsid nsDOMClassInfo::sOnbeforescriptexecute_id = JSID_VOID;
jsid nsDOMClassInfo::sOnafterscriptexecute_id = JSID_VOID;
jsid nsDOMClassInfo::sWrappedJSObject_id = JSID_VOID;
jsid nsDOMClassInfo::sURL_id = JSID_VOID;
jsid nsDOMClassInfo::sKeyPath_id = JSID_VOID;
jsid nsDOMClassInfo::sAutoIncrement_id = JSID_VOID;
jsid nsDOMClassInfo::sUnique_id = JSID_VOID;
static const JSClass *sObjectClass = nsnull;
@ -1681,12 +1686,12 @@ PrintWarningOnConsole(JSContext *cx, const char *stringBundleProperty)
}
nsCOMPtr<nsIConsoleService> consoleService
(do_GetService("@mozilla.org/consoleservice;1"));
(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
if (!consoleService) {
return;
}
nsCOMPtr<nsIScriptError> scriptError =
nsCOMPtr<nsIScriptError2> scriptError =
do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
if (!scriptError) {
return;
@ -1709,15 +1714,19 @@ PrintWarningOnConsole(JSContext *cx, const char *stringBundleProperty)
}
}
}
nsresult rv = scriptError->Init(msg.get(),
nsresult rv = scriptError->InitWithWindowID(msg.get(),
sourcefile.get(),
EmptyString().get(),
lineno,
0, // column for error is not available
nsIScriptError::warningFlag,
"DOM:HTML");
"DOM:HTML",
nsJSUtils::GetCurrentlyRunningCodeWindowID(cx));
if (NS_SUCCEEDED(rv)){
consoleService->LogMessage(scriptError);
nsCOMPtr<nsIScriptError> logError = do_QueryInterface(scriptError);
consoleService->LogMessage(logError);
}
}
@ -1790,6 +1799,8 @@ nsDOMClassInfo::DefineStaticJSVals(JSContext *cx)
SET_JSID_TO_STRING(sOnsubmit_id, cx, "onsubmit");
SET_JSID_TO_STRING(sOnreset_id, cx, "onreset");
SET_JSID_TO_STRING(sOnchange_id, cx, "onchange");
SET_JSID_TO_STRING(sOninput_id, cx, "oninput");
SET_JSID_TO_STRING(sOninvalid_id, cx, "oninvalid");
SET_JSID_TO_STRING(sOnselect_id, cx, "onselect");
SET_JSID_TO_STRING(sOnload_id, cx, "onload");
SET_JSID_TO_STRING(sOnpopstate_id, cx, "onpopstate");
@ -1862,6 +1873,9 @@ nsDOMClassInfo::DefineStaticJSVals(JSContext *cx)
#endif // MOZ_MEDIA
SET_JSID_TO_STRING(sWrappedJSObject_id, cx, "wrappedJSObject");
SET_JSID_TO_STRING(sURL_id, cx, "URL");
SET_JSID_TO_STRING(sKeyPath_id, cx, "keyPath");
SET_JSID_TO_STRING(sAutoIncrement_id, cx, "autoIncrement");
SET_JSID_TO_STRING(sUnique_id, cx, "unique");
return NS_OK;
}
@ -4856,6 +4870,8 @@ nsDOMClassInfo::ShutDown()
sOnsubmit_id = JSID_VOID;
sOnreset_id = JSID_VOID;
sOnchange_id = JSID_VOID;
sOninput_id = JSID_VOID;
sOninvalid_id = JSID_VOID;
sOnselect_id = JSID_VOID;
sOnload_id = JSID_VOID;
sOnbeforeunload_id = JSID_VOID;
@ -4923,6 +4939,9 @@ nsDOMClassInfo::ShutDown()
sOnbeforescriptexecute_id = JSID_VOID;
sOnafterscriptexecute_id = JSID_VOID;
sWrappedJSObject_id = JSID_VOID;
sKeyPath_id = JSID_VOID;
sAutoIncrement_id = JSID_VOID;
sUnique_id = JSID_VOID;
NS_IF_RELEASE(sXPConnect);
NS_IF_RELEASE(sSecMan);
@ -7490,6 +7509,9 @@ nsEventReceiverSH::ReallyIsEventName(jsid id, jschar aFirstChar)
return id == sOnfocus_id;
case 'h' :
return id == sOnhashchange_id;
case 'i' :
return (id == sOninput_id ||
id == sOninvalid_id);
case 'k' :
return (id == sOnkeydown_id ||
id == sOnkeypress_id ||

Просмотреть файл

@ -282,6 +282,7 @@ protected:
static PRBool sDisableDocumentAllSupport;
static PRBool sDisableGlobalScopePollutionSupport;
public:
static jsid sTop_id;
static jsid sParent_id;
static jsid sScrollbars_id;
@ -321,6 +322,8 @@ protected:
static jsid sOnsubmit_id;
static jsid sOnreset_id;
static jsid sOnchange_id;
static jsid sOninput_id;
static jsid sOninvalid_id;
static jsid sOnselect_id;
static jsid sOnload_id;
static jsid sOnpopstate_id;
@ -391,7 +394,11 @@ protected:
static jsid sOnafterscriptexecute_id;
static jsid sWrappedJSObject_id;
static jsid sURL_id;
static jsid sKeyPath_id;
static jsid sAutoIncrement_id;
static jsid sUnique_id;
protected:
static JSPropertyOp sXPCNativeWrapperGetPropertyOp;
static JSPropertyOp sXrayWrapperPropertyHolderGetPropertyOp;
};
@ -1801,4 +1808,34 @@ public:
}
};
class nsWebGLViewportHandlerSH : public nsDOMGenericSH
{
protected:
nsWebGLViewportHandlerSH(nsDOMClassInfoData *aData) : nsDOMGenericSH(aData)
{
}
virtual ~nsWebGLViewportHandlerSH()
{
}
public:
NS_IMETHOD PostCreatePrototype(JSContext * cx, JSObject * proto) {
nsresult rv = nsDOMGenericSH::PostCreatePrototype(cx, proto);
if (NS_SUCCEEDED(rv)) {
if (!::JS_DefineProperty(cx, proto, "VIEWPORT", INT_TO_JSVAL(0x0BA2),
nsnull, nsnull, JSPROP_ENUMERATE))
{
return NS_ERROR_UNEXPECTED;
}
}
return rv;
}
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
{
return new nsWebGLViewportHandlerSH(aData);
}
};
#endif /* nsDOMClassInfo_h___ */

Просмотреть файл

@ -171,6 +171,11 @@ nsFocusManager::~nsFocusManager()
prefBranch->RemoveObserver("accessibility.tabfocus_applies_to_xul", this);
prefBranch->RemoveObserver("accessibility.mouse_focuses_formcontrol", this);
}
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
obs->RemoveObserver(this, "xpcom-shutdown");
}
}
// static
@ -194,6 +199,11 @@ nsFocusManager::Init()
prefBranch->AddObserver("accessibility.tabfocus_applies_to_xul", fm, PR_TRUE);
prefBranch->AddObserver("accessibility.mouse_focuses_formcontrol", fm, PR_TRUE);
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
obs->AddObserver(fm, "xpcom-shutdown", PR_TRUE);
}
return NS_OK;
}
@ -209,8 +219,8 @@ nsFocusManager::Observe(nsISupports *aSubject,
const char *aTopic,
const PRUnichar *aData)
{
nsDependentString data(aData);
if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
nsDependentString data(aData);
if (data.EqualsLiteral("accessibility.browsewithcaret")) {
UpdateCaret(PR_FALSE, PR_TRUE, mFocusedContent);
}
@ -223,6 +233,14 @@ nsFocusManager::Observe(nsISupports *aSubject,
sMouseFocusesFormControl =
nsContentUtils::GetBoolPref("accessibility.mouse_focuses_formcontrol", PR_FALSE);
}
} else if (!nsCRT::strcmp(aTopic, "xpcom-shutdown")) {
mActiveWindow = nsnull;
mFocusedWindow = nsnull;
mFocusedContent = nsnull;
mFirstBlurEvent = nsnull;
mFirstFocusEvent = nsnull;
mWindowBeingLowered = nsnull;
mMouseDownEventHandlingDocument = nsnull;
}
return NS_OK;

Просмотреть файл

@ -3530,15 +3530,12 @@ nsGlobalWindow::GetInnerWidth(PRInt32* aInnerWidth)
EnsureSizeUpToDate();
nsCOMPtr<nsIBaseWindow> docShellWin(do_QueryInterface(mDocShell));
nsRefPtr<nsPresContext> presContext;
mDocShell->GetPresContext(getter_AddRefs(presContext));
if (docShellWin && presContext) {
PRInt32 width, notused;
docShellWin->GetSize(&width, &notused);
*aInnerWidth = nsPresContext::
AppUnitsToIntCSSPixels(presContext->DevPixelsToAppUnits(width));
if (presContext) {
nsRect shellArea = presContext->GetVisibleArea();
*aInnerWidth = nsPresContext::AppUnitsToIntCSSPixels(shellArea.width);
} else {
*aInnerWidth = 0;
}
@ -3557,31 +3554,42 @@ nsGlobalWindow::SetInnerWidth(PRInt32 aInnerWidth)
* If caller is not chrome and the user has not explicitly exempted the site,
* prevent setting window.innerWidth by exiting early
*/
if (!CanMoveResizeWindows() || IsFrame()) {
return NS_OK;
}
nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_FAILURE);
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
docShellAsItem->GetTreeOwner(getter_AddRefs(treeOwner));
NS_ENSURE_TRUE(treeOwner, NS_ERROR_FAILURE);
NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(&aInnerWidth, nsnull),
NS_ERROR_FAILURE);
PRInt32 width = CSSToDevIntPixels(aInnerWidth);
nsRefPtr<nsIPresShell> presShell;
mDocShell->GetPresShell(getter_AddRefs(presShell));
nsCOMPtr<nsIPresShell_MOZILLA_2_0_BRANCH> presShell20 =
do_QueryInterface(presShell);
if (presShell20 && presShell20->GetIsViewportOverridden())
{
nscoord height = 0;
nscoord width = 0;
nsRefPtr<nsPresContext> presContext;
presContext = presShell->GetPresContext();
nsRect shellArea = presContext->GetVisibleArea();
height = shellArea.height;
width = nsPresContext::CSSPixelsToAppUnits(aInnerWidth);
return SetCSSViewportWidthAndHeight(width, height);
}
else
{
PRInt32 height = 0;
PRInt32 width = 0;
nsCOMPtr<nsIBaseWindow> docShellAsWin(do_QueryInterface(mDocShell));
PRInt32 notused, height = 0;
docShellAsWin->GetSize(&notused, &height);
NS_ENSURE_SUCCESS(treeOwner->SizeShellTo(docShellAsItem, width, height),
NS_ERROR_FAILURE);
return NS_OK;
docShellAsWin->GetSize(&width, &height);
width = CSSToDevIntPixels(aInnerWidth);
return SetDocShellWidthAndHeight(width, height);
}
}
NS_IMETHODIMP
@ -3593,15 +3601,12 @@ nsGlobalWindow::GetInnerHeight(PRInt32* aInnerHeight)
EnsureSizeUpToDate();
nsCOMPtr<nsIBaseWindow> docShellWin(do_QueryInterface(mDocShell));
nsRefPtr<nsPresContext> presContext;
mDocShell->GetPresContext(getter_AddRefs(presContext));
if (docShellWin && presContext) {
PRInt32 height, notused;
docShellWin->GetSize(&notused, &height);
*aInnerHeight = nsPresContext::
AppUnitsToIntCSSPixels(presContext->DevPixelsToAppUnits(height));
if (presContext) {
nsRect shellArea = presContext->GetVisibleArea();
*aInnerHeight = nsPresContext::AppUnitsToIntCSSPixels(shellArea.height);
} else {
*aInnerHeight = 0;
}
@ -3619,31 +3624,41 @@ nsGlobalWindow::SetInnerHeight(PRInt32 aInnerHeight)
* If caller is not chrome and the user has not explicitly exempted the site,
* prevent setting window.innerHeight by exiting early
*/
if (!CanMoveResizeWindows() || IsFrame()) {
return NS_OK;
}
nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_FAILURE);
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
docShellAsItem->GetTreeOwner(getter_AddRefs(treeOwner));
NS_ENSURE_TRUE(treeOwner, NS_ERROR_FAILURE);
NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(nsnull, &aInnerHeight),
NS_ERROR_FAILURE);
PRInt32 height = CSSToDevIntPixels(aInnerHeight);
nsRefPtr<nsIPresShell> presShell;
mDocShell->GetPresShell(getter_AddRefs(presShell));
nsCOMPtr<nsIPresShell_MOZILLA_2_0_BRANCH> presShell20 =
do_QueryInterface(presShell);
if (presShell20 && presShell20->GetIsViewportOverridden())
{
nscoord height = 0;
nscoord width = 0;
nsRefPtr<nsPresContext> presContext;
presContext = presShell->GetPresContext();
nsRect shellArea = presContext->GetVisibleArea();
width = shellArea.width;
height = nsPresContext::CSSPixelsToAppUnits(aInnerHeight);
return SetCSSViewportWidthAndHeight(width, height);
}
else
{
PRInt32 height = 0;
PRInt32 width = 0;
nsCOMPtr<nsIBaseWindow> docShellAsWin(do_QueryInterface(mDocShell));
PRInt32 width = 0, notused;
docShellAsWin->GetSize(&width, &notused);
NS_ENSURE_SUCCESS(treeOwner->SizeShellTo(docShellAsItem, width, height),
NS_ERROR_FAILURE);
return NS_OK;
docShellAsWin->GetSize(&width, &height);
height = CSSToDevIntPixels(aInnerHeight);
return SetDocShellWidthAndHeight(width, height);
}
}
nsresult
@ -3971,6 +3986,38 @@ nsGlobalWindow::CheckSecurityWidthAndHeight(PRInt32* aWidth, PRInt32* aHeight)
return NS_OK;
}
// NOTE: Arguments to this function should have values in device pixels
nsresult
nsGlobalWindow::SetDocShellWidthAndHeight(PRInt32 aInnerWidth, PRInt32 aInnerHeight)
{
nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_FAILURE);
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
docShellAsItem->GetTreeOwner(getter_AddRefs(treeOwner));
NS_ENSURE_TRUE(treeOwner, NS_ERROR_FAILURE);
NS_ENSURE_SUCCESS(treeOwner->SizeShellTo(docShellAsItem, aInnerWidth, aInnerHeight),
NS_ERROR_FAILURE);
return NS_OK;
}
// NOTE: Arguments to this function should have values in app units
nsresult
nsGlobalWindow::SetCSSViewportWidthAndHeight(nscoord aInnerWidth, nscoord aInnerHeight)
{
nsRefPtr<nsPresContext> presContext;
mDocShell->GetPresContext(getter_AddRefs(presContext));
nsRect shellArea = presContext->GetVisibleArea();
shellArea.height = aInnerHeight;
shellArea.width = aInnerWidth;
presContext->SetVisibleArea(shellArea);
return NS_OK;
}
// NOTE: Arguments to this function should have values scaled to
// CSS pixels, not device pixels.
nsresult
@ -5350,10 +5397,10 @@ ReportUseOfDeprecatedMethod(nsGlobalWindow* aWindow, const char* aWarning)
nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
aWarning,
nsnull, 0,
doc ? doc->GetDocumentURI() : nsnull,
nsnull,
EmptyString(), 0, 0,
nsIScriptError::warningFlag,
"DOM Events");
"DOM Events", doc);
}
NS_IMETHODIMP
@ -6048,11 +6095,10 @@ nsGlobalWindow::Close()
nsContentUtils::eDOM_PROPERTIES,
"WindowCloseBlockedWarning",
nsnull, 0, // No params
nsnull, // No URI. Not clear which URI we should be using
// here anyway
nsnull,
EmptyString(), 0, 0, // No source, or column/line number
nsIScriptError::warningFlag,
"DOM Window"); // Better name for the category?
"DOM Window", mDoc); // Better name for the category?
return NS_OK;
}

Просмотреть файл

@ -707,6 +707,12 @@ protected:
void EnsureReflowFlushAndPaint();
nsresult CheckSecurityWidthAndHeight(PRInt32* width, PRInt32* height);
nsresult CheckSecurityLeftAndTop(PRInt32* left, PRInt32* top);
// Arguments to this function should have values in app units
nsresult SetCSSViewportWidthAndHeight(nscoord width, nscoord height);
// Arguments to this function should have values in device pixels
nsresult SetDocShellWidthAndHeight(PRInt32 width, PRInt32 height);
static PRBool CanSetProperty(const char *aPrefName);
static void MakeScriptDialogTitle(nsAString &aOutTitle);

Просмотреть файл

@ -2548,37 +2548,14 @@ nsJSContext::ConnectToInner(nsIScriptGlobalObject *aNewInner, void *aOuterGlobal
JSObject *newInnerJSObject = (JSObject *)aNewInner->GetScriptGlobal(JAVASCRIPT);
JSObject *outerGlobal = (JSObject *)aOuterGlobal;
// Make the inner and outer window both share the same
// prototype. The prototype we share is the outer window's
// prototype, this way XPConnect can still find the wrapper to
// use when making a call like alert() (w/o qualifying it with
// "window."). XPConnect looks up the wrapper based on the
// function object's parent, which is the object the function
// was called on, and when calling alert() we'll be calling the
// alert() function from the outer window's prototype off of the
// inner window. In this case XPConnect is able to find the
// outer (through the JSExtendedClass hook outerObject), so this
// prototype sharing works.
// Now that we're connecting the outer global to the inner one,
// we must have transplanted it. The JS engine tries to maintain
// the global object's compartment as its default compartment,
// so update that now since it might have changed.
JS_SetGlobalObject(mContext, outerGlobal);
// We do *not* want to use anything else out of the outer
// object's prototype chain than the first prototype, which is
// the XPConnect prototype. The rest we want from the inner
// window's prototype, i.e. the global scope polluter and
// Object.prototype. This way the outer also gets the benefits
// of the global scope polluter, and the inner window's
// Object.prototype.
JSObject *proto = JS_GetPrototype(mContext, outerGlobal);
JSObject *innerProto = JS_GetPrototype(mContext, newInnerJSObject);
JSObject *innerProtoProto = JS_GetPrototype(mContext, innerProto);
JS_SetPrototype(mContext, newInnerJSObject, proto);
JS_SetPrototype(mContext, proto, innerProtoProto);
NS_ASSERTION(JS_GetPrototype(mContext, outerGlobal) ==
JS_GetPrototype(mContext, newInnerJSObject),
"outer and inner globals should have the same prototype");
return NS_OK;
}
@ -2626,19 +2603,6 @@ nsJSContext::CreateOuterObject(nsIScriptGlobalObject *aGlobalObject,
JS_SetOptions(mContext, JS_GetOptions(mContext) | JSOPTION_XML);
}
nsIXPConnect *xpc = nsContentUtils::XPConnect();
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = xpc->WrapNative(mContext, aCurrentInner->GetGlobalJSObject(),
aCurrentInner, NS_GET_IID(nsISupports),
getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIXPConnectWrappedNative> wrapper(do_QueryInterface(holder));
NS_ABORT_IF_FALSE(wrapper, "bad wrapper");
wrapper->RefreshPrototype();
JSObject *outer =
NS_NewOuterWindowProxy(mContext, aCurrentInner->GetGlobalJSObject());
if (!outer) {
@ -2655,6 +2619,20 @@ nsJSContext::SetOuterObject(void *aOuterObject)
// Force our context's global object to be the outer.
JS_SetGlobalObject(mContext, outer);
// NB: JS_SetGlobalObject sets mContext->compartment.
JSObject *inner = JS_GetParent(mContext, outer);
nsIXPConnect *xpc = nsContentUtils::XPConnect();
nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
nsresult rv = xpc->GetWrappedNativeOfJSObject(mContext, inner,
getter_AddRefs(wrapper));
NS_ENSURE_SUCCESS(rv, rv);
NS_ABORT_IF_FALSE(wrapper, "bad wrapper");
wrapper->RefreshPrototype();
JS_SetPrototype(mContext, outer, JS_GetPrototype(mContext, inner));
return NS_OK;
}

Просмотреть файл

@ -141,10 +141,18 @@ nsJSUtils::GetStaticScriptGlobal(JSContext* aContext, JSObject* aObj)
return nsnull;
}
// We might either have a window directly (e.g. if the global is a
// sandbox whose script object principal pointer is a window), or an
// XPCWrappedNative for a window. We could also have other
// sandbox-related script object principals, but we can't do much
// about those short of trying to walk the proto chain of |glob|
// looking for a window or something.
nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(supports));
if (!sgo) {
nsCOMPtr<nsIXPConnectWrappedNative> wrapper(do_QueryInterface(supports));
NS_ENSURE_TRUE(wrapper, nsnull);
nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryWrappedNative(wrapper));
sgo = do_QueryWrappedNative(wrapper);
}
// We're returning a pointer to something that's about to be
// released, but that's ok here.
@ -175,3 +183,26 @@ nsJSUtils::GetDynamicScriptContext(JSContext *aContext)
{
return GetScriptContextFromJSContext(aContext);
}
PRUint64
nsJSUtils::GetCurrentlyRunningCodeWindowID(JSContext *aContext)
{
if (!aContext)
return 0;
PRUint64 windowID = 0;
JSObject *jsGlobal = JS_GetGlobalForScopeChain(aContext);
if (jsGlobal) {
nsIScriptGlobalObject *scriptGlobal = GetStaticScriptGlobal(aContext,
jsGlobal);
if (scriptGlobal) {
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(scriptGlobal);
if (win)
windowID = win->GetOuterWindow()->WindowID();
}
}
return windowID;
}

Просмотреть файл

@ -69,6 +69,16 @@ public:
static nsIScriptGlobalObject *GetDynamicScriptGlobal(JSContext *aContext);
static nsIScriptContext *GetDynamicScriptContext(JSContext *aContext);
/**
* Retrieve the outer window ID based on the given JSContext.
*
* @param JSContext aContext
* The JSContext from which you want to find the outer window ID.
*
* @returns PRUint64 the outer window ID.
*/
static PRUint64 GetCurrentlyRunningCodeWindowID(JSContext *aContext);
};

Просмотреть файл

@ -47,7 +47,6 @@
#include "nsContentUtils.h"
#include "nsDOMClassInfo.h"
#include "nsEventDispatcher.h"
#include "nsJSON.h"
#include "nsJSUtils.h"
#include "nsThreadUtils.h"
@ -91,6 +90,7 @@ public:
void ReleaseMainThreadObjects()
{
mCursor = nsnull;
mCloneBuffer.clear();
AsyncConnectionHelper::ReleaseMainThreadObjects();
}
@ -105,7 +105,7 @@ protected:
nsRefPtr<IDBCursor> mCursor;
Key mKey;
Key mObjectKey;
nsString mValue;
JSAutoStructuredCloneBuffer mCloneBuffer;
};
class ContinueObjectStoreHelper : public ContinueHelper
@ -155,7 +155,7 @@ IDBCursor::Create(IDBRequest* aRequest,
const nsACString& aContinueQuery,
const nsACString& aContinueToQuery,
const Key& aKey,
const nsAString& aValue)
JSAutoStructuredCloneBuffer& aCloneBuffer)
{
NS_ASSERTION(aObjectStore, "Null pointer!");
NS_ASSERTION(!aKey.IsUnset(), "Bad key!");
@ -168,7 +168,7 @@ IDBCursor::Create(IDBRequest* aRequest,
cursor->mObjectStore = aObjectStore;
cursor->mType = OBJECTSTORE;
cursor->mKey = aKey;
cursor->mValue = aValue;
cursor->mCloneBuffer.swap(aCloneBuffer);
return cursor.forget();
}
@ -214,7 +214,7 @@ IDBCursor::Create(IDBRequest* aRequest,
const nsACString& aContinueToQuery,
const Key& aKey,
const Key& aObjectKey,
const nsAString& aValue)
JSAutoStructuredCloneBuffer& aCloneBuffer)
{
NS_ASSERTION(aIndex, "Null pointer!");
NS_ASSERTION(!aKey.IsUnset(), "Bad key!");
@ -230,7 +230,7 @@ IDBCursor::Create(IDBRequest* aRequest,
cursor->mType = INDEXOBJECT;
cursor->mKey = aKey;
cursor->mObjectKey = aObjectKey;
cursor->mValue = aValue;
cursor->mCloneBuffer.swap(aCloneBuffer);
return cursor.forget();
}
@ -285,6 +285,7 @@ IDBCursor::~IDBCursor()
if (mValueRooted) {
NS_DROP_JS_OBJECTS(this, IDBCursor);
}
IDBObjectStore::ClearStructuredCloneBuffer(mCloneBuffer);
}
NS_IMPL_CYCLE_COLLECTION_CLASS(IDBCursor)
@ -411,17 +412,19 @@ IDBCursor::GetValue(JSContext* aCx,
}
if (!mHaveCachedValue) {
JSAutoRequest ar(aCx);
nsCOMPtr<nsIJSON> json(new nsJSON());
rv = json->DecodeToJSVal(mValue, aCx, &mCachedValue);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_DATA_CLONE_ERR);
if (!mValueRooted) {
NS_HOLD_JS_OBJECTS(this, IDBCursor);
mValueRooted = true;
}
JSAutoRequest ar(aCx);
if (!mCloneBuffer.read(&mCachedValue, aCx)) {
mCachedValue = JSVAL_VOID;
return NS_ERROR_DOM_DATA_CLONE_ERR;
}
mCloneBuffer.clear(aCx);
mHaveCachedValue = true;
}
@ -668,7 +671,8 @@ ContinueHelper::GetSuccessResult(nsIWritableVariant* aResult)
// And set new values.
mCursor->mKey = mKey;
mCursor->mObjectKey = mObjectKey;
mCursor->mValue = mValue;
mCursor->mCloneBuffer.clear();
mCursor->mCloneBuffer.swap(mCloneBuffer);
mCursor->mContinueToKey = Key::UNSETKEY;
rv = aResult->SetAsISupports(mCursor);
@ -744,17 +748,9 @@ ContinueObjectStoreHelper::GatherResultsFromStatement(
NS_NOTREACHED("Bad SQLite type!");
}
#ifdef DEBUG
{
PRInt32 valueType;
NS_ASSERTION(NS_SUCCEEDED(aStatement->GetTypeOfIndex(1, &valueType)) &&
valueType == mozIStorageStatement::VALUE_TYPE_TEXT,
"Bad value type!");
}
#endif
rv = aStatement->GetString(1, mValue);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
rv = IDBObjectStore::GetStructuredCloneDataFromStatement(aStatement, 1,
mCloneBuffer);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
@ -912,17 +908,9 @@ ContinueIndexObjectHelper::GatherResultsFromStatement(
NS_NOTREACHED("Bad SQLite type!");
}
#ifdef DEBUG
{
PRInt32 valueType;
NS_ASSERTION(NS_SUCCEEDED(aStatement->GetTypeOfIndex(2, &valueType)) &&
valueType == mozIStorageStatement::VALUE_TYPE_TEXT,
"Bad value type!");
}
#endif
rv = aStatement->GetString(2, mValue);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
rv = IDBObjectStore::GetStructuredCloneDataFromStatement(aStatement, 2,
mCloneBuffer);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}

Просмотреть файл

@ -86,7 +86,7 @@ public:
const nsACString& aContinueQuery,
const nsACString& aContinueToQuery,
const Key& aKey,
const nsAString& aValue);
JSAutoStructuredCloneBuffer& aCloneBuffer);
// For INDEX cursors.
static
@ -113,7 +113,7 @@ public:
const nsACString& aContinueToQuery,
const Key& aKey,
const Key& aObjectKey,
const nsAString& aValue);
JSAutoStructuredCloneBuffer& aCloneBuffer);
enum Type
{
@ -163,7 +163,7 @@ protected:
Key mKey;
Key mObjectKey;
nsString mValue;
JSAutoStructuredCloneBuffer mCloneBuffer;
Key mContinueToKey;
bool mHaveCachedValue;

Просмотреть файл

@ -39,10 +39,12 @@
#include "IDBDatabase.h"
#include "jscntxt.h"
#include "mozilla/Mutex.h"
#include "mozilla/storage.h"
#include "nsDOMClassInfo.h"
#include "nsEventDispatcher.h"
#include "nsJSUtils.h"
#include "nsProxyRelease.h"
#include "nsThreadUtils.h"
@ -523,8 +525,8 @@ IDBDatabase::GetObjectStoreNames(nsIDOMDOMStringList** aObjectStores)
NS_IMETHODIMP
IDBDatabase::CreateObjectStore(const nsAString& aName,
const nsAString& aKeyPath,
PRBool aAutoIncrement,
const jsval& aOptions,
JSContext* aCx,
nsIIDBObjectStore** _retval)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
@ -534,12 +536,6 @@ IDBDatabase::CreateObjectStore(const nsAString& aName,
return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_ERR;
}
// XPConnect makes "null" into a void string, we need an empty string.
nsString keyPath(aKeyPath);
if (keyPath.IsVoid()) {
keyPath.Truncate();
}
IDBTransaction* transaction = AsyncConnectionHelper::GetCurrentTransaction();
if (!transaction ||
@ -556,12 +552,66 @@ IDBDatabase::CreateObjectStore(const nsAString& aName,
return NS_ERROR_DOM_INDEXEDDB_CONSTRAINT_ERR;
}
nsString keyPath;
bool autoIncrement = false;
if (!JSVAL_IS_VOID(aOptions) && !JSVAL_IS_NULL(aOptions)) {
if (JSVAL_IS_PRIMITIVE(aOptions)) {
// XXX Update spec for a real code here
return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_ERR;
}
NS_ASSERTION(JSVAL_IS_OBJECT(aOptions), "Huh?!");
JSObject* options = JSVAL_TO_OBJECT(aOptions);
js::AutoIdArray ids(aCx, JS_Enumerate(aCx, options));
if (!ids) {
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
for (size_t index = 0; index < ids.length(); index++) {
jsid id = ids[index];
if (id != nsDOMClassInfo::sKeyPath_id &&
id != nsDOMClassInfo::sAutoIncrement_id) {
// XXX Update spec for a real code here
return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_ERR;
}
jsval val;
if (!JS_GetPropertyById(aCx, options, id, &val)) {
NS_WARNING("JS_GetPropertyById failed!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
if (id == nsDOMClassInfo::sKeyPath_id) {
JSString* str = JS_ValueToString(aCx, val);
if (!str) {
NS_WARNING("JS_ValueToString failed!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
keyPath = nsDependentJSString(str);
}
else if (id == nsDOMClassInfo::sAutoIncrement_id) {
JSBool boolVal;
if (!JS_ValueToBoolean(aCx, val, &boolVal)) {
NS_WARNING("JS_ValueToBoolean failed!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
autoIncrement = !!boolVal;
}
else {
NS_NOTREACHED("Shouldn't be able to get here!");
}
}
}
nsAutoPtr<ObjectStoreInfo> newInfo(new ObjectStoreInfo());
newInfo->name = aName;
newInfo->id = databaseInfo->nextObjectStoreId++;
newInfo->keyPath = keyPath;
newInfo->autoIncrement = aAutoIncrement;
newInfo->autoIncrement = autoIncrement;
newInfo->databaseId = mDatabaseId;
if (!ObjectStoreInfo::Put(newInfo)) {

Просмотреть файл

@ -355,9 +355,13 @@ IDBSuccessEvent::GetTransaction(nsIIDBTransaction** aTransaction)
GetSuccessEvent::~GetSuccessEvent()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
if (mValueRooted) {
NS_DROP_JS_OBJECTS(this, GetSuccessEvent);
}
IDBObjectStore::ClearStructuredCloneBuffer(mCloneBuffer);
}
nsresult
@ -381,26 +385,22 @@ NS_IMETHODIMP
GetSuccessEvent::GetResult(JSContext* aCx,
jsval* aResult)
{
if (mValue.IsVoid()) {
*aResult = JSVAL_VOID;
return NS_OK;
}
if (!mValueRooted) {
RootCachedValue();
nsString jsonValue = mValue;
mValue.Truncate();
if (mCloneBuffer.data()) {
JSAutoRequest ar(aCx);
nsCOMPtr<nsIJSON> json(new nsJSON());
nsresult rv = json->DecodeToJSVal(jsonValue, aCx, &mCachedValue);
if (NS_FAILED(rv)) {
if (!mCloneBuffer.read(&mCachedValue, aCx)) {
mCachedValue = JSVAL_VOID;
NS_ERROR("Failed to decode!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
return NS_ERROR_DOM_DATA_CLONE_ERR;
}
mCloneBuffer.clear();
}
else {
NS_ASSERTION(JSVAL_IS_VOID(mCachedValue), "Should be undefined!");
}
}
@ -449,55 +449,61 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(GetSuccessEvent)
NS_INTERFACE_MAP_END_INHERITING(IDBSuccessEvent)
GetAllSuccessEvent::~GetAllSuccessEvent()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
for (PRUint32 index = 0; index < mCloneBuffers.Length(); index++) {
IDBObjectStore::ClearStructuredCloneBuffer(mCloneBuffers[index]);
}
}
NS_IMETHODIMP
GetAllSuccessEvent::GetResult(JSContext* aCx,
jsval* aResult)
{
if (!mValueRooted) {
RootCachedValue();
JSAutoRequest ar(aCx);
// Swap into a stack array so that we don't hang on to the strings if
// Swap into a stack array so that we don't hang on to the buffers if
// something fails.
nsTArray<nsString> values;
if (!mValues.SwapElements(values)) {
nsTArray<JSAutoStructuredCloneBuffer> cloneBuffers;
if (!mCloneBuffers.SwapElements(cloneBuffers)) {
NS_ERROR("Failed to swap elements!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
JSAutoRequest ar(aCx);
JSObject* array = JS_NewArrayObject(aCx, 0, NULL);
if (!array) {
NS_ERROR("Failed to make array!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
RootCachedValue();
mCachedValue = OBJECT_TO_JSVAL(array);
if (!values.IsEmpty()) {
if (!JS_SetArrayLength(aCx, array, jsuint(values.Length()))) {
if (!cloneBuffers.IsEmpty()) {
if (!JS_SetArrayLength(aCx, array, jsuint(cloneBuffers.Length()))) {
mCachedValue = JSVAL_VOID;
NS_ERROR("Failed to set array length!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
nsCOMPtr<nsIJSON> json(new nsJSON());
js::AutoValueRooter value(aCx);
jsint count = jsint(values.Length());
jsint count = jsint(cloneBuffers.Length());
for (jsint index = 0; index < count; index++) {
nsString jsonValue = values[index];
values[index].Truncate();
JSAutoStructuredCloneBuffer& buffer = cloneBuffers[index];
nsresult rv = json->DecodeToJSVal(jsonValue, aCx, value.jsval_addr());
if (NS_FAILED(rv)) {
jsval val;
if (!buffer.read(&val, aCx)) {
mCachedValue = JSVAL_VOID;
NS_ERROR("Failed to decode!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
return NS_ERROR_DOM_DATA_CLONE_ERR;
}
if (!JS_SetElement(aCx, array, index, value.jsval_addr())) {
buffer.clear(aCx);
if (!JS_SetElement(aCx, array, index, &val)) {
mCachedValue = JSVAL_VOID;
NS_ERROR("Failed to set array element!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
@ -515,10 +521,6 @@ GetAllKeySuccessEvent::GetResult(JSContext* aCx,
jsval* aResult)
{
if (!mValueRooted) {
RootCachedValue();
JSAutoRequest ar(aCx);
// Swap into a stack array so that we don't hang on to the strings if
// something fails.
nsTArray<Key> keys;
@ -527,12 +529,16 @@ GetAllKeySuccessEvent::GetResult(JSContext* aCx,
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
JSAutoRequest ar(aCx);
JSObject* array = JS_NewArrayObject(aCx, 0, NULL);
if (!array) {
NS_ERROR("Failed to make array!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
RootCachedValue();
mCachedValue = OBJECT_TO_JSVAL(array);
if (!keys.IsEmpty()) {
@ -550,11 +556,12 @@ GetAllKeySuccessEvent::GetResult(JSContext* aCx,
const Key& key = keys[index];
NS_ASSERTION(!key.IsUnset(), "Bad key!");
nsresult rv = IDBObjectStore::GetJSValFromKey(key, aCx, value.jsval_addr());
nsresult rv = IDBObjectStore::GetJSValFromKey(key, aCx,
value.jsval_addr());
if (NS_FAILED(rv)) {
mCachedValue = JSVAL_VOID;
NS_WARNING("Failed to get jsval for key!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
return rv;
}
if (!JS_SetElement(aCx, array, index, value.jsval_addr())) {

Просмотреть файл

@ -151,9 +151,15 @@ protected:
class GetSuccessEvent : public IDBSuccessEvent
{
public:
GetSuccessEvent(const nsAString& aValue)
: mValue(aValue),
mCachedValue(JSVAL_VOID),
GetSuccessEvent(JSAutoStructuredCloneBuffer& aCloneBuffer)
: mCachedValue(JSVAL_VOID),
mValueRooted(PR_FALSE)
{
mCloneBuffer.swap(aCloneBuffer);
}
GetSuccessEvent()
: mCachedValue(JSVAL_VOID),
mValueRooted(PR_FALSE)
{ }
@ -170,7 +176,7 @@ public:
IDBTransaction* aTransaction);
private:
nsString mValue;
JSAutoStructuredCloneBuffer mCloneBuffer;
protected:
void RootCachedValue();
@ -183,26 +189,26 @@ protected:
class GetAllSuccessEvent : public GetSuccessEvent
{
public:
GetAllSuccessEvent(nsTArray<nsString>& aValues)
: GetSuccessEvent(EmptyString())
GetAllSuccessEvent(nsTArray<JSAutoStructuredCloneBuffer>& aCloneBuffers)
{
if (!mValues.SwapElements(aValues)) {
if (!mCloneBuffers.SwapElements(aCloneBuffers)) {
NS_ERROR("Failed to swap elements!");
}
}
~GetAllSuccessEvent();
NS_IMETHOD GetResult(JSContext* aCx,
jsval* aResult);
private:
nsTArray<nsString> mValues;
nsTArray<JSAutoStructuredCloneBuffer> mCloneBuffers;
};
class GetAllKeySuccessEvent : public GetSuccessEvent
{
public:
GetAllKeySuccessEvent(nsTArray<Key>& aKeys)
: GetSuccessEvent(EmptyString())
{
if (!mKeys.SwapElements(aKeys)) {
NS_ERROR("Failed to swap elements!");

Просмотреть файл

@ -70,7 +70,7 @@
#define BAD_TLS_INDEX (PRUintn)-1
#define DB_SCHEMA_VERSION 3
#define DB_SCHEMA_VERSION 4
USING_INDEXEDDB_NAMESPACE
@ -143,6 +143,7 @@ private:
// Out-params.
nsTArray<nsAutoPtr<ObjectStoreInfo> > mObjectStores;
nsString mVersion;
PRUint32 mDataVersion;
nsString mDatabaseFilePath;
PRUint32 mDatabaseId;
PRInt64 mLastObjectStoreId;
@ -160,7 +161,8 @@ CreateTables(mozIStorageConnection* aDBConn)
nsresult rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TABLE database ("
"name TEXT NOT NULL, "
"version TEXT DEFAULT NULL"
"version TEXT DEFAULT NULL, "
"dataVersion INTEGER NOT NULL"
");"
));
NS_ENSURE_SUCCESS(rv, rv);
@ -183,7 +185,7 @@ CreateTables(mozIStorageConnection* aDBConn)
"CREATE TABLE object_data ("
"id INTEGER, "
"object_store_id INTEGER NOT NULL, "
"data TEXT NOT NULL, "
"data BLOB NOT NULL, "
"key_value DEFAULT NULL, " // NONE affinity
"PRIMARY KEY (id), "
"FOREIGN KEY (object_store_id) REFERENCES object_store(id) ON DELETE "
@ -203,7 +205,7 @@ CreateTables(mozIStorageConnection* aDBConn)
"CREATE TABLE ai_object_data ("
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"object_store_id INTEGER NOT NULL, "
"data TEXT NOT NULL, "
"data BLOB NOT NULL, "
"FOREIGN KEY (object_store_id) REFERENCES object_store(id) ON DELETE "
"CASCADE"
");"
@ -328,14 +330,18 @@ CreateMetaData(mozIStorageConnection* aConnection,
nsCOMPtr<mozIStorageStatement> stmt;
nsresult rv = aConnection->CreateStatement(NS_LITERAL_CSTRING(
"INSERT OR REPLACE INTO database (name) "
"VALUES (:name)"
"INSERT OR REPLACE INTO database (name, dataVersion) "
"VALUES (:name, :dataVersion)"
), getter_AddRefs(stmt));
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->BindStringByName(NS_LITERAL_CSTRING("name"), aName);
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("dataVersion"),
JS_STRUCTURED_CLONE_VERSION);
NS_ENSURE_SUCCESS(rv, rv);
return stmt->Execute();
}
@ -549,7 +555,7 @@ IDBFactory::GetConnection(const nsAString& aDatabaseFilePath)
}
#endif
// Turn on foreign key constraints in debug builds to catch bugs!
// Turn on foreign key constraints!
rv = connection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"PRAGMA foreign_keys = ON;"
));
@ -726,7 +732,6 @@ IDBFactory::LoadDatabaseInformation(mozIStorageConnection* aConnection,
if (version.IsVoid()) {
version.SetIsVoid(PR_FALSE);
}
aVersion = version;
return NS_OK;
}
@ -884,6 +889,37 @@ OpenDatabaseHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
getter_AddRefs(connection));
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
// Get the data version.
nsCOMPtr<mozIStorageStatement> stmt;
rv = connection->CreateStatement(NS_LITERAL_CSTRING(
"SELECT dataVersion "
"FROM database"
), getter_AddRefs(stmt));
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
PRBool hasResult;
rv = stmt->ExecuteStep(&hasResult);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
if (!hasResult) {
NS_ERROR("Database has no dataVersion!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
PRInt64 dataVersion;
rv = stmt->GetInt64(0, &dataVersion);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
if (dataVersion > JS_STRUCTURED_CLONE_VERSION) {
NS_ERROR("Bad data version!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
if (dataVersion < JS_STRUCTURED_CLONE_VERSION) {
// Need to upgrade the database, here, before returning to the main thread.
NS_NOTYETIMPLEMENTED("Implement me!");
}
mDatabaseId = HashString(mDatabaseFilePath);
NS_ASSERTION(mDatabaseId, "HashString gave us 0?!");

Просмотреть файл

@ -42,6 +42,7 @@
#include "IDBIndex.h"
#include "nsIIDBKeyRange.h"
#include "nsIJSContextStack.h"
#include "nsDOMClassInfo.h"
#include "nsEventDispatcher.h"
@ -97,8 +98,14 @@ public:
nsresult DoDatabaseWork(mozIStorageConnection* aConnection);
nsresult OnSuccess(nsIDOMEventTarget* aTarget);
void ReleaseMainThreadObjects()
{
IDBObjectStore::ClearStructuredCloneBuffer(mCloneBuffer);
GetKeyHelper::ReleaseMainThreadObjects();
}
protected:
nsString mValue;
JSAutoStructuredCloneBuffer mCloneBuffer;
};
class GetAllKeysHelper : public GetKeyHelper
@ -134,9 +141,17 @@ public:
nsresult DoDatabaseWork(mozIStorageConnection* aConnection);
nsresult OnSuccess(nsIDOMEventTarget* aTarget);
void ReleaseMainThreadObjects()
{
for (PRUint32 index = 0; index < mCloneBuffers.Length(); index++) {
IDBObjectStore::ClearStructuredCloneBuffer(mCloneBuffers[index]);
}
GetKeyHelper::ReleaseMainThreadObjects();
}
protected:
const PRUint32 mLimit;
nsTArray<nsString> mValues;
nsTArray<JSAutoStructuredCloneBuffer> mCloneBuffers;
};
class OpenKeyCursorHelper : public AsyncConnectionHelper
@ -203,6 +218,7 @@ public:
void ReleaseMainThreadObjects()
{
mIndex = nsnull;
IDBObjectStore::ClearStructuredCloneBuffer(mCloneBuffer);
AsyncConnectionHelper::ReleaseMainThreadObjects();
}
@ -218,7 +234,7 @@ private:
// Out-params.
Key mKey;
Key mObjectKey;
nsString mValue;
JSAutoStructuredCloneBuffer mCloneBuffer;
nsCString mContinueQuery;
nsCString mContinueToQuery;
Key mRangeKey;
@ -749,11 +765,9 @@ GetHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
if (hasResult) {
rv = stmt->GetString(0, mValue);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
}
else {
mValue.SetIsVoid(PR_TRUE);
rv = IDBObjectStore::GetStructuredCloneDataFromStatement(stmt, 0,
mCloneBuffer);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
@ -762,7 +776,7 @@ GetHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
nsresult
GetHelper::OnSuccess(nsIDOMEventTarget* aTarget)
{
nsRefPtr<GetSuccessEvent> event(new GetSuccessEvent(mValue));
nsRefPtr<GetSuccessEvent> event(new GetSuccessEvent(mCloneBuffer));
nsresult rv = event->Init(mRequest, mTransaction);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
@ -901,7 +915,7 @@ GetAllHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
{
NS_ASSERTION(aConnection, "Passed a null connection!");
if (!mValues.SetCapacity(50)) {
if (!mCloneBuffers.SetCapacity(50)) {
NS_ERROR("Out of memory!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
@ -978,27 +992,18 @@ GetAllHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
PRBool hasResult;
while(NS_SUCCEEDED((rv = stmt->ExecuteStep(&hasResult))) && hasResult) {
if (mValues.Capacity() == mValues.Length()) {
if (!mValues.SetCapacity(mValues.Capacity() * 2)) {
if (mCloneBuffers.Capacity() == mCloneBuffers.Length()) {
if (!mCloneBuffers.SetCapacity(mCloneBuffers.Capacity() * 2)) {
NS_ERROR("Out of memory!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
}
nsString* value = mValues.AppendElement();
NS_ASSERTION(value, "This shouldn't fail!");
JSAutoStructuredCloneBuffer* buffer = mCloneBuffers.AppendElement();
NS_ASSERTION(buffer, "This shouldn't fail!");
#ifdef DEBUG
{
PRInt32 keyType;
NS_ASSERTION(NS_SUCCEEDED(stmt->GetTypeOfIndex(0, &keyType)) &&
keyType == mozIStorageStatement::VALUE_TYPE_TEXT,
"Bad SQLITE type!");
}
#endif
rv = stmt->GetString(0, *value);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
rv = IDBObjectStore::GetStructuredCloneDataFromStatement(stmt, 0, *buffer);
NS_ENSURE_SUCCESS(rv, rv);
}
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
@ -1008,9 +1013,10 @@ GetAllHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
nsresult
GetAllHelper::OnSuccess(nsIDOMEventTarget* aTarget)
{
nsRefPtr<GetAllSuccessEvent> event(new GetAllSuccessEvent(mValues));
NS_ASSERTION(mCloneBuffers.Length() <= mLimit, "Too many results!");
NS_ASSERTION(mValues.IsEmpty(), "Should have swapped!");
nsRefPtr<GetAllSuccessEvent> event = new GetAllSuccessEvent(mCloneBuffers);
NS_ASSERTION(mCloneBuffers.IsEmpty(), "Should have swapped!");
nsresult rv = event->Init(mRequest, mTransaction);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
@ -1421,17 +1427,9 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
NS_NOTREACHED("Bad SQLite type!");
}
#ifdef DEBUG
{
PRInt32 valueType;
NS_ASSERTION(NS_SUCCEEDED(stmt->GetTypeOfIndex(2, &valueType)) &&
valueType == mozIStorageStatement::VALUE_TYPE_TEXT,
"Bad value type!");
}
#endif
rv = stmt->GetString(2, mValue);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
rv = IDBObjectStore::GetStructuredCloneDataFromStatement(stmt, 2,
mCloneBuffer);
NS_ENSURE_SUCCESS(rv, rv);
/*
SELECT index_data.value, object_data.key_value, object_data.data
@ -1541,7 +1539,7 @@ OpenCursorHelper::GetSuccessResult(nsIWritableVariant* aResult)
nsRefPtr<IDBCursor> cursor =
IDBCursor::Create(mRequest, mTransaction, mIndex, mDirection, mRangeKey,
mContinueQuery, mContinueToQuery, mKey, mObjectKey,
mValue);
mCloneBuffer);
NS_ENSURE_TRUE(cursor, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
aResult->SetAsISupports(cursor);

Просмотреть файл

@ -47,7 +47,6 @@
#include "nsContentUtils.h"
#include "nsDOMClassInfo.h"
#include "nsEventDispatcher.h"
#include "nsJSON.h"
#include "nsJSUtils.h"
#include "nsServiceManagerUtils.h"
#include "nsThreadUtils.h"
@ -70,13 +69,14 @@ public:
AddHelper(IDBTransaction* aTransaction,
IDBRequest* aRequest,
IDBObjectStore* aObjectStore,
const nsAString& aValue,
JSAutoStructuredCloneBuffer& aCloneBuffer,
const Key& aKey,
bool aOverwrite,
nsTArray<IndexUpdateInfo>& aIndexUpdateInfo)
: AsyncConnectionHelper(aTransaction, aRequest), mObjectStore(aObjectStore),
mValue(aValue), mKey(aKey), mOverwrite(aOverwrite)
mKey(aKey), mOverwrite(aOverwrite)
{
mCloneBuffer.swap(aCloneBuffer);
mIndexUpdateInfo.SwapElements(aIndexUpdateInfo);
}
@ -86,6 +86,7 @@ public:
void ReleaseMainThreadObjects()
{
mObjectStore = nsnull;
IDBObjectStore::ClearStructuredCloneBuffer(mCloneBuffer);
AsyncConnectionHelper::ReleaseMainThreadObjects();
}
@ -98,7 +99,7 @@ private:
nsRefPtr<IDBObjectStore> mObjectStore;
// These may change in the autoincrement case.
nsString mValue;
JSAutoStructuredCloneBuffer mCloneBuffer;
Key mKey;
const bool mOverwrite;
nsTArray<IndexUpdateInfo> mIndexUpdateInfo;
@ -121,6 +122,7 @@ public:
void ReleaseMainThreadObjects()
{
mObjectStore = nsnull;
IDBObjectStore::ClearStructuredCloneBuffer(mCloneBuffer);
AsyncConnectionHelper::ReleaseMainThreadObjects();
}
@ -131,7 +133,7 @@ protected:
private:
// Out-params.
nsString mValue;
JSAutoStructuredCloneBuffer mCloneBuffer;
};
class DeleteHelper : public GetHelper
@ -193,6 +195,7 @@ public:
void ReleaseMainThreadObjects()
{
mObjectStore = nsnull;
IDBObjectStore::ClearStructuredCloneBuffer(mCloneBuffer);
AsyncConnectionHelper::ReleaseMainThreadObjects();
}
@ -207,7 +210,7 @@ private:
// Out-params.
Key mKey;
nsString mValue;
JSAutoStructuredCloneBuffer mCloneBuffer;
nsCString mContinueQuery;
nsCString mContinueToQuery;
Key mRangeKey;
@ -289,6 +292,9 @@ public:
void ReleaseMainThreadObjects()
{
mObjectStore = nsnull;
for (PRUint32 index = 0; index < mCloneBuffers.Length(); index++) {
IDBObjectStore::ClearStructuredCloneBuffer(mCloneBuffers[index]);
}
AsyncConnectionHelper::ReleaseMainThreadObjects();
}
@ -303,7 +309,7 @@ protected:
private:
// Out-params.
nsTArray<nsString> mValues;
nsTArray<JSAutoStructuredCloneBuffer> mCloneBuffers;
};
NS_STACK_CLASS
@ -498,12 +504,14 @@ IDBObjectStore::GetJSValFromKey(const Key& aKey,
// static
nsresult
IDBObjectStore::GetKeyPathValueFromJSON(const nsAString& aJSON,
IDBObjectStore::GetKeyPathValueFromStructuredData(const PRUint8* aData,
PRUint32 aDataLength,
const nsAString& aKeyPath,
JSContext** aCx,
Key& aValue)
{
NS_ASSERTION(!aJSON.IsEmpty(), "Empty JSON!");
NS_ASSERTION(aData, "Null pointer!");
NS_ASSERTION(aDataLength, "Empty data!");
NS_ASSERTION(!aKeyPath.IsEmpty(), "Empty keyPath!");
NS_ASSERTION(aCx, "Null pointer!");
@ -513,33 +521,34 @@ IDBObjectStore::GetKeyPathValueFromJSON(const nsAString& aJSON,
rv = nsContentUtils::ThreadJSContextStack()->GetSafeJSContext(aCx);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
}
JSContext*& cx = *aCx;
JSAutoRequest ar(*aCx);
JSAutoRequest ar(cx);
js::AutoValueRooter clone(*aCx);
jsval clone;
if (!JS_ReadStructuredClone(cx, reinterpret_cast<const uint64*>(aData),
aDataLength, JS_STRUCTURED_CLONE_VERSION,
&clone)) {
return NS_ERROR_DOM_DATA_CLONE_ERR;
}
nsCOMPtr<nsIJSON> json(new nsJSON());
rv = json->DecodeToJSVal(aJSON, *aCx, clone.jsval_addr());
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
if (JSVAL_IS_PRIMITIVE(clone.jsval_value())) {
if (JSVAL_IS_PRIMITIVE(clone)) {
// This isn't an object, so just leave the key unset.
aValue = Key::UNSETKEY;
return NS_OK;
}
JSObject* obj = JSVAL_TO_OBJECT(clone.jsval_value());
JSObject* obj = JSVAL_TO_OBJECT(clone);
const jschar* keyPathChars =
reinterpret_cast<const jschar*>(aKeyPath.BeginReading());
const size_t keyPathLen = aKeyPath.Length();
js::AutoValueRooter value(*aCx);
JSBool ok = JS_GetUCProperty(*aCx, obj, keyPathChars, keyPathLen,
value.jsval_addr());
jsval keyVal;
JSBool ok = JS_GetUCProperty(cx, obj, keyPathChars, keyPathLen, &keyVal);
NS_ENSURE_TRUE(ok, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
rv = GetKeyFromJSVal(value.jsval_value(), aValue);
rv = GetKeyFromJSVal(keyVal, aValue);
if (NS_FAILED(rv)) {
// If the object doesn't have a value that we can use for our index then we
// leave it unset.
@ -722,6 +731,62 @@ IDBObjectStore::UpdateIndexes(IDBTransaction* aTransaction,
return NS_OK;
}
// static
nsresult
IDBObjectStore::GetStructuredCloneDataFromStatement(
mozIStorageStatement* aStatement,
PRUint32 aIndex,
JSAutoStructuredCloneBuffer& aBuffer)
{
#ifdef DEBUG
{
PRInt32 valueType;
NS_ASSERTION(NS_SUCCEEDED(aStatement->GetTypeOfIndex(aIndex, &valueType)) &&
valueType == mozIStorageStatement::VALUE_TYPE_BLOB,
"Bad value type!");
}
#endif
const PRUint8* data;
PRUint32 dataLength;
nsresult rv = aStatement->GetSharedBlob(aIndex, &dataLength, &data);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
JSContext* cx;
rv = nsContentUtils::ThreadJSContextStack()->GetSafeJSContext(&cx);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
JSAutoRequest ar(cx);
uint64* newData = static_cast<uint64*>(JS_malloc(cx, dataLength));
NS_ENSURE_TRUE(newData, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
memcpy(newData, data, dataLength);
aBuffer.adopt(cx, newData, dataLength);
return NS_OK;
}
// static
void
IDBObjectStore::ClearStructuredCloneBuffer(JSAutoStructuredCloneBuffer& aBuffer)
{
if (aBuffer.data()) {
JSContext* cx;
if (NS_SUCCEEDED(nsContentUtils::ThreadJSContextStack()->
GetSafeJSContext(&cx))) {
JSAutoRequest ar(cx);
aBuffer.clear(cx);
}
else {
NS_WARNING("Couldn't get safe JSContext! Leaking data!");
uint64* data;
size_t length;
aBuffer.steal(&data, &length);
}
}
}
IDBObjectStore::IDBObjectStore()
: mId(LL_MININT),
mAutoIncrement(PR_FALSE)
@ -738,7 +803,7 @@ nsresult
IDBObjectStore::GetAddInfo(JSContext* aCx,
jsval aValue,
jsval aKeyVal,
nsString& aJSON,
JSAutoStructuredCloneBuffer& aCloneBuffer,
Key& aKey,
nsTArray<IndexUpdateInfo>& aUpdateInfoArray)
{
@ -783,9 +848,9 @@ IDBObjectStore::GetAddInfo(JSContext* aCx,
rv = GetIndexUpdateInfo(info, aCx, aValue, aUpdateInfoArray);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
nsCOMPtr<nsIJSON> json(new nsJSON());
rv = json->EncodeFromJSVal(&aValue, aCx, aJSON);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_DATA_CLONE_ERR);
if (!aCloneBuffer.write(aCx, aValue)) {
return NS_ERROR_DOM_DATA_CLONE_ERR;
}
return NS_OK;
}
@ -810,11 +875,11 @@ IDBObjectStore::AddOrPut(const jsval& aValue,
jsval keyval = (aOptionalArgCount >= 1) ? aKey : JSVAL_VOID;
nsString jsonValue;
JSAutoStructuredCloneBuffer cloneBuffer;
Key key;
nsTArray<IndexUpdateInfo> updateInfo;
nsresult rv = GetAddInfo(aCx, aValue, keyval, jsonValue, key, updateInfo);
nsresult rv = GetAddInfo(aCx, aValue, keyval, cloneBuffer, key, updateInfo);
if (NS_FAILED(rv)) {
return rv;
}
@ -828,7 +893,7 @@ IDBObjectStore::AddOrPut(const jsval& aValue,
NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
nsRefPtr<AddHelper> helper =
new AddHelper(mTransaction, request, this, jsonValue, key, aOverwrite,
new AddHelper(mTransaction, request, this, cloneBuffer, key, aOverwrite,
updateInfo);
rv = helper->DispatchToTransactionPool();
@ -1192,7 +1257,8 @@ IDBObjectStore::OpenCursor(nsIIDBKeyRange* aKeyRange,
NS_IMETHODIMP
IDBObjectStore::CreateIndex(const nsAString& aName,
const nsAString& aKeyPath,
PRBool aUnique,
const jsval& aOptions,
JSContext* aCx,
nsIIDBIndex** _retval)
{
NS_PRECONDITION(NS_IsMainThread(), "Wrong thread!");
@ -1229,6 +1295,51 @@ IDBObjectStore::CreateIndex(const nsAString& aName,
NS_ASSERTION(mTransaction->IsOpen(), "Impossible!");
bool unique = false;
// Get optional arguments.
if (!JSVAL_IS_VOID(aOptions) && !JSVAL_IS_NULL(aOptions)) {
if (JSVAL_IS_PRIMITIVE(aOptions)) {
// XXX Update spec for a real code here
return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_ERR;
}
NS_ASSERTION(JSVAL_IS_OBJECT(aOptions), "Huh?!");
JSObject* options = JSVAL_TO_OBJECT(aOptions);
js::AutoIdArray ids(aCx, JS_Enumerate(aCx, options));
if (!ids) {
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
for (size_t index = 0; index < ids.length(); index++) {
jsid id = ids[index];
if (id != nsDOMClassInfo::sUnique_id) {
// XXX Update spec for a real code here
return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_ERR;
}
jsval val;
if (!JS_GetPropertyById(aCx, options, id, &val)) {
NS_WARNING("JS_GetPropertyById failed!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
if (id == nsDOMClassInfo::sUnique_id) {
JSBool boolVal;
if (!JS_ValueToBoolean(aCx, val, &boolVal)) {
NS_WARNING("JS_ValueToBoolean failed!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
unique = !!boolVal;
}
else {
NS_NOTREACHED("Shouldn't be able to get here!");
}
}
}
DatabaseInfo* databaseInfo;
if (!DatabaseInfo::Get(mTransaction->Database()->Id(), &databaseInfo)) {
NS_ERROR("This should never fail!");
@ -1243,7 +1354,7 @@ IDBObjectStore::CreateIndex(const nsAString& aName,
indexInfo->id = databaseInfo->nextIndexId++;
indexInfo->name = aName;
indexInfo->keyPath = aKeyPath;
indexInfo->unique = aUnique;
indexInfo->unique = unique;
indexInfo->autoIncrement = mAutoIncrement;
// Don't leave this in the list if we fail below!
@ -1459,12 +1570,20 @@ AddHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
}
rv = stmt->BindStringByName(NS_LITERAL_CSTRING("data"), mValue);
const PRUint8* buffer = reinterpret_cast<const PRUint8*>(mCloneBuffer.data());
size_t bufferLength = mCloneBuffer.nbytes();
rv = stmt->BindBlobByName(NS_LITERAL_CSTRING("data"), buffer, bufferLength);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
rv = stmt->Execute();
if (NS_FAILED(rv)) {
if (mayOverwrite && rv == NS_ERROR_STORAGE_CONSTRAINT) {
scoper.Abandon();
rv = stmt->Reset();
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
stmt = mTransaction->AddStatement(false, true, autoIncrement);
NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
@ -1486,7 +1605,8 @@ AddHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
}
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
rv = stmt->BindStringByName(NS_LITERAL_CSTRING("data"), mValue);
rv = stmt->BindBlobByName(NS_LITERAL_CSTRING("data"), buffer,
bufferLength);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
rv = stmt->Execute();
@ -1535,7 +1655,11 @@ AddHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
rv = stmt->BindInt64ByName(keyValue, mKey.IntValue());
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
rv = stmt->BindStringByName(NS_LITERAL_CSTRING("data"), mValue);
buffer = reinterpret_cast<const PRUint8*>(mCloneBuffer.data());
bufferLength = mCloneBuffer.nbytes();
rv = stmt->BindBlobByName(NS_LITERAL_CSTRING("data"), buffer,
bufferLength);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
rv = stmt->Execute();
@ -1591,33 +1715,38 @@ AddHelper::ModifyValueForNewKey()
JSAutoRequest ar(cx);
js::AutoValueRooter clone(cx);
jsval clone;
if (!mCloneBuffer.read(&clone, cx)) {
return NS_ERROR_DOM_DATA_CLONE_ERR;
}
nsCOMPtr<nsIJSON> json(new nsJSON());
rv = json->DecodeToJSVal(mValue, cx, clone.jsval_addr());
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(!JSVAL_IS_PRIMITIVE(clone), "We should have an object!");
JSObject* obj = JSVAL_TO_OBJECT(clone.jsval_value());
JSObject* obj = JSVAL_TO_OBJECT(clone);
JSBool ok;
js::AutoValueRooter key(cx);
const jschar* keyPathChars = reinterpret_cast<const jschar*>(keyPath.get());
const size_t keyPathLen = keyPath.Length();
#ifdef DEBUG
ok = JS_GetUCProperty(cx, obj, keyPathChars, keyPathLen, key.jsval_addr());
NS_ASSERTION(ok && JSVAL_IS_VOID(key.jsval_value()), "Already has a key prop!");
{
jsval prop;
ok = JS_GetUCProperty(cx, obj, keyPathChars, keyPathLen, &prop);
NS_ASSERTION(ok && JSVAL_IS_VOID(prop), "Already has a key prop!");
}
#endif
ok = JS_NewNumberValue(cx, mKey.IntValue(), key.jsval_addr());
jsval key;
ok = JS_NewNumberValue(cx, mKey.IntValue(), &key);
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
ok = JS_DefineUCProperty(cx, obj, keyPathChars, keyPathLen, key.jsval_value(),
nsnull, nsnull, JSPROP_ENUMERATE);
ok = JS_DefineUCProperty(cx, obj, keyPathChars, keyPathLen, key, nsnull,
nsnull, JSPROP_ENUMERATE);
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
rv = json->EncodeFromJSVal(clone.jsval_addr(), cx, mValue);
NS_ENSURE_SUCCESS(rv, rv);
if (!mCloneBuffer.write(cx, OBJECT_TO_JSVAL(obj))) {
return NS_ERROR_DOM_DATA_CLONE_ERR;
}
return NS_OK;
}
@ -1658,12 +1787,9 @@ GetHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
if (hasResult) {
// Set the value based on results.
rv = stmt->GetString(0, mValue);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
}
else {
mValue.SetIsVoid(PR_TRUE);
rv = IDBObjectStore::GetStructuredCloneDataFromStatement(stmt, 0,
mCloneBuffer);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
@ -1672,12 +1798,12 @@ GetHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
nsresult
GetHelper::OnSuccess(nsIDOMEventTarget* aTarget)
{
if (mValue.IsVoid()) {
if (!mCloneBuffer.data()) {
// Default is to have an undefined result.
return AsyncConnectionHelper::OnSuccess(aTarget);
}
nsRefPtr<GetSuccessEvent> event(new GetSuccessEvent(mValue));
nsRefPtr<GetSuccessEvent> event(new GetSuccessEvent(mCloneBuffer));
nsresult rv = event->Init(mRequest, mTransaction);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
@ -1886,17 +2012,9 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
NS_NOTREACHED("Bad SQLite type!");
}
#ifdef DEBUG
{
PRInt32 valueType;
NS_ASSERTION(NS_SUCCEEDED(stmt->GetTypeOfIndex(1, &valueType)) &&
valueType == mozIStorageStatement::VALUE_TYPE_TEXT,
"Bad value type!");
}
#endif
rv = stmt->GetString(1, mValue);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
rv = IDBObjectStore::GetStructuredCloneDataFromStatement(stmt, 1,
mCloneBuffer);
NS_ENSURE_SUCCESS(rv, rv);
// Now we need to make the query to get the next match.
keyRangeClause.Truncate();
@ -1965,7 +2083,7 @@ OpenCursorHelper::GetSuccessResult(nsIWritableVariant* aResult)
nsRefPtr<IDBCursor> cursor =
IDBCursor::Create(mRequest, mTransaction, mObjectStore, mDirection,
mRangeKey, mContinueQuery, mContinueToQuery, mKey,
mValue);
mCloneBuffer);
NS_ENSURE_TRUE(cursor, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
aResult->SetAsISupports(cursor);
@ -2081,14 +2199,16 @@ CreateIndexHelper::InsertDataFromObjectStore(mozIStorageConnection* aConnection)
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
}
nsString json;
rv = stmt->GetString(1, json);
const PRUint8* data;
PRUint32 dataLength;
rv = stmt->GetSharedBlob(1, &dataLength, &data);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
Key key;
JSContext* cx = nsnull;
rv = IDBObjectStore::GetKeyPathValueFromJSON(json, mIndex->KeyPath(), &cx,
key);
rv = IDBObjectStore::GetKeyPathValueFromStructuredData(data, dataLength,
mIndex->KeyPath(),
&cx, key);
NS_ENSURE_SUCCESS(rv, rv);
NS_NAMED_LITERAL_CSTRING(value, "value");
@ -2221,7 +2341,7 @@ GetAllHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
keyRangeClause + NS_LITERAL_CSTRING(" ORDER BY ") +
keyColumn + NS_LITERAL_CSTRING(" ASC") + limitClause;
if (!mValues.SetCapacity(50)) {
if (!mCloneBuffers.SetCapacity(50)) {
NS_ERROR("Out of memory!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
@ -2262,18 +2382,18 @@ GetAllHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
PRBool hasResult;
while (NS_SUCCEEDED((rv = stmt->ExecuteStep(&hasResult))) && hasResult) {
if (mValues.Capacity() == mValues.Length()) {
if (!mValues.SetCapacity(mValues.Capacity() * 2)) {
if (mCloneBuffers.Capacity() == mCloneBuffers.Length()) {
if (!mCloneBuffers.SetCapacity(mCloneBuffers.Capacity() * 2)) {
NS_ERROR("Out of memory!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
}
nsString* value = mValues.AppendElement();
NS_ASSERTION(value, "Shouldn't fail if SetCapacity succeeded!");
JSAutoStructuredCloneBuffer* buffer = mCloneBuffers.AppendElement();
NS_ASSERTION(buffer, "Shouldn't fail if SetCapacity succeeded!");
rv = stmt->GetString(0, *value);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
rv = IDBObjectStore::GetStructuredCloneDataFromStatement(stmt, 0, *buffer);
NS_ENSURE_SUCCESS(rv, rv);
}
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
@ -2283,11 +2403,10 @@ GetAllHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
nsresult
GetAllHelper::OnSuccess(nsIDOMEventTarget* aTarget)
{
NS_ASSERTION(mValues.Length() <= mLimit, "Too many results!");
NS_ASSERTION(mCloneBuffers.Length() <= mLimit, "Too many results!");
nsRefPtr<GetAllSuccessEvent> event(new GetAllSuccessEvent(mValues));
NS_ASSERTION(mValues.IsEmpty(), "Should have swapped!");
nsRefPtr<GetAllSuccessEvent> event = new GetAllSuccessEvent(mCloneBuffers);
NS_ASSERTION(mCloneBuffers.IsEmpty(), "Should have swapped!");
nsresult rv = event->Init(mRequest, mTransaction);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);

Просмотреть файл

@ -86,7 +86,8 @@ public:
jsval* aKeyVal);
static nsresult
GetKeyPathValueFromJSON(const nsAString& aJSON,
GetKeyPathValueFromStructuredData(const PRUint8* aData,
PRUint32 aDataLength,
const nsAString& aKeyPath,
JSContext** aCx,
Key& aValue);
@ -106,6 +107,14 @@ public:
PRInt64 aObjectDataId,
const nsTArray<IndexUpdateInfo>& aUpdateInfoArray);
static nsresult
GetStructuredCloneDataFromStatement(mozIStorageStatement* aStatement,
PRUint32 aIndex,
JSAutoStructuredCloneBuffer& aBuffer);
static void
ClearStructuredCloneBuffer(JSAutoStructuredCloneBuffer& aBuffer);
const nsString& Name() const
{
return mName;
@ -144,7 +153,7 @@ protected:
nsresult GetAddInfo(JSContext* aCx,
jsval aValue,
jsval aKeyVal,
nsString& aJSON,
JSAutoStructuredCloneBuffer& aCloneBuffer,
Key& aKey,
nsTArray<IndexUpdateInfo>& aUpdateInfoArray);
@ -166,6 +175,7 @@ private:
nsString mKeyPath;
PRBool mAutoIncrement;
PRUint32 mDatabaseId;
PRUint32 mStructuredCloneVersion;
nsTArray<nsRefPtr<IDBIndex> > mCreatedIndexes;

Просмотреть файл

@ -55,7 +55,7 @@ interface nsIDOMEventListener;
* http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBDatabase
* for more information.
*/
[scriptable, uuid(6563ebdc-4509-4aeb-ac14-7e78ad74e2d3)]
[scriptable, uuid(42b38d02-1a29-45f0-99ef-04fd5b441270)]
interface nsIIDBDatabase : nsISupports
{
readonly attribute DOMString name;
@ -64,10 +64,18 @@ interface nsIIDBDatabase : nsISupports
readonly attribute nsIDOMDOMStringList objectStoreNames;
/**
* Optional arguments:
* - keyPath (string):
* Specifies key path on objects in the objectStore. Defaults to no key
* path.
* - autoIncrement (boolean):
* Specifies if the objectStore has a key generator. Defaults to false.
*/
[implicit_jscontext]
nsIIDBObjectStore
createObjectStore(in AString name,
[optional /* none */] in AString keyPath,
[optional /* false */] in boolean autoIncrement);
[optional /* none */] in jsval options);
void
deleteObjectStore(in AString name);

Просмотреть файл

@ -55,7 +55,7 @@ interface nsIDOMDOMStringList;
* http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-nsIIDBObjectStore
* for more information.
*/
[scriptable, uuid(64f34805-d3e3-4305-91f8-b2cafac3d33c)]
[scriptable, uuid(6a65dc92-66e3-407a-a370-590a6c54664a)]
interface nsIIDBObjectStore : nsISupports
{
readonly attribute DOMString name;
@ -104,11 +104,17 @@ interface nsIIDBObjectStore : nsISupports
openCursor([optional /* null */] in nsIIDBKeyRange range,
[optional /* NEXT */] in unsigned short direction);
// Returns object immediately
/**
* Optional arguments:
* - unique (boolean):
* Specifies whether values in the index must be unique. Defaults to
* false.
*/
[implicit_jscontext]
nsIIDBIndex
createIndex(in AString name,
in AString keyPath,
[optional /* false */] in boolean unique);
[optional /* none */] in jsval options);
// Returns object immediately
nsIIDBIndex

Просмотреть файл

@ -13,7 +13,7 @@ moz_indexedDB.open(parent.location).onsuccess = function(e) {
if (db.objectStoreNames.contains("mystore")) {
db.deleteObjectStore("mystore");
}
var store = db.createObjectStore("mystore", "");
var store = db.createObjectStore("mystore");
store.add({ hello: "world" }, 42);
trans.oncomplete = function() {
parent.postMessage("go", "http://mochi.test:8888");

Просмотреть файл

@ -67,7 +67,7 @@
request.onsuccess = grabEventAndContinueHandler;
event = yield;
db.createObjectStore("foo", "", true);
db.createObjectStore("foo", { autoIncrement: true });
setTimeout(testFinishedCallback, 0, "ready");
yield;

Просмотреть файл

@ -77,7 +77,7 @@
is(db.version, "1", "Correct version");
is(db.objectStoreNames.length, 0, "Correct objectStoreNames length");
let objectStore = db.createObjectStore("foo", "");
let objectStore = db.createObjectStore("foo");
is(db.objectStoreNames.length, 1, "Correct objectStoreNames length");
ok(db.objectStoreNames.contains("foo"), "Has correct objectStore");
@ -110,7 +110,7 @@
is(db.version, "1", "Correct version");
is(db.objectStoreNames.length, 0, "Correct objectStoreNames length");
let objectStore = db.createObjectStore("foo", "");
let objectStore = db.createObjectStore("foo");
is(db.objectStoreNames.length, 1, "Correct objectStoreNames length");
ok(db.objectStoreNames.contains("foo"), "Has correct objectStore");

Просмотреть файл

@ -111,7 +111,7 @@
event.transaction.oncomplete = grabEventAndContinueHandler;
db.createObjectStore("foo", "", true);
db.createObjectStore("foo", { autoIncrement: true });
yield;
let transaction = db.transaction("foo", IDBTransaction.READ_WRITE);

Просмотреть файл

@ -82,7 +82,7 @@
is(db.version, "1", "Correct version");
is(db.objectStoreNames.length, 0, "Correct objectStoreNames length");
let objectStore = db.createObjectStore("foo", "");
let objectStore = db.createObjectStore("foo");
is(db.objectStoreNames.length, 1, "Correct objectStoreNames length");
ok(db.objectStoreNames.contains("foo"), "Has correct objectStore");

Просмотреть файл

@ -28,7 +28,7 @@
request.onsuccess = grabEventAndContinueHandler;
let event = yield;
let objectStore = db.createObjectStore("foo", "");
let objectStore = db.createObjectStore("foo", { keyPath: "" });
let key = 10;
request = objectStore.add({}, key);

Просмотреть файл

@ -28,7 +28,7 @@
request.onsuccess = grabEventAndContinueHandler;
event = yield;
let objectStore = db.createObjectStore("foo", "keyPath");
let objectStore = db.createObjectStore("foo", { keyPath: "keyPath" });
request = objectStore.add({keyPath:"foo"});
request.onerror = errorHandler;

Просмотреть файл

@ -10,6 +10,8 @@
<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">
SimpleTest.requestLongerTimeout(2);
var gOrigMaxTotalViewers = undefined;
function setCachePref(enabled) {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');

Просмотреть файл

@ -33,7 +33,7 @@
event.transaction.oncomplete = continueToNextStep;
let objectStore = db.createObjectStore("foo", "", true);
let objectStore = db.createObjectStore("foo", { autoIncrement: true });
let firstKey;
for (let i = 0; i < entryCount; i++) {

Просмотреть файл

@ -19,13 +19,13 @@
const name = window.location.pathname;
const description = "My Test Database";
const objectStoreInfo = [
{ name: "a", keyPath: "id", autoIncrement: true },
{ name: "b", keyPath: "id", autoIncrement: false },
{ name: "a", options: { keyPath: "id", autoIncrement: true } },
{ name: "b", options: { keyPath: "id", autoIncrement: false } },
];
const indexInfo = [
{ name: "1", keyPath: "unique_value", unique: true },
{ name: "2", keyPath: "value", unique: false },
{ name: "3", keyPath: "value" },
{ name: "1", keyPath: "unique_value", options: { unique: true } },
{ name: "2", keyPath: "value", options: { unique: false } },
{ name: "3", keyPath: "value", options: { unique: false } },
];
let request = moz_indexedDB.open(name, description);
@ -41,10 +41,9 @@
for (let i = 0; i < objectStoreInfo.length; i++) {
let info = objectStoreInfo[i];
let objectStore = info.hasOwnProperty("autoIncrement") ?
db.createObjectStore(info.name, info.keyPath,
info.autoIncrement) :
db.createObjectStore(info.name, info.keyPath);
let objectStore = info.hasOwnProperty("options") ?
db.createObjectStore(info.name, info.options) :
db.createObjectStore(info.name);
// Test basic failure conditions.
try {
@ -71,19 +70,35 @@
ok(true, "createIndex with no keyPath should throw");
}
try {
request = objectStore.createIndex("foo", "bar", 10);
ok(false, "createIndex with bad options should throw");
}
catch(e) {
ok(true, "createIndex with bad options threw");
}
try {
request = objectStore.createIndex("foo", "bar", { foo: "" });
ok(false, "createIndex with bad options should throw");
}
catch(e) {
ok(true, "createIndex with bad options threw");
}
// Test index creation, and that it ends up in indexNames.
let objectStoreName = info.name;
for (let j = 0; j < indexInfo.length; j++) {
let info = indexInfo[j];
let count = objectStore.indexNames.length;
let index = info.hasOwnProperty("unique") ?
let index = info.hasOwnProperty("options") ?
objectStore.createIndex(info.name, info.keyPath,
info.unique) :
info.options) :
objectStore.createIndex(info.name, info.keyPath);
is(index.name, info.name, "correct name");
is(index.keyPath, info.keyPath, "correct keyPath");
is(index.unique, !!info.unique, "correct uniqueness");
is(index.unique, info.options.unique, "correct uniqueness");
is(objectStore.indexNames.length, count + 1,
"indexNames grew in size");

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше