This commit is contained in:
Brian Hackett 2011-08-23 07:08:50 -07:00
Родитель 301eb51b89 5ad50ec627
Коммит 5bf926fb84
184 изменённых файлов: 2988 добавлений и 1383 удалений

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

@ -976,10 +976,12 @@ refRelationSetCB(AtkObject *aAtkObj)
while ((tempAcc = rel.Next()))
targets.AppendElement(nsAccessibleWrap::GetAtkObject(tempAcc));
if (targets.Length()) {
atkRelation = atk_relation_new(targets.Elements(), targets.Length(), atkType);
atk_relation_set_add(relation_set, atkRelation);
g_object_unref(atkRelation);
}
}
return relation_set;
}

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

@ -868,8 +868,11 @@ var InspectorUI = {
delete this.treeBrowserDocument;
}
if (this.treeIFrame)
if (this.treeIFrame) {
let parent = this.treeIFrame.parentNode;
parent.removeChild(this.treeIFrame);
delete this.treeIFrame;
}
delete this.ioBox;
if (this.domplate) {
@ -893,6 +896,8 @@ var InspectorUI = {
this.treeLoaded = false;
this.treePanel.addEventListener("popuphidden", function treePanelHidden() {
this.removeEventListener("popuphidden", treePanelHidden, false);
InspectorUI.closing = false;
Services.obs.notifyObservers(null, INSPECTOR_NOTIFICATIONS.CLOSED, null);
}, false);

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

@ -156,10 +156,9 @@ Sanitizer.prototype = {
}
// Clear plugin data.
let ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
const phInterface = Ci.nsIPluginHost;
const FLAG_CLEAR_ALL = phInterface.FLAG_CLEAR_ALL;
ph.QueryInterface(phInterface);
let ph = Cc["@mozilla.org/plugin/host;1"].getService(phInterface);
// Determine age range in seconds. (-1 means clear all.) We don't know
// that this.range[1] is actually now, so we compute age range based

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

@ -0,0 +1,46 @@
/* ***** 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 content.js.
*
* The Initial Developer of the Original Code is the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Tim Taubert <ttaubert@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
addEventListener("DOMWillOpenModalDialog", function (event) {
// (event.isTrusted == true) when the event is generated by a user action
// and does not originate from a script.
if (event.isTrusted) {
// we're intentionally sending a synchronous message to handle this event
// as quick as possible, switch the selected tab and hide the tabview
// before the modal dialog is shown
sendSyncMessage("Panorama:DOMWillOpenModalDialog");
}
}, true);

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

@ -231,7 +231,7 @@ function GroupItem(listOfEls, options) {
.appendTo(appTabTrayContainer);
AllTabs.tabs.forEach(function(xulTab) {
if (xulTab.pinned && xulTab.ownerDocument.defaultView == gWindow)
if (xulTab.pinned)
self.addAppTab(xulTab, {dontAdjustTray: true});
});
@ -744,9 +744,13 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
// ----------
// Function: _unhide
// Shows the hidden group.
_unhide: function GroupItem__unhide() {
let self = this;
//
// Parameters:
// options - various options (see below)
//
// Possible options:
// immediately - true when no animations should be used
_unhide: function GroupItem__unhide(options) {
this._cancelFadeAwayUndoButtonTimer();
this.hidden = false;
this.$undoContainer.remove();
@ -754,20 +758,31 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
this.droppable(true);
this.setTrenches(this.bounds);
iQ(this.container).show().animate({
"-moz-transform": "scale(1)",
"opacity": 1
}, {
duration: 170,
complete: function() {
let self = this;
let finalize = function () {
self._children.forEach(function(child) {
iQ(child.container).show();
});
UI.setActive(self);
self._sendToSubscribers("groupShown", { groupItemId: self.id });
}
};
let $container = iQ(this.container).show();
if (!options || !options.immediately) {
$container.animate({
"-moz-transform": "scale(1)",
"opacity": 1
}, {
duration: 170,
complete: finalize
});
} else {
$container.css({"-moz-transform": "none", opacity: 1});
finalize();
}
GroupItems.updateGroupCloseButtons();
},
@ -785,15 +800,29 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
let remainingGroups = GroupItems.groupItems.filter(function (groupItem) {
return (groupItem != self && groupItem.getChildren().length);
});
let tab = null;
if (!gBrowser._numPinnedTabs && !remainingGroups.length) {
let emptyGroups = GroupItems.groupItems.filter(function (groupItem) {
return (groupItem != self && !groupItem.getChildren().length);
});
let group = (emptyGroups.length ? emptyGroups[0] : GroupItems.newGroup());
group.newTab(null, { closedLastTab: true });
tab = group.newTab(null, {dontZoomIn: true});
}
this.destroy();
let closed = this.destroy();
if (!tab)
return;
if (closed) {
// Let's make the new tab the selected tab.
UI.goToTab(tab);
} else {
// Remove the new tab and group, if this group is no longer closed.
tab._tabViewTabItem.parent.destroy({immediately: true});
}
},
// ----------
@ -806,6 +835,10 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
//
// Options:
// immediately - (bool) if true, no animation will be used
//
// Returns true if the groupItem has been closed, or false otherwise. A group
// could not have been closed due to a tab with an onUnload handler (that
// waits for user interaction).
destroy: function GroupItem_destroy(options) {
let self = this;
@ -814,14 +847,11 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
// In other words, the group "close" event is fired before all browser
// tabs in the group are closed. The below code would fire the group "close"
// event only after all browser tabs in that group are closed.
let shouldRemoveTabItems = [];
let toClose = this._children.concat();
toClose.forEach(function(child) {
this._children.concat().forEach(function(child) {
child.removeSubscriber("close", self._onChildClose);
let removed = child.close(true);
if (removed) {
shouldRemoveTabItems.push(child);
if (child.close(true)) {
self.remove(child, { dontArrange: true });
} else {
// child.removeSubscriber() must be called before child.close(),
// therefore we call child.addSubscriber() if the tab is not removed.
@ -829,15 +859,14 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
}
});
if (shouldRemoveTabItems.length != toClose.length) {
// remove children without the assiciated tab and show the group item
shouldRemoveTabItems.forEach(function(child) {
self.remove(child, { dontArrange: true });
});
if (this._children.length) {
if (this.hidden)
this.$undoContainer.fadeOut(function() { self._unhide() });
return false;
} else {
this.close(options);
return true;
}
},
@ -1818,13 +1847,16 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
// Parameters:
// url - the new tab should open this url as well
// options - the options object
// dontZoomIn - set to true to not zoom into the newly created tab
// closedLastTab - boolean indicates the last tab has just been closed
newTab: function GroupItem_newTab(url, options) {
if (options && options.closedLastTab)
UI.closedLastTabInTabView = true;
UI.setActive(this, { dontSetActiveTabInGroup: true });
gBrowser.loadOneTab(url || "about:blank", { inBackground: false });
let dontZoomIn = !!(options && options.dontZoomIn);
return gBrowser.loadOneTab(url || "about:blank", { inBackground: dontZoomIn });
},
// ----------
@ -1926,13 +1958,13 @@ let GroupItems = {
let self = this;
// setup attr modified handler, and prepare for its uninit
function handleAttrModified(xulTab) {
self._handleAttrModified(xulTab);
function handleAttrModified(event) {
self._handleAttrModified(event.target);
}
// make sure any closed tabs are removed from the delay update list
function handleClose(xulTab) {
let idx = self._delayedModUpdates.indexOf(xulTab);
function handleClose(event) {
let idx = self._delayedModUpdates.indexOf(event.target);
if (idx != -1)
self._delayedModUpdates.splice(idx, 1);
}
@ -2040,7 +2072,7 @@ let GroupItems = {
// Function: _updateAppTabIcons
// Update images of any apptab icons that point to passed in xultab
_updateAppTabIcons: function GroupItems__updateAppTabIcons(xulTab) {
if (xulTab.ownerDocument.defaultView != gWindow || !xulTab.pinned)
if (!xulTab.pinned)
return;
let iconUrl = this.getAppTabFavIconUrl(xulTab);

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

@ -1,183 +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 TabView AllTabs.
*
* 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):
* Edward Lee <edilee@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
"use strict";
const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
let EXPORTED_SYMBOLS = ["AllTabs"];
let AllTabs = {
// ----------
// Function: toString
// Prints [AllTabs] for debug use
toString: function AllTabs_toString() {
return "[AllTabs]";
},
/**
* Get an array of all tabs from all tabbrowser windows.
*
* @usage let numAllTabs = AllTabs.tabs.length;
* AllTabs.tabs.forEach(handleAllTabs);
*/
get tabs() {
// Get tabs from each browser window and flatten them into one array
return Array.concat.apply(null, browserWindows.map(function(browserWindow) {
return Array.filter(browserWindow.gBrowser.tabs, function (tab) !tab.closing);
}));
},
/**
* Attach a callback for a given tab event.
*
* @param eventName
* Name of the corresponding Tab* Event; one of "attrModified",
* "close", "move", "open", "select", "pinned", "unpinned".
* @param callback
* Callback that gets called with the tab as the first argument and
* the event as the second argument.
* @usage AllTabs.register("change", function handleChange(tab, event) {});
*/
register: function register(eventName, callback) {
// Either add additional callbacks or create the first entry
let listeners = eventListeners[events[eventName]];
if (listeners)
listeners.push(callback);
else
eventListeners[events[eventName]] = [callback];
},
/**
* Remove a callback for a given tab event.
*
* @param eventName
* Name of the corresponding Tab* Event; one of "attrModified",
* "close", "move", "open", "select", "pinned", "unpinned".
* @param callback
* The callback given for the original AllTabs.register call.
* @usage AllTabs.unregister("close", handleClose);
*/
unregister: function unregister(eventName, callback) {
// Nothing to remove for this event
let listeners = eventListeners[events[eventName]];
if (!listeners)
return;
// Can only remove a callback if we have it
let index = listeners.indexOf(callback);
if (index == -1)
return;
listeners.splice(index, 1);
}
};
__defineGetter__("browserWindows", function browserWindows() {
let browserWindows = [];
let windows = Services.wm.getEnumerator("navigator:browser");
while (windows.hasMoreElements())
browserWindows.push(windows.getNext());
return browserWindows;
});
let events = {
attrModified: "TabAttrModified",
close: "TabClose",
move: "TabMove",
open: "TabOpen",
select: "TabSelect",
pinned: "TabPinned",
unpinned: "TabUnpinned"
};
let eventListeners = {};
function registerBrowserWindow(browserWindow) {
for each (let event in events)
browserWindow.addEventListener(event, tabEventListener, true);
browserWindow.addEventListener("unload", unregisterBrowserWindow, false);
}
function unregisterBrowserWindow(unloadEvent) {
let browserWindow = unloadEvent.currentTarget;
for each (let event in events)
browserWindow.removeEventListener(event, tabEventListener, true);
browserWindow.removeEventListener("unload", unregisterBrowserWindow, false);
}
function tabEventListener(event) {
// Make sure we've gotten listeners before trying to call
let listeners = eventListeners[event.type];
if (!listeners)
return;
let tab = event.target;
// Make a copy of the listeners, so it can't change as we call back
listeners.slice().forEach(function (callback) {
try {
callback(tab, event);
}
// Don't let failing callbacks stop us but report the failure
catch (ex) {
Cu.reportError(ex);
}
});
}
function observer(subject, topic, data) {
switch (topic) {
case "domwindowopened":
subject.addEventListener("load", function onLoad() {
subject.removeEventListener("load", onLoad, false);
// Now that the window has loaded, only register on browser windows
let doc = subject.document.documentElement;
if (doc.getAttribute("windowtype") == "navigator:browser")
registerBrowserWindow(subject);
}, false);
break;
}
}
// Register listeners on all browser windows and future ones
browserWindows.forEach(registerBrowserWindow);
Services.obs.addObserver(observer, "domwindowopened", false);

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

@ -520,6 +520,9 @@ function createSearchTabMacher() {
}
function hideSearch(event) {
if (!isSearchEnabled())
return;
iQ("#searchbox").val("");
iQ("#searchshade").hide();
iQ("#search").hide();

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

@ -79,9 +79,6 @@ let Storage = {
// ___ Tabs
AllTabs.tabs.forEach(function(tab) {
if (tab.ownerDocument.defaultView != gWindow)
return;
self.saveTab(tab, null);
});
@ -184,6 +181,23 @@ let Storage = {
return existingData;
},
// ----------
// Function: readWindowBusyState
// Returns the current busyState for the given window.
readWindowBusyState: function Storage_readWindowBusyState(win) {
let state;
try {
let data = this._sessionStore.getWindowState(win);
if (data)
state = JSON.parse(data);
} catch (e) {
Utils.log("Error while parsing window state");
}
return (state && state.windows[0].busy);
},
// ----------
// Function: saveGroupItemsData
// Saves the global data for the <GroupItems> singleton for the given window.

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

@ -478,29 +478,22 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), {
// closing tab doesn't belong to a group and no empty group, create a new
// one for the new tab.
if (!groupClose && gBrowser.tabs.length == 1) {
let group;
if (this.tab._tabViewTabItem.parent) {
group = this.tab._tabViewTabItem.parent;
} else {
let emptyGroups = GroupItems.groupItems.filter(function (groupItem) {
return (!groupItem.getChildren().length);
});
group = (emptyGroups.length ? emptyGroups[0] : GroupItems.newGroup());
}
let group = this.tab._tabViewTabItem.parent;
group.newTab(null, { closedLastTab: true });
}
// when "TabClose" event is fired, the browser tab is about to close and our
// item "close" is fired before the browser tab actually get closed.
// Therefore, we need "tabRemoved" event below.
gBrowser.removeTab(this.tab);
let tabNotClosed =
Array.some(gBrowser.tabs, function(tab) { return tab == this.tab; }, this);
if (!tabNotClosed)
let tabClosed = !this.tab;
if (tabClosed)
this._sendToSubscribers("tabRemoved");
// No need to explicitly delete the tab data, becasue sessionstore data
// associated with the tab will automatically go away
return !tabNotClosed;
return tabClosed;
},
// ----------
@ -746,27 +739,26 @@ let TabItems = {
this.tempCanvas.height = 112;
// When a tab is opened, create the TabItem
this._eventListeners["open"] = function(tab) {
if (tab.ownerDocument.defaultView != gWindow || tab.pinned)
return;
this._eventListeners.open = function (event) {
let tab = event.target;
if (!tab.pinned)
self.link(tab);
}
// When a tab's content is loaded, show the canvas and hide the cached data
// if necessary.
this._eventListeners["attrModified"] = function(tab) {
if (tab.ownerDocument.defaultView != gWindow || tab.pinned)
return;
this._eventListeners.attrModified = function (event) {
let tab = event.target;
if (!tab.pinned)
self.update(tab);
}
// When a tab is closed, unlink.
this._eventListeners["close"] = function(tab) {
if (tab.ownerDocument.defaultView != gWindow || tab.pinned)
return;
this._eventListeners.close = function (event) {
let tab = event.target;
// XXX bug #635975 - don't unlink the tab if the dom window is closing.
if (!UI.isDOMWindowClosing)
if (!tab.pinned && !UI.isDOMWindowClosing)
self.unlink(tab);
}
for (let name in this._eventListeners) {
@ -774,8 +766,8 @@ let TabItems = {
}
// For each tab, create the link.
AllTabs.tabs.forEach(function(tab) {
if (tab.ownerDocument.defaultView != gWindow || tab.pinned)
AllTabs.tabs.forEach(function (tab) {
if (tab.pinned)
return;
self.link(tab, {immediately: true});

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

@ -5,7 +5,6 @@ const Ci = Components.interfaces;
const Cu = Components.utils;
const Cr = Components.results;
Cu.import("resource:///modules/tabview/AllTabs.jsm");
Cu.import("resource:///modules/tabview/utils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
@ -44,6 +43,30 @@ var gTabViewDeck = gWindow.document.getElementById("tab-view-deck");
var gBrowserPanel = gWindow.document.getElementById("browser-panel");
var gTabViewFrame = gWindow.document.getElementById("tab-view");
let AllTabs = {
_events: {
attrModified: "TabAttrModified",
close: "TabClose",
move: "TabMove",
open: "TabOpen",
select: "TabSelect",
pinned: "TabPinned",
unpinned: "TabUnpinned"
},
get tabs() {
return Array.filter(gBrowser.tabs, function (tab) !tab.closing);
},
register: function AllTabs_register(eventName, callback) {
gBrowser.tabContainer.addEventListener(this._events[eventName], callback, false);
},
unregister: function AllTabs_unregister(eventName, callback) {
gBrowser.tabContainer.removeEventListener(this._events[eventName], callback, false);
}
};
# NB: Certain files need to evaluate before others
#include iq.js

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

@ -26,6 +26,7 @@
* Raymond Lee <raymond@appcoast.com>
* Sean Dunn <seanedunn@yahoo.com>
* Tim Taubert <tim.taubert@gmx.de>
* Mihai Sucan <mihai.sucan@gmail.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
@ -80,6 +81,10 @@ let UI = {
// If true, a closed tab has just been restored.
restoredClosedTab: false,
// Variable: _isChangingVisibility
// Tracks whether we're currently in the process of showing/hiding the tabview.
_isChangingVisibility: false,
// Variable: _reorderTabItemsOnShow
// Keeps track of the <GroupItem>s which their tab items' tabs have been moved
// and re-orders the tab items when switching to TabView.
@ -123,9 +128,9 @@ let UI = {
wasInTabView: false
},
// Variable: _storageBusyCount
// Used to keep track of how many calls to storageBusy vs storageReady.
_storageBusyCount: 0,
// Variable: _storageBusy
// Tells whether the storage is currently busy or not.
_storageBusy: false,
// Variable: isDOMWindowClosing
// Tells wether the parent window is about to close
@ -169,6 +174,10 @@ let UI = {
// ___ storage
Storage.init();
if (Storage.readWindowBusyState(gWindow))
this.storageBusy();
let data = Storage.readUIData(gWindow);
this._storageSanity(data);
this._pageBounds = data.pageBounds;
@ -230,6 +239,15 @@ let UI = {
self.uninit();
});
// ___ setup DOMWillOpenModalDialog message handler
let mm = gWindow.messageManager;
let callback = this._onDOMWillOpenModalDialog.bind(this);
mm.addMessageListener("Panorama:DOMWillOpenModalDialog", callback);
this._cleanupFunctions.push(function () {
mm.removeMessageListener("Panorama:DOMWillOpenModalDialog", callback);
});
// ___ setup key handlers
this._setTabViewFrameKeyHandlers();
@ -272,6 +290,10 @@ let UI = {
self._save();
}, false);
// ___ load frame script
let frameScript = "chrome://browser/content/tabview-content.js";
gWindow.messageManager.loadFrameScript(frameScript, true);
// ___ Done
this._frameInitialized = true;
this._save();
@ -477,9 +499,11 @@ let UI = {
// Parameters:
// zoomOut - true for zoom out animation, false for nothing.
showTabView: function UI_showTabView(zoomOut) {
if (this.isTabViewVisible())
if (this.isTabViewVisible() || this._isChangingVisibility)
return;
this._isChangingVisibility = true;
// initialize the direction of the page
this._initPageDirection();
@ -522,6 +546,7 @@ let UI = {
self.setActive(item);
self._resize(true);
self._isChangingVisibility = false;
dispatchEvent(event);
// Flush pending updates
@ -531,6 +556,7 @@ let UI = {
});
} else {
self.clearActiveTab();
self._isChangingVisibility = false;
dispatchEvent(event);
// Flush pending updates
@ -547,9 +573,11 @@ let UI = {
// Function: hideTabView
// Hides TabView and shows the main browser UI.
hideTabView: function UI_hideTabView() {
if (!this.isTabViewVisible())
if (!this.isTabViewVisible() || this._isChangingVisibility)
return;
this._isChangingVisibility = true;
// another tab might be select if user decides to stay on a page when
// a onclose confirmation prompts.
GroupItems.removeHiddenGroups();
@ -576,6 +604,8 @@ let UI = {
#endif
Storage.saveVisibilityData(gWindow, "false");
this._isChangingVisibility = false;
let event = document.createEvent("Events");
event.initEvent("tabviewhidden", true, false);
dispatchEvent(event);
@ -612,12 +642,13 @@ let UI = {
// Pauses the storage activity that conflicts with sessionstore updates and
// private browsing mode switches. Calls can be nested.
storageBusy: function UI_storageBusy() {
if (!this._storageBusyCount) {
if (this._storageBusy)
return;
this._storageBusy = true;
TabItems.pauseReconnecting();
GroupItems.pauseAutoclose();
}
this._storageBusyCount++;
},
// ----------
@ -625,8 +656,11 @@ let UI = {
// Resumes the activity paused by storageBusy, and updates for any new group
// information in sessionstore. Calls can be nested.
storageReady: function UI_storageReady() {
this._storageBusyCount--;
if (!this._storageBusyCount) {
if (!this._storageBusy)
return;
this._storageBusy = false;
let hasGroupItemsData = GroupItems.load();
if (!hasGroupItemsData)
this.reset();
@ -634,7 +668,6 @@ let UI = {
TabItems.resumeReconnecting();
GroupItems._updateTabBar();
GroupItems.resumeAutoclose();
}
},
// ----------
@ -678,6 +711,7 @@ let UI = {
}
} else if (topic == "private-browsing-change-granted") {
if (data == "enter" || data == "exit") {
hideSearch();
self._privateBrowsing.transitionMode = data;
self.storageBusy();
}
@ -703,9 +737,8 @@ let UI = {
});
// TabOpen
this._eventListeners.open = function(tab) {
if (tab.ownerDocument.defaultView != gWindow)
return;
this._eventListeners.open = function (event) {
let tab = event.target;
// if it's an app tab, add it to all the group items
if (tab.pinned)
@ -715,9 +748,8 @@ let UI = {
};
// TabClose
this._eventListeners.close = function(tab) {
if (tab.ownerDocument.defaultView != gWindow)
return;
this._eventListeners.close = function (event) {
let tab = event.target;
// if it's an app tab, remove it from all the group items
if (tab.pinned)
@ -730,7 +762,7 @@ let UI = {
} else {
// If we're currently in the process of entering private browsing,
// we don't want to go to the Tab View UI.
if (self._storageBusyCount)
if (self._storageBusy)
return;
// if not closing the last tab
@ -749,21 +781,14 @@ let UI = {
groupItem._children.length == 1 &&
groupItem._children[0].tab == tab);
// 2) Take care of the case where you've closed the last tab in
// an un-named groupItem, which means that the groupItem is gone (null) and
// there are no visible tabs.
let closingUnnamedGroup = (groupItem == null &&
gBrowser.visibleTabs.length <= 1);
// 3) When a blank tab is active while restoring a closed tab the
// 2) When a blank tab is active while restoring a closed tab the
// blank tab gets removed. The active group is not closed as this is
// where the restored tab goes. So do not show the TabView.
let tabItem = tab && tab._tabViewTabItem;
let closingBlankTabAfterRestore =
(tabItem && tabItem.isRemovedAfterRestore);
if ((closingLastOfGroup || closingUnnamedGroup) &&
!closingBlankTabAfterRestore) {
if (closingLastOfGroup && !closingBlankTabAfterRestore) {
// for the tab focus event to pick up.
self._closedLastVisibleTab = true;
self.showTabView();
@ -773,9 +798,8 @@ let UI = {
};
// TabMove
this._eventListeners.move = function(tab) {
if (tab.ownerDocument.defaultView != gWindow)
return;
this._eventListeners.move = function (event) {
let tab = event.target;
if (GroupItems.groupItems.length > 0) {
if (tab.pinned) {
@ -790,26 +814,21 @@ let UI = {
};
// TabSelect
this._eventListeners.select = function(tab) {
if (tab.ownerDocument.defaultView != gWindow)
return;
self.onTabSelect(tab);
this._eventListeners.select = function (event) {
self.onTabSelect(event.target);
};
// TabPinned
this._eventListeners.pinned = function(tab) {
if (tab.ownerDocument.defaultView != gWindow)
return;
this._eventListeners.pinned = function (event) {
let tab = event.target;
TabItems.handleTabPin(tab);
GroupItems.addAppTab(tab);
};
// TabUnpinned
this._eventListeners.unpinned = function(tab) {
if (tab.ownerDocument.defaultView != gWindow)
return;
this._eventListeners.unpinned = function (event) {
let tab = event.target;
TabItems.handleTabUnpin(tab);
GroupItems.removeAppTab(tab);
@ -883,8 +902,14 @@ let UI = {
// if TabView is visible but we didn't just close the last tab or
// selected tab, show chrome.
if (this.isTabViewVisible())
if (this.isTabViewVisible()) {
// Unhide the group of the tab the user is activating.
if (tab && tab._tabViewTabItem && tab._tabViewTabItem.parent &&
tab._tabViewTabItem.parent.hidden)
tab._tabViewTabItem.parent._unhide({immediately: true});
this.hideTabView();
}
// another tab might be selected when hideTabView() is invoked so a
// validation is needed.
@ -918,6 +943,27 @@ let UI = {
}
},
// ----------
// Function: _onDOMWillOpenModalDialog
// Called when a web page is about to show a modal dialog.
_onDOMWillOpenModalDialog: function UI__onDOMWillOpenModalDialog(cx) {
if (!this.isTabViewVisible())
return;
let index = gBrowser.browsers.indexOf(cx.target);
if (index == -1)
return;
let tab = gBrowser.tabs[index];
// When TabView is visible, we need to call onTabSelect to make sure that
// TabView is hidden and that the correct group is activated. When a modal
// dialog is shown for currently selected tab the onTabSelect event handler
// is not called, so we need to do it.
if (gBrowser.selectedTab == tab && this._currentTab == tab)
this.onTabSelect(tab);
},
// ----------
// Function: setReorderTabsOnHide
// Sets the groupItem which the tab items' tabs should be re-ordered when

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

@ -111,6 +111,7 @@ _BROWSER_FILES = \
browser_tabview_bug625269.js \
browser_tabview_bug625424.js \
browser_tabview_bug626368.js \
browser_tabview_bug626455.js \
browser_tabview_bug626525.js \
browser_tabview_bug626791.js \
browser_tabview_bug627239.js \
@ -139,6 +140,7 @@ _BROWSER_FILES = \
browser_tabview_bug649006.js \
browser_tabview_bug649307.js \
browser_tabview_bug649319.js \
browser_tabview_bug650280.js \
browser_tabview_bug650573.js \
browser_tabview_bug651311.js \
browser_tabview_bug654721.js \

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

@ -1,15 +1,16 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource:///modules/tabview/AllTabs.jsm");
function test() {
waitForExplicitFinish();
let AllTabs;
let newTab = gBrowser.addTab();
// TabPinned
let pinned = function(tab) {
let pinned = function (event) {
let tab = event.target;
is(tab, newTab, "The tabs are the same after the tab is pinned");
ok(tab.pinned, "The tab gets pinned");
@ -17,7 +18,9 @@ function test() {
};
// TabUnpinned
let unpinned = function(tab) {
let unpinned = function (event) {
let tab = event.target;
AllTabs.unregister("pinned", pinned);
AllTabs.unregister("unpinned", unpinned);
@ -26,13 +29,17 @@ function test() {
// clean up and finish
gBrowser.removeTab(tab);
finish();
hideTabView(finish);
};
showTabView(function () {
AllTabs = TabView.getContentWindow().AllTabs;
AllTabs.register("pinned", pinned);
AllTabs.register("unpinned", unpinned);
ok(!newTab.pinned, "The tab is not pinned");
gBrowser.pinTab(newTab);
});
}

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

@ -22,7 +22,7 @@ function setupOne(win) {
afterAllTabsLoaded(function () setupTwo(win), win);
}
let restoreWin;
let restoredWin;
function setupTwo(win) {
let contentWindow = win.TabView.getContentWindow();
@ -37,26 +37,20 @@ function setupTwo(win) {
contentWindow.TabItems.update(tabItem.tab);
tabItem.addSubscriber("savedCachedImageData", function onSaved(item) {
item.removeSubscriber("savedCachedImageData", onSaved);
--numTabsToSave;
if (!--numTabsToSave)
restoreWindow();
});
});
// after the window is closed, restore it.
let xulWindowDestory = function() {
Services.obs.removeObserver(
xulWindowDestory, "xul-window-destroyed", false);
// "xul-window-destroyed" is just fired just before a XUL window is
// destroyed so restore window and test it after a delay
let restoreWindow = function() {
executeSoon(function() {
restoredWin = undoCloseWindow();
restoredWin.addEventListener("load", function onLoad(event) {
restoredWin.removeEventListener("load", onLoad, false);
registerCleanupFunction(function() restoredWin.close());
// ensure that closed tabs have been saved
is(numTabsToSave, 0, "All tabs were saved when window was closed.");
is(restoredWin.gBrowser.tabs.length, 3, "The total number of tabs is 3");
// setup tab variables and listen to the tabs load progress
@ -103,7 +97,6 @@ function setupTwo(win) {
}, false);
});
};
Services.obs.addObserver(xulWindowDestory, "xul-window-destroyed", false);
win.close();
}

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

@ -10,7 +10,7 @@ function test() {
function part1(win) {
registerCleanupFunction(function() win.close());
let contentWindow = win.document.getElementById("tab-view").contentWindow;
let contentWindow = win.TabView.getContentWindow();
is(contentWindow.GroupItems.groupItems.length, 1, "Has only one group");
let originalTab = win.gBrowser.selectedTab;
@ -71,15 +71,12 @@ function part2(win) {
// switch the selected tab to new tab
win.gBrowser.selectedTab = newTab;
whenTabViewIsHidden(function () {
is(win.gBrowser.selectedTab, newTab, "The seleted tab should be the same as before (new tab)");
win.close();
finish();
});
// show tabview
EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true }, win);
// hide tabview
EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true }, win);
})
showTabView(function () {
hideTabView(function () {
is(win.gBrowser.selectedTab, newTab,
"The selected tab should be the same as before (new tab)");
waitForFocus(finish);
}, win);
}, win);
}, win);
}

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

@ -21,9 +21,7 @@ function onTabViewShown() {
function testStayOnPage(contentWindow, groupItemOne, groupItemTwo) {
whenDialogOpened(function (dialog) {
groupItemTwo.addSubscriber("groupShown", function onShown() {
groupItemTwo.removeSubscriber("groupShown", onShown);
executeSoon(function () {
is(gBrowser.tabs.length, 2,
"The total number of tab is 2 when staying on the page");
is(contentWindow.TabItems.getItems().length, 2,

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

@ -25,6 +25,7 @@ function test1() {
is(groupItems.length, 1, "there is one groupItem");
whenTabViewIsHidden(function() {
gBrowser.selectedTab = gBrowser.tabs[0];
is(groupItems.length, 2, "there are two groupItems");
closeGroupItem(groupItems[1], finish);
});

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

@ -18,6 +18,6 @@ function test() {
cw.GroupItems.resumeArrange();
ok(groupItem.isStacked(), 'groupItem is now stacked');
closeGroupItem(groupItem, finish);
closeGroupItem(groupItem, function () hideTabView(finish));
});
}

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

@ -34,7 +34,7 @@ function test() {
ok(!document.getElementById("context_openTabInWindow").disabled, "The 'Move to New Window' menu item is enabled");
let newTabTwo = gBrowser.selectedTab;
gBrowser.selected = originalTab;
gBrowser.selectedTab = originalTab;
gBrowser.removeTab(newTabOne);
gBrowser.removeTab(newTabTwo);

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

@ -0,0 +1,127 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* Contributor(s):
* Mihai Sucan <mihai.sucan@gmail.com>
* Raymond Lee <raymond@appcoast.com>
*/
const TEST_URL = 'data:text/html,<script>window.onbeforeunload=' +
'function(e){e.returnValue="?"}</script><body ' +
'onunload="alert(\'onunload\')" onpagehide="' +
'alert(\'onpagehide\')"></body>';
let contentWindow;
let activeGroup;
function test() {
waitForExplicitFinish();
showTabView(function () {
contentWindow = TabView.getContentWindow();
activeGroup = contentWindow.GroupItems.getActiveGroupItem();
gBrowser.browsers[0].contentWindow.location =
"data:text/html,<p>test for bug 626455, tab1";
gBrowser.addTab(TEST_URL);
afterAllTabsLoaded(testStayOnPage);
});
}
function testStayOnPage() {
whenDialogOpened(function (dialog) {
// stay on page
dialog.cancelDialog();
executeSoon(function () {
showTabView(function () {
is(gBrowser.tabs.length, 1,
"The total number of tab is 1 when staying on the page");
let location = gBrowser.browsers[0].contentWindow.location.toString();
isnot(location.indexOf("onbeforeunload"), -1,
"The open tab is the expected one");
is(contentWindow.GroupItems.getActiveGroupItem(), activeGroup,
"Active group is still the same");
is(contentWindow.GroupItems.groupItems.length, 1,
"Only one group is open");
// start the next test
testLeavePage();
});
});
});
closeGroupItem(activeGroup);
}
function testLeavePage() {
let dialogsAccepted = 0;
whenDialogOpened(function onDialogOpened(dialog) {
if (++dialogsAccepted < 3)
whenDialogOpened(onDialogOpened);
// Leave page
dialog.acceptDialog();
});
whenGroupClosed(activeGroup, finishTest);
closeGroupItem(activeGroup);
}
function finishTest() {
is(gBrowser.tabs.length, 1,
"The total number of tab is 1 after leaving the page");
is(contentWindow.TabItems.getItems().length, 1,
"The total number of tab items is 1 after leaving the page");
let location = gBrowser.browsers[0].contentWindow.location.toString();
is(location, "about:blank", "The open tab is the expected one");
isnot(contentWindow.GroupItems.getActiveGroupItem(), activeGroup,
"Active group is no longer the same");
is(contentWindow.GroupItems.groupItems.length, 1,
"Only one group is open");
finish();
}
// ----------
function whenGroupClosed(group, callback) {
group.addSubscriber("close", function onClose() {
group.removeSubscriber("close", onClose);
callback();
});
}
// ----------
function whenDialogOpened(callback) {
let wm = Cc["@mozilla.org/appshell/window-mediator;1"]
.getService(Ci.nsIWindowMediator);
let listener = {
onCloseWindow: function () {},
onWindowTitleChange: function () {},
onOpenWindow: function (xulWin) {
let domWin = xulWin.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
whenWindowLoaded(domWin, function () {
let dialog = domWin.document.querySelector("dialog");
if (dialog) {
wm.removeListener(listener);
callback(dialog);
}
});
}
};
wm.addListener(listener);
}

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

@ -15,7 +15,7 @@ function loadTabs (win) {
function testTopOfStack(win) {
registerCleanupFunction(function () { win.close(); });
let cw = win.TabView.getContentWindow();
groupItem = cw.GroupItems.getActiveGroupItem();
let groupItem = cw.GroupItems.getActiveGroupItem();
ok(!groupItem.isStacked(), 'groupItem is not stacked');
groupItem.setSize(150, 150);
groupItem.setUserSize();

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

@ -0,0 +1,67 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
let pb = Cc["@mozilla.org/privatebrowsing;1"].
getService(Ci.nsIPrivateBrowsingService);
function test() {
let cw;
registerCleanupFunction(function() {
if (cw)
cw.hideSearch();
TabView.hide();
pb.privateBrowsingEnabled = false;
});
let enableSearch = function (callback) {
if (cw.isSearchEnabled()) {
callback();
return;
}
cw.addEventListener("tabviewsearchenabled", function onSearchEnabled() {
cw.removeEventListener("tabviewsearchenabled", onSearchEnabled, false);
executeSoon(callback);
}, false);
cw.ensureSearchShown();
};
let getSearchboxValue = function () {
return cw.iQ("#searchbox").val();
};
let prepareSearchbox = function (callback) {
ok(!cw.isSearchEnabled(), "search is disabled");
enableSearch(function () {
cw.iQ("#searchbox").val("moz");
callback();
});
};
let searchAndSwitchPBMode = function (callback) {
prepareSearchbox(function () {
togglePrivateBrowsing(function () {
showTabView(function () {
ok(!cw.isSearchEnabled(), "search is disabled");
is(getSearchboxValue(), "", "search box is empty");
callback();
});
});
});
};
waitForExplicitFinish();
showTabView(function () {
cw = TabView.getContentWindow();
searchAndSwitchPBMode(function () {
searchAndSwitchPBMode(function () {
hideTabView(finish);
});
});
});
}

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

@ -67,7 +67,7 @@ function test() {
EventUtils.synthesizeMouse(target, 600, 5, {type: "mouseup"}, cw);
checkNumberOfGroupItems(2);
next();
closeGroupItem(cw.GroupItems.groupItems[1], next);
}, win);
}

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

@ -3,49 +3,32 @@
function test() {
waitForExplicitFinish();
window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
TabView.toggle();
showTabView(onTabViewShown);
}
function onTabViewWindowLoaded() {
window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
function onTabViewShown() {
ok(TabView.isVisible(), "Tab View is visible");
let contentWindow = document.getElementById("tab-view").contentWindow;
let contentWindow = TabView.getContentWindow();
let [originalTab] = gBrowser.visibleTabs;
let createGroupItem = function (left, top, width, height) {
let box = new contentWindow.Rect(left, top, width, height);
let groupItem = new contentWindow.GroupItem([], {bounds: box, immediately: true});
contentWindow.UI.setActive(groupItem);
gBrowser.loadOneTab("about:blank", {inBackground: true});
return groupItem;
};
// create group one and two
let boxOne = new contentWindow.Rect(20, 20, 300, 300);
let groupOne = new contentWindow.GroupItem([], { bounds: boxOne });
ok(groupOne.isEmpty(), "This group is empty");
let groupOne = createGroupItem(20, 20, 300, 300);
let groupTwo = createGroupItem(20, 400, 300, 300);
let boxTwo = new contentWindow.Rect(20, 400, 300, 300);
let groupTwo = new contentWindow.GroupItem([], { bounds: boxTwo });
groupOne.addSubscriber("childAdded", function onChildAdded() {
groupOne.removeSubscriber("childAdded", onChildAdded);
groupTwo.newTab();
});
let count = 0;
let onTabViewShown = function() {
if (count == 2) {
window.removeEventListener("tabviewshown", onTabViewShown, false);
waitForFocus(function () {
addTest(contentWindow, groupOne.id, groupTwo.id, originalTab);
}
};
let onTabViewHidden = function() {
TabView.toggle();
if (++count == 2)
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
};
window.addEventListener("tabviewshown", onTabViewShown, false);
window.addEventListener("tabviewhidden", onTabViewHidden, false);
// open tab in group
groupOne.newTab();
});
}
function addTest(contentWindow, groupOneId, groupTwoId, originalTab) {
@ -75,23 +58,12 @@ function addTest(contentWindow, groupOneId, groupTwoId, originalTab) {
is(groupTwo.getChildren().length, ++groupTwoTabItemCount,
"The number of children in group two is increased by 1");
let onTabViewHidden = function() {
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
groupTwo.closeAll();
// close undo group
let closeButton = groupTwo.$undoContainer.find(".close");
EventUtils.sendMouseEvent(
{ type: "click" }, closeButton[0], contentWindow);
};
groupTwo.addSubscriber("close", function onClose() {
groupTwo.removeSubscriber("close", onClose);
finish();
closeGroupItem(groupOne, function () {
closeGroupItem(groupTwo, function () hideTabView(finish));
});
window.addEventListener("tabviewhidden", onTabViewHidden, false);
gBrowser.selectedTab = originalTab;
}
groupTwo.addSubscriber("childAdded", endGame);
groupTwo.addSubscriber("childAdded", endGame);
simulateDragDrop(tabItem.container, offsetX, offsetY, contentWindow);
}

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

@ -1,15 +1,18 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
let timerId;
let newWin;
// ----------
function test() {
waitForExplicitFinish();
// launch tab view for the first time
newWindowWithTabView(function() {}, function(win) {
let panelSelected = false;
registerCleanupFunction(function () ok(panelSelected, "panel is selected"));
let onLoad = function (win) {
registerCleanupFunction(function () win.close());
newWin = win;
let onSelect = function(event) {
@ -21,27 +24,26 @@ function test() {
return;
deck.removeEventListener("select", onSelect, true);
panelSelected = true;
};
whenTabViewIsShown(function() {
let deck = win.document.getElementById("tab-view-deck");
deck.addEventListener("select", onSelect, true);
};
let onShow = function (win) {
executeSoon(function() {
testMethodToHideAndShowTabView(function() {
newWin.document.getElementById("menu_tabview").doCommand();
}, function() {
testMethodToHideAndShowTabView(function() {
EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true }, newWin);
EventUtils.synthesizeKey("E", { accelKey: true, shiftKey: true }, newWin);
}, finish);
});
});
}, win);
};
let deck = win.document.getElementById("tab-view-deck");
deck.addEventListener("select", onSelect, true);
});
registerCleanupFunction(function () {
newWin.close();
});
newWindowWithTabView(onShow, onLoad);
}
function testMethodToHideAndShowTabView(executeFunc, callback) {

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

@ -49,11 +49,15 @@ function onTabViewLoadedAndShown() {
groupTitles[a] = gi.getTitle();
}
contentWindow.gPrefBranch.setBoolPref("animate_zoom", false);
// Create a second tab
gBrowser.addTab("about:robots");
is(gBrowser.tabs.length, 2, "we now have 2 tabs");
registerCleanupFunction(function() {
gBrowser.removeTab(gBrowser.tabs[1]);
contentWindow.gPrefBranch.clearUserPref("animate_zoom");
});
afterAllTabsLoaded(function() {

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

@ -361,7 +361,10 @@ function togglePrivateBrowsing(callback) {
Services.obs.addObserver(function observe() {
Services.obs.removeObserver(observe, topic);
afterAllTabsLoaded(callback);
// use executeSoon() to let Panorama load its group data from the session
// before we call afterAllTabsLoaded()
executeSoon(function () afterAllTabsLoaded(callback));
}, topic, false);
let pb = Cc["@mozilla.org/privatebrowsing;1"].

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

@ -53,6 +53,7 @@ browser.jar:
content/browser/tabview.css (content/tabview/tabview.css)
* content/browser/tabview.js (content/tabview/tabview.js)
content/browser/tabview.html (content/tabview/tabview.html)
content/browser/tabview-content.js (content/tabview/content.js)
* content/browser/urlbarBindings.xml (content/urlbarBindings.xml)
* content/browser/utilityOverlay.js (content/utilityOverlay.js)
* content/browser/web-panels.js (content/web-panels.js)

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

@ -256,7 +256,8 @@ FeedWriter.prototype = {
__contentSandbox: null,
get _contentSandbox() {
if (!this.__contentSandbox)
this.__contentSandbox = new Cu.Sandbox(this._window);
this.__contentSandbox = new Cu.Sandbox(this._window,
{sandboxName: 'FeedWriter'});
return this.__contentSandbox;
},

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

@ -619,11 +619,9 @@ PrivateBrowsingService.prototype = {
}
// Plugin data
let (ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost)) {
const phInterface = Ci.nsIPluginHost;
const FLAG_CLEAR_ALL = phInterface.FLAG_CLEAR_ALL;
ph.QueryInterface(phInterface);
let (ph = Cc["@mozilla.org/plugin/host;1"].getService(phInterface)) {
let tags = ph.getPluginTags();
for (let i = 0; i < tags.length; i++) {
try {

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

@ -59,7 +59,7 @@ window.onload = function() {
gStateObject = JSON.parse(sessionData.value);
}
catch (exJSON) {
var s = new Cu.Sandbox("about:blank");
var s = new Cu.Sandbox("about:blank", {sandboxName: 'aboutSessionRestore'});
gStateObject = Cu.evalInSandbox("(" + sessionData.value + ")", s);
// If we couldn't parse the string with JSON.parse originally, make sure
// that the value in the textbox will be parsable.

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

@ -135,7 +135,7 @@ SessionStartup.prototype = {
this._initialState = JSON.parse(iniString);
}
catch (exJSON) {
var s = new Cu.Sandbox("about:blank");
var s = new Cu.Sandbox("about:blank", {sandboxName: 'nsSessionStartup'});
this._initialState = Cu.evalInSandbox("(" + iniString + ")", s);
}

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

@ -785,7 +785,7 @@ SessionStoreService.prototype = {
aWindow.__SSi = "window" + Date.now();
// and create its data object
this._windows[aWindow.__SSi] = { tabs: [], selected: 0, _closedTabs: [] };
this._windows[aWindow.__SSi] = { tabs: [], selected: 0, _closedTabs: [], busy: false };
if (!this._isWindowLoaded(aWindow))
this._windows[aWindow.__SSi]._restoring = true;
if (!aWindow.toolbar.visible)
@ -969,6 +969,9 @@ SessionStoreService.prototype = {
// save the window if it has multiple tabs or a single saveable tab
if (winData.tabs.length > 1 ||
(winData.tabs.length == 1 && this._shouldSaveTabState(winData.tabs[0]))) {
// we don't want to save the busy state
delete winData.busy;
this._closedWindows.unshift(winData);
this._capClosedWindows();
}
@ -1265,7 +1268,7 @@ SessionStoreService.prototype = {
throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
var window = aTab.ownerDocument.defaultView;
this._sendWindowStateEvent(window, "Busy");
this._setWindowStateBusy(window);
this.restoreHistoryPrecursor(window, [aTab], [tabState], 0, 0, 0);
},
@ -1281,7 +1284,7 @@ SessionStoreService.prototype = {
tabState.index = Math.max(1, Math.min(tabState.index, tabState.entries.length));
tabState.pinned = false;
this._sendWindowStateEvent(aWindow, "Busy");
this._setWindowStateBusy(aWindow);
let newTab = aTab == aWindow.gBrowser.selectedTab ?
aWindow.gBrowser.addTab(null, {relatedToCurrent: true, ownerTab: aTab}) :
aWindow.gBrowser.addTab();
@ -1324,7 +1327,7 @@ SessionStoreService.prototype = {
let closedTab = closedTabs.splice(aIndex, 1).shift();
let closedTabState = closedTab.state;
this._sendWindowStateEvent(aWindow, "Busy");
this._setWindowStateBusy(aWindow);
// create a new tab
let browser = aWindow.gBrowser;
let tab = browser.addTab();
@ -2534,7 +2537,7 @@ SessionStoreService.prototype = {
// We're not returning from this before we end up calling restoreHistoryPrecursor
// for this window, so make sure we send the SSWindowStateBusy event.
this._sendWindowStateEvent(aWindow, "Busy");
this._setWindowStateBusy(aWindow);
if (root._closedWindows)
this._closedWindows = root._closedWindows;
@ -2721,7 +2724,7 @@ SessionStoreService.prototype = {
if (aTabs.length == 0) {
// this is normally done in restoreHistory() but as we're returning early
// here we need to take care of it.
this._sendWindowStateEvent(aWindow, "Ready");
this._setWindowStateReady(aWindow);
return;
}
@ -2866,7 +2869,7 @@ SessionStoreService.prototype = {
if (aTabs.length == 0) {
// At this point we're essentially ready for consumers to read/write data
// via the sessionstore API so we'll send the SSWindowStateReady event.
this._sendWindowStateEvent(aWindow, "Ready");
this._setWindowStateReady(aWindow);
return; // no more tabs to restore
}
@ -4011,6 +4014,42 @@ SessionStoreService.prototype = {
this._restoreCount = -1;
},
/**
* Set the given window's busy state
* @param aWindow the window
* @param aValue the window's busy state
*/
_setWindowStateBusyValue:
function sss__changeWindowStateBusyValue(aWindow, aValue) {
this._windows[aWindow.__SSi].busy = aValue;
// Keep the to-be-restored state in sync because that is returned by
// getWindowState() as long as the window isn't loaded, yet.
if (!this._isWindowLoaded(aWindow)) {
let stateToRestore = this._statesToRestore[aWindow.__SS_restoreID].windows[0];
stateToRestore.busy = aValue;
}
},
/**
* Set the given window's state to 'not busy'.
* @param aWindow the window
*/
_setWindowStateReady: function sss__setWindowStateReady(aWindow) {
this._setWindowStateBusyValue(aWindow, false);
this._sendWindowStateEvent(aWindow, "Ready");
},
/**
* Set the given window's state to 'busy'.
* @param aWindow the window
*/
_setWindowStateBusy: function sss__setWindowStateBusy(aWindow) {
this._setWindowStateBusyValue(aWindow, true);
this._sendWindowStateEvent(aWindow, "Busy");
},
/**
* Dispatch an SSWindowState_____ event for the given window.
* @param aWindow the window

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

@ -151,6 +151,7 @@ _BROWSER_TEST_FILES = \
browser_636279.js \
browser_645428.js \
browser_659591.js \
browser_662812.js \
$(NULL)
ifneq ($(OS_ARCH),Darwin)

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

@ -4,8 +4,6 @@
const TAB_STATE_NEEDS_RESTORE = 1;
const TAB_STATE_RESTORING = 2;
let stateBackup = ss.getBrowserState();
let state = {windows:[{tabs:[
{entries:[{url:"http://example.com#1"}]},
{entries:[{url:"http://example.com#2"}]},
@ -22,20 +20,12 @@ function test() {
registerCleanupFunction(function () {
Services.prefs.clearUserPref("browser.sessionstore.restore_hidden_tabs");
TabsProgressListener.uninit();
ss.setBrowserState(stateBackup);
});
TabsProgressListener.init();
// First stage: restoreHiddenTabs = true
// Second stage: restoreHiddenTabs = false
test_loadTabs(true, function () {
test_loadTabs(false, function () {
waitForFocus(finish);
});
test_loadTabs(false, finish);
});
}
@ -43,10 +33,9 @@ function test_loadTabs(restoreHiddenTabs, callback) {
Services.prefs.setBoolPref("browser.sessionstore.restore_hidden_tabs", restoreHiddenTabs);
let expectedTabs = restoreHiddenTabs ? 8 : 4;
let firstProgress = true;
TabsProgressListener.setCallback(function (needsRestore, isRestoring) {
newWindowWithState(state, function (win, needsRestore, isRestoring) {
if (firstProgress) {
firstProgress = false;
is(isRestoring, 3, "restoring 3 tabs concurrently");
@ -54,60 +43,75 @@ function test_loadTabs(restoreHiddenTabs, callback) {
ok(isRestoring < 4, "restoring max. 3 tabs concurrently");
}
if (gBrowser.tabs.length - needsRestore == expectedTabs) {
TabsProgressListener.unsetCallback();
is(gBrowser.visibleTabs.length, 4, "only 4 visible tabs");
if (win.gBrowser.tabs.length - needsRestore == expectedTabs) {
is(win.gBrowser.visibleTabs.length, 4, "only 4 visible tabs");
TabsProgressListener.uninit();
callback();
}
});
ss.setBrowserState(JSON.stringify(state));
}
function countTabs() {
let needsRestore = 0, isRestoring = 0;
let windowsEnum = Services.wm.getEnumerator("navigator:browser");
while (windowsEnum.hasMoreElements()) {
let window = windowsEnum.getNext();
if (window.closed)
continue;
for (let i = 0; i < window.gBrowser.tabs.length; i++) {
let browser = window.gBrowser.tabs[i].linkedBrowser;
if (browser.__SS_restoreState == TAB_STATE_RESTORING)
isRestoring++;
else if (browser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE)
needsRestore++;
}
}
return [needsRestore, isRestoring];
}
let TabsProgressListener = {
init: function () {
gBrowser.addTabsProgressListener(this);
init: function (win) {
this.window = win;
this.window.gBrowser.addTabsProgressListener(this);
},
uninit: function () {
this.unsetCallback();
gBrowser.removeTabsProgressListener(this);
this.window.gBrowser.removeTabsProgressListener(this);
delete this.window;
delete this.callback;
},
setCallback: function (callback) {
this.callback = callback;
},
unsetCallback: function () {
delete this.callback;
},
onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
if (this.callback && aBrowser.__SS_restoreState == TAB_STATE_RESTORING &&
aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK &&
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW)
this.callback.apply(null, countTabs());
this.callback.apply(null, [this.window].concat(this.countTabs()));
},
countTabs: function () {
let needsRestore = 0, isRestoring = 0;
for (let i = 0; i < this.window.gBrowser.tabs.length; i++) {
let browser = this.window.gBrowser.tabs[i].linkedBrowser;
if (browser.__SS_restoreState == TAB_STATE_RESTORING)
isRestoring++;
else if (browser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE)
needsRestore++;
}
return [needsRestore, isRestoring];
}
}
// ----------
function whenWindowLoaded(win, callback) {
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad, false);
executeSoon(callback);
}, false);
}
// ----------
function newWindowWithState(state, callback) {
let opts = "chrome,all,dialog=no,height=800,width=800";
let win = window.openDialog(getBrowserURL(), "_blank", opts);
registerCleanupFunction(function () win.close());
whenWindowLoaded(win, function () {
TabsProgressListener.init(win);
TabsProgressListener.setCallback(callback);
ss.setWindowState(win, JSON.stringify(state), true);
});
}

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

@ -0,0 +1,34 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
waitForExplicitFinish();
window.addEventListener("SSWindowStateBusy", function onBusy() {
window.removeEventListener("SSWindowStateBusy", onBusy, false);
let state = JSON.parse(ss.getWindowState(window));
ok(state.windows[0].busy, "window is busy");
window.addEventListener("SSWindowStateReady", function onReady() {
window.removeEventListener("SSWindowStateReady", onReady, false);
let state = JSON.parse(ss.getWindowState(window));
ok(!state.windows[0].busy, "window is not busy");
gBrowser.removeTab(gBrowser.tabs[1]);
executeSoon(finish);
}, false);
}, false);
// create a new tab
let tab = gBrowser.addTab("about:mozilla");
let browser = tab.linkedBrowser;
// close and restore it
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
gBrowser.removeTab(tab);
ss.undoCloseTab(window, 0);
}, true);
}

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

@ -178,7 +178,8 @@ var Scratchpad = {
this._previousLocation != this.gBrowser.contentWindow.location.href) {
let contentWindow = this.gBrowser.selectedBrowser.contentWindow;
this._contentSandbox = new Cu.Sandbox(contentWindow,
{ sandboxPrototype: contentWindow, wantXrays: false });
{ sandboxPrototype: contentWindow, wantXrays: false,
sandboxName: 'scratchpad-content'});
this._previousBrowserWindow = this.browserWindow;
this._previousBrowser = this.gBrowser.selectedBrowser;
@ -211,7 +212,8 @@ var Scratchpad = {
if (!this._chromeSandbox ||
this.browserWindow != this._previousBrowserWindow) {
this._chromeSandbox = new Cu.Sandbox(this.browserWindow,
{ sandboxPrototype: this.browserWindow, wantXrays: false });
{ sandboxPrototype: this.browserWindow, wantXrays: false,
sandboxName: 'scratchpad-chrome'});
this._previousBrowserWindow = this.browserWindow;
}

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

@ -603,18 +603,37 @@ toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button {
#forward-button {
list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=toolbar");
-moz-transition: 250ms ease-out;
}
#forward-button[disabled="true"] {
list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=toolbar&state=disabled");
}
#forward-button:-moz-locale-dir(rtl) {
list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=toolbar");
}
#forward-button[disabled="true"]:-moz-locale-dir(rtl) {
toolbar:not([mode=icons]) #forward-button[disabled="true"] {
list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=toolbar&state=disabled");
}
toolbar:not([mode=icons]) #forward-button[disabled="true"]:-moz-locale-dir(rtl) {
list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=toolbar&state=disabled");
}
toolbar[mode=icons] #forward-button[disabled="true"] {
-moz-transform: scale(0);
opacity: 0;
pointer-events: none;
}
toolbar[mode=icons] #forward-button[disabled="true"]:-moz-locale-dir(ltr) {
margin-left: -36px;
}
toolbar[mode=icons] #forward-button[disabled="true"]:-moz-locale-dir(rtl) {
margin-right: -36px;
}
toolbar[mode=icons][iconsize=small] #forward-button[disabled="true"]:-moz-locale-dir(ltr) {
margin-left: -28px;
}
toolbar[mode=icons][iconsize=small] #forward-button[disabled="true"]:-moz-locale-dir(rtl) {
margin-right: -28px;
}
#reload-button {
list-style-image: url("moz-icon://stock/gtk-refresh?size=toolbar");
}
@ -786,7 +805,7 @@ toolbar[iconsize="small"] #forward-button {
.unified-nav-forward[_moz-menuactive] {
list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=menu") !important;
}
toolbar[iconsize="small"] #forward-button[disabled="true"] {
toolbar[iconsize="small"]:not([mode=icons]) #forward-button[disabled="true"] {
list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=menu&state=disabled");
}
@ -796,7 +815,7 @@ toolbar[iconsize="small"] #forward-button:-moz-locale-dir(rtl) {
.unified-nav-forward[_moz-menuactive]:-moz-locale-dir(rtl) {
list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=menu") !important;
}
toolbar[iconsize="small"] #forward-button[disabled="true"]:-moz-locale-dir(rtl) {
toolbar[iconsize="small"]:not([mode=icons]) #forward-button[disabled="true"]:-moz-locale-dir(rtl) {
list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=menu&state=disabled");
}

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

@ -5,12 +5,17 @@ import os
class DeviceManagerADB(DeviceManager):
def __init__(self, host = None, port = 20701, retrylimit = 5, packageName = "org.mozilla.fennec_unofficial"):
def __init__(self, host = None, port = 20701, retrylimit = 5, packageName = None):
self.host = host
self.port = port
self.retrylimit = retrylimit
self.retries = 0
self._sock = None
if packageName == None:
if os.getenv('USER'):
packageName = 'org.mozilla.fennec_' + os.getenv('USER')
else:
packageName = 'org.mozilla.fennec_'
self.Init(packageName)
def Init(self, packageName):
@ -27,7 +32,11 @@ class DeviceManagerADB(DeviceManager):
self.tmpDir = None
try:
# a test to see if we have root privs
self.checkCmd(["shell", "ls", "/sbin"])
files = self.listFiles("/data/data")
if (len(files) == 1):
if (files[0].find("Permission denied") != -1):
print "NOT running as root"
raise Exception("not running as root")
except:
try:
self.checkCmd(["root"])
@ -98,7 +107,7 @@ class DeviceManagerADB(DeviceManager):
try:
if (not self.dirExists(remoteDir)):
self.mkDirs(remoteDir+"/x")
for root, dirs, files in os.walk(localDir):
for root, dirs, files in os.walk(localDir, followlinks='true'):
relRoot = os.path.relpath(root, localDir)
for file in files:
localFile = os.path.join(root, file)
@ -134,8 +143,12 @@ class DeviceManagerADB(DeviceManager):
# success: True
# failure: False
def fileExists(self, filepath):
self.checkCmd(["shell", "ls", filepath])
p = self.runCmd(["shell", "ls", "-a", filepath])
data = p.stdout.readlines()
if (len(data) == 1):
if (data[0].rstrip() == filepath):
return True
return False
def removeFile(self, filename):
return self.runCmd(["shell", "rm", filename]).stdout.read()
@ -381,18 +394,11 @@ class DeviceManagerADB(DeviceManager):
return devroot + '/fennec'
elif (self.dirExists(devroot + '/firefox')):
return devroot + '/firefox'
elif (self.dirExists('/data/data/org.mozilla.fennec')):
return '/data/data/org.mozilla.fennec'
elif (self.dirExists('/data/data/org.mozilla.firefox')):
return '/data/data/org.mozilla.firefox'
elif (self.dirExists('/data/data/org.mozilla.fennec_unofficial')):
return '/data/data/org.mozilla.fennec_unofficial'
elif (self.dirExists('/data/data/org.mozilla.fennec_aurora')):
return '/data/data/org.mozilla.fennec_aurora'
elif (self.dirExists('/data/data/org.mozilla.firefox_beta')):
return '/data/data/org.mozilla.firefox_beta'
elif (self.packageName and self.dirExists('/data/data/' + self.packageName)):
return '/data/data/' + self.packageName
# Failure (either not installed or not a recognized platform)
print "devicemanagerADB: getAppRoot failed"
return None
# Gets the directory location on the device for a specific test type

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

@ -43,7 +43,6 @@ USE_AUTOCONF = 1
MOZILLA_CLIENT = 1
target = @target@
ac_configure_args = @ac_configure_args@
BUILD_MODULES = @BUILD_MODULES@
MOZILLA_VERSION = @MOZILLA_VERSION@
FIREFOX_VERSION = @FIREFOX_VERSION@

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

@ -41,6 +41,38 @@ static BOOL sh_DoCopy(wchar_t *srcFileName, DWORD srcFileAttributes,
#define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
#define STR_LEN(a) (ARRAY_LEN(a) - 1)
#ifdef __MINGW32__
/* MingW currently does not implement a wide version of the
startup routines. Workaround is to implement something like
it ourselves. */
#include <shellapi.h>
int wmain(int argc, WCHAR **argv);
int main(int argc, char **argv)
{
int result;
wchar_t *commandLine = GetCommandLineW();
int argcw = 0;
wchar_t **_argvw = CommandLineToArgvW( commandLine, &argcw );
wchar_t *argvw[argcw + 1];
int i;
if (!_argvw)
return 127;
/* CommandLineToArgvW doesn't output the ending NULL so
we have to manually add it on */
for ( i = 0; i < argcw; i++ )
argvw[i] = _argvw[i];
argvw[argcw] = NULL;
result = wmain(argcw, argvw);
LocalFree(_argvw);
return result;
}
#endif /* __MINGW32__ */
/* changes all forward slashes in token to backslashes */
void changeForwardSlashesToBackSlashes ( wchar_t *arg )
{

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

@ -153,6 +153,20 @@ xpcshell-tests:
$(LIBXUL_DIST)/bin/xpcshell \
$(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
xpcshell-tests-remote: DM_TRANS?=adb
xpcshell-tests-remote:
$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
-I$(topsrcdir)/build \
-I$(topsrcdir)/build/mobile \
$(topsrcdir)/testing/xpcshell/remotexpcshelltests.py \
--symbols-path=$(DIST)/crashreporter-symbols \
--build-info-json=$(DEPTH)/mozinfo.json \
$(EXTRA_TEST_ARGS) \
--dm_trans=$(DM_TRANS) \
--deviceIP=${TEST_DEVICE} \
--objdir=$(DEPTH) \
$(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
# Execute a single test, specified in $(SOLO_FILE), but don't automatically
# start the test. Instead, present the xpcshell prompt so the user can
# attach a debugger and then start the test.
@ -182,6 +196,23 @@ check-one:
$(LIBXUL_DIST)/bin/xpcshell \
$(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
check-one-remote: DM_TRANS?=adb
check-one-remote:
$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
-I$(topsrcdir)/build \
-I$(topsrcdir)/build/mobile \
$(testxpcsrcdir)/remotexpcshelltests.py \
--symbols-path=$(DIST)/crashreporter-symbols \
--build-info-json=$(DEPTH)/mozinfo.json \
--test-path=$(SOLO_FILE) \
--profile-name=$(MOZ_APP_NAME) \
--verbose \
$(EXTRA_TEST_ARGS) \
--dm_trans=$(DM_TRANS) \
--deviceIP=${TEST_DEVICE} \
--objdir=$(DEPTH) \
--noSetup \
$(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
endif # XPCSHELL_TESTS
ifdef CPP_UNIT_TESTS
@ -1122,8 +1153,9 @@ ifdef HAVE_DTRACE
ifndef XP_MACOSX
ifdef DTRACE_PROBE_OBJ
ifndef DTRACE_LIB_DEPENDENT
$(DTRACE_PROBE_OBJ):
dtrace -G -C -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ)
NON_DTRACE_OBJS := $(filter-out $(DTRACE_PROBE_OBJ),$(OBJS))
$(DTRACE_PROBE_OBJ): $(NON_DTRACE_OBJS)
dtrace -G -C -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ) $(NON_DTRACE_OBJS)
endif
endif
endif
@ -1519,9 +1551,6 @@ export:: FORCE
@echo; sleep 2; false
endif
$(IDL_DIR)::
$(NSINSTALL) -D $@
# generate .h files from into $(XPIDL_GEN_DIR), then export to $(DIST)/include;
# warn against overriding existing .h file.
$(XPIDL_GEN_DIR)/.done:
@ -1592,14 +1621,8 @@ endif # XPIDLSRCS
#
# General rules for exporting idl files.
#
# WORK-AROUND ONLY, for mozilla/tools/module-deps/bootstrap.pl build.
# Bug to fix idl dependency problems w/o this extra build pass is
# http://bugzilla.mozilla.org/show_bug.cgi?id=145777
#
$(IDL_DIR)::
$(IDL_DIR):
$(NSINSTALL) -D $@
export-idl:: $(SUBMAKEFILES) $(MAKE_DIRS)
@ -2066,7 +2089,6 @@ showhost:
@echo "HOST_LIBRARY = $(HOST_LIBRARY)"
showbuildmods::
@echo "Build Modules = $(BUILD_MODULES)"
@echo "Module dirs = $(BUILD_MODULE_DIRS)"
documentation:

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

@ -970,7 +970,6 @@ if test -n "$_WIN32_MSVC"; then
AC_DEFINE(HAVE_IO_H)
AC_DEFINE(HAVE_SETBUF)
AC_DEFINE(HAVE_ISATTY)
AC_DEFINE(HAVE_STDCALL)
fi
fi # COMPILE_ENVIRONMENT
@ -2482,6 +2481,8 @@ ia64*-hpux*)
if test -n "$GNU_CC"; then
CFLAGS="$CFLAGS -mstackrealign"
CXXFLAGS="$CXXFLAGS -mstackrealign"
else
AC_DEFINE(HAVE_STDCALL)
fi
MOZ_CHECK_HEADERS(mmintrin.h)

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

@ -6125,7 +6125,7 @@ nsDocument::AdoptNode(nsIDOMNode *aAdoptedNode, nsIDOMNode **aResult)
} while ((doc = doc->GetParentDocument()));
// Remove from parent.
nsINode* parent = adoptedNode->GetNodeParent();
nsCOMPtr<nsINode> parent = adoptedNode->GetNodeParent();
if (parent) {
rv = parent->RemoveChildAt(parent->IndexOf(adoptedNode), PR_TRUE);
NS_ENSURE_SUCCESS(rv, rv);

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

@ -620,7 +620,7 @@ nsINode::Normalize()
}
// Remove node
nsINode* parent = node->GetNodeParent();
nsCOMPtr<nsINode> parent = node->GetNodeParent();
NS_ASSERTION(parent || hasRemoveListeners,
"Should always have a parent unless "
"mutation events messed us up");
@ -3945,7 +3945,7 @@ nsINode::ReplaceOrInsertBefore(PRBool aReplace, nsINode* aNewChild,
}
// Remove the new child from the old parent if one exists
nsINode* oldParent = newContent->GetNodeParent();
nsCOMPtr<nsINode> oldParent = newContent->GetNodeParent();
if (oldParent) {
PRInt32 removeIndex = oldParent->IndexOf(newContent);
if (removeIndex < 0) {

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

@ -2510,12 +2510,12 @@ nsHTMLInputElement::SanitizeValue(nsAString& aValue)
case NS_FORM_INPUT_SEARCH:
case NS_FORM_INPUT_TEL:
case NS_FORM_INPUT_PASSWORD:
case NS_FORM_INPUT_EMAIL:
{
PRUnichar crlf[] = { PRUnichar('\r'), PRUnichar('\n'), 0 };
aValue.StripChars(crlf);
}
break;
case NS_FORM_INPUT_EMAIL:
case NS_FORM_INPUT_URL:
{
PRUnichar crlf[] = { PRUnichar('\r'), PRUnichar('\n'), 0 };

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

@ -75,8 +75,12 @@ var email = document.forms[0].elements[0];
var values = [
[ '', true ], // The empty string shouldn't be considered as invalid.
[ 'foo@bar.com', true ],
[ ' foo@bar.com', false ],
[ 'foo@bar.com ', false ],
[ ' foo@bar.com', true ],
[ 'foo@bar.com ', true ],
[ '\r\n foo@bar.com', true ],
[ 'foo@bar.com \n\r', true ],
[ '\n\n \r\rfoo@bar.com\n\n \r\r', true ],
[ '\n\r \n\rfoo@bar.com\n\r \n\r', true ],
[ 'tulip', false ],
// Some checks on the user part of the address.
[ '@bar.com', false ],
@ -163,7 +167,7 @@ values.push(["foo@bar.com" + legalCharacters, true]);
// Add domain illegal characters.
illegalCharacters = "()<>[]:;@\\,!#$%&'*+/=?^_`{|}~ \t";
for each (c in illegalCharacters) {
values.push(['foo@foo.bar' + c, false]);
values.push(['foo@foo.ba' + c + 'r', false]);
}
values.forEach(function([value, valid]) {

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

@ -47,9 +47,9 @@ function sanitizeValue(aType, aValue)
case "password":
case "search":
case "tel":
case "email":
return aValue.replace(/[\n\r]/g, "");
case "url":
case "email":
return aValue.replace(/[\n\r]/g, "").replace(/^\s+|\s+$/g, "");
case "date":
case "month":

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

@ -32,7 +32,6 @@ function seekStarted(evt) {
function seekEnded(evt) {
var v = evt.target;
v._gotSeekEnded = true;
v.play();
}
function loadedData(evt) {

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

@ -146,8 +146,14 @@ nsSMILCSSProperty::GetBaseValue() const
// (4) Populate our nsSMILValue from the computed style
if (didGetComputedVal) {
// When we parse animation values we check if they are context-sensitive or
// not so that we don't cache animation values whose meaning may change.
// For base values however this is unnecessary since on each sample the
// compositor will fetch the (computed) base value and compare it against
// the cached (computed) value and detect changes for us.
nsSMILCSSValueType::ValueFromString(mPropID, mElement,
computedStyleVal, baseValue);
computedStyleVal, baseValue,
nsnull);
}
return baseValue;
}
@ -160,22 +166,17 @@ nsSMILCSSProperty::ValueFromString(const nsAString& aStr,
{
NS_ENSURE_TRUE(IsPropertyAnimatable(mPropID), NS_ERROR_FAILURE);
nsSMILCSSValueType::ValueFromString(mPropID, mElement, aStr, aValue);
if (aValue.IsNull()) {
return NS_ERROR_FAILURE;
nsSMILCSSValueType::ValueFromString(mPropID, mElement, aStr, aValue,
&aPreventCachingOfSandwich);
// XXX Due to bug 536660 (or at least that seems to be the most likely
// culprit), when we have animation setting display:none on a <use> element,
// if we DON'T set the property every sample, chaos ensues.
if (!aPreventCachingOfSandwich && mPropID == eCSSProperty_display) {
aPreventCachingOfSandwich = PR_TRUE;
}
// XXXdholbert: For simplicity, just assume that all CSS values have to
// reparsed every sample. This prevents us from doing the "nothing's changed
// so don't recompose" optimization (bug 533291) for CSS properties & mapped
// attributes. If it ends up being expensive to always recompose those, we
// can be a little smarter here. We really only need to set
// aPreventCachingOfSandwich to true for "inherit" & "currentColor" (whose
// values could change at any time), for length-valued types (particularly
// those with em/ex/percent units, since their conversion ratios can change
// at any time), and for any value for 'font-family'.
aPreventCachingOfSandwich = PR_TRUE;
return NS_OK;
return aValue.IsNull() ? NS_ERROR_FAILURE : NS_OK;
}
nsresult

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

@ -371,7 +371,8 @@ ValueFromStringHelper(nsCSSProperty aPropID,
Element* aTargetElement,
nsPresContext* aPresContext,
const nsAString& aString,
nsStyleAnimation::Value& aStyleAnimValue)
nsStyleAnimation::Value& aStyleAnimValue,
PRBool* aIsContextSensitive)
{
// If value is negative, we'll strip off the "-" so the CSS parser won't
// barf, and then manually make the parsed value negative.
@ -386,7 +387,8 @@ ValueFromStringHelper(nsCSSProperty aPropID,
}
nsDependentSubstring subString(aString, subStringBegin);
if (!nsStyleAnimation::ComputeValue(aPropID, aTargetElement, subString,
PR_TRUE, aStyleAnimValue)) {
PR_TRUE, aStyleAnimValue,
aIsContextSensitive)) {
return PR_FALSE;
}
if (isNegative) {
@ -409,7 +411,8 @@ void
nsSMILCSSValueType::ValueFromString(nsCSSProperty aPropID,
Element* aTargetElement,
const nsAString& aString,
nsSMILValue& aValue)
nsSMILValue& aValue,
PRBool* aIsContextSensitive)
{
NS_ABORT_IF_FALSE(aValue.IsNull(), "Outparam should be null-typed");
nsPresContext* presContext = GetPresContextForElement(aTargetElement);
@ -420,7 +423,7 @@ nsSMILCSSValueType::ValueFromString(nsCSSProperty aPropID,
nsStyleAnimation::Value parsedValue;
if (ValueFromStringHelper(aPropID, aTargetElement, presContext,
aString, parsedValue)) {
aString, parsedValue, aIsContextSensitive)) {
sSingleton.Init(aValue);
aValue.mU.mPtr = new ValueWrapper(aPropID, parsedValue, presContext);
}

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

@ -100,13 +100,20 @@ public:
* @param aString The string to be parsed as a CSS value.
* @param [out] aValue The nsSMILValue to be populated. Should
* initially be null-typed.
* @param [out] aIsContextSensitive Set to PR_TRUE if |aString| may produce
* a different |aValue| depending on other
* CSS properties on |aTargetElement|
* or its ancestors (e.g. 'inherit).
* PR_FALSE otherwise. May be nsnull.
* Not set if the method fails.
* @pre aValue.IsNull()
* @post aValue.IsNull() || aValue.mType == nsSMILCSSValueType::sSingleton
*/
static void ValueFromString(nsCSSProperty aPropID,
Element* aTargetElement,
const nsAString& aString,
nsSMILValue& aValue);
nsSMILValue& aValue,
PRBool* aIsContextSensitive);
/**
* Creates a string representation of the given nsSMILValue.

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

@ -67,15 +67,9 @@ nsSMILMappedAttribute::ValueFromString(const nsAString& aStr,
{
NS_ENSURE_TRUE(IsPropertyAnimatable(mPropID), NS_ERROR_FAILURE);
nsSMILCSSValueType::ValueFromString(mPropID, mElement, aStr, aValue);
if (aValue.IsNull()) {
return NS_ERROR_FAILURE;
}
// XXXdholbert: For simplicity, just assume that all CSS values have to
// reparsed every sample. See note in nsSMILCSSProperty::ValueFromString.
aPreventCachingOfSandwich = PR_TRUE;
return NS_OK;
nsSMILCSSValueType::ValueFromString(mPropID, mElement, aStr, aValue,
&aPreventCachingOfSandwich);
return aValue.IsNull() ? NS_ERROR_FAILURE : NS_OK;
}
nsSMILValue
@ -87,8 +81,12 @@ nsSMILMappedAttribute::GetBaseValue() const
baseStringValue);
nsSMILValue baseValue;
if (success) {
// For base values, we don't need to worry whether the value returned is
// context-sensitive or not since the compositor will take care of comparing
// the returned (computed) base value and its cached value and determining
// if an update is required or not.
nsSMILCSSValueType::ValueFromString(mPropID, mElement,
baseStringValue, baseValue);
baseStringValue, baseValue, nsnull);
} else {
// Attribute is unset -- use computed value.
// FIRST: Temporarily clear animated value, to make sure it doesn't pollute

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

@ -8,7 +8,10 @@
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=533291">Mozilla Bug 533291</a>
<p id="display"></p>
<div id="content" style="display: none">
<!-- Bug 628848: The following should be display: none but we currently don't
handle percentage lengths properly when the whole fragment is display: none
-->
<div id="content" style="visibility: hidden">
<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="120px" height="120px"
onload="this.pauseAnimations()">
<g id="circleParent">
@ -19,68 +22,99 @@
<pre id="test">
<script class="testbody" type="text/javascript">
<![CDATA[
/** Test for SMIL fill modes **/
/** Test for SMIL values that are context-sensitive **/
/* See bugs 533291 and 562815.
The format of each test is basically:
1) create some animated and frozen state
2) test the animated values
3) change the context
4) test that context-sensitive animation values have changed
Ideally, after changing the context (3), the animated state would instantly
update. However, this is not currently the case for many situations.
For CSS properties we have bug 545282 - In animations involving 'inherit'
/ 'currentColor', changes to inherited value / 'color' don't show up in
animated value immediately
For SVG lengths we have bug 508206 - Relative units used in
animation don't update immediately
(There are a few of todo_is's in the following tests so that if those bugs
are ever resolved we'll know to update this test case accordingly.)
So in between (3) and (4) we force a sample. This is currently done by
calling SVGSVGElement.setCurrentTime with the same current time which has the
side effect of forcing a sample.
What we *are* testing is that we're not too zealous with caching animation
values whilst in the frozen state. Normally we'd say, "Hey, we're frozen,
let's just use the same animation result as last time" but for some
context-sensitive animation values that doesn't work.
*/
/* Global Variables */
const SVGNS = "http://www.w3.org/2000/svg";
// Animation parameters -- not used for <set> animation
const ANIM_DUR = "4s";
const TIME_ANIM_END = "4";
const TIME_AFTER_ANIM_END = "5";
// SETTIMEOUT_INTERVAL: This value just needs to be at least as large as
// nsSMILAnimationController::kTimerInterval, so we can queue up a callback
// for this far in the future and be assured that an animation sample will
// have happened before the callback fires (because we presumably already
// have an animation sample in the setTimeout queue, with a lower timeout
// value than this).
// NOTE: We only need to use timeouts here because of Bug 545282.
const SETTIMEOUT_INTERVAL = 60;
const gTestArray =
[ testBaseValueChange,
testCurrentColorChange,
testCurrentColorChangeUsingStyle,
testInheritChange,
testInheritChangeUsingStyle
];
// Index of current test in gTestArray
var gNextTestIndex = 0;
const gSvg = document.getElementById("svg");
const gCircle = document.getElementById("circle");
const gCircleParent = document.getElementById("circleParent");
SimpleTest.waitForExplicitFinish();
// MAIN FUNCTION
// -------------
function main() {
function main()
{
ok(gSvg.animationsPaused(), "should be paused by <svg> load handler");
is(gSvg.getCurrentTime(), 0, "should be paused at 0 in <svg> load handler");
if (gNextTestIndex != 0) {
ok(false, "expecting to start at first test in array.");
const tests =
[ testBaseValueChange,
testCurrentColorChange,
testCurrentColorChangeUsingStyle,
testCurrentColorChangeOnFallback,
testInheritChange,
testInheritChangeUsingStyle,
testEmUnitChangeOnProp,
testEmUnitChangeOnPropBase,
testEmUnitChangeOnLength,
testPercentUnitChangeOnProp,
testPercentUnitChangeOnLength,
testRelativeFontSize,
testRelativeFontWeight,
testRelativeFont,
testCalcFontSize,
testDashArray,
testClip
];
while (tests.length) {
tests.shift()();
}
// Kick off first test. (It will kick off the one after it, and so on.)
runNextTest();
SimpleTest.finish();
}
// HELPER FUNCTIONS
// ----------------
function createAnimFromTo(attrName, fromVal, toVal) {
var anim = document.createElementNS(SVGNS,"animate");
function createAnimSetTo(attrName, toVal)
{
var anim = document.createElementNS(SVGNS,"set");
anim.setAttribute("attributeName", attrName);
anim.setAttribute("dur", ANIM_DUR);
anim.setAttribute("begin", "0s");
anim.setAttribute("from", fromVal);
anim.setAttribute("to", toVal);
anim.setAttribute("fill", "freeze");
return gCircle.appendChild(anim);
}
function createAnimBy(attrName, byVal) {
function createAnimBy(attrName, byVal)
{
var anim = document.createElementNS(SVGNS,"animate");
anim.setAttribute("attributeName", attrName);
anim.setAttribute("dur", ANIM_DUR);
@ -90,6 +124,18 @@ function createAnimBy(attrName, byVal) {
return gCircle.appendChild(anim);
}
function createAnimFromTo(attrName, fromVal, toVal)
{
var anim = document.createElementNS(SVGNS,"animate");
anim.setAttribute("attributeName", attrName);
anim.setAttribute("dur", ANIM_DUR);
anim.setAttribute("begin","0s");
anim.setAttribute("from", fromVal);
anim.setAttribute("to", toVal);
anim.setAttribute("fill", "freeze");
return gCircle.appendChild(anim);
}
// Common setup code for each test function: seek to 0, and make sure
// the previous test cleaned up its animations.
function setupTest() {
@ -99,17 +145,6 @@ function setupTest() {
}
}
function runNextTest() {
if (gNextTestIndex == gTestArray.length) {
// No tests left! we're done.
SimpleTest.finish();
return;
}
// Call next test (and increment next-test index)
gTestArray[gNextTestIndex++]();
}
// THE TESTS
// ---------
@ -130,106 +165,400 @@ function testBaseValueChange()
"Checking animated cx after anim ends & after changing base val");
anim.parentNode.removeChild(anim); // clean up
runNextTest();
}
function testCurrentColorChange()
{
gCircle.setAttribute("color", "red"); // At first: currentColor=red
var anim = createAnimFromTo("fill", "yellow", "currentColor");
var anim = createAnimSetTo("fill", "currentColor");
gSvg.setCurrentTime(TIME_AFTER_ANIM_END);
gSvg.setCurrentTime(0); // trigger synchronous sample
is(SMILUtil.getComputedStyleSimple(gCircle, "fill"), "rgb(255, 0, 0)",
"Checking animated fill=currentColor after anim ends");
"Checking animated fill=currentColor after animating");
gCircle.setAttribute("color", "lime"); // Change: currentColor=lime
setTimeout(testCurrentColorChange_final, SETTIMEOUT_INTERVAL);
}
function testCurrentColorChange_final()
{
// Bug 545282: We should really detect this change and update immediately but
// currently we don't until we get sampled again
todo_is(SMILUtil.getComputedStyleSimple(gCircle, "fill"), "rgb(0, 255, 0)",
"Checking animated fill=currentColor after updating context but before " +
"sampling");
gSvg.setCurrentTime(0);
is(SMILUtil.getComputedStyleSimple(gCircle, "fill"), "rgb(0, 255, 0)",
"Checking animated fill=currentColor after anim ends and 'color' changes");
"Checking animated fill=currentColor after updating context");
// Clean up
gCircle.removeAttribute("color");
gCircle.firstChild.parentNode.removeChild(gCircle.firstChild);
// Kick off next test
runNextTest();
gCircle.removeChild(gCircle.firstChild);
}
function testCurrentColorChangeUsingStyle()
{
setupTest();
gCircle.setAttribute("style", "color: red"); // At first: currentColor=red
var anim = createAnimFromTo("fill", "yellow", "currentColor");
var anim = createAnimSetTo("fill", "currentColor");
gSvg.setCurrentTime(TIME_AFTER_ANIM_END);
gSvg.setCurrentTime(0);
is(SMILUtil.getComputedStyleSimple(gCircle, "fill"), "rgb(255, 0, 0)",
"Checking animated fill=currentColor after anim ends (using style attr)");
"Checking animated fill=currentColor after animating (using style attr)");
gCircle.setAttribute("style", "color: lime"); // Change: currentColor=lime
setTimeout(testCurrentColorChangeUsingStyle_final, SETTIMEOUT_INTERVAL);
}
function testCurrentColorChangeUsingStyle_final()
{
gSvg.setCurrentTime(0);
is(SMILUtil.getComputedStyleSimple(gCircle, "fill"), "rgb(0, 255, 0)",
"Checking animated fill=currentColor after anim ends and 'color' changes "
"Checking animated fill=currentColor after updating context "
+ "(using style attr)");
// Clean up
gCircle.removeAttribute("style");
gCircle.firstChild.parentNode.removeChild(gCircle.firstChild);
runNextTest();
gCircle.removeChild(gCircle.firstChild);
}
function getFallbackColor(pServerStr)
{
return pServerStr.substr(pServerStr.indexOf(" ")+1);
}
function testCurrentColorChangeOnFallback()
{
setupTest();
gCircle.setAttribute("color", "red"); // At first: currentColor=red
var anim = createAnimSetTo("fill", "url(#missingGrad) currentColor");
gSvg.setCurrentTime(0);
var fallback =
getFallbackColor(SMILUtil.getComputedStyleSimple(gCircle, "fill"));
is(fallback, "rgb(255, 0, 0)",
"Checking animated fallback fill=currentColor after animating");
gCircle.setAttribute("color", "lime"); // Change: currentColor=lime
gSvg.setCurrentTime(0);
fallback = getFallbackColor(SMILUtil.getComputedStyleSimple(gCircle, "fill"));
is(fallback, "rgb(0, 255, 0)",
"Checking animated fallback fill=currentColor after updating context");
gCircle.removeAttribute("style");
gCircle.removeChild(gCircle.firstChild);
}
function testInheritChange()
{
setupTest();
gCircleParent.setAttribute("fill", "red"); // At first: inherit=red
var anim = createAnimFromTo("fill", "yellow", "inherit");
var anim = createAnimSetTo("fill", "inherit");
gSvg.setCurrentTime(TIME_AFTER_ANIM_END);
gSvg.setCurrentTime(0);
is(SMILUtil.getComputedStyleSimple(gCircle, "fill"), "rgb(255, 0, 0)",
"Checking animated fill=inherit after anim ends");
"Checking animated fill=inherit after animating");
gCircleParent.setAttribute("fill", "lime"); // Change: inherit=lime
setTimeout(testInheritChange_final, SETTIMEOUT_INTERVAL);
}
function testInheritChange_final() {
gSvg.setCurrentTime(0);
is(SMILUtil.getComputedStyleSimple(gCircle, "fill"), "rgb(0, 255, 0)",
"Checking animated fill=inherit after anim ends and parent val changes");
"Checking animated fill=inherit after updating context");
gCircleParent.removeAttribute("fill");
gCircle.firstChild.parentNode.removeChild(gCircle.firstChild);
runNextTest();
gCircle.removeChild(gCircle.firstChild);
}
function testInheritChangeUsingStyle()
{
setupTest();
gCircleParent.setAttribute("style", "fill: red"); // At first: inherit=red
var anim = createAnimFromTo("fill", "yellow", "inherit");
var anim = createAnimSetTo("fill", "inherit");
gSvg.setCurrentTime(TIME_AFTER_ANIM_END);
gSvg.setCurrentTime(0);
is(SMILUtil.getComputedStyleSimple(gCircle, "fill"), "rgb(255, 0, 0)",
"Checking animated fill=inherit after anim ends (using style attr)");
"Checking animated fill=inherit after animating (using style attr)");
gCircleParent.setAttribute("style", "fill: lime"); // Change: inherit=lime
setTimeout(testInheritChangeUsingStyle_final, SETTIMEOUT_INTERVAL);
}
function testInheritChangeUsingStyle_final() {
gSvg.setCurrentTime(0);
is(SMILUtil.getComputedStyleSimple(gCircle, "fill"), "rgb(0, 255, 0)",
"Checking animated fill=inherit after anim ends and parent val changes "
"Checking animated fill=inherit after updating context "
+ "(using style attr)");
gCircleParent.removeAttribute("style");
gCircle.firstChild.parentNode.removeChild(gCircle.firstChild);
runNextTest();
gCircle.removeChild(gCircle.firstChild);
}
function testEmUnitChangeOnProp()
{
setupTest();
gCircleParent.setAttribute("font-size", "10px"); // At first: font-size: 10px
var anim = createAnimSetTo("font-size", "2em");
gSvg.setCurrentTime(0);
is(SMILUtil.getComputedStyleSimple(gCircle, "font-size"), "20px",
"Checking animated font-size=2em after animating ends");
gCircleParent.setAttribute("font-size", "20px"); // Change: font-size: 20px
gSvg.setCurrentTime(0);
is(SMILUtil.getComputedStyleSimple(gCircle, "font-size"), "40px",
"Checking animated font-size=2em after updating context");
gCircleParent.removeAttribute("font-size");
gCircle.removeChild(gCircle.firstChild);
}
function testEmUnitChangeOnPropBase()
{
// Test the case where the base value for our animation sandwich is
// context-sensitive.
// Currently, this is taken care of by the compositor which keeps a cached
// base value and compares it with the current base value. This test then just
// serves as a regression test in case the compositor's behaviour changes.
setupTest();
gSvg.setAttribute("font-size", "10px"); // At first: font-size: 10px
gCircleParent.setAttribute("font-size", "1em"); // Base: 10px
var anim = createAnimBy("font-size", "10px");
gSvg.setCurrentTime(TIME_AFTER_ANIM_END);
is(SMILUtil.getComputedStyleSimple(gCircle, "font-size"), "20px",
"Checking animated font-size=20px after anim ends");
gSvg.setAttribute("font-size", "20px"); // Change: font-size: 20px
gSvg.setCurrentTime(TIME_AFTER_ANIM_END);
is(SMILUtil.getComputedStyleSimple(gCircle, "font-size"), "30px",
"Checking animated font-size=30px after updating context");
gCircleParent.removeAttribute("font-size");
gCircle.removeChild(gCircle.firstChild);
}
function testEmUnitChangeOnLength()
{
setupTest();
gCircleParent.setAttribute("font-size", "10px"); // At first: font-size: 10px
var anim = createAnimSetTo("cx", "2em");
gSvg.setCurrentTime(0);
is(gCircle.cx.animVal.value, 20,
"Checking animated length=2em after animating");
gCircleParent.setAttribute("font-size", "20px"); // Change: font-size: 20px
// Bug 508206: We should really detect this change and update immediately but
// currently we don't until we get sampled again
todo_is(gCircle.cx.animVal.value, 40,
"Checking animated length=2em after updating context but before sampling");
gSvg.setCurrentTime(0);
is(gCircle.cx.animVal.value, 40,
"Checking animated length=2em after updating context and after " +
"resampling");
gCircleParent.removeAttribute("font-size");
gCircle.removeChild(gCircle.firstChild);
}
function testPercentUnitChangeOnProp()
{
setupTest();
gCircleParent.setAttribute("font-size", "10px"); // At first: font-size: 10px
var anim = createAnimSetTo("font-size", "150%");
gSvg.setCurrentTime(0);
is(SMILUtil.getComputedStyleSimple(gCircle, "font-size"), "15px",
"Checking animated font-size=150% after animating");
gCircleParent.setAttribute("font-size", "20px"); // Change: font-size: 20px
gSvg.setCurrentTime(0);
is(SMILUtil.getComputedStyleSimple(gCircle, "font-size"), "30px",
"Checking animated font-size=150% after updating context");
gCircleParent.removeAttribute("font-size");
gCircle.removeChild(gCircle.firstChild);
}
function testPercentUnitChangeOnLength()
{
setupTest();
var oldHeight = gSvg.getAttribute("height");
gSvg.setAttribute("height", "100px"); // At first: viewport height: 100px
var anim = createAnimSetTo("cy", "100%");
gSvg.setCurrentTime(0); // Force synchronous sample so animation takes effect
// Due to bug 627594 (SVGLength.value for percent value lengths doesn't
// reflect updated viewport until reflow) the following will fail.
// Check that it does indeed fail so that when that bug is fixed this test
// can be updated.
todo_is(gCircle.cy.animVal.value, 100,
"Checking animated length=100% after animating but before reflow");
gSvg.forceRedraw();
// Even after doing a reflow though we'll still fail due to bug 508206
// (Relative units used in animation don't update immediately)
todo_is(gCircle.cy.animVal.value, 100,
"Checking animated length=100% after animating but before resampling");
gSvg.setCurrentTime(0);
// Now we should be up to date
is(gCircle.cy.animVal.value, 100,
"Checking animated length=100% after animating");
gSvg.setAttribute("height", "50px"); // Change: height: 50px
gSvg.forceRedraw(); // Bug 627594
gSvg.setCurrentTime(0); // Bug 508206
is(gCircle.cy.animVal.value, 50,
"Checking animated length=100% after updating context");
gSvg.setAttribute("height", oldHeight);
gCircle.removeChild(gCircle.firstChild);
}
function testRelativeFontSize()
{
setupTest();
gCircleParent.setAttribute("font-size", "10px"); // At first: font-size: 10px
var anim = createAnimSetTo("font-size", "larger");
gSvg.setCurrentTime(0);
var fsize = parseInt(SMILUtil.getComputedStyleSimple(gCircle, "font-size"));
// CSS 2 suggests a scaling factor of 1.2 so we should be looking at something
// around about 12 or so
ok(fsize > 10 && fsize < 20,
"Checking animated font-size > 10px after animating");
gCircleParent.setAttribute("font-size", "20px"); // Change: font-size: 20px
gSvg.setCurrentTime(0);
fsize = parseInt(SMILUtil.getComputedStyleSimple(gCircle, "font-size"));
ok(fsize > 20, "Checking animated font-size > 20px after updating context");
gCircleParent.removeAttribute("font-size");
gCircle.removeChild(gCircle.firstChild);
}
function testRelativeFontWeight()
{
setupTest();
gCircleParent.setAttribute("font-weight", "100"); // At first: font-weight 100
var anim = createAnimSetTo("font-weight", "bolder");
// CSS 2: 'bolder': Specifies the next weight that is assigned to a font
// that is darker than the inherited one. If there is no such weight, it
// simply results in the next darker numerical value (and the font remains
// unchanged), unless the inherited value was '900', in which case the
// resulting weight is also '900'.
gSvg.setCurrentTime(0);
var weight =
parseInt(SMILUtil.getComputedStyleSimple(gCircle, "font-weight"));
ok(weight > 100, "Checking animated font-weight > 100 after animating");
gCircleParent.setAttribute("font-weight", "800"); // Change: font-weight 800
gSvg.setCurrentTime(0);
weight = parseInt(SMILUtil.getComputedStyleSimple(gCircle, "font-weight"));
is(weight, 900,
"Checking animated font-weight = 900 after updating context");
gCircleParent.removeAttribute("font-weight");
gCircle.removeChild(gCircle.firstChild);
}
function testRelativeFont()
{
// Test a relative font-size as part of a 'font' spec since the code path
// is different in this case
// It turns out that, due to the way we store shorthand font properties, we
// don't need to worry about marking such values as context-sensitive since we
// seem to store them in their relative form. If, however, we change the way
// we store shorthand font properties in the future, this will serve as
// a useful regression test.
setupTest();
gCircleParent.setAttribute("font-size", "10px"); // At first: font-size: 10px
// We must be sure to set every part of the shorthand property to some
// non-context sensitive value because we want to test that even if only the
// font-size is relative we will update it appropriately.
var anim =
createAnimSetTo("font", "normal normal bold larger/normal sans-serif");
gSvg.setCurrentTime(0);
var fsize = parseInt(SMILUtil.getComputedStyleSimple(gCircle, "font-size"));
ok(fsize > 10 && fsize < 20,
"Checking size of shorthand 'font' > 10px after animating");
gCircleParent.setAttribute("font-size", "20px"); // Change: font-size: 20px
gSvg.setCurrentTime(0);
fsize = parseInt(SMILUtil.getComputedStyleSimple(gCircle, "font-size"));
ok(fsize > 20,
"Checking size of shorthand 'font' > 20px after updating context");
gCircleParent.removeAttribute("font-size");
gCircle.removeChild(gCircle.firstChild);
}
function testCalcFontSize()
{
setupTest();
gCircleParent.setAttribute("font-size", "10px"); // At first: font-size: 10px
var anim = createAnimSetTo("font-size", "-moz-calc(110% + 0.1em)");
gSvg.setCurrentTime(0);
var fsize = parseInt(SMILUtil.getComputedStyleSimple(gCircle, "font-size"));
// Font size should be 1.1 * 10px + 0.1 * 10px = 12
is(fsize, 12, "Checking animated calc font-size == 12px after animating");
gCircleParent.setAttribute("font-size", "20px"); // Change: font-size: 20px
gSvg.setCurrentTime(0);
fsize = parseInt(SMILUtil.getComputedStyleSimple(gCircle, "font-size"));
is(fsize, 24, "Checking animated calc font-size == 24px after updating " +
"context");
gCircleParent.removeAttribute("font-size");
gCircle.removeChild(gCircle.firstChild);
}
function testDashArray()
{
// stroke dasharrays don't currently convert units--but if someone ever fixes
// that, hopefully this test will fail and remind us not to cache percentage
// values in that case
setupTest();
var oldHeight = gSvg.getAttribute("height");
var oldWidth = gSvg.getAttribute("width");
gSvg.setAttribute("height", "100px"); // At first: viewport: 100x100px
gSvg.setAttribute("width", "100px");
var anim = createAnimFromTo("stroke-dasharray", "0 5", "0 50%");
gSvg.setCurrentTime(TIME_AFTER_ANIM_END);
// Now we should be up to date
is(SMILUtil.getComputedStyleSimple(gCircle, "stroke-dasharray"), "0, 50%",
"Checking animated stroke-dasharray after animating");
gSvg.setAttribute("height", "50px"); // Change viewport: 50x50px
gSvg.setAttribute("width", "50px");
gSvg.setCurrentTime(TIME_AFTER_ANIM_END);
is(SMILUtil.getComputedStyleSimple(gCircle, "stroke-dasharray"), "0, 50%",
"Checking animated stroke-dasharray after updating context");
gSvg.setAttribute("height", oldHeight);
gSvg.setAttribute("width", oldWidth);
gCircle.removeChild(gCircle.firstChild);
}
function testClip()
{
setupTest();
gCircleParent.setAttribute("font-size", "20px"); // At first: font-size: 20px
// The clip property only applies to elements that establish a new
// viewport so we need to create a nested svg and add animation to that
var nestedSVG = document.createElementNS(SVGNS, "svg");
nestedSVG.setAttribute("clip", "rect(0px 0px 0px 0px)");
gCircleParent.appendChild(nestedSVG);
var anim = createAnimSetTo("clip", "rect(1em 1em 1em 1em)");
// createAnimSetTo will make the animation a child of gCircle so we need to
// move it so it targets nestedSVG instead
nestedSVG.appendChild(anim);
gSvg.setCurrentTime(TIME_AFTER_ANIM_END);
is(SMILUtil.getComputedStyleSimple(nestedSVG, "clip"),
"rect(20px, 20px, 20px, 20px)",
"Checking animated clip rect after animating");
gCircleParent.setAttribute("font-size", "10px"); // Change: font-size: 10px
gSvg.setCurrentTime(TIME_AFTER_ANIM_END);
is(SMILUtil.getComputedStyleSimple(nestedSVG, "clip"),
"rect(10px, 10px, 10px, 10px)",
"Checking animated clip rect after updating context");
gCircleParent.removeAttribute("font-size");
gCircleParent.removeChild(nestedSVG);
}
window.addEventListener("load", main, false);

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

@ -57,7 +57,6 @@ _TEST_FILES = \
a_href_helper_04.svg \
test_animLengthObjectIdentity.xhtml \
test_animLengthReadonly.xhtml \
test_animLengthRelativeUnits.xhtml \
test_animLengthUnits.xhtml \
test_bbox.xhtml \
test_bbox-with-invalid-viewBox.xhtml \

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

@ -1,80 +0,0 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=508206
-->
<head>
<title>Test for liveness of relative units in animation</title>
<script type="text/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=508206">Mozilla Bug 508206</a>
<p id="display"></p>
<!-- XXX The following should be display: none but that's broken by bug 413975
where we don't handle percentage lengths when the whole fragment is
display: none properly. -->
<div id="content" style="visibility: hidden">
<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="100px" height="100px"
onload="this.pauseAnimations()">
<g font-size="10px">
<circle cx="0" cy="0" r="15" fill="blue" id="circle">
<animate attributeName="cx" from="0" to="10em" dur="10s" begin="0s"
fill="freeze" id="animate"/>
<animate attributeName="cy" from="0" to="100%" dur="10s" begin="0s"
fill="freeze"/>
</circle>
</g>
</svg>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
<![CDATA[
/** Test liveness of relative units of animated lengths **/
/* Global Variables */
const svgns="http://www.w3.org/2000/svg";
var svg = document.getElementById("svg");
var circle = document.getElementById('circle');
SimpleTest.waitForExplicitFinish();
function main() {
ok(svg.animationsPaused(), "should be paused by <svg> load handler");
is(svg.getCurrentTime(), 0, "should be paused at 0 in <svg> load handler");
// Sample mid-way through the animation
svg.setCurrentTime(5);
// (1) Check values mid-way
is(circle.cx.animVal.value, 50,
"(1) Unexpected animVal for cx before changing base length");
is(circle.cy.animVal.value, 50,
"(1) Unexpected animVal for cy before changing base length");
// (2) Change the frame of reference and check values are updated immediately
// Change font-size
circle.parentNode.setAttribute('font-size', '5px');
todo_is(circle.cx.animVal.value, 25,
"(2) Unexpected animVal for cx after changing parent font-size");
// Change the viewport size
svg.setAttribute('height', '50px');
todo_is(circle.cy.animVal.value, 25,
"(2) Unexpected animVal for cy after changing containing viewport size");
SimpleTest.finish();
}
var animate = document.getElementById('animate');
if (animate && animate.targetElement) {
window.addEventListener("load", main, false);
} else {
ok(true); // Skip tests but don't report 'todo' either
SimpleTest.finish();
}
]]>
</script>
</pre>
</body>
</html>

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

@ -429,7 +429,7 @@ static PRBool IsChromeURI(nsIURI* aURI)
/* Implementation file */
static PRIntn
static PRBool
TraverseProtos(nsHashKey *aKey, void *aData, void* aClosure)
{
nsCycleCollectionTraversalCallback *cb =
@ -439,7 +439,7 @@ TraverseProtos(nsHashKey *aKey, void *aData, void* aClosure)
return kHashEnumerateNext;
}
static PRIntn
static PRBool
UnlinkProtoJSObjects(nsHashKey *aKey, void *aData, void* aClosure)
{
nsXBLPrototypeBinding *proto = static_cast<nsXBLPrototypeBinding*>(aData);
@ -453,7 +453,7 @@ struct ProtoTracer
void *mClosure;
};
static PRIntn
static PRBool
TraceProtos(nsHashKey *aKey, void *aData, void* aClosure)
{
ProtoTracer* closure = static_cast<ProtoTracer*>(aClosure);

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

@ -328,7 +328,7 @@ PRBool nsXBLPrototypeBinding::CompareBindingURI(nsIURI* aURI) const
return equal;
}
static PRIntn
static PRBool
TraverseInsertionPoint(nsHashKey* aKey, void* aData, void* aClosure)
{
nsCycleCollectionTraversalCallback &cb =
@ -1213,7 +1213,7 @@ nsXBLPrototypeBinding::ConstructInsertionTable(nsIContent* aContent)
PRInt32 i;
for (i = 0; i < count; i++) {
nsIContent* child = childrenElements[i];
nsIContent* parent = child->GetParent();
nsCOMPtr<nsIContent> parent = child->GetParent();
// Create an XBL insertion point entry.
nsXBLInsertionPointEntry* xblIns = nsXBLInsertionPointEntry::Create(parent);

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

@ -4047,7 +4047,8 @@ nsXULDocument::OverlayForwardReference::Merge(nsIContent* aTargetNode,
if (attr == nsGkAtoms::removeelement &&
value.EqualsLiteral("true")) {
rv = RemoveElement(aTargetNode->GetParent(), aTargetNode);
nsCOMPtr<nsIContent> parent = aTargetNode->GetParent();
rv = RemoveElement(parent, aTargetNode);
if (NS_FAILED(rv)) return rv;
return NS_OK;

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

@ -1324,7 +1324,7 @@ nsXULContentBuilder::RemoveGeneratedContent(nsIContent* aElement)
while (0 != (count = ungenerated.Length())) {
// Pull the next "ungenerated" element off the queue.
PRUint32 last = count - 1;
nsIContent* element = ungenerated[last];
nsCOMPtr<nsIContent> element = ungenerated[last];
ungenerated.RemoveElementAt(last);
PRUint32 i = element->GetChildCount();

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

@ -8452,13 +8452,13 @@ nsDocShell::InternalLoad(nsIURI * aURI,
GetCurScrollPos(ScrollOrientation_X, &cx);
GetCurScrollPos(ScrollOrientation_Y, &cy);
// We scroll whenever we're not doing a history load. Note that
// sometimes we might scroll even if we don't fire a hashchange
// event! See bug 653741.
if (!aSHEntry) {
// ScrollToAnchor doesn't necessarily cause us to scroll the window;
// the function decides whether a scroll is appropriate based on the
// arguments it receives. But even if we don't end up scrolling,
// ScrollToAnchor performs other important tasks, such as informing
// the presShell that we have a new hash. See bug 680257.
rv = ScrollToAnchor(curHash, newHash, aLoadType);
NS_ENSURE_SUCCESS(rv, rv);
}
mLoadType = aLoadType;
mURIResultedInDocument = PR_TRUE;

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

@ -120,6 +120,8 @@ _TEST_FILES = \
file_bug669671.sjs \
test_bug675587.html \
test_bfcache_plus_hash.html \
test_bug680257.html \
file_bug680257.html \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)

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

@ -0,0 +1,16 @@
<!DOCTYPE HTML>
<html>
<head>
<style type='text/css'>
a { color: black; }
a:target { color: red; }
</style>
</head>
<body onload='(opener || parent).popupLoaded()'>
<a id='a' href='#a'>link</a>
<a id='b' href='#b'>link2</a>
</body>
</html>

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

@ -0,0 +1,59 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=680257
-->
<head>
<title>Test for Bug 680257</title>
<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=680257">Mozilla Bug 680257</a>
<script type="application/javascript;version=1.7">
SimpleTest.waitForExplicitFinish();
var popup = window.open('file_bug680257.html');
// The popup will call into popupLoaded() once it loads.
function popupLoaded() {
// runTests() needs to be called from outside popupLoaded's onload handler.
// Otherwise, the navigations we do in runTests won't create new SHEntries.
SimpleTest.executeSoon(runTests);
}
function runTests() {
checkPopupLinkStyle(false, 'Initial');
popup.location.hash = 'a';
checkPopupLinkStyle(true, 'After setting hash');
popup.history.back();
checkPopupLinkStyle(false, 'After going back');
popup.history.forward();
checkPopupLinkStyle(true, 'After going forward');
popup.close();
SimpleTest.finish();
}
function checkPopupLinkStyle(isTarget, desc) {
var link = popup.document.getElementById('a');
var style = popup.getComputedStyle(link);
var color = style.getPropertyValue('color');
// Color is red if isTarget, black otherwise.
if (isTarget) {
is(color, 'rgb(255, 0, 0)', desc);
}
else {
is(color, 'rgb(0, 0, 0)', desc);
}
}
</script>
</body>
</html>

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

@ -8220,6 +8220,7 @@ NS_IMETHODIMP
nsGlobalWindow::GetMozIndexedDB(nsIIDBFactory** _retval)
{
if (!mIndexedDB) {
if (!IsChromeWindow()) {
nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
do_GetService(THIRDPARTYUTIL_CONTRACTID);
NS_ENSURE_TRUE(thirdPartyUtil, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
@ -8234,6 +8235,7 @@ nsGlobalWindow::GetMozIndexedDB(nsIIDBFactory** _retval)
*_retval = nsnull;
return NS_OK;
}
}
mIndexedDB = indexedDB::IDBFactory::Create(this);
NS_ENSURE_TRUE(mIndexedDB, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);

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

@ -51,7 +51,7 @@
* http://www.w3.org/TR/DOM-Level-2-Style
*/
[builtinclass, scriptable, uuid(10f43750-b379-11e0-aff2-0800200c9a66)]
[builtinclass, scriptable, uuid(286466f1-4246-4574-afdb-2f8a03ad7cc8)]
interface nsIDOMCSS2Properties : nsISupports
{
attribute DOMString background;
@ -657,6 +657,9 @@ interface nsIDOMCSS2Properties : nsISupports
attribute DOMString MozBorderImage;
// raises(DOMException) on setting
attribute DOMString MozColumns;
// raises(DOMException) on setting
attribute DOMString MozColumnRule;
// raises(DOMException) on setting

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

@ -45,7 +45,7 @@
* For more information on this interface, please see
* http://www.whatwg.org/specs/web-apps/current-work/#messageevent
*/
[scriptable, uuid(dc8ec5c6-ebf2-4f95-be99-cd13e3c0d0c6)]
[scriptable, uuid(9ac4fa26-4d19-4f4e-807e-b30cd0dbe56a)]
interface nsIDOMMessageEvent : nsIDOMEvent
{
/**

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

@ -3,4 +3,8 @@ head = head_plugins.js
tail =
[test_bug455213.js]
# Bug 676953: test fails consistently on Android
fail-if = os == "android"
[test_bug471245.js]
# Bug 676953: test fails consistently on Android
fail-if = os == "android"

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

@ -421,6 +421,7 @@ abstract public class GeckoApp
public void onStart()
{
Log.i(LOG_FILE_NAME, "start");
GeckoAppShell.sendEventToGecko(new GeckoEvent(GeckoEvent.ACTIVITY_START));
super.onStart();
}

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

@ -72,6 +72,7 @@ public class GeckoEvent {
public static final int SURFACE_CREATED = 13;
public static final int SURFACE_DESTROYED = 14;
public static final int GECKO_EVENT_SYNC = 15;
public static final int ACTIVITY_START = 17;
public static final int IME_COMPOSITION_END = 0;
public static final int IME_COMPOSITION_BEGIN = 1;

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

@ -169,8 +169,30 @@ class GeckoSurfaceView
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// Force exactly one frame to render
// because the surface change is only seen after we
// have swapped the back buffer.
// The buffer size only changes after the next swap buffer.
// We need to make sure the Gecko's view resize when Android's
// buffer resizes.
if (mDrawMode == DRAW_GLES_2) {
// When we get a surfaceChange event, we have 0 to n paint events
// waiting in the Gecko event queue. We will make the first
// succeed and the abort the others.
mDrawSingleFrame = true;
if (!mInDrawing) {
// Queue at least one paint event in case none are queued.
GeckoAppShell.scheduleRedraw();
}
GeckoAppShell.geckoEventSync();
mDrawSingleFrame = false;
mAbortDraw = false;
}
if (mShowingSplashScreen)
drawSplashScreen(holder, width, height);
mSurfaceLock.lock();
try {
@ -221,6 +243,12 @@ class GeckoSurfaceView
}
} finally {
mSurfaceLock.unlock();
if (mDrawMode == DRAW_GLES_2) {
// Force a frame to be drawn before the surfaceChange returns,
// otherwise we get artifacts.
GeckoAppShell.scheduleRedraw();
GeckoAppShell.geckoEventSync();
}
}
Object syncDrawObject = null;
@ -293,6 +321,10 @@ class GeckoSurfaceView
public static final int DRAW_ERROR = 0;
public static final int DRAW_GLES_2 = 1;
public static final int DRAW_2D = 2;
// Drawing is disable when the surface buffer
// has changed size but we haven't yet processed the
// resize event.
public static final int DRAW_DISABLED = 3;
public int beginDrawing() {
if (mInDrawing) {
@ -300,6 +332,12 @@ class GeckoSurfaceView
return DRAW_ERROR;
}
// Once we drawn our first frame after resize we can ignore
// the other draw events until we handle the resize events.
if (mAbortDraw) {
return DRAW_DISABLED;
}
/* Grab the lock, which we'll hold while we're drawing.
* It gets released in endDrawing(), and is also used in surfaceChanged
* to make sure that we don't change our surface details while
@ -330,6 +368,9 @@ class GeckoSurfaceView
return;
}
if (mDrawSingleFrame)
mAbortDraw = true;
try {
if (!mSurfaceValid) {
Log.e(LOG_FILE_NAME, "endDrawing with false mSurfaceValid");
@ -657,6 +698,10 @@ class GeckoSurfaceView
// Are we actively between beginDrawing/endDrawing?
boolean mInDrawing;
// Used to finish the current buffer before changing the surface size
boolean mDrawSingleFrame = false;
boolean mAbortDraw = false;
// Are we waiting for a buffer to draw in surfaceChanged?
boolean mSyncDraw;

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

@ -3,4 +3,8 @@ head =
tail =
[test_wwauthpromptfactory.js]
# Bug 676955: test fails consistently on Android
fail-if = os == "android"
[test_wwpromptfactory.js]
# Bug 676955: test fails consistently on Android
fail-if = os == "android"

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

@ -285,7 +285,7 @@ NS_IMETHODIMP nsSystemPrefService::GetBoolPref(const char *aPrefName, PRBool *_r
}
/* void setBoolPref (in string aPrefName, in long aValue); */
NS_IMETHODIMP nsSystemPrefService::SetBoolPref(const char *aPrefName, PRInt32 aValue)
NS_IMETHODIMP nsSystemPrefService::SetBoolPref(const char *aPrefName, PRBool aValue)
{
return NS_ERROR_NOT_IMPLEMENTED;
}

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

@ -41,10 +41,6 @@
#include "nsICategoryManager.h"
#include "nsISupportsPrimitives.h"
// The number 130 more or less comes out of thin air.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=355178#c78 for a pseudo-rationale.
#define UNREASONABLE_WORD_LENGTH 130
#define DEFAULT_SPELL_CHECKER "@mozilla.org/spellchecker/engine;1"
NS_IMPL_CYCLE_COLLECTING_ADDREF(mozSpellChecker)
@ -149,12 +145,6 @@ mozSpellChecker::CheckWord(const nsAString &aWord, PRBool *aIsMisspelled, nsTArr
if(!mSpellCheckingEngine)
return NS_ERROR_NULL_POINTER;
// don't bother to check crazy words
if (aWord.Length() > UNREASONABLE_WORD_LENGTH) {
*aIsMisspelled = PR_TRUE;
return NS_OK;
}
*aIsMisspelled = PR_FALSE;
result = mSpellCheckingEngine->Check(PromiseFlatString(aWord).get(), &correct);
NS_ENSURE_SUCCESS(result, result);

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

@ -111,6 +111,8 @@ tail =
[test_encode_CP852.js]
[test_encode_CP855.js]
[test_encode_CP857.js]
# Bug 676958: test consistently hangs on Android
skip-if = os == "android"
[test_encode_CP862.js]
[test_encode_CP864.js]
[test_encode_CP874.js]

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

@ -3,4 +3,6 @@ head =
tail =
[test_ipcshell.js]
# Bug 676963: test fails consistently on Android
fail-if = os == "android"
[test_ipcshell_child.js]

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

@ -77,6 +77,36 @@ GRE_MODULE = 1
LIBS = $(NSPR_LIBS)
ifdef GNU_CXX
ifdef INTEL_CXX
# icc gets special optimize flags
ifdef MOZ_PROFILE_GENERATE
MODULE_OPTIMIZE_FLAGS = -O0
else
MODULE_OPTIMIZE_FLAGS = -O2 -ip
endif
else # not INTEL_CXX
MODULE_OPTIMIZE_FLAGS = -O3 -fstrict-aliasing -fno-stack-protector
# We normally want -fomit-frame-pointer, but we want an explicit
# -fno-omit-frame-pointer if we're using a sampling profiler.
ifndef MOZ_PROFILING
MODULE_OPTIMIZE_FLAGS += -fomit-frame-pointer
else
MODULE_OPTIMIZE_FLAGS += -fno-omit-frame-pointer
endif
endif
else # not GNU_CXX
ifeq ($(OS_ARCH),SunOS)
MODULE_OPTIMIZE_FLAGS = -xO4
endif
ifeq ($(OS_ARCH),WINNT)
MODULE_OPTIMIZE_FLAGS = -O2
endif
endif
ifeq ($(OS_ARCH),WINNT)
NO_PROFILE_GUIDED_OPTIMIZE = 1
endif

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

@ -43,7 +43,6 @@ USE_AUTOCONF = 1
MOZILLA_CLIENT = 1
target = @target@
ac_configure_args = @ac_configure_args@
BUILD_MODULES = @BUILD_MODULES@
MOZILLA_VERSION = @MOZILLA_VERSION@
MOZ_BUILD_APP = @MOZ_BUILD_APP@

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

@ -41,6 +41,38 @@ static BOOL sh_DoCopy(wchar_t *srcFileName, DWORD srcFileAttributes,
#define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
#define STR_LEN(a) (ARRAY_LEN(a) - 1)
#ifdef __MINGW32__
/* MingW currently does not implement a wide version of the
startup routines. Workaround is to implement something like
it ourselves. */
#include <shellapi.h>
int wmain(int argc, WCHAR **argv);
int main(int argc, char **argv)
{
int result;
wchar_t *commandLine = GetCommandLineW();
int argcw = 0;
wchar_t **_argvw = CommandLineToArgvW( commandLine, &argcw );
wchar_t *argvw[argcw + 1];
int i;
if (!_argvw)
return 127;
/* CommandLineToArgvW doesn't output the ending NULL so
we have to manually add it on */
for ( i = 0; i < argcw; i++ )
argvw[i] = _argvw[i];
argvw[argcw] = NULL;
result = wmain(argcw, argvw);
LocalFree(_argvw);
return result;
}
#endif /* __MINGW32__ */
/* changes all forward slashes in token to backslashes */
void changeForwardSlashesToBackSlashes ( wchar_t *arg )
{

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

@ -153,6 +153,20 @@ xpcshell-tests:
$(LIBXUL_DIST)/bin/xpcshell \
$(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
xpcshell-tests-remote: DM_TRANS?=adb
xpcshell-tests-remote:
$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
-I$(topsrcdir)/build \
-I$(topsrcdir)/build/mobile \
$(topsrcdir)/testing/xpcshell/remotexpcshelltests.py \
--symbols-path=$(DIST)/crashreporter-symbols \
--build-info-json=$(DEPTH)/mozinfo.json \
$(EXTRA_TEST_ARGS) \
--dm_trans=$(DM_TRANS) \
--deviceIP=${TEST_DEVICE} \
--objdir=$(DEPTH) \
$(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
# Execute a single test, specified in $(SOLO_FILE), but don't automatically
# start the test. Instead, present the xpcshell prompt so the user can
# attach a debugger and then start the test.
@ -182,6 +196,23 @@ check-one:
$(LIBXUL_DIST)/bin/xpcshell \
$(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
check-one-remote: DM_TRANS?=adb
check-one-remote:
$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
-I$(topsrcdir)/build \
-I$(topsrcdir)/build/mobile \
$(testxpcsrcdir)/remotexpcshelltests.py \
--symbols-path=$(DIST)/crashreporter-symbols \
--build-info-json=$(DEPTH)/mozinfo.json \
--test-path=$(SOLO_FILE) \
--profile-name=$(MOZ_APP_NAME) \
--verbose \
$(EXTRA_TEST_ARGS) \
--dm_trans=$(DM_TRANS) \
--deviceIP=${TEST_DEVICE} \
--objdir=$(DEPTH) \
--noSetup \
$(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
endif # XPCSHELL_TESTS
ifdef CPP_UNIT_TESTS
@ -1122,8 +1153,9 @@ ifdef HAVE_DTRACE
ifndef XP_MACOSX
ifdef DTRACE_PROBE_OBJ
ifndef DTRACE_LIB_DEPENDENT
$(DTRACE_PROBE_OBJ):
dtrace -G -C -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ)
NON_DTRACE_OBJS := $(filter-out $(DTRACE_PROBE_OBJ),$(OBJS))
$(DTRACE_PROBE_OBJ): $(NON_DTRACE_OBJS)
dtrace -G -C -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ) $(NON_DTRACE_OBJS)
endif
endif
endif
@ -1519,9 +1551,6 @@ export:: FORCE
@echo; sleep 2; false
endif
$(IDL_DIR)::
$(NSINSTALL) -D $@
# generate .h files from into $(XPIDL_GEN_DIR), then export to $(DIST)/include;
# warn against overriding existing .h file.
$(XPIDL_GEN_DIR)/.done:
@ -1592,14 +1621,8 @@ endif # XPIDLSRCS
#
# General rules for exporting idl files.
#
# WORK-AROUND ONLY, for mozilla/tools/module-deps/bootstrap.pl build.
# Bug to fix idl dependency problems w/o this extra build pass is
# http://bugzilla.mozilla.org/show_bug.cgi?id=145777
#
$(IDL_DIR)::
$(IDL_DIR):
$(NSINSTALL) -D $@
export-idl:: $(SUBMAKEFILES) $(MAKE_DIRS)
@ -2066,7 +2089,6 @@ showhost:
@echo "HOST_LIBRARY = $(HOST_LIBRARY)"
showbuildmods::
@echo "Build Modules = $(BUILD_MODULES)"
@echo "Module dirs = $(BUILD_MODULE_DIRS)"
documentation:

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

@ -1992,14 +1992,11 @@ case "$target" in
*-darwin*)
MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -o $@'
MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -o $@'
MOZ_OPTIMIZE_FLAGS="-O3 -fstrict-aliasing -fno-stack-protector"
# We normally want -fomit-frame-pointer, but we want an explicit
# -fno-omit-frame-pointer if we're using a sampling profiler.
# If we're building with --enable-profiling, we need a frame pointer.
if test -z "$MOZ_PROFILING"; then
MOZ_OPTIMIZE_FLAGS="$MOZ_OPTIMIZE_FLAGS -fomit-frame-pointer"
MOZ_OPTIMIZE_FLAGS="-O3 -fomit-frame-pointer"
else
MOZ_OPTIMIZE_FLAGS="$MOZ_OPTIMIZE_FLAGS -fno-omit-frame-pointer"
MOZ_OPTIMIZE_FLAGS="-O3 -fno-omit-frame-pointer"
fi
_PEDANTIC=
CFLAGS="$CFLAGS -fpascal-strings -fno-common"

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

@ -2563,6 +2563,7 @@ js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent,
JS_ASSERT(script->compartment != cx->compartment);
JS_OPT_ASSERT(script->ownerObject == fun);
cfun->u.i.script = NULL;
JSScript *cscript = js_CloneScript(cx, script);
if (!cscript)
return NULL;

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

@ -1839,6 +1839,8 @@ main(int argc, char **argv, char **envp)
XRE_GetFileFromPath(argv[4], getter_AddRefs(appOmni));
argc-=2;
argv+=2;
} else {
appOmni = greOmni;
}
XRE_InitOmnijar(greOmni, appOmni);

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

@ -46,17 +46,8 @@ include $(DEPTH)/config/autoconf.mk
MODULE = xpconnect
ifeq (xpconnect, $(findstring xpconnect, $(BUILD_MODULES)))
LIBRARY_NAME = xpconnect
EXPORT_LIBRARY = 1
SHORT_LIBNAME = xpconect
IS_COMPONENT = 1
MODULE_NAME = xpconnect
GRE_MODULE = 1
else
LIBRARY_NAME = xpconnect_s
FORCE_STATIC_LIB = 1
endif
LIBXUL_LIBRARY = 1
EXPORTS = xpcpublic.h

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

@ -2074,7 +2074,8 @@ nsXPConnect::CreateSandbox(JSContext *cx, nsIPrincipal *principal,
jsval rval = JSVAL_VOID;
AUTO_MARK_JSVAL(ccx, &rval);
nsresult rv = xpc_CreateSandboxObject(cx, &rval, principal, NULL, false);
nsresult rv = xpc_CreateSandboxObject(cx, &rval, principal, NULL, false,
EmptyCString());
NS_ASSERTION(NS_FAILED(rv) || !JSVAL_IS_PRIMITIVE(rval),
"Bad return value from xpc_CreateSandboxObject()!");

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

@ -3153,7 +3153,7 @@ NS_IMPL_ISUPPORTS0(Identity)
nsresult
xpc_CreateSandboxObject(JSContext * cx, jsval * vp, nsISupports *prinOrSop, JSObject *proto,
bool wantXrays)
bool wantXrays, const nsACString &sandboxName)
{
// Create the sandbox global object
nsresult rv;
@ -3240,6 +3240,10 @@ xpc_CreateSandboxObject(JSContext * cx, jsval * vp, nsISupports *prinOrSop, JSOb
}
}
xpc::CompartmentPrivate *compartmentPrivate =
static_cast<xpc::CompartmentPrivate*>(JS_GetCompartmentPrivate(cx, compartment));
compartmentPrivate->location = sandboxName;
return NS_OK;
}
@ -3351,6 +3355,8 @@ nsXPCComponents_utils_Sandbox::CallOrConstruct(nsIXPConnectWrappedNative *wrappe
JSObject *proto = nsnull;
bool wantXrays = true;
nsCString sandboxName;
if (argc > 1) {
if (!JSVAL_IS_OBJECT(argv[1]))
return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
@ -3382,9 +3388,26 @@ nsXPCComponents_utils_Sandbox::CallOrConstruct(nsIXPConnectWrappedNative *wrappe
wantXrays = JSVAL_TO_BOOLEAN(option);
}
if (!JS_HasProperty(cx, optionsObject, "sandboxName", &found))
return NS_ERROR_INVALID_ARG;
if (found) {
if (!JS_GetProperty(cx, optionsObject, "sandboxName", &option) ||
!JSVAL_IS_STRING(option)) {
return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
}
rv = xpc_CreateSandboxObject(cx, vp, prinOrSop, proto, wantXrays);
char *tmp = JS_EncodeString(cx, JSVAL_TO_STRING(option));
if (!tmp) {
return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
}
sandboxName.Adopt(tmp, strlen(tmp));
}
}
rv = xpc_CreateSandboxObject(cx, vp, prinOrSop, proto, wantXrays, sandboxName);
if (NS_FAILED(rv)) {
return ThrowAndFail(rv, cx, _retval);

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

@ -1584,22 +1584,30 @@ CompartmentStats::CompartmentStats(JSContext *cx, JSCompartment *c)
{
if(c->principals->codebase)
{
// A hack: replace forward slashes with '\\' so they aren't
// treated as path separators. Users of the reporters
// (such as about:memory) have to undo this change.
name.Assign(c->principals->codebase);
name.ReplaceChar('/', '\\');
// If it's the system compartment, append the address.
// This means that multiple system compartments (and there
// can be many) can be distinguished.
if(c->isSystemCompartment)
{
if (c->data &&
!((xpc::CompartmentPrivate*)c->data)->location.IsEmpty())
{
name.AppendLiteral(", ");
name.Append(((xpc::CompartmentPrivate*)c->data)->location);
}
// ample; 64-bit address max is 18 chars
static const int maxLength = 31;
nsPrintfCString address(maxLength, ", 0x%llx", PRUint64(c));
name.Append(address);
}
// A hack: replace forward slashes with '\\' so they aren't
// treated as path separators. Users of the reporters
// (such as about:memory) have to undo this change.
name.ReplaceChar('/', '\\');
}
else
{

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

@ -4315,7 +4315,7 @@ xpc_GetJSPrivate(JSObject *obj)
// and used.
nsresult
xpc_CreateSandboxObject(JSContext * cx, jsval * vp, nsISupports *prinOrSop,
JSObject *proto, bool preferXray);
JSObject *proto, bool preferXray, const nsACString &sandboxName);
// Helper for evaluating scripts in a sandbox object created with
// xpc_CreateSandboxObject(). The caller is responsible of ensuring
@ -4396,6 +4396,7 @@ struct CompartmentPrivate
JSObject2JSObjectMap *waiverWrapperMap;
// NB: we don't want this map to hold a strong reference to the wrapper.
nsDataHashtable<nsPtrHashKey<XPCWrappedNative>, JSObject *> *expandoMap;
nsCString location;
bool RegisterExpandoObject(XPCWrappedNative *wn, JSObject *expando) {
if (!expandoMap) {

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

@ -15,6 +15,8 @@ tail =
[test_import.js]
[test_js_weak_references.js]
[test_localeCompare.js]
# Bug 676965: test fails consistently on Android
fail-if = os == "android"
[test_recursive_import.js]
[test_xpcomutils.js]
[test_unload.js]

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

@ -83,11 +83,7 @@
#endif
// Size to use for PLArena block allocations.
// XXX: This should be 8192; the subtracted elements are a hack that's
// required to ensure the allocation requests are power-of-two-sized and thus
// avoid lots of wasted memory caused by the heap allocator rounding up request
// sizes. Bug 676457 will fix it properly.
static const size_t ARENA_PAGE_SIZE = 8192 - sizeof(PLArena) - PL_ARENA_CONST_ALIGN_MASK;
static const size_t ARENA_PAGE_SIZE = 8192;
// Freed memory is filled with a poison value, which we arrange to
// form a pointer either to an always-unmapped region of the address

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

@ -12,13 +12,13 @@
function test() {
document.querySelector("div").focus();
// type a character, then press backspace to delete it
sendKey("X", window);
sendKey("BACK_SPACE", window);
sendKey("X", "div1");
sendKey("BACK_SPACE", "div1");
document.documentElement.removeAttribute("class");
}
</script>
</head>
<body onload="test()">
<div contenteditable></div>
<div id="div1" contenteditable></div>
</body>
</html>

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

@ -12,13 +12,13 @@
function test() {
document.querySelector("div").focus();
// type a character, then press backspace to delete it
sendKey("X", window);
sendKey("BACK_SPACE", window);
sendKey("X", "div1");
sendKey("BACK_SPACE", "div1");
document.documentElement.removeAttribute("class");
}
</script>
</head>
<body onload="test()">
<div contenteditable></div>
<div id="div1" contenteditable></div>
</body>
</html>

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

@ -12,13 +12,13 @@
function test() {
document.querySelector("div").focus();
// type a character, then press backspace to delete it
sendKey("X", window);
sendKey("BACK_SPACE", window);
sendKey("X", "div1");
sendKey("BACK_SPACE", "div1");
document.documentElement.removeAttribute("class");
}
</script>
</head>
<body onload="test()">
<div contenteditable></div>
<div id="div1" contenteditable></div>
</body>
</html>

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

@ -249,6 +249,7 @@ nsProgressFrame::AttributeChanged(PRInt32 aNameSpaceID,
NS_ASSERTION(barFrame, "The progress frame should have a child with a frame!");
PresContext()->PresShell()->FrameNeedsReflow(barFrame, nsIPresShell::eResize,
NS_FRAME_IS_DIRTY);
Invalidate(GetVisualOverflowRectRelativeToSelf());
}
return nsHTMLContainerFrame::AttributeChanged(aNameSpaceID, aAttribute,
@ -278,6 +279,28 @@ nsProgressFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext,
return autoSize;
}
nscoord
nsProgressFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
{
nsRefPtr<nsFontMetrics> fontMet;
NS_ENSURE_SUCCESS(
nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet)), 0);
nscoord minWidth = fontMet->Font().size; // 1em
if (GetStyleDisplay()->mOrient == NS_STYLE_ORIENT_HORIZONTAL) {
minWidth *= 10; // 10em
}
return minWidth;
}
nscoord
nsProgressFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
{
return GetMinWidth(aRenderingContext);
}
bool
nsProgressFrame::ShouldUseNativeStyle() const
{

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

@ -84,6 +84,9 @@ public:
nsSize aMargin, nsSize aBorder,
nsSize aPadding, PRBool aShrinkWrap);
virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext);
virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext);
virtual PRBool IsFrameOfType(PRUint32 aFlags) const
{
return nsHTMLContainerFrame::IsFrameOfType(aFlags &

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

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<link rel='stylesheet' type='text/css' href='style.css'>
<style>
progress { display: block; }
</style>
<body>
<progress value='0.5'></progress>
</body>
</html>

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

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html class='reftest-wait'>
<link rel='stylesheet' type='text/css' href='style.css'>
<style>
progress { display: block; }
</style>
<script>
function loadHandler() {
setTimeout(function() {
var p = document.getElementsByTagName('progress')[0];
p.value = '0.5';
document.documentElement.className = '';
}, 0);
}
</script>
<body onload="loadHandler();">
<progress value='0'></progress>
</body>
</html>

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

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<link rel='stylesheet' type='text/css' href='style.css'>
<style>
progress { width: 10em; height: 1em; }
progress.vertical { -moz-orient: vertical; width: 1em; height: 10em; }
</style>
<body>
<table>
<tr>
<td>foo</td>
<td><progress value='0.5'></td>
<td>bar</td>
</tr>
<tr>
<td>foo</td>
<td><progress class='vertical' value='0.5'></td>
<td>bar</td>
</tr>
</table>
</body>
</html>

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

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<link rel='stylesheet' type='text/css' href='style.css'>
<style>
progress.vertical { -moz-orient: vertical; }
</style>
<body>
<table>
<tr>
<td>foo</td>
<td><progress value='0.5'></td>
<td>bar</td>
</tr>
<tr>
<td>foo</td>
<td><progress class='vertical' value='0.5'></td>
<td>bar</td>
</tr>
</table>
</body>
</html>

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

@ -19,3 +19,7 @@
# transformations will not behave exactly the same for <progress> and two divs.
# However, it would be possible to manually check those.
# == transformations.html transformations-ref.html
# Tests for bugs:
== block-invalidate.html block-invalidate-ref.html
== in-cells.html in-cells-ref.html

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