зеркало из https://github.com/mozilla/gecko-dev.git
Backing out part 5 of bug 617152. a=blocking
This commit is contained in:
Коммит
0a31156e28
1
.hgtags
1
.hgtags
|
@ -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, ¬used);
|
||||
*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(¬used, &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(¬used, &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, ¬used);
|
||||
|
||||
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");
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче