зеркало из https://github.com/mozilla/pjs.git
Merge mozilla-central to tracemonkey.
This commit is contained in:
Коммит
b8b5a371a7
|
@ -2766,6 +2766,13 @@ nsAccessible::RemoveChild(nsAccessible* aChild)
|
|||
if (aChild->mParent != this || aChild->mIndexInParent == -1)
|
||||
return PR_FALSE;
|
||||
|
||||
if (aChild->mIndexInParent >= mChildren.Length() ||
|
||||
mChildren[aChild->mIndexInParent] != aChild) {
|
||||
NS_ERROR("Child is bound to parent but parent hasn't this child at its index!");
|
||||
aChild->UnbindFromParent();
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
for (PRUint32 idx = aChild->mIndexInParent + 1; idx < mChildren.Length(); idx++)
|
||||
mChildren[idx]->mIndexInParent--;
|
||||
|
||||
|
|
|
@ -1538,7 +1538,7 @@ nsHyperTextAccessible::SetSelectionRange(PRInt32 aStartPos, PRInt32 aEndPos)
|
|||
// XXX I'm not sure this can do synchronous scrolling. If the last param is
|
||||
// set to true, this calling might flush the pending reflow. See bug 418470.
|
||||
selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL,
|
||||
nsISelectionController::SELECTION_FOCUS_REGION, PR_FALSE);
|
||||
nsISelectionController::SELECTION_FOCUS_REGION, 0);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -330,6 +330,7 @@ pref("browser.search.log", false);
|
|||
// Ordering of Search Engines in the Engine list.
|
||||
pref("browser.search.order.1", "chrome://browser-region/locale/region.properties");
|
||||
pref("browser.search.order.2", "chrome://browser-region/locale/region.properties");
|
||||
pref("browser.search.order.3", "chrome://browser-region/locale/region.properties");
|
||||
|
||||
// search bar results always open in a new tab
|
||||
pref("browser.search.openintab", false);
|
||||
|
|
|
@ -787,7 +787,6 @@ const gFormSubmitObserver = {
|
|||
init: function()
|
||||
{
|
||||
this.panel = document.getElementById('invalid-form-popup');
|
||||
this.panel.appendChild(document.createTextNode(""));
|
||||
},
|
||||
|
||||
panelIsOpen: function()
|
||||
|
@ -820,8 +819,7 @@ const gFormSubmitObserver = {
|
|||
return;
|
||||
}
|
||||
|
||||
// Limit the message to 256 characters.
|
||||
this.panel.firstChild.nodeValue = element.validationMessage.substring(0, 256);
|
||||
this.panel.firstChild.textContent = element.validationMessage;
|
||||
|
||||
element.focus();
|
||||
|
||||
|
@ -5092,54 +5090,28 @@ function asyncOpenWebPanel(event)
|
|||
return true;
|
||||
}
|
||||
|
||||
function handleLinkClick(event, href, linkNode)
|
||||
{
|
||||
function handleLinkClick(event, href, linkNode) {
|
||||
if (event.button == 2) // right click
|
||||
return false;
|
||||
|
||||
var where = whereToOpenLink(event);
|
||||
if (where == "current")
|
||||
return false;
|
||||
|
||||
var doc = event.target.ownerDocument;
|
||||
|
||||
switch (event.button) {
|
||||
case 0: // if left button clicked
|
||||
#ifdef XP_MACOSX
|
||||
if (event.metaKey) { // Cmd
|
||||
#else
|
||||
if (event.ctrlKey) {
|
||||
#endif
|
||||
openNewTabWith(href, doc, null, event, false);
|
||||
event.stopPropagation();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event.shiftKey && event.altKey) {
|
||||
var feedService =
|
||||
Cc["@mozilla.org/browser/feeds/result-service;1"].
|
||||
getService(Ci.nsIFeedResultService);
|
||||
feedService.forcePreviewPage = true;
|
||||
loadURI(href, null, null, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event.shiftKey) {
|
||||
openNewWindowWith(href, doc, null, false);
|
||||
event.stopPropagation();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event.altKey) {
|
||||
saveURL(href, linkNode ? gatherTextUnder(linkNode) : "", null, true,
|
||||
true, doc.documentURIObject);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
case 1: // if middle button clicked
|
||||
var tab = gPrefService.getBoolPref("browser.tabs.opentabfor.middleclick");
|
||||
if (tab)
|
||||
openNewTabWith(href, doc, null, event, false);
|
||||
else
|
||||
openNewWindowWith(href, doc, null, false);
|
||||
event.stopPropagation();
|
||||
return true;
|
||||
if (where == "save") {
|
||||
saveURL(href, linkNode ? gatherTextUnder(linkNode) : "", null, true,
|
||||
true, doc.documentURIObject);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
urlSecurityCheck(href, doc.nodePrincipal);
|
||||
openLinkIn(href, where, { fromContent: true,
|
||||
referrerURI: doc.documentURIObject,
|
||||
charset: doc.characterSet });
|
||||
event.stopPropagation();
|
||||
return true;
|
||||
}
|
||||
|
||||
function middleMousePaste(event) {
|
||||
|
|
|
@ -167,7 +167,9 @@
|
|||
<panel type="autocomplete-richlistbox" id="PopupAutoCompleteRichResult" noautofocus="true" hidden="true"/>
|
||||
|
||||
<!-- for invalid form error message -->
|
||||
<panel id="invalid-form-popup" noautofocus="true" hidden="true" level="parent"/>
|
||||
<panel id="invalid-form-popup" noautofocus="true" hidden="true" level="parent">
|
||||
<description/>
|
||||
</panel>
|
||||
|
||||
<panel id="editBookmarkPanel"
|
||||
orient="vertical"
|
||||
|
|
|
@ -958,14 +958,17 @@ nsContextMenu.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
// in case we need to prompt the user for authentication
|
||||
function callbacks() {}
|
||||
callbacks.prototype = {
|
||||
getInterface: function sLA_callbacks_getInterface(aIID) {
|
||||
if (aIID.equals(Ci.nsIAuthPrompt) || aIID.equals(Ci.nsIAuthPrompt2)) {
|
||||
var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
|
||||
getService(Ci.nsIPromptFactory);
|
||||
return ww.getPrompt(doc.defaultView, aIID);
|
||||
// If the channel demands authentication prompt, we must cancel it
|
||||
// because the save-as-timer would expire and cancel the channel
|
||||
// before we get credentials from user. Both authentication dialog
|
||||
// and save as dialog would appear on the screen as we fall back to
|
||||
// the old fashioned way after the timeout.
|
||||
timer.cancel();
|
||||
channel.cancel(NS_ERROR_SAVE_LINK_AS_TIMEOUT);
|
||||
}
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
|
|
|
@ -70,6 +70,7 @@ function GroupItem(listOfEls, options) {
|
|||
options = {};
|
||||
|
||||
this._inited = false;
|
||||
this._uninited = false;
|
||||
this._children = []; // an array of Items
|
||||
this.defaultSize = new Point(TabItems.tabWidth * 1.5, TabItems.tabHeight * 1.5);
|
||||
this.isAGroupItem = true;
|
||||
|
@ -366,7 +367,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
|||
// Function: save
|
||||
// Saves this groupItem to persistent storage.
|
||||
save: function GroupItem_save() {
|
||||
if (!this._inited) // too soon to save now
|
||||
if (!this._inited || this._uninited) // too soon/late to save
|
||||
return;
|
||||
|
||||
var data = this.getStorageData();
|
||||
|
@ -374,6 +375,14 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
|||
Storage.saveGroupItem(gWindow, data);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: deleteData
|
||||
// Deletes the groupItem in the persistent storage.
|
||||
deleteData: function GroupItem_deleteData() {
|
||||
this._uninited = true;
|
||||
Storage.deleteGroupItem(gWindow, this.id);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: getTitle
|
||||
// Returns the title of this groupItem as a string.
|
||||
|
@ -561,7 +570,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
|||
}
|
||||
});
|
||||
|
||||
Storage.deleteGroupItem(gWindow, this.id);
|
||||
this.deleteData();
|
||||
},
|
||||
|
||||
// ----------
|
||||
|
@ -647,7 +656,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
|||
self.$undoContainer = null;
|
||||
Items.unsquish();
|
||||
|
||||
Storage.deleteGroupItem(gWindow, self.id);
|
||||
self.deleteData();
|
||||
};
|
||||
|
||||
this.$undoContainer.click(function(e) {
|
||||
|
@ -2072,7 +2081,7 @@ let GroupItems = {
|
|||
child.close();
|
||||
});
|
||||
|
||||
Storage.deleteGroupItem(gWindow, groupItem.id);
|
||||
groupItem.deleteData();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -202,11 +202,10 @@ function TabItem(tab, options) {
|
|||
this._updateDebugBounds();
|
||||
|
||||
TabItems.register(this);
|
||||
|
||||
if (!this.reconnected) {
|
||||
|
||||
if (!this.reconnected)
|
||||
GroupItems.newTab(this, options);
|
||||
}
|
||||
|
||||
|
||||
// tabs which were not reconnected at all or were not immediately added
|
||||
// to a group get the same treatment.
|
||||
if (!this.reconnected || (reconnected && !reconnected.addedToGroup) ) {
|
||||
|
@ -804,7 +803,7 @@ let TabItems = {
|
|||
let oldURL = tabItem.url;
|
||||
tabItem.url = tabUrl;
|
||||
|
||||
if (!tabItem.reconnected && (oldURL == 'about:blank' || !oldURL))
|
||||
if (!tabItem.reconnected)
|
||||
this.reconnect(tabItem);
|
||||
|
||||
tabItem.save();
|
||||
|
@ -1057,10 +1056,10 @@ let TabItems = {
|
|||
item.reconnected = true;
|
||||
found = {addedToGroup: tabData.groupID};
|
||||
} else {
|
||||
// if it's not a blank tab or it belongs to a group, it would mean
|
||||
// the item is reconnected.
|
||||
item.reconnected =
|
||||
(item.tab.linkedBrowser.currentURI.spec != 'about:blank' || item.parent);
|
||||
// We should never have any orphaned tabs. Therefore, item is not
|
||||
// connected if it has no parent and GroupItems.newTab() would handle
|
||||
// the group creation.
|
||||
item.reconnected = (item.parent != null);
|
||||
}
|
||||
item.save();
|
||||
|
||||
|
|
|
@ -16,9 +16,9 @@ function checkPopupHide()
|
|||
|
||||
function checkPopupMessage(doc)
|
||||
{
|
||||
is(gInvalidFormPopup.firstChild.nodeValue,
|
||||
doc.getElementById('i').validationMessage.substring(0,256),
|
||||
"The panel should show the 256 first characters of the validationMessage");
|
||||
is(gInvalidFormPopup.firstChild.textContent,
|
||||
doc.getElementById('i').validationMessage,
|
||||
"The panel should show the message from validationMessage");
|
||||
}
|
||||
|
||||
let gObserver = {
|
||||
|
@ -132,50 +132,11 @@ function test3()
|
|||
gBrowser.selectedTab.linkedBrowser.loadURI(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* In this test, we check that the validation message is correctly cut.
|
||||
*/
|
||||
function test4()
|
||||
{
|
||||
let uri = "data:text/html,<iframe name='t'></iframe><form target='t' action='data:text/html,'><input id='i'><input id='s' type='submit'></form>";
|
||||
let tab = gBrowser.addTab();
|
||||
|
||||
gInvalidFormPopup.addEventListener("popupshown", function() {
|
||||
gInvalidFormPopup.removeEventListener("popupshown", arguments.callee, false);
|
||||
|
||||
let doc = gBrowser.contentDocument;
|
||||
is(doc.activeElement, doc.getElementById('i'),
|
||||
"First invalid element should be focused");
|
||||
|
||||
checkPopupShow();
|
||||
checkPopupMessage(doc);
|
||||
|
||||
// Clean-up and next test.
|
||||
gBrowser.removeTab(gBrowser.selectedTab, {animate: false});
|
||||
executeSoon(test5);
|
||||
}, false);
|
||||
|
||||
tab.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
let msg = "";
|
||||
for (let i=0; i<50; ++i) {
|
||||
msg += "abcde ";
|
||||
}
|
||||
// msg has 300 characters
|
||||
gBrowser.contentDocument.getElementById('i').setCustomValidity(msg);
|
||||
gBrowser.contentDocument.getElementById('s').click();
|
||||
}, true);
|
||||
|
||||
gBrowser.selectedTab = tab;
|
||||
gBrowser.selectedTab.linkedBrowser.loadURI(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* In this test, we check that, we can hide the popup by interacting with the
|
||||
* invalid element.
|
||||
*/
|
||||
function test5()
|
||||
function test4()
|
||||
{
|
||||
let uri = "data:text/html,<iframe name='t'></iframe><form target='t' action='data:text/html,'><input id='i' required><input id='s' type='submit'></form>";
|
||||
let tab = gBrowser.addTab();
|
||||
|
@ -197,7 +158,7 @@ function test5()
|
|||
|
||||
// Clean-up and next test.
|
||||
gBrowser.removeTab(gBrowser.selectedTab, {animate: false});
|
||||
executeSoon(test6);
|
||||
executeSoon(test5);
|
||||
});
|
||||
}, false);
|
||||
|
||||
|
@ -215,7 +176,7 @@ function test5()
|
|||
* In this test, we check that we can hide the popup by blurring the invalid
|
||||
* element.
|
||||
*/
|
||||
function test6()
|
||||
function test5()
|
||||
{
|
||||
let uri = "data:text/html,<iframe name='t'></iframe><form target='t' action='data:text/html,'><input id='i' required><input id='s' type='submit'></form>";
|
||||
let tab = gBrowser.addTab();
|
||||
|
@ -237,7 +198,7 @@ function test6()
|
|||
|
||||
// Clean-up and next test.
|
||||
gBrowser.removeTab(gBrowser.selectedTab, {animate: false});
|
||||
executeSoon(test7);
|
||||
executeSoon(test6);
|
||||
});
|
||||
}, false);
|
||||
|
||||
|
@ -254,7 +215,7 @@ function test6()
|
|||
/**
|
||||
* In this test, we check that we can hide the popup by pressing TAB.
|
||||
*/
|
||||
function test7()
|
||||
function test6()
|
||||
{
|
||||
let uri = "data:text/html,<iframe name='t'></iframe><form target='t' action='data:text/html,'><input id='i' required><input id='s' type='submit'></form>";
|
||||
let tab = gBrowser.addTab();
|
||||
|
@ -276,7 +237,7 @@ function test7()
|
|||
|
||||
// Clean-up and next test.
|
||||
gBrowser.removeTab(gBrowser.selectedTab, {animate: false});
|
||||
executeSoon(test8);
|
||||
executeSoon(test7);
|
||||
});
|
||||
}, false);
|
||||
|
||||
|
@ -293,7 +254,7 @@ function test7()
|
|||
/**
|
||||
* In this test, we check that the popup will hide if we move to another tab.
|
||||
*/
|
||||
function test8()
|
||||
function test7()
|
||||
{
|
||||
let uri = "data:text/html,<iframe name='t'></iframe><form target='t' action='data:text/html,'><input id='i' required><input id='s' type='submit'></form>";
|
||||
let tab = gBrowser.addTab();
|
||||
|
@ -317,7 +278,7 @@ function test8()
|
|||
// Clean-up and next test.
|
||||
gBrowser.removeTab(gBrowser.selectedTab, {animate: false});
|
||||
gBrowser.removeTab(gBrowser.selectedTab, {animate: false});
|
||||
executeSoon(test9);
|
||||
executeSoon(test8);
|
||||
});
|
||||
}, false);
|
||||
|
||||
|
@ -336,7 +297,7 @@ function test8()
|
|||
* invalid form is submitted in another tab than the current focused one
|
||||
* (submitted in background).
|
||||
*/
|
||||
function test9()
|
||||
function test8()
|
||||
{
|
||||
let uri = "data:text/html,<iframe name='t'></iframe><form target='t' action='data:text/html,'><input id='i' required><input id='s' type='submit'></form>";
|
||||
let tab = gBrowser.addTab();
|
||||
|
@ -355,7 +316,7 @@ function test9()
|
|||
gBrowser.removeTab(tab, {animate: false});
|
||||
|
||||
// Next test
|
||||
executeSoon(test10);
|
||||
executeSoon(test9);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -376,7 +337,7 @@ function test9()
|
|||
/**
|
||||
* In this test, we check that the author defined error message is shown.
|
||||
*/
|
||||
function test10()
|
||||
function test9()
|
||||
{
|
||||
let uri = "data:text/html,<iframe name='t'></iframe><form target='t' action='data:text/html,'><input x-moz-errormessage='foo' required id='i'><input id='s' type='submit'></form>";
|
||||
let tab = gBrowser.addTab();
|
||||
|
@ -390,7 +351,7 @@ function test10()
|
|||
|
||||
checkPopupShow();
|
||||
|
||||
is(gInvalidFormPopup.firstChild.nodeValue, "foo",
|
||||
is(gInvalidFormPopup.firstChild.textContent, "foo",
|
||||
"The panel should show the author defined error message");
|
||||
|
||||
// Clean-up and next test.
|
||||
|
|
|
@ -1,9 +1,36 @@
|
|||
var tab;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
var tab = gBrowser.addTab();
|
||||
executeSoon(function () {
|
||||
gBrowser.removeTab(tab, {animate:true});
|
||||
ok(!tab.parentNode, "tab successfully removed");
|
||||
finish();
|
||||
});
|
||||
|
||||
tab = gBrowser.addTab();
|
||||
isnot(tab.getAttribute("fadein"), "true", "newly opened tab is yet to fade in");
|
||||
|
||||
// Try to remove the tab right before the opening animation's first frame
|
||||
window.mozRequestAnimationFrame(checkAnimationState);
|
||||
}
|
||||
|
||||
function checkAnimationState() {
|
||||
if (tab.getAttribute("fadein") != "true") {
|
||||
window.mozRequestAnimationFrame(checkAnimationState);
|
||||
return;
|
||||
}
|
||||
|
||||
info(window.getComputedStyle(tab).maxWidth);
|
||||
gBrowser.removeTab(tab, { animate: true });
|
||||
if (!tab.parentNode) {
|
||||
ok(true, "tab removed synchronously since the opening animation hasn't moved yet");
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
info("tab didn't close immediately, so the tab opening animation must have started moving");
|
||||
info("waiting for the tab to close asynchronously");
|
||||
tab.addEventListener("transitionend", function (event) {
|
||||
if (event.propertyName == "max-width")
|
||||
executeSoon(function () {
|
||||
ok(!tab.parentNode, "tab removed asynchronously");
|
||||
finish();
|
||||
});
|
||||
}, false);
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ _BROWSER_FILES = \
|
|||
browser_tabview_bug595804.js \
|
||||
browser_tabview_bug595930.js \
|
||||
browser_tabview_bug595943.js \
|
||||
browser_tabview_bug598600.js \
|
||||
browser_tabview_dragdrop.js \
|
||||
browser_tabview_exit_button.js \
|
||||
browser_tabview_group.js \
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is tabview bug598600 test.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Raymond Lee <raymond@appcoast.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
let newWin;
|
||||
let prefService;
|
||||
|
||||
function test() {
|
||||
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
|
||||
prefService =
|
||||
Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService).
|
||||
getBranch("browser.panorama.");
|
||||
// make sure we don't trigger the 'first run' behavior
|
||||
prefService.setBoolPref("experienced_first_run", true);
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
// open a new window and setup the window state.
|
||||
newWin = openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no");
|
||||
newWin.addEventListener("load", function(event) {
|
||||
this.removeEventListener("load", arguments.callee, false);
|
||||
|
||||
let newState = {
|
||||
windows: [{
|
||||
tabs: [{
|
||||
entries: [{ "url": "about:blank" }],
|
||||
hidden: true,
|
||||
attributes: {},
|
||||
extData: {
|
||||
"tabview-tab":
|
||||
'{"bounds":{"left":20,"top":35,"width":280,"height":210},' +
|
||||
'"userSize":null,"url":"about:blank","groupID":1,' +
|
||||
'"imageData":null,"title":null}'
|
||||
}
|
||||
},{
|
||||
entries: [{ url: "about:blank" }],
|
||||
index: 1,
|
||||
hidden: false,
|
||||
attributes: {},
|
||||
extData: {
|
||||
"tabview-tab":
|
||||
'{"bounds":{"left":375,"top":35,"width":280,"height":210},' +
|
||||
'"userSize":null,"url":"about:blank","groupID":2,' +
|
||||
'"imageData":null,"title":null}'
|
||||
}
|
||||
}],
|
||||
selected:2,
|
||||
_closedTabs: [],
|
||||
extData: {
|
||||
"tabview-groups": '{"nextID":3,"activeGroupId":2}',
|
||||
"tabview-group":
|
||||
'{"1":{"bounds":{"left":15,"top":10,"width":320,"height":375},' +
|
||||
'"userSize":null,"locked":{},"title":"","id":1},' +
|
||||
'"2":{"bounds":{"left":380,"top":5,"width":320,"height":375},' +
|
||||
'"userSize":null,"locked":{},"title":"","id":2}}',
|
||||
"tabview-ui": '{"pageBounds":{"left":0,"top":0,"width":875,"height":650}}'
|
||||
}, sizemode:"normal"
|
||||
}]
|
||||
};
|
||||
ss.setWindowState(newWin, JSON.stringify(newState), true);
|
||||
|
||||
// add a new tab.
|
||||
newWin.gBrowser.addTab();
|
||||
is(newWin.gBrowser.tabs.length, 3, "There are 3 browser tabs");
|
||||
|
||||
let onTabViewShow = function() {
|
||||
newWin.removeEventListener("tabviewshown", onTabViewShow, false);
|
||||
|
||||
let contentWindow = newWin.document.getElementById("tab-view").contentWindow;
|
||||
|
||||
is(contentWindow.GroupItems.groupItems.length, 2, "Has two group items");
|
||||
is(contentWindow.GroupItems.getOrphanedTabs().length, 0, "No orphan tabs");
|
||||
|
||||
// clean up and finish
|
||||
prefService.setBoolPref("experienced_first_run", false);
|
||||
newWin.close();
|
||||
|
||||
finish();
|
||||
}
|
||||
newWin.addEventListener("tabviewshown", onTabViewShow, false);
|
||||
newWin.TabView.toggle();
|
||||
}, false);
|
||||
}
|
|
@ -50,8 +50,12 @@ function getBrowserURL()
|
|||
return "chrome://browser/content/browser.xul";
|
||||
}
|
||||
|
||||
function getTopWin()
|
||||
{
|
||||
function getTopWin(skipPopups) {
|
||||
if (skipPopups) {
|
||||
return Components.classes["@mozilla.org/browser/browserglue;1"]
|
||||
.getService(Components.interfaces.nsIBrowserGlue)
|
||||
.getMostRecentBrowserWindow();
|
||||
}
|
||||
return Services.wm.getMostRecentWindow("navigator:browser");
|
||||
}
|
||||
|
||||
|
@ -158,18 +162,33 @@ function whereToOpenLink( e, ignoreButton, ignoreAlt )
|
|||
* relatedToCurrent (boolean)
|
||||
*/
|
||||
function openUILinkIn(url, where, aAllowThirdPartyFixup, aPostData, aReferrerURI) {
|
||||
var params;
|
||||
|
||||
if (arguments.length == 3 && typeof arguments[2] == "object") {
|
||||
params = aAllowThirdPartyFixup;
|
||||
} else {
|
||||
params = {
|
||||
allowThirdPartyFixup: aAllowThirdPartyFixup,
|
||||
postData: aPostData,
|
||||
referrerURI: aReferrerURI
|
||||
};
|
||||
}
|
||||
|
||||
params.fromContent = false;
|
||||
|
||||
openLinkIn(url, where, params);
|
||||
}
|
||||
|
||||
function openLinkIn(url, where, params) {
|
||||
if (!where || !url)
|
||||
return;
|
||||
|
||||
var aRelatedToCurrent;
|
||||
if (arguments.length == 3 &&
|
||||
typeof arguments[2] == "object") {
|
||||
let params = arguments[2];
|
||||
aAllowThirdPartyFixup = params.allowThirdPartyFixup;
|
||||
aPostData = params.postData;
|
||||
aReferrerURI = params.referrerURI;
|
||||
aRelatedToCurrent = params.relatedToCurrent;
|
||||
}
|
||||
var aFromContent = params.fromContent;
|
||||
var aAllowThirdPartyFixup = params.allowThirdPartyFixup;
|
||||
var aPostData = params.postData;
|
||||
var aCharset = params.charset;
|
||||
var aReferrerURI = params.referrerURI;
|
||||
var aRelatedToCurrent = params.relatedToCurrent;
|
||||
|
||||
if (where == "save") {
|
||||
saveURL(url, null, null, true, null, aReferrerURI);
|
||||
|
@ -179,6 +198,11 @@ function openUILinkIn(url, where, aAllowThirdPartyFixup, aPostData, aReferrerURI
|
|||
const Ci = Components.interfaces;
|
||||
|
||||
var w = getTopWin();
|
||||
if ((where == "tab" || where == "tabshifted") &&
|
||||
w.document.documentElement.getAttribute("chromehidden")) {
|
||||
w = getTopWin(true);
|
||||
aRelatedToCurrent = false;
|
||||
}
|
||||
|
||||
if (!w || where == "window") {
|
||||
var sa = Cc["@mozilla.org/supports-array;1"].
|
||||
|
@ -188,12 +212,19 @@ function openUILinkIn(url, where, aAllowThirdPartyFixup, aPostData, aReferrerURI
|
|||
createInstance(Ci.nsISupportsString);
|
||||
wuri.data = url;
|
||||
|
||||
let charset = null;
|
||||
if (aCharset) {
|
||||
charset = Cc["@mozilla.org/supports-string;1"]
|
||||
.createInstance(Ci.nsISupportsString);
|
||||
charset.data = "charset=" + aCharset;
|
||||
}
|
||||
|
||||
var allowThirdPartyFixupSupports = Cc["@mozilla.org/supports-PRBool;1"].
|
||||
createInstance(Ci.nsISupportsPRBool);
|
||||
allowThirdPartyFixupSupports.data = aAllowThirdPartyFixup;
|
||||
|
||||
sa.AppendElement(wuri);
|
||||
sa.AppendElement(null);
|
||||
sa.AppendElement(charset);
|
||||
sa.AppendElement(aReferrerURI);
|
||||
sa.AppendElement(aPostData);
|
||||
sa.AppendElement(allowThirdPartyFixupSupports);
|
||||
|
@ -210,7 +241,9 @@ function openUILinkIn(url, where, aAllowThirdPartyFixup, aPostData, aReferrerURI
|
|||
return;
|
||||
}
|
||||
|
||||
var loadInBackground = getBoolPref("browser.tabs.loadBookmarksInBackground");
|
||||
var loadInBackground = aFromContent ?
|
||||
getBoolPref("browser.tabs.loadInBackground") :
|
||||
getBoolPref("browser.tabs.loadBookmarksInBackground");
|
||||
|
||||
if (where == "current" && w.gBrowser.selectedTab.pinned) {
|
||||
try {
|
||||
|
@ -237,6 +270,7 @@ function openUILinkIn(url, where, aAllowThirdPartyFixup, aPostData, aReferrerURI
|
|||
let browser = w.gBrowser;
|
||||
browser.loadOneTab(url, {
|
||||
referrerURI: aReferrerURI,
|
||||
charset: aCharset,
|
||||
postData: aPostData,
|
||||
inBackground: loadInBackground,
|
||||
allowThirdPartyFixup: aAllowThirdPartyFixup,
|
||||
|
@ -449,7 +483,7 @@ function openTroubleshootingPage()
|
|||
*/
|
||||
function openFeedbackPage()
|
||||
{
|
||||
openUILinkIn("http://input.mozilla.com/sad", "tab");
|
||||
openUILinkIn("http://input.mozilla.com/feedback", "tab");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -762,6 +762,19 @@ var gCookiesWindow = {
|
|||
this._view._filterSet.reverse();
|
||||
}
|
||||
|
||||
// Adjust the Sort Indicator
|
||||
var domainCol = document.getElementById("domainCol");
|
||||
var nameCol = document.getElementById("nameCol");
|
||||
var sortOrderString = ascending ? "ascending" : "descending";
|
||||
if (aProperty == "rawHost") {
|
||||
domainCol.setAttribute("sortDirection", sortOrderString);
|
||||
nameCol.removeAttribute("sortDirection");
|
||||
}
|
||||
else {
|
||||
nameCol.setAttribute("sortDirection", sortOrderString);
|
||||
domainCol.removeAttribute("sortDirection");
|
||||
}
|
||||
|
||||
this._view._invalidateCache(0);
|
||||
this._view.selection.clearSelection();
|
||||
this._view.selection.select(0);
|
||||
|
|
|
@ -45,8 +45,9 @@ include $(DEPTH)/config/autoconf.mk
|
|||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_BROWSER_TEST_FILES = browser_405664.js \
|
||||
browser_415700.js \
|
||||
browser_addEngine.js \
|
||||
testEngine.xml \
|
||||
testEngine.src \
|
||||
browser_426329.js \
|
||||
426329.xml \
|
||||
browser_483086.js \
|
||||
|
|
|
@ -1,85 +0,0 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ryan Flint <rflint@dslr.net> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
var gSS = Services.search;
|
||||
|
||||
function observers(aSubject, aTopic, aData) {
|
||||
switch (aData) {
|
||||
case "engine-added":
|
||||
test2();
|
||||
break;
|
||||
case "engine-current":
|
||||
test3();
|
||||
break;
|
||||
case "engine-removed":
|
||||
test4();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
Services.obs.addObserver(observers, "browser-search-engine-modified", false);
|
||||
|
||||
gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine.xml",
|
||||
Ci.nsISearchEngine.DATA_XML, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC",
|
||||
false);
|
||||
}
|
||||
|
||||
function test2() {
|
||||
var engine = gSS.getEngineByName("Foo");
|
||||
ok(engine, "Engine was added.");
|
||||
|
||||
var aEngine = gSS.getEngineByAlias("fooalias");
|
||||
ok(!aEngine, "Alias was not parsed from engine description");
|
||||
|
||||
gSS.currentEngine = engine;
|
||||
}
|
||||
|
||||
function test3() {
|
||||
var engine = gSS.currentEngine;
|
||||
is(engine.name, "Foo", "Current engine was changed successfully");
|
||||
|
||||
gSS.removeEngine(engine);
|
||||
}
|
||||
|
||||
function test4() {
|
||||
var engine = gSS.currentEngine;
|
||||
ok(engine, "An engine is present.");
|
||||
isnot(engine.name, "Foo", "Current engine reset after removal");
|
||||
|
||||
Services.obs.removeObserver(observers, "browser-search-engine-modified");
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,168 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ryan Flint <rflint@dslr.net> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
var gSS = Services.search;
|
||||
|
||||
function observer(aSubject, aTopic, aData) {
|
||||
if (!gCurrentTest) {
|
||||
info("Observer called with no test active");
|
||||
return;
|
||||
}
|
||||
|
||||
let engine = aSubject.QueryInterface(Ci.nsISearchEngine);
|
||||
info("Observer: " + aData + " for " + engine.name);
|
||||
let method;
|
||||
switch (aData) {
|
||||
case "engine-added":
|
||||
if (gCurrentTest.added)
|
||||
method = "added"
|
||||
break;
|
||||
case "engine-current":
|
||||
if (gCurrentTest.current)
|
||||
method = "current";
|
||||
break;
|
||||
case "engine-removed":
|
||||
if (gCurrentTest.removed)
|
||||
method = "removed";
|
||||
break;
|
||||
}
|
||||
|
||||
if (method)
|
||||
gCurrentTest[method](engine);
|
||||
}
|
||||
|
||||
function checkEngine(checkObj, engineObj) {
|
||||
info("Checking engine");
|
||||
for (var prop in checkObj)
|
||||
is(checkObj[prop], engineObj[prop], prop + " is correct");
|
||||
}
|
||||
|
||||
var gTests = [
|
||||
{
|
||||
name: "opensearch install",
|
||||
engine: {
|
||||
name: "Foo",
|
||||
alias: null,
|
||||
description: "Foo Search",
|
||||
searchForm: "http://mochi.test:8888/browser/browser/components/search/test/",
|
||||
type: Ci.nsISearchEngine.TYPE_OPENSEARCH
|
||||
},
|
||||
run: function () {
|
||||
gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine.xml",
|
||||
Ci.nsISearchEngine.DATA_XML, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC",
|
||||
false);
|
||||
},
|
||||
added: function (engine) {
|
||||
ok(engine, "engine was added.");
|
||||
|
||||
checkEngine(this.engine, engine);
|
||||
|
||||
let engineFromSS = gSS.getEngineByName(this.engine.name);
|
||||
is(engine, engineFromSS, "engine is obtainable via getEngineByName");
|
||||
|
||||
let aEngine = gSS.getEngineByAlias("fooalias");
|
||||
ok(!aEngine, "Alias was not parsed from engine description");
|
||||
|
||||
gSS.currentEngine = engine;
|
||||
},
|
||||
current: function (engine) {
|
||||
let currentEngine = gSS.currentEngine;
|
||||
is(engine, currentEngine, "engine is current");
|
||||
is(engine.name, this.engine.name, "current engine was changed successfully");
|
||||
|
||||
gSS.removeEngine(engine);
|
||||
},
|
||||
removed: function (engine) {
|
||||
let currentEngine = gSS.currentEngine;
|
||||
ok(currentEngine, "An engine is present.");
|
||||
isnot(currentEngine.name, this.engine.name, "Current engine reset after removal");
|
||||
|
||||
nextTest();
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "sherlock install",
|
||||
engine: {
|
||||
name: "Test Sherlock",
|
||||
alias: null,
|
||||
description: "Test Description",
|
||||
searchForm: "http://example.com/searchform",
|
||||
type: Ci.nsISearchEngine.TYPE_SHERLOCK
|
||||
},
|
||||
run: function () {
|
||||
gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine.src",
|
||||
Ci.nsISearchEngine.DATA_TEXT, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC",
|
||||
false);
|
||||
},
|
||||
added: function (engine) {
|
||||
ok(engine, "engine was added.");
|
||||
checkEngine(this.engine, engine);
|
||||
|
||||
let engineFromSS = gSS.getEngineByName(this.engine.name);
|
||||
is(engineFromSS, engine, "engine is obtainable via getEngineByName");
|
||||
|
||||
gSS.removeEngine(engine);
|
||||
},
|
||||
removed: function (engine) {
|
||||
let currentEngine = gSS.currentEngine;
|
||||
ok(currentEngine, "An engine is present.");
|
||||
isnot(currentEngine.name, this.engine.name, "Current engine reset after removal");
|
||||
|
||||
nextTest();
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
var gCurrentTest = null;
|
||||
function nextTest() {
|
||||
if (gTests.length) {
|
||||
gCurrentTest = gTests.shift();
|
||||
info("Running " + gCurrentTest.name);
|
||||
gCurrentTest.run();
|
||||
} else
|
||||
executeSoon(finish);
|
||||
}
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
Services.obs.addObserver(observer, "browser-search-engine-modified", false);
|
||||
registerCleanupFunction(cleanup);
|
||||
|
||||
nextTest();
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
Services.obs.removeObserver(observer, "browser-search-engine-modified");
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
<search
|
||||
name="Test Sherlock"
|
||||
description="Test Description"
|
||||
method="GET"
|
||||
searchform="http://example.com/searchform"
|
||||
action="http://example.com/action"
|
||||
queryCharset="UTF-8"
|
||||
>
|
||||
<input name="userParam" user>
|
||||
<input name="param" value="value">
|
||||
</search>
|
|
@ -1400,9 +1400,22 @@ SessionStoreService.prototype = {
|
|||
if (!browser || !browser.currentURI)
|
||||
// can happen when calling this function right after .addTab()
|
||||
return tabData;
|
||||
else if (browser.__SS_data && browser.__SS_data._tabStillLoading)
|
||||
else if (browser.__SS_data && browser.__SS_data._tabStillLoading) {
|
||||
// use the data to be restored when the tab hasn't been completely loaded
|
||||
return browser.__SS_data;
|
||||
tabData = browser.__SS_data;
|
||||
if (aTab.pinned)
|
||||
tabData.pinned = true;
|
||||
else
|
||||
delete tabData.pinned;
|
||||
if (browser.userTypedValue) {
|
||||
tabData.userTypedValue = browser.userTypedValue;
|
||||
tabData.userTypedClear = browser.userTypedClear;
|
||||
} else {
|
||||
delete tabData.userTypedValue;
|
||||
delete tabData.userTypedClear;
|
||||
}
|
||||
return tabData;
|
||||
}
|
||||
|
||||
var history = null;
|
||||
try {
|
||||
|
@ -1443,10 +1456,15 @@ SessionStoreService.prototype = {
|
|||
if (browser.userTypedValue) {
|
||||
tabData.userTypedValue = browser.userTypedValue;
|
||||
tabData.userTypedClear = browser.userTypedClear;
|
||||
} else {
|
||||
delete tabData.userTypedValue;
|
||||
delete tabData.userTypedClear;
|
||||
}
|
||||
|
||||
if (aTab.pinned)
|
||||
tabData.pinned = true;
|
||||
else
|
||||
delete tabData.pinned;
|
||||
tabData.hidden = aTab.hidden;
|
||||
|
||||
var disallow = [];
|
||||
|
|
|
@ -114,6 +114,7 @@ _BROWSER_TEST_FILES = \
|
|||
browser_522545.js \
|
||||
browser_524745.js \
|
||||
browser_528776.js \
|
||||
browser_579868.js \
|
||||
browser_579879.js \
|
||||
browser_580512.js \
|
||||
browser_586147.js \
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is bug 579868 test.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sindre Dammann <sindrebugzilla@gmail.com>
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
function test() {
|
||||
let tab1 = gBrowser.addTab("about:robots");
|
||||
let tab2 = gBrowser.addTab("about:credits");
|
||||
tab1.addEventListener("load", mainPart, true);
|
||||
waitForExplicitFinish();
|
||||
|
||||
function mainPart() {
|
||||
// Tell the session storer that the tab is pinned
|
||||
// and that userTypedValue is "Hello World!"
|
||||
let newTabState = '{"entries":[{"url":"about:robots"}],"pinned":true,"userTypedValue":"Hello World!"}';
|
||||
let ss = Cc["@mozilla.org/browser/sessionstore;1"]
|
||||
.getService(Ci.nsISessionStore);
|
||||
ss.setTabState(tab1, newTabState);
|
||||
|
||||
// Undo pinning and userTypedValue
|
||||
gBrowser.unpinTab(tab1);
|
||||
tab1.linkedBrowser.userTypedValue = null;
|
||||
|
||||
is(tab1.linkedBrowser.__SS_data._tabStillLoading, true,
|
||||
"_tabStillLoading should be true.");
|
||||
|
||||
// Close and restore tab
|
||||
gBrowser.removeTab(tab1);
|
||||
let savedState = JSON.parse(ss.getClosedTabData(window))[0].state;
|
||||
isnot(savedState.pinned, true, "Pinned should not be true");
|
||||
isnot(savedState.userTypedValue, "Hello World!",
|
||||
"userTypedValue should not be Hello World!");
|
||||
tab1 = ss.undoCloseTab(window, 0);
|
||||
|
||||
isnot(tab1.pinned, true, "Should not be pinned");
|
||||
gBrowser.removeTab(tab1);
|
||||
gBrowser.removeTab(tab2);
|
||||
finish();
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ browser.search.defaultenginename=Google
|
|||
# Search engine order (order displayed in the search bar dropdown)s
|
||||
browser.search.order.1=Google
|
||||
browser.search.order.2=Yahoo
|
||||
browser.search.order.3=Bing
|
||||
|
||||
# This is the default set of web based feed handlers shown in the reader
|
||||
# selection UI
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
|
||||
<ShortName>Bing</ShortName>
|
||||
<Description>Bing. Search by Microsoft.</Description>
|
||||
<InputEncoding>UTF-8</InputEncoding>
|
||||
<Image width="16" height="16" type="image/x-icon">data:image/x-icon;base64,AAABAAEAEBAAAAEAGABoAwAAFgAAACgAAAAQAAAAIAAAAAEAGAAAAAAAAAAAABMLAAATCwAAAAAAAAAAAAAVpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8ysf97zf+24//F6f/F6f/F6f+K0/9QvP8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8krP+Z2P/////////w+f/F6f/F6f/i9P/////////T7v9Bt/8Vpv8Vpv8Vpv8Vpv/T7v/////w+f97zf8Vpv8Vpv8Vpv8Vpv9QvP/T7v/////w+f9Bt/8Vpv8Vpv97zf////////9QvP8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8krP/i9P/////i9P8Vpv8Vpv+24//////i9P8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv+K0/////////8Vpv8Vpv/F6f////////8krP8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv+n3v/////w+f8Vpv8Vpv/F6f////////+n3v8krP8Vpv8Vpv8Vpv8Vpv8Vpv9tx/////////+Z2P8Vpv8Vpv/F6f/////////////i9P+K0/9QvP9QvP9tx//F6f////////+n3v8Vpv8Vpv8Vpv/F6f/////T7v+Z2P/i9P////////////////////+24/9QvP8Vpv8Vpv8Vpv8Vpv/F6f/////F6f8Vpv8Vpv8krP9QvP9QvP9Bt/8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv/F6f/////F6f8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv9Bt/9QvP9Bt/8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8AAHBsAABhdAAAbiAAAHJ0AABsaQAAdGkAACBDAABlbgAAUEEAAEVYAAAuQwAAOy4AAEU7AABBVAAAQ00AAC5W</Image>
|
||||
<Url type="application/x-suggestions+json" template="http://api.bing.com/osjson.aspx">
|
||||
<Param name="query" value="{searchTerms}"/>
|
||||
<Param name="form" value="OSDJAS"/>
|
||||
</Url>
|
||||
<Url type="text/html" method="GET" template="http://www.bing.com/search">
|
||||
<Param name="q" value="{searchTerms}"/>
|
||||
<Param name="form" value="MOZSBR"/>
|
||||
<MozParam name="pc" condition="pref" pref="ms-pc"/>
|
||||
</Url>
|
||||
<Url type="application/x-moz-keywordsearch" method="GET" template="http://www.bing.com/search">
|
||||
<Param name="q" value="{searchTerms}"/>
|
||||
<Param name="form" value="MOZLBR"/>
|
||||
<MozParam name="pc" condition="pref" pref="ms-pc"/>
|
||||
</Url>
|
||||
<SearchForm>http://www.bing.com/search</SearchForm>
|
||||
</SearchPlugin>
|
|
@ -1,6 +1,5 @@
|
|||
amazondotcom
|
||||
answers
|
||||
creativecommons
|
||||
bing
|
||||
eBay
|
||||
google
|
||||
wikipedia
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
af
|
||||
ak
|
||||
ar
|
||||
be
|
||||
bg
|
||||
bn-BD
|
||||
br
|
||||
ca
|
||||
cs
|
||||
da
|
||||
de
|
||||
el
|
||||
en-GB
|
||||
en-US
|
||||
en-ZA
|
||||
eo
|
||||
|
@ -43,6 +46,7 @@ ro
|
|||
ru
|
||||
sk
|
||||
son
|
||||
sq
|
||||
sv-SE
|
||||
tr
|
||||
uk
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
-moz-border-bottom-colors: rgba(255,255,255,.5) rgba(83,42,6,.9);
|
||||
-moz-border-right-colors: rgba(255,255,255,.5) rgba(83,42,6,.9);
|
||||
box-shadow: 0 1px 0 rgba(255,255,255,.25) inset,
|
||||
0 0 2px 1px rgba(255,255,255,.25) inset;
|
||||
0 0 2px 1px rgba(255,255,255,.25) inset;
|
||||
}
|
||||
|
||||
#appmenu-button:-moz-window-inactive {
|
||||
|
|
31
configure.in
31
configure.in
|
@ -5006,8 +5006,8 @@ BUILD_CTYPES=1
|
|||
XPC_IDISPATCH_SUPPORT=
|
||||
|
||||
|
||||
case "$target_os" in
|
||||
darwin*|*wince*|*winmo*)
|
||||
case "${target}" in
|
||||
*android*|*darwin*|*wince*|*winmo*)
|
||||
ACCESSIBILITY=
|
||||
;;
|
||||
*)
|
||||
|
@ -8512,31 +8512,6 @@ if test "$MOZ_TREE_CAIRO"; then
|
|||
AC_CHECK_HEADER(d3d10.h, MOZ_ENABLE_D3D10_LAYER=1)
|
||||
fi
|
||||
|
||||
AC_TRY_COMPILE([#include <ddraw.h>], [int foo = DDLOCK_WAITNOTBUSY;], HAS_DDRAW=1, HAS_DDRAW=)
|
||||
if test -z "$HAS_DDRAW"; then
|
||||
AC_MSG_WARN([DirectDraw ddraw.h header not found or it's missing DDLOCK_WAITNOTBUSY, disabling DirectDraw surface. If you have an older SDK (such as the CE5 SDK), try copying in ddraw.lib and ddraw.h from the WM6 SDK.])
|
||||
DDRAW_SURFACE_FEATURE=
|
||||
else
|
||||
DDRAW_SURFACE_FEATURE="#define CAIRO_HAS_DDRAW_SURFACE 1"
|
||||
fi
|
||||
|
||||
if test -z "$OGLES_SDK_DIR"; then
|
||||
OGLES_SURFACE_FEATURE=
|
||||
else
|
||||
AC_TRY_COMPILE([
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <GLES2/gl2.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
], [ EGLDisplay _cairo_ddraw_egl_dpy = EGL_NO_DISPLAY;], HAS_OGLES=1, HAS_OGLES=)
|
||||
if test -z "$HAS_OGLES"; then
|
||||
AC_MSG_WARN([OpenGL ES2 headers not found, disabling OpenGL acceleration surfaces.])
|
||||
OGLES_SURFACE_FEATURE=
|
||||
else
|
||||
OGLES_SURFACE_FEATURE="#define CAIRO_DDRAW_USE_GL 1"
|
||||
fi
|
||||
fi
|
||||
|
||||
PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
|
||||
fi
|
||||
if test "$MOZ_WIDGET_TOOLKIT" = "os2"; then
|
||||
|
@ -8581,8 +8556,6 @@ if test "$MOZ_TREE_CAIRO"; then
|
|||
AC_SUBST(QUARTZ_IMAGE_SURFACE_FEATURE)
|
||||
AC_SUBST(XCB_SURFACE_FEATURE)
|
||||
AC_SUBST(WIN32_SURFACE_FEATURE)
|
||||
AC_SUBST(DDRAW_SURFACE_FEATURE)
|
||||
AC_SUBST(OGLES_SURFACE_FEATURE)
|
||||
AC_SUBST(OS2_SURFACE_FEATURE)
|
||||
AC_SUBST(BEOS_SURFACE_FEATURE)
|
||||
AC_SUBST(DIRECTFB_SURFACE_FEATURE)
|
||||
|
|
|
@ -51,7 +51,7 @@ interface nsIDOMNode;
|
|||
interface nsISelection;
|
||||
interface nsISelectionDisplay;
|
||||
|
||||
[scriptable, uuid(bc5795ab-bcb5-448b-b3c7-a111bead7c26)]
|
||||
[scriptable, uuid(ff11fa25-788f-444f-8f69-dcdf14348fb3)]
|
||||
interface nsISelectionController : nsISelectionDisplay
|
||||
{
|
||||
const short SELECTION_NONE=0;
|
||||
|
@ -94,20 +94,27 @@ interface nsISelectionController : nsISelectionDisplay
|
|||
*/
|
||||
nsISelection getSelection(in short type);
|
||||
|
||||
const short SCROLL_SYNCHRONOUS = 1<<1;
|
||||
const short SCROLL_FIRST_ANCESTOR_ONLY = 1<<2;
|
||||
|
||||
/**
|
||||
* ScrollSelectionIntoView scrolls a region of the selection,
|
||||
* so that it is visible in the scrolled view.
|
||||
*
|
||||
* @param aType the selection to scroll into view. //SelectionType
|
||||
* @param aRegion the region inside the selection to scroll into view. //SelectionRegion
|
||||
* @param aIsSynchronous when true, scrolls the selection into view
|
||||
* before returning. If false, posts a request which is processed
|
||||
* @param aFlags the scroll flags. Valid bits include:
|
||||
* SCROLL_SYNCHRONOUS: when set, scrolls the selection into view
|
||||
* before returning. If not set, posts a request which is processed
|
||||
* at some point after the method returns.
|
||||
* SCROLL_FIRST_ANCESTOR_ONLY: if set, only the first ancestor will be scrolled
|
||||
* into view.
|
||||
*
|
||||
* Note that if isSynchronous is true, then this might flush the pending
|
||||
* reflow. It's dangerous for some objects. See bug 418470 comment 12.
|
||||
*/
|
||||
void scrollSelectionIntoView(in short type, in short region, in boolean isSynchronous);
|
||||
void scrollSelectionIntoView(in short type, in short region, in short flags);
|
||||
|
||||
/**
|
||||
* RepaintSelection repaints the selection specified by aType.
|
||||
*
|
||||
|
|
|
@ -286,7 +286,7 @@ nsDOMFile::GetAsText(const nsAString &aCharset, nsAString &aResult)
|
|||
rv = alias->GetPreferred(charsetGuess, charset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return ConvertStream(stream, charset.get(), aResult);
|
||||
return DOMFileResult(ConvertStream(stream, charset.get(), aResult));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -338,8 +338,17 @@ nsDOMFile::GetAsDataURL(nsAString &aResult)
|
|||
|
||||
// out buffer should be at least 4/3rds the read buf, plus a terminator
|
||||
char *base64 = PL_Base64Encode(readBuf, numEncode, nsnull);
|
||||
AppendASCIItoUTF16(base64, aResult);
|
||||
if (!base64) {
|
||||
return DOMFileResult(NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
nsDependentCString str(base64);
|
||||
PRUint32 strLen = str.Length();
|
||||
PRUint32 oldLength = aResult.Length();
|
||||
AppendASCIItoUTF16(str, aResult);
|
||||
PR_Free(base64);
|
||||
if (aResult.Length() - oldLength != strLen) {
|
||||
return DOMFileResult(NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
if (leftOver) {
|
||||
memmove(readBuf, readBuf + numEncode, leftOver);
|
||||
|
@ -363,7 +372,11 @@ nsDOMFile::GetAsBinary(nsAString &aResult)
|
|||
char readBuf[4096];
|
||||
rv = stream->Read(readBuf, sizeof(readBuf), &numRead);
|
||||
NS_ENSURE_SUCCESS(rv, DOMFileResult(rv));
|
||||
PRUint32 oldLength = aResult.Length();
|
||||
AppendASCIItoUTF16(Substring(readBuf, readBuf + numRead), aResult);
|
||||
if (aResult.Length() - oldLength != numRead) {
|
||||
return DOMFileResult(NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
} while (numRead > 0);
|
||||
|
||||
return NS_OK;
|
||||
|
@ -524,7 +537,11 @@ nsDOMFile::ConvertStream(nsIInputStream *aStream,
|
|||
nsString result;
|
||||
rv = unicharStream->ReadString(8192, result, &numChars);
|
||||
while (NS_SUCCEEDED(rv) && numChars > 0) {
|
||||
PRUint32 oldLength = aResult.Length();
|
||||
aResult.Append(result);
|
||||
if (aResult.Length() - oldLength != result.Length()) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
rv = unicharStream->ReadString(8192, result, &numChars);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,15 +6,13 @@
|
|||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"/>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/x-javascript">
|
||||
var bodyOnLoad = false;
|
||||
function checkOnLoad()
|
||||
function onLoadFired()
|
||||
{
|
||||
ok(bodyOnLoad, "Body onload event should fire");
|
||||
ok(true, "Body onload event should fire");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
setTimeout(checkOnLoad, 500);
|
||||
</script>
|
||||
</head>
|
||||
<body onload="bodyOnLoad = true;"/>
|
||||
<body onload="onLoadFired();"/>
|
||||
</html>
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
|
||||
function boom()
|
||||
{
|
||||
var r = document.documentElement;
|
||||
var i = document.getElementById("i");
|
||||
|
||||
document.removeChild(r);
|
||||
document.appendChild(r);
|
||||
w("dump('A\\n')");
|
||||
document.removeChild(r);
|
||||
w("dump('B\\n')");
|
||||
document.appendChild(r);
|
||||
|
||||
function w(s)
|
||||
{
|
||||
var ns = document.createElement("script");
|
||||
var nt = document.createTextNode(s);
|
||||
ns.appendChild(nt);
|
||||
i.appendChild(ns);
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body onload="boom();"><input id="i"></body>
|
||||
</html>
|
|
@ -20,3 +20,4 @@ load 580507-1.xhtml
|
|||
load 590387.html
|
||||
load 596785-1.html
|
||||
load 596785-2.html
|
||||
load 606430-1.html
|
||||
|
|
|
@ -64,6 +64,8 @@ public:
|
|||
|
||||
friend class nsDOMValidityState;
|
||||
|
||||
static const PRUint16 sContentSpecifiedMaxLengthMessage;
|
||||
|
||||
virtual ~nsIConstraintValidation();
|
||||
|
||||
PRBool IsValid() const { return mValidityBitField == 0; }
|
||||
|
|
|
@ -193,7 +193,7 @@ nsHTMLFieldSetElement::InsertChildAt(nsIContent* aChild, PRUint32 aIndex,
|
|||
} else {
|
||||
// If mFirstLegend is before aIndex, we do not change it.
|
||||
// Otherwise, mFirstLegend is now aChild.
|
||||
if (aIndex <= IndexOf(mFirstLegend)) {
|
||||
if (PRInt32(aIndex) <= IndexOf(mFirstLegend)) {
|
||||
mFirstLegend = aChild;
|
||||
firstLegendHasChanged = true;
|
||||
}
|
||||
|
|
|
@ -3972,6 +3972,9 @@ nsHTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
|
|||
"FormValidationPatternMismatch",
|
||||
message);
|
||||
} else {
|
||||
if (title.Length() > nsIConstraintValidation::sContentSpecifiedMaxLengthMessage) {
|
||||
title.Truncate(nsIConstraintValidation::sContentSpecifiedMaxLengthMessage);
|
||||
}
|
||||
const PRUnichar* params[] = { title.get() };
|
||||
rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
|
||||
"FormValidationPatternMismatchWithTitle",
|
||||
|
|
|
@ -45,6 +45,8 @@
|
|||
#include "nsHTMLFormElement.h"
|
||||
|
||||
|
||||
const PRUint16 nsIConstraintValidation::sContentSpecifiedMaxLengthMessage = 256;
|
||||
|
||||
nsIConstraintValidation::nsIConstraintValidation()
|
||||
: mValidityBitField(0)
|
||||
, mValidity(nsnull)
|
||||
|
@ -87,8 +89,14 @@ nsIConstraintValidation::GetValidationMessage(nsAString& aValidationMessage)
|
|||
|
||||
if (!authorMessage.IsEmpty()) {
|
||||
aValidationMessage.Assign(authorMessage);
|
||||
if (aValidationMessage.Length() > sContentSpecifiedMaxLengthMessage) {
|
||||
aValidationMessage.Truncate(sContentSpecifiedMaxLengthMessage);
|
||||
}
|
||||
} else if (GetValidityState(VALIDITY_STATE_CUSTOM_ERROR)) {
|
||||
aValidationMessage.Assign(mCustomValidity);
|
||||
if (aValidationMessage.Length() > sContentSpecifiedMaxLengthMessage) {
|
||||
aValidationMessage.Truncate(sContentSpecifiedMaxLengthMessage);
|
||||
}
|
||||
} else if (GetValidityState(VALIDITY_STATE_TOO_LONG)) {
|
||||
GetValidationMessage(aValidationMessage, VALIDITY_STATE_TOO_LONG);
|
||||
} else if (GetValidityState(VALIDITY_STATE_VALUE_MISSING)) {
|
||||
|
|
|
@ -78,6 +78,30 @@ struct SelectionState {
|
|||
PRInt32 mEnd;
|
||||
};
|
||||
|
||||
class RestoreSelectionState : public nsRunnable {
|
||||
public:
|
||||
RestoreSelectionState(nsTextControlFrame *aFrame, PRInt32 aStart, PRInt32 aEnd)
|
||||
: mFrame(aFrame),
|
||||
mWeakFrame(aFrame),
|
||||
mStart(aStart),
|
||||
mEnd(aEnd)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
if (mWeakFrame.IsAlive()) {
|
||||
mFrame->SetSelectionRange(mStart, mEnd);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsTextControlFrame* mFrame;
|
||||
nsWeakFrame mWeakFrame;
|
||||
PRInt32 mStart;
|
||||
PRInt32 mEnd;
|
||||
};
|
||||
|
||||
/*static*/
|
||||
PRBool
|
||||
nsITextControlElement::GetWrapPropertyEnum(nsIContent* aContent,
|
||||
|
@ -160,7 +184,7 @@ public:
|
|||
NS_IMETHOD SetSelectionFlags(PRInt16 aInEnable);
|
||||
NS_IMETHOD GetSelectionFlags(PRInt16 *aOutEnable);
|
||||
NS_IMETHOD GetSelection(PRInt16 type, nsISelection **_retval);
|
||||
NS_IMETHOD ScrollSelectionIntoView(PRInt16 aType, PRInt16 aRegion, PRBool aIsSynchronous);
|
||||
NS_IMETHOD ScrollSelectionIntoView(PRInt16 aType, PRInt16 aRegion, PRInt16 aFlags);
|
||||
NS_IMETHOD RepaintSelection(PRInt16 type);
|
||||
NS_IMETHOD RepaintSelection(nsPresContext* aPresContext, SelectionType aSelectionType);
|
||||
NS_IMETHOD SetCaretEnabled(PRBool enabled);
|
||||
|
@ -279,12 +303,12 @@ nsTextInputSelectionImpl::GetSelection(PRInt16 type, nsISelection **_retval)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextInputSelectionImpl::ScrollSelectionIntoView(PRInt16 aType, PRInt16 aRegion, PRBool aIsSynchronous)
|
||||
nsTextInputSelectionImpl::ScrollSelectionIntoView(PRInt16 aType, PRInt16 aRegion, PRInt16 aFlags)
|
||||
{
|
||||
if (!mFrameSelection)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return mFrameSelection->ScrollSelectionIntoView(aType, aRegion, aIsSynchronous);
|
||||
return mFrameSelection->ScrollSelectionIntoView(aType, aRegion, aFlags);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -461,7 +485,8 @@ nsTextInputSelectionImpl::PageMove(PRBool aForward, PRBool aExtend)
|
|||
}
|
||||
// After ScrollSelectionIntoView(), the pending notifications might be
|
||||
// flushed and PresShell/PresContext/Frames may be dead. See bug 418470.
|
||||
return ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_FOCUS_REGION, PR_TRUE);
|
||||
return ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_FOCUS_REGION,
|
||||
nsISelectionController::SCROLL_SYNCHRONOUS);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -1328,7 +1353,7 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
|
|||
|
||||
// Restore our selection after being bound to a new frame
|
||||
if (mSelState) {
|
||||
mBoundFrame->SetSelectionRange(mSelState->mStart, mSelState->mEnd);
|
||||
nsContentUtils::AddScriptRunner(new RestoreSelectionState(mBoundFrame, mSelState->mStart, mSelState->mEnd));
|
||||
mSelState = nsnull;
|
||||
}
|
||||
|
||||
|
|
|
@ -235,6 +235,7 @@ _TEST_FILES = \
|
|||
test_bug596350.html \
|
||||
test_bug600155.html \
|
||||
test_bug556007.html \
|
||||
test_bug606817.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=606817
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 606817</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.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=606817">Mozilla Bug 606817</a>
|
||||
<p id="display"></p>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 606817 **/
|
||||
|
||||
var messageMaxLength = 256;
|
||||
|
||||
function checkMessage(aInput, aMsg, aWithTerminalPeriod)
|
||||
{
|
||||
ok(aInput.validationMessage != aMsg,
|
||||
"Original content-defined message should have been truncate");
|
||||
is(aInput.validationMessage.length - aInput.validationMessage.indexOf("_42_"),
|
||||
aWithTerminalPeriod ? messageMaxLength+1 : messageMaxLength,
|
||||
"validation message should be 256 characters length");
|
||||
}
|
||||
|
||||
var input = document.createElement("input");
|
||||
|
||||
var msg = "";
|
||||
for (var i=0; i<75; ++i) {
|
||||
msg += "_42_";
|
||||
}
|
||||
// msg is now 300 chars long
|
||||
|
||||
// Testing with setCustomValidity().
|
||||
input.setCustomValidity(msg);
|
||||
checkMessage(input, msg, false);
|
||||
|
||||
// The input is still invalid but x-moz-errormessage will be used as the message.
|
||||
input.setAttribute("x-moz-errormessage", msg);
|
||||
checkMessage(input, msg, false);
|
||||
|
||||
// Cleaning.
|
||||
input.setCustomValidity("");
|
||||
input.removeAttribute("x-moz-errormessage");
|
||||
|
||||
// Testing with pattern and titl.
|
||||
input.pattern = "[0-9]*";
|
||||
input.value = "foo";
|
||||
input.title = msg;
|
||||
checkMessage(input, msg, true);
|
||||
|
||||
// Cleaning.
|
||||
input.removeAttribute("pattern");
|
||||
input.removeAttribute("title");
|
||||
input.value = "";
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -65,9 +65,10 @@ function startTest(test, token) {
|
|||
if (v.parentNode) {
|
||||
v.parentNode.removeChild(v);
|
||||
}
|
||||
dump("SEEK-TEST: Finished " + name + "\n");
|
||||
manager.finished(v.token);
|
||||
}}(v, manager);
|
||||
dump("Seek test: " + test.number + "\n");
|
||||
dump("SEEK-TEST: Started " + name + "\n");
|
||||
window['test_seek' + test.number](v, test.duration/2, localIs, localOk, localFinish);
|
||||
}
|
||||
|
||||
|
|
|
@ -404,6 +404,8 @@ nsXULCommandDispatcher::UpdateCommands(const nsAString& aEventName)
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
nsCOMArray<nsIContent> updaters;
|
||||
|
||||
for (Updater* updater = mUpdaters; updater != nsnull; updater = updater->mNext) {
|
||||
// Skip any nodes that don't match our 'events' or 'targets'
|
||||
// filters.
|
||||
|
@ -418,6 +420,12 @@ nsXULCommandDispatcher::UpdateCommands(const nsAString& aEventName)
|
|||
if (! content)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
updaters.AppendObject(content);
|
||||
}
|
||||
|
||||
for (PRUint32 u = 0; u < updaters.Count(); u++) {
|
||||
nsIContent* content = updaters[u];
|
||||
|
||||
nsCOMPtr<nsIDocument> document = content->GetDocument();
|
||||
|
||||
NS_ASSERTION(document != nsnull, "element has no document");
|
||||
|
@ -430,7 +438,7 @@ nsXULCommandDispatcher::UpdateCommands(const nsAString& aEventName)
|
|||
CopyUTF16toUTF8(aEventName, aeventnameC);
|
||||
PR_LOG(gLog, PR_LOG_NOTICE,
|
||||
("xulcmd[%p] update %p event=%s",
|
||||
this, updater->mElement.get(),
|
||||
this, content,
|
||||
aeventnameC.get()));
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -57,6 +57,8 @@ _TEST_FILES = \
|
|||
$(NULL)
|
||||
|
||||
_CHROME_FILES = \
|
||||
test_bug583948.xul \
|
||||
window_bug583948.xul \
|
||||
test_bug497875.xul \
|
||||
bug497875-iframe.xul \
|
||||
$(NULL)
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||||
type="text/css"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
|
||||
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<div id="content" style="display: none"/>
|
||||
</body>
|
||||
|
||||
<script>
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var attempts = 0;
|
||||
|
||||
function update() {
|
||||
setTimeout(function() {
|
||||
if (otherWindow.location)
|
||||
otherWindow.location.reload()
|
||||
}, 1);
|
||||
otherWindow.document.commandDispatcher.updateCommands('');
|
||||
// without the crash fix, this usually crashes after 2 to 4 reloads
|
||||
if (++attempts == 6) {
|
||||
ok(true, "didn't crash after 6 attempts");
|
||||
otherWindow.close();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
else {
|
||||
setTimeout(update, 100);
|
||||
}
|
||||
}
|
||||
|
||||
var otherWindow = window.open("window_bug583948.xul", "_new", "chrome");
|
||||
setTimeout(update, 100);
|
||||
</script>
|
||||
|
||||
</window>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<command oncommandupdate="document.removeChild(document.documentElement)" commandupdater="true"/>
|
||||
<box command="c"/>
|
||||
<iframe/>
|
||||
|
||||
</window>
|
|
@ -1139,13 +1139,8 @@ nsXULTemplateBuilder::AttributeChanged(nsIDocument* aDocument,
|
|||
// Check for a change to the 'datasources' attribute. If so, setup
|
||||
// mDB by parsing the new value and rebuild.
|
||||
else if (aAttribute == nsGkAtoms::datasources) {
|
||||
Uninit(PR_FALSE); // Reset results
|
||||
|
||||
PRBool shouldDelay;
|
||||
LoadDataSources(aDocument, &shouldDelay);
|
||||
if (!shouldDelay)
|
||||
nsContentUtils::AddScriptRunner(
|
||||
NS_NewRunnableMethod(this, &nsXULTemplateBuilder::RunnableRebuild));
|
||||
nsContentUtils::AddScriptRunner(
|
||||
NS_NewRunnableMethod(this, &nsXULTemplateBuilder::RunnableLoadAndRebuild));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1163,8 +1158,9 @@ nsXULTemplateBuilder::ContentRemoved(nsIDocument* aDocument,
|
|||
if (mQueryProcessor)
|
||||
mQueryProcessor->Done();
|
||||
|
||||
// use false since content is going away anyway
|
||||
Uninit(PR_FALSE);
|
||||
// Pass false to Uninit since content is going away anyway
|
||||
nsContentUtils::AddScriptRunner(
|
||||
NS_NewRunnableMethod(this, &nsXULTemplateBuilder::UninitFalse));
|
||||
|
||||
aDocument->RemoveObserver(this);
|
||||
|
||||
|
@ -1201,7 +1197,8 @@ nsXULTemplateBuilder::NodeWillBeDestroyed(const nsINode* aNode)
|
|||
mCompDB = nsnull;
|
||||
mRoot = nsnull;
|
||||
|
||||
Uninit(PR_TRUE);
|
||||
nsContentUtils::AddScriptRunner(
|
||||
NS_NewRunnableMethod(this, &nsXULTemplateBuilder::UninitTrue));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -152,6 +152,20 @@ public:
|
|||
RebuildAll() = 0; // must be implemented by subclasses
|
||||
|
||||
void RunnableRebuild() { Rebuild(); }
|
||||
void RunnableLoadAndRebuild() {
|
||||
Uninit(PR_FALSE); // Reset results
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = mRoot ? mRoot->GetDocument() : nsnull;
|
||||
if (doc) {
|
||||
PRBool shouldDelay;
|
||||
LoadDataSources(doc, &shouldDelay);
|
||||
if (!shouldDelay) {
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
}
|
||||
void UninitFalse() { Uninit(PR_FALSE); }
|
||||
void UninitTrue() { Uninit(PR_TRUE); }
|
||||
|
||||
/**
|
||||
* Find the <template> tag that applies for this builder
|
||||
|
|
|
@ -27,8 +27,7 @@ function checkConsole(expectedError)
|
|||
{
|
||||
var out = {};
|
||||
consoleService.getMessageArray(out, {});
|
||||
var messages = out.value || [];
|
||||
is(messages[0].message, expectedError, "logged message " + expectedError);
|
||||
is(out.value[0].message, expectedError, "logged message " + expectedError);
|
||||
}
|
||||
|
||||
// each test consists of a pre function executed before the template build, an
|
||||
|
|
|
@ -69,6 +69,8 @@
|
|||
#include "nsComputedDOMStyle.h"
|
||||
#include "nsIViewObserver.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsStyleAnimation.h"
|
||||
#include "nsCSSProps.h"
|
||||
|
||||
#if defined(MOZ_X11) && defined(MOZ_WIDGET_GTK2)
|
||||
#include <gdk/gdk.h>
|
||||
|
@ -1495,6 +1497,74 @@ nsDOMWindowUtils::GetLayerManagerType(nsAString& aType)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
static PRBool
|
||||
ComputeAnimationValue(nsCSSProperty aProperty, nsIContent* aContent,
|
||||
const nsAString& aInput,
|
||||
nsStyleAnimation::Value& aOutput)
|
||||
{
|
||||
|
||||
if (!nsStyleAnimation::ComputeValue(aProperty, aContent, aInput,
|
||||
PR_FALSE, aOutput)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// This matches TransExtractComputedValue in nsTransitionManager.cpp.
|
||||
if (aProperty == eCSSProperty_visibility) {
|
||||
NS_ABORT_IF_FALSE(aOutput.GetUnit() == nsStyleAnimation::eUnit_Enumerated,
|
||||
"unexpected unit");
|
||||
aOutput.SetIntValue(aOutput.GetIntValue(),
|
||||
nsStyleAnimation::eUnit_Visibility);
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::ComputeAnimationDistance(nsIDOMElement* aElement,
|
||||
const nsAString& aProperty,
|
||||
const nsAString& aValue1,
|
||||
const nsAString& aValue2,
|
||||
double* aResult)
|
||||
{
|
||||
if (!IsUniversalXPConnectCapable()) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Convert direction-dependent properties as appropriate, e.g.,
|
||||
// border-left to border-left-value.
|
||||
nsCSSProperty property = nsCSSProps::LookupProperty(aProperty);
|
||||
if (property != eCSSProperty_UNKNOWN && nsCSSProps::IsShorthand(property)) {
|
||||
nsCSSProperty subprop0 = *nsCSSProps::SubpropertyEntryFor(property);
|
||||
if (nsCSSProps::PropHasFlags(subprop0, CSS_PROPERTY_REPORT_OTHER_NAME) &&
|
||||
nsCSSProps::OtherNameFor(subprop0) == property) {
|
||||
property = subprop0;
|
||||
} else {
|
||||
property = eCSSProperty_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
NS_ABORT_IF_FALSE(property == eCSSProperty_UNKNOWN ||
|
||||
!nsCSSProps::IsShorthand(property),
|
||||
"should not have shorthand");
|
||||
|
||||
nsStyleAnimation::Value v1, v2;
|
||||
if (property == eCSSProperty_UNKNOWN ||
|
||||
!ComputeAnimationValue(property, content, aValue1, v1) ||
|
||||
!ComputeAnimationValue(property, content, aValue2, v2)) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
if (!nsStyleAnimation::ComputeDistance(property, v1, v2, *aResult)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWindowUtils::RenderDocument(const nsRect& aRect,
|
||||
PRUint32 aFlags,
|
||||
|
|
|
@ -1238,6 +1238,9 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
|
|||
}
|
||||
}
|
||||
|
||||
if (!chromeWindow)
|
||||
newDefaultJSOptions |= JSOPTION_ROPES;
|
||||
|
||||
if (useTraceJIT)
|
||||
newDefaultJSOptions |= JSOPTION_JIT;
|
||||
else
|
||||
|
|
|
@ -65,7 +65,7 @@ interface nsITransferable;
|
|||
interface nsIQueryContentEventResult;
|
||||
interface nsIDOMWindow;
|
||||
|
||||
[scriptable, uuid(33cbae2d-2361-4f3d-b589-cc55af07a434)]
|
||||
[scriptable, uuid(def3fbe8-961b-4c8b-8cac-eb6a4e604bb5)]
|
||||
interface nsIDOMWindowUtils : nsISupports {
|
||||
|
||||
/**
|
||||
|
@ -808,4 +808,16 @@ interface nsIDOMWindowUtils : nsISupports {
|
|||
in PRUint32 aFlags,
|
||||
in nscolor aBackgroundColor,
|
||||
in gfxContext aThebesContext);
|
||||
|
||||
/**
|
||||
* Method for testing nsStyleAnimation::ComputeDistance.
|
||||
*
|
||||
* Returns the distance between the two values as reported by
|
||||
* nsStyleAnimation::ComputeDistance for the given element and
|
||||
* property.
|
||||
*/
|
||||
double computeAnimationDistance(in nsIDOMElement element,
|
||||
in AString property,
|
||||
in AString value1,
|
||||
in AString value2);
|
||||
};
|
||||
|
|
|
@ -74,6 +74,7 @@ FormValidationSelectMissing=Please select an item in the list.
|
|||
FormValidationInvalidEmail=Please enter an email address.
|
||||
FormValidationInvalidURL=Please enter a URL.
|
||||
FormValidationPatternMismatch=Please match the requested format.
|
||||
# LOCALIZATION NOTE (FormValidationPatternMismatchWithTitle): %S is the (possibly truncated) title attribute value.
|
||||
FormValidationPatternMismatchWithTitle=Please match the requested format: %S.
|
||||
UseOfDocumentWidthWarning=Non-standard document.width was used. Use standard document.body.clientWidth instead.
|
||||
UseOfDocumentHeightWarning=Non-standard document.height was used. Use standard document.body.clientHeight instead.
|
||||
|
|
|
@ -76,6 +76,10 @@ static const PRUint32 DEFAULT_OFFLINE_APP_QUOTA = 200 * 1024;
|
|||
// ... but warn if it goes over this amount
|
||||
static const PRUint32 DEFAULT_OFFLINE_WARN_QUOTA = 50 * 1024;
|
||||
|
||||
// Intervals to flush the temporary table after in seconds
|
||||
#define NS_DOMSTORAGE_MAXIMUM_TEMPTABLE_INACTIVITY_TIME (5)
|
||||
#define NS_DOMSTORAGE_MAXIMUM_TEMPTABLE_AGE (30)
|
||||
|
||||
static const char kPermissionType[] = "cookie";
|
||||
static const char kStorageEnabled[] = "dom.storage.enabled";
|
||||
static const char kDefaultQuota[] = "dom.storage.default_quota";
|
||||
|
@ -414,6 +418,10 @@ nsDOMStorageManager::Observe(nsISupports *aSubject,
|
|||
return nsDOMStorage::gStorageDB->DropSessionOnlyStoragesForHost(host);
|
||||
#endif
|
||||
}
|
||||
} else if (!strcmp(aTopic, "timer-callback")) {
|
||||
nsCOMPtr<nsIObserverService> obsserv = mozilla::services::GetObserverService();
|
||||
if (obsserv)
|
||||
obsserv->NotifyObservers(nsnull, NS_DOMSTORAGE_FLUSH_TIMER_OBSERVER, nsnull);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -533,6 +541,8 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMStorage)
|
|||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMStorageObsolete)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMStorageObsolete)
|
||||
NS_INTERFACE_MAP_ENTRY(nsPIDOMStorage)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(StorageObsolete)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
|
@ -563,6 +573,7 @@ nsDOMStorage::nsDOMStorage()
|
|||
, mItemsCached(PR_FALSE)
|
||||
, mEventBroadcaster(nsnull)
|
||||
, mCanUseChromePersist(false)
|
||||
, mLoadedTemporaryTable(false)
|
||||
{
|
||||
mSecurityChecker = this;
|
||||
mItems.Init(8);
|
||||
|
@ -581,6 +592,9 @@ nsDOMStorage::nsDOMStorage(nsDOMStorage& aThat)
|
|||
#endif
|
||||
, mEventBroadcaster(nsnull)
|
||||
, mCanUseChromePersist(aThat.mCanUseChromePersist)
|
||||
, mLoadedTemporaryTable(aThat.mLoadedTemporaryTable)
|
||||
, mLastTemporaryTableAccessTime(aThat.mLastTemporaryTableAccessTime)
|
||||
, mTemporaryTableAge(aThat.mTemporaryTableAge)
|
||||
{
|
||||
mSecurityChecker = this;
|
||||
mItems.Init(8);
|
||||
|
@ -689,6 +703,8 @@ nsDOMStorage::InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aD
|
|||
mCanUseChromePersist = URICanUseChromePersist(URI);
|
||||
}
|
||||
|
||||
RegisterObservers();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -714,6 +730,9 @@ nsDOMStorage::InitAsGlobalStorage(const nsACString &aDomainDemanded)
|
|||
|
||||
mStorageType = GlobalStorage;
|
||||
mEventBroadcaster = this;
|
||||
|
||||
RegisterObservers();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1041,31 +1060,32 @@ nsDOMStorage::SetItem(const nsAString& aKey, const nsAString& aData)
|
|||
if (aKey.IsEmpty())
|
||||
return NS_OK;
|
||||
|
||||
nsresult rv;
|
||||
nsString oldValue;
|
||||
SetDOMStringToNull(oldValue);
|
||||
|
||||
nsresult rv;
|
||||
nsRefPtr<nsDOMStorageItem> newitem = nsnull;
|
||||
// First store the value to the database, we need to do this before we update
|
||||
// the mItems cache. SetDBValue is using the old cached value to decide
|
||||
// on quota checking.
|
||||
bool isCallerSecure = IsCallerSecure();
|
||||
if (UseDB()) {
|
||||
rv = SetDBValue(aKey, aData, isCallerSecure);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
nsSessionStorageEntry *entry = mItems.GetEntry(aKey);
|
||||
if (entry) {
|
||||
if (entry->mItem->IsSecure() && !IsCallerSecure()) {
|
||||
if (entry->mItem->IsSecure() && !isCallerSecure) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
oldValue = entry->mItem->GetValueInternal();
|
||||
entry->mItem->SetValueInternal(aData);
|
||||
}
|
||||
else {
|
||||
newitem = new nsDOMStorageItem(this, aKey, aData, IsCallerSecure());
|
||||
nsRefPtr<nsDOMStorageItem> newitem =
|
||||
new nsDOMStorageItem(this, aKey, aData, isCallerSecure);
|
||||
if (!newitem)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if (UseDB()) {
|
||||
rv = SetDBValue(aKey, aData, IsCallerSecure());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (newitem) {
|
||||
entry = mItems.PutEntry(aKey);
|
||||
NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY);
|
||||
entry->mItem = newitem;
|
||||
|
@ -1110,7 +1130,7 @@ NS_IMETHODIMP nsDOMStorage::RemoveItem(const nsAString& aKey)
|
|||
aKey.Length() + value.Length());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mItemsCached = PR_FALSE;
|
||||
// Before bug 536544 got fixed we were dropping mItemsCached flag here
|
||||
#endif
|
||||
}
|
||||
else if (entry) {
|
||||
|
@ -1232,6 +1252,23 @@ nsDOMStorage::CacheKeysFromDB()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMStorage::GetCachedValue(const nsAString& aKey, nsAString& aValue,
|
||||
PRBool* aSecure)
|
||||
{
|
||||
aValue.Truncate();
|
||||
*aSecure = PR_FALSE;
|
||||
|
||||
nsSessionStorageEntry *entry = mItems.GetEntry(aKey);
|
||||
if (!entry)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
aValue = entry->mItem->GetValueInternal();
|
||||
*aSecure = entry->mItem->IsSecure();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMStorage::GetDBValue(const nsAString& aKey, nsAString& aValue,
|
||||
PRBool* aSecure)
|
||||
|
@ -1289,7 +1326,7 @@ nsDOMStorage::SetDBValue(const nsAString& aKey,
|
|||
&usage);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mItemsCached = PR_FALSE;
|
||||
// Before bug 536544 got fixed we were dropping mItemsCached flag here
|
||||
|
||||
if (warnQuota >= 0 && usage > warnQuota) {
|
||||
// try to include the window that exceeded the warn quota
|
||||
|
@ -1468,6 +1505,84 @@ nsDOMStorage::BroadcastChangeNotification(const nsSubstring &aKey,
|
|||
NS_ConvertUTF8toUTF16(mDomain).get());
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMStorage::MaybeCommitTemporaryTable(bool force)
|
||||
{
|
||||
#ifdef MOZ_STORAGE
|
||||
if (!UseDB())
|
||||
return NS_OK;
|
||||
|
||||
if (!mLoadedTemporaryTable)
|
||||
return NS_OK;
|
||||
|
||||
// If we are not forced to flush (e.g. on shutdown) then don't flush if the
|
||||
// last table access is less then 5 seconds ago or the table itself is not
|
||||
// older then 30 secs
|
||||
if (!force &&
|
||||
((TimeStamp::Now() - mLastTemporaryTableAccessTime).ToSeconds() <
|
||||
NS_DOMSTORAGE_MAXIMUM_TEMPTABLE_INACTIVITY_TIME) &&
|
||||
((TimeStamp::Now() - mTemporaryTableAge).ToSeconds() <
|
||||
NS_DOMSTORAGE_MAXIMUM_TEMPTABLE_AGE))
|
||||
return NS_OK;
|
||||
|
||||
return gStorageDB->FlushAndDeleteTemporaryTableForStorage(this);
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMStorage::RegisterObservers()
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> obsserv = mozilla::services::GetObserverService();
|
||||
if (obsserv) {
|
||||
obsserv->AddObserver(this, "profile-before-change", PR_TRUE);
|
||||
obsserv->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_TRUE);
|
||||
obsserv->AddObserver(this, NS_DOMSTORAGE_FLUSH_TIMER_OBSERVER, PR_TRUE);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
nsDOMStorage::WasTemporaryTableLoaded()
|
||||
{
|
||||
return mLoadedTemporaryTable;
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMStorage::SetTemporaryTableLoaded(bool loaded)
|
||||
{
|
||||
if (loaded) {
|
||||
mLastTemporaryTableAccessTime = TimeStamp::Now();
|
||||
if (!mLoadedTemporaryTable)
|
||||
mTemporaryTableAge = mLastTemporaryTableAccessTime;
|
||||
}
|
||||
|
||||
mLoadedTemporaryTable = loaded;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMStorage::Observe(nsISupports *subject,
|
||||
const char *topic,
|
||||
const PRUnichar *data)
|
||||
{
|
||||
bool isProfileBeforeChange = !strcmp(topic, "profile-before-change");
|
||||
bool isXPCOMShutdown = !strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
|
||||
bool isFlushTimer = !strcmp(topic, NS_DOMSTORAGE_FLUSH_TIMER_OBSERVER);
|
||||
|
||||
if (isXPCOMShutdown || isProfileBeforeChange || isFlushTimer) {
|
||||
nsresult rv = MaybeCommitTemporaryTable(isXPCOMShutdown || isProfileBeforeChange);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("DOMStorage: temporary table commit failed");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_WARNING("Unrecognized topic in nsDOMStorage::Observe");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//
|
||||
// nsDOMStorage2
|
||||
//
|
||||
|
@ -2131,4 +2246,3 @@ nsDOMStorageEventObsolete::InitStorageEvent(const nsAString& aTypeArg,
|
|||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,11 @@
|
|||
#include "nsIDOMStorageManager.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
||||
#define NS_DOMSTORAGE_FLUSH_TIMER_OBSERVER "domstorage-flush-timer"
|
||||
|
||||
#ifdef MOZ_STORAGE
|
||||
#include "nsDOMStorageDBWrapper.h"
|
||||
|
@ -72,6 +77,9 @@ class nsDOMStorage;
|
|||
class nsIDOMStorage;
|
||||
class nsDOMStorageItem;
|
||||
|
||||
using mozilla::TimeStamp;
|
||||
using mozilla::TimeDuration;
|
||||
|
||||
class nsDOMStorageEntry : public nsVoidPtrHashKey
|
||||
{
|
||||
public:
|
||||
|
@ -128,19 +136,20 @@ protected:
|
|||
};
|
||||
|
||||
class nsDOMStorage : public nsIDOMStorageObsolete,
|
||||
public nsPIDOMStorage
|
||||
public nsPIDOMStorage,
|
||||
public nsIObserver,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
nsDOMStorage();
|
||||
nsDOMStorage(nsDOMStorage& aThat);
|
||||
virtual ~nsDOMStorage();
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsDOMStorage, nsIDOMStorageObsolete)
|
||||
|
||||
// nsIDOMStorageObsolete
|
||||
NS_DECL_NSIDOMSTORAGEOBSOLETE
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
// Helpers for implementing nsIDOMStorage
|
||||
nsresult GetItem(const nsAString& key, nsAString& aData);
|
||||
|
@ -195,6 +204,13 @@ public:
|
|||
PRBool
|
||||
CacheStoragePermissions();
|
||||
|
||||
// retrieve the value and secure state corresponding to a key out of storage
|
||||
// that has been cached in mItems hash table.
|
||||
nsresult
|
||||
GetCachedValue(const nsAString& aKey,
|
||||
nsAString& aValue,
|
||||
PRBool* aSecure);
|
||||
|
||||
// retrieve the value and secure state corresponding to a key out of storage.
|
||||
nsresult
|
||||
GetDBValue(const nsAString& aKey,
|
||||
|
@ -226,10 +242,17 @@ public:
|
|||
return static_cast<nsDOMStorage*>(static_cast<nsIDOMStorageObsolete*>(aSupports));
|
||||
}
|
||||
|
||||
nsresult RegisterObservers();
|
||||
nsresult MaybeCommitTemporaryTable(bool force);
|
||||
|
||||
bool WasTemporaryTableLoaded();
|
||||
void SetTemporaryTableLoaded(bool loaded);
|
||||
|
||||
protected:
|
||||
|
||||
friend class nsDOMStorageManager;
|
||||
friend class nsDOMStorage2;
|
||||
friend class nsDOMStoragePersistentDB;
|
||||
|
||||
static nsresult InitDB();
|
||||
|
||||
|
@ -278,6 +301,10 @@ protected:
|
|||
|
||||
bool mCanUseChromePersist;
|
||||
|
||||
bool mLoadedTemporaryTable;
|
||||
TimeStamp mLastTemporaryTableAccessTime;
|
||||
TimeStamp mTemporaryTableAge;
|
||||
|
||||
public:
|
||||
// e.g. "moc.rab.oof.:" or "moc.rab.oof.:http:80" depending
|
||||
// on association with a domain (globalStorage) or
|
||||
|
|
|
@ -69,6 +69,17 @@ void ReverseString(const nsCSubstring& source, nsCSubstring& result)
|
|||
}
|
||||
}
|
||||
|
||||
nsDOMStorageDBWrapper::nsDOMStorageDBWrapper()
|
||||
{
|
||||
}
|
||||
|
||||
nsDOMStorageDBWrapper::~nsDOMStorageDBWrapper()
|
||||
{
|
||||
if (mFlushTimer) {
|
||||
mFlushTimer->Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMStorageDBWrapper::Init()
|
||||
{
|
||||
|
@ -86,9 +97,42 @@ nsDOMStorageDBWrapper::Init()
|
|||
rv = mPrivateBrowsingDB.Init();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mFlushTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mFlushTimer->Init(nsDOMStorageManager::gStorageManager, 5000,
|
||||
nsITimer::TYPE_REPEATING_SLACK);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMStorageDBWrapper::EnsureLoadTemporaryTableForStorage(nsDOMStorage* aStorage)
|
||||
{
|
||||
if (aStorage->CanUseChromePersist())
|
||||
return mChromePersistentDB.EnsureLoadTemporaryTableForStorage(aStorage);
|
||||
if (nsDOMStorageManager::gStorageManager->InPrivateBrowsingMode())
|
||||
return NS_OK;
|
||||
if (aStorage->SessionOnly())
|
||||
return NS_OK;
|
||||
|
||||
return mPersistentDB.EnsureLoadTemporaryTableForStorage(aStorage);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMStorageDBWrapper::FlushAndDeleteTemporaryTableForStorage(nsDOMStorage* aStorage)
|
||||
{
|
||||
if (aStorage->CanUseChromePersist())
|
||||
return mChromePersistentDB.FlushAndDeleteTemporaryTableForStorage(aStorage);
|
||||
if (nsDOMStorageManager::gStorageManager->InPrivateBrowsingMode())
|
||||
return NS_OK;
|
||||
if (aStorage->SessionOnly())
|
||||
return NS_OK;
|
||||
|
||||
return mPersistentDB.FlushAndDeleteTemporaryTableForStorage(aStorage);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMStorageDBWrapper::GetAllKeys(nsDOMStorage* aStorage,
|
||||
nsTHashtable<nsSessionStorageEntry>* aKeys)
|
||||
|
|
|
@ -86,12 +86,17 @@ class nsSessionStorageEntry;
|
|||
class nsDOMStorageDBWrapper
|
||||
{
|
||||
public:
|
||||
nsDOMStorageDBWrapper() {}
|
||||
~nsDOMStorageDBWrapper() {}
|
||||
nsDOMStorageDBWrapper();
|
||||
~nsDOMStorageDBWrapper();
|
||||
|
||||
nsresult
|
||||
Init();
|
||||
|
||||
nsresult
|
||||
EnsureLoadTemporaryTableForStorage(nsDOMStorage* aStorage);
|
||||
nsresult
|
||||
FlushAndDeleteTemporaryTableForStorage(nsDOMStorage* aStorage);
|
||||
|
||||
/**
|
||||
* Retrieve a list of all the keys associated with a particular domain.
|
||||
*/
|
||||
|
@ -221,6 +226,8 @@ protected:
|
|||
nsDOMStoragePersistentDB mPersistentDB;
|
||||
nsDOMStorageMemoryDB mSessionOnlyDB;
|
||||
nsDOMStorageMemoryDB mPrivateBrowsingDB;
|
||||
|
||||
nsCOMPtr<nsITimer> mFlushTimer;
|
||||
};
|
||||
|
||||
#endif /* nsDOMStorageDB_h___ */
|
||||
|
|
|
@ -48,6 +48,8 @@
|
|||
#include "mozStorageCID.h"
|
||||
#include "mozStorageHelper.h"
|
||||
#include "mozIStorageService.h"
|
||||
#include "mozIStorageBindingParamsArray.h"
|
||||
#include "mozIStorageBindingParams.h"
|
||||
#include "mozIStorageValueArray.h"
|
||||
#include "mozIStorageFunction.h"
|
||||
#include "nsPrintfCString.h"
|
||||
|
@ -94,6 +96,10 @@ class nsIsOfflineSQLFunction : public mozIStorageFunction
|
|||
|
||||
NS_IMPL_ISUPPORTS1(nsIsOfflineSQLFunction, mozIStorageFunction)
|
||||
|
||||
nsDOMStoragePersistentDB::nsDOMStoragePersistentDB()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIsOfflineSQLFunction::OnFunctionCall(
|
||||
mozIStorageValueArray *aFunctionArguments, nsIVariant **aResult)
|
||||
|
@ -123,6 +129,53 @@ nsIsOfflineSQLFunction::OnFunctionCall(
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
class Binder
|
||||
{
|
||||
public:
|
||||
Binder(mozIStorageStatement* statement, nsresult *rv);
|
||||
|
||||
mozIStorageBindingParams* operator->();
|
||||
nsresult Add();
|
||||
|
||||
private:
|
||||
mozIStorageStatement* mStmt;
|
||||
nsCOMPtr<mozIStorageBindingParamsArray> mArray;
|
||||
nsCOMPtr<mozIStorageBindingParams> mParams;
|
||||
};
|
||||
|
||||
Binder::Binder(mozIStorageStatement* statement, nsresult *rv)
|
||||
: mStmt(statement)
|
||||
{
|
||||
*rv = mStmt->NewBindingParamsArray(getter_AddRefs(mArray));
|
||||
if (NS_FAILED(*rv))
|
||||
return;
|
||||
|
||||
*rv = mArray->NewBindingParams(getter_AddRefs(mParams));
|
||||
if (NS_FAILED(*rv))
|
||||
return;
|
||||
|
||||
*rv = NS_OK;
|
||||
}
|
||||
|
||||
mozIStorageBindingParams*
|
||||
Binder::operator->()
|
||||
{
|
||||
return mParams;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Binder::Add()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = mArray->AddParams(mParams);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = mStmt->BindParameters(mArray);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMStoragePersistentDB::Init(const nsString& aDatabaseName)
|
||||
{
|
||||
|
@ -148,14 +201,20 @@ nsDOMStoragePersistentDB::Init(const nsString& aDatabaseName)
|
|||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"PRAGMA temp_store = MEMORY"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mozStorageTransaction transaction(mConnection, PR_FALSE);
|
||||
|
||||
// Ensure Gecko 1.9.1 storage table
|
||||
rv = mConnection->ExecuteSimpleSQL(
|
||||
NS_LITERAL_CSTRING("CREATE TABLE IF NOT EXISTS webappsstore2 ("
|
||||
"scope TEXT, "
|
||||
"key TEXT, "
|
||||
"value TEXT, "
|
||||
"secure INTEGER, "
|
||||
"owner TEXT)"));
|
||||
rv = mConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"CREATE TABLE IF NOT EXISTS webappsstore2 ("
|
||||
"scope TEXT, "
|
||||
"key TEXT, "
|
||||
"value TEXT, "
|
||||
"secure INTEGER, "
|
||||
"owner TEXT)"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
|
@ -163,6 +222,43 @@ nsDOMStoragePersistentDB::Init(const nsString& aDatabaseName)
|
|||
" ON webappsstore2(scope, key)"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"CREATE TEMPORARY TABLE webappsstore2_temp ("
|
||||
"scope TEXT, "
|
||||
"key TEXT, "
|
||||
"value TEXT, "
|
||||
"secure INTEGER, "
|
||||
"owner TEXT)"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"CREATE UNIQUE INDEX scope_key_index_temp"
|
||||
" ON webappsstore2_temp(scope, key)"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
||||
rv = mConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"CREATE TEMPORARY VIEW webappsstore2_view AS "
|
||||
"SELECT * FROM webappsstore2_temp "
|
||||
"UNION ALL "
|
||||
"SELECT * FROM webappsstore2 "
|
||||
"WHERE NOT EXISTS ("
|
||||
"SELECT scope, key FROM webappsstore2_temp "
|
||||
"WHERE scope = webappsstore2.scope AND key = webappsstore2.key)"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// carry deletion to both the temporary table and the disk table
|
||||
rv = mConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"CREATE TEMPORARY TRIGGER webappsstore2_view_delete_trigger "
|
||||
"INSTEAD OF DELETE ON webappsstore2_view "
|
||||
"BEGIN "
|
||||
"DELETE FROM webappsstore2_temp "
|
||||
"WHERE scope = OLD.scope AND key = OLD.key; "
|
||||
"DELETE FROM webappsstore2 "
|
||||
"WHERE scope = OLD.scope AND key = OLD.key; "
|
||||
"END"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<mozIStorageFunction> function1(new nsReverseStringSQLFunction());
|
||||
NS_ENSURE_TRUE(function1, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
|
@ -218,92 +314,218 @@ nsDOMStoragePersistentDB::Init(const nsString& aDatabaseName)
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// temporary - disk synchronization statements
|
||||
rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"INSERT INTO webappsstore2_temp"
|
||||
" SELECT * FROM webappsstore2"
|
||||
" WHERE scope = :scope AND NOT EXISTS ("
|
||||
"SELECT scope, key FROM webappsstore2_temp "
|
||||
"WHERE scope = webappsstore2.scope AND key = webappsstore2.key)"),
|
||||
getter_AddRefs(mCopyToTempTableStatement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"INSERT OR REPLACE INTO webappsstore2"
|
||||
" SELECT * FROM webappsstore2_temp"
|
||||
" WHERE scope = :scope;"),
|
||||
getter_AddRefs(mCopyBackToDiskStatement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"DELETE FROM webappsstore2_temp"
|
||||
" WHERE scope = :scope;"),
|
||||
getter_AddRefs(mDeleteTemporaryTableStatement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// retrieve all keys associated with a domain
|
||||
rv = mConnection->CreateStatement(
|
||||
NS_LITERAL_CSTRING("SELECT key, secure FROM webappsstore2 "
|
||||
"WHERE scope = ?1"),
|
||||
rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT key, value, secure FROM webappsstore2_temp "
|
||||
"WHERE scope = :scope"),
|
||||
getter_AddRefs(mGetAllKeysStatement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// retrieve a value given a domain and a key
|
||||
rv = mConnection->CreateStatement(
|
||||
NS_LITERAL_CSTRING("SELECT value, secure FROM webappsstore2 "
|
||||
"WHERE scope = ?1 "
|
||||
"AND key = ?2"),
|
||||
rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT value, secure FROM webappsstore2_temp "
|
||||
"WHERE scope = :scope "
|
||||
"AND key = :key"),
|
||||
getter_AddRefs(mGetKeyValueStatement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// insert a new key
|
||||
rv = mConnection->CreateStatement(
|
||||
NS_LITERAL_CSTRING("INSERT OR REPLACE INTO "
|
||||
"webappsstore2(scope, key, value, secure) "
|
||||
"VALUES (?1, ?2, ?3, ?4)"),
|
||||
rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"INSERT OR REPLACE INTO "
|
||||
"webappsstore2_temp(scope, key, value, secure) "
|
||||
"VALUES (:scope, :key, :value, :secure)"),
|
||||
getter_AddRefs(mInsertKeyStatement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// update an existing key
|
||||
rv = mConnection->CreateStatement(
|
||||
NS_LITERAL_CSTRING("UPDATE webappsstore2 "
|
||||
"SET value = ?1, secure = ?2"
|
||||
"WHERE scope = ?3 "
|
||||
"AND key = ?4"),
|
||||
getter_AddRefs(mUpdateKeyStatement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// update the secure status of an existing key
|
||||
rv = mConnection->CreateStatement(
|
||||
NS_LITERAL_CSTRING("UPDATE webappsstore2 "
|
||||
"SET secure = ?1 "
|
||||
"WHERE scope = ?2 "
|
||||
"AND key = ?3 "),
|
||||
rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"UPDATE webappsstore2_temp "
|
||||
"SET secure = :secure "
|
||||
"WHERE scope = :scope "
|
||||
"AND key = :key "),
|
||||
getter_AddRefs(mSetSecureStatement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// remove a key
|
||||
rv = mConnection->CreateStatement(
|
||||
NS_LITERAL_CSTRING("DELETE FROM webappsstore2 "
|
||||
"WHERE scope = ?1 "
|
||||
"AND key = ?2"),
|
||||
rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"DELETE FROM webappsstore2_view "
|
||||
"WHERE scope = :scope "
|
||||
"AND key = :key"),
|
||||
getter_AddRefs(mRemoveKeyStatement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// remove keys owned by a specific domain
|
||||
rv = mConnection->CreateStatement(
|
||||
NS_LITERAL_CSTRING("DELETE FROM webappsstore2 "
|
||||
"WHERE scope GLOB ?1"),
|
||||
rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"DELETE FROM webappsstore2_view "
|
||||
"WHERE scope GLOB :scope"),
|
||||
getter_AddRefs(mRemoveOwnerStatement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// remove keys belonging exactly only to a specific domain
|
||||
rv = mConnection->CreateStatement(
|
||||
NS_LITERAL_CSTRING("DELETE FROM webappsstore2 "
|
||||
"WHERE scope = ?1"),
|
||||
rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"DELETE FROM webappsstore2_view "
|
||||
"WHERE scope = :scope"),
|
||||
getter_AddRefs(mRemoveStorageStatement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// remove all keys
|
||||
rv = mConnection->CreateStatement(
|
||||
NS_LITERAL_CSTRING("DELETE FROM webappsstore2"),
|
||||
rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"DELETE FROM webappsstore2_view"),
|
||||
getter_AddRefs(mRemoveAllStatement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// check the usage for a given owner that is an offline-app allowed domain
|
||||
rv = mConnection->CreateStatement(
|
||||
NS_LITERAL_CSTRING("SELECT SUM(LENGTH(key) + LENGTH(value)) "
|
||||
"FROM webappsstore2 "
|
||||
"WHERE scope GLOB ?1"),
|
||||
rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT SUM(LENGTH(key) + LENGTH(value)) "
|
||||
"FROM ("
|
||||
"SELECT key,value FROM webappsstore2_temp "
|
||||
"WHERE scope GLOB :scope "
|
||||
"UNION ALL "
|
||||
"SELECT key,value FROM webappsstore2 "
|
||||
"WHERE scope GLOB :scope "
|
||||
"AND NOT EXISTS ("
|
||||
"SELECT scope, key "
|
||||
"FROM webappsstore2_temp "
|
||||
"WHERE scope = webappsstore2.scope "
|
||||
"AND key = webappsstore2.key"
|
||||
")"
|
||||
")"),
|
||||
getter_AddRefs(mGetFullUsageStatement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// check the usage for a given owner that is not an offline-app allowed domain
|
||||
rv = mConnection->CreateStatement(
|
||||
NS_LITERAL_CSTRING("SELECT SUM(LENGTH(key) + LENGTH(value)) "
|
||||
"FROM webappsstore2 "
|
||||
"WHERE scope GLOB ?1 "
|
||||
"AND NOT ISOFFLINE(scope)"),
|
||||
rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT SUM(LENGTH(key) + LENGTH(value)) "
|
||||
"FROM ("
|
||||
"SELECT key, value FROM webappsstore2_temp "
|
||||
"WHERE scope GLOB :scope "
|
||||
"AND NOT ISOFFLINE(scope) "
|
||||
"UNION ALL "
|
||||
"SELECT key, value FROM webappsstore2 "
|
||||
"WHERE scope GLOB :scope "
|
||||
"AND NOT ISOFFLINE(scope) "
|
||||
"AND NOT EXISTS ("
|
||||
"SELECT scope, key "
|
||||
"FROM webappsstore2_temp "
|
||||
"WHERE scope = webappsstore2.scope "
|
||||
"AND key = webappsstore2.key"
|
||||
")"
|
||||
")"),
|
||||
getter_AddRefs(mGetOfflineExcludedUsageStatement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = transaction.Commit();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMStoragePersistentDB::EnsureLoadTemporaryTableForStorage(nsDOMStorage* aStorage)
|
||||
{
|
||||
if (!aStorage->WasTemporaryTableLoaded()) {
|
||||
nsresult rv;
|
||||
|
||||
rv = MaybeCommitInsertTransaction();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mozStorageStatementScoper scope(mCopyToTempTableStatement);
|
||||
|
||||
Binder binder(mCopyToTempTableStatement, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = binder->BindUTF8StringByName(NS_LITERAL_CSTRING("scope"),
|
||||
aStorage->GetScopeDBKey());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = binder.Add();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mCopyToTempTableStatement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Always call this to update the last access time
|
||||
aStorage->SetTemporaryTableLoaded(true);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMStoragePersistentDB::FlushAndDeleteTemporaryTableForStorage(nsDOMStorage* aStorage)
|
||||
{
|
||||
if (!aStorage->WasTemporaryTableLoaded())
|
||||
return NS_OK;
|
||||
|
||||
mozStorageTransaction trans(mConnection, PR_FALSE);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
{
|
||||
mozStorageStatementScoper scope(mCopyBackToDiskStatement);
|
||||
|
||||
Binder binder(mCopyBackToDiskStatement, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = binder->BindUTF8StringByName(NS_LITERAL_CSTRING("scope"),
|
||||
aStorage->GetScopeDBKey());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = binder.Add();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mCopyBackToDiskStatement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
{
|
||||
mozStorageStatementScoper scope(mDeleteTemporaryTableStatement);
|
||||
|
||||
Binder binder(mDeleteTemporaryTableStatement, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = binder->BindUTF8StringByName(NS_LITERAL_CSTRING("scope"),
|
||||
aStorage->GetScopeDBKey());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = binder.Add();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mDeleteTemporaryTableStatement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
rv = trans.Commit();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = MaybeCommitInsertTransaction();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aStorage->SetTemporaryTableLoaded(false);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -311,9 +533,24 @@ nsresult
|
|||
nsDOMStoragePersistentDB::GetAllKeys(nsDOMStorage* aStorage,
|
||||
nsTHashtable<nsSessionStorageEntry>* aKeys)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = MaybeCommitInsertTransaction();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = EnsureLoadTemporaryTableForStorage(aStorage);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mozStorageStatementScoper scope(mGetAllKeysStatement);
|
||||
|
||||
nsresult rv = mGetAllKeysStatement->BindUTF8StringParameter(0, aStorage->GetScopeDBKey());
|
||||
Binder binder(mGetAllKeysStatement, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = binder->BindUTF8StringByName(NS_LITERAL_CSTRING("scope"),
|
||||
aStorage->GetScopeDBKey());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = binder.Add();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool exists;
|
||||
|
@ -324,14 +561,18 @@ nsDOMStoragePersistentDB::GetAllKeys(nsDOMStorage* aStorage,
|
|||
rv = mGetAllKeysStatement->GetString(0, key);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoString value;
|
||||
rv = mGetAllKeysStatement->GetString(1, value);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt32 secureInt = 0;
|
||||
rv = mGetAllKeysStatement->GetInt32(1, &secureInt);
|
||||
rv = mGetAllKeysStatement->GetInt32(2, &secureInt);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsSessionStorageEntry* entry = aKeys->PutEntry(key);
|
||||
NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
entry->mItem = new nsDOMStorageItem(aStorage, key, EmptyString(), secureInt);
|
||||
entry->mItem = new nsDOMStorageItem(aStorage, key, value, secureInt);
|
||||
if (!entry->mItem) {
|
||||
aKeys->RawRemoveEntry(entry);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
@ -347,12 +588,27 @@ nsDOMStoragePersistentDB::GetKeyValue(nsDOMStorage* aStorage,
|
|||
nsAString& aValue,
|
||||
PRBool* aSecure)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = MaybeCommitInsertTransaction();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = EnsureLoadTemporaryTableForStorage(aStorage);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mozStorageStatementScoper scope(mGetKeyValueStatement);
|
||||
|
||||
nsresult rv = mGetKeyValueStatement->BindUTF8StringParameter(
|
||||
0, aStorage->GetScopeDBKey());
|
||||
Binder binder(mGetKeyValueStatement, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = mGetKeyValueStatement->BindStringParameter(1, aKey);
|
||||
|
||||
rv = binder->BindUTF8StringByName(NS_LITERAL_CSTRING("scope"),
|
||||
aStorage->GetScopeDBKey());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = binder->BindStringByName(NS_LITERAL_CSTRING("key"),
|
||||
aKey);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = binder.Add();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool exists;
|
||||
|
@ -385,84 +641,61 @@ nsDOMStoragePersistentDB::SetKey(nsDOMStorage* aStorage,
|
|||
PRBool aExcludeOfflineFromUsage,
|
||||
PRInt32 *aNewUsage)
|
||||
{
|
||||
mozStorageStatementScoper scope(mGetKeyValueStatement);
|
||||
nsresult rv;
|
||||
|
||||
rv = EnsureLoadTemporaryTableForStorage(aStorage);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt32 usage = 0;
|
||||
nsresult rv;
|
||||
if (!aStorage->GetQuotaDomainDBKey(!aExcludeOfflineFromUsage).IsEmpty()) {
|
||||
rv = GetUsage(aStorage, aExcludeOfflineFromUsage, &usage);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
aStorage->CacheKeysFromDB();
|
||||
|
||||
usage += aKey.Length() + aValue.Length();
|
||||
|
||||
rv = mGetKeyValueStatement->BindUTF8StringParameter(0,
|
||||
aStorage->GetScopeDBKey());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = mGetKeyValueStatement->BindStringParameter(1, aKey);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool exists;
|
||||
rv = mGetKeyValueStatement->ExecuteStep(&exists);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (exists) {
|
||||
if (!aSecure) {
|
||||
PRInt32 secureInt = 0;
|
||||
rv = mGetKeyValueStatement->GetInt32(1, &secureInt);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (secureInt)
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
nsAutoString previousValue;
|
||||
rv = mGetKeyValueStatement->GetString(0, previousValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoString previousValue;
|
||||
PRBool secure;
|
||||
rv = aStorage->GetCachedValue(aKey, previousValue, &secure);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (!aSecure && secure)
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
usage -= aKey.Length() + previousValue.Length();
|
||||
|
||||
mGetKeyValueStatement->Reset();
|
||||
|
||||
if (usage > aQuota) {
|
||||
return NS_ERROR_DOM_QUOTA_REACHED;
|
||||
}
|
||||
|
||||
mozStorageStatementScoper scopeupdate(mUpdateKeyStatement);
|
||||
|
||||
rv = mUpdateKeyStatement->BindStringParameter(0, aValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = mUpdateKeyStatement->BindInt32Parameter(1, aSecure);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = mUpdateKeyStatement->BindUTF8StringParameter(2,
|
||||
aStorage->GetScopeDBKey());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = mUpdateKeyStatement->BindStringParameter(3, aKey);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mUpdateKeyStatement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else {
|
||||
if (usage > aQuota) {
|
||||
return NS_ERROR_DOM_QUOTA_REACHED;
|
||||
}
|
||||
|
||||
mozStorageStatementScoper scopeinsert(mInsertKeyStatement);
|
||||
|
||||
rv = mInsertKeyStatement->BindUTF8StringParameter(0,
|
||||
aStorage->GetScopeDBKey());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = mInsertKeyStatement->BindStringParameter(1, aKey);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = mInsertKeyStatement->BindStringParameter(2, aValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = mInsertKeyStatement->BindInt32Parameter(3, aSecure);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mInsertKeyStatement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (usage > aQuota) {
|
||||
return NS_ERROR_DOM_QUOTA_REACHED;
|
||||
}
|
||||
|
||||
rv = EnsureInsertTransaction();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mozStorageStatementScoper scopeinsert(mInsertKeyStatement);
|
||||
|
||||
Binder binder(mInsertKeyStatement, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = binder->BindUTF8StringByName(NS_LITERAL_CSTRING("scope"),
|
||||
aStorage->GetScopeDBKey());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = binder->BindStringByName(NS_LITERAL_CSTRING("key"),
|
||||
aKey);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = binder->BindStringByName(NS_LITERAL_CSTRING("value"),
|
||||
aValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = binder->BindInt32ByName(NS_LITERAL_CSTRING("secure"),
|
||||
aSecure ? 1 : 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = binder.Add();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mInsertKeyStatement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!aStorage->GetQuotaDomainDBKey(!aExcludeOfflineFromUsage).IsEmpty()) {
|
||||
mCachedOwner = aStorage->GetQuotaDomainDBKey(!aExcludeOfflineFromUsage);
|
||||
mCachedUsage = usage;
|
||||
|
@ -480,13 +713,28 @@ nsDOMStoragePersistentDB::SetSecure(nsDOMStorage* aStorage,
|
|||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = EnsureLoadTemporaryTableForStorage(aStorage);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = EnsureInsertTransaction();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mozStorageStatementScoper scope(mSetSecureStatement);
|
||||
|
||||
rv = mSetSecureStatement->BindInt32Parameter(0, aSecure ? 1 : 0);
|
||||
Binder binder(mSetSecureStatement, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = mSetSecureStatement->BindUTF8StringParameter(1, aStorage->GetScopeDBKey());
|
||||
|
||||
rv = binder->BindUTF8StringByName(NS_LITERAL_CSTRING("scope"),
|
||||
aStorage->GetScopeDBKey());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = mSetSecureStatement->BindStringParameter(2, aKey);
|
||||
rv = binder->BindStringByName(NS_LITERAL_CSTRING("key"),
|
||||
aKey);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = binder->BindInt32ByName(NS_LITERAL_CSTRING("secure"),
|
||||
aSecure ? 1 : 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = binder.Add();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return mSetSecureStatement->Execute();
|
||||
|
@ -498,42 +746,74 @@ nsDOMStoragePersistentDB::RemoveKey(nsDOMStorage* aStorage,
|
|||
PRBool aExcludeOfflineFromUsage,
|
||||
PRInt32 aKeyUsage)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = MaybeCommitInsertTransaction();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mozStorageStatementScoper scope(mRemoveKeyStatement);
|
||||
|
||||
if (aStorage->GetQuotaDomainDBKey(!aExcludeOfflineFromUsage) == mCachedOwner) {
|
||||
mCachedUsage -= aKeyUsage;
|
||||
}
|
||||
|
||||
nsresult rv = mRemoveKeyStatement->BindUTF8StringParameter(
|
||||
0, aStorage->GetScopeDBKey());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = mRemoveKeyStatement->BindStringParameter(1, aKey);
|
||||
Binder binder(mRemoveKeyStatement, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return mRemoveKeyStatement->Execute();
|
||||
rv = binder->BindUTF8StringByName(NS_LITERAL_CSTRING("scope"),
|
||||
aStorage->GetScopeDBKey());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = binder->BindStringByName(NS_LITERAL_CSTRING("key"),
|
||||
aKey);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = binder.Add();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mRemoveKeyStatement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMStoragePersistentDB::ClearStorage(nsDOMStorage* aStorage)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = MaybeCommitInsertTransaction();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mozStorageStatementScoper scope(mRemoveStorageStatement);
|
||||
|
||||
mCachedUsage = 0;
|
||||
mCachedOwner.Truncate();
|
||||
|
||||
nsresult rv;
|
||||
|
||||
rv = mRemoveStorageStatement->BindUTF8StringParameter(
|
||||
0, aStorage->GetScopeDBKey());
|
||||
Binder binder(mRemoveStorageStatement, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return mRemoveStorageStatement->Execute();
|
||||
rv = binder->BindUTF8StringByName(NS_LITERAL_CSTRING("scope"),
|
||||
aStorage->GetScopeDBKey());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = binder.Add();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mRemoveStorageStatement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMStoragePersistentDB::RemoveOwner(const nsACString& aOwner,
|
||||
PRBool aIncludeSubDomains)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = MaybeCommitInsertTransaction();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mozStorageStatementScoper scope(mRemoveOwnerStatement);
|
||||
|
||||
nsCAutoString subdomainsDBKey;
|
||||
|
@ -548,12 +828,20 @@ nsDOMStoragePersistentDB::RemoveOwner(const nsACString& aOwner,
|
|||
mCachedOwner.Truncate();
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
rv = mRemoveOwnerStatement->BindUTF8StringParameter(0, subdomainsDBKey);
|
||||
Binder binder(mRemoveOwnerStatement, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return mRemoveOwnerStatement->Execute();
|
||||
rv = binder->BindUTF8StringByName(NS_LITERAL_CSTRING("scope"),
|
||||
subdomainsDBKey);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = binder.Add();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mRemoveOwnerStatement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
@ -574,9 +862,9 @@ nsDOMStoragePersistentDB::RemoveOwners(const nsTArray<nsString> &aOwners,
|
|||
nsCString expression;
|
||||
|
||||
if (aMatch) {
|
||||
expression.AppendLiteral("DELETE FROM webappsstore2 WHERE scope IN (");
|
||||
expression.AppendLiteral("DELETE FROM webappsstore2_view WHERE scope IN (");
|
||||
} else {
|
||||
expression.AppendLiteral("DELETE FROM webappsstore2 WHERE scope NOT IN (");
|
||||
expression.AppendLiteral("DELETE FROM webappsstore2_view WHERE scope NOT IN (");
|
||||
}
|
||||
|
||||
for (PRUint32 i = 0; i < aOwners.Length(); i++) {
|
||||
|
@ -584,14 +872,27 @@ nsDOMStoragePersistentDB::RemoveOwners(const nsTArray<nsString> &aOwners,
|
|||
expression.AppendLiteral(" UNION ");
|
||||
|
||||
expression.AppendLiteral(
|
||||
"SELECT DISTINCT scope FROM webappsstore2 WHERE scope GLOB ?");
|
||||
"SELECT DISTINCT scope FROM webappsstore2_temp WHERE scope GLOB :scope");
|
||||
expression.AppendInt(i);
|
||||
expression.AppendLiteral(" UNION ");
|
||||
expression.AppendLiteral(
|
||||
"SELECT DISTINCT scope FROM webappsstore2 WHERE scope GLOB :scope");
|
||||
expression.AppendInt(i);
|
||||
}
|
||||
expression.AppendLiteral(");");
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> statement;
|
||||
|
||||
nsresult rv = mConnection->CreateStatement(expression,
|
||||
getter_AddRefs(statement));
|
||||
nsresult rv;
|
||||
|
||||
rv = MaybeCommitInsertTransaction();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mConnection->CreateStatement(expression,
|
||||
getter_AddRefs(statement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
Binder binder(statement, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (PRUint32 i = 0; i < aOwners.Length(); i++) {
|
||||
|
@ -603,10 +904,17 @@ nsDOMStoragePersistentDB::RemoveOwners(const nsTArray<nsString> &aOwners,
|
|||
quotaKey.AppendLiteral(":");
|
||||
quotaKey.AppendLiteral("*");
|
||||
|
||||
rv = statement->BindUTF8StringParameter(i, quotaKey);
|
||||
nsCAutoString paramName;
|
||||
paramName.Assign("scope");
|
||||
paramName.AppendInt(i);
|
||||
|
||||
rv = binder->BindUTF8StringByName(paramName, quotaKey);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
rv = binder.Add();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = statement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
@ -616,8 +924,17 @@ nsDOMStoragePersistentDB::RemoveOwners(const nsTArray<nsString> &aOwners,
|
|||
nsresult
|
||||
nsDOMStoragePersistentDB::RemoveAll()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = MaybeCommitInsertTransaction();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mozStorageStatementScoper scope(mRemoveAllStatement);
|
||||
return mRemoveAllStatement->Execute();
|
||||
|
||||
rv = mRemoveAllStatement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -657,17 +974,26 @@ nsDOMStoragePersistentDB::GetUsageInternal(const nsACString& aQuotaDomainDBKey,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
rv = MaybeCommitInsertTransaction();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mozIStorageStatement* statement = aExcludeOfflineFromUsage
|
||||
? mGetOfflineExcludedUsageStatement : mGetFullUsageStatement;
|
||||
|
||||
mozStorageStatementScoper scope(statement);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCAutoString scopeValue(aQuotaDomainDBKey);
|
||||
scopeValue += NS_LITERAL_CSTRING("*");
|
||||
|
||||
rv = statement->BindUTF8StringParameter(0, scopeValue);
|
||||
Binder binder(statement, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = binder->BindUTF8StringByName(NS_LITERAL_CSTRING("scope"), scopeValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = binder.Add();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool exists;
|
||||
|
@ -689,3 +1015,44 @@ nsDOMStoragePersistentDB::GetUsageInternal(const nsACString& aQuotaDomainDBKey,
|
|||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMStoragePersistentDB::EnsureInsertTransaction()
|
||||
{
|
||||
if (!mConnection)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
PRBool transactionInProgress;
|
||||
nsresult rv = mConnection->GetTransactionInProgress(&transactionInProgress);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (transactionInProgress)
|
||||
return NS_OK;
|
||||
|
||||
rv = mConnection->BeginTransaction();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMStoragePersistentDB::MaybeCommitInsertTransaction()
|
||||
{
|
||||
if (!mConnection)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
PRBool transactionInProgress;
|
||||
nsresult rv = mConnection->GetTransactionInProgress(&transactionInProgress);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("nsDOMStoragePersistentDB::MaybeCommitInsertTransaction: "
|
||||
"connection probably already dead");
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv) || !transactionInProgress)
|
||||
return NS_OK;
|
||||
|
||||
rv = mConnection->CommitTransaction();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -50,12 +50,17 @@ class nsSessionStorageEntry;
|
|||
class nsDOMStoragePersistentDB
|
||||
{
|
||||
public:
|
||||
nsDOMStoragePersistentDB() {}
|
||||
nsDOMStoragePersistentDB();
|
||||
~nsDOMStoragePersistentDB() {}
|
||||
|
||||
nsresult
|
||||
Init(const nsString& aDatabaseName);
|
||||
|
||||
nsresult
|
||||
EnsureLoadTemporaryTableForStorage(nsDOMStorage* aStorage);
|
||||
nsresult
|
||||
FlushAndDeleteTemporaryTableForStorage(nsDOMStorage* aStorage);
|
||||
|
||||
/**
|
||||
* Retrieve a list of all the keys associated with a particular domain.
|
||||
*/
|
||||
|
@ -146,14 +151,27 @@ public:
|
|||
*/
|
||||
nsresult ClearAllPrivateBrowsingData();
|
||||
|
||||
/**
|
||||
* We process INSERTs in a transaction because of performance.
|
||||
* If there is currently no transaction in progress, start one.
|
||||
*/
|
||||
nsresult EnsureInsertTransaction();
|
||||
|
||||
/**
|
||||
* If there is an INSERT transaction in progress, commit it now.
|
||||
*/
|
||||
nsresult MaybeCommitInsertTransaction();
|
||||
|
||||
protected:
|
||||
|
||||
nsCOMPtr<mozIStorageConnection> mConnection;
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> mCopyToTempTableStatement;
|
||||
nsCOMPtr<mozIStorageStatement> mCopyBackToDiskStatement;
|
||||
nsCOMPtr<mozIStorageStatement> mDeleteTemporaryTableStatement;
|
||||
nsCOMPtr<mozIStorageStatement> mGetAllKeysStatement;
|
||||
nsCOMPtr<mozIStorageStatement> mGetKeyValueStatement;
|
||||
nsCOMPtr<mozIStorageStatement> mInsertKeyStatement;
|
||||
nsCOMPtr<mozIStorageStatement> mUpdateKeyStatement;
|
||||
nsCOMPtr<mozIStorageStatement> mSetSecureStatement;
|
||||
nsCOMPtr<mozIStorageStatement> mRemoveKeyStatement;
|
||||
nsCOMPtr<mozIStorageStatement> mRemoveOwnerStatement;
|
||||
|
|
|
@ -2278,7 +2278,7 @@ NS_IMETHODIMP nsEditor::ScrollSelectionIntoView(PRBool aScrollToAnchor)
|
|||
region = nsISelectionController::SELECTION_ANCHOR_REGION;
|
||||
|
||||
selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL,
|
||||
region, PR_FALSE);
|
||||
region, 0);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -1203,7 +1203,8 @@ nsTextServicesDocument::ScrollSelectionIntoView()
|
|||
|
||||
// After ScrollSelectionIntoView(), the pending notifications might be flushed
|
||||
// and PresShell/PresContext/Frames may be dead. See bug 418470.
|
||||
result = mSelCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_FOCUS_REGION, PR_TRUE);
|
||||
result = mSelCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_FOCUS_REGION,
|
||||
nsISelectionController::SCROLL_SYNCHRONOUS);
|
||||
|
||||
UNLOCK_DOC(this);
|
||||
|
||||
|
|
|
@ -266,13 +266,15 @@ public class CrashReporter extends Activity
|
|||
void doRestart()
|
||||
{
|
||||
try {
|
||||
String action = "org.mozilla.gecko.restart@MOZ_APP_NAME@";
|
||||
String amCmd = "/system/bin/am broadcast -a " + action +
|
||||
" -n org.mozilla.@MOZ_APP_NAME@/org.mozilla.@MOZ_APP_NAME@.Restarter";
|
||||
Log.i("GeckoCrashReporter", amCmd);
|
||||
Runtime.getRuntime().exec(amCmd);
|
||||
String action = "android.intent.action.MAIN";
|
||||
Intent intent = new Intent(action);
|
||||
intent.setClassName("org.mozilla.@MOZ_APP_NAME@",
|
||||
"org.mozilla.@MOZ_APP_NAME@.App");
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
Log.i("GeckoCrashReporter", intent.toString());
|
||||
startActivity(intent);
|
||||
} catch (Exception e) {
|
||||
Log.i("GeckoCrashReporter", e.toString());
|
||||
Log.e("GeckoCrashReporter", "error while trying to restart", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -426,7 +426,7 @@ abstract public class GeckoApp
|
|||
outFile.setLastModified(fileEntry.getTime());
|
||||
}
|
||||
|
||||
public String getEnvString() {
|
||||
public void addEnvToIntent(Intent intent) {
|
||||
Map<String,String> envMap = System.getenv();
|
||||
Set<Map.Entry<String,String>> envSet = envMap.entrySet();
|
||||
Iterator<Map.Entry<String,String>> envIter = envSet.iterator();
|
||||
|
@ -434,39 +434,25 @@ abstract public class GeckoApp
|
|||
int c = 0;
|
||||
while (envIter.hasNext()) {
|
||||
Map.Entry<String,String> entry = envIter.next();
|
||||
// No need to pass env vars that we know the system provides
|
||||
// Unnecessary vars need to be trimmed since amount of data
|
||||
// we can pass this way is limited
|
||||
if (!entry.getKey().equals("BOOTCLASSPATH") &&
|
||||
!entry.getKey().equals("ANDROID_SOCKET_zygote") &&
|
||||
!entry.getKey().equals("TMPDIR") &&
|
||||
!entry.getKey().equals("ANDROID_BOOTLOGO") &&
|
||||
!entry.getKey().equals("EXTERNAL_STORAGE") &&
|
||||
!entry.getKey().equals("ANDROID_ASSETS") &&
|
||||
!entry.getKey().equals("PATH") &&
|
||||
!entry.getKey().equals("TERMINFO") &&
|
||||
!entry.getKey().equals("LD_LIBRARY_PATH") &&
|
||||
!entry.getKey().equals("ANDROID_DATA") &&
|
||||
!entry.getKey().equals("ANDROID_PROPERTY_WORKSPACE") &&
|
||||
!entry.getKey().equals("ANDROID_ROOT")) {
|
||||
envstr.append(" --es env" + c + " " + entry.getKey() + "="
|
||||
+ entry.getValue());
|
||||
c++;
|
||||
}
|
||||
intent.putExtra("env" + c, entry.getKey() + "="
|
||||
+ entry.getValue());
|
||||
c++;
|
||||
}
|
||||
return envstr.toString();
|
||||
}
|
||||
|
||||
public void doRestart() {
|
||||
try {
|
||||
String action = "org.mozilla.gecko.restart" + getAppName();
|
||||
String amCmd = "/system/bin/am broadcast -a " + action + getEnvString() + " -n org.mozilla." + getAppName() + "/org.mozilla." + getAppName() + ".Restarter";
|
||||
Log.i("GeckoAppJava", amCmd);
|
||||
Runtime.getRuntime().exec(amCmd);
|
||||
Intent intent = new Intent(action);
|
||||
intent.setClassName("org.mozilla." + getAppName(),
|
||||
"org.mozilla." + getAppName() + ".Restarter");
|
||||
addEnvToIntent(intent);
|
||||
Log.i("GeckoAppJava", intent.toString());
|
||||
sendBroadcast(intent);
|
||||
} catch (Exception e) {
|
||||
Log.i("GeckoAppJava", e.toString());
|
||||
}
|
||||
System.exit(0);
|
||||
finish();
|
||||
}
|
||||
|
||||
public void handleNotification(String action, String alertName, String alertCookie) {
|
||||
|
|
|
@ -70,6 +70,7 @@ class GeckoAppShell
|
|||
private GeckoAppShell() { }
|
||||
|
||||
static boolean sGeckoRunning;
|
||||
static private GeckoEvent gPendingResize = null;
|
||||
|
||||
static private boolean gRestartScheduled = false;
|
||||
|
||||
|
@ -90,7 +91,6 @@ class GeckoAppShell
|
|||
public static native void nativeRun(String args);
|
||||
|
||||
// helper methods
|
||||
public static native void setInitialSize(int width, int height);
|
||||
public static native void setSurfaceView(GeckoSurfaceView sv);
|
||||
public static native void putenv(String map);
|
||||
public static native void onResume();
|
||||
|
@ -136,8 +136,6 @@ class GeckoAppShell
|
|||
// Tell Gecko where the target surface view is for rendering
|
||||
GeckoAppShell.setSurfaceView(GeckoApp.surfaceView);
|
||||
|
||||
sGeckoRunning = true;
|
||||
|
||||
// First argument is the .apk path
|
||||
String combinedArgs = apkPath + " -omnijar " + apkPath;
|
||||
if (args != null)
|
||||
|
@ -151,8 +149,16 @@ class GeckoAppShell
|
|||
private static GeckoEvent mLastDrawEvent;
|
||||
|
||||
public static void sendEventToGecko(GeckoEvent e) {
|
||||
if (sGeckoRunning)
|
||||
if (sGeckoRunning) {
|
||||
if (gPendingResize != null) {
|
||||
notifyGeckoOfEvent(gPendingResize);
|
||||
gPendingResize = null;
|
||||
}
|
||||
notifyGeckoOfEvent(e);
|
||||
} else {
|
||||
if (e.mType == GeckoEvent.SIZE_CHANGED)
|
||||
gPendingResize = e;
|
||||
}
|
||||
}
|
||||
|
||||
// Tell the Gecko event loop that an event is available.
|
||||
|
@ -325,6 +331,15 @@ class GeckoAppShell
|
|||
}
|
||||
}
|
||||
|
||||
static void onAppShellReady()
|
||||
{
|
||||
sGeckoRunning = true;
|
||||
if (gPendingResize != null) {
|
||||
notifyGeckoOfEvent(gPendingResize);
|
||||
gPendingResize = null;
|
||||
}
|
||||
}
|
||||
|
||||
static void onXreExit() {
|
||||
sGeckoRunning = false;
|
||||
Log.i("GeckoAppJava", "XRE exited");
|
||||
|
@ -332,7 +347,7 @@ class GeckoAppShell
|
|||
GeckoApp.mAppContext.doRestart();
|
||||
} else {
|
||||
Log.i("GeckoAppJava", "we're done, good bye");
|
||||
System.exit(0);
|
||||
GeckoApp.mAppContext.finish();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -116,9 +116,6 @@ class GeckoSurfaceView
|
|||
|
||||
Log.i("GeckoAppJava", "surfaceChanged: fmt: " + format + " dim: " + width + " " + height);
|
||||
|
||||
if (!GeckoAppShell.sGeckoRunning)
|
||||
return;
|
||||
|
||||
GeckoEvent e = new GeckoEvent(GeckoEvent.SIZE_CHANGED, width, height, -1, -1);
|
||||
GeckoAppShell.sendEventToGecko(e);
|
||||
|
||||
|
@ -126,8 +123,6 @@ class GeckoSurfaceView
|
|||
GeckoAppShell.scheduleRedraw();
|
||||
mSurfaceNeedsRedraw = false;
|
||||
}
|
||||
|
||||
mSurfaceChanged = true;
|
||||
} finally {
|
||||
mSurfaceLock.unlock();
|
||||
}
|
||||
|
@ -195,8 +190,6 @@ class GeckoSurfaceView
|
|||
Log.e("GeckoAppJava", "endDrawing with false mSurfaceValid");
|
||||
return;
|
||||
}
|
||||
} catch (java.lang.IllegalArgumentException ex) {
|
||||
mSurfaceChanged = true;
|
||||
} finally {
|
||||
mInDrawing = false;
|
||||
|
||||
|
@ -291,10 +284,6 @@ class GeckoSurfaceView
|
|||
// Do we need to force a redraw on surfaceChanged?
|
||||
boolean mSurfaceNeedsRedraw;
|
||||
|
||||
// Has this surface been changed? (That is,
|
||||
// do we need to recreate buffers?)
|
||||
boolean mSurfaceChanged;
|
||||
|
||||
// Are we actively between beginDrawing/endDrawing?
|
||||
boolean mInDrawing;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: Java; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
|
@ -39,24 +39,25 @@
|
|||
package org.mozilla.@MOZ_APP_NAME@;
|
||||
|
||||
import android.content.*;
|
||||
import android.util.Log;
|
||||
import android.util.*;
|
||||
import android.os.*;
|
||||
import java.io.*;
|
||||
|
||||
public class Restarter extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
@Override
|
||||
public void onReceive(Context aContext, Intent aIntent) {
|
||||
Log.i("Restarter", "trying to restart @MOZ_APP_NAME@");
|
||||
try {
|
||||
try {
|
||||
boolean stillRunning;
|
||||
do {
|
||||
stillRunning = false;
|
||||
Process p = Runtime.getRuntime().exec("/system/bin/ps");
|
||||
java.lang.Process p = Runtime.getRuntime().exec("/system/bin/ps");
|
||||
BufferedReader psOut = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
String line;
|
||||
Log.i("Restarter", "pid: " + new Integer(android.os.Process.myPid()).toString());
|
||||
while((line = psOut.readLine()) != null) {
|
||||
Log.i("Restarter", "ps: " + line);
|
||||
if (line.contains("org.mozilla.@MOZ_APP_NAME@.App")){
|
||||
if (line.contains("org.mozilla.@MOZ_APP_NAME@")){
|
||||
if (!line.contains(new Integer(android.os.Process.myPid()).toString())){
|
||||
Log.i("Restarter", "app still running, wait a bit");
|
||||
stillRunning = true;
|
||||
|
@ -69,23 +70,22 @@ public class Restarter extends BroadcastReceiver {
|
|||
}
|
||||
} while(stillRunning);
|
||||
} catch (Exception e) {
|
||||
Log.i("Restarter", e.toString());
|
||||
Log.i("Restarter", e.toString());
|
||||
}
|
||||
try {
|
||||
String action = "android.intent.action.MAIN";
|
||||
String env;
|
||||
StringBuffer envstr = new StringBuffer();
|
||||
for (int c = 0; (env = intent.getStringExtra("env" + c)) != null; c++) {
|
||||
envstr.append(" --es env" + c + " " + env);
|
||||
}
|
||||
String amCmd = "/system/bin/am start -a " + action + envstr.toString() +
|
||||
" -n org.mozilla.@MOZ_APP_NAME@/org.mozilla.@MOZ_APP_NAME@.App";
|
||||
Log.i("Restarter", amCmd);
|
||||
|
||||
Runtime.getRuntime().exec(amCmd);
|
||||
Intent intent = new Intent(action);
|
||||
intent.setClassName("org.mozilla.@MOZ_APP_NAME@",
|
||||
"org.mozilla.@MOZ_APP_NAME@.App");
|
||||
Bundle b = aIntent.getExtras();
|
||||
if (b != null)
|
||||
intent.putExtras(b);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
Log.i("GeckoAppJava", intent.toString());
|
||||
aContext.startActivity(intent);
|
||||
} catch (Exception e) {
|
||||
Log.i("Restarter", e.toString());
|
||||
}
|
||||
System.exit(0);
|
||||
System.exit(0);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -451,7 +451,8 @@ void nsWebBrowserFind::SetSelectionAndScroll(nsIDOMWindow* aWindow,
|
|||
// flushed and PresShell/PresContext/Frames may be dead. See bug 418470.
|
||||
selCon->ScrollSelectionIntoView
|
||||
(nsISelectionController::SELECTION_NORMAL,
|
||||
nsISelectionController::SELECTION_FOCUS_REGION, PR_TRUE);
|
||||
nsISelectionController::SELECTION_FOCUS_REGION,
|
||||
nsISelectionController::SCROLL_SYNCHRONOUS);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -81,10 +81,6 @@
|
|||
|
||||
@QT_SURFACE_FEATURE@
|
||||
|
||||
@DDRAW_SURFACE_FEATURE@
|
||||
|
||||
@OGLES_SURFACE_FEATURE@
|
||||
|
||||
@FT_FONT_FEATURE@
|
||||
|
||||
@WIN32_FONT_FEATURE@
|
||||
|
|
|
@ -390,16 +390,6 @@ ClipToContain(gfxContext* aContext, const nsIntRect& aRect)
|
|||
aContext->SetMatrix(currentMatrix);
|
||||
}
|
||||
|
||||
static void
|
||||
InheritContextFlags(gfxContext* aSource, gfxContext* aDest)
|
||||
{
|
||||
if (aSource->GetFlags() & gfxContext::FLAG_DESTINED_FOR_SCREEN) {
|
||||
aDest->SetFlag(gfxContext::FLAG_DESTINED_FOR_SCREEN);
|
||||
} else {
|
||||
aDest->ClearFlag(gfxContext::FLAG_DESTINED_FOR_SCREEN);
|
||||
}
|
||||
}
|
||||
|
||||
static PRBool
|
||||
ShouldRetainTransparentSurface(PRUint32 aContentFlags,
|
||||
gfxASurface* aTargetSurface)
|
||||
|
@ -493,7 +483,6 @@ BasicThebesLayer::Paint(gfxContext* aContext,
|
|||
// from RGB to RGBA, because we might need to repaint with
|
||||
// subpixel AA)
|
||||
state.mRegionToInvalidate.And(state.mRegionToInvalidate, mVisibleRegion);
|
||||
InheritContextFlags(target, state.mContext);
|
||||
mXResolution = paintXRes;
|
||||
mYResolution = paintYRes;
|
||||
PaintBuffer(state.mContext,
|
||||
|
@ -1016,7 +1005,6 @@ BasicLayerManager::PushGroupWithCachedSurface(gfxContext *aTarget,
|
|||
mCachedSurface.Get(aContent,
|
||||
gfxIntSize(clip.size.width, clip.size.height),
|
||||
currentSurf);
|
||||
InheritContextFlags(aTarget, ctx);
|
||||
/* Align our buffer for the original surface */
|
||||
ctx->Translate(-clip.pos);
|
||||
*aSavedOffset = clip.pos;
|
||||
|
|
|
@ -46,22 +46,23 @@ using mozilla::MutexAutoLock;
|
|||
|
||||
ImageContainerD3D10::ImageContainerD3D10(LayerManagerD3D10 *aManager)
|
||||
: ImageContainer(aManager)
|
||||
, mDevice(aManager->device())
|
||||
, mActiveImageLock("mozilla.layers.ImageContainerD3D10.mActiveImageLock")
|
||||
{
|
||||
}
|
||||
|
||||
already_AddRefed<Image>
|
||||
ImageContainerD3D10::CreateImage(const Image::Format *aFormats,
|
||||
PRUint32 aNumFormats)
|
||||
PRUint32 aNumFormats)
|
||||
{
|
||||
if (!aNumFormats) {
|
||||
return nsnull;
|
||||
}
|
||||
nsRefPtr<Image> img;
|
||||
if (aFormats[0] == Image::PLANAR_YCBCR) {
|
||||
img = new PlanarYCbCrImageD3D10(static_cast<LayerManagerD3D10*>(mManager));
|
||||
img = new PlanarYCbCrImageD3D10(mDevice);
|
||||
} else if (aFormats[0] == Image::CAIRO_SURFACE) {
|
||||
img = new CairoImageD3D10(static_cast<LayerManagerD3D10*>(mManager));
|
||||
img = new CairoImageD3D10(mDevice);
|
||||
}
|
||||
return img.forget();
|
||||
}
|
||||
|
@ -212,11 +213,11 @@ ImageLayerD3D10::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform)
|
|||
device()->Draw(4, 0);
|
||||
}
|
||||
|
||||
PlanarYCbCrImageD3D10::PlanarYCbCrImageD3D10(mozilla::layers::LayerManagerD3D10* aManager)
|
||||
PlanarYCbCrImageD3D10::PlanarYCbCrImageD3D10(ID3D10Device1 *aDevice)
|
||||
: PlanarYCbCrImage(static_cast<ImageD3D10*>(this))
|
||||
, mDevice(aDevice)
|
||||
, mHasData(PR_FALSE)
|
||||
{
|
||||
mDevice = aManager->device();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -381,8 +382,8 @@ CairoImageD3D10::SetData(const CairoImage::Data &aData)
|
|||
data.pSysMem = imageSurface->Data();
|
||||
data.SysMemPitch = imageSurface->Stride();
|
||||
|
||||
mManager->device()->CreateTexture2D(&desc, &data, getter_AddRefs(mTexture));
|
||||
mManager->device()->CreateShaderResourceView(mTexture, NULL, getter_AddRefs(mSRView));
|
||||
mDevice->CreateTexture2D(&desc, &data, getter_AddRefs(mTexture));
|
||||
mDevice->CreateShaderResourceView(mTexture, NULL, getter_AddRefs(mSRView));
|
||||
}
|
||||
|
||||
already_AddRefed<gfxASurface>
|
||||
|
|
|
@ -69,6 +69,7 @@ private:
|
|||
typedef mozilla::Mutex Mutex;
|
||||
|
||||
nsRefPtr<Image> mActiveImage;
|
||||
nsRefPtr<ID3D10Device1> mDevice;
|
||||
|
||||
Mutex mActiveImageLock;
|
||||
};
|
||||
|
@ -100,7 +101,7 @@ class THEBES_API PlanarYCbCrImageD3D10 : public PlanarYCbCrImage,
|
|||
public ImageD3D10
|
||||
{
|
||||
public:
|
||||
PlanarYCbCrImageD3D10(LayerManagerD3D10 *aManager);
|
||||
PlanarYCbCrImageD3D10(ID3D10Device1 *aDevice);
|
||||
~PlanarYCbCrImageD3D10() {}
|
||||
|
||||
virtual void SetData(const Data &aData);
|
||||
|
@ -134,9 +135,9 @@ class THEBES_API CairoImageD3D10 : public CairoImage,
|
|||
public ImageD3D10
|
||||
{
|
||||
public:
|
||||
CairoImageD3D10(LayerManagerD3D10 *aManager)
|
||||
CairoImageD3D10(ID3D10Device1 *aDevice)
|
||||
: CairoImage(static_cast<ImageD3D10*>(this))
|
||||
, mManager(aManager)
|
||||
, mDevice(aDevice)
|
||||
{ }
|
||||
~CairoImageD3D10();
|
||||
|
||||
|
@ -144,10 +145,10 @@ public:
|
|||
|
||||
virtual already_AddRefed<gfxASurface> GetAsSurface();
|
||||
|
||||
nsRefPtr<ID3D10Device1> mDevice;
|
||||
nsRefPtr<ID3D10Texture2D> mTexture;
|
||||
nsRefPtr<ID3D10ShaderResourceView> mSRView;
|
||||
gfxIntSize mSize;
|
||||
LayerManagerD3D10 *mManager;
|
||||
};
|
||||
|
||||
} /* layers */
|
||||
|
|
|
@ -637,15 +637,7 @@ public:
|
|||
* When this flag is set, snapping to device pixels is disabled.
|
||||
* It simply never does anything.
|
||||
*/
|
||||
FLAG_DISABLE_SNAPPING = (1 << 1),
|
||||
/**
|
||||
* When this flag is set, rendering through this context
|
||||
* is destined to be (eventually) drawn on the screen. It can be
|
||||
* useful to know this, for example so that windowed plugins are
|
||||
* not unnecessarily rendered (since they will already appear
|
||||
* on the screen, thanks to their windows).
|
||||
*/
|
||||
FLAG_DESTINED_FOR_SCREEN = (1 << 2)
|
||||
FLAG_DISABLE_SNAPPING = (1 << 1)
|
||||
};
|
||||
|
||||
void SetFlag(PRInt32 aFlag) { mFlags |= aFlag; }
|
||||
|
|
|
@ -363,3 +363,16 @@ static const PRUint32 gCaseBlocks [8] = {
|
|||
0x00000000,
|
||||
0x80000000
|
||||
};
|
||||
|
||||
// We map x -> x, except for upper-case letters,
|
||||
// which we map to their lower-case equivalents.
|
||||
static const PRUint8 gASCIIToLower [128] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||
0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
|
||||
};
|
||||
|
|
|
@ -281,6 +281,103 @@ static PRUnichar t4result[T4LEN+2] = {
|
|||
0x0041 , // Dummy entry to prevent overflow
|
||||
0x00
|
||||
};
|
||||
|
||||
static unsigned char t6lhs[] = {
|
||||
0x31 , // 0
|
||||
0x19 , // 1
|
||||
0x43 , // 2
|
||||
0x67 , // 3
|
||||
0xC3, 0x88 , // 4
|
||||
0xC3, 0xA9 , // 5
|
||||
0xC5, 0x87 , // 6
|
||||
0xC7, 0x84 , // 7
|
||||
0xC7, 0x86 , // 8
|
||||
0xC7, 0x85 , // 9
|
||||
0xCF, 0x80 , // 10
|
||||
0xCE, 0xB2 , // 11
|
||||
0xD0, 0xB8 , // 12
|
||||
0xD2, 0xA5 , // 13
|
||||
0xD7, 0x90 , // 14
|
||||
0xE0, 0xA8, 0xA0 , // 15
|
||||
0xE3, 0x82, 0xB0 , // 16
|
||||
0xE5, 0x86, 0x85 , // 17
|
||||
0xEC, 0x80, 0xA1 , // 18
|
||||
0xEF, 0xBD, 0x88 , // 19
|
||||
0xC7, 0x87 , // 20
|
||||
0xC7, 0x88 , // 21
|
||||
0xC7, 0x89 , // 22
|
||||
0xC7, 0x8A , // 23
|
||||
0xC7, 0x8B , // 24
|
||||
0xC7, 0x8C , // 25
|
||||
0xC7, 0xB1 , // 26
|
||||
0xC7, 0xB2 , // 27
|
||||
0xC7, 0xB3 , // 28
|
||||
0xC9, 0x90 , // 29
|
||||
0xC9, 0xB1 , // 30
|
||||
0xEA, 0x99, 0x81 , // 31
|
||||
0x00
|
||||
};
|
||||
|
||||
static unsigned char t6rhs[] = {
|
||||
0x31 , // 0
|
||||
0x19 , // 1
|
||||
0x43 , // 2
|
||||
0x47 , // 3
|
||||
0xC3, 0x88 , // 4
|
||||
0xC3, 0x89 , // 5
|
||||
0xC5, 0x87 , // 6
|
||||
0xC7, 0x84 , // 7
|
||||
0xC7, 0x84 , // 8
|
||||
0xC7, 0x84 , // 9
|
||||
0xCE, 0xA0 , // 10
|
||||
0xCE, 0x92 , // 11
|
||||
0xD0, 0x98 , // 12
|
||||
0xD2, 0xA4 , // 13
|
||||
0xD7, 0x90 , // 14
|
||||
0xE0, 0xA8, 0xA0 , // 15
|
||||
0xE3, 0x82, 0xB0 , // 16
|
||||
0xE5, 0x86, 0x85 , // 17
|
||||
0xEC, 0x80, 0xA1 , // 18
|
||||
0xEF, 0xBC, 0xA8 , // 19
|
||||
0xC7, 0x87 , // 20
|
||||
0xC7, 0x87 , // 21
|
||||
0xC7, 0x87 , // 22
|
||||
0xC7, 0x8a , // 23
|
||||
0xC7, 0x8a , // 24
|
||||
0xC7, 0x8a , // 25
|
||||
0xC7, 0xB1 , // 26
|
||||
0xC7, 0xB1 , // 27
|
||||
0xC7, 0xB1 , // 28
|
||||
0xE2, 0xB1, 0xAF , // 29
|
||||
0xE2, 0xB1, 0xAE , // 30
|
||||
0xEA, 0x99, 0x80 , // 31
|
||||
0x00
|
||||
};
|
||||
|
||||
static const char *t7lhs = "aBcDeFGHIJKL1!!2!!a!uuuu";
|
||||
static const char *t7rhs = "AbCdEFghijkL1!!2!!A!UUuU";
|
||||
|
||||
static const char *t8lhs = "aazzz";
|
||||
static const char *t8rhs = "aBa";
|
||||
|
||||
static const char *t9lhs = "@a";
|
||||
static const char *t9rhs = "`a";
|
||||
|
||||
bool CharByCharCompareEqual(const char *a, const char *b,
|
||||
PRUint32 aLen, PRUint32 bLen)
|
||||
{
|
||||
// Do basically a CaseInsensitiveCompare(), but using
|
||||
// CaseInsensitiveUTF8CharsEqual().
|
||||
|
||||
const char *aEnd = a + aLen;
|
||||
const char *bEnd = b + bLen;
|
||||
while (a < aEnd && b < bEnd) {
|
||||
PRBool err;
|
||||
if (!CaseInsensitiveUTF8CharsEqual(a, b, aEnd, bEnd, &a, &b, &err) || err)
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void TestCaseConversion()
|
||||
{
|
||||
|
@ -291,7 +388,7 @@ void TestCaseConversion()
|
|||
int i;
|
||||
PRUnichar buf[256];
|
||||
|
||||
printf("Test 2 - ToUpper(PRUnichar, PRUnichar*):\n");
|
||||
printf("Test 1 - ToUpper(PRUnichar, PRUnichar*):\n");
|
||||
for(i=0;i < T2LEN ; i++)
|
||||
{
|
||||
PRUnichar ch = ToUpperCase(t2data[i]);
|
||||
|
@ -300,7 +397,7 @@ void TestCaseConversion()
|
|||
}
|
||||
|
||||
|
||||
printf("Test 3 - ToLower(PRUnichar, PRUnichar*):\n");
|
||||
printf("Test 2 - ToLower(PRUnichar, PRUnichar*):\n");
|
||||
for(i=0;i < T3LEN; i++)
|
||||
{
|
||||
PRUnichar ch = ToLowerCase(t3data[i]);
|
||||
|
@ -308,7 +405,7 @@ void TestCaseConversion()
|
|||
printf("\tFailed!! result unexpected %d\n", i);
|
||||
}
|
||||
|
||||
printf("Test 4 - ToTitle(PRUnichar, PRUnichar*):\n");
|
||||
printf("Test 3 - ToTitle(PRUnichar, PRUnichar*):\n");
|
||||
for(i=0;i < T4LEN; i++)
|
||||
{
|
||||
PRUnichar ch = ToTitleCase(t4data[i]);
|
||||
|
@ -316,7 +413,7 @@ void TestCaseConversion()
|
|||
printf("\tFailed!! result unexpected %d\n", i);
|
||||
}
|
||||
|
||||
printf("Test 5 - ToUpper(PRUnichar*, PRUnichar*, PRUint32):\n");
|
||||
printf("Test 4 - ToUpper(PRUnichar*, PRUnichar*, PRUint32):\n");
|
||||
ToUpperCase(t2data, buf, T2LEN);
|
||||
for(i = 0; i < T2LEN; i++)
|
||||
{
|
||||
|
@ -327,7 +424,7 @@ void TestCaseConversion()
|
|||
}
|
||||
}
|
||||
|
||||
printf("Test 6 - ToLower(PRUnichar*, PRUnichar*, PRUint32):\n");
|
||||
printf("Test 5 - ToLower(PRUnichar*, PRUnichar*, PRUint32):\n");
|
||||
ToLowerCase(t3data, buf, T3LEN);
|
||||
for(i = 0; i < T3LEN; i++)
|
||||
{
|
||||
|
@ -338,11 +435,85 @@ void TestCaseConversion()
|
|||
}
|
||||
}
|
||||
|
||||
printf("Test 6 - CaseInsensitiveCompare UTF-8 (1):\n");
|
||||
if (CaseInsensitiveCompare((char*)t6lhs, (char*)t6rhs, sizeof(t6lhs), sizeof(t6rhs)))
|
||||
printf("\tFailed!\n");
|
||||
if (!CharByCharCompareEqual((char*)t6lhs, (char*)t6rhs, sizeof(t6lhs), sizeof(t6rhs)))
|
||||
printf("\tFailed character-by-character comparison!\n");
|
||||
|
||||
printf("Test 7 - CaseInsensitiveCompare UTF-8 (2):\n");
|
||||
if (CaseInsensitiveCompare(t7lhs, t7rhs, strlen(t7lhs), strlen(t7rhs)))
|
||||
printf("\tFailed!\n");
|
||||
if (!CharByCharCompareEqual(t7lhs, t7rhs, sizeof(t7lhs), sizeof(t7rhs)))
|
||||
printf("\tFailed character-by-character comparison!\n");
|
||||
|
||||
printf("Test 8a - CaseInsensitiveCompare UTF-8 (3):\n");
|
||||
if (CaseInsensitiveCompare(t8lhs, t8rhs, strlen(t8lhs), strlen(t8rhs)) != -1)
|
||||
printf("\tFailed!\n");
|
||||
if (CharByCharCompareEqual(t8lhs, t8rhs, strlen(t8lhs), strlen(t8rhs)))
|
||||
printf("\tFailed character-by-character comparison!\n");
|
||||
|
||||
printf("Test 8b - CaseInsensitiveCompare UTF-8 (4):\n");
|
||||
if (CaseInsensitiveCompare(t8rhs, t8lhs, strlen(t8rhs), strlen(t8lhs)) != 1)
|
||||
printf("\tFailed!\n");
|
||||
|
||||
// This test may seem a bit strange. But it's actually an easy bug to make
|
||||
// if we tried to be clever and say that two ASCII characters x and y are
|
||||
// case-insensitively equal if (x & ~0x20) == (y & ~0x20).
|
||||
printf("Test 9 - CaseInsensitiveCompare UTF-8 (5):\n");
|
||||
if (CaseInsensitiveCompare(t9rhs, t9lhs, strlen(t9lhs), strlen(t9rhs)) != 1)
|
||||
printf("\tFailed!\n");
|
||||
if (CharByCharCompareEqual(t9lhs, t9rhs, strlen(t9lhs), strlen(t9rhs)))
|
||||
printf("\tFailed character-by-character comparison!\n");
|
||||
|
||||
printf("===========================\n");
|
||||
printf("Finish case conversion test\n");
|
||||
printf("===========================\n");
|
||||
}
|
||||
|
||||
static void FuzzOneInvalidCaseConversion()
|
||||
{
|
||||
PRUint32 aLen = rand() % 32;
|
||||
PRUint32 bLen = rand() % 32;
|
||||
|
||||
// We could use a static length-32 buffer for these, but then Valgrind
|
||||
// wouldn't be able to detect errors.
|
||||
unsigned char *aBuf = (unsigned char*)malloc(aLen * sizeof(unsigned char));
|
||||
unsigned char *bBuf = (unsigned char*)malloc(bLen * sizeof(unsigned char));
|
||||
|
||||
for (PRUint32 i = 0; i < aLen; i++) {
|
||||
aBuf[i] = rand() & 0xff;
|
||||
}
|
||||
|
||||
for (PRUint32 i = 0; i < bLen; i++) {
|
||||
bBuf[i] = rand() & 0xff;
|
||||
}
|
||||
|
||||
CaseInsensitiveCompare((char*)aBuf, (char*)bBuf, aLen, bLen);
|
||||
CharByCharCompareEqual((char*)aBuf, (char*)bBuf, aLen, bLen);
|
||||
|
||||
free(aBuf);
|
||||
free(bBuf);
|
||||
}
|
||||
|
||||
static void FuzzCaseConversion()
|
||||
{
|
||||
printf("==========================\n");
|
||||
printf("Start fuzz case conversion\n");
|
||||
printf("==========================\n");
|
||||
|
||||
srand(0);
|
||||
|
||||
printf("Fuzzing invalid UTF8 data...\n");
|
||||
for (PRUint32 i = 0; i < 100000; i++) {
|
||||
FuzzOneInvalidCaseConversion();
|
||||
}
|
||||
|
||||
printf("===========================\n");
|
||||
printf("Finish fuzz case conversion\n");
|
||||
printf("===========================\n");
|
||||
}
|
||||
|
||||
static void TestEntityConversion(PRUint32 version)
|
||||
{
|
||||
printf("==============================\n");
|
||||
|
@ -567,6 +738,10 @@ int main(int argc, char** argv) {
|
|||
|
||||
// --------------------------------------------
|
||||
|
||||
FuzzCaseConversion();
|
||||
|
||||
// --------------------------------------------
|
||||
|
||||
TestEntityConversion(nsIEntityConverter::html40);
|
||||
|
||||
// --------------------------------------------
|
||||
|
|
|
@ -1,32 +1,3 @@
|
|||
Instructions for using these tools are on the Mozilla Wiki.
|
||||
|
||||
* How to generate various properties files in intl/unicharutils/tables and
|
||||
header files in intl/unicharutils/src
|
||||
( written by Jungshik Shin for bug 210502
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=210502 on 2005-04-05 )
|
||||
|
||||
1. Grab the latest version of idnkit at http://www.nic.ad.jp/en/idn/index.html
|
||||
(http://www.nic.ad.jp/ja/idn/idnkit/download/index.html )
|
||||
|
||||
2. There are three files we need in the kit:
|
||||
generate_normalize_data.pl, UCD.pm and SparseMap.pm
|
||||
|
||||
3. a. Download the following Unicode data files :
|
||||
CaseFolding.txt,CompositionExclusions.txt,
|
||||
SpecialCasing.txt, UnicodeData.txt
|
||||
|
||||
b. Rename UnicodeData.txt to UnicodeData-Latest.txt
|
||||
|
||||
The latest version is, as of this writing, in
|
||||
ftp://ftp.unicode.org/Public/4.1.0/ucd
|
||||
|
||||
4. a. Run generate_normalize_data.pl and save the output to a temporary file
|
||||
b. Edit the file
|
||||
- remove the case folding part (search for 'Lowercase' and delete
|
||||
all the lines following it) because we have separate scripts for that,
|
||||
- replace 'unsigned short' and 'unsigned long' with 'PRUnichar' and
|
||||
'PRUint32'
|
||||
c. Replace the actual source part (after the license) of
|
||||
intl/unicharutil/src/normalization_data.h with the file you edited.
|
||||
|
||||
5. Generate casetable.h and cattable.h with gencasetable.pl and gencattable.pl
|
||||
Just running them will put casetable.h and cattable.h in the right place.
|
||||
https://wiki.mozilla.org/I18n:Updating_Unicode_version
|
||||
|
|
|
@ -383,6 +383,38 @@ for($idx=0;$idx<8;$idx++)
|
|||
printf OUT "\n";
|
||||
}
|
||||
}
|
||||
print OUT "};\n\n";
|
||||
|
||||
######################################################################
|
||||
#
|
||||
# Print out gASCIIToLower table
|
||||
#
|
||||
######################################################################
|
||||
print OUT "// We map x -> x, except for upper-case letters,\n";
|
||||
print OUT "// which we map to their lower-case equivalents.\n";
|
||||
print OUT "static const PRUint8 gASCIIToLower [128] = {\n";
|
||||
|
||||
# Map x -> x, except for upper-case letters, which we map to lower-case
|
||||
# letters.
|
||||
for($idx=0; $idx < 128; $idx++)
|
||||
{
|
||||
if ($idx % 16 == 0) {
|
||||
print OUT " "
|
||||
}
|
||||
|
||||
if (65 <= $idx && $idx <= 90) {
|
||||
printf OUT "0x%02x", ($idx + 0x20);
|
||||
} else {
|
||||
printf OUT "0x%02x", $idx;
|
||||
}
|
||||
|
||||
if (($idx+1) % 16 != 0) {
|
||||
print OUT ", ";
|
||||
}
|
||||
else {
|
||||
print OUT ",\n";
|
||||
}
|
||||
}
|
||||
print OUT "};\n";
|
||||
|
||||
|
||||
|
|
|
@ -46,10 +46,11 @@
|
|||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsXPCOMStrings.h"
|
||||
#include "casetable.h"
|
||||
#include "nsUTF8Utils.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
// For gUpperToTitle
|
||||
// For gUpperToTitle
|
||||
enum {
|
||||
kUpperIdx =0,
|
||||
kTitleIdx
|
||||
|
@ -62,18 +63,19 @@ enum {
|
|||
kDiffIdx
|
||||
};
|
||||
|
||||
#define IS_ASCII(u) ( 0x0000 == ((u) & 0xFF80))
|
||||
#define IS_ASCII_UPPER(u) ((0x0041 <= (u)) && ( (u) <= 0x005a))
|
||||
#define IS_ASCII_LOWER(u) ((0x0061 <= (u)) && ( (u) <= 0x007a))
|
||||
#define IS_ASCII(u) ((u) < 0x80)
|
||||
#define IS_ASCII_UPPER(u) (('A' <= (u)) && ( (u) <= 'Z' ))
|
||||
#define IS_ASCII_LOWER(u) (('a' <= (u)) && ( (u) <= 'z'))
|
||||
#define IS_ASCII_ALPHA(u) (IS_ASCII_UPPER(u) || IS_ASCII_LOWER(u))
|
||||
#define IS_ASCII_SPACE(u) ( 0x0020 == (u) )
|
||||
#define IS_ASCII_SPACE(u) ( ' ' == (u) )
|
||||
|
||||
#define IS_NOCASE_CHAR(u) (0==(1&(gCaseBlocks[(u)>>13]>>(0x001F&((u)>>8)))))
|
||||
|
||||
|
||||
// Size of Tables
|
||||
|
||||
#define CASE_MAP_CACHE_SIZE 0x40
|
||||
#define CASE_MAP_CACHE_MASK 0x3F
|
||||
// Changing these numbers may break UTF-8 caching. Be careful!
|
||||
#define CASE_MAP_CACHE_SIZE 0x100
|
||||
#define CASE_MAP_CACHE_MASK 0xFF
|
||||
|
||||
struct nsCompressedMap {
|
||||
const PRUnichar *mTable;
|
||||
|
@ -83,75 +85,94 @@ struct nsCompressedMap {
|
|||
|
||||
PRUnichar Map(PRUnichar aChar)
|
||||
{
|
||||
// no need to worry about thread safety since cached values are
|
||||
// not objects but primitive data types which could be
|
||||
// accessed in atomic operations. We need to access
|
||||
// the whole 32 bit of cachedData at once in order to make it
|
||||
// thread safe. Never access bits from mCache directly.
|
||||
// We don't need explicit locking here since the cached values are int32s,
|
||||
// which are read and written atomically. The following code is threadsafe
|
||||
// because we never access bits from mCache directly -- we always first
|
||||
// read the entire entry into a local variable and then mask off the bits
|
||||
// we're interested in.
|
||||
|
||||
// Check the 256-byte cache first and bail with our answer if we can.
|
||||
PRUint32 cachedData = mCache[aChar & CASE_MAP_CACHE_MASK];
|
||||
if(aChar == ((cachedData >> 16) & 0x0000FFFF))
|
||||
return (cachedData & 0x0000FFFF);
|
||||
if (aChar == ((cachedData >> 16) & 0x0000FFFF))
|
||||
return cachedData & 0x0000FFFF;
|
||||
|
||||
// try the last index first
|
||||
// store into local variable so we can be thread safe
|
||||
PRUint32 base = mLastBase;
|
||||
// Now try the last index we looked up, storing it into a local variable
|
||||
// for thread-safety.
|
||||
PRUint32 base = mLastBase;
|
||||
PRUnichar res = 0;
|
||||
|
||||
if (( aChar <= ((mTable[base+kSizeEveryIdx] >> 8) +
|
||||
mTable[base+kLowIdx])) &&
|
||||
( mTable[base+kLowIdx] <= aChar ))
|
||||
{
|
||||
// Hit the last base
|
||||
if(((mTable[base+kSizeEveryIdx] & 0x00FF) > 0) &&
|
||||
|
||||
// Does this character fit in the slot?
|
||||
if ((aChar <= ((mTable[base+kSizeEveryIdx] >> 8) +
|
||||
mTable[base+kLowIdx])) &&
|
||||
(mTable[base+kLowIdx] <= aChar)) {
|
||||
|
||||
// This character uses the same base as our last lookup, so the
|
||||
// conversion is easy.
|
||||
if (((mTable[base+kSizeEveryIdx] & 0x00FF) > 0) &&
|
||||
(0 != ((aChar - mTable[base+kLowIdx]) %
|
||||
(mTable[base+kSizeEveryIdx] & 0x00FF))))
|
||||
{
|
||||
res = aChar;
|
||||
} else {
|
||||
res = aChar + mTable[base+kDiffIdx];
|
||||
}
|
||||
(mTable[base+kSizeEveryIdx] & 0x00FF))))
|
||||
{
|
||||
res = aChar;
|
||||
} else {
|
||||
res = aChar + mTable[base+kDiffIdx];
|
||||
}
|
||||
|
||||
} else {
|
||||
res = this->Lookup(0, (mSize/2), mSize-1, aChar);
|
||||
// Do the full lookup.
|
||||
res = this->Lookup(0, mSize/2, mSize-1, aChar);
|
||||
}
|
||||
|
||||
// Cache the result and return.
|
||||
mCache[aChar & CASE_MAP_CACHE_MASK] =
|
||||
(((aChar << 16) & 0xFFFF0000) | (0x0000FFFF & res));
|
||||
((aChar << 16) & 0xFFFF0000) | (0x0000FFFF & res);
|
||||
return res;
|
||||
}
|
||||
|
||||
// Takes as arguments the left bound, middle, right bound, and character to
|
||||
// search for. Executes a binary search.
|
||||
PRUnichar Lookup(PRUint32 l,
|
||||
PRUint32 m,
|
||||
PRUint32 r,
|
||||
PRUnichar aChar)
|
||||
{
|
||||
PRUint32 base = m*3;
|
||||
if ( aChar > ((mTable[base+kSizeEveryIdx] >> 8) +
|
||||
PRUint32 base = m*3; // Every line in the table is 3 units wide.
|
||||
|
||||
// Is aChar past the top of the current table entry? (The upper byte of
|
||||
// the 'every' entry contains the offset to the end of this entry.)
|
||||
if (aChar > ((mTable[base+kSizeEveryIdx] >> 8) +
|
||||
mTable[base+kLowIdx]))
|
||||
{
|
||||
if( l > m )
|
||||
if (l > m || l == r)
|
||||
return aChar;
|
||||
// Advance one round.
|
||||
PRUint32 newm = (m+r+1)/2;
|
||||
if(newm == m)
|
||||
if (newm == m)
|
||||
newm++;
|
||||
return this->Lookup(m+1, newm , r, aChar);
|
||||
|
||||
} else if ( mTable[base+kLowIdx] > aChar ) {
|
||||
if( r < m )
|
||||
return this->Lookup(m+1, newm, r, aChar);
|
||||
|
||||
// Is aChar below the bottom of the current table entry?
|
||||
} else if (mTable[base+kLowIdx] > aChar) {
|
||||
if (r < m || l == r)
|
||||
return aChar;
|
||||
// Advance one round
|
||||
PRUint32 newm = (l+m-1)/2;
|
||||
if(newm == m)
|
||||
newm++;
|
||||
return this->Lookup(l, newm, m-1, aChar);
|
||||
|
||||
} else {
|
||||
if(((mTable[base+kSizeEveryIdx] & 0x00FF) > 0) &&
|
||||
(0 != ((aChar - mTable[base+kLowIdx]) %
|
||||
(mTable[base+kSizeEveryIdx] & 0x00FF))))
|
||||
// We've found the entry aChar should live in.
|
||||
} else {
|
||||
// Determine if aChar falls in a gap. (The lower byte of the 'every'
|
||||
// entry contains n for which every nth character from the base is a
|
||||
// character of interest.)
|
||||
if (((mTable[base+kSizeEveryIdx] & 0x00FF) > 0) &&
|
||||
(0 != ((aChar - mTable[base+kLowIdx]) %
|
||||
(mTable[base+kSizeEveryIdx] & 0x00FF))))
|
||||
{
|
||||
return aChar;
|
||||
}
|
||||
mLastBase = base; // cache the base
|
||||
// If aChar doesn't fall in the gap, cache and convert.
|
||||
mLastBase = base;
|
||||
return aChar + mTable[base+kDiffIdx];
|
||||
}
|
||||
}
|
||||
|
@ -167,6 +188,29 @@ static nsCompressedMap gLowerMap = {
|
|||
gToLowerItems
|
||||
};
|
||||
|
||||
// We want ToLowerCase(PRUnichar) and ToLowerCaseASCII(PRUnichar) to be fast
|
||||
// when they're called from within the case-insensitive comparators, so we
|
||||
// define inlined versions.
|
||||
static NS_ALWAYS_INLINE PRUnichar
|
||||
ToLowerCase_inline(PRUnichar aChar)
|
||||
{
|
||||
if (IS_ASCII(aChar)) {
|
||||
return gASCIIToLower[aChar];
|
||||
} else if (IS_NOCASE_CHAR(aChar)) {
|
||||
return aChar;
|
||||
}
|
||||
|
||||
return gLowerMap.Map(aChar);
|
||||
}
|
||||
|
||||
static NS_ALWAYS_INLINE PRUnichar
|
||||
ToLowerCaseASCII_inline(const PRUnichar aChar)
|
||||
{
|
||||
if (IS_ASCII(aChar))
|
||||
return gASCIIToLower[aChar];
|
||||
return aChar;
|
||||
}
|
||||
|
||||
void
|
||||
ToLowerCase(nsAString& aString)
|
||||
{
|
||||
|
@ -189,9 +233,7 @@ ToLowerCase(const nsAString& aSource,
|
|||
PRUnichar
|
||||
ToLowerCaseASCII(const PRUnichar aChar)
|
||||
{
|
||||
if (IS_ASCII_UPPER(aChar))
|
||||
return aChar + 0x0020;
|
||||
return aChar;
|
||||
return ToLowerCaseASCII_inline(aChar);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -218,115 +260,58 @@ ToUpperCase(const nsAString& aSource,
|
|||
PRInt32
|
||||
nsCaseInsensitiveStringComparator::operator()(const PRUnichar* lhs,
|
||||
const PRUnichar* rhs,
|
||||
PRUint32 aLength) const
|
||||
PRUint32 lLength,
|
||||
PRUint32 rLength) const
|
||||
{
|
||||
return CaseInsensitiveCompare(lhs, rhs, aLength);
|
||||
return (lLength == rLength) ? CaseInsensitiveCompare(lhs, rhs, lLength) :
|
||||
(lLength > rLength) ? 1 : -1;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
nsCaseInsensitiveStringComparator::operator()(PRUnichar lhs,
|
||||
PRUnichar rhs) const
|
||||
nsCaseInsensitiveUTF8StringComparator::operator()(const char* lhs,
|
||||
const char* rhs,
|
||||
PRUint32 lLength,
|
||||
PRUint32 rLength) const
|
||||
{
|
||||
// see if they're an exact match first
|
||||
if (lhs == rhs)
|
||||
return 0;
|
||||
|
||||
lhs = ToLowerCase(lhs);
|
||||
rhs = ToLowerCase(rhs);
|
||||
|
||||
if (lhs == rhs)
|
||||
return 0;
|
||||
else if (lhs < rhs)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
return CaseInsensitiveCompare(lhs, rhs, lLength, rLength);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
nsASCIICaseInsensitiveStringComparator::operator()(const PRUnichar* lhs,
|
||||
const PRUnichar* rhs,
|
||||
PRUint32 aLength) const
|
||||
PRUint32 lLength,
|
||||
PRUint32 rLength) const
|
||||
{
|
||||
while (aLength) {
|
||||
if (lLength != rLength) {
|
||||
if (lLength > rLength)
|
||||
return 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (rLength) {
|
||||
PRUnichar l = *lhs++;
|
||||
PRUnichar r = *rhs++;
|
||||
if (l != r) {
|
||||
l = ToLowerCaseASCII(l);
|
||||
r = ToLowerCaseASCII(r);
|
||||
l = ToLowerCaseASCII_inline(l);
|
||||
r = ToLowerCaseASCII_inline(r);
|
||||
|
||||
if (l > r)
|
||||
return 1;
|
||||
else if (r > l)
|
||||
return -1;
|
||||
}
|
||||
aLength--;
|
||||
rLength--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
nsASCIICaseInsensitiveStringComparator::operator()(PRUnichar lhs,
|
||||
PRUnichar rhs) const
|
||||
{
|
||||
// see if they're an exact match first
|
||||
if (lhs == rhs)
|
||||
return 0;
|
||||
|
||||
lhs = ToLowerCaseASCII(lhs);
|
||||
rhs = ToLowerCaseASCII(rhs);
|
||||
|
||||
if (lhs == rhs)
|
||||
return 0;
|
||||
else if (lhs < rhs)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#endif // MOZILLA_INTERNAL_API
|
||||
|
||||
PRInt32
|
||||
CaseInsensitiveCompare(const PRUnichar *a,
|
||||
const PRUnichar *b,
|
||||
PRUint32 len)
|
||||
{
|
||||
NS_ASSERTION(a && b, "Do not pass in invalid pointers!");
|
||||
|
||||
if (len) {
|
||||
do {
|
||||
PRUnichar c1 = *a++;
|
||||
PRUnichar c2 = *b++;
|
||||
|
||||
if (c1 != c2) {
|
||||
c1 = ToLowerCase(c1);
|
||||
c2 = ToLowerCase(c2);
|
||||
if (c1 != c2) {
|
||||
if (c1 < c2) {
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} while (--len != 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRUnichar
|
||||
ToLowerCase(PRUnichar aChar)
|
||||
{
|
||||
if (IS_ASCII(aChar)) {
|
||||
if (IS_ASCII_UPPER(aChar))
|
||||
return aChar + 0x0020;
|
||||
else
|
||||
return aChar;
|
||||
} else if (IS_NOCASE_CHAR(aChar)) {
|
||||
return aChar;
|
||||
}
|
||||
|
||||
return gLowerMap.Map(aChar);
|
||||
return ToLowerCase_inline(aChar);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -342,7 +327,7 @@ ToUpperCase(PRUnichar aChar)
|
|||
{
|
||||
if (IS_ASCII(aChar)) {
|
||||
if (IS_ASCII_LOWER(aChar))
|
||||
return aChar - 0x0020;
|
||||
return aChar - 0x20;
|
||||
else
|
||||
return aChar;
|
||||
} else if (IS_NOCASE_CHAR(aChar)) {
|
||||
|
@ -380,7 +365,7 @@ ToTitleCase(PRUnichar aChar)
|
|||
}
|
||||
|
||||
PRUnichar upper = gUpperMap.Map(aChar);
|
||||
|
||||
|
||||
if (0x01C0 == ( upper & 0xFFC0)) {
|
||||
for (PRUint32 i = 0 ; i < gUpperToTitleItems; i++) {
|
||||
if (upper == gUpperToTitle[(i*2)+kUpperIdx]) {
|
||||
|
@ -391,3 +376,167 @@ ToTitleCase(PRUnichar aChar)
|
|||
|
||||
return upper;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
CaseInsensitiveCompare(const PRUnichar *a,
|
||||
const PRUnichar *b,
|
||||
PRUint32 len)
|
||||
{
|
||||
NS_ASSERTION(a && b, "Do not pass in invalid pointers!");
|
||||
|
||||
if (len) {
|
||||
do {
|
||||
PRUnichar c1 = *a++;
|
||||
PRUnichar c2 = *b++;
|
||||
|
||||
if (c1 != c2) {
|
||||
c1 = ToLowerCase_inline(c1);
|
||||
c2 = ToLowerCase_inline(c2);
|
||||
if (c1 != c2) {
|
||||
if (c1 < c2) {
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} while (--len != 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Calculates the codepoint of the UTF8 sequence starting at aStr. Sets aNext
|
||||
// to the byte following the end of the sequence.
|
||||
//
|
||||
// If the sequence is invalid, or if computing the codepoint would take us off
|
||||
// the end of the string (as marked by aEnd), returns -1 and does not set
|
||||
// aNext. Note that this function doesn't check that aStr < aEnd -- it assumes
|
||||
// you've done that already.
|
||||
static NS_ALWAYS_INLINE PRUint32
|
||||
GetLowerUTF8Codepoint(const char* aStr, const char* aEnd, const char **aNext)
|
||||
{
|
||||
// Convert to unsigned char so that stuffing chars into PRUint32s doesn't
|
||||
// sign extend.
|
||||
const unsigned char *str = (unsigned char*)aStr;
|
||||
|
||||
if (UTF8traits::isASCII(str[0])) {
|
||||
// It's ASCII; just convert to lower-case and return it.
|
||||
*aNext = aStr + 1;
|
||||
return gASCIIToLower[*str];
|
||||
}
|
||||
if (UTF8traits::is2byte(str[0]) && NS_LIKELY(aStr + 1 < aEnd)) {
|
||||
// It's a two-byte sequence, so it looks like
|
||||
// 110XXXXX 10XXXXXX.
|
||||
// This is definitely in the BMP, so we can store straightaway into a
|
||||
// PRUint16.
|
||||
|
||||
PRUint16 c;
|
||||
c = (str[0] & 0x1F) << 6;
|
||||
c += (str[1] & 0x3F);
|
||||
|
||||
if (!IS_NOCASE_CHAR(c))
|
||||
c = gLowerMap.Map(c);
|
||||
|
||||
*aNext = aStr + 2;
|
||||
return c;
|
||||
}
|
||||
if (UTF8traits::is3byte(str[0]) && NS_LIKELY(aStr + 2 < aEnd)) {
|
||||
// It's a three-byte sequence, so it looks like
|
||||
// 1110XXXX 10XXXXXX 10XXXXXX.
|
||||
// This will just barely fit into 16-bits, so store into a PRUint16.
|
||||
|
||||
PRUint16 c;
|
||||
c = (str[0] & 0x0F) << 12;
|
||||
c += (str[1] & 0x3F) << 6;
|
||||
c += (str[2] & 0x3F);
|
||||
|
||||
if (!IS_NOCASE_CHAR(c))
|
||||
c = gLowerMap.Map(c);
|
||||
|
||||
*aNext = aStr + 3;
|
||||
return c;
|
||||
}
|
||||
if (UTF8traits::is4byte(str[0]) && NS_LIKELY(aStr + 3 < aEnd)) {
|
||||
// It's a four-byte sequence, so it looks like
|
||||
// 11110XXX 10XXXXXX 10XXXXXX 10XXXXXX.
|
||||
// Unless this is an overlong sequence, the codepoint it encodes definitely
|
||||
// isn't in the BMP, so we don't bother trying to convert it to lower-case.
|
||||
|
||||
PRUint32 c;
|
||||
c = (str[0] & 0x07) << 18;
|
||||
c += (str[1] & 0x3F) << 12;
|
||||
c += (str[2] & 0x3F) << 6;
|
||||
c += (str[3] & 0x3F);
|
||||
|
||||
*aNext = aStr + 4;
|
||||
return c;
|
||||
}
|
||||
|
||||
// Hm, we don't understand this sequence.
|
||||
return -1;
|
||||
}
|
||||
|
||||
PRInt32 CaseInsensitiveCompare(const char *aLeft,
|
||||
const char *aRight,
|
||||
PRUint32 aLeftBytes,
|
||||
PRUint32 aRightBytes)
|
||||
{
|
||||
const char *leftEnd = aLeft + aLeftBytes;
|
||||
const char *rightEnd = aRight + aRightBytes;
|
||||
|
||||
while (aLeft < leftEnd && aRight < rightEnd) {
|
||||
PRUint32 leftChar = GetLowerUTF8Codepoint(aLeft, leftEnd, &aLeft);
|
||||
if (NS_UNLIKELY(leftChar == PRUint32(-1)))
|
||||
return -1;
|
||||
|
||||
PRUint32 rightChar = GetLowerUTF8Codepoint(aRight, rightEnd, &aRight);
|
||||
if (NS_UNLIKELY(rightChar == PRUint32(-1)))
|
||||
return -1;
|
||||
|
||||
// Now leftChar and rightChar are lower-case, so we can compare them.
|
||||
if (leftChar != rightChar) {
|
||||
if (leftChar > rightChar)
|
||||
return 1;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure that if one string is longer than the other we return the
|
||||
// correct result.
|
||||
if (aLeft < leftEnd)
|
||||
return 1;
|
||||
if (aRight < rightEnd)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRBool
|
||||
CaseInsensitiveUTF8CharsEqual(const char* aLeft, const char* aRight,
|
||||
const char* aLeftEnd, const char* aRightEnd,
|
||||
const char** aLeftNext, const char** aRightNext,
|
||||
PRBool* aErr)
|
||||
{
|
||||
NS_ASSERTION(aLeftNext, "Out pointer shouldn't be null.");
|
||||
NS_ASSERTION(aRightNext, "Out pointer shouldn't be null.");
|
||||
NS_ASSERTION(aErr, "Out pointer shouldn't be null.");
|
||||
NS_ASSERTION(aLeft < aLeftEnd, "aLeft must be less than aLeftEnd.");
|
||||
NS_ASSERTION(aRight < aRightEnd, "aRight must be less than aRightEnd.");
|
||||
|
||||
PRUint32 leftChar = GetLowerUTF8Codepoint(aLeft, aLeftEnd, aLeftNext);
|
||||
if (NS_UNLIKELY(leftChar == PRUint32(-1))) {
|
||||
*aErr = PR_TRUE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRUint32 rightChar = GetLowerUTF8Codepoint(aRight, aRightEnd, aRightNext);
|
||||
if (NS_UNLIKELY(rightChar == PRUint32(-1))) {
|
||||
*aErr = PR_TRUE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// Can't have an error past this point.
|
||||
*aErr = PR_FALSE;
|
||||
|
||||
return leftChar == rightChar;
|
||||
}
|
||||
|
||||
|
|
|
@ -78,9 +78,17 @@ class nsCaseInsensitiveStringComparator : public nsStringComparator
|
|||
public:
|
||||
virtual PRInt32 operator() (const PRUnichar*,
|
||||
const PRUnichar*,
|
||||
PRUint32 aLength) const;
|
||||
virtual PRInt32 operator() (PRUnichar,
|
||||
PRUnichar) const;
|
||||
PRUint32,
|
||||
PRUint32) const;
|
||||
};
|
||||
|
||||
class nsCaseInsensitiveUTF8StringComparator : public nsCStringComparator
|
||||
{
|
||||
public:
|
||||
virtual PRInt32 operator() (const char*,
|
||||
const char*,
|
||||
PRUint32,
|
||||
PRUint32) const;
|
||||
};
|
||||
|
||||
class nsCaseInsensitiveStringArrayComparator
|
||||
|
@ -97,9 +105,8 @@ class nsASCIICaseInsensitiveStringComparator : public nsStringComparator
|
|||
public:
|
||||
virtual int operator() (const PRUnichar*,
|
||||
const PRUnichar*,
|
||||
PRUint32 aLength) const;
|
||||
virtual int operator() (PRUnichar,
|
||||
PRUnichar) const;
|
||||
PRUint32,
|
||||
PRUint32) const;
|
||||
};
|
||||
|
||||
inline PRBool
|
||||
|
@ -126,4 +133,33 @@ CaseInsensitiveFindInReadable(const nsAString& aPattern,
|
|||
PRInt32
|
||||
CaseInsensitiveCompare(const PRUnichar *a, const PRUnichar *b, PRUint32 len);
|
||||
|
||||
PRInt32
|
||||
CaseInsensitiveCompare(const char* aLeft, const char* aRight,
|
||||
PRUint32 aLeftBytes, PRUint32 aRightBytes);
|
||||
|
||||
/**
|
||||
* This function determines whether the UTF-8 sequence pointed to by aLeft is
|
||||
* case-insensitively-equal to the UTF-8 sequence pointed to by aRight.
|
||||
*
|
||||
* aLeftEnd marks the first memory location past aLeft that is not part of
|
||||
* aLeft; aRightEnd similarly marks the end of aRight.
|
||||
*
|
||||
* The function assumes that aLeft < aLeftEnd and aRight < aRightEnd.
|
||||
*
|
||||
* The function stores the addresses of the next characters in the sequence
|
||||
* into aLeftNext and aRightNext. It's up to the caller to make sure that the
|
||||
* returned pointers are valid -- i.e. the function may return aLeftNext >=
|
||||
* aLeftEnd or aRightNext >= aRightEnd.
|
||||
*
|
||||
* If the function encounters invalid text, it sets aErr to true and returns
|
||||
* false, possibly leaving aLeftNext and aRightNext uninitialized. If the
|
||||
* function returns true, aErr is guaranteed to be false and both aLeftNext and
|
||||
* aRightNext are guaranteed to be initialized.
|
||||
*/
|
||||
PRBool
|
||||
CaseInsensitiveUTF8CharsEqual(const char* aLeft, const char* aRight,
|
||||
const char* aLeftEnd, const char* aRightEnd,
|
||||
const char** aLeftNext, const char** aRightNext,
|
||||
PRBool* aErr);
|
||||
|
||||
#endif /* nsUnicharUtils_h__ */
|
||||
|
|
|
@ -595,8 +595,9 @@ bool Channel::ChannelImpl::ProcessOutgoingMessages() {
|
|||
struct iovec iov = {const_cast<char*>(out_bytes), amt_to_write};
|
||||
msgh.msg_iov = &iov;
|
||||
msgh.msg_iovlen = 1;
|
||||
char buf[CMSG_SPACE(
|
||||
sizeof(int[FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE]))];
|
||||
static const int tmp = CMSG_SPACE(sizeof(
|
||||
int[FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE]));
|
||||
char buf[tmp];
|
||||
|
||||
if (message_send_bytes_written_ == 0 &&
|
||||
!msg->file_descriptor_set()->empty()) {
|
||||
|
|
|
@ -916,6 +916,8 @@ JS_StringToVersion(const char *string);
|
|||
|
||||
#define JSOPTION_METHODJIT JS_BIT(14) /* Whole-method JIT. */
|
||||
#define JSOPTION_PROFILING JS_BIT(15) /* Profiler to make tracer/methodjit choices. */
|
||||
#define JSOPTION_ROPES JS_BIT(16) /* Enable rope optimization for
|
||||
* string concat. */
|
||||
|
||||
extern JS_PUBLIC_API(uint32)
|
||||
JS_GetOptions(JSContext *cx);
|
||||
|
|
|
@ -108,8 +108,6 @@ JSString::flatten()
|
|||
jschar *chars;
|
||||
size_t capacity;
|
||||
JS_ASSERT(isRope());
|
||||
if (!isRope())
|
||||
JS_CRASH(0xe0 | (mLengthAndFlags & TYPE_FLAGS_MASK));
|
||||
|
||||
/*
|
||||
* This can be called from any string in the rope, so first traverse to the
|
||||
|
@ -131,7 +129,7 @@ JSString::flatten()
|
|||
* interior node with a NULL parent, so that we end up at NULL when we are
|
||||
* done processing it.
|
||||
*/
|
||||
topNode->convertToInteriorNode((JSString *) 0x2);
|
||||
topNode->convertToInteriorNode(NULL);
|
||||
JSString *str = topNode, *next;
|
||||
size_t pos = 0;
|
||||
|
||||
|
@ -139,7 +137,7 @@ JSString::flatten()
|
|||
* Traverse the tree, making each interior string dependent on the resulting
|
||||
* string.
|
||||
*/
|
||||
while (str != (JSString *) 0x2) {
|
||||
while (str) {
|
||||
switch (str->ropeTraversalCount()) {
|
||||
case 0:
|
||||
next = str->ropeLeft();
|
||||
|
@ -270,6 +268,8 @@ FinishConcat(JSContext *cx, bool usingLeft, bool usingRight,
|
|||
left->convertToInteriorNode(res);
|
||||
if (usingRight)
|
||||
right->convertToInteriorNode(res);
|
||||
if (!JS_HAS_OPTION(cx, JSOPTION_ROPES))
|
||||
res->flatten();
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -300,9 +300,6 @@ js_ConcatStrings(JSContext *cx, JSString *left, JSString *right)
|
|||
return shortStr->header();
|
||||
}
|
||||
|
||||
left->checkCompartment(cx, 0xd0);
|
||||
right->checkCompartment(cx, 0xd4);
|
||||
|
||||
/*
|
||||
* We need to enforce a tree structure in ropes: every node needs to have a
|
||||
* unique parent. So, we can't have the left or right child be in the middle
|
||||
|
|
|
@ -57,8 +57,6 @@
|
|||
#include "jsvalue.h"
|
||||
#include "jscell.h"
|
||||
|
||||
#define JS_CRASH(addr) *(int *) (addr) = 0;
|
||||
|
||||
#define JSSTRING_BIT(n) ((size_t)1 << (n))
|
||||
#define JSSTRING_BITMASK(n) (JSSTRING_BIT(n) - 1)
|
||||
|
||||
|
@ -206,13 +204,6 @@ struct JSString {
|
|||
return reinterpret_cast<js::gc::FreeCell *>(this);
|
||||
}
|
||||
|
||||
inline void checkInteriorParent(int addr) {
|
||||
if (isInteriorNode() && e.mParent == NULL)
|
||||
JS_CRASH(addr);
|
||||
}
|
||||
|
||||
inline void checkCompartment(JSContext *cx, int addr);
|
||||
|
||||
/*
|
||||
* Generous but sane length bound; the "-1" is there for comptibility with
|
||||
* OOM tests.
|
||||
|
@ -287,7 +278,6 @@ struct JSString {
|
|||
e.mCapacity = 0;
|
||||
mLengthAndFlags = (length << FLAGS_LENGTH_SHIFT) | FLAT;
|
||||
mChars = chars;
|
||||
checkInteriorParent(0x90);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE void initFlatMutable(jschar *chars, size_t length, size_t cap) {
|
||||
|
@ -297,7 +287,6 @@ struct JSString {
|
|||
e.mCapacity = cap;
|
||||
mLengthAndFlags = (length << FLAGS_LENGTH_SHIFT) | FLAT | MUTABLE;
|
||||
mChars = chars;
|
||||
checkInteriorParent(0x94);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE jschar *flatChars() const {
|
||||
|
@ -346,14 +335,12 @@ struct JSString {
|
|||
JS_ASSERT(isFlat());
|
||||
JS_ASSERT(!isStatic(this));
|
||||
JS_ATOMIC_SET_MASK((jsword *)&mLengthAndFlags, ATOMIZED);
|
||||
checkInteriorParent(0x98);
|
||||
}
|
||||
|
||||
inline void flatSetMutable() {
|
||||
JS_ASSERT(isFlat());
|
||||
JS_ASSERT(!isAtomized());
|
||||
mLengthAndFlags |= MUTABLE;
|
||||
checkInteriorParent(0x9c);
|
||||
}
|
||||
|
||||
inline void flatClearMutable() {
|
||||
|
@ -365,7 +352,6 @@ struct JSString {
|
|||
*/
|
||||
if (mLengthAndFlags & MUTABLE)
|
||||
mLengthAndFlags &= ~MUTABLE;
|
||||
checkInteriorParent(0xa0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -379,7 +365,6 @@ struct JSString {
|
|||
mChars = chars;
|
||||
mLengthAndFlags = DEPENDENT | (len << FLAGS_LENGTH_SHIFT);
|
||||
e.mBase = bstr;
|
||||
checkInteriorParent(0xa4);
|
||||
}
|
||||
|
||||
inline JSString *dependentBase() const {
|
||||
|
@ -405,16 +390,12 @@ struct JSString {
|
|||
mLeft = left;
|
||||
e.mRight = right;
|
||||
e.mBufferWithInfo = buf;
|
||||
checkInteriorParent(0xa8);
|
||||
}
|
||||
|
||||
inline void convertToInteriorNode(JSString *parent) {
|
||||
JS_ASSERT(isTopNode());
|
||||
if (parent == NULL)
|
||||
JS_CRASH(0x80);
|
||||
e.mParent = parent;
|
||||
mLengthAndFlags = INTERIOR_NODE | (length() << FLAGS_LENGTH_SHIFT);
|
||||
checkInteriorParent(0xac);
|
||||
}
|
||||
|
||||
inline JSString *interiorNodeParent() const {
|
||||
|
@ -444,10 +425,7 @@ struct JSString {
|
|||
|
||||
inline void nullifyTopNodeBuffer() {
|
||||
JS_ASSERT(isTopNode());
|
||||
if (!isTopNode())
|
||||
JS_CRASH(0x84);
|
||||
e.mBufferWithInfo = NULL;
|
||||
checkInteriorParent(0xb0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -466,13 +444,11 @@ struct JSString {
|
|||
mLengthAndFlags = JSString::DEPENDENT |
|
||||
((chars + end - mChars) << JSString::FLAGS_LENGTH_SHIFT);
|
||||
e.mBase = base;
|
||||
checkInteriorParent(0xb4);
|
||||
}
|
||||
|
||||
inline void ropeClearTraversalCount() {
|
||||
JS_ASSERT(isRope());
|
||||
mLengthAndFlags &= ~ROPE_TRAVERSAL_COUNT_MASK;
|
||||
checkInteriorParent(0xb8);
|
||||
}
|
||||
|
||||
inline size_t ropeTraversalCount() const {
|
||||
|
@ -484,7 +460,6 @@ struct JSString {
|
|||
inline void ropeIncrementTraversalCount() {
|
||||
JS_ASSERT(isRope());
|
||||
mLengthAndFlags += ROPE_TRAVERSAL_COUNT_UNIT;
|
||||
checkInteriorParent(0xbc);
|
||||
}
|
||||
|
||||
inline bool ensureNotDependent(JSContext *cx) {
|
||||
|
|
|
@ -123,11 +123,4 @@ inline
|
|||
JSRopeBuilder::JSRopeBuilder(JSContext *cx)
|
||||
: cx(cx), mStr(cx->runtime->emptyString) {}
|
||||
|
||||
inline void
|
||||
JSString::checkCompartment(JSContext *cx, int addr)
|
||||
{
|
||||
if (isRope() && asCell()->compartment() != cx->compartment)
|
||||
JS_CRASH(addr);
|
||||
}
|
||||
|
||||
#endif /* jsstrinlines_h___ */
|
||||
|
|
|
@ -5436,7 +5436,7 @@ main(int argc, char **argv, char **envp)
|
|||
if (!cx)
|
||||
return 1;
|
||||
|
||||
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_ANONFUNFIX);
|
||||
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_ANONFUNFIX | JSOPTION_ROPES);
|
||||
JS_SetGCParameterForThread(cx, JSGC_MAX_CODE_CACHE_BYTES, 16 * 1024 * 1024);
|
||||
|
||||
result = Shell(cx, argc, argv, envp);
|
||||
|
|
|
@ -740,13 +740,13 @@ public:
|
|||
// we have not yet created the relevant frame.
|
||||
PRPackedBool mHavePendingPopupgroup;
|
||||
|
||||
// If true (which is the default) then call SetPrimaryFrame() as needed
|
||||
// during frame construction. If false, don't make any SetPrimaryFrame()
|
||||
// calls. The mSetPrimaryFrames == PR_FALSE mode is meant to be used for
|
||||
// If false (which is the default) then call SetPrimaryFrame() as needed
|
||||
// during frame construction. If true, don't make any SetPrimaryFrame()
|
||||
// calls. The mCreatingExtraFrames == PR_TRUE mode is meant to be used for
|
||||
// construction of random "extra" frames for elements via normal frame
|
||||
// construction APIs (e.g. replication of things across pages in paginated
|
||||
// mode).
|
||||
PRPackedBool mSetPrimaryFrames;
|
||||
PRPackedBool mCreatingExtraFrames;
|
||||
|
||||
nsCOMArray<nsIContent> mGeneratedTextNodesWithInitializer;
|
||||
|
||||
|
@ -911,7 +911,7 @@ nsFrameConstructorState::nsFrameConstructorState(nsIPresShell* aPresShe
|
|||
aAbsoluteContainingBlock->GetStyleDisplay()->
|
||||
HasTransform()),
|
||||
mHavePendingPopupgroup(PR_FALSE),
|
||||
mSetPrimaryFrames(PR_TRUE),
|
||||
mCreatingExtraFrames(PR_FALSE),
|
||||
mCurrentPendingBindingInsertionPoint(&mPendingBindings)
|
||||
{
|
||||
#ifdef MOZ_XUL
|
||||
|
@ -943,7 +943,7 @@ nsFrameConstructorState::nsFrameConstructorState(nsIPresShell* aPresShell,
|
|||
aAbsoluteContainingBlock->GetStyleDisplay()->
|
||||
HasTransform()),
|
||||
mHavePendingPopupgroup(PR_FALSE),
|
||||
mSetPrimaryFrames(PR_TRUE),
|
||||
mCreatingExtraFrames(PR_FALSE),
|
||||
mCurrentPendingBindingInsertionPoint(&mPendingBindings)
|
||||
{
|
||||
#ifdef MOZ_XUL
|
||||
|
@ -2162,7 +2162,7 @@ NeedFrameFor(const nsFrameConstructorState& aState,
|
|||
// XXX the GetContent() != aChildContent check is needed due to bug 135040.
|
||||
// Remove it once that's fixed.
|
||||
NS_PRECONDITION(!aChildContent->GetPrimaryFrame() ||
|
||||
!aState.mSetPrimaryFrames ||
|
||||
aState.mCreatingExtraFrames ||
|
||||
aChildContent->GetPrimaryFrame()->GetContent() != aChildContent,
|
||||
"Why did we get called?");
|
||||
|
||||
|
@ -3435,7 +3435,7 @@ nsCSSFrameConstructor::ConstructTextFrame(const FrameConstructionData* aData,
|
|||
// Add the newly constructed frame to the flow
|
||||
aFrameItems.AddChild(newFrame);
|
||||
|
||||
if (aState.mSetPrimaryFrames)
|
||||
if (!aState.mCreatingExtraFrames)
|
||||
aContent->SetPrimaryFrame(newFrame);
|
||||
|
||||
return rv;
|
||||
|
@ -3710,6 +3710,13 @@ nsCSSFrameConstructor::ConstructFrameFromItemInternal(FrameConstructionItem& aIt
|
|||
CHECK_ONLY_ONE_BIT(FCDATA_MAY_NEED_SCROLLFRAME, FCDATA_FORCE_VIEW);
|
||||
#undef CHECK_ONLY_ONE_BIT
|
||||
|
||||
// Don't create a subdocument frame for iframes if we're creating extra frames
|
||||
if (aState.mCreatingExtraFrames && aItem.mContent->IsHTML() &&
|
||||
aItem.mContent->Tag() == nsGkAtoms::iframe)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsStyleContext* const styleContext = aItem.mStyleContext;
|
||||
const nsStyleDisplay* display = styleContext->GetStyleDisplay();
|
||||
|
||||
|
@ -3865,7 +3872,7 @@ nsCSSFrameConstructor::ConstructFrameFromItemInternal(FrameConstructionItem& aIt
|
|||
((bits & FCDATA_IS_LINE_PARTICIPANT) != 0),
|
||||
"Incorrectly set FCDATA_IS_LINE_PARTICIPANT bits");
|
||||
|
||||
if (aState.mSetPrimaryFrames && !(bits & FCDATA_SKIP_FRAMESET)) {
|
||||
if (!aState.mCreatingExtraFrames && !(bits & FCDATA_SKIP_FRAMESET)) {
|
||||
aItem.mContent->SetPrimaryFrame(primaryFrame);
|
||||
}
|
||||
|
||||
|
@ -8407,7 +8414,7 @@ nsCSSFrameConstructor::CreateContinuingTableFrame(nsIPresShell* aPresShell,
|
|||
nsFrameConstructorState state(mPresShell, mFixedContainingBlock,
|
||||
GetAbsoluteContainingBlock(newFrame),
|
||||
nsnull);
|
||||
state.mSetPrimaryFrames = PR_FALSE;
|
||||
state.mCreatingExtraFrames = PR_TRUE;
|
||||
|
||||
headerFooterFrame = static_cast<nsTableRowGroupFrame*>
|
||||
(NS_NewTableRowGroupFrame(aPresShell, rowGroupFrame->GetStyleContext()));
|
||||
|
@ -8734,7 +8741,7 @@ nsCSSFrameConstructor::ReplicateFixedFrames(nsPageContentFrame* aParentFrame)
|
|||
nsFrameConstructorState state(mPresShell, aParentFrame,
|
||||
nsnull,
|
||||
mRootElementFrame);
|
||||
state.mSetPrimaryFrames = PR_FALSE;
|
||||
state.mCreatingExtraFrames = PR_TRUE;
|
||||
|
||||
// Iterate across fixed frames and replicate each whose placeholder is a
|
||||
// descendant of aFrame. (We don't want to explicitly copy placeholders that
|
||||
|
@ -11720,7 +11727,7 @@ PRBool
|
|||
nsCSSFrameConstructor::
|
||||
FrameConstructionItem::IsWhitespace(nsFrameConstructorState& aState) const
|
||||
{
|
||||
NS_PRECONDITION(!aState.mSetPrimaryFrames ||
|
||||
NS_PRECONDITION(aState.mCreatingExtraFrames ||
|
||||
!mContent->GetPrimaryFrame(), "How did that happen?");
|
||||
if (!mIsText) {
|
||||
return PR_FALSE;
|
||||
|
|
|
@ -2495,8 +2495,7 @@ PaintBackgroundLayer(nsPresContext* aPresContext,
|
|||
}
|
||||
}
|
||||
|
||||
if (aRenderingContext.ThebesContext()->GetFlags() &
|
||||
gfxContext::FLAG_DESTINED_FOR_SCREEN) {
|
||||
if (aFlags & nsCSSRendering::PAINTBG_TO_WINDOW) {
|
||||
// Clip background-attachment:fixed backgrounds to the viewport, if we're
|
||||
// painting to the screen. This avoids triggering tiling in common cases,
|
||||
// without affecting output since drawing is always clipped to the viewport
|
||||
|
|
|
@ -224,8 +224,14 @@ struct nsCSSRendering {
|
|||
*/
|
||||
PAINTBG_WILL_PAINT_BORDER = 0x01,
|
||||
/**
|
||||
* When this flag is passed, images are synchronously decoded. */
|
||||
PAINTBG_SYNC_DECODE_IMAGES = 0x02
|
||||
* When this flag is passed, images are synchronously decoded.
|
||||
*/
|
||||
PAINTBG_SYNC_DECODE_IMAGES = 0x02,
|
||||
/**
|
||||
* When this flag is passed, painting will go to the screen so we can
|
||||
* take advantage of the fact that it will be clipped to the viewport.
|
||||
*/
|
||||
PAINTBG_TO_WINDOW = 0x04
|
||||
};
|
||||
static void PaintBackground(nsPresContext* aPresContext,
|
||||
nsIRenderingContext& aRenderingContext,
|
||||
|
|
|
@ -161,6 +161,9 @@ nsDisplayListBuilder::GetBackgroundPaintFlags() {
|
|||
if (mSyncDecodeImages) {
|
||||
flags |= nsCSSRendering::PAINTBG_SYNC_DECODE_IMAGES;
|
||||
}
|
||||
if (mIsPaintingToWindow) {
|
||||
flags |= nsCSSRendering::PAINTBG_TO_WINDOW;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
|
|
|
@ -734,7 +734,8 @@ public:
|
|||
|
||||
NS_IMETHOD SetDisplaySelection(PRInt16 aToggle);
|
||||
NS_IMETHOD GetDisplaySelection(PRInt16 *aToggle);
|
||||
NS_IMETHOD ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion, PRBool aIsSynchronous);
|
||||
NS_IMETHOD ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion,
|
||||
PRInt16 aFlags);
|
||||
NS_IMETHOD RepaintSelection(SelectionType aType);
|
||||
|
||||
virtual NS_HIDDEN_(void) BeginObservingDocument();
|
||||
|
@ -2574,12 +2575,13 @@ PresShell::GetCurrentSelection(SelectionType aType)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresShell::ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion, PRBool aIsSynchronous)
|
||||
PresShell::ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion,
|
||||
PRInt16 aFlags)
|
||||
{
|
||||
if (!mSelection)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
return mSelection->ScrollSelectionIntoView(aType, aRegion, aIsSynchronous);
|
||||
return mSelection->ScrollSelectionIntoView(aType, aRegion, aFlags);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -3129,7 +3131,9 @@ PresShell::PageMove(PRBool aForward, PRBool aExtend)
|
|||
mSelection->CommonPageMove(aForward, aExtend, scrollableFrame);
|
||||
// After ScrollSelectionIntoView(), the pending notifications might be
|
||||
// flushed and PresShell/PresContext/Frames may be dead. See bug 418470.
|
||||
return ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_FOCUS_REGION, PR_TRUE);
|
||||
return ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL,
|
||||
nsISelectionController::SELECTION_FOCUS_REGION,
|
||||
nsISelectionController::SCROLL_SYNCHRONOUS);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3235,7 +3239,7 @@ PresShell::CompleteMove(PRBool aForward, PRBool aExtend)
|
|||
// flushed and PresShell/PresContext/Frames may be dead. See bug 418470.
|
||||
return ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL,
|
||||
nsISelectionController::SELECTION_FOCUS_REGION,
|
||||
PR_TRUE);
|
||||
nsISelectionController::SCROLL_SYNCHRONOUS);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -4300,7 +4304,7 @@ PresShell::ScrollFrameRectIntoView(nsIFrame* aFrame,
|
|||
}
|
||||
|
||||
// only scroll one container when this flag is set
|
||||
if (aFlags & SCROLL_FIRST_ANCESTOR_ONLY) {
|
||||
if (aFlags & nsIPresShell::SCROLL_FIRST_ANCESTOR_ONLY) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -7177,7 +7181,8 @@ PresShell::PrepareToUseCaretPosition(nsIWidget* aEventWidget, nsIntPoint& aTarge
|
|||
selCon = static_cast<nsISelectionController *>(this);
|
||||
if (selCon) {
|
||||
rv = selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL,
|
||||
nsISelectionController::SELECTION_FOCUS_REGION, PR_TRUE);
|
||||
nsISelectionController::SELECTION_FOCUS_REGION,
|
||||
nsISelectionController::SCROLL_SYNCHRONOUS);
|
||||
NS_ENSURE_SUCCESS(rv, PR_FALSE);
|
||||
}
|
||||
|
||||
|
|
|
@ -218,6 +218,17 @@ function runTest4() {
|
|||
function runTest4end() {
|
||||
printpreview();
|
||||
exitprintpreview();
|
||||
|
||||
runTest5();
|
||||
}
|
||||
|
||||
// This is a crash test for bug 595337
|
||||
function runTest5() {
|
||||
window.frames[0].document.body.innerHTML =
|
||||
'<iframe style="position: fixed; visibility: hidden; bottom: 10em;"></iframe>' +
|
||||
'<input contenteditable="true" style="display: table; page-break-before: left; width: 10000px;">';
|
||||
printpreview();
|
||||
exitprintpreview();
|
||||
SimpleTest.finish();
|
||||
window.close();
|
||||
}
|
||||
|
|
|
@ -655,7 +655,7 @@ nsTextControlFrame::ScrollOnFocusEvent::Run()
|
|||
mFrame->mScrollEvent.Forget();
|
||||
selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL,
|
||||
nsISelectionController::SELECTION_FOCUS_REGION,
|
||||
PR_TRUE);
|
||||
nsISelectionController::SCROLL_SYNCHRONOUS);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
|
@ -856,7 +856,7 @@ nsTextControlFrame::SetSelectionInternal(nsIDOMNode *aStartNode,
|
|||
// Scroll the selection into view (see bug 231389)
|
||||
return selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL,
|
||||
nsISelectionController::SELECTION_FOCUS_REGION,
|
||||
PR_FALSE);
|
||||
nsISelectionController::SCROLL_FIRST_ANCESTOR_ONLY);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -1370,11 +1370,11 @@ nsTextControlFrame::SetInitialChildList(nsIAtom* aListName,
|
|||
// than descending from the root frame of the frame hierarchy.
|
||||
if (first) {
|
||||
first->AddStateBits(NS_FRAME_REFLOW_ROOT);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
|
||||
NS_ASSERTION(txtCtrl, "Content not a text control element");
|
||||
txtCtrl->InitializeKeyboardEventListeners();
|
||||
nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
|
||||
NS_ASSERTION(txtCtrl, "Content not a text control element");
|
||||
txtCtrl->InitializeKeyboardEventListeners();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -388,13 +388,17 @@ public:
|
|||
*
|
||||
* @param aType the selection to scroll into view.
|
||||
* @param aRegion the region inside the selection to scroll into view.
|
||||
* @param aIsSynchronous when PR_TRUE, scrolls the selection into view
|
||||
* at some point after the method returns.request which is processed
|
||||
* @param aFlags the scroll flags. Valid bits include:
|
||||
* SCROLL_SYNCHRONOUS: when set, scrolls the selection into view
|
||||
* before returning. If not set, posts a request which is processed
|
||||
* at some point after the method returns.
|
||||
* SCROLL_FIRST_ANCESTOR_ONLY: if set, only the first ancestor will be scrolled
|
||||
* into view.
|
||||
*/
|
||||
/*unsafe*/
|
||||
nsresult ScrollSelectionIntoView(SelectionType aType,
|
||||
SelectionRegion aRegion,
|
||||
PRBool aIsSynchronous) const;
|
||||
PRInt16 aFlags) const;
|
||||
|
||||
/** RepaintSelection repaints the selected frames that are inside the selection
|
||||
* specified by aSelectionType.
|
||||
|
|
|
@ -1255,7 +1255,7 @@ nsDisplayPlugin::Paint(nsDisplayListBuilder* aBuilder,
|
|||
nsIRenderingContext* aCtx)
|
||||
{
|
||||
nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame);
|
||||
f->PaintPlugin(*aCtx, mVisibleRect, GetBounds(aBuilder));
|
||||
f->PaintPlugin(aBuilder, *aCtx, mVisibleRect, GetBounds(aBuilder));
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
@ -1779,7 +1779,8 @@ nsObjectFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
|
|||
}
|
||||
|
||||
void
|
||||
nsObjectFrame::PaintPlugin(nsIRenderingContext& aRenderingContext,
|
||||
nsObjectFrame::PaintPlugin(nsDisplayListBuilder* aBuilder,
|
||||
nsIRenderingContext& aRenderingContext,
|
||||
const nsRect& aDirtyRect, const nsRect& aPluginRect)
|
||||
{
|
||||
// Screen painting code
|
||||
|
@ -2014,7 +2015,7 @@ nsObjectFrame::PaintPlugin(nsIRenderingContext& aRenderingContext,
|
|||
nativeDraw.EndNativeDrawing();
|
||||
} while (nativeDraw.ShouldRenderAgain());
|
||||
nativeDraw.PaintToContext();
|
||||
} else if (!(ctx->GetFlags() & gfxContext::FLAG_DESTINED_FOR_SCREEN)) {
|
||||
} else if (!aBuilder->IsPaintingToWindow()) {
|
||||
// Get PrintWindow dynamically since it's not present on Win2K,
|
||||
// which we still support
|
||||
typedef BOOL (WINAPI * PrintWindowPtr)
|
||||
|
@ -2306,6 +2307,10 @@ nsObjectFrame::Instantiate(const char* aMimeType, nsIURI* aURI)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// XXXbz can aMimeType ever actually be null here? If not, either
|
||||
// the callers are wrong (and passing "" instead of null) or we can
|
||||
// remove the codepaths dealing with null aMimeType in
|
||||
// InstantiateEmbeddedPlugin.
|
||||
NS_ASSERTION(aMimeType || aURI, "Need a type or a URI!");
|
||||
|
||||
// Note: If PrepareInstanceOwner() returns an error, |this| may very
|
||||
|
|
|
@ -239,7 +239,8 @@ protected:
|
|||
const nsRect& aDirtyRect, nsPoint aPt);
|
||||
void PrintPlugin(nsIRenderingContext& aRenderingContext,
|
||||
const nsRect& aDirtyRect);
|
||||
void PaintPlugin(nsIRenderingContext& aRenderingContext,
|
||||
void PaintPlugin(nsDisplayListBuilder* aBuilder,
|
||||
nsIRenderingContext& aRenderingContext,
|
||||
const nsRect& aDirtyRect, const nsRect& aPluginRect);
|
||||
|
||||
/**
|
||||
|
|
|
@ -200,13 +200,18 @@ public:
|
|||
// to. The 'position' is a zero-width rectangle.
|
||||
nsIFrame* GetSelectionAnchorGeometry(SelectionRegion aRegion, nsRect *aRect);
|
||||
|
||||
nsresult PostScrollSelectionIntoViewEvent(SelectionRegion aRegion);
|
||||
nsresult PostScrollSelectionIntoViewEvent(SelectionRegion aRegion, PRBool aFirstAncestorOnly);
|
||||
enum {
|
||||
SCROLL_SYNCHRONOUS = 1<<1,
|
||||
SCROLL_FIRST_ANCESTOR_ONLY = 1<<2,
|
||||
SCROLL_DO_FLUSH = 1<<3
|
||||
};
|
||||
// aDoFlush only matters if aIsSynchronous is true. If not, we'll just flush
|
||||
// when the scroll event fires so we make sure to scroll to the right place.
|
||||
nsresult ScrollIntoView(SelectionRegion aRegion, PRBool aIsSynchronous,
|
||||
PRBool aDoFlush,
|
||||
nsresult ScrollIntoView(SelectionRegion aRegion,
|
||||
PRInt16 aVPercent = NS_PRESSHELL_SCROLL_ANYWHERE,
|
||||
PRInt16 aHPercent = NS_PRESSHELL_SCROLL_ANYWHERE);
|
||||
PRInt16 aHPercent = NS_PRESSHELL_SCROLL_ANYWHERE,
|
||||
PRInt32 aFlags = 0);
|
||||
nsresult SubtractRange(RangeData* aRange, nsIRange* aSubtract,
|
||||
nsTArray<RangeData>* aOutput);
|
||||
nsresult AddItem(nsIRange *aRange, PRInt32* aOutIndex = nsnull);
|
||||
|
@ -278,15 +283,18 @@ private:
|
|||
public:
|
||||
NS_DECL_NSIRUNNABLE
|
||||
ScrollSelectionIntoViewEvent(nsTypedSelection *aTypedSelection,
|
||||
SelectionRegion aRegion)
|
||||
SelectionRegion aRegion,
|
||||
PRBool aFirstAncestorOnly)
|
||||
: mTypedSelection(aTypedSelection),
|
||||
mRegion(aRegion) {
|
||||
mRegion(aRegion),
|
||||
mFirstAncestorOnly(aFirstAncestorOnly) {
|
||||
NS_ASSERTION(aTypedSelection, "null parameter");
|
||||
}
|
||||
void Revoke() { mTypedSelection = nsnull; }
|
||||
private:
|
||||
nsTypedSelection *mTypedSelection;
|
||||
SelectionRegion mRegion;
|
||||
PRBool mFirstAncestorOnly;
|
||||
};
|
||||
|
||||
void setAnchorFocusRange(PRInt32 aIndex); // pass in index into mRanges;
|
||||
|
@ -459,15 +467,17 @@ public:
|
|||
{
|
||||
nsWeakFrame frame =
|
||||
mContent ? mPresContext->GetPrimaryFrameFor(mContent) : nsnull;
|
||||
if (!frame)
|
||||
return NS_OK;
|
||||
mContent = nsnull;
|
||||
|
||||
mFrameSelection->HandleDrag(frame, mPoint);
|
||||
nsPoint pt = mPoint -
|
||||
frame->GetOffsetTo(mPresContext->PresShell()->FrameManager()->GetRootFrame());
|
||||
mFrameSelection->HandleDrag(frame, pt);
|
||||
if (!frame.IsAlive())
|
||||
return NS_OK;
|
||||
|
||||
NS_ASSERTION(frame->PresContext() == mPresContext, "document mismatch?");
|
||||
nsPoint pt = mPoint -
|
||||
frame->GetOffsetTo(mPresContext->PresShell()->FrameManager()->GetRootFrame());
|
||||
mSelection->DoAutoScroll(frame, pt);
|
||||
}
|
||||
return NS_OK;
|
||||
|
@ -1959,7 +1969,7 @@ nsFrameSelection::GetSelection(SelectionType aType) const
|
|||
nsresult
|
||||
nsFrameSelection::ScrollSelectionIntoView(SelectionType aType,
|
||||
SelectionRegion aRegion,
|
||||
PRBool aIsSynchronous) const
|
||||
PRInt16 aFlags) const
|
||||
{
|
||||
PRInt8 index = GetIndexFromSelectionType(aType);
|
||||
if (index < 0)
|
||||
|
@ -1968,10 +1978,19 @@ nsFrameSelection::ScrollSelectionIntoView(SelectionType aType,
|
|||
if (!mDomSelections[index])
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
PRInt32 flags = nsTypedSelection::SCROLL_DO_FLUSH;
|
||||
if (aFlags & nsISelectionController::SCROLL_SYNCHRONOUS) {
|
||||
flags |= nsTypedSelection::SCROLL_SYNCHRONOUS;
|
||||
} else if (aFlags & nsISelectionController::SCROLL_FIRST_ANCESTOR_ONLY) {
|
||||
flags |= nsTypedSelection::SCROLL_FIRST_ANCESTOR_ONLY;
|
||||
}
|
||||
|
||||
// After ScrollSelectionIntoView(), the pending notifications might be
|
||||
// flushed and PresShell/PresContext/Frames may be dead. See bug 418470.
|
||||
return mDomSelections[index]->ScrollIntoView(aRegion, aIsSynchronous,
|
||||
PR_TRUE);
|
||||
return mDomSelections[index]->ScrollIntoView(aRegion,
|
||||
PRInt16(NS_PRESSHELL_SCROLL_ANYWHERE),
|
||||
PRInt16(NS_PRESSHELL_SCROLL_ANYWHERE),
|
||||
flags);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -5550,13 +5569,22 @@ nsTypedSelection::ScrollSelectionIntoViewEvent::Run()
|
|||
if (!mTypedSelection)
|
||||
return NS_OK; // event revoked
|
||||
|
||||
PRInt32 flags = nsTypedSelection::SCROLL_DO_FLUSH |
|
||||
nsTypedSelection::SCROLL_SYNCHRONOUS;
|
||||
if (mFirstAncestorOnly) {
|
||||
flags |= nsTypedSelection::SCROLL_FIRST_ANCESTOR_ONLY;
|
||||
}
|
||||
|
||||
mTypedSelection->mScrollEvent.Forget();
|
||||
mTypedSelection->ScrollIntoView(mRegion, PR_TRUE, PR_TRUE);
|
||||
mTypedSelection->ScrollIntoView(mRegion,
|
||||
PRInt16(NS_PRESSHELL_SCROLL_ANYWHERE),
|
||||
PRInt16(NS_PRESSHELL_SCROLL_ANYWHERE),
|
||||
flags);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsTypedSelection::PostScrollSelectionIntoViewEvent(SelectionRegion aRegion)
|
||||
nsTypedSelection::PostScrollSelectionIntoViewEvent(SelectionRegion aRegion, PRBool aFirstAncestorOnly)
|
||||
{
|
||||
// If we've already posted an event, revoke it and place a new one at the
|
||||
// end of the queue to make sure that any new pending reflow events are
|
||||
|
@ -5565,7 +5593,7 @@ nsTypedSelection::PostScrollSelectionIntoViewEvent(SelectionRegion aRegion)
|
|||
mScrollEvent.Revoke();
|
||||
|
||||
nsRefPtr<ScrollSelectionIntoViewEvent> ev =
|
||||
new ScrollSelectionIntoViewEvent(this, aRegion);
|
||||
new ScrollSelectionIntoViewEvent(this, aRegion, aFirstAncestorOnly);
|
||||
nsresult rv = NS_DispatchToCurrentThread(ev);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
@ -5577,14 +5605,14 @@ NS_IMETHODIMP
|
|||
nsTypedSelection::ScrollIntoView(SelectionRegion aRegion, PRBool aIsSynchronous,
|
||||
PRInt16 aVPercent, PRInt16 aHPercent)
|
||||
{
|
||||
return ScrollIntoView(aRegion, aIsSynchronous, PR_FALSE,
|
||||
aVPercent, aHPercent);
|
||||
return ScrollIntoView(aRegion, aVPercent, aHPercent,
|
||||
aIsSynchronous ? nsTypedSelection::SCROLL_SYNCHRONOUS : 0);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsTypedSelection::ScrollIntoView(SelectionRegion aRegion,
|
||||
PRBool aIsSynchronous, PRBool aDoFlush,
|
||||
PRInt16 aVPercent, PRInt16 aHPercent)
|
||||
PRInt16 aVPercent, PRInt16 aHPercent,
|
||||
PRInt32 aFlags)
|
||||
{
|
||||
nsresult result;
|
||||
if (!mFrameSelection)
|
||||
|
@ -5593,8 +5621,9 @@ nsTypedSelection::ScrollIntoView(SelectionRegion aRegion,
|
|||
if (mFrameSelection->GetBatching())
|
||||
return NS_OK;
|
||||
|
||||
if (!aIsSynchronous)
|
||||
return PostScrollSelectionIntoViewEvent(aRegion);
|
||||
if (!(aFlags & nsTypedSelection::SCROLL_SYNCHRONOUS))
|
||||
return PostScrollSelectionIntoViewEvent(aRegion,
|
||||
!!(aFlags & nsTypedSelection::SCROLL_FIRST_ANCESTOR_ONLY));
|
||||
|
||||
//
|
||||
// Shut the caret off before scrolling to avoid
|
||||
|
@ -5612,7 +5641,7 @@ nsTypedSelection::ScrollIntoView(SelectionRegion aRegion,
|
|||
// is that some callers might scroll to the wrong place. Those should
|
||||
// either manually flush if they're in a safe position for it or use the
|
||||
// async version of this method.
|
||||
if (aDoFlush) {
|
||||
if (aFlags & nsTypedSelection::SCROLL_DO_FLUSH) {
|
||||
presShell->FlushPendingNotifications(Flush_Layout);
|
||||
|
||||
// Reget the presshell, since it might have gone away.
|
||||
|
@ -5632,7 +5661,8 @@ nsTypedSelection::ScrollIntoView(SelectionRegion aRegion,
|
|||
if (!frame)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
presShell->ScrollFrameRectIntoView(frame, rect, aVPercent, aHPercent, 0);
|
||||
presShell->ScrollFrameRectIntoView(frame, rect, aVPercent, aHPercent,
|
||||
(aFlags & nsTypedSelection::SCROLL_FIRST_ANCESTOR_ONLY) ? nsIPresShell::SCROLL_FIRST_ANCESTOR_ONLY: 0);
|
||||
return NS_OK;
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<html>
|
||||
<head>
|
||||
<link href="data:text/css,#master{display:table; width: 100%;}" rel="stylesheet" type="text/css" media="screen">
|
||||
</head>
|
||||
<body>
|
||||
<div id="master">
|
||||
<div style="height:10000px; background: -moz-linear-gradient(right bottom, rgb(0,0,0) 0%, rgb(255,255,255) 100%);">
|
||||
</div>
|
||||
|
||||
<div style="height:100px"></div>
|
||||
|
||||
</div>
|
||||
</html>
|
|
@ -0,0 +1,14 @@
|
|||
<html>
|
||||
<head>
|
||||
<link href="data:text/css,#master{display:table; width: 100%;}" rel="stylesheet" type="text/css" media="screen">
|
||||
</head>
|
||||
<body>
|
||||
<div id="master">
|
||||
<div style="height:10000px; background: -moz-linear-gradient(right bottom, rgb(0,0,0) 0%, rgb(255,255,255) 100%);">
|
||||
</div>
|
||||
|
||||
<textarea style="height:100px; margin:0; border:0;"></textarea>
|
||||
<script> </script>
|
||||
|
||||
</div>
|
||||
</html>
|
|
@ -1522,4 +1522,5 @@ fails-if(!haveTestPlugin) == 599476.html 599476-ref.html
|
|||
== 604737.html 604737-ref.html
|
||||
== 600974-2.html 600974-1-ref.html
|
||||
== 600974-3.html 600974-1-ref.html
|
||||
== 605138-1.html 605138-1-ref.html
|
||||
== 605157-1.xhtml 605157-1-ref.xhtml
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
document.documentElement.pauseAnimations();
|
||||
document.documentElement.setCurrentTime(1);
|
||||
document.getElementById('a').setAttribute('end', '0s');
|
||||
/* Force a sample to make sure that event gets fired */
|
||||
document.documentElement.setCurrentTime(1);
|
||||
delayedSnapshot(2)">
|
||||
<script xlink:href="event-util.js" type="text/javascript"/>
|
||||
<rect width="100" height="100" fill="red">
|
||||
|
|
До Ширина: | Высота: | Размер: 612 B После Ширина: | Высота: | Размер: 728 B |
|
@ -12,7 +12,7 @@
|
|||
== event-end-1.svg green-box-ref.svg
|
||||
== event-end-2.svg green-box-ref.svg
|
||||
== event-end-open-1.svg green-box-ref.svg
|
||||
# == event-end-trimmed-1.svg green-box-ref.svg failing on mc, tracking in bug Bug 579828
|
||||
== event-end-trimmed-1.svg green-box-ref.svg
|
||||
== event-preventDefault-1.svg green-box-ref.svg
|
||||
== event-seek-1.svg green-box-ref.svg
|
||||
== event-target-default-1.svg green-box-ref.svg
|
||||
|
|
|
@ -668,18 +668,24 @@ canvas {
|
|||
|
||||
/* focusable content: anything w/ tabindex >=0 is focusable */
|
||||
abbr:-moz-focusring, acronym:-moz-focusring, address:-moz-focusring,
|
||||
applet:-moz-focusring,
|
||||
b:-moz-focusring, base:-moz-focusring, big:-moz-focusring,
|
||||
blockquote:-moz-focusring, br:-moz-focusring, canvas:-moz-focusring,
|
||||
caption:-moz-focusring, center:-moz-focusring, cite:-moz-focusring,
|
||||
code:-moz-focusring, col:-moz-focusring, colgroup:-moz-focusring,
|
||||
dd:-moz-focusring, del:-moz-focusring, dfn:-moz-focusring, dir:-moz-focusring,
|
||||
div:-moz-focusring, dl:-moz-focusring, dt:-moz-focusring, em:-moz-focusring,
|
||||
embed:-moz-focusring,
|
||||
fieldset:-moz-focusring, font:-moz-focusring, form:-moz-focusring,
|
||||
h1:-moz-focusring, h2:-moz-focusring, h3:-moz-focusring, h4:-moz-focusring,
|
||||
h5:-moz-focusring, h6:-moz-focusring, hr:-moz-focusring, i:-moz-focusring,
|
||||
img:-moz-focusring, ins:-moz-focusring, kbd:-moz-focusring,
|
||||
label:-moz-focusring, legend:-moz-focusring, li:-moz-focusring,
|
||||
link:-moz-focusring, menu:-moz-focusring, ol:-moz-focusring, p:-moz-focusring,
|
||||
link:-moz-focusring,
|
||||
menu:-moz-focusring,
|
||||
object:-moz-focusring,
|
||||
ol:-moz-focusring,
|
||||
p:-moz-focusring,
|
||||
pre:-moz-focusring, q:-moz-focusring, s:-moz-focusring, samp:-moz-focusring,
|
||||
small:-moz-focusring, span:-moz-focusring, strike:-moz-focusring,
|
||||
strong:-moz-focusring, sub:-moz-focusring, sup:-moz-focusring,
|
||||
|
|
|
@ -557,45 +557,87 @@ nsStyleAnimation::ComputeDistance(nsCSSProperty aProperty,
|
|||
return PR_TRUE;
|
||||
}
|
||||
case eUnit_Transform: {
|
||||
const nsCSSValueList *list1 = aStartValue.GetCSSValueListValue();
|
||||
const nsCSSValueList *list2 = aEndValue.GetCSSValueListValue();
|
||||
|
||||
nsStyleTransformMatrix matrix1, matrix2; // initialized to identity
|
||||
|
||||
PRBool dummy;
|
||||
if (list1->mValue.GetUnit() != eCSSUnit_None) {
|
||||
matrix1 = nsStyleTransformMatrix::ReadTransforms(list1, nsnull,
|
||||
nsnull, dummy);
|
||||
// Call AddWeighted to normalize to the format we use for
|
||||
// interpolation. (This is far from ideal, but it provides good
|
||||
// behavior for distance along a running transition.)
|
||||
Value normValue1, normValue2;
|
||||
if (!AddWeighted(aProperty, 1.0, aStartValue, 0.0, aEndValue,
|
||||
normValue1) ||
|
||||
!AddWeighted(aProperty, 0.0, aStartValue, 1.0, aEndValue,
|
||||
normValue2)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (list2->mValue.GetUnit() != eCSSUnit_None) {
|
||||
matrix2 = nsStyleTransformMatrix::ReadTransforms(list2, nsnull,
|
||||
nsnull, dummy);
|
||||
const nsCSSValueList *list1 = normValue1.GetCSSValueListValue();
|
||||
const nsCSSValueList *list2 = normValue2.GetCSSValueListValue();
|
||||
|
||||
NS_ABORT_IF_FALSE((list1->mValue.GetUnit() == eCSSUnit_None) ==
|
||||
(list2->mValue.GetUnit() == eCSSUnit_None),
|
||||
"none-ness should match after AddWeighted");
|
||||
if (list1->mValue.GetUnit() == eCSSUnit_None) {
|
||||
aDistance = 0;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
double diff;
|
||||
double squareDistance = 0.0;
|
||||
for (PRUint32 i = 0; i < 4; ++i) {
|
||||
diff = matrix1.GetMainMatrixEntry(i) - matrix2.GetMainMatrixEntry(i);
|
||||
squareDistance += diff * diff;
|
||||
for (; list1 && list2; list1 = list1->mNext, list2 = list2->mNext) {
|
||||
NS_ABORT_IF_FALSE(list1->mValue.GetUnit() == eCSSUnit_Function &&
|
||||
list2->mValue.GetUnit() == eCSSUnit_Function,
|
||||
"unexpected unit");
|
||||
const nsCSSValue::Array *a1 = list1->mValue.GetArrayValue(),
|
||||
*a2 = list2->mValue.GetArrayValue();
|
||||
NS_ABORT_IF_FALSE(a1->Item(0).GetUnit() == eCSSUnit_Ident &&
|
||||
a2->Item(0).GetUnit() == eCSSUnit_Ident,
|
||||
"unexpected unit");
|
||||
NS_ABORT_IF_FALSE(a1->Item(0) == a2->Item(0),
|
||||
"unexpected function mismatch");
|
||||
nsCSSKeyword tfunc = nsStyleTransformMatrix::TransformFunctionOf(a1);
|
||||
NS_ABORT_IF_FALSE(a1->Count() == a2->Count(),
|
||||
"unexpected count mismatch");
|
||||
for (size_t i = 1, iEnd = NS_MIN(a1->Count(), a2->Count());
|
||||
i < iEnd; ++i) {
|
||||
const nsCSSValue &v1 = a1->Item(i), &v2 = a2->Item(i);
|
||||
NS_ABORT_IF_FALSE(v1.GetUnit() == eCSSUnit_Pixel ||
|
||||
v1.GetUnit() == eCSSUnit_Percent ||
|
||||
v1.GetUnit() == eCSSUnit_Calc ||
|
||||
v1.GetUnit() == eCSSUnit_Radian ||
|
||||
v1.GetUnit() == eCSSUnit_Number,
|
||||
"unexpected unit");
|
||||
NS_ABORT_IF_FALSE(v2.GetUnit() == eCSSUnit_Pixel ||
|
||||
v2.GetUnit() == eCSSUnit_Percent ||
|
||||
v2.GetUnit() == eCSSUnit_Calc ||
|
||||
v2.GetUnit() == eCSSUnit_Radian ||
|
||||
v2.GetUnit() == eCSSUnit_Number,
|
||||
"unexpected unit");
|
||||
if (v1.GetUnit() == eCSSUnit_Pixel ||
|
||||
v1.GetUnit() == eCSSUnit_Percent ||
|
||||
v1.GetUnit() == eCSSUnit_Calc) {
|
||||
NS_ABORT_IF_FALSE(v2.GetUnit() == eCSSUnit_Pixel ||
|
||||
v2.GetUnit() == eCSSUnit_Percent ||
|
||||
v2.GetUnit() == eCSSUnit_Calc,
|
||||
"unit mismatch");
|
||||
CalcValue c1 = ExtractCalcValue(v1),
|
||||
c2 = ExtractCalcValue(v2);
|
||||
double diff = c1.mLength - c2.mLength;
|
||||
squareDistance += diff * diff;
|
||||
diff = c1.mPercent - c2.mPercent;
|
||||
squareDistance += diff * diff;
|
||||
} else {
|
||||
NS_ABORT_IF_FALSE(v1.GetUnit() == v2.GetUnit(), "unit mismatch");
|
||||
double diff;
|
||||
if (tfunc == eCSSKeyword_skewx ||
|
||||
tfunc == eCSSKeyword_skewy ||
|
||||
tfunc == eCSSKeyword_skew) {
|
||||
NS_ABORT_IF_FALSE(v1.GetUnit() == eCSSUnit_Radian, "unexpected unit");
|
||||
diff = tan(v2.GetFloatValue()) - tan(v1.GetFloatValue());
|
||||
} else {
|
||||
diff = v2.GetFloatValue() - v1.GetFloatValue();
|
||||
}
|
||||
squareDistance += diff * diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
diff = nsPresContext::AppUnitsToFloatCSSPixels(
|
||||
matrix1.GetCoordXTranslation() - matrix2.GetCoordXTranslation());
|
||||
squareDistance += diff * diff;
|
||||
diff = nsPresContext::AppUnitsToFloatCSSPixels(
|
||||
matrix1.GetCoordYTranslation() - matrix2.GetCoordYTranslation());
|
||||
squareDistance += diff * diff;
|
||||
diff = matrix1.GetWidthRelativeXTranslation() -
|
||||
matrix2.GetWidthRelativeXTranslation();
|
||||
squareDistance += diff * diff;
|
||||
diff = matrix1.GetWidthRelativeYTranslation() -
|
||||
matrix2.GetWidthRelativeYTranslation();
|
||||
squareDistance += diff * diff;
|
||||
diff = matrix1.GetHeightRelativeXTranslation() -
|
||||
matrix2.GetHeightRelativeXTranslation();
|
||||
squareDistance += diff * diff;
|
||||
diff = matrix1.GetHeightRelativeYTranslation() -
|
||||
matrix2.GetHeightRelativeYTranslation();
|
||||
squareDistance += diff * diff;
|
||||
NS_ABORT_IF_FALSE(!list1 && !list2,
|
||||
"list lengths should match after AddWeighted");
|
||||
|
||||
aDistance = sqrt(squareDistance);
|
||||
return PR_TRUE;
|
||||
|
@ -707,36 +749,6 @@ AddCSSValuePercent(double aCoeff1, const nsCSSValue &aValue1,
|
|||
aCoeff2 * aValue2.GetPercentValue());
|
||||
}
|
||||
|
||||
// Add two non-canonical-form calc values (eUnit_Transform) to make
|
||||
// another non-canonical-form calc value.
|
||||
static void
|
||||
AddCSSValueNoncanonicalCalc(double aCoeff1, const nsCSSValue &aValue1,
|
||||
double aCoeff2, const nsCSSValue &aValue2,
|
||||
nsCSSValue &aResult)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aValue1.GetUnit() == eCSSUnit_Percent ||
|
||||
aValue1.GetUnit() == eCSSUnit_Pixel ||
|
||||
aValue1.IsCalcUnit(), "unexpected unit");
|
||||
NS_ABORT_IF_FALSE(aValue2.GetUnit() == eCSSUnit_Percent ||
|
||||
aValue2.GetUnit() == eCSSUnit_Pixel ||
|
||||
aValue2.IsCalcUnit(), "unexpected unit");
|
||||
nsRefPtr<nsCSSValue::Array> a1 = nsCSSValue::Array::Create(2),
|
||||
a2 = nsCSSValue::Array::Create(2),
|
||||
atop = nsCSSValue::Array::Create(2),
|
||||
acalc = nsCSSValue::Array::Create(1);
|
||||
// Don't nest the eCSSUnit_Calc in our input inside any expressions.
|
||||
a1->Item(0).SetFloatValue(aCoeff1, eCSSUnit_Number);
|
||||
a1->Item(1) = aValue1.GetUnit() == eCSSUnit_Calc
|
||||
? aValue1.GetArrayValue()->Item(0) : aValue1;
|
||||
a2->Item(0).SetFloatValue(aCoeff2, eCSSUnit_Number);
|
||||
a2->Item(1) = aValue2.GetUnit() == eCSSUnit_Calc
|
||||
? aValue2.GetArrayValue()->Item(0) : aValue2;
|
||||
atop->Item(0).SetArrayValue(a1, eCSSUnit_Calc_Times_L);
|
||||
atop->Item(1).SetArrayValue(a2, eCSSUnit_Calc_Times_L);
|
||||
acalc->Item(0).SetArrayValue(atop, eCSSUnit_Calc_Plus);
|
||||
aResult.SetArrayValue(acalc, eCSSUnit_Calc);
|
||||
}
|
||||
|
||||
// Add two canonical-form calc values (eUnit_Calc) to make another
|
||||
// canonical-form calc value.
|
||||
static void
|
||||
|
@ -841,7 +853,7 @@ AddTransformTranslate(const nsCSSValue &aValue1, double aCoeff1,
|
|||
|
||||
if (aValue1.GetUnit() != aValue2.GetUnit() || aValue1.IsCalcUnit()) {
|
||||
// different units; create a calc() expression
|
||||
AddCSSValueNoncanonicalCalc(aCoeff1, aValue1, aCoeff2, aValue2, aResult);
|
||||
AddCSSValueCanonicalCalc(aCoeff1, aValue1, aCoeff2, aValue2, aResult);
|
||||
} else if (aValue1.GetUnit() == eCSSUnit_Percent) {
|
||||
// both percent
|
||||
AddCSSValuePercent(aCoeff1, aValue1, aCoeff2, aValue2, aResult);
|
||||
|
@ -1108,7 +1120,7 @@ AddTransformMatrix(const nsStyleTransformMatrix &aMatrix1, double aCoeff1,
|
|||
|
||||
// append a rotate(90deg)
|
||||
arr = AppendTransformFunction(eCSSKeyword_rotate, resultTail);
|
||||
arr->Item(1).SetFloatValue(90.0f, eCSSUnit_Degree);
|
||||
arr->Item(1).SetFloatValue(float(M_PI_2), eCSSUnit_Radian);
|
||||
|
||||
// append the translation for parts of the % translation components
|
||||
// that were from inside a rotation
|
||||
|
@ -1124,7 +1136,7 @@ AddTransformMatrix(const nsStyleTransformMatrix &aMatrix1, double aCoeff1,
|
|||
|
||||
// append a rotate(-90deg)
|
||||
arr = AppendTransformFunction(eCSSKeyword_rotate, resultTail);
|
||||
arr->Item(1).SetFloatValue(-90.0f, eCSSUnit_Degree);
|
||||
arr->Item(1).SetFloatValue(-float(M_PI_2), eCSSUnit_Radian);
|
||||
|
||||
nscoord translateXCoord = NSToCoordRound(
|
||||
aMatrix1.GetCoordXTranslation() * aCoeff1 +
|
||||
|
@ -1905,8 +1917,12 @@ nsStyleAnimation::ComputeValue(nsCSSProperty aProperty,
|
|||
"we should only be able to actively animate nodes that "
|
||||
"are in a document");
|
||||
|
||||
nsCSSProperty propToParse =
|
||||
nsCSSProps::PropHasFlags(aProperty, CSS_PROPERTY_REPORT_OTHER_NAME)
|
||||
? nsCSSProps::OtherNameFor(aProperty) : aProperty;
|
||||
|
||||
nsRefPtr<nsStyleContext> tmpStyleContext =
|
||||
StyleWithDeclarationAdded(aProperty, aTargetElement,
|
||||
StyleWithDeclarationAdded(propToParse, aTargetElement,
|
||||
aSpecifiedValue, aUseSVGMode);
|
||||
if (!tmpStyleContext) {
|
||||
return PR_FALSE;
|
||||
|
@ -2116,13 +2132,25 @@ StyleCoordToCSSValue(const nsStyleCoord& aCoord, nsCSSValue& aCSSValue)
|
|||
|
||||
/*
|
||||
* Assign |aOutput = aInput|, except with any non-pixel lengths
|
||||
* replaced with the equivalent in pixels.
|
||||
* replaced with the equivalent in pixels, and any non-canonical calc()
|
||||
* expressions replaced with canonical ones.
|
||||
*/
|
||||
static void
|
||||
SubstitutePixelValues(nsStyleContext* aStyleContext,
|
||||
const nsCSSValue& aInput, nsCSSValue& aOutput)
|
||||
{
|
||||
if (aInput.UnitHasArrayValue()) {
|
||||
if (aInput.IsCalcUnit()) {
|
||||
PRBool canStoreInRuleTree = PR_TRUE;
|
||||
nsRuleNode::ComputedCalc c =
|
||||
nsRuleNode::SpecifiedCalcToComputedCalc(aInput, aStyleContext,
|
||||
aStyleContext->PresContext(),
|
||||
canStoreInRuleTree);
|
||||
nsStyleCoord::Calc c2;
|
||||
c2.mLength = c.mLength;
|
||||
c2.mPercent = c.mPercent;
|
||||
c2.mHasPercent = PR_TRUE; // doesn't matter for transform translate
|
||||
SetCalcValue(&c2, aOutput);
|
||||
} else if (aInput.UnitHasArrayValue()) {
|
||||
const nsCSSValue::Array *inputArray = aInput.GetArrayValue();
|
||||
nsRefPtr<nsCSSValue::Array> outputArray =
|
||||
nsCSSValue::Array::Create(inputArray->Count());
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче