зеркало из https://github.com/mozilla/pjs.git
Merge MC -> JM
This commit is contained in:
Коммит
5bf926fb84
|
@ -976,10 +976,12 @@ refRelationSetCB(AtkObject *aAtkObj)
|
||||||
while ((tempAcc = rel.Next()))
|
while ((tempAcc = rel.Next()))
|
||||||
targets.AppendElement(nsAccessibleWrap::GetAtkObject(tempAcc));
|
targets.AppendElement(nsAccessibleWrap::GetAtkObject(tempAcc));
|
||||||
|
|
||||||
|
if (targets.Length()) {
|
||||||
atkRelation = atk_relation_new(targets.Elements(), targets.Length(), atkType);
|
atkRelation = atk_relation_new(targets.Elements(), targets.Length(), atkType);
|
||||||
atk_relation_set_add(relation_set, atkRelation);
|
atk_relation_set_add(relation_set, atkRelation);
|
||||||
g_object_unref(atkRelation);
|
g_object_unref(atkRelation);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return relation_set;
|
return relation_set;
|
||||||
}
|
}
|
||||||
|
|
|
@ -868,8 +868,11 @@ var InspectorUI = {
|
||||||
delete this.treeBrowserDocument;
|
delete this.treeBrowserDocument;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.treeIFrame)
|
if (this.treeIFrame) {
|
||||||
|
let parent = this.treeIFrame.parentNode;
|
||||||
|
parent.removeChild(this.treeIFrame);
|
||||||
delete this.treeIFrame;
|
delete this.treeIFrame;
|
||||||
|
}
|
||||||
delete this.ioBox;
|
delete this.ioBox;
|
||||||
|
|
||||||
if (this.domplate) {
|
if (this.domplate) {
|
||||||
|
@ -893,6 +896,8 @@ var InspectorUI = {
|
||||||
this.treeLoaded = false;
|
this.treeLoaded = false;
|
||||||
|
|
||||||
this.treePanel.addEventListener("popuphidden", function treePanelHidden() {
|
this.treePanel.addEventListener("popuphidden", function treePanelHidden() {
|
||||||
|
this.removeEventListener("popuphidden", treePanelHidden, false);
|
||||||
|
|
||||||
InspectorUI.closing = false;
|
InspectorUI.closing = false;
|
||||||
Services.obs.notifyObservers(null, INSPECTOR_NOTIFICATIONS.CLOSED, null);
|
Services.obs.notifyObservers(null, INSPECTOR_NOTIFICATIONS.CLOSED, null);
|
||||||
}, false);
|
}, false);
|
||||||
|
|
|
@ -156,10 +156,9 @@ Sanitizer.prototype = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear plugin data.
|
// Clear plugin data.
|
||||||
let ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
|
||||||
const phInterface = Ci.nsIPluginHost;
|
const phInterface = Ci.nsIPluginHost;
|
||||||
const FLAG_CLEAR_ALL = phInterface.FLAG_CLEAR_ALL;
|
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
|
// 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
|
// 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);
|
.appendTo(appTabTrayContainer);
|
||||||
|
|
||||||
AllTabs.tabs.forEach(function(xulTab) {
|
AllTabs.tabs.forEach(function(xulTab) {
|
||||||
if (xulTab.pinned && xulTab.ownerDocument.defaultView == gWindow)
|
if (xulTab.pinned)
|
||||||
self.addAppTab(xulTab, {dontAdjustTray: true});
|
self.addAppTab(xulTab, {dontAdjustTray: true});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -744,9 +744,13 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||||
// ----------
|
// ----------
|
||||||
// Function: _unhide
|
// Function: _unhide
|
||||||
// Shows the hidden group.
|
// 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._cancelFadeAwayUndoButtonTimer();
|
||||||
this.hidden = false;
|
this.hidden = false;
|
||||||
this.$undoContainer.remove();
|
this.$undoContainer.remove();
|
||||||
|
@ -754,20 +758,31 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||||
this.droppable(true);
|
this.droppable(true);
|
||||||
this.setTrenches(this.bounds);
|
this.setTrenches(this.bounds);
|
||||||
|
|
||||||
iQ(this.container).show().animate({
|
let self = this;
|
||||||
"-moz-transform": "scale(1)",
|
|
||||||
"opacity": 1
|
let finalize = function () {
|
||||||
}, {
|
|
||||||
duration: 170,
|
|
||||||
complete: function() {
|
|
||||||
self._children.forEach(function(child) {
|
self._children.forEach(function(child) {
|
||||||
iQ(child.container).show();
|
iQ(child.container).show();
|
||||||
});
|
});
|
||||||
|
|
||||||
UI.setActive(self);
|
UI.setActive(self);
|
||||||
self._sendToSubscribers("groupShown", { groupItemId: self.id });
|
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();
|
GroupItems.updateGroupCloseButtons();
|
||||||
},
|
},
|
||||||
|
@ -785,15 +800,29 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||||
let remainingGroups = GroupItems.groupItems.filter(function (groupItem) {
|
let remainingGroups = GroupItems.groupItems.filter(function (groupItem) {
|
||||||
return (groupItem != self && groupItem.getChildren().length);
|
return (groupItem != self && groupItem.getChildren().length);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let tab = null;
|
||||||
|
|
||||||
if (!gBrowser._numPinnedTabs && !remainingGroups.length) {
|
if (!gBrowser._numPinnedTabs && !remainingGroups.length) {
|
||||||
let emptyGroups = GroupItems.groupItems.filter(function (groupItem) {
|
let emptyGroups = GroupItems.groupItems.filter(function (groupItem) {
|
||||||
return (groupItem != self && !groupItem.getChildren().length);
|
return (groupItem != self && !groupItem.getChildren().length);
|
||||||
});
|
});
|
||||||
let group = (emptyGroups.length ? emptyGroups[0] : GroupItems.newGroup());
|
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:
|
// Options:
|
||||||
// immediately - (bool) if true, no animation will be used
|
// 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) {
|
destroy: function GroupItem_destroy(options) {
|
||||||
let self = this;
|
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
|
// 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"
|
// 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.
|
// event only after all browser tabs in that group are closed.
|
||||||
let shouldRemoveTabItems = [];
|
this._children.concat().forEach(function(child) {
|
||||||
let toClose = this._children.concat();
|
|
||||||
toClose.forEach(function(child) {
|
|
||||||
child.removeSubscriber("close", self._onChildClose);
|
child.removeSubscriber("close", self._onChildClose);
|
||||||
|
|
||||||
let removed = child.close(true);
|
if (child.close(true)) {
|
||||||
if (removed) {
|
self.remove(child, { dontArrange: true });
|
||||||
shouldRemoveTabItems.push(child);
|
|
||||||
} else {
|
} else {
|
||||||
// child.removeSubscriber() must be called before child.close(),
|
// child.removeSubscriber() must be called before child.close(),
|
||||||
// therefore we call child.addSubscriber() if the tab is not removed.
|
// 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) {
|
if (this._children.length) {
|
||||||
// remove children without the assiciated tab and show the group item
|
if (this.hidden)
|
||||||
shouldRemoveTabItems.forEach(function(child) {
|
|
||||||
self.remove(child, { dontArrange: true });
|
|
||||||
});
|
|
||||||
|
|
||||||
this.$undoContainer.fadeOut(function() { self._unhide() });
|
this.$undoContainer.fadeOut(function() { self._unhide() });
|
||||||
|
|
||||||
|
return false;
|
||||||
} else {
|
} else {
|
||||||
this.close(options);
|
this.close(options);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1818,13 +1847,16 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// url - the new tab should open this url as well
|
// url - the new tab should open this url as well
|
||||||
// options - the options object
|
// 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
|
// closedLastTab - boolean indicates the last tab has just been closed
|
||||||
newTab: function GroupItem_newTab(url, options) {
|
newTab: function GroupItem_newTab(url, options) {
|
||||||
if (options && options.closedLastTab)
|
if (options && options.closedLastTab)
|
||||||
UI.closedLastTabInTabView = true;
|
UI.closedLastTabInTabView = true;
|
||||||
|
|
||||||
UI.setActive(this, { dontSetActiveTabInGroup: 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;
|
let self = this;
|
||||||
|
|
||||||
// setup attr modified handler, and prepare for its uninit
|
// setup attr modified handler, and prepare for its uninit
|
||||||
function handleAttrModified(xulTab) {
|
function handleAttrModified(event) {
|
||||||
self._handleAttrModified(xulTab);
|
self._handleAttrModified(event.target);
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure any closed tabs are removed from the delay update list
|
// make sure any closed tabs are removed from the delay update list
|
||||||
function handleClose(xulTab) {
|
function handleClose(event) {
|
||||||
let idx = self._delayedModUpdates.indexOf(xulTab);
|
let idx = self._delayedModUpdates.indexOf(event.target);
|
||||||
if (idx != -1)
|
if (idx != -1)
|
||||||
self._delayedModUpdates.splice(idx, 1);
|
self._delayedModUpdates.splice(idx, 1);
|
||||||
}
|
}
|
||||||
|
@ -2040,7 +2072,7 @@ let GroupItems = {
|
||||||
// Function: _updateAppTabIcons
|
// Function: _updateAppTabIcons
|
||||||
// Update images of any apptab icons that point to passed in xultab
|
// Update images of any apptab icons that point to passed in xultab
|
||||||
_updateAppTabIcons: function GroupItems__updateAppTabIcons(xulTab) {
|
_updateAppTabIcons: function GroupItems__updateAppTabIcons(xulTab) {
|
||||||
if (xulTab.ownerDocument.defaultView != gWindow || !xulTab.pinned)
|
if (!xulTab.pinned)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let iconUrl = this.getAppTabFavIconUrl(xulTab);
|
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) {
|
function hideSearch(event) {
|
||||||
|
if (!isSearchEnabled())
|
||||||
|
return;
|
||||||
|
|
||||||
iQ("#searchbox").val("");
|
iQ("#searchbox").val("");
|
||||||
iQ("#searchshade").hide();
|
iQ("#searchshade").hide();
|
||||||
iQ("#search").hide();
|
iQ("#search").hide();
|
||||||
|
|
|
@ -79,9 +79,6 @@ let Storage = {
|
||||||
|
|
||||||
// ___ Tabs
|
// ___ Tabs
|
||||||
AllTabs.tabs.forEach(function(tab) {
|
AllTabs.tabs.forEach(function(tab) {
|
||||||
if (tab.ownerDocument.defaultView != gWindow)
|
|
||||||
return;
|
|
||||||
|
|
||||||
self.saveTab(tab, null);
|
self.saveTab(tab, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -184,6 +181,23 @@ let Storage = {
|
||||||
return existingData;
|
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
|
// Function: saveGroupItemsData
|
||||||
// Saves the global data for the <GroupItems> singleton for the given window.
|
// 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
|
// closing tab doesn't belong to a group and no empty group, create a new
|
||||||
// one for the new tab.
|
// one for the new tab.
|
||||||
if (!groupClose && gBrowser.tabs.length == 1) {
|
if (!groupClose && gBrowser.tabs.length == 1) {
|
||||||
let group;
|
let group = this.tab._tabViewTabItem.parent;
|
||||||
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());
|
|
||||||
}
|
|
||||||
group.newTab(null, { closedLastTab: true });
|
group.newTab(null, { closedLastTab: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
// when "TabClose" event is fired, the browser tab is about to close and our
|
// 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.
|
// item "close" is fired before the browser tab actually get closed.
|
||||||
// Therefore, we need "tabRemoved" event below.
|
// Therefore, we need "tabRemoved" event below.
|
||||||
gBrowser.removeTab(this.tab);
|
gBrowser.removeTab(this.tab);
|
||||||
let tabNotClosed =
|
let tabClosed = !this.tab;
|
||||||
Array.some(gBrowser.tabs, function(tab) { return tab == this.tab; }, this);
|
|
||||||
if (!tabNotClosed)
|
if (tabClosed)
|
||||||
this._sendToSubscribers("tabRemoved");
|
this._sendToSubscribers("tabRemoved");
|
||||||
|
|
||||||
// No need to explicitly delete the tab data, becasue sessionstore data
|
// No need to explicitly delete the tab data, becasue sessionstore data
|
||||||
// associated with the tab will automatically go away
|
// associated with the tab will automatically go away
|
||||||
return !tabNotClosed;
|
return tabClosed;
|
||||||
},
|
},
|
||||||
|
|
||||||
// ----------
|
// ----------
|
||||||
|
@ -746,27 +739,26 @@ let TabItems = {
|
||||||
this.tempCanvas.height = 112;
|
this.tempCanvas.height = 112;
|
||||||
|
|
||||||
// When a tab is opened, create the TabItem
|
// When a tab is opened, create the TabItem
|
||||||
this._eventListeners["open"] = function(tab) {
|
this._eventListeners.open = function (event) {
|
||||||
if (tab.ownerDocument.defaultView != gWindow || tab.pinned)
|
let tab = event.target;
|
||||||
return;
|
|
||||||
|
|
||||||
|
if (!tab.pinned)
|
||||||
self.link(tab);
|
self.link(tab);
|
||||||
}
|
}
|
||||||
// When a tab's content is loaded, show the canvas and hide the cached data
|
// When a tab's content is loaded, show the canvas and hide the cached data
|
||||||
// if necessary.
|
// if necessary.
|
||||||
this._eventListeners["attrModified"] = function(tab) {
|
this._eventListeners.attrModified = function (event) {
|
||||||
if (tab.ownerDocument.defaultView != gWindow || tab.pinned)
|
let tab = event.target;
|
||||||
return;
|
|
||||||
|
|
||||||
|
if (!tab.pinned)
|
||||||
self.update(tab);
|
self.update(tab);
|
||||||
}
|
}
|
||||||
// When a tab is closed, unlink.
|
// When a tab is closed, unlink.
|
||||||
this._eventListeners["close"] = function(tab) {
|
this._eventListeners.close = function (event) {
|
||||||
if (tab.ownerDocument.defaultView != gWindow || tab.pinned)
|
let tab = event.target;
|
||||||
return;
|
|
||||||
|
|
||||||
// XXX bug #635975 - don't unlink the tab if the dom window is closing.
|
// 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);
|
self.unlink(tab);
|
||||||
}
|
}
|
||||||
for (let name in this._eventListeners) {
|
for (let name in this._eventListeners) {
|
||||||
|
@ -774,8 +766,8 @@ let TabItems = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// For each tab, create the link.
|
// For each tab, create the link.
|
||||||
AllTabs.tabs.forEach(function(tab) {
|
AllTabs.tabs.forEach(function (tab) {
|
||||||
if (tab.ownerDocument.defaultView != gWindow || tab.pinned)
|
if (tab.pinned)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
self.link(tab, {immediately: true});
|
self.link(tab, {immediately: true});
|
||||||
|
|
|
@ -5,7 +5,6 @@ const Ci = Components.interfaces;
|
||||||
const Cu = Components.utils;
|
const Cu = Components.utils;
|
||||||
const Cr = Components.results;
|
const Cr = Components.results;
|
||||||
|
|
||||||
Cu.import("resource:///modules/tabview/AllTabs.jsm");
|
|
||||||
Cu.import("resource:///modules/tabview/utils.jsm");
|
Cu.import("resource:///modules/tabview/utils.jsm");
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.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 gBrowserPanel = gWindow.document.getElementById("browser-panel");
|
||||||
var gTabViewFrame = gWindow.document.getElementById("tab-view");
|
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
|
# NB: Certain files need to evaluate before others
|
||||||
|
|
||||||
#include iq.js
|
#include iq.js
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
* Raymond Lee <raymond@appcoast.com>
|
* Raymond Lee <raymond@appcoast.com>
|
||||||
* Sean Dunn <seanedunn@yahoo.com>
|
* Sean Dunn <seanedunn@yahoo.com>
|
||||||
* Tim Taubert <tim.taubert@gmx.de>
|
* 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
|
* 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
|
* 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.
|
// If true, a closed tab has just been restored.
|
||||||
restoredClosedTab: false,
|
restoredClosedTab: false,
|
||||||
|
|
||||||
|
// Variable: _isChangingVisibility
|
||||||
|
// Tracks whether we're currently in the process of showing/hiding the tabview.
|
||||||
|
_isChangingVisibility: false,
|
||||||
|
|
||||||
// Variable: _reorderTabItemsOnShow
|
// Variable: _reorderTabItemsOnShow
|
||||||
// Keeps track of the <GroupItem>s which their tab items' tabs have been moved
|
// Keeps track of the <GroupItem>s which their tab items' tabs have been moved
|
||||||
// and re-orders the tab items when switching to TabView.
|
// and re-orders the tab items when switching to TabView.
|
||||||
|
@ -123,9 +128,9 @@ let UI = {
|
||||||
wasInTabView: false
|
wasInTabView: false
|
||||||
},
|
},
|
||||||
|
|
||||||
// Variable: _storageBusyCount
|
// Variable: _storageBusy
|
||||||
// Used to keep track of how many calls to storageBusy vs storageReady.
|
// Tells whether the storage is currently busy or not.
|
||||||
_storageBusyCount: 0,
|
_storageBusy: false,
|
||||||
|
|
||||||
// Variable: isDOMWindowClosing
|
// Variable: isDOMWindowClosing
|
||||||
// Tells wether the parent window is about to close
|
// Tells wether the parent window is about to close
|
||||||
|
@ -169,6 +174,10 @@ let UI = {
|
||||||
|
|
||||||
// ___ storage
|
// ___ storage
|
||||||
Storage.init();
|
Storage.init();
|
||||||
|
|
||||||
|
if (Storage.readWindowBusyState(gWindow))
|
||||||
|
this.storageBusy();
|
||||||
|
|
||||||
let data = Storage.readUIData(gWindow);
|
let data = Storage.readUIData(gWindow);
|
||||||
this._storageSanity(data);
|
this._storageSanity(data);
|
||||||
this._pageBounds = data.pageBounds;
|
this._pageBounds = data.pageBounds;
|
||||||
|
@ -230,6 +239,15 @@ let UI = {
|
||||||
self.uninit();
|
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
|
// ___ setup key handlers
|
||||||
this._setTabViewFrameKeyHandlers();
|
this._setTabViewFrameKeyHandlers();
|
||||||
|
|
||||||
|
@ -272,6 +290,10 @@ let UI = {
|
||||||
self._save();
|
self._save();
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
|
// ___ load frame script
|
||||||
|
let frameScript = "chrome://browser/content/tabview-content.js";
|
||||||
|
gWindow.messageManager.loadFrameScript(frameScript, true);
|
||||||
|
|
||||||
// ___ Done
|
// ___ Done
|
||||||
this._frameInitialized = true;
|
this._frameInitialized = true;
|
||||||
this._save();
|
this._save();
|
||||||
|
@ -477,9 +499,11 @@ let UI = {
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// zoomOut - true for zoom out animation, false for nothing.
|
// zoomOut - true for zoom out animation, false for nothing.
|
||||||
showTabView: function UI_showTabView(zoomOut) {
|
showTabView: function UI_showTabView(zoomOut) {
|
||||||
if (this.isTabViewVisible())
|
if (this.isTabViewVisible() || this._isChangingVisibility)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
this._isChangingVisibility = true;
|
||||||
|
|
||||||
// initialize the direction of the page
|
// initialize the direction of the page
|
||||||
this._initPageDirection();
|
this._initPageDirection();
|
||||||
|
|
||||||
|
@ -522,6 +546,7 @@ let UI = {
|
||||||
self.setActive(item);
|
self.setActive(item);
|
||||||
|
|
||||||
self._resize(true);
|
self._resize(true);
|
||||||
|
self._isChangingVisibility = false;
|
||||||
dispatchEvent(event);
|
dispatchEvent(event);
|
||||||
|
|
||||||
// Flush pending updates
|
// Flush pending updates
|
||||||
|
@ -531,6 +556,7 @@ let UI = {
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
self.clearActiveTab();
|
self.clearActiveTab();
|
||||||
|
self._isChangingVisibility = false;
|
||||||
dispatchEvent(event);
|
dispatchEvent(event);
|
||||||
|
|
||||||
// Flush pending updates
|
// Flush pending updates
|
||||||
|
@ -547,9 +573,11 @@ let UI = {
|
||||||
// Function: hideTabView
|
// Function: hideTabView
|
||||||
// Hides TabView and shows the main browser UI.
|
// Hides TabView and shows the main browser UI.
|
||||||
hideTabView: function UI_hideTabView() {
|
hideTabView: function UI_hideTabView() {
|
||||||
if (!this.isTabViewVisible())
|
if (!this.isTabViewVisible() || this._isChangingVisibility)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
this._isChangingVisibility = true;
|
||||||
|
|
||||||
// another tab might be select if user decides to stay on a page when
|
// another tab might be select if user decides to stay on a page when
|
||||||
// a onclose confirmation prompts.
|
// a onclose confirmation prompts.
|
||||||
GroupItems.removeHiddenGroups();
|
GroupItems.removeHiddenGroups();
|
||||||
|
@ -576,6 +604,8 @@ let UI = {
|
||||||
#endif
|
#endif
|
||||||
Storage.saveVisibilityData(gWindow, "false");
|
Storage.saveVisibilityData(gWindow, "false");
|
||||||
|
|
||||||
|
this._isChangingVisibility = false;
|
||||||
|
|
||||||
let event = document.createEvent("Events");
|
let event = document.createEvent("Events");
|
||||||
event.initEvent("tabviewhidden", true, false);
|
event.initEvent("tabviewhidden", true, false);
|
||||||
dispatchEvent(event);
|
dispatchEvent(event);
|
||||||
|
@ -612,12 +642,13 @@ let UI = {
|
||||||
// Pauses the storage activity that conflicts with sessionstore updates and
|
// Pauses the storage activity that conflicts with sessionstore updates and
|
||||||
// private browsing mode switches. Calls can be nested.
|
// private browsing mode switches. Calls can be nested.
|
||||||
storageBusy: function UI_storageBusy() {
|
storageBusy: function UI_storageBusy() {
|
||||||
if (!this._storageBusyCount) {
|
if (this._storageBusy)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this._storageBusy = true;
|
||||||
|
|
||||||
TabItems.pauseReconnecting();
|
TabItems.pauseReconnecting();
|
||||||
GroupItems.pauseAutoclose();
|
GroupItems.pauseAutoclose();
|
||||||
}
|
|
||||||
|
|
||||||
this._storageBusyCount++;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// ----------
|
// ----------
|
||||||
|
@ -625,8 +656,11 @@ let UI = {
|
||||||
// Resumes the activity paused by storageBusy, and updates for any new group
|
// Resumes the activity paused by storageBusy, and updates for any new group
|
||||||
// information in sessionstore. Calls can be nested.
|
// information in sessionstore. Calls can be nested.
|
||||||
storageReady: function UI_storageReady() {
|
storageReady: function UI_storageReady() {
|
||||||
this._storageBusyCount--;
|
if (!this._storageBusy)
|
||||||
if (!this._storageBusyCount) {
|
return;
|
||||||
|
|
||||||
|
this._storageBusy = false;
|
||||||
|
|
||||||
let hasGroupItemsData = GroupItems.load();
|
let hasGroupItemsData = GroupItems.load();
|
||||||
if (!hasGroupItemsData)
|
if (!hasGroupItemsData)
|
||||||
this.reset();
|
this.reset();
|
||||||
|
@ -634,7 +668,6 @@ let UI = {
|
||||||
TabItems.resumeReconnecting();
|
TabItems.resumeReconnecting();
|
||||||
GroupItems._updateTabBar();
|
GroupItems._updateTabBar();
|
||||||
GroupItems.resumeAutoclose();
|
GroupItems.resumeAutoclose();
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// ----------
|
// ----------
|
||||||
|
@ -678,6 +711,7 @@ let UI = {
|
||||||
}
|
}
|
||||||
} else if (topic == "private-browsing-change-granted") {
|
} else if (topic == "private-browsing-change-granted") {
|
||||||
if (data == "enter" || data == "exit") {
|
if (data == "enter" || data == "exit") {
|
||||||
|
hideSearch();
|
||||||
self._privateBrowsing.transitionMode = data;
|
self._privateBrowsing.transitionMode = data;
|
||||||
self.storageBusy();
|
self.storageBusy();
|
||||||
}
|
}
|
||||||
|
@ -703,9 +737,8 @@ let UI = {
|
||||||
});
|
});
|
||||||
|
|
||||||
// TabOpen
|
// TabOpen
|
||||||
this._eventListeners.open = function(tab) {
|
this._eventListeners.open = function (event) {
|
||||||
if (tab.ownerDocument.defaultView != gWindow)
|
let tab = event.target;
|
||||||
return;
|
|
||||||
|
|
||||||
// if it's an app tab, add it to all the group items
|
// if it's an app tab, add it to all the group items
|
||||||
if (tab.pinned)
|
if (tab.pinned)
|
||||||
|
@ -715,9 +748,8 @@ let UI = {
|
||||||
};
|
};
|
||||||
|
|
||||||
// TabClose
|
// TabClose
|
||||||
this._eventListeners.close = function(tab) {
|
this._eventListeners.close = function (event) {
|
||||||
if (tab.ownerDocument.defaultView != gWindow)
|
let tab = event.target;
|
||||||
return;
|
|
||||||
|
|
||||||
// if it's an app tab, remove it from all the group items
|
// if it's an app tab, remove it from all the group items
|
||||||
if (tab.pinned)
|
if (tab.pinned)
|
||||||
|
@ -730,7 +762,7 @@ let UI = {
|
||||||
} else {
|
} else {
|
||||||
// If we're currently in the process of entering private browsing,
|
// If we're currently in the process of entering private browsing,
|
||||||
// we don't want to go to the Tab View UI.
|
// we don't want to go to the Tab View UI.
|
||||||
if (self._storageBusyCount)
|
if (self._storageBusy)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// if not closing the last tab
|
// if not closing the last tab
|
||||||
|
@ -749,21 +781,14 @@ let UI = {
|
||||||
groupItem._children.length == 1 &&
|
groupItem._children.length == 1 &&
|
||||||
groupItem._children[0].tab == tab);
|
groupItem._children[0].tab == tab);
|
||||||
|
|
||||||
// 2) Take care of the case where you've closed the last tab in
|
// 2) When a blank tab is active while restoring a closed tab the
|
||||||
// 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
|
|
||||||
// blank tab gets removed. The active group is not closed as this is
|
// blank tab gets removed. The active group is not closed as this is
|
||||||
// where the restored tab goes. So do not show the TabView.
|
// where the restored tab goes. So do not show the TabView.
|
||||||
let tabItem = tab && tab._tabViewTabItem;
|
let tabItem = tab && tab._tabViewTabItem;
|
||||||
let closingBlankTabAfterRestore =
|
let closingBlankTabAfterRestore =
|
||||||
(tabItem && tabItem.isRemovedAfterRestore);
|
(tabItem && tabItem.isRemovedAfterRestore);
|
||||||
|
|
||||||
if ((closingLastOfGroup || closingUnnamedGroup) &&
|
if (closingLastOfGroup && !closingBlankTabAfterRestore) {
|
||||||
!closingBlankTabAfterRestore) {
|
|
||||||
// for the tab focus event to pick up.
|
// for the tab focus event to pick up.
|
||||||
self._closedLastVisibleTab = true;
|
self._closedLastVisibleTab = true;
|
||||||
self.showTabView();
|
self.showTabView();
|
||||||
|
@ -773,9 +798,8 @@ let UI = {
|
||||||
};
|
};
|
||||||
|
|
||||||
// TabMove
|
// TabMove
|
||||||
this._eventListeners.move = function(tab) {
|
this._eventListeners.move = function (event) {
|
||||||
if (tab.ownerDocument.defaultView != gWindow)
|
let tab = event.target;
|
||||||
return;
|
|
||||||
|
|
||||||
if (GroupItems.groupItems.length > 0) {
|
if (GroupItems.groupItems.length > 0) {
|
||||||
if (tab.pinned) {
|
if (tab.pinned) {
|
||||||
|
@ -790,26 +814,21 @@ let UI = {
|
||||||
};
|
};
|
||||||
|
|
||||||
// TabSelect
|
// TabSelect
|
||||||
this._eventListeners.select = function(tab) {
|
this._eventListeners.select = function (event) {
|
||||||
if (tab.ownerDocument.defaultView != gWindow)
|
self.onTabSelect(event.target);
|
||||||
return;
|
|
||||||
|
|
||||||
self.onTabSelect(tab);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// TabPinned
|
// TabPinned
|
||||||
this._eventListeners.pinned = function(tab) {
|
this._eventListeners.pinned = function (event) {
|
||||||
if (tab.ownerDocument.defaultView != gWindow)
|
let tab = event.target;
|
||||||
return;
|
|
||||||
|
|
||||||
TabItems.handleTabPin(tab);
|
TabItems.handleTabPin(tab);
|
||||||
GroupItems.addAppTab(tab);
|
GroupItems.addAppTab(tab);
|
||||||
};
|
};
|
||||||
|
|
||||||
// TabUnpinned
|
// TabUnpinned
|
||||||
this._eventListeners.unpinned = function(tab) {
|
this._eventListeners.unpinned = function (event) {
|
||||||
if (tab.ownerDocument.defaultView != gWindow)
|
let tab = event.target;
|
||||||
return;
|
|
||||||
|
|
||||||
TabItems.handleTabUnpin(tab);
|
TabItems.handleTabUnpin(tab);
|
||||||
GroupItems.removeAppTab(tab);
|
GroupItems.removeAppTab(tab);
|
||||||
|
@ -883,8 +902,14 @@ let UI = {
|
||||||
|
|
||||||
// if TabView is visible but we didn't just close the last tab or
|
// if TabView is visible but we didn't just close the last tab or
|
||||||
// selected tab, show chrome.
|
// 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();
|
this.hideTabView();
|
||||||
|
}
|
||||||
|
|
||||||
// another tab might be selected when hideTabView() is invoked so a
|
// another tab might be selected when hideTabView() is invoked so a
|
||||||
// validation is needed.
|
// 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
|
// Function: setReorderTabsOnHide
|
||||||
// Sets the groupItem which the tab items' tabs should be re-ordered when
|
// 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_bug625269.js \
|
||||||
browser_tabview_bug625424.js \
|
browser_tabview_bug625424.js \
|
||||||
browser_tabview_bug626368.js \
|
browser_tabview_bug626368.js \
|
||||||
|
browser_tabview_bug626455.js \
|
||||||
browser_tabview_bug626525.js \
|
browser_tabview_bug626525.js \
|
||||||
browser_tabview_bug626791.js \
|
browser_tabview_bug626791.js \
|
||||||
browser_tabview_bug627239.js \
|
browser_tabview_bug627239.js \
|
||||||
|
@ -139,6 +140,7 @@ _BROWSER_FILES = \
|
||||||
browser_tabview_bug649006.js \
|
browser_tabview_bug649006.js \
|
||||||
browser_tabview_bug649307.js \
|
browser_tabview_bug649307.js \
|
||||||
browser_tabview_bug649319.js \
|
browser_tabview_bug649319.js \
|
||||||
|
browser_tabview_bug650280.js \
|
||||||
browser_tabview_bug650573.js \
|
browser_tabview_bug650573.js \
|
||||||
browser_tabview_bug651311.js \
|
browser_tabview_bug651311.js \
|
||||||
browser_tabview_bug654721.js \
|
browser_tabview_bug654721.js \
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
/* Any copyright is dedicated to the Public Domain.
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
Cu.import("resource:///modules/tabview/AllTabs.jsm");
|
|
||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
waitForExplicitFinish();
|
waitForExplicitFinish();
|
||||||
|
|
||||||
|
let AllTabs;
|
||||||
let newTab = gBrowser.addTab();
|
let newTab = gBrowser.addTab();
|
||||||
|
|
||||||
// TabPinned
|
// 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");
|
is(tab, newTab, "The tabs are the same after the tab is pinned");
|
||||||
ok(tab.pinned, "The tab gets pinned");
|
ok(tab.pinned, "The tab gets pinned");
|
||||||
|
|
||||||
|
@ -17,7 +18,9 @@ function test() {
|
||||||
};
|
};
|
||||||
|
|
||||||
// TabUnpinned
|
// TabUnpinned
|
||||||
let unpinned = function(tab) {
|
let unpinned = function (event) {
|
||||||
|
let tab = event.target;
|
||||||
|
|
||||||
AllTabs.unregister("pinned", pinned);
|
AllTabs.unregister("pinned", pinned);
|
||||||
AllTabs.unregister("unpinned", unpinned);
|
AllTabs.unregister("unpinned", unpinned);
|
||||||
|
|
||||||
|
@ -26,13 +29,17 @@ function test() {
|
||||||
|
|
||||||
// clean up and finish
|
// clean up and finish
|
||||||
gBrowser.removeTab(tab);
|
gBrowser.removeTab(tab);
|
||||||
finish();
|
hideTabView(finish);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
showTabView(function () {
|
||||||
|
AllTabs = TabView.getContentWindow().AllTabs;
|
||||||
|
|
||||||
AllTabs.register("pinned", pinned);
|
AllTabs.register("pinned", pinned);
|
||||||
AllTabs.register("unpinned", unpinned);
|
AllTabs.register("unpinned", unpinned);
|
||||||
|
|
||||||
ok(!newTab.pinned, "The tab is not pinned");
|
ok(!newTab.pinned, "The tab is not pinned");
|
||||||
gBrowser.pinTab(newTab);
|
gBrowser.pinTab(newTab);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ function setupOne(win) {
|
||||||
afterAllTabsLoaded(function () setupTwo(win), win);
|
afterAllTabsLoaded(function () setupTwo(win), win);
|
||||||
}
|
}
|
||||||
|
|
||||||
let restoreWin;
|
let restoredWin;
|
||||||
|
|
||||||
function setupTwo(win) {
|
function setupTwo(win) {
|
||||||
let contentWindow = win.TabView.getContentWindow();
|
let contentWindow = win.TabView.getContentWindow();
|
||||||
|
@ -37,26 +37,20 @@ function setupTwo(win) {
|
||||||
contentWindow.TabItems.update(tabItem.tab);
|
contentWindow.TabItems.update(tabItem.tab);
|
||||||
tabItem.addSubscriber("savedCachedImageData", function onSaved(item) {
|
tabItem.addSubscriber("savedCachedImageData", function onSaved(item) {
|
||||||
item.removeSubscriber("savedCachedImageData", onSaved);
|
item.removeSubscriber("savedCachedImageData", onSaved);
|
||||||
--numTabsToSave;
|
|
||||||
|
if (!--numTabsToSave)
|
||||||
|
restoreWindow();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// after the window is closed, restore it.
|
// after the window is closed, restore it.
|
||||||
let xulWindowDestory = function() {
|
let restoreWindow = 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
|
|
||||||
executeSoon(function() {
|
executeSoon(function() {
|
||||||
restoredWin = undoCloseWindow();
|
restoredWin = undoCloseWindow();
|
||||||
restoredWin.addEventListener("load", function onLoad(event) {
|
restoredWin.addEventListener("load", function onLoad(event) {
|
||||||
restoredWin.removeEventListener("load", onLoad, false);
|
restoredWin.removeEventListener("load", onLoad, false);
|
||||||
|
|
||||||
registerCleanupFunction(function() restoredWin.close());
|
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");
|
is(restoredWin.gBrowser.tabs.length, 3, "The total number of tabs is 3");
|
||||||
|
|
||||||
// setup tab variables and listen to the tabs load progress
|
// setup tab variables and listen to the tabs load progress
|
||||||
|
@ -103,7 +97,6 @@ function setupTwo(win) {
|
||||||
}, false);
|
}, false);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
Services.obs.addObserver(xulWindowDestory, "xul-window-destroyed", false);
|
|
||||||
|
|
||||||
win.close();
|
win.close();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ function test() {
|
||||||
function part1(win) {
|
function part1(win) {
|
||||||
registerCleanupFunction(function() win.close());
|
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");
|
is(contentWindow.GroupItems.groupItems.length, 1, "Has only one group");
|
||||||
|
|
||||||
let originalTab = win.gBrowser.selectedTab;
|
let originalTab = win.gBrowser.selectedTab;
|
||||||
|
@ -71,15 +71,12 @@ function part2(win) {
|
||||||
// switch the selected tab to new tab
|
// switch the selected tab to new tab
|
||||||
win.gBrowser.selectedTab = newTab;
|
win.gBrowser.selectedTab = newTab;
|
||||||
|
|
||||||
whenTabViewIsHidden(function () {
|
showTabView(function () {
|
||||||
is(win.gBrowser.selectedTab, newTab, "The seleted tab should be the same as before (new tab)");
|
hideTabView(function () {
|
||||||
win.close();
|
is(win.gBrowser.selectedTab, newTab,
|
||||||
finish();
|
"The selected tab should be the same as before (new tab)");
|
||||||
});
|
waitForFocus(finish);
|
||||||
|
}, win);
|
||||||
// show tabview
|
}, win);
|
||||||
EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true }, win);
|
}, win);
|
||||||
// hide tabview
|
|
||||||
EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true }, win);
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,9 +21,7 @@ function onTabViewShown() {
|
||||||
|
|
||||||
function testStayOnPage(contentWindow, groupItemOne, groupItemTwo) {
|
function testStayOnPage(contentWindow, groupItemOne, groupItemTwo) {
|
||||||
whenDialogOpened(function (dialog) {
|
whenDialogOpened(function (dialog) {
|
||||||
groupItemTwo.addSubscriber("groupShown", function onShown() {
|
executeSoon(function () {
|
||||||
groupItemTwo.removeSubscriber("groupShown", onShown);
|
|
||||||
|
|
||||||
is(gBrowser.tabs.length, 2,
|
is(gBrowser.tabs.length, 2,
|
||||||
"The total number of tab is 2 when staying on the page");
|
"The total number of tab is 2 when staying on the page");
|
||||||
is(contentWindow.TabItems.getItems().length, 2,
|
is(contentWindow.TabItems.getItems().length, 2,
|
||||||
|
|
|
@ -25,6 +25,7 @@ function test1() {
|
||||||
is(groupItems.length, 1, "there is one groupItem");
|
is(groupItems.length, 1, "there is one groupItem");
|
||||||
|
|
||||||
whenTabViewIsHidden(function() {
|
whenTabViewIsHidden(function() {
|
||||||
|
gBrowser.selectedTab = gBrowser.tabs[0];
|
||||||
is(groupItems.length, 2, "there are two groupItems");
|
is(groupItems.length, 2, "there are two groupItems");
|
||||||
closeGroupItem(groupItems[1], finish);
|
closeGroupItem(groupItems[1], finish);
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,6 +18,6 @@ function test() {
|
||||||
cw.GroupItems.resumeArrange();
|
cw.GroupItems.resumeArrange();
|
||||||
ok(groupItem.isStacked(), 'groupItem is now stacked');
|
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");
|
ok(!document.getElementById("context_openTabInWindow").disabled, "The 'Move to New Window' menu item is enabled");
|
||||||
|
|
||||||
let newTabTwo = gBrowser.selectedTab;
|
let newTabTwo = gBrowser.selectedTab;
|
||||||
gBrowser.selected = originalTab;
|
gBrowser.selectedTab = originalTab;
|
||||||
|
|
||||||
gBrowser.removeTab(newTabOne);
|
gBrowser.removeTab(newTabOne);
|
||||||
gBrowser.removeTab(newTabTwo);
|
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) {
|
function testTopOfStack(win) {
|
||||||
registerCleanupFunction(function () { win.close(); });
|
registerCleanupFunction(function () { win.close(); });
|
||||||
let cw = win.TabView.getContentWindow();
|
let cw = win.TabView.getContentWindow();
|
||||||
groupItem = cw.GroupItems.getActiveGroupItem();
|
let groupItem = cw.GroupItems.getActiveGroupItem();
|
||||||
ok(!groupItem.isStacked(), 'groupItem is not stacked');
|
ok(!groupItem.isStacked(), 'groupItem is not stacked');
|
||||||
groupItem.setSize(150, 150);
|
groupItem.setSize(150, 150);
|
||||||
groupItem.setUserSize();
|
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);
|
EventUtils.synthesizeMouse(target, 600, 5, {type: "mouseup"}, cw);
|
||||||
|
|
||||||
checkNumberOfGroupItems(2);
|
checkNumberOfGroupItems(2);
|
||||||
next();
|
closeGroupItem(cw.GroupItems.groupItems[1], next);
|
||||||
}, win);
|
}, win);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,49 +3,32 @@
|
||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
waitForExplicitFinish();
|
waitForExplicitFinish();
|
||||||
|
showTabView(onTabViewShown);
|
||||||
window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
|
||||||
TabView.toggle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onTabViewWindowLoaded() {
|
function onTabViewShown() {
|
||||||
window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
|
||||||
|
|
||||||
ok(TabView.isVisible(), "Tab View is visible");
|
ok(TabView.isVisible(), "Tab View is visible");
|
||||||
|
|
||||||
let contentWindow = document.getElementById("tab-view").contentWindow;
|
let contentWindow = TabView.getContentWindow();
|
||||||
let [originalTab] = gBrowser.visibleTabs;
|
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
|
// create group one and two
|
||||||
let boxOne = new contentWindow.Rect(20, 20, 300, 300);
|
let groupOne = createGroupItem(20, 20, 300, 300);
|
||||||
let groupOne = new contentWindow.GroupItem([], { bounds: boxOne });
|
let groupTwo = createGroupItem(20, 400, 300, 300);
|
||||||
ok(groupOne.isEmpty(), "This group is empty");
|
|
||||||
|
|
||||||
let boxTwo = new contentWindow.Rect(20, 400, 300, 300);
|
waitForFocus(function () {
|
||||||
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);
|
|
||||||
addTest(contentWindow, groupOne.id, groupTwo.id, originalTab);
|
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) {
|
function addTest(contentWindow, groupOneId, groupTwoId, originalTab) {
|
||||||
|
@ -75,23 +58,12 @@ function addTest(contentWindow, groupOneId, groupTwoId, originalTab) {
|
||||||
is(groupTwo.getChildren().length, ++groupTwoTabItemCount,
|
is(groupTwo.getChildren().length, ++groupTwoTabItemCount,
|
||||||
"The number of children in group two is increased by 1");
|
"The number of children in group two is increased by 1");
|
||||||
|
|
||||||
let onTabViewHidden = function() {
|
closeGroupItem(groupOne, function () {
|
||||||
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
closeGroupItem(groupTwo, function () hideTabView(finish));
|
||||||
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();
|
|
||||||
});
|
});
|
||||||
window.addEventListener("tabviewhidden", onTabViewHidden, false);
|
|
||||||
gBrowser.selectedTab = originalTab;
|
|
||||||
}
|
}
|
||||||
groupTwo.addSubscriber("childAdded", endGame);
|
|
||||||
|
|
||||||
|
groupTwo.addSubscriber("childAdded", endGame);
|
||||||
simulateDragDrop(tabItem.container, offsetX, offsetY, contentWindow);
|
simulateDragDrop(tabItem.container, offsetX, offsetY, contentWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
/* Any copyright is dedicated to the Public Domain.
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
let timerId;
|
|
||||||
let newWin;
|
let newWin;
|
||||||
|
|
||||||
// ----------
|
// ----------
|
||||||
function test() {
|
function test() {
|
||||||
waitForExplicitFinish();
|
waitForExplicitFinish();
|
||||||
|
|
||||||
// launch tab view for the first time
|
let panelSelected = false;
|
||||||
newWindowWithTabView(function() {}, function(win) {
|
registerCleanupFunction(function () ok(panelSelected, "panel is selected"));
|
||||||
|
|
||||||
|
let onLoad = function (win) {
|
||||||
|
registerCleanupFunction(function () win.close());
|
||||||
|
|
||||||
newWin = win;
|
newWin = win;
|
||||||
|
|
||||||
let onSelect = function(event) {
|
let onSelect = function(event) {
|
||||||
|
@ -21,27 +24,26 @@ function test() {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
deck.removeEventListener("select", onSelect, true);
|
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() {
|
executeSoon(function() {
|
||||||
testMethodToHideAndShowTabView(function() {
|
testMethodToHideAndShowTabView(function() {
|
||||||
newWin.document.getElementById("menu_tabview").doCommand();
|
newWin.document.getElementById("menu_tabview").doCommand();
|
||||||
}, function() {
|
}, function() {
|
||||||
testMethodToHideAndShowTabView(function() {
|
testMethodToHideAndShowTabView(function() {
|
||||||
EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true }, newWin);
|
EventUtils.synthesizeKey("E", { accelKey: true, shiftKey: true }, newWin);
|
||||||
}, finish);
|
}, finish);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}, win);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let deck = win.document.getElementById("tab-view-deck");
|
newWindowWithTabView(onShow, onLoad);
|
||||||
deck.addEventListener("select", onSelect, true);
|
|
||||||
});
|
|
||||||
|
|
||||||
registerCleanupFunction(function () {
|
|
||||||
newWin.close();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMethodToHideAndShowTabView(executeFunc, callback) {
|
function testMethodToHideAndShowTabView(executeFunc, callback) {
|
||||||
|
|
|
@ -49,11 +49,15 @@ function onTabViewLoadedAndShown() {
|
||||||
groupTitles[a] = gi.getTitle();
|
groupTitles[a] = gi.getTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
contentWindow.gPrefBranch.setBoolPref("animate_zoom", false);
|
||||||
|
|
||||||
// Create a second tab
|
// Create a second tab
|
||||||
gBrowser.addTab("about:robots");
|
gBrowser.addTab("about:robots");
|
||||||
is(gBrowser.tabs.length, 2, "we now have 2 tabs");
|
is(gBrowser.tabs.length, 2, "we now have 2 tabs");
|
||||||
|
|
||||||
registerCleanupFunction(function() {
|
registerCleanupFunction(function() {
|
||||||
gBrowser.removeTab(gBrowser.tabs[1]);
|
gBrowser.removeTab(gBrowser.tabs[1]);
|
||||||
|
contentWindow.gPrefBranch.clearUserPref("animate_zoom");
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAllTabsLoaded(function() {
|
afterAllTabsLoaded(function() {
|
||||||
|
|
|
@ -361,7 +361,10 @@ function togglePrivateBrowsing(callback) {
|
||||||
|
|
||||||
Services.obs.addObserver(function observe() {
|
Services.obs.addObserver(function observe() {
|
||||||
Services.obs.removeObserver(observe, topic);
|
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);
|
}, topic, false);
|
||||||
|
|
||||||
let pb = Cc["@mozilla.org/privatebrowsing;1"].
|
let pb = Cc["@mozilla.org/privatebrowsing;1"].
|
||||||
|
|
|
@ -53,6 +53,7 @@ browser.jar:
|
||||||
content/browser/tabview.css (content/tabview/tabview.css)
|
content/browser/tabview.css (content/tabview/tabview.css)
|
||||||
* content/browser/tabview.js (content/tabview/tabview.js)
|
* content/browser/tabview.js (content/tabview/tabview.js)
|
||||||
content/browser/tabview.html (content/tabview/tabview.html)
|
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/urlbarBindings.xml (content/urlbarBindings.xml)
|
||||||
* content/browser/utilityOverlay.js (content/utilityOverlay.js)
|
* content/browser/utilityOverlay.js (content/utilityOverlay.js)
|
||||||
* content/browser/web-panels.js (content/web-panels.js)
|
* content/browser/web-panels.js (content/web-panels.js)
|
||||||
|
|
|
@ -256,7 +256,8 @@ FeedWriter.prototype = {
|
||||||
__contentSandbox: null,
|
__contentSandbox: null,
|
||||||
get _contentSandbox() {
|
get _contentSandbox() {
|
||||||
if (!this.__contentSandbox)
|
if (!this.__contentSandbox)
|
||||||
this.__contentSandbox = new Cu.Sandbox(this._window);
|
this.__contentSandbox = new Cu.Sandbox(this._window,
|
||||||
|
{sandboxName: 'FeedWriter'});
|
||||||
|
|
||||||
return this.__contentSandbox;
|
return this.__contentSandbox;
|
||||||
},
|
},
|
||||||
|
|
|
@ -619,11 +619,9 @@ PrivateBrowsingService.prototype = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Plugin data
|
// Plugin data
|
||||||
let (ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost)) {
|
|
||||||
const phInterface = Ci.nsIPluginHost;
|
const phInterface = Ci.nsIPluginHost;
|
||||||
const FLAG_CLEAR_ALL = phInterface.FLAG_CLEAR_ALL;
|
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();
|
let tags = ph.getPluginTags();
|
||||||
for (let i = 0; i < tags.length; i++) {
|
for (let i = 0; i < tags.length; i++) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -59,7 +59,7 @@ window.onload = function() {
|
||||||
gStateObject = JSON.parse(sessionData.value);
|
gStateObject = JSON.parse(sessionData.value);
|
||||||
}
|
}
|
||||||
catch (exJSON) {
|
catch (exJSON) {
|
||||||
var s = new Cu.Sandbox("about:blank");
|
var s = new Cu.Sandbox("about:blank", {sandboxName: 'aboutSessionRestore'});
|
||||||
gStateObject = Cu.evalInSandbox("(" + sessionData.value + ")", s);
|
gStateObject = Cu.evalInSandbox("(" + sessionData.value + ")", s);
|
||||||
// If we couldn't parse the string with JSON.parse originally, make sure
|
// If we couldn't parse the string with JSON.parse originally, make sure
|
||||||
// that the value in the textbox will be parsable.
|
// that the value in the textbox will be parsable.
|
||||||
|
|
|
@ -135,7 +135,7 @@ SessionStartup.prototype = {
|
||||||
this._initialState = JSON.parse(iniString);
|
this._initialState = JSON.parse(iniString);
|
||||||
}
|
}
|
||||||
catch (exJSON) {
|
catch (exJSON) {
|
||||||
var s = new Cu.Sandbox("about:blank");
|
var s = new Cu.Sandbox("about:blank", {sandboxName: 'nsSessionStartup'});
|
||||||
this._initialState = Cu.evalInSandbox("(" + iniString + ")", s);
|
this._initialState = Cu.evalInSandbox("(" + iniString + ")", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -785,7 +785,7 @@ SessionStoreService.prototype = {
|
||||||
aWindow.__SSi = "window" + Date.now();
|
aWindow.__SSi = "window" + Date.now();
|
||||||
|
|
||||||
// and create its data object
|
// 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))
|
if (!this._isWindowLoaded(aWindow))
|
||||||
this._windows[aWindow.__SSi]._restoring = true;
|
this._windows[aWindow.__SSi]._restoring = true;
|
||||||
if (!aWindow.toolbar.visible)
|
if (!aWindow.toolbar.visible)
|
||||||
|
@ -969,6 +969,9 @@ SessionStoreService.prototype = {
|
||||||
// save the window if it has multiple tabs or a single saveable tab
|
// save the window if it has multiple tabs or a single saveable tab
|
||||||
if (winData.tabs.length > 1 ||
|
if (winData.tabs.length > 1 ||
|
||||||
(winData.tabs.length == 1 && this._shouldSaveTabState(winData.tabs[0]))) {
|
(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._closedWindows.unshift(winData);
|
||||||
this._capClosedWindows();
|
this._capClosedWindows();
|
||||||
}
|
}
|
||||||
|
@ -1265,7 +1268,7 @@ SessionStoreService.prototype = {
|
||||||
throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
|
throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
var window = aTab.ownerDocument.defaultView;
|
var window = aTab.ownerDocument.defaultView;
|
||||||
this._sendWindowStateEvent(window, "Busy");
|
this._setWindowStateBusy(window);
|
||||||
this.restoreHistoryPrecursor(window, [aTab], [tabState], 0, 0, 0);
|
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.index = Math.max(1, Math.min(tabState.index, tabState.entries.length));
|
||||||
tabState.pinned = false;
|
tabState.pinned = false;
|
||||||
|
|
||||||
this._sendWindowStateEvent(aWindow, "Busy");
|
this._setWindowStateBusy(aWindow);
|
||||||
let newTab = aTab == aWindow.gBrowser.selectedTab ?
|
let newTab = aTab == aWindow.gBrowser.selectedTab ?
|
||||||
aWindow.gBrowser.addTab(null, {relatedToCurrent: true, ownerTab: aTab}) :
|
aWindow.gBrowser.addTab(null, {relatedToCurrent: true, ownerTab: aTab}) :
|
||||||
aWindow.gBrowser.addTab();
|
aWindow.gBrowser.addTab();
|
||||||
|
@ -1324,7 +1327,7 @@ SessionStoreService.prototype = {
|
||||||
let closedTab = closedTabs.splice(aIndex, 1).shift();
|
let closedTab = closedTabs.splice(aIndex, 1).shift();
|
||||||
let closedTabState = closedTab.state;
|
let closedTabState = closedTab.state;
|
||||||
|
|
||||||
this._sendWindowStateEvent(aWindow, "Busy");
|
this._setWindowStateBusy(aWindow);
|
||||||
// create a new tab
|
// create a new tab
|
||||||
let browser = aWindow.gBrowser;
|
let browser = aWindow.gBrowser;
|
||||||
let tab = browser.addTab();
|
let tab = browser.addTab();
|
||||||
|
@ -2534,7 +2537,7 @@ SessionStoreService.prototype = {
|
||||||
|
|
||||||
// We're not returning from this before we end up calling restoreHistoryPrecursor
|
// We're not returning from this before we end up calling restoreHistoryPrecursor
|
||||||
// for this window, so make sure we send the SSWindowStateBusy event.
|
// for this window, so make sure we send the SSWindowStateBusy event.
|
||||||
this._sendWindowStateEvent(aWindow, "Busy");
|
this._setWindowStateBusy(aWindow);
|
||||||
|
|
||||||
if (root._closedWindows)
|
if (root._closedWindows)
|
||||||
this._closedWindows = root._closedWindows;
|
this._closedWindows = root._closedWindows;
|
||||||
|
@ -2721,7 +2724,7 @@ SessionStoreService.prototype = {
|
||||||
if (aTabs.length == 0) {
|
if (aTabs.length == 0) {
|
||||||
// this is normally done in restoreHistory() but as we're returning early
|
// this is normally done in restoreHistory() but as we're returning early
|
||||||
// here we need to take care of it.
|
// here we need to take care of it.
|
||||||
this._sendWindowStateEvent(aWindow, "Ready");
|
this._setWindowStateReady(aWindow);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2866,7 +2869,7 @@ SessionStoreService.prototype = {
|
||||||
if (aTabs.length == 0) {
|
if (aTabs.length == 0) {
|
||||||
// At this point we're essentially ready for consumers to read/write data
|
// At this point we're essentially ready for consumers to read/write data
|
||||||
// via the sessionstore API so we'll send the SSWindowStateReady event.
|
// via the sessionstore API so we'll send the SSWindowStateReady event.
|
||||||
this._sendWindowStateEvent(aWindow, "Ready");
|
this._setWindowStateReady(aWindow);
|
||||||
return; // no more tabs to restore
|
return; // no more tabs to restore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4011,6 +4014,42 @@ SessionStoreService.prototype = {
|
||||||
this._restoreCount = -1;
|
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.
|
* Dispatch an SSWindowState_____ event for the given window.
|
||||||
* @param aWindow the window
|
* @param aWindow the window
|
||||||
|
|
|
@ -151,6 +151,7 @@ _BROWSER_TEST_FILES = \
|
||||||
browser_636279.js \
|
browser_636279.js \
|
||||||
browser_645428.js \
|
browser_645428.js \
|
||||||
browser_659591.js \
|
browser_659591.js \
|
||||||
|
browser_662812.js \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
ifneq ($(OS_ARCH),Darwin)
|
ifneq ($(OS_ARCH),Darwin)
|
||||||
|
|
|
@ -4,8 +4,6 @@
|
||||||
const TAB_STATE_NEEDS_RESTORE = 1;
|
const TAB_STATE_NEEDS_RESTORE = 1;
|
||||||
const TAB_STATE_RESTORING = 2;
|
const TAB_STATE_RESTORING = 2;
|
||||||
|
|
||||||
let stateBackup = ss.getBrowserState();
|
|
||||||
|
|
||||||
let state = {windows:[{tabs:[
|
let state = {windows:[{tabs:[
|
||||||
{entries:[{url:"http://example.com#1"}]},
|
{entries:[{url:"http://example.com#1"}]},
|
||||||
{entries:[{url:"http://example.com#2"}]},
|
{entries:[{url:"http://example.com#2"}]},
|
||||||
|
@ -22,20 +20,12 @@ function test() {
|
||||||
|
|
||||||
registerCleanupFunction(function () {
|
registerCleanupFunction(function () {
|
||||||
Services.prefs.clearUserPref("browser.sessionstore.restore_hidden_tabs");
|
Services.prefs.clearUserPref("browser.sessionstore.restore_hidden_tabs");
|
||||||
|
|
||||||
TabsProgressListener.uninit();
|
|
||||||
|
|
||||||
ss.setBrowserState(stateBackup);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
TabsProgressListener.init();
|
|
||||||
|
|
||||||
// First stage: restoreHiddenTabs = true
|
// First stage: restoreHiddenTabs = true
|
||||||
// Second stage: restoreHiddenTabs = false
|
// Second stage: restoreHiddenTabs = false
|
||||||
test_loadTabs(true, function () {
|
test_loadTabs(true, function () {
|
||||||
test_loadTabs(false, function () {
|
test_loadTabs(false, finish);
|
||||||
waitForFocus(finish);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,10 +33,9 @@ function test_loadTabs(restoreHiddenTabs, callback) {
|
||||||
Services.prefs.setBoolPref("browser.sessionstore.restore_hidden_tabs", restoreHiddenTabs);
|
Services.prefs.setBoolPref("browser.sessionstore.restore_hidden_tabs", restoreHiddenTabs);
|
||||||
|
|
||||||
let expectedTabs = restoreHiddenTabs ? 8 : 4;
|
let expectedTabs = restoreHiddenTabs ? 8 : 4;
|
||||||
|
|
||||||
let firstProgress = true;
|
let firstProgress = true;
|
||||||
|
|
||||||
TabsProgressListener.setCallback(function (needsRestore, isRestoring) {
|
newWindowWithState(state, function (win, needsRestore, isRestoring) {
|
||||||
if (firstProgress) {
|
if (firstProgress) {
|
||||||
firstProgress = false;
|
firstProgress = false;
|
||||||
is(isRestoring, 3, "restoring 3 tabs concurrently");
|
is(isRestoring, 3, "restoring 3 tabs concurrently");
|
||||||
|
@ -54,60 +43,75 @@ function test_loadTabs(restoreHiddenTabs, callback) {
|
||||||
ok(isRestoring < 4, "restoring max. 3 tabs concurrently");
|
ok(isRestoring < 4, "restoring max. 3 tabs concurrently");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gBrowser.tabs.length - needsRestore == expectedTabs) {
|
if (win.gBrowser.tabs.length - needsRestore == expectedTabs) {
|
||||||
TabsProgressListener.unsetCallback();
|
is(win.gBrowser.visibleTabs.length, 4, "only 4 visible tabs");
|
||||||
is(gBrowser.visibleTabs.length, 4, "only 4 visible tabs");
|
|
||||||
|
TabsProgressListener.uninit();
|
||||||
callback();
|
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 = {
|
let TabsProgressListener = {
|
||||||
init: function () {
|
init: function (win) {
|
||||||
gBrowser.addTabsProgressListener(this);
|
this.window = win;
|
||||||
|
|
||||||
|
this.window.gBrowser.addTabsProgressListener(this);
|
||||||
},
|
},
|
||||||
|
|
||||||
uninit: function () {
|
uninit: function () {
|
||||||
this.unsetCallback();
|
this.window.gBrowser.removeTabsProgressListener(this);
|
||||||
gBrowser.removeTabsProgressListener(this);
|
|
||||||
|
delete this.window;
|
||||||
|
delete this.callback;
|
||||||
},
|
},
|
||||||
|
|
||||||
setCallback: function (callback) {
|
setCallback: function (callback) {
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
},
|
},
|
||||||
|
|
||||||
unsetCallback: function () {
|
|
||||||
delete this.callback;
|
|
||||||
},
|
|
||||||
|
|
||||||
onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
|
onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
|
||||||
if (this.callback && aBrowser.__SS_restoreState == TAB_STATE_RESTORING &&
|
if (this.callback && aBrowser.__SS_restoreState == TAB_STATE_RESTORING &&
|
||||||
aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
|
aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
|
||||||
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK &&
|
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK &&
|
||||||
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW)
|
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) {
|
this._previousLocation != this.gBrowser.contentWindow.location.href) {
|
||||||
let contentWindow = this.gBrowser.selectedBrowser.contentWindow;
|
let contentWindow = this.gBrowser.selectedBrowser.contentWindow;
|
||||||
this._contentSandbox = new Cu.Sandbox(contentWindow,
|
this._contentSandbox = new Cu.Sandbox(contentWindow,
|
||||||
{ sandboxPrototype: contentWindow, wantXrays: false });
|
{ sandboxPrototype: contentWindow, wantXrays: false,
|
||||||
|
sandboxName: 'scratchpad-content'});
|
||||||
|
|
||||||
this._previousBrowserWindow = this.browserWindow;
|
this._previousBrowserWindow = this.browserWindow;
|
||||||
this._previousBrowser = this.gBrowser.selectedBrowser;
|
this._previousBrowser = this.gBrowser.selectedBrowser;
|
||||||
|
@ -211,7 +212,8 @@ var Scratchpad = {
|
||||||
if (!this._chromeSandbox ||
|
if (!this._chromeSandbox ||
|
||||||
this.browserWindow != this._previousBrowserWindow) {
|
this.browserWindow != this._previousBrowserWindow) {
|
||||||
this._chromeSandbox = new Cu.Sandbox(this.browserWindow,
|
this._chromeSandbox = new Cu.Sandbox(this.browserWindow,
|
||||||
{ sandboxPrototype: this.browserWindow, wantXrays: false });
|
{ sandboxPrototype: this.browserWindow, wantXrays: false,
|
||||||
|
sandboxName: 'scratchpad-chrome'});
|
||||||
|
|
||||||
this._previousBrowserWindow = this.browserWindow;
|
this._previousBrowserWindow = this.browserWindow;
|
||||||
}
|
}
|
||||||
|
|
|
@ -603,18 +603,37 @@ toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button {
|
||||||
|
|
||||||
#forward-button {
|
#forward-button {
|
||||||
list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=toolbar");
|
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) {
|
#forward-button:-moz-locale-dir(rtl) {
|
||||||
list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=toolbar");
|
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");
|
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 {
|
#reload-button {
|
||||||
list-style-image: url("moz-icon://stock/gtk-refresh?size=toolbar");
|
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] {
|
.unified-nav-forward[_moz-menuactive] {
|
||||||
list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=menu") !important;
|
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");
|
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) {
|
.unified-nav-forward[_moz-menuactive]:-moz-locale-dir(rtl) {
|
||||||
list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=menu") !important;
|
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");
|
list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=menu&state=disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,17 @@ import os
|
||||||
|
|
||||||
class DeviceManagerADB(DeviceManager):
|
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.host = host
|
||||||
self.port = port
|
self.port = port
|
||||||
self.retrylimit = retrylimit
|
self.retrylimit = retrylimit
|
||||||
self.retries = 0
|
self.retries = 0
|
||||||
self._sock = None
|
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)
|
self.Init(packageName)
|
||||||
|
|
||||||
def Init(self, packageName):
|
def Init(self, packageName):
|
||||||
|
@ -27,7 +32,11 @@ class DeviceManagerADB(DeviceManager):
|
||||||
self.tmpDir = None
|
self.tmpDir = None
|
||||||
try:
|
try:
|
||||||
# a test to see if we have root privs
|
# 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:
|
except:
|
||||||
try:
|
try:
|
||||||
self.checkCmd(["root"])
|
self.checkCmd(["root"])
|
||||||
|
@ -98,7 +107,7 @@ class DeviceManagerADB(DeviceManager):
|
||||||
try:
|
try:
|
||||||
if (not self.dirExists(remoteDir)):
|
if (not self.dirExists(remoteDir)):
|
||||||
self.mkDirs(remoteDir+"/x")
|
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)
|
relRoot = os.path.relpath(root, localDir)
|
||||||
for file in files:
|
for file in files:
|
||||||
localFile = os.path.join(root, file)
|
localFile = os.path.join(root, file)
|
||||||
|
@ -134,8 +143,12 @@ class DeviceManagerADB(DeviceManager):
|
||||||
# success: True
|
# success: True
|
||||||
# failure: False
|
# failure: False
|
||||||
def fileExists(self, filepath):
|
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 True
|
||||||
|
return False
|
||||||
|
|
||||||
def removeFile(self, filename):
|
def removeFile(self, filename):
|
||||||
return self.runCmd(["shell", "rm", filename]).stdout.read()
|
return self.runCmd(["shell", "rm", filename]).stdout.read()
|
||||||
|
@ -381,18 +394,11 @@ class DeviceManagerADB(DeviceManager):
|
||||||
return devroot + '/fennec'
|
return devroot + '/fennec'
|
||||||
elif (self.dirExists(devroot + '/firefox')):
|
elif (self.dirExists(devroot + '/firefox')):
|
||||||
return devroot + '/firefox'
|
return devroot + '/firefox'
|
||||||
elif (self.dirExists('/data/data/org.mozilla.fennec')):
|
elif (self.packageName and self.dirExists('/data/data/' + self.packageName)):
|
||||||
return '/data/data/org.mozilla.fennec'
|
return '/data/data/' + self.packageName
|
||||||
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'
|
|
||||||
|
|
||||||
# Failure (either not installed or not a recognized platform)
|
# Failure (either not installed or not a recognized platform)
|
||||||
|
print "devicemanagerADB: getAppRoot failed"
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Gets the directory location on the device for a specific test type
|
# Gets the directory location on the device for a specific test type
|
||||||
|
|
|
@ -43,7 +43,6 @@ USE_AUTOCONF = 1
|
||||||
MOZILLA_CLIENT = 1
|
MOZILLA_CLIENT = 1
|
||||||
target = @target@
|
target = @target@
|
||||||
ac_configure_args = @ac_configure_args@
|
ac_configure_args = @ac_configure_args@
|
||||||
BUILD_MODULES = @BUILD_MODULES@
|
|
||||||
MOZILLA_VERSION = @MOZILLA_VERSION@
|
MOZILLA_VERSION = @MOZILLA_VERSION@
|
||||||
FIREFOX_VERSION = @FIREFOX_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 ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
|
||||||
#define STR_LEN(a) (ARRAY_LEN(a) - 1)
|
#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 */
|
/* changes all forward slashes in token to backslashes */
|
||||||
void changeForwardSlashesToBackSlashes ( wchar_t *arg )
|
void changeForwardSlashesToBackSlashes ( wchar_t *arg )
|
||||||
{
|
{
|
||||||
|
|
|
@ -153,6 +153,20 @@ xpcshell-tests:
|
||||||
$(LIBXUL_DIST)/bin/xpcshell \
|
$(LIBXUL_DIST)/bin/xpcshell \
|
||||||
$(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
|
$(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
|
# Execute a single test, specified in $(SOLO_FILE), but don't automatically
|
||||||
# start the test. Instead, present the xpcshell prompt so the user can
|
# start the test. Instead, present the xpcshell prompt so the user can
|
||||||
# attach a debugger and then start the test.
|
# attach a debugger and then start the test.
|
||||||
|
@ -182,6 +196,23 @@ check-one:
|
||||||
$(LIBXUL_DIST)/bin/xpcshell \
|
$(LIBXUL_DIST)/bin/xpcshell \
|
||||||
$(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
|
$(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
|
endif # XPCSHELL_TESTS
|
||||||
|
|
||||||
ifdef CPP_UNIT_TESTS
|
ifdef CPP_UNIT_TESTS
|
||||||
|
@ -1122,8 +1153,9 @@ ifdef HAVE_DTRACE
|
||||||
ifndef XP_MACOSX
|
ifndef XP_MACOSX
|
||||||
ifdef DTRACE_PROBE_OBJ
|
ifdef DTRACE_PROBE_OBJ
|
||||||
ifndef DTRACE_LIB_DEPENDENT
|
ifndef DTRACE_LIB_DEPENDENT
|
||||||
$(DTRACE_PROBE_OBJ):
|
NON_DTRACE_OBJS := $(filter-out $(DTRACE_PROBE_OBJ),$(OBJS))
|
||||||
dtrace -G -C -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ)
|
$(DTRACE_PROBE_OBJ): $(NON_DTRACE_OBJS)
|
||||||
|
dtrace -G -C -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ) $(NON_DTRACE_OBJS)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
@ -1519,9 +1551,6 @@ export:: FORCE
|
||||||
@echo; sleep 2; false
|
@echo; sleep 2; false
|
||||||
endif
|
endif
|
||||||
|
|
||||||
$(IDL_DIR)::
|
|
||||||
$(NSINSTALL) -D $@
|
|
||||||
|
|
||||||
# generate .h files from into $(XPIDL_GEN_DIR), then export to $(DIST)/include;
|
# generate .h files from into $(XPIDL_GEN_DIR), then export to $(DIST)/include;
|
||||||
# warn against overriding existing .h file.
|
# warn against overriding existing .h file.
|
||||||
$(XPIDL_GEN_DIR)/.done:
|
$(XPIDL_GEN_DIR)/.done:
|
||||||
|
@ -1592,14 +1621,8 @@ endif # XPIDLSRCS
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# General rules for exporting idl files.
|
# General rules for exporting idl files.
|
||||||
#
|
$(IDL_DIR):
|
||||||
# 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)::
|
|
||||||
$(NSINSTALL) -D $@
|
$(NSINSTALL) -D $@
|
||||||
|
|
||||||
export-idl:: $(SUBMAKEFILES) $(MAKE_DIRS)
|
export-idl:: $(SUBMAKEFILES) $(MAKE_DIRS)
|
||||||
|
@ -2066,7 +2089,6 @@ showhost:
|
||||||
@echo "HOST_LIBRARY = $(HOST_LIBRARY)"
|
@echo "HOST_LIBRARY = $(HOST_LIBRARY)"
|
||||||
|
|
||||||
showbuildmods::
|
showbuildmods::
|
||||||
@echo "Build Modules = $(BUILD_MODULES)"
|
|
||||||
@echo "Module dirs = $(BUILD_MODULE_DIRS)"
|
@echo "Module dirs = $(BUILD_MODULE_DIRS)"
|
||||||
|
|
||||||
documentation:
|
documentation:
|
||||||
|
|
|
@ -970,7 +970,6 @@ if test -n "$_WIN32_MSVC"; then
|
||||||
AC_DEFINE(HAVE_IO_H)
|
AC_DEFINE(HAVE_IO_H)
|
||||||
AC_DEFINE(HAVE_SETBUF)
|
AC_DEFINE(HAVE_SETBUF)
|
||||||
AC_DEFINE(HAVE_ISATTY)
|
AC_DEFINE(HAVE_ISATTY)
|
||||||
AC_DEFINE(HAVE_STDCALL)
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
fi # COMPILE_ENVIRONMENT
|
fi # COMPILE_ENVIRONMENT
|
||||||
|
@ -2482,6 +2481,8 @@ ia64*-hpux*)
|
||||||
if test -n "$GNU_CC"; then
|
if test -n "$GNU_CC"; then
|
||||||
CFLAGS="$CFLAGS -mstackrealign"
|
CFLAGS="$CFLAGS -mstackrealign"
|
||||||
CXXFLAGS="$CXXFLAGS -mstackrealign"
|
CXXFLAGS="$CXXFLAGS -mstackrealign"
|
||||||
|
else
|
||||||
|
AC_DEFINE(HAVE_STDCALL)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
MOZ_CHECK_HEADERS(mmintrin.h)
|
MOZ_CHECK_HEADERS(mmintrin.h)
|
||||||
|
|
|
@ -6125,7 +6125,7 @@ nsDocument::AdoptNode(nsIDOMNode *aAdoptedNode, nsIDOMNode **aResult)
|
||||||
} while ((doc = doc->GetParentDocument()));
|
} while ((doc = doc->GetParentDocument()));
|
||||||
|
|
||||||
// Remove from parent.
|
// Remove from parent.
|
||||||
nsINode* parent = adoptedNode->GetNodeParent();
|
nsCOMPtr<nsINode> parent = adoptedNode->GetNodeParent();
|
||||||
if (parent) {
|
if (parent) {
|
||||||
rv = parent->RemoveChildAt(parent->IndexOf(adoptedNode), PR_TRUE);
|
rv = parent->RemoveChildAt(parent->IndexOf(adoptedNode), PR_TRUE);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
|
@ -620,7 +620,7 @@ nsINode::Normalize()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove node
|
// Remove node
|
||||||
nsINode* parent = node->GetNodeParent();
|
nsCOMPtr<nsINode> parent = node->GetNodeParent();
|
||||||
NS_ASSERTION(parent || hasRemoveListeners,
|
NS_ASSERTION(parent || hasRemoveListeners,
|
||||||
"Should always have a parent unless "
|
"Should always have a parent unless "
|
||||||
"mutation events messed us up");
|
"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
|
// Remove the new child from the old parent if one exists
|
||||||
nsINode* oldParent = newContent->GetNodeParent();
|
nsCOMPtr<nsINode> oldParent = newContent->GetNodeParent();
|
||||||
if (oldParent) {
|
if (oldParent) {
|
||||||
PRInt32 removeIndex = oldParent->IndexOf(newContent);
|
PRInt32 removeIndex = oldParent->IndexOf(newContent);
|
||||||
if (removeIndex < 0) {
|
if (removeIndex < 0) {
|
||||||
|
|
|
@ -2510,12 +2510,12 @@ nsHTMLInputElement::SanitizeValue(nsAString& aValue)
|
||||||
case NS_FORM_INPUT_SEARCH:
|
case NS_FORM_INPUT_SEARCH:
|
||||||
case NS_FORM_INPUT_TEL:
|
case NS_FORM_INPUT_TEL:
|
||||||
case NS_FORM_INPUT_PASSWORD:
|
case NS_FORM_INPUT_PASSWORD:
|
||||||
case NS_FORM_INPUT_EMAIL:
|
|
||||||
{
|
{
|
||||||
PRUnichar crlf[] = { PRUnichar('\r'), PRUnichar('\n'), 0 };
|
PRUnichar crlf[] = { PRUnichar('\r'), PRUnichar('\n'), 0 };
|
||||||
aValue.StripChars(crlf);
|
aValue.StripChars(crlf);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case NS_FORM_INPUT_EMAIL:
|
||||||
case NS_FORM_INPUT_URL:
|
case NS_FORM_INPUT_URL:
|
||||||
{
|
{
|
||||||
PRUnichar crlf[] = { PRUnichar('\r'), PRUnichar('\n'), 0 };
|
PRUnichar crlf[] = { PRUnichar('\r'), PRUnichar('\n'), 0 };
|
||||||
|
|
|
@ -75,8 +75,12 @@ var email = document.forms[0].elements[0];
|
||||||
var values = [
|
var values = [
|
||||||
[ '', true ], // The empty string shouldn't be considered as invalid.
|
[ '', true ], // The empty string shouldn't be considered as invalid.
|
||||||
[ 'foo@bar.com', true ],
|
[ 'foo@bar.com', true ],
|
||||||
[ ' foo@bar.com', false ],
|
[ ' foo@bar.com', true ],
|
||||||
[ 'foo@bar.com ', false ],
|
[ '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 ],
|
[ 'tulip', false ],
|
||||||
// Some checks on the user part of the address.
|
// Some checks on the user part of the address.
|
||||||
[ '@bar.com', false ],
|
[ '@bar.com', false ],
|
||||||
|
@ -163,7 +167,7 @@ values.push(["foo@bar.com" + legalCharacters, true]);
|
||||||
// Add domain illegal characters.
|
// Add domain illegal characters.
|
||||||
illegalCharacters = "()<>[]:;@\\,!#$%&'*+/=?^_`{|}~ \t";
|
illegalCharacters = "()<>[]:;@\\,!#$%&'*+/=?^_`{|}~ \t";
|
||||||
for each (c in illegalCharacters) {
|
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]) {
|
values.forEach(function([value, valid]) {
|
||||||
|
|
|
@ -47,9 +47,9 @@ function sanitizeValue(aType, aValue)
|
||||||
case "password":
|
case "password":
|
||||||
case "search":
|
case "search":
|
||||||
case "tel":
|
case "tel":
|
||||||
case "email":
|
|
||||||
return aValue.replace(/[\n\r]/g, "");
|
return aValue.replace(/[\n\r]/g, "");
|
||||||
case "url":
|
case "url":
|
||||||
|
case "email":
|
||||||
return aValue.replace(/[\n\r]/g, "").replace(/^\s+|\s+$/g, "");
|
return aValue.replace(/[\n\r]/g, "").replace(/^\s+|\s+$/g, "");
|
||||||
case "date":
|
case "date":
|
||||||
case "month":
|
case "month":
|
||||||
|
|
|
@ -32,7 +32,6 @@ function seekStarted(evt) {
|
||||||
function seekEnded(evt) {
|
function seekEnded(evt) {
|
||||||
var v = evt.target;
|
var v = evt.target;
|
||||||
v._gotSeekEnded = true;
|
v._gotSeekEnded = true;
|
||||||
v.play();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadedData(evt) {
|
function loadedData(evt) {
|
||||||
|
|
|
@ -146,8 +146,14 @@ nsSMILCSSProperty::GetBaseValue() const
|
||||||
|
|
||||||
// (4) Populate our nsSMILValue from the computed style
|
// (4) Populate our nsSMILValue from the computed style
|
||||||
if (didGetComputedVal) {
|
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,
|
nsSMILCSSValueType::ValueFromString(mPropID, mElement,
|
||||||
computedStyleVal, baseValue);
|
computedStyleVal, baseValue,
|
||||||
|
nsnull);
|
||||||
}
|
}
|
||||||
return baseValue;
|
return baseValue;
|
||||||
}
|
}
|
||||||
|
@ -160,22 +166,17 @@ nsSMILCSSProperty::ValueFromString(const nsAString& aStr,
|
||||||
{
|
{
|
||||||
NS_ENSURE_TRUE(IsPropertyAnimatable(mPropID), NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(IsPropertyAnimatable(mPropID), NS_ERROR_FAILURE);
|
||||||
|
|
||||||
nsSMILCSSValueType::ValueFromString(mPropID, mElement, aStr, aValue);
|
nsSMILCSSValueType::ValueFromString(mPropID, mElement, aStr, aValue,
|
||||||
if (aValue.IsNull()) {
|
&aPreventCachingOfSandwich);
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
|
// 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
|
return aValue.IsNull() ? NS_ERROR_FAILURE : NS_OK;
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
|
|
@ -371,7 +371,8 @@ ValueFromStringHelper(nsCSSProperty aPropID,
|
||||||
Element* aTargetElement,
|
Element* aTargetElement,
|
||||||
nsPresContext* aPresContext,
|
nsPresContext* aPresContext,
|
||||||
const nsAString& aString,
|
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
|
// If value is negative, we'll strip off the "-" so the CSS parser won't
|
||||||
// barf, and then manually make the parsed value negative.
|
// barf, and then manually make the parsed value negative.
|
||||||
|
@ -386,7 +387,8 @@ ValueFromStringHelper(nsCSSProperty aPropID,
|
||||||
}
|
}
|
||||||
nsDependentSubstring subString(aString, subStringBegin);
|
nsDependentSubstring subString(aString, subStringBegin);
|
||||||
if (!nsStyleAnimation::ComputeValue(aPropID, aTargetElement, subString,
|
if (!nsStyleAnimation::ComputeValue(aPropID, aTargetElement, subString,
|
||||||
PR_TRUE, aStyleAnimValue)) {
|
PR_TRUE, aStyleAnimValue,
|
||||||
|
aIsContextSensitive)) {
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
}
|
}
|
||||||
if (isNegative) {
|
if (isNegative) {
|
||||||
|
@ -409,7 +411,8 @@ void
|
||||||
nsSMILCSSValueType::ValueFromString(nsCSSProperty aPropID,
|
nsSMILCSSValueType::ValueFromString(nsCSSProperty aPropID,
|
||||||
Element* aTargetElement,
|
Element* aTargetElement,
|
||||||
const nsAString& aString,
|
const nsAString& aString,
|
||||||
nsSMILValue& aValue)
|
nsSMILValue& aValue,
|
||||||
|
PRBool* aIsContextSensitive)
|
||||||
{
|
{
|
||||||
NS_ABORT_IF_FALSE(aValue.IsNull(), "Outparam should be null-typed");
|
NS_ABORT_IF_FALSE(aValue.IsNull(), "Outparam should be null-typed");
|
||||||
nsPresContext* presContext = GetPresContextForElement(aTargetElement);
|
nsPresContext* presContext = GetPresContextForElement(aTargetElement);
|
||||||
|
@ -420,7 +423,7 @@ nsSMILCSSValueType::ValueFromString(nsCSSProperty aPropID,
|
||||||
|
|
||||||
nsStyleAnimation::Value parsedValue;
|
nsStyleAnimation::Value parsedValue;
|
||||||
if (ValueFromStringHelper(aPropID, aTargetElement, presContext,
|
if (ValueFromStringHelper(aPropID, aTargetElement, presContext,
|
||||||
aString, parsedValue)) {
|
aString, parsedValue, aIsContextSensitive)) {
|
||||||
sSingleton.Init(aValue);
|
sSingleton.Init(aValue);
|
||||||
aValue.mU.mPtr = new ValueWrapper(aPropID, parsedValue, presContext);
|
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 aString The string to be parsed as a CSS value.
|
||||||
* @param [out] aValue The nsSMILValue to be populated. Should
|
* @param [out] aValue The nsSMILValue to be populated. Should
|
||||||
* initially be null-typed.
|
* 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()
|
* @pre aValue.IsNull()
|
||||||
* @post aValue.IsNull() || aValue.mType == nsSMILCSSValueType::sSingleton
|
* @post aValue.IsNull() || aValue.mType == nsSMILCSSValueType::sSingleton
|
||||||
*/
|
*/
|
||||||
static void ValueFromString(nsCSSProperty aPropID,
|
static void ValueFromString(nsCSSProperty aPropID,
|
||||||
Element* aTargetElement,
|
Element* aTargetElement,
|
||||||
const nsAString& aString,
|
const nsAString& aString,
|
||||||
nsSMILValue& aValue);
|
nsSMILValue& aValue,
|
||||||
|
PRBool* aIsContextSensitive);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a string representation of the given nsSMILValue.
|
* 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);
|
NS_ENSURE_TRUE(IsPropertyAnimatable(mPropID), NS_ERROR_FAILURE);
|
||||||
|
|
||||||
nsSMILCSSValueType::ValueFromString(mPropID, mElement, aStr, aValue);
|
nsSMILCSSValueType::ValueFromString(mPropID, mElement, aStr, aValue,
|
||||||
if (aValue.IsNull()) {
|
&aPreventCachingOfSandwich);
|
||||||
return NS_ERROR_FAILURE;
|
return aValue.IsNull() ? NS_ERROR_FAILURE : NS_OK;
|
||||||
}
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsSMILValue
|
nsSMILValue
|
||||||
|
@ -87,8 +81,12 @@ nsSMILMappedAttribute::GetBaseValue() const
|
||||||
baseStringValue);
|
baseStringValue);
|
||||||
nsSMILValue baseValue;
|
nsSMILValue baseValue;
|
||||||
if (success) {
|
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,
|
nsSMILCSSValueType::ValueFromString(mPropID, mElement,
|
||||||
baseStringValue, baseValue);
|
baseStringValue, baseValue, nsnull);
|
||||||
} else {
|
} else {
|
||||||
// Attribute is unset -- use computed value.
|
// Attribute is unset -- use computed value.
|
||||||
// FIRST: Temporarily clear animated value, to make sure it doesn't pollute
|
// FIRST: Temporarily clear animated value, to make sure it doesn't pollute
|
||||||
|
|
|
@ -8,7 +8,10 @@
|
||||||
<body>
|
<body>
|
||||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=533291">Mozilla Bug 533291</a>
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=533291">Mozilla Bug 533291</a>
|
||||||
<p id="display"></p>
|
<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"
|
<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="120px" height="120px"
|
||||||
onload="this.pauseAnimations()">
|
onload="this.pauseAnimations()">
|
||||||
<g id="circleParent">
|
<g id="circleParent">
|
||||||
|
@ -19,68 +22,99 @@
|
||||||
<pre id="test">
|
<pre id="test">
|
||||||
<script class="testbody" type="text/javascript">
|
<script class="testbody" type="text/javascript">
|
||||||
<![CDATA[
|
<![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 */
|
/* Global Variables */
|
||||||
const SVGNS = "http://www.w3.org/2000/svg";
|
const SVGNS = "http://www.w3.org/2000/svg";
|
||||||
|
|
||||||
|
// Animation parameters -- not used for <set> animation
|
||||||
const ANIM_DUR = "4s";
|
const ANIM_DUR = "4s";
|
||||||
const TIME_ANIM_END = "4";
|
const TIME_ANIM_END = "4";
|
||||||
const TIME_AFTER_ANIM_END = "5";
|
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 gSvg = document.getElementById("svg");
|
||||||
const gCircle = document.getElementById("circle");
|
const gCircle = document.getElementById("circle");
|
||||||
const gCircleParent = document.getElementById("circleParent");
|
const gCircleParent = document.getElementById("circleParent");
|
||||||
|
|
||||||
|
|
||||||
SimpleTest.waitForExplicitFinish();
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
// MAIN FUNCTION
|
// MAIN FUNCTION
|
||||||
// -------------
|
// -------------
|
||||||
|
|
||||||
function main() {
|
function main()
|
||||||
|
{
|
||||||
ok(gSvg.animationsPaused(), "should be paused by <svg> load handler");
|
ok(gSvg.animationsPaused(), "should be paused by <svg> load handler");
|
||||||
is(gSvg.getCurrentTime(), 0, "should be paused at 0 in <svg> load handler");
|
is(gSvg.getCurrentTime(), 0, "should be paused at 0 in <svg> load handler");
|
||||||
|
|
||||||
if (gNextTestIndex != 0) {
|
const tests =
|
||||||
ok(false, "expecting to start at first test in array.");
|
[ 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.)
|
SimpleTest.finish();
|
||||||
runNextTest();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// HELPER FUNCTIONS
|
// HELPER FUNCTIONS
|
||||||
// ----------------
|
// ----------------
|
||||||
function createAnimFromTo(attrName, fromVal, toVal) {
|
function createAnimSetTo(attrName, toVal)
|
||||||
var anim = document.createElementNS(SVGNS,"animate");
|
{
|
||||||
|
var anim = document.createElementNS(SVGNS,"set");
|
||||||
anim.setAttribute("attributeName", attrName);
|
anim.setAttribute("attributeName", attrName);
|
||||||
anim.setAttribute("dur", ANIM_DUR);
|
|
||||||
anim.setAttribute("begin", "0s");
|
|
||||||
anim.setAttribute("from", fromVal);
|
|
||||||
anim.setAttribute("to", toVal);
|
anim.setAttribute("to", toVal);
|
||||||
anim.setAttribute("fill", "freeze");
|
|
||||||
return gCircle.appendChild(anim);
|
return gCircle.appendChild(anim);
|
||||||
}
|
}
|
||||||
function createAnimBy(attrName, byVal) {
|
|
||||||
|
function createAnimBy(attrName, byVal)
|
||||||
|
{
|
||||||
var anim = document.createElementNS(SVGNS,"animate");
|
var anim = document.createElementNS(SVGNS,"animate");
|
||||||
anim.setAttribute("attributeName", attrName);
|
anim.setAttribute("attributeName", attrName);
|
||||||
anim.setAttribute("dur", ANIM_DUR);
|
anim.setAttribute("dur", ANIM_DUR);
|
||||||
|
@ -90,6 +124,18 @@ function createAnimBy(attrName, byVal) {
|
||||||
return gCircle.appendChild(anim);
|
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
|
// Common setup code for each test function: seek to 0, and make sure
|
||||||
// the previous test cleaned up its animations.
|
// the previous test cleaned up its animations.
|
||||||
function setupTest() {
|
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
|
// THE TESTS
|
||||||
// ---------
|
// ---------
|
||||||
|
|
||||||
|
@ -130,106 +165,400 @@ function testBaseValueChange()
|
||||||
"Checking animated cx after anim ends & after changing base val");
|
"Checking animated cx after anim ends & after changing base val");
|
||||||
|
|
||||||
anim.parentNode.removeChild(anim); // clean up
|
anim.parentNode.removeChild(anim); // clean up
|
||||||
runNextTest();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function testCurrentColorChange()
|
function testCurrentColorChange()
|
||||||
{
|
{
|
||||||
gCircle.setAttribute("color", "red"); // At first: currentColor=red
|
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)",
|
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
|
gCircle.setAttribute("color", "lime"); // Change: currentColor=lime
|
||||||
setTimeout(testCurrentColorChange_final, SETTIMEOUT_INTERVAL);
|
// 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)",
|
||||||
function testCurrentColorChange_final()
|
"Checking animated fill=currentColor after updating context but before " +
|
||||||
{
|
"sampling");
|
||||||
|
gSvg.setCurrentTime(0);
|
||||||
is(SMILUtil.getComputedStyleSimple(gCircle, "fill"), "rgb(0, 255, 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
|
// Clean up
|
||||||
gCircle.removeAttribute("color");
|
gCircle.removeAttribute("color");
|
||||||
gCircle.firstChild.parentNode.removeChild(gCircle.firstChild);
|
gCircle.removeChild(gCircle.firstChild);
|
||||||
|
|
||||||
// Kick off next test
|
|
||||||
runNextTest();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function testCurrentColorChangeUsingStyle()
|
function testCurrentColorChangeUsingStyle()
|
||||||
{
|
{
|
||||||
setupTest();
|
setupTest();
|
||||||
gCircle.setAttribute("style", "color: red"); // At first: currentColor=red
|
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)",
|
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
|
gCircle.setAttribute("style", "color: lime"); // Change: currentColor=lime
|
||||||
setTimeout(testCurrentColorChangeUsingStyle_final, SETTIMEOUT_INTERVAL);
|
gSvg.setCurrentTime(0);
|
||||||
}
|
|
||||||
|
|
||||||
function testCurrentColorChangeUsingStyle_final()
|
|
||||||
{
|
|
||||||
is(SMILUtil.getComputedStyleSimple(gCircle, "fill"), "rgb(0, 255, 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)");
|
+ "(using style attr)");
|
||||||
|
|
||||||
// Clean up
|
// Clean up
|
||||||
gCircle.removeAttribute("style");
|
gCircle.removeAttribute("style");
|
||||||
gCircle.firstChild.parentNode.removeChild(gCircle.firstChild);
|
gCircle.removeChild(gCircle.firstChild);
|
||||||
runNextTest();
|
}
|
||||||
|
|
||||||
|
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()
|
function testInheritChange()
|
||||||
{
|
{
|
||||||
setupTest();
|
setupTest();
|
||||||
gCircleParent.setAttribute("fill", "red"); // At first: inherit=red
|
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)",
|
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
|
gCircleParent.setAttribute("fill", "lime"); // Change: inherit=lime
|
||||||
setTimeout(testInheritChange_final, SETTIMEOUT_INTERVAL);
|
gSvg.setCurrentTime(0);
|
||||||
}
|
|
||||||
|
|
||||||
function testInheritChange_final() {
|
|
||||||
is(SMILUtil.getComputedStyleSimple(gCircle, "fill"), "rgb(0, 255, 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");
|
gCircleParent.removeAttribute("fill");
|
||||||
gCircle.firstChild.parentNode.removeChild(gCircle.firstChild);
|
gCircle.removeChild(gCircle.firstChild);
|
||||||
runNextTest();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function testInheritChangeUsingStyle()
|
function testInheritChangeUsingStyle()
|
||||||
{
|
{
|
||||||
setupTest();
|
setupTest();
|
||||||
gCircleParent.setAttribute("style", "fill: red"); // At first: inherit=red
|
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)",
|
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
|
gCircleParent.setAttribute("style", "fill: lime"); // Change: inherit=lime
|
||||||
setTimeout(testInheritChangeUsingStyle_final, SETTIMEOUT_INTERVAL);
|
gSvg.setCurrentTime(0);
|
||||||
}
|
|
||||||
|
|
||||||
function testInheritChangeUsingStyle_final() {
|
|
||||||
is(SMILUtil.getComputedStyleSimple(gCircle, "fill"), "rgb(0, 255, 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)");
|
+ "(using style attr)");
|
||||||
|
|
||||||
gCircleParent.removeAttribute("style");
|
gCircleParent.removeAttribute("style");
|
||||||
gCircle.firstChild.parentNode.removeChild(gCircle.firstChild);
|
gCircle.removeChild(gCircle.firstChild);
|
||||||
runNextTest();
|
}
|
||||||
|
|
||||||
|
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);
|
window.addEventListener("load", main, false);
|
||||||
|
|
|
@ -57,7 +57,6 @@ _TEST_FILES = \
|
||||||
a_href_helper_04.svg \
|
a_href_helper_04.svg \
|
||||||
test_animLengthObjectIdentity.xhtml \
|
test_animLengthObjectIdentity.xhtml \
|
||||||
test_animLengthReadonly.xhtml \
|
test_animLengthReadonly.xhtml \
|
||||||
test_animLengthRelativeUnits.xhtml \
|
|
||||||
test_animLengthUnits.xhtml \
|
test_animLengthUnits.xhtml \
|
||||||
test_bbox.xhtml \
|
test_bbox.xhtml \
|
||||||
test_bbox-with-invalid-viewBox.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 */
|
/* Implementation file */
|
||||||
|
|
||||||
static PRIntn
|
static PRBool
|
||||||
TraverseProtos(nsHashKey *aKey, void *aData, void* aClosure)
|
TraverseProtos(nsHashKey *aKey, void *aData, void* aClosure)
|
||||||
{
|
{
|
||||||
nsCycleCollectionTraversalCallback *cb =
|
nsCycleCollectionTraversalCallback *cb =
|
||||||
|
@ -439,7 +439,7 @@ TraverseProtos(nsHashKey *aKey, void *aData, void* aClosure)
|
||||||
return kHashEnumerateNext;
|
return kHashEnumerateNext;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PRIntn
|
static PRBool
|
||||||
UnlinkProtoJSObjects(nsHashKey *aKey, void *aData, void* aClosure)
|
UnlinkProtoJSObjects(nsHashKey *aKey, void *aData, void* aClosure)
|
||||||
{
|
{
|
||||||
nsXBLPrototypeBinding *proto = static_cast<nsXBLPrototypeBinding*>(aData);
|
nsXBLPrototypeBinding *proto = static_cast<nsXBLPrototypeBinding*>(aData);
|
||||||
|
@ -453,7 +453,7 @@ struct ProtoTracer
|
||||||
void *mClosure;
|
void *mClosure;
|
||||||
};
|
};
|
||||||
|
|
||||||
static PRIntn
|
static PRBool
|
||||||
TraceProtos(nsHashKey *aKey, void *aData, void* aClosure)
|
TraceProtos(nsHashKey *aKey, void *aData, void* aClosure)
|
||||||
{
|
{
|
||||||
ProtoTracer* closure = static_cast<ProtoTracer*>(aClosure);
|
ProtoTracer* closure = static_cast<ProtoTracer*>(aClosure);
|
||||||
|
|
|
@ -328,7 +328,7 @@ PRBool nsXBLPrototypeBinding::CompareBindingURI(nsIURI* aURI) const
|
||||||
return equal;
|
return equal;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PRIntn
|
static PRBool
|
||||||
TraverseInsertionPoint(nsHashKey* aKey, void* aData, void* aClosure)
|
TraverseInsertionPoint(nsHashKey* aKey, void* aData, void* aClosure)
|
||||||
{
|
{
|
||||||
nsCycleCollectionTraversalCallback &cb =
|
nsCycleCollectionTraversalCallback &cb =
|
||||||
|
@ -1213,7 +1213,7 @@ nsXBLPrototypeBinding::ConstructInsertionTable(nsIContent* aContent)
|
||||||
PRInt32 i;
|
PRInt32 i;
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
nsIContent* child = childrenElements[i];
|
nsIContent* child = childrenElements[i];
|
||||||
nsIContent* parent = child->GetParent();
|
nsCOMPtr<nsIContent> parent = child->GetParent();
|
||||||
|
|
||||||
// Create an XBL insertion point entry.
|
// Create an XBL insertion point entry.
|
||||||
nsXBLInsertionPointEntry* xblIns = nsXBLInsertionPointEntry::Create(parent);
|
nsXBLInsertionPointEntry* xblIns = nsXBLInsertionPointEntry::Create(parent);
|
||||||
|
|
|
@ -4047,7 +4047,8 @@ nsXULDocument::OverlayForwardReference::Merge(nsIContent* aTargetNode,
|
||||||
if (attr == nsGkAtoms::removeelement &&
|
if (attr == nsGkAtoms::removeelement &&
|
||||||
value.EqualsLiteral("true")) {
|
value.EqualsLiteral("true")) {
|
||||||
|
|
||||||
rv = RemoveElement(aTargetNode->GetParent(), aTargetNode);
|
nsCOMPtr<nsIContent> parent = aTargetNode->GetParent();
|
||||||
|
rv = RemoveElement(parent, aTargetNode);
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
|
@ -1324,7 +1324,7 @@ nsXULContentBuilder::RemoveGeneratedContent(nsIContent* aElement)
|
||||||
while (0 != (count = ungenerated.Length())) {
|
while (0 != (count = ungenerated.Length())) {
|
||||||
// Pull the next "ungenerated" element off the queue.
|
// Pull the next "ungenerated" element off the queue.
|
||||||
PRUint32 last = count - 1;
|
PRUint32 last = count - 1;
|
||||||
nsIContent* element = ungenerated[last];
|
nsCOMPtr<nsIContent> element = ungenerated[last];
|
||||||
ungenerated.RemoveElementAt(last);
|
ungenerated.RemoveElementAt(last);
|
||||||
|
|
||||||
PRUint32 i = element->GetChildCount();
|
PRUint32 i = element->GetChildCount();
|
||||||
|
|
|
@ -8452,13 +8452,13 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
||||||
GetCurScrollPos(ScrollOrientation_X, &cx);
|
GetCurScrollPos(ScrollOrientation_X, &cx);
|
||||||
GetCurScrollPos(ScrollOrientation_Y, &cy);
|
GetCurScrollPos(ScrollOrientation_Y, &cy);
|
||||||
|
|
||||||
// We scroll whenever we're not doing a history load. Note that
|
// ScrollToAnchor doesn't necessarily cause us to scroll the window;
|
||||||
// sometimes we might scroll even if we don't fire a hashchange
|
// the function decides whether a scroll is appropriate based on the
|
||||||
// event! See bug 653741.
|
// arguments it receives. But even if we don't end up scrolling,
|
||||||
if (!aSHEntry) {
|
// ScrollToAnchor performs other important tasks, such as informing
|
||||||
|
// the presShell that we have a new hash. See bug 680257.
|
||||||
rv = ScrollToAnchor(curHash, newHash, aLoadType);
|
rv = ScrollToAnchor(curHash, newHash, aLoadType);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
}
|
|
||||||
|
|
||||||
mLoadType = aLoadType;
|
mLoadType = aLoadType;
|
||||||
mURIResultedInDocument = PR_TRUE;
|
mURIResultedInDocument = PR_TRUE;
|
||||||
|
|
|
@ -120,6 +120,8 @@ _TEST_FILES = \
|
||||||
file_bug669671.sjs \
|
file_bug669671.sjs \
|
||||||
test_bug675587.html \
|
test_bug675587.html \
|
||||||
test_bfcache_plus_hash.html \
|
test_bfcache_plus_hash.html \
|
||||||
|
test_bug680257.html \
|
||||||
|
file_bug680257.html \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
|
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)
|
nsGlobalWindow::GetMozIndexedDB(nsIIDBFactory** _retval)
|
||||||
{
|
{
|
||||||
if (!mIndexedDB) {
|
if (!mIndexedDB) {
|
||||||
|
if (!IsChromeWindow()) {
|
||||||
nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
|
nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
|
||||||
do_GetService(THIRDPARTYUTIL_CONTRACTID);
|
do_GetService(THIRDPARTYUTIL_CONTRACTID);
|
||||||
NS_ENSURE_TRUE(thirdPartyUtil, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
NS_ENSURE_TRUE(thirdPartyUtil, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||||
|
@ -8234,6 +8235,7 @@ nsGlobalWindow::GetMozIndexedDB(nsIIDBFactory** _retval)
|
||||||
*_retval = nsnull;
|
*_retval = nsnull;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mIndexedDB = indexedDB::IDBFactory::Create(this);
|
mIndexedDB = indexedDB::IDBFactory::Create(this);
|
||||||
NS_ENSURE_TRUE(mIndexedDB, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
NS_ENSURE_TRUE(mIndexedDB, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
* http://www.w3.org/TR/DOM-Level-2-Style
|
* 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
|
interface nsIDOMCSS2Properties : nsISupports
|
||||||
{
|
{
|
||||||
attribute DOMString background;
|
attribute DOMString background;
|
||||||
|
@ -657,6 +657,9 @@ interface nsIDOMCSS2Properties : nsISupports
|
||||||
attribute DOMString MozBorderImage;
|
attribute DOMString MozBorderImage;
|
||||||
// raises(DOMException) on setting
|
// raises(DOMException) on setting
|
||||||
|
|
||||||
|
attribute DOMString MozColumns;
|
||||||
|
// raises(DOMException) on setting
|
||||||
|
|
||||||
attribute DOMString MozColumnRule;
|
attribute DOMString MozColumnRule;
|
||||||
// raises(DOMException) on setting
|
// raises(DOMException) on setting
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
* For more information on this interface, please see
|
* For more information on this interface, please see
|
||||||
* http://www.whatwg.org/specs/web-apps/current-work/#messageevent
|
* 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
|
interface nsIDOMMessageEvent : nsIDOMEvent
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -3,4 +3,8 @@ head = head_plugins.js
|
||||||
tail =
|
tail =
|
||||||
|
|
||||||
[test_bug455213.js]
|
[test_bug455213.js]
|
||||||
|
# Bug 676953: test fails consistently on Android
|
||||||
|
fail-if = os == "android"
|
||||||
[test_bug471245.js]
|
[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()
|
public void onStart()
|
||||||
{
|
{
|
||||||
Log.i(LOG_FILE_NAME, "start");
|
Log.i(LOG_FILE_NAME, "start");
|
||||||
|
GeckoAppShell.sendEventToGecko(new GeckoEvent(GeckoEvent.ACTIVITY_START));
|
||||||
super.onStart();
|
super.onStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,7 @@ public class GeckoEvent {
|
||||||
public static final int SURFACE_CREATED = 13;
|
public static final int SURFACE_CREATED = 13;
|
||||||
public static final int SURFACE_DESTROYED = 14;
|
public static final int SURFACE_DESTROYED = 14;
|
||||||
public static final int GECKO_EVENT_SYNC = 15;
|
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_END = 0;
|
||||||
public static final int IME_COMPOSITION_BEGIN = 1;
|
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) {
|
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)
|
if (mShowingSplashScreen)
|
||||||
drawSplashScreen(holder, width, height);
|
drawSplashScreen(holder, width, height);
|
||||||
|
|
||||||
mSurfaceLock.lock();
|
mSurfaceLock.lock();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -221,6 +243,12 @@ class GeckoSurfaceView
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
mSurfaceLock.unlock();
|
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;
|
Object syncDrawObject = null;
|
||||||
|
@ -293,6 +321,10 @@ class GeckoSurfaceView
|
||||||
public static final int DRAW_ERROR = 0;
|
public static final int DRAW_ERROR = 0;
|
||||||
public static final int DRAW_GLES_2 = 1;
|
public static final int DRAW_GLES_2 = 1;
|
||||||
public static final int DRAW_2D = 2;
|
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() {
|
public int beginDrawing() {
|
||||||
if (mInDrawing) {
|
if (mInDrawing) {
|
||||||
|
@ -300,6 +332,12 @@ class GeckoSurfaceView
|
||||||
return DRAW_ERROR;
|
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.
|
/* Grab the lock, which we'll hold while we're drawing.
|
||||||
* It gets released in endDrawing(), and is also used in surfaceChanged
|
* It gets released in endDrawing(), and is also used in surfaceChanged
|
||||||
* to make sure that we don't change our surface details while
|
* to make sure that we don't change our surface details while
|
||||||
|
@ -330,6 +368,9 @@ class GeckoSurfaceView
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mDrawSingleFrame)
|
||||||
|
mAbortDraw = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!mSurfaceValid) {
|
if (!mSurfaceValid) {
|
||||||
Log.e(LOG_FILE_NAME, "endDrawing with false mSurfaceValid");
|
Log.e(LOG_FILE_NAME, "endDrawing with false mSurfaceValid");
|
||||||
|
@ -657,6 +698,10 @@ class GeckoSurfaceView
|
||||||
// Are we actively between beginDrawing/endDrawing?
|
// Are we actively between beginDrawing/endDrawing?
|
||||||
boolean mInDrawing;
|
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?
|
// Are we waiting for a buffer to draw in surfaceChanged?
|
||||||
boolean mSyncDraw;
|
boolean mSyncDraw;
|
||||||
|
|
||||||
|
|
|
@ -3,4 +3,8 @@ head =
|
||||||
tail =
|
tail =
|
||||||
|
|
||||||
[test_wwauthpromptfactory.js]
|
[test_wwauthpromptfactory.js]
|
||||||
|
# Bug 676955: test fails consistently on Android
|
||||||
|
fail-if = os == "android"
|
||||||
[test_wwpromptfactory.js]
|
[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); */
|
/* 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;
|
return NS_ERROR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,10 +41,6 @@
|
||||||
#include "nsICategoryManager.h"
|
#include "nsICategoryManager.h"
|
||||||
#include "nsISupportsPrimitives.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"
|
#define DEFAULT_SPELL_CHECKER "@mozilla.org/spellchecker/engine;1"
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(mozSpellChecker)
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(mozSpellChecker)
|
||||||
|
@ -149,12 +145,6 @@ mozSpellChecker::CheckWord(const nsAString &aWord, PRBool *aIsMisspelled, nsTArr
|
||||||
if(!mSpellCheckingEngine)
|
if(!mSpellCheckingEngine)
|
||||||
return NS_ERROR_NULL_POINTER;
|
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;
|
*aIsMisspelled = PR_FALSE;
|
||||||
result = mSpellCheckingEngine->Check(PromiseFlatString(aWord).get(), &correct);
|
result = mSpellCheckingEngine->Check(PromiseFlatString(aWord).get(), &correct);
|
||||||
NS_ENSURE_SUCCESS(result, result);
|
NS_ENSURE_SUCCESS(result, result);
|
||||||
|
|
|
@ -111,6 +111,8 @@ tail =
|
||||||
[test_encode_CP852.js]
|
[test_encode_CP852.js]
|
||||||
[test_encode_CP855.js]
|
[test_encode_CP855.js]
|
||||||
[test_encode_CP857.js]
|
[test_encode_CP857.js]
|
||||||
|
# Bug 676958: test consistently hangs on Android
|
||||||
|
skip-if = os == "android"
|
||||||
[test_encode_CP862.js]
|
[test_encode_CP862.js]
|
||||||
[test_encode_CP864.js]
|
[test_encode_CP864.js]
|
||||||
[test_encode_CP874.js]
|
[test_encode_CP874.js]
|
||||||
|
|
|
@ -3,4 +3,6 @@ head =
|
||||||
tail =
|
tail =
|
||||||
|
|
||||||
[test_ipcshell.js]
|
[test_ipcshell.js]
|
||||||
|
# Bug 676963: test fails consistently on Android
|
||||||
|
fail-if = os == "android"
|
||||||
[test_ipcshell_child.js]
|
[test_ipcshell_child.js]
|
||||||
|
|
|
@ -77,6 +77,36 @@ GRE_MODULE = 1
|
||||||
|
|
||||||
LIBS = $(NSPR_LIBS)
|
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)
|
ifeq ($(OS_ARCH),WINNT)
|
||||||
NO_PROFILE_GUIDED_OPTIMIZE = 1
|
NO_PROFILE_GUIDED_OPTIMIZE = 1
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -43,7 +43,6 @@ USE_AUTOCONF = 1
|
||||||
MOZILLA_CLIENT = 1
|
MOZILLA_CLIENT = 1
|
||||||
target = @target@
|
target = @target@
|
||||||
ac_configure_args = @ac_configure_args@
|
ac_configure_args = @ac_configure_args@
|
||||||
BUILD_MODULES = @BUILD_MODULES@
|
|
||||||
MOZILLA_VERSION = @MOZILLA_VERSION@
|
MOZILLA_VERSION = @MOZILLA_VERSION@
|
||||||
|
|
||||||
MOZ_BUILD_APP = @MOZ_BUILD_APP@
|
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 ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
|
||||||
#define STR_LEN(a) (ARRAY_LEN(a) - 1)
|
#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 */
|
/* changes all forward slashes in token to backslashes */
|
||||||
void changeForwardSlashesToBackSlashes ( wchar_t *arg )
|
void changeForwardSlashesToBackSlashes ( wchar_t *arg )
|
||||||
{
|
{
|
||||||
|
|
|
@ -153,6 +153,20 @@ xpcshell-tests:
|
||||||
$(LIBXUL_DIST)/bin/xpcshell \
|
$(LIBXUL_DIST)/bin/xpcshell \
|
||||||
$(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
|
$(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
|
# Execute a single test, specified in $(SOLO_FILE), but don't automatically
|
||||||
# start the test. Instead, present the xpcshell prompt so the user can
|
# start the test. Instead, present the xpcshell prompt so the user can
|
||||||
# attach a debugger and then start the test.
|
# attach a debugger and then start the test.
|
||||||
|
@ -182,6 +196,23 @@ check-one:
|
||||||
$(LIBXUL_DIST)/bin/xpcshell \
|
$(LIBXUL_DIST)/bin/xpcshell \
|
||||||
$(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
|
$(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
|
endif # XPCSHELL_TESTS
|
||||||
|
|
||||||
ifdef CPP_UNIT_TESTS
|
ifdef CPP_UNIT_TESTS
|
||||||
|
@ -1122,8 +1153,9 @@ ifdef HAVE_DTRACE
|
||||||
ifndef XP_MACOSX
|
ifndef XP_MACOSX
|
||||||
ifdef DTRACE_PROBE_OBJ
|
ifdef DTRACE_PROBE_OBJ
|
||||||
ifndef DTRACE_LIB_DEPENDENT
|
ifndef DTRACE_LIB_DEPENDENT
|
||||||
$(DTRACE_PROBE_OBJ):
|
NON_DTRACE_OBJS := $(filter-out $(DTRACE_PROBE_OBJ),$(OBJS))
|
||||||
dtrace -G -C -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ)
|
$(DTRACE_PROBE_OBJ): $(NON_DTRACE_OBJS)
|
||||||
|
dtrace -G -C -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ) $(NON_DTRACE_OBJS)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
@ -1519,9 +1551,6 @@ export:: FORCE
|
||||||
@echo; sleep 2; false
|
@echo; sleep 2; false
|
||||||
endif
|
endif
|
||||||
|
|
||||||
$(IDL_DIR)::
|
|
||||||
$(NSINSTALL) -D $@
|
|
||||||
|
|
||||||
# generate .h files from into $(XPIDL_GEN_DIR), then export to $(DIST)/include;
|
# generate .h files from into $(XPIDL_GEN_DIR), then export to $(DIST)/include;
|
||||||
# warn against overriding existing .h file.
|
# warn against overriding existing .h file.
|
||||||
$(XPIDL_GEN_DIR)/.done:
|
$(XPIDL_GEN_DIR)/.done:
|
||||||
|
@ -1592,14 +1621,8 @@ endif # XPIDLSRCS
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# General rules for exporting idl files.
|
# General rules for exporting idl files.
|
||||||
#
|
$(IDL_DIR):
|
||||||
# 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)::
|
|
||||||
$(NSINSTALL) -D $@
|
$(NSINSTALL) -D $@
|
||||||
|
|
||||||
export-idl:: $(SUBMAKEFILES) $(MAKE_DIRS)
|
export-idl:: $(SUBMAKEFILES) $(MAKE_DIRS)
|
||||||
|
@ -2066,7 +2089,6 @@ showhost:
|
||||||
@echo "HOST_LIBRARY = $(HOST_LIBRARY)"
|
@echo "HOST_LIBRARY = $(HOST_LIBRARY)"
|
||||||
|
|
||||||
showbuildmods::
|
showbuildmods::
|
||||||
@echo "Build Modules = $(BUILD_MODULES)"
|
|
||||||
@echo "Module dirs = $(BUILD_MODULE_DIRS)"
|
@echo "Module dirs = $(BUILD_MODULE_DIRS)"
|
||||||
|
|
||||||
documentation:
|
documentation:
|
||||||
|
|
|
@ -1992,14 +1992,11 @@ case "$target" in
|
||||||
*-darwin*)
|
*-darwin*)
|
||||||
MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -o $@'
|
MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -o $@'
|
||||||
MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -o $@'
|
MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -o $@'
|
||||||
|
# If we're building with --enable-profiling, we need a frame pointer.
|
||||||
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 test -z "$MOZ_PROFILING"; then
|
if test -z "$MOZ_PROFILING"; then
|
||||||
MOZ_OPTIMIZE_FLAGS="$MOZ_OPTIMIZE_FLAGS -fomit-frame-pointer"
|
MOZ_OPTIMIZE_FLAGS="-O3 -fomit-frame-pointer"
|
||||||
else
|
else
|
||||||
MOZ_OPTIMIZE_FLAGS="$MOZ_OPTIMIZE_FLAGS -fno-omit-frame-pointer"
|
MOZ_OPTIMIZE_FLAGS="-O3 -fno-omit-frame-pointer"
|
||||||
fi
|
fi
|
||||||
_PEDANTIC=
|
_PEDANTIC=
|
||||||
CFLAGS="$CFLAGS -fpascal-strings -fno-common"
|
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_ASSERT(script->compartment != cx->compartment);
|
||||||
JS_OPT_ASSERT(script->ownerObject == fun);
|
JS_OPT_ASSERT(script->ownerObject == fun);
|
||||||
|
|
||||||
|
cfun->u.i.script = NULL;
|
||||||
JSScript *cscript = js_CloneScript(cx, script);
|
JSScript *cscript = js_CloneScript(cx, script);
|
||||||
if (!cscript)
|
if (!cscript)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -1839,6 +1839,8 @@ main(int argc, char **argv, char **envp)
|
||||||
XRE_GetFileFromPath(argv[4], getter_AddRefs(appOmni));
|
XRE_GetFileFromPath(argv[4], getter_AddRefs(appOmni));
|
||||||
argc-=2;
|
argc-=2;
|
||||||
argv+=2;
|
argv+=2;
|
||||||
|
} else {
|
||||||
|
appOmni = greOmni;
|
||||||
}
|
}
|
||||||
|
|
||||||
XRE_InitOmnijar(greOmni, appOmni);
|
XRE_InitOmnijar(greOmni, appOmni);
|
||||||
|
|
|
@ -46,17 +46,8 @@ include $(DEPTH)/config/autoconf.mk
|
||||||
|
|
||||||
MODULE = xpconnect
|
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
|
LIBRARY_NAME = xpconnect_s
|
||||||
FORCE_STATIC_LIB = 1
|
FORCE_STATIC_LIB = 1
|
||||||
endif
|
|
||||||
LIBXUL_LIBRARY = 1
|
LIBXUL_LIBRARY = 1
|
||||||
EXPORTS = xpcpublic.h
|
EXPORTS = xpcpublic.h
|
||||||
|
|
||||||
|
|
|
@ -2074,7 +2074,8 @@ nsXPConnect::CreateSandbox(JSContext *cx, nsIPrincipal *principal,
|
||||||
jsval rval = JSVAL_VOID;
|
jsval rval = JSVAL_VOID;
|
||||||
AUTO_MARK_JSVAL(ccx, &rval);
|
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),
|
NS_ASSERTION(NS_FAILED(rv) || !JSVAL_IS_PRIMITIVE(rval),
|
||||||
"Bad return value from xpc_CreateSandboxObject()!");
|
"Bad return value from xpc_CreateSandboxObject()!");
|
||||||
|
|
||||||
|
|
|
@ -3153,7 +3153,7 @@ NS_IMPL_ISUPPORTS0(Identity)
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
xpc_CreateSandboxObject(JSContext * cx, jsval * vp, nsISupports *prinOrSop, JSObject *proto,
|
xpc_CreateSandboxObject(JSContext * cx, jsval * vp, nsISupports *prinOrSop, JSObject *proto,
|
||||||
bool wantXrays)
|
bool wantXrays, const nsACString &sandboxName)
|
||||||
{
|
{
|
||||||
// Create the sandbox global object
|
// Create the sandbox global object
|
||||||
nsresult rv;
|
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;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3351,6 +3355,8 @@ nsXPCComponents_utils_Sandbox::CallOrConstruct(nsIXPConnectWrappedNative *wrappe
|
||||||
|
|
||||||
JSObject *proto = nsnull;
|
JSObject *proto = nsnull;
|
||||||
bool wantXrays = true;
|
bool wantXrays = true;
|
||||||
|
nsCString sandboxName;
|
||||||
|
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
if (!JSVAL_IS_OBJECT(argv[1]))
|
if (!JSVAL_IS_OBJECT(argv[1]))
|
||||||
return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
|
return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
|
||||||
|
@ -3382,9 +3388,26 @@ nsXPCComponents_utils_Sandbox::CallOrConstruct(nsIXPConnectWrappedNative *wrappe
|
||||||
|
|
||||||
wantXrays = JSVAL_TO_BOOLEAN(option);
|
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)) {
|
if (NS_FAILED(rv)) {
|
||||||
return ThrowAndFail(rv, cx, _retval);
|
return ThrowAndFail(rv, cx, _retval);
|
||||||
|
|
|
@ -1584,22 +1584,30 @@ CompartmentStats::CompartmentStats(JSContext *cx, JSCompartment *c)
|
||||||
{
|
{
|
||||||
if(c->principals->codebase)
|
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.Assign(c->principals->codebase);
|
||||||
name.ReplaceChar('/', '\\');
|
|
||||||
|
|
||||||
// If it's the system compartment, append the address.
|
// If it's the system compartment, append the address.
|
||||||
// This means that multiple system compartments (and there
|
// This means that multiple system compartments (and there
|
||||||
// can be many) can be distinguished.
|
// can be many) can be distinguished.
|
||||||
if(c->isSystemCompartment)
|
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
|
// ample; 64-bit address max is 18 chars
|
||||||
static const int maxLength = 31;
|
static const int maxLength = 31;
|
||||||
nsPrintfCString address(maxLength, ", 0x%llx", PRUint64(c));
|
nsPrintfCString address(maxLength, ", 0x%llx", PRUint64(c));
|
||||||
name.Append(address);
|
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
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -4315,7 +4315,7 @@ xpc_GetJSPrivate(JSObject *obj)
|
||||||
// and used.
|
// and used.
|
||||||
nsresult
|
nsresult
|
||||||
xpc_CreateSandboxObject(JSContext * cx, jsval * vp, nsISupports *prinOrSop,
|
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
|
// Helper for evaluating scripts in a sandbox object created with
|
||||||
// xpc_CreateSandboxObject(). The caller is responsible of ensuring
|
// xpc_CreateSandboxObject(). The caller is responsible of ensuring
|
||||||
|
@ -4396,6 +4396,7 @@ struct CompartmentPrivate
|
||||||
JSObject2JSObjectMap *waiverWrapperMap;
|
JSObject2JSObjectMap *waiverWrapperMap;
|
||||||
// NB: we don't want this map to hold a strong reference to the wrapper.
|
// NB: we don't want this map to hold a strong reference to the wrapper.
|
||||||
nsDataHashtable<nsPtrHashKey<XPCWrappedNative>, JSObject *> *expandoMap;
|
nsDataHashtable<nsPtrHashKey<XPCWrappedNative>, JSObject *> *expandoMap;
|
||||||
|
nsCString location;
|
||||||
|
|
||||||
bool RegisterExpandoObject(XPCWrappedNative *wn, JSObject *expando) {
|
bool RegisterExpandoObject(XPCWrappedNative *wn, JSObject *expando) {
|
||||||
if (!expandoMap) {
|
if (!expandoMap) {
|
||||||
|
|
|
@ -15,6 +15,8 @@ tail =
|
||||||
[test_import.js]
|
[test_import.js]
|
||||||
[test_js_weak_references.js]
|
[test_js_weak_references.js]
|
||||||
[test_localeCompare.js]
|
[test_localeCompare.js]
|
||||||
|
# Bug 676965: test fails consistently on Android
|
||||||
|
fail-if = os == "android"
|
||||||
[test_recursive_import.js]
|
[test_recursive_import.js]
|
||||||
[test_xpcomutils.js]
|
[test_xpcomutils.js]
|
||||||
[test_unload.js]
|
[test_unload.js]
|
||||||
|
|
|
@ -83,11 +83,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Size to use for PLArena block allocations.
|
// Size to use for PLArena block allocations.
|
||||||
// XXX: This should be 8192; the subtracted elements are a hack that's
|
static const size_t ARENA_PAGE_SIZE = 8192;
|
||||||
// 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;
|
|
||||||
|
|
||||||
// Freed memory is filled with a poison value, which we arrange to
|
// Freed memory is filled with a poison value, which we arrange to
|
||||||
// form a pointer either to an always-unmapped region of the address
|
// form a pointer either to an always-unmapped region of the address
|
||||||
|
|
|
@ -12,13 +12,13 @@
|
||||||
function test() {
|
function test() {
|
||||||
document.querySelector("div").focus();
|
document.querySelector("div").focus();
|
||||||
// type a character, then press backspace to delete it
|
// type a character, then press backspace to delete it
|
||||||
sendKey("X", window);
|
sendKey("X", "div1");
|
||||||
sendKey("BACK_SPACE", window);
|
sendKey("BACK_SPACE", "div1");
|
||||||
document.documentElement.removeAttribute("class");
|
document.documentElement.removeAttribute("class");
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body onload="test()">
|
<body onload="test()">
|
||||||
<div contenteditable></div>
|
<div id="div1" contenteditable></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -12,13 +12,13 @@
|
||||||
function test() {
|
function test() {
|
||||||
document.querySelector("div").focus();
|
document.querySelector("div").focus();
|
||||||
// type a character, then press backspace to delete it
|
// type a character, then press backspace to delete it
|
||||||
sendKey("X", window);
|
sendKey("X", "div1");
|
||||||
sendKey("BACK_SPACE", window);
|
sendKey("BACK_SPACE", "div1");
|
||||||
document.documentElement.removeAttribute("class");
|
document.documentElement.removeAttribute("class");
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body onload="test()">
|
<body onload="test()">
|
||||||
<div contenteditable></div>
|
<div id="div1" contenteditable></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -12,13 +12,13 @@
|
||||||
function test() {
|
function test() {
|
||||||
document.querySelector("div").focus();
|
document.querySelector("div").focus();
|
||||||
// type a character, then press backspace to delete it
|
// type a character, then press backspace to delete it
|
||||||
sendKey("X", window);
|
sendKey("X", "div1");
|
||||||
sendKey("BACK_SPACE", window);
|
sendKey("BACK_SPACE", "div1");
|
||||||
document.documentElement.removeAttribute("class");
|
document.documentElement.removeAttribute("class");
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body onload="test()">
|
<body onload="test()">
|
||||||
<div contenteditable></div>
|
<div id="div1" contenteditable></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -249,6 +249,7 @@ nsProgressFrame::AttributeChanged(PRInt32 aNameSpaceID,
|
||||||
NS_ASSERTION(barFrame, "The progress frame should have a child with a frame!");
|
NS_ASSERTION(barFrame, "The progress frame should have a child with a frame!");
|
||||||
PresContext()->PresShell()->FrameNeedsReflow(barFrame, nsIPresShell::eResize,
|
PresContext()->PresShell()->FrameNeedsReflow(barFrame, nsIPresShell::eResize,
|
||||||
NS_FRAME_IS_DIRTY);
|
NS_FRAME_IS_DIRTY);
|
||||||
|
Invalidate(GetVisualOverflowRectRelativeToSelf());
|
||||||
}
|
}
|
||||||
|
|
||||||
return nsHTMLContainerFrame::AttributeChanged(aNameSpaceID, aAttribute,
|
return nsHTMLContainerFrame::AttributeChanged(aNameSpaceID, aAttribute,
|
||||||
|
@ -278,6 +279,28 @@ nsProgressFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext,
|
||||||
return autoSize;
|
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
|
bool
|
||||||
nsProgressFrame::ShouldUseNativeStyle() const
|
nsProgressFrame::ShouldUseNativeStyle() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -84,6 +84,9 @@ public:
|
||||||
nsSize aMargin, nsSize aBorder,
|
nsSize aMargin, nsSize aBorder,
|
||||||
nsSize aPadding, PRBool aShrinkWrap);
|
nsSize aPadding, PRBool aShrinkWrap);
|
||||||
|
|
||||||
|
virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext);
|
||||||
|
virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext);
|
||||||
|
|
||||||
virtual PRBool IsFrameOfType(PRUint32 aFlags) const
|
virtual PRBool IsFrameOfType(PRUint32 aFlags) const
|
||||||
{
|
{
|
||||||
return nsHTMLContainerFrame::IsFrameOfType(aFlags &
|
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.
|
# transformations will not behave exactly the same for <progress> and two divs.
|
||||||
# However, it would be possible to manually check those.
|
# However, it would be possible to manually check those.
|
||||||
# == transformations.html transformations-ref.html
|
# == transformations.html transformations-ref.html
|
||||||
|
|
||||||
|
# Tests for bugs:
|
||||||
|
== block-invalidate.html block-invalidate-ref.html
|
||||||
|
== in-cells.html in-cells-ref.html
|
||||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче