Merge mozilla-central to electrolysis to pick up bug 515436.

This commit is contained in:
Benjamin Smedberg 2009-10-12 10:51:38 -04:00
Родитель de31404147 2a2bea0133
Коммит 960781ec85
3928 изменённых файлов: 34968 добавлений и 15075 удалений

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

@ -408,15 +408,6 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eARIASelectable,
eARIAReadonly
},
{
"section",
nsIAccessibleRole::ROLE_SECTION,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
kNoReqStates
},
{
"separator",
nsIAccessibleRole::ROLE_SEPARATOR,

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

@ -96,6 +96,7 @@ _TEST_FILES =\
test_events_doc.html \
test_events_draganddrop.html \
test_events_flush.html \
test_events_focus.html \
test_events_focus.xul \
test_events_mutation.html \
test_events_tree.xul \

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

@ -91,6 +91,7 @@ function unregisterA11yEventListener(aEventType, aEventHandler)
listenA11yEvents(false);
}
////////////////////////////////////////////////////////////////////////////////
// Event queue
@ -106,15 +107,6 @@ const INVOKER_ACTION_FAILED = 1;
*/
const DO_NOT_FINISH_TEST = 1;
/**
* Common invoker checker (see eventSeq of eventQueue).
*/
function invokerChecker(aEventType, aTarget)
{
this.type = aEventType;
this.target = aTarget;
}
/**
* Creates event queue for the given event type. The queue consists of invoker
* objects, each of them generates the event of the event type. When queue is
@ -539,6 +531,9 @@ function eventQueue(aEventType)
}
////////////////////////////////////////////////////////////////////////////////
// Action sequence
/**
* Deal with action sequence. Used when you need to execute couple of actions
* each after other one.
@ -586,6 +581,168 @@ function sequence()
}
////////////////////////////////////////////////////////////////////////////////
// Event queue invokers
/**
* Invokers defined below take a checker object implementing 'check' method
* which will be called when proper event is handled. Invokers listen default
* event type registered in event queue object.
*
* Note, you don't need to initialize 'target' and 'type' members of checker
* object. The 'target' member will be initialized by invoker object and you are
* free to use it in 'check' method.
*/
/**
* Click invoker.
*/
function synthClick(aNodeOrID, aChecker)
{
this.__proto__ = new synthAction(aNodeOrID, aChecker);
this.invoke = function synthClick_invoke()
{
// Scroll the node into view, otherwise synth click may fail.
this.DOMNode.scrollIntoView(true);
synthesizeMouse(this.DOMNode, 1, 1, {});
}
this.getID = function synthFocus_getID()
{
return prettyName(aNodeOrID) + " click";
}
}
/**
* General key press invoker.
*/
function synthKey(aNodeOrID, aKey, aArgs, aChecker)
{
this.__proto__ = new synthAction(aNodeOrID, aChecker);
this.invoke = function synthKey_invoke()
{
synthesizeKey(this.mKey, this.mArgs);
}
this.getID = function synthFocus_getID()
{
return prettyName(aNodeOrID) + " '" + this.mKey + "' key";
}
this.mKey = aKey;
this.mArgs = aArgs ? aArgs : {};
}
/**
* Tab key invoker.
*/
function synthTab(aNodeOrID, aChecker)
{
this.__proto__ = new synthKey(aNodeOrID, "VK_TAB", { shiftKey: false },
aChecker);
this.getID = function synthTabTest_getID()
{
return prettyName(aNodeOrID) + " tab";
}
}
/**
* Shift tab key invoker.
*/
function synthShiftTab(aNodeOrID, aChecker)
{
this.__proto__ = new synthKey(aNodeOrID, "VK_TAB", { shiftKey: true },
aChecker);
this.getID = function synthTabTest_getID()
{
return prettyName(aNodeOrID) + " shift tab";
}
}
/**
* Down arrow key invoker.
*/
function synthDownKey(aNodeOrID, aChecker)
{
this.__proto__ = new synthKey(aNodeOrID, "VK_DOWN", null, aChecker);
this.getID = function synthDownKey_getID()
{
return prettyName(aNodeOrID) + " key down";
}
}
/**
* Right arrow key invoker.
*/
function synthRightKey(aNodeOrID, aChecker)
{
this.__proto__ = new synthKey(aNodeOrID, "VK_RIGHT", null, aChecker);
this.getID = function synthRightKey_getID()
{
return prettyName(aNodeOrID) + " key right";
}
}
/**
* Focus invoker.
*/
function synthFocus(aNodeOrID, aChecker)
{
this.__proto__ = new synthAction(aNodeOrID, aChecker);
this.invoke = function synthFocus_invoke()
{
this.DOMNode.focus();
}
this.getID = function synthFocus_getID()
{
return prettyName(aNodeOrID) + " focus";
}
}
/**
* Select all invoker.
*/
function synthSelectAll(aNodeOrID, aChecker)
{
this.__proto__ = new synthAction(aNodeOrID, aChecker);
this.invoke = function synthSelectAll_invoke()
{
if (this.DOMNode instanceof Components.interfaces.nsIDOMHTMLInputElement)
this.DOMNode.select();
else
window.getSelection().selectAllChildren(this.DOMNode);
}
this.getID = function synthSelectAll_getID()
{
return aNodeOrID + " selectall";
}
}
////////////////////////////////////////////////////////////////////////////////
// Event queue checkers
/**
* Common invoker checker (see eventSeq of eventQueue).
*/
function invokerChecker(aEventType, aTarget)
{
this.type = aEventType;
this.target = aTarget;
}
////////////////////////////////////////////////////////////////////////////////
// Private implementation details.
////////////////////////////////////////////////////////////////////////////////
@ -741,3 +898,22 @@ function sequenceItem(aProcessor, aEventType, aTarget, aItemID)
this.queue.push(invoker);
}
////////////////////////////////////////////////////////////////////////////////
// Event queue invokers
/**
* Invoker base class for prepare an action.
*/
function synthAction(aNodeOrID, aChecker)
{
this.DOMNode = getNode(aNodeOrID);
aChecker.target = this.DOMNode;
this.check = function synthAction_check(aEvent)
{
aChecker.check(aEvent);
}
this.getID = function synthAction_getID() { return aNodeOrID + " action"; }
}

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

@ -56,6 +56,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=469688
// test gEmptyRoleMap
testRole("cell", ROLE_NOTHING);
// abstract roles
var abstract_roles = ["composite", "landmark", "structure", "widget",
"window", "input", "range", "select", "section",
"sectionhead"];
for (a in abstract_roles)
testRole(abstract_roles[a], ROLE_SECTION);
SimpleTest.finish();
}
@ -111,5 +118,21 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=469688
</tr>
</table>
<!-- user agents must not map abstract roles to platform API -->
<!-- test abstract base type roles -->
<div role="composite" id="composite">composite</div>
<div role="landmark" id="landmark">landmark</div>
<div role="roletype" id="roletype">roletype</div>
<div role="structure" id="structure">structure</div>
<div role="widget" id="widget">widget</div>
<div role="window" id="window">window</div>
<!-- test abstract input roles -->
<div role="input" id="input">input</div>
<div role="range" id="range">range</div>
<div role="select" id="select">select</div>
<!-- test abstract structure roles -->
<div role="section" id="section">section</div>
<div role="sectionhead" id="sectionhead">sectionhead</div>
</body>
</html>

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

@ -20,135 +20,37 @@
<script type="application/javascript">
/**
* Invoker base class.
* Generic checker.
*/
function synthAction(aNodeOrID, aCaretOffset)
function checker(aCaretOffset)
{
this.DOMNode = getNode(aNodeOrID);
this.check = function synthAction_check(aEvent)
this.check = function checker_check(aEvent)
{
is(aEvent.QueryInterface(nsIAccessibleCaretMoveEvent).caretOffset,
this.caretOffset,
"Wrong caret offset for " + aNodeOrID);
aCaretOffset,
"Wrong caret offset for " + prettyName(aEvent.target));
}
this.getID = function synthAction_getID() { return aNodeOrID + " action"; }
this.caretOffset = aCaretOffset;
}
/**
* Click invoker.
* Click checker.
*/
function synthClick(aNodeOrID, aCaretOffset,
aExtraNodeOrID, aExtraCaretOffset)
function clickChecker(aCaretOffset, aExtraNodeOrID, aExtraCaretOffset)
{
this.__proto__ = new synthAction(aNodeOrID, aCaretOffset);
this.__proto__ = new checker(aCaretOffset);
this.extraNode = getNode(aExtraNodeOrID);
this.extraCaretOffset = aExtraCaretOffset;
this.invoke = function synthClick_invoke()
{
// Scroll the node into view, otherwise synth click may fail.
this.DOMNode.scrollIntoView(true);
synthesizeMouse(this.DOMNode, 1, 1, {});
}
this.check = function synthFocus_check(aEvent)
this.check = function clickChecker_check(aEvent)
{
this.__proto__.check(aEvent);
if (this.extraNode) {
var acc = getAccessible(this.extraNode, [nsIAccessibleText]);
is(acc.caretOffset, this.extraCaretOffset,
is(acc.caretOffset, aExtraCaretOffset,
"Wrong caret offset for " + aExtraNodeOrID);
}
}
this.getID = function synthFocus_getID() { return aNodeOrID + " click"; }
}
/**
* Key press invokers.
*/
function synthKey(aNodeOrID, aCaretOffset, aKey, aArgs)
{
this.__proto__ = new synthAction(aNodeOrID, aCaretOffset);
this.invoke = function synthKey_invoke()
{
synthesizeKey(this.mKey, this.mArgs);
}
this.mKey = aKey;
this.mArgs = aArgs ? aArgs : {};
}
function synthTabTest(aNodeOrID, aCaretOffset, aBackTab)
{
this.__proto__ = new synthKey(aNodeOrID, aCaretOffset,
"VK_TAB", {shiftKey: aBackTab});
this.getID = function synthTabTest_getID() { return aNodeOrID + " tab"; }
}
function synthDownKey(aNodeOrID, aCaretOffset)
{
this.__proto__ = new synthKey(aNodeOrID, aCaretOffset, "VK_DOWN");
this.getID = function synthDownKey_getID()
{
return aNodeOrID + " key down";
}
}
function synthRightKey(aNodeOrID, aCaretOffset)
{
this.__proto__ = new synthKey(aNodeOrID, aCaretOffset, "VK_RIGHT");
this.getID = function synthRightKey_getID()
{
return aNodeOrID + " key right";
}
}
/**
* Focus invoker.
*/
function synthFocus(aNodeOrID, aCaretOffset)
{
this.__proto__ = new synthAction(aNodeOrID, aCaretOffset);
this.invoke = function synthFocus_invoke()
{
this.DOMNode.focus();
}
this.getID = function synthFocus_getID() { return aNodeOrID + " focus"; }
}
/**
* Select all invoker.
*/
function synthSelectAll(aNodeOrID, aCaretOffset)
{
this.__proto__ = new synthAction(aNodeOrID, aCaretOffset);
this.invoke = function synthSelectAll_invoke()
{
if (this.DOMNode instanceof Components.interfaces.nsIDOMHTMLInputElement)
this.DOMNode.select();
else
window.getSelection().selectAllChildren(this.DOMNode);
}
this.getID = function synthSelectAll_getID()
{
return aNodeOrID + " selectall";
}
}
/**
@ -177,26 +79,27 @@
gQueue = new eventQueue(nsIAccessibleEvent.EVENT_TEXT_CARET_MOVED);
var id = "textbox";
gQueue.push(new synthFocus(id, 5));
gQueue.push(new synthSelectAll(id, 5));
gQueue.push(new synthClick(id, 0));
gQueue.push(new synthRightKey(id, 1));
gQueue.push(new synthFocus(id, new checker(5)));
gQueue.push(new synthSelectAll(id, new checker(5)));
gQueue.push(new synthClick(id, new checker(0)));
gQueue.push(new synthRightKey(id, new checker(1)));
id = "textarea";
gQueue.push(new synthClick(id, 0));
gQueue.push(new synthRightKey(id, 1));
gQueue.push(new synthDownKey(id, 12));
gQueue.push(new synthClick(id, new checker(0)));
gQueue.push(new synthRightKey(id, new checker(1)));
gQueue.push(new synthDownKey(id, new checker(12)));
id = "p";
gQueue.push(new synthClick(id, 0));
gQueue.push(new synthRightKey(id, 1));
gQueue.push(new synthDownKey(id, 6));
gQueue.push(new synthClick(id, new checker(0)));
gQueue.push(new synthRightKey(id, new checker(1)));
gQueue.push(new synthDownKey(id, new checker(6)));
gQueue.push(new synthClick("p1_in_div", 0, "p2_in_div", -1));
gQueue.push(new synthClick("p1_in_div",
new clickChecker(0, "p2_in_div", -1)));
gQueue.push(new synthTabTest("p", 0, true));
gQueue.push(new synthTabTest("textarea", 12, true));
gQueue.push(new synthTabTest("p", 0, false));
gQueue.push(new synthShiftTab("p", new checker(0)));
gQueue.push(new synthShiftTab("textarea", new checker(12)));
gQueue.push(new synthTab("p", new checker(0)));
gQueue.invoke(); // Will call SimpleTest.finish();
}

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

@ -0,0 +1,121 @@
<html>
<head>
<title>Accessible focus testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/common.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/events.js"></script>
<script type="application/javascript">
/**
* Checker for invokers.
*/
function actionChecker(aDescription)
{
this.check = function actionChecker_check(aEvent)
{
var target = aEvent.accessible;
is(target.description, aDescription,
"Wrong description for " + prettyName(target));
}
}
var gFocusHandler = {
handleEvent: function gFocusHandler_handleEvent(aEvent) {
var elm = aEvent.target;
if (elm.nodeType != nsIDOMNode.ELEMENT_NODE)
return;
gTooltipElm.style.display = "block";
elm.setAttribute("aria-describedby", "tooltip");
}
};
var gBlurHandler = {
handleEvent: function gBlurHandler_handleEvent(aEvent) {
gTooltipElm.style.display = "none";
var elm = aEvent.target;
if (elm.nodeType == nsIDOMNode.ELEMENT_NODE)
elm.removeAttribute("aria-describedby");
}
};
/**
* Do tests.
*/
// gA11yEventDumpID = "eventdump"; // debug stuff
var gQueue = null;
var gButtonElm = null;
var gTextboxElm = null;
var gTooltipElm = null;
function doTests()
{
gButtonElm = getNode("button");
gTextboxElm = getNode("textbox");
gTooltipElm = getNode("tooltip");
gButtonElm.addEventListener("focus", gFocusHandler, false);
gButtonElm.addEventListener("blur", gBlurHandler, false);
gTextboxElm.addEventListener("focus", gFocusHandler, false);
gTextboxElm.addEventListener("blur", gBlurHandler, false);
// The aria-describedby is changed on DOM focus. Accessible description
// should be updated when a11y focus is fired.
gQueue = new eventQueue(nsIAccessibleEvent.EVENT_FOCUS);
gQueue.onFinish = function()
{
gButtonElm.removeEventListener("focus", gFocusHandler, false);
gButtonElm.removeEventListener("blur", gBlurHandler, false);
gTextboxElm.removeEventListener("focus", gFocusHandler, false);
gTextboxElm.removeEventListener("blur", gBlurHandler, false);
}
var checker = new actionChecker("It's a tooltip");
gQueue.push(new synthFocus("button", checker));
gQueue.push(new synthTab("textbox", checker));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=520709"
title="mochitest to ensure name/description are updated on a11y focus if they were changed on DOM focus">
Mozilla Bug 520709
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div id="tooltip" style="display: none" aria-hidden="true">It's a tooltip</div>
<button id="button">button</button>
<input id="textbox">
<div id="eventdump"></div>
</body>
</html>

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

@ -122,7 +122,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=391829
<div id="live" aria-live="polite">excuse <div id="liveChild">me</div></div>
<div id="live2" role="marquee" aria-live="polite">excuse <div id="live2Child">me</div></div>
<div id="live3" role="section">excuse</div>
<div id="live3" role="region">excuse</div>
<div id="log" role="log">excuse <div id="logChild">me</div></div>
<div id="logAssertive" role="log" aria-live="assertive">excuse <div id="logAssertiveChild">me</div></div>
<div id="marquee" role="marquee">excuse <div id="marqueeChild">me</div></div>

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

@ -342,10 +342,6 @@ ifdef LIBXUL_SDK
else
rm -f $(DIST)/$(APP_NAME).app/Contents/MacOS/$(PROGRAM)
rsync -aL $(PROGRAM) $(DIST)/$(APP_NAME).app/Contents/MacOS
endif
ifndef MOZ_COCOA_PRINTING
mkdir -p $(DIST)/$(APP_NAME).app/Contents/Plug-Ins
rsync -a --copy-unsafe-links $(LIBXUL_DIST)/package/PrintPDE.plugin $(DIST)/$(APP_NAME).app/Contents/Plug-Ins
endif
-cp -L $(DIST)/bin/mangle $(DIST)/bin/shlibsign $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)
cp -RL $(DIST)/branding/firefox.icns $(DIST)/$(APP_NAME).app/Contents/Resources/firefox.icns

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

@ -572,7 +572,7 @@ pref("pfs.datasource.url", "https://pfs.mozilla.org/plugins/PluginFinderService.
pref("plugins.hide_infobar_for_missing_plugin", false);
pref("plugins.hide_infobar_for_outdated_plugin", false);
pref("plugins.update.url", "https://www.mozilla.com/%LOCALE%/plugins/");
pref("plugins.update.url", "https://www.mozilla.com/%LOCALE%/plugincheck/");
pref("plugins.update.notifyUser", false);
#ifdef XP_WIN
@ -903,3 +903,16 @@ pref("toolbar.customization.usesheet", false);
pref("dom.ipc.plugins.enabled", false);
pref("dom.ipc.tabs.enabled", false);
#ifdef XP_WIN
#ifndef WINCE
pref("browser.taskbar.previews.enable", true);
pref("browser.taskbar.previews.max", 20);
pref("browser.taskbar.previews.cachetime", 20);
pref("browser.taskbar.lists.enabled", true);
pref("browser.taskbar.lists.frequent.enabled", true);
pref("browser.taskbar.lists.recent.enabled", false);
pref("browser.taskbar.lists.maxListItemCount", 7);
pref("browser.taskbar.lists.tasks.enabled", true);
#endif
#endif

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

@ -91,7 +91,7 @@
<command id="Browser:AddBookmarkAs"
oncommand="PlacesCommandHook.bookmarkCurrentPage(true, PlacesUtils.bookmarksMenuFolderId);"/>
<!-- The command is disabled for the hidden window. Otherwise its enabled
state is handled by the BookmarkAllTabsHandler object. -->
state is handled by gBookmarkAllTabsHandler. -->
<command id="Browser:BookmarkAllTabs"
oncommand="gBookmarkAllTabsHandler.doCommand();"
disabled="true"/>

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

@ -83,7 +83,8 @@ toolbarpaletteitem[place="palette"] > toolbaritem > hbox[type="places"] {
%ifdef MOZ_WIDGET_GTK2
/* Bookmarks override the "images-in-menus" metric in xul.css */
.bookmark-item > .menu-iconic-left {
.bookmark-item > .menu-iconic-left,
.searchbar-engine-menuitem > .menu-iconic-left {
visibility: inherit;
}
%endif

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

@ -47,6 +47,7 @@
# Edward Lee <edward.lee@engineering.uiuc.edu>
# Paul OShannessy <paul@oshannessy.com>
# Nils Maier <maierman@web.de>
# Rob Arnold <robarnold@cmu.edu>
#
# 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
@ -73,15 +74,9 @@ var gLastBrowserCharset = null;
var gPrevCharset = null;
var gProxyFavIcon = null;
var gLastValidURLStr = "";
var gProgressCollapseTimer = null;
var gInPrintPreviewMode = false;
let gDownloadMgr = null;
// Global variable that holds the nsContextMenu instance.
var gContextMenu = null;
var gAutoHideTabbarPrefListener = null;
var gBookmarkAllTabsHandler = null;
var gDownloadMgr = null;
var gContextMenu = null; // nsContextMenu instance
#ifndef XP_MACOSX
var gEditUIVisible = true;
@ -92,7 +87,6 @@ var gEditUIVisible = true;
["gNavToolbox", "navigator-toolbox"],
["gURLBar", "urlbar"],
["gNavigatorBundle", "bundle_browser"],
["gProgressMeterPanel", "statusbar-progresspanel"],
["gFindBar", "FindToolbar"]
].forEach(function (elementGlobal) {
var [name, id] = elementGlobal;
@ -135,6 +129,29 @@ let gInitialPages = [
#include browser-places.js
#include browser-tabPreviews.js
XPCOMUtils.defineLazyGetter(this, "Win7Features", function () {
#ifdef XP_WIN
#ifndef WINCE
const WINTASKBAR_CONTRACTID = "@mozilla.org/windows-taskbar;1";
if (WINTASKBAR_CONTRACTID in Cc &&
Cc[WINTASKBAR_CONTRACTID].getService(Ci.nsIWinTaskbar).available) {
let temp = {};
Cu.import("resource://gre/modules/WindowsPreviewPerTab.jsm", temp);
let AeroPeek = temp.AeroPeek;
return {
onOpenWindow: function () {
AeroPeek.onOpenWindow(window);
},
onCloseWindow: function () {
AeroPeek.onCloseWindow(window);
}
};
}
#endif
#endif
return null;
});
/**
* We can avoid adding multiple load event listeners and save some time by adding
* one listener that calls all real handlers.
@ -1077,7 +1094,6 @@ function prepareForStartup() {
gBrowser.addEventListener("PluginOutdated", gMissingPluginInstaller.newMissingPlugin, true, true);
gBrowser.addEventListener("PluginDisabled", gMissingPluginInstaller.newDisabledPlugin, true, true);
gBrowser.addEventListener("NewPluginInstalled", gMissingPluginInstaller.refreshBrowser, false);
gBrowser.addEventListener("NewTab", BrowserOpenTab, false);
window.addEventListener("AppCommand", HandleAppCommandEvent, true);
var webNavigation;
@ -1192,7 +1208,7 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) {
initializeSanitizer();
// Enable/Disable auto-hide tabbar
gAutoHideTabbarPrefListener = new AutoHideTabbarPrefListener();
gAutoHideTabbarPrefListener.toggleAutoHideTabbar();
gPrefService.addObserver(gAutoHideTabbarPrefListener.domain,
gAutoHideTabbarPrefListener, false);
@ -1279,7 +1295,7 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) {
}
// bookmark-all-tabs command
gBookmarkAllTabsHandler = new BookmarkAllTabsHandler();
gBookmarkAllTabsHandler.init();
// Attach a listener to watch for "command" events bubbling up from error
// pages. This lets us fix bugs like 401575 which require error page UI to
@ -1341,10 +1357,16 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) {
gBrowser.mPanelContainer.addEventListener("InstallBrowserTheme", LightWeightThemeWebInstaller, false, true);
gBrowser.mPanelContainer.addEventListener("PreviewBrowserTheme", LightWeightThemeWebInstaller, false, true);
gBrowser.mPanelContainer.addEventListener("ResetBrowserThemePreview", LightWeightThemeWebInstaller, false, true);
if (Win7Features)
Win7Features.onOpenWindow();
}
function BrowserShutdown()
{
if (Win7Features)
Win7Features.onCloseWindow();
gPrefService.removeObserver(ctrlTab.prefName, ctrlTab);
gPrefService.removeObserver(allTabs.prefName, allTabs);
tabPreviews.uninit();
@ -1353,6 +1375,8 @@ function BrowserShutdown()
gGestureSupport.init(false);
FullScreen.cleanup();
try {
FullZoom.destroy();
}
@ -1471,24 +1495,13 @@ function nonBrowserWindowShutdown()
}
#endif
function AutoHideTabbarPrefListener()
{
this.toggleAutoHideTabbar();
}
AutoHideTabbarPrefListener.prototype =
{
var gAutoHideTabbarPrefListener = {
domain: "browser.tabs.autoHide",
observe: function (aSubject, aTopic, aPrefName)
{
if (aTopic != "nsPref:changed" || aPrefName != this.domain)
return;
this.toggleAutoHideTabbar();
observe: function (aSubject, aTopic, aPrefName) {
if (aTopic == "nsPref:changed" && aPrefName == this.domain)
this.toggleAutoHideTabbar();
},
toggleAutoHideTabbar: function ()
{
toggleAutoHideTabbar: function () {
if (gBrowser.tabContainer.childNodes.length == 1 &&
window.toolbar.visible) {
var aVisible = false;
@ -1884,24 +1897,8 @@ function BrowserCloseTabOrWindow() {
function BrowserTryToCloseWindow()
{
if (WindowIsClosing()) {
if (window.fullScreen) {
gBrowser.mPanelContainer.removeEventListener("mousemove",
FullScreen._collapseCallback, false);
document.removeEventListener("keypress", FullScreen._keyToggleCallback, false);
document.removeEventListener("popupshown", FullScreen._setPopupOpen, false);
document.removeEventListener("popuphidden", FullScreen._setPopupOpen, false);
gPrefService.removeObserver("browser.fullscreen", FullScreen);
var fullScrToggler = document.getElementById("fullscr-toggler");
if (fullScrToggler) {
fullScrToggler.removeEventListener("mouseover", FullScreen._expandCallback, false);
fullScrToggler.removeEventListener("dragenter", FullScreen._expandCallback, false);
}
}
if (WindowIsClosing())
window.close(); // WindowIsClosing does all the necessary checks
}
}
function loadURI(uri, referrer, postData, allowThirdPartyFixup)
@ -3489,11 +3486,11 @@ var FullScreen =
this.showXULChrome("statusbar", window.fullScreen);
document.getElementById("View:FullScreen").setAttribute("checked", !window.fullScreen);
var fullScrToggler = document.getElementById("fullscr-toggler");
if (!window.fullScreen) {
// Add a tiny toolbar to receive mouseover and dragenter events, and provide affordance.
// This will help simulate the "collapse" metaphor while also requiring less code and
// events than raw listening of mouse coords.
let fullScrToggler = document.getElementById("fullscr-toggler");
if (!fullScrToggler) {
fullScrToggler = document.createElement("toolbar");
fullScrToggler.id = "fullscr-toggler";
@ -3519,16 +3516,6 @@ var FullScreen =
gPrefService.addObserver("browser.fullscreen", this, false);
}
else {
document.removeEventListener("keypress", this._keyToggleCallback, false);
document.removeEventListener("popupshown", this._setPopupOpen, false);
document.removeEventListener("popuphidden", this._setPopupOpen, false);
gPrefService.removeObserver("browser.fullscreen", this);
if (fullScrToggler) {
fullScrToggler.removeEventListener("mouseover", this._expandCallback, false);
fullScrToggler.removeEventListener("dragenter", this._expandCallback, false);
}
// The user may quit fullscreen during an animation
clearInterval(this._animationInterval);
clearTimeout(this._animationTimeout);
@ -3539,8 +3526,24 @@ var FullScreen =
// This is needed if they use the context menu to quit fullscreen
this._isPopupOpen = false;
this.cleanup();
}
},
cleanup: function () {
if (window.fullScreen) {
gBrowser.mPanelContainer.removeEventListener("mousemove",
this._collapseCallback, false);
document.removeEventListener("keypress", this._keyToggleCallback, false);
document.removeEventListener("popupshown", this._setPopupOpen, false);
document.removeEventListener("popuphidden", this._setPopupOpen, false);
gPrefService.removeObserver("browser.fullscreen", this);
let fullScrToggler = document.getElementById("fullscr-toggler");
if (fullScrToggler) {
fullScrToggler.removeEventListener("mouseover", this._expandCallback, false);
fullScrToggler.removeEventListener("dragenter", this._expandCallback, false);
}
}
},
@ -3805,7 +3808,7 @@ var XULBrowserWindow = {
lastURI: null,
isBusy: false,
statusTimeoutInEffect: false,
_progressCollapseTimer: 0,
QueryInterface: function (aIID) {
if (aIID.equals(Ci.nsIWebProgressListener) ||
@ -3954,9 +3957,9 @@ var XULBrowserWindow = {
// Turn the status meter on.
this.statusMeter.value = 0; // be sure to clear the progress bar
if (gProgressCollapseTimer) {
window.clearTimeout(gProgressCollapseTimer);
gProgressCollapseTimer = null;
if (this._progressCollapseTimer) {
clearTimeout(this._progressCollapseTimer);
this._progressCollapseTimer = 0;
}
else
this.statusMeter.parentNode.collapsed = false;
@ -4021,10 +4024,10 @@ var XULBrowserWindow = {
this._busyUI = false;
// Turn the progress meter and throbber off.
gProgressCollapseTimer = window.setTimeout(function () {
gProgressMeterPanel.collapsed = true;
gProgressCollapseTimer = null;
}, 100);
this._progressCollapseTimer = setTimeout(function (self) {
self.statusMeter.parentNode.collapsed = true;
self._progressCollapseTimer = 0;
}, 100, this);
if (this.throbberElement)
this.throbberElement.removeAttribute("busy");
@ -4376,22 +4379,12 @@ var TabsProgressListener = {
}
}
function nsBrowserAccess()
{
}
function nsBrowserAccess() { }
nsBrowserAccess.prototype =
{
QueryInterface : function(aIID)
{
if (aIID.equals(Ci.nsIBrowserDOMWindow) ||
aIID.equals(Ci.nsISupports))
return this;
throw Components.results.NS_NOINTERFACE;
},
nsBrowserAccess.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIBrowserDOMWindow, Ci.nsISupports]),
openURI : function(aURI, aOpener, aWhere, aContext)
{
openURI: function (aURI, aOpener, aWhere, aContext) {
var newWindow = null;
var isExternal = (aContext == Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
@ -4462,8 +4455,7 @@ nsBrowserAccess.prototype =
return newWindow;
},
isTabContentWindow : function(aWindow)
{
isTabContentWindow: function (aWindow) {
return gBrowser.browsers.some(function (browser) browser.contentWindow == aWindow);
}
}
@ -5868,187 +5860,185 @@ function getPluginInfo(pluginElement)
return {mimetype: tagMimetype, pluginsPage: pluginsPage};
}
function missingPluginInstaller(){
}
var gMissingPluginInstaller = {
missingPluginInstaller.prototype.installSinglePlugin = function(aEvent){
var missingPluginsArray = {};
installSinglePlugin: function (aEvent) {
var missingPluginsArray = {};
var pluginInfo = getPluginInfo(aEvent.target);
missingPluginsArray[pluginInfo.mimetype] = pluginInfo;
var pluginInfo = getPluginInfo(aEvent.target);
missingPluginsArray[pluginInfo.mimetype] = pluginInfo;
if (missingPluginsArray) {
window.openDialog("chrome://mozapps/content/plugins/pluginInstallerWizard.xul",
"PFSWindow", "chrome,centerscreen,resizable=yes",
{plugins: missingPluginsArray, browser: gBrowser.selectedBrowser});
}
aEvent.stopPropagation();
}
missingPluginInstaller.prototype.managePlugins = function(aEvent){
BrowserOpenAddonsMgr("plugins");
aEvent.stopPropagation();
}
missingPluginInstaller.prototype.newMissingPlugin = function(aEvent){
// Since we are expecting also untrusted events, make sure
// that the target is a plugin
if (!(aEvent.target instanceof Components.interfaces.nsIObjectLoadingContent))
return;
// For broken non-object plugin tags, register a click handler so
// that the user can click the plugin replacement to get the new
// plugin. Object tags can, and often do, deal with that themselves,
// so don't stomp on the page developers toes.
if (aEvent.type != "PluginBlocklisted" &&
aEvent.type != "PluginOutdated" &&
!(aEvent.target instanceof HTMLObjectElement)) {
aEvent.target.addEventListener("click",
gMissingPluginInstaller.installSinglePlugin,
true);
}
let hideBarPrefName = aEvent.type == "PluginOutdated" ?
"plugins.hide_infobar_for_outdated_plugin" :
"plugins.hide_infobar_for_missing_plugin";
if (gPrefService.getBoolPref(hideBarPrefName))
return;
var browser = gBrowser.getBrowserForDocument(aEvent.target.ownerDocument
.defaultView.top.document);
if (!browser.missingPlugins)
browser.missingPlugins = {};
var pluginInfo = getPluginInfo(aEvent.target);
browser.missingPlugins[pluginInfo.mimetype] = pluginInfo;
var notificationBox = gBrowser.getNotificationBox(browser);
// Should only display one of these warnings per page.
// In order of priority, they are: outdated > missing > blocklisted
// If there is already an outdated plugin notification then do nothing
if (notificationBox.getNotificationWithValue("outdated-plugins"))
return;
var blockedNotification = notificationBox.getNotificationWithValue("blocked-plugins");
var missingNotification = notificationBox.getNotificationWithValue("missing-plugins");
var priority = notificationBox.PRIORITY_WARNING_MEDIUM;
function showBlocklistInfo() {
var url = formatURL("extensions.blocklist.detailsURL", true);
gBrowser.loadOneTab(url, {inBackground: false});
return true;
}
function showOutdatedPluginsInfo() {
var url = formatURL("plugins.update.url", true);
gBrowser.loadOneTab(url, {inBackground: false});
return true;
}
function showPluginsMissing() {
// get the urls of missing plugins
var missingPluginsArray = gBrowser.selectedBrowser.missingPlugins;
if (missingPluginsArray) {
window.openDialog("chrome://mozapps/content/plugins/pluginInstallerWizard.xul",
"PFSWindow", "chrome,centerscreen,resizable=yes",
{plugins: missingPluginsArray, browser: gBrowser.selectedBrowser});
openDialog("chrome://mozapps/content/plugins/pluginInstallerWizard.xul",
"PFSWindow", "chrome,centerscreen,resizable=yes",
{plugins: missingPluginsArray, browser: gBrowser.selectedBrowser});
}
}
if (aEvent.type == "PluginBlocklisted") {
if (blockedNotification || missingNotification)
aEvent.stopPropagation();
},
managePlugins: function (aEvent) {
BrowserOpenAddonsMgr("plugins");
aEvent.stopPropagation();
},
newMissingPlugin: function (aEvent) {
// Since we are expecting also untrusted events, make sure
// that the target is a plugin
if (!(aEvent.target instanceof Ci.nsIObjectLoadingContent))
return;
let iconURL = "chrome://mozapps/skin/plugins/pluginBlocked-16.png";
let messageString = gNavigatorBundle.getString("blockedpluginsMessage.title");
let buttons = [{
label: gNavigatorBundle.getString("blockedpluginsMessage.infoButton.label"),
accessKey: gNavigatorBundle.getString("blockedpluginsMessage.infoButton.accesskey"),
popup: null,
callback: showBlocklistInfo
}, {
label: gNavigatorBundle.getString("blockedpluginsMessage.searchButton.label"),
accessKey: gNavigatorBundle.getString("blockedpluginsMessage.searchButton.accesskey"),
popup: null,
callback: showOutdatedPluginsInfo
}];
// For broken non-object plugin tags, register a click handler so
// that the user can click the plugin replacement to get the new
// plugin. Object tags can, and often do, deal with that themselves,
// so don't stomp on the page developers toes.
notificationBox.appendNotification(messageString, "blocked-plugins",
iconURL, priority, buttons);
}
else if (aEvent.type == "PluginOutdated") {
// Cancel any notification about blocklisting/missing plugins
if (blockedNotification)
blockedNotification.close();
if (missingNotification)
missingNotification.close();
if (aEvent.type != "PluginBlocklisted" &&
aEvent.type != "PluginOutdated" &&
!(aEvent.target instanceof HTMLObjectElement)) {
aEvent.target.addEventListener("click",
gMissingPluginInstaller.installSinglePlugin,
true);
}
let iconURL = "chrome://mozapps/skin/plugins/pluginOutdated-16.png";
let messageString = gNavigatorBundle.getString("outdatedpluginsMessage.title");
let buttons = [{
label: gNavigatorBundle.getString("outdatedpluginsMessage.updateButton.label"),
accessKey: gNavigatorBundle.getString("outdatedpluginsMessage.updateButton.accesskey"),
popup: null,
callback: showOutdatedPluginsInfo
}];
notificationBox.appendNotification(messageString, "outdated-plugins",
iconURL, priority, buttons);
}
else if (aEvent.type == "PluginNotFound") {
if (missingNotification)
let hideBarPrefName = aEvent.type == "PluginOutdated" ?
"plugins.hide_infobar_for_outdated_plugin" :
"plugins.hide_infobar_for_missing_plugin";
if (gPrefService.getBoolPref(hideBarPrefName))
return;
// Cancel any notification about blocklisting plugins
if (blockedNotification)
blockedNotification.close();
var browser = gBrowser.getBrowserForDocument(aEvent.target.ownerDocument
.defaultView.top.document);
if (!browser.missingPlugins)
browser.missingPlugins = {};
let iconURL = "chrome://mozapps/skin/plugins/pluginGeneric-16.png";
let messageString = gNavigatorBundle.getString("missingpluginsMessage.title");
let buttons = [{
label: gNavigatorBundle.getString("missingpluginsMessage.button.label"),
accessKey: gNavigatorBundle.getString("missingpluginsMessage.button.accesskey"),
popup: null,
callback: showPluginsMissing
}];
notificationBox.appendNotification(messageString, "missing-plugins",
iconURL, priority, buttons);
var pluginInfo = getPluginInfo(aEvent.target);
browser.missingPlugins[pluginInfo.mimetype] = pluginInfo;
var notificationBox = gBrowser.getNotificationBox(browser);
// Should only display one of these warnings per page.
// In order of priority, they are: outdated > missing > blocklisted
// If there is already an outdated plugin notification then do nothing
if (notificationBox.getNotificationWithValue("outdated-plugins"))
return;
var blockedNotification = notificationBox.getNotificationWithValue("blocked-plugins");
var missingNotification = notificationBox.getNotificationWithValue("missing-plugins");
var priority = notificationBox.PRIORITY_WARNING_MEDIUM;
function showBlocklistInfo() {
var url = formatURL("extensions.blocklist.detailsURL", true);
gBrowser.loadOneTab(url, {inBackground: false});
return true;
}
function showOutdatedPluginsInfo() {
var url = formatURL("plugins.update.url", true);
gBrowser.loadOneTab(url, {inBackground: false});
return true;
}
function showPluginsMissing() {
// get the urls of missing plugins
var missingPluginsArray = gBrowser.selectedBrowser.missingPlugins;
if (missingPluginsArray) {
openDialog("chrome://mozapps/content/plugins/pluginInstallerWizard.xul",
"PFSWindow", "chrome,centerscreen,resizable=yes",
{plugins: missingPluginsArray, browser: gBrowser.selectedBrowser});
}
}
if (aEvent.type == "PluginBlocklisted") {
if (blockedNotification || missingNotification)
return;
let iconURL = "chrome://mozapps/skin/plugins/pluginBlocked-16.png";
let messageString = gNavigatorBundle.getString("blockedpluginsMessage.title");
let buttons = [{
label: gNavigatorBundle.getString("blockedpluginsMessage.infoButton.label"),
accessKey: gNavigatorBundle.getString("blockedpluginsMessage.infoButton.accesskey"),
popup: null,
callback: showBlocklistInfo
}, {
label: gNavigatorBundle.getString("blockedpluginsMessage.searchButton.label"),
accessKey: gNavigatorBundle.getString("blockedpluginsMessage.searchButton.accesskey"),
popup: null,
callback: showOutdatedPluginsInfo
}];
notificationBox.appendNotification(messageString, "blocked-plugins",
iconURL, priority, buttons);
}
else if (aEvent.type == "PluginOutdated") {
// Cancel any notification about blocklisting/missing plugins
if (blockedNotification)
blockedNotification.close();
if (missingNotification)
missingNotification.close();
let iconURL = "chrome://mozapps/skin/plugins/pluginOutdated-16.png";
let messageString = gNavigatorBundle.getString("outdatedpluginsMessage.title");
let buttons = [{
label: gNavigatorBundle.getString("outdatedpluginsMessage.updateButton.label"),
accessKey: gNavigatorBundle.getString("outdatedpluginsMessage.updateButton.accesskey"),
popup: null,
callback: showOutdatedPluginsInfo
}];
notificationBox.appendNotification(messageString, "outdated-plugins",
iconURL, priority, buttons);
}
else if (aEvent.type == "PluginNotFound") {
if (missingNotification)
return;
// Cancel any notification about blocklisting plugins
if (blockedNotification)
blockedNotification.close();
let iconURL = "chrome://mozapps/skin/plugins/pluginGeneric-16.png";
let messageString = gNavigatorBundle.getString("missingpluginsMessage.title");
let buttons = [{
label: gNavigatorBundle.getString("missingpluginsMessage.button.label"),
accessKey: gNavigatorBundle.getString("missingpluginsMessage.button.accesskey"),
popup: null,
callback: showPluginsMissing
}];
notificationBox.appendNotification(messageString, "missing-plugins",
iconURL, priority, buttons);
}
},
newDisabledPlugin: function (aEvent) {
// Since we are expecting also untrusted events, make sure
// that the target is a plugin
if (!(aEvent.target instanceof Ci.nsIObjectLoadingContent))
return;
aEvent.target.addEventListener("click",
gMissingPluginInstaller.managePlugins,
true);
},
refreshBrowser: function (aEvent) {
// browser elements are anonymous so we can't just use target.
var browser = aEvent.originalTarget;
var notificationBox = gBrowser.getNotificationBox(browser);
var notification = notificationBox.getNotificationWithValue("missing-plugins");
// clear the plugin list, now that at least one plugin has been installed
browser.missingPlugins = null;
if (notification) {
// reset UI
notificationBox.removeNotification(notification);
}
// reload the browser to make the new plugin show.
browser.reload();
}
}
missingPluginInstaller.prototype.newDisabledPlugin = function(aEvent){
// Since we are expecting also untrusted events, make sure
// that the target is a plugin
if (!(aEvent.target instanceof Components.interfaces.nsIObjectLoadingContent))
return;
aEvent.target.addEventListener("click",
gMissingPluginInstaller.managePlugins,
true);
}
missingPluginInstaller.prototype.refreshBrowser = function(aEvent) {
// browser elements are anonymous so we can't just use target.
var browser = aEvent.originalTarget;
var notificationBox = gBrowser.getNotificationBox(browser);
var notification = notificationBox.getNotificationWithValue("missing-plugins");
// clear the plugin list, now that at least one plugin has been installed
browser.missingPlugins = null;
if (notification) {
// reset UI
notificationBox.removeNotification(notification);
}
// reload the browser to make the new plugin show.
browser.reload();
}
var gMissingPluginInstaller = new missingPluginInstaller();
};
function convertFromUnicode(charset, str)
{
@ -6298,20 +6288,12 @@ function formatURL(aFormat, aIsPref) {
* This also takes care of updating the command enabled-state when tabs are
* created or removed.
*/
function BookmarkAllTabsHandler() {
this._command = document.getElementById("Browser:BookmarkAllTabs");
gBrowser.addEventListener("TabOpen", this, true);
gBrowser.addEventListener("TabClose", this, true);
this._updateCommandState();
}
BookmarkAllTabsHandler.prototype = {
QueryInterface: function BATH_QueryInterface(aIID) {
if (aIID.equals(Ci.nsIDOMEventListener) ||
aIID.equals(Ci.nsISupports))
return this;
throw Cr.NS_NOINTERFACE;
var gBookmarkAllTabsHandler = {
init: function () {
this._command = document.getElementById("Browser:BookmarkAllTabs");
gBrowser.tabContainer.addEventListener("TabOpen", this, true);
gBrowser.tabContainer.addEventListener("TabClose", this, true);
this._updateCommandState();
},
_updateCommandState: function BATH__updateCommandState(aTabClose) {
@ -7079,7 +7061,7 @@ var LightWeightThemeWebInstaller = {
handleEvent: function (event) {
switch (event.type) {
case "InstallBrowserTheme":
this._install(event);
this._installRequest(event);
break;
case "PreviewBrowserTheme":
this._preview(event);
@ -7097,14 +7079,14 @@ var LightWeightThemeWebInstaller = {
return this._manager = temp.LightweightThemeManager;
},
_install: function (event) {
_installRequest: function (event) {
var node = event.target;
var data = this._getThemeFromNode(node);
if (!data)
return;
if (this._isAllowed(node)) {
this._manager.currentTheme = data;
this._install(data);
return;
}
@ -7119,15 +7101,66 @@ var LightWeightThemeWebInstaller = {
label: allowButtonText,
accessKey: allowButtonAccesskey,
callback: function () {
LightWeightThemeWebInstaller._manager.currentTheme = data;
LightWeightThemeWebInstaller._install(data);
}
}];
this._removePreviousNotifications();
var notificationBox = gBrowser.getNotificationBox();
notificationBox.appendNotification(message, "lwtheme-install-request", "",
notificationBox.PRIORITY_INFO_MEDIUM,
buttons);
},
_install: function (newTheme) {
var previousTheme = this._manager.currentTheme;
this._manager.currentTheme = newTheme;
if (this._manager.currentTheme &&
this._manager.currentTheme.id == newTheme.id)
this._postInstallNotification(newTheme, previousTheme);
},
_postInstallNotification: function (newTheme, previousTheme) {
function text(id) {
return gNavigatorBundle.getString("lwthemePostInstallNotification." + id);
}
var buttons = [{
label: text("undoButton"),
accessKey: text("undoButton.accesskey"),
callback: function () {
LightWeightThemeWebInstaller._manager.forgetUsedTheme(newTheme.id);
LightWeightThemeWebInstaller._manager.currentTheme = previousTheme;
}
}, {
label: text("manageButton"),
accessKey: text("manageButton.accesskey"),
callback: function () {
BrowserOpenAddonsMgr("themes");
}
}];
this._removePreviousNotifications();
var notificationBox = gBrowser.getNotificationBox();
notificationBox.appendNotification(text("message"),
"lwtheme-install-notification", "",
notificationBox.PRIORITY_INFO_MEDIUM,
buttons);
},
_removePreviousNotifications: function () {
var box = gBrowser.getNotificationBox();
["lwtheme-install-request",
"lwtheme-install-notification"].forEach(function (value) {
var notification = box.getNotificationWithValue(value);
if (notification)
box.removeNotification(notification);
});
},
_preview: function (event) {
if (!this._isAllowed(event.target))
return;

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

@ -577,7 +577,6 @@
<tabbrowser id="content" disablehistory="true"
flex="1" contenttooltip="aHTMLTooltip"
contentcontextmenu="contentAreaContextMenu"
onnewtab="BrowserOpenTab();"
autocompletepopup="PopupAutoComplete"
ondrop="contentAreaDNDObserver.onDrop(event)"
onclick="return contentAreaClick(event, false);"/>

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

@ -32,6 +32,7 @@
- Mark Pilgrim <pilgrim@gmail.com>
- Dão Gottwald <dao@mozilla.com>
- Paul OShannessy <paul@oshannessy.com>
- Rob Arnold <tellrob@gmail.com>
-
- Alternatively, the contents of this file may be used under the terms of
- either the GNU General Public License Version 2 or later (the "GPL"), or
@ -82,7 +83,7 @@
<xul:tooltip onpopupshowing="return this.parentNode.parentNode.parentNode.createTooltip(event);"/>
<xul:menupopup anonid="tabContextMenu" onpopupshowing="this.parentNode.parentNode.parentNode.updatePopupMenu(this);">
<xul:menuitem id="context_newTab" label="&newTab.label;" accesskey="&newTab.accesskey;"
xbl:inherits="oncommand=onnewtab"/>
command="cmd_newNavigatorTab"/>
<xul:menuseparator/>
<xul:menuitem id="context_reloadTab" label="&reloadTab.label;" accesskey="&reloadTab.accesskey;"
oncommand="var tabbrowser = this.parentNode.parentNode.parentNode.parentNode;
@ -126,7 +127,6 @@
anonid="tabcontainer"
setfocus="false"
onclick="this.parentNode.parentNode.parentNode.onTabClick(event);"
xbl:inherits="onnewtab"
ondblclick="this.parentNode.parentNode.parentNode.onTabBarDblClick(event);"
onclosetab="var node = this.parentNode;
while (node.localName != 'tabbrowser')
@ -236,6 +236,29 @@
null
</field>
<field name="_previewMode">
false
</field>
<method name="previewTab">
<parameter name="aTab"/>
<parameter name="aCallback"/>
<body>
<![CDATA[
let currentTab = this.selectedTab;
try {
// Suppress focus, ownership and selected tab changes
this._previewMode = true;
this.selectedTab = aTab;
aCallback();
} finally {
this.selectedTab = currentTab;
this._previewMode = false;
}
]]>
</body>
</method>
<method name="getBrowserAtIndex">
<parameter name="aIndex"/>
<body>
@ -843,7 +866,8 @@
if (this.mCurrentBrowser == newBrowser && !aForceUpdate)
return;
if (this.mCurrentTab != this.selectedTab)
// Preview mode should not reset the owner
if (!this._previewMode && this.mCurrentTab != this.selectedTab)
this.mCurrentTab.owner = null;
this._lastRelatedTab = null;
@ -897,7 +921,9 @@
}
}
this._fastFind.setDocShell(this.mCurrentBrowser.docShell);
// Don't switch the fast find - this tab switch is temporary
if (!this._previewMode)
this._fastFind.setDocShell(this.mCurrentBrowser.docShell);
// Update the window title.
this.updateTitlebar();
@ -935,18 +961,23 @@
}
}
// We've selected the new tab, so go ahead and notify listeners.
var event = document.createEvent("Events");
event.initEvent("TabSelect", true, false);
this.mCurrentTab.dispatchEvent(event);
// TabSelect events are suppressed during preview mode to avoid confusing extensions and other bits of code
// that might rely upon the other changes suppressed.
// Focus is suppressed in the event that the main browser window is minimized - focusing a tab would restore the window
if (!this._previewMode) {
// We've selected the new tab, so go ahead and notify listeners.
var event = document.createEvent("Events");
event.initEvent("TabSelect", true, false);
this.mCurrentTab.dispatchEvent(event);
// change focus to the new tab if nothing is focused, the old tab
// is focused or there is something in the new tab to focus. One
// specific case where focus is not changed is when the new tab
// has no focused element and a chrome element is focused.
if (!focusedChromeElement || focusedChromeElement == oldBrowser ||
fm.getFocusedElementForWindow(window.content, true, {}))
fm.setFocus(newBrowser, fm.FLAG_NOSCROLL);
// change focus to the new tab if nothing is focused, the old tab
// is focused or there is something in the new tab to focus. One
// specific case where focus is not changed is when the new tab
// has no focused element and a chrome element is focused.
if ((!focusedChromeElement || focusedChromeElement == oldBrowser ||
fm.getFocusedElementForWindow(window.content, true, {})))
fm.setFocus(newBrowser, fm.FLAG_NOSCROLL);
}
]]>
</body>
</method>
@ -1314,30 +1345,6 @@
if (t.previousSibling.selected)
t.setAttribute("afterselected", true);
if (!blank) {
// Stop the existing about:blank load. Otherwise, if aURI
// doesn't stop in-progress loads on its own, we'll get into
// trouble with multiple parallel loads running at once.
b.stop();
// pretend the user typed this so it'll be available till
// the document successfully loads
b.userTypedValue = aURI;
if (aPostData === undefined)
aPostData = null;
const nsIWebNavigation = Components.interfaces.nsIWebNavigation;
var flags = nsIWebNavigation.LOAD_FLAGS_NONE;
if (aAllowThirdPartyFixup) {
flags = nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
}
try {
b.loadURIWithFlags(aURI, flags, aReferrerURI, aCharset, aPostData);
}
catch (ex) {
}
}
this.tabContainer.adjustTabstrip();
// Do this asynchronically, as we don't know yet if the tab
@ -1361,6 +1368,25 @@
evt.initEvent("TabOpen", true, false);
t.dispatchEvent(evt);
if (!blank) {
// Stop the existing about:blank load. Otherwise, if aURI
// doesn't stop in-progress loads on its own, we'll get into
// trouble with multiple parallel loads running at once.
b.stop();
// pretend the user typed this so it'll be available till
// the document successfully loads
b.userTypedValue = aURI;
let flags = aAllowThirdPartyFixup ?
Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP :
Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
try {
b.loadURIWithFlags(aURI, flags, aReferrerURI, aCharset, aPostData);
}
catch (ex) { }
}
// Check if we're opening a tab related to the current tab and
// move it to after the current tab.
// aReferrerURI is null or undefined if the tab is opened from
@ -1769,12 +1795,8 @@
<![CDATA[
// See hack note in the tabbrowser-close-button binding
if (!this._blockDblClick && aEvent.button == 0 &&
aEvent.originalTarget.localName == "box") {
// xxx this needs to check that we're in the empty area of the tabstrip
var e = document.createEvent("Events");
e.initEvent("NewTab", true, true);
this.dispatchEvent(e);
}
aEvent.originalTarget.localName == "box")
BrowserOpenTab();
]]>
</body>
</method>

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

@ -99,6 +99,7 @@ _BROWSER_FILES = \
browser_bug481560.js \
browser_bug477014.js \
browser_bug495058.js \
browser_bug521216.js \
browser_discovery.js \
browser_tabfocus.js \
discovery.html \

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

@ -0,0 +1,49 @@
var expected = ["TabOpen", "onLinkIconAvailable", "onLocationChange", "onStateChange"];
var actual = [];
var tabIndex = -1;
__defineGetter__("tab", function () gBrowser.tabContainer.childNodes[tabIndex]);
function test() {
waitForExplicitFinish();
tabIndex = gBrowser.tabContainer.childElementCount;
gBrowser.addTabsProgressListener(progressListener);
gBrowser.tabContainer.addEventListener("TabOpen", TabOpen, false);
gBrowser.addTab("http://example.org/browser/browser/base/content/test/dummy_page.html");
}
function record(aName) {
info("got " + aName);
if (actual.indexOf(aName) == -1)
actual.push(aName);
if (actual.length == expected.length) {
is(actual.toString(), expected.toString(),
"got events and progress notifications in expected order");
gBrowser.removeTab(tab);
gBrowser.removeTabsProgressListener(progressListener);
gBrowser.tabContainer.removeEventListener("TabOpen", TabOpen, false);
finish();
}
}
function TabOpen(aEvent) {
if (aEvent.target == tab)
record(arguments.callee.name);
}
var progressListener = {
onLocationChange: function onLocationChange(aBrowser) {
if (aBrowser == tab.linkedBrowser)
record(arguments.callee.name);
},
onProgressChange: function () {},
onSecurityChange: function () {},
onStateChange: function onStateChange(aBrowser) {
if (aBrowser == tab.linkedBrowser)
record(arguments.callee.name);
},
onStatusChange: function () {},
onLinkIconAvailable: function onLinkIconAvailable(aBrowser) {
if (aBrowser == tab.linkedBrowser)
record(arguments.callee.name);
}
};

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

@ -76,6 +76,12 @@ ifndef WINCE
DIRS += migration
endif
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
ifndef WINCE
DIRS += wintaskbar
endif
endif
ifdef MOZ_SAFE_BROWSING
DIRS += safebrowsing
endif

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

@ -505,7 +505,7 @@ var nsBrowserContentHandler = {
#endif
},
helpInfo : " -browser Open a browser window.\n",
helpInfo : " -browser Open a browser window.\n",
/* nsIBrowserHandler */

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

@ -354,6 +354,19 @@ BrowserGlue.prototype = {
// been warned about them yet, open the plugins update page.
if (this._prefs.getBoolPref(PREF_PLUGINS_NOTIFYUSER))
this._showPluginUpdatePage();
#ifdef XP_WIN
#ifndef WINCE
// For windows seven, initialize the jump list module.
const WINTASKBAR_CONTRACTID = "@mozilla.org/windows-taskbar;1";
if (WINTASKBAR_CONTRACTID in Cc &&
Cc[WINTASKBAR_CONTRACTID].getService(Ci.nsIWinTaskbar).available) {
let temp = {};
Cu.import("resource://gre/modules/WindowsJumpLists.jsm", temp);
temp.WinTaskbarJumpList.startup();
}
#endif
#endif
},
_onQuitRequest: function(aCancelQuit, aQuitType)
@ -645,7 +658,7 @@ BrowserGlue.prototype = {
var bookmarksBackupFile = PlacesUtils.backups.getMostRecent("json");
if (bookmarksBackupFile) {
// restore from JSON backup
PlacesUtils.backups.restoreBookmarksFromJSONFile(bookmarksBackupFile);
PlacesUtils.restoreBookmarksFromJSONFile(bookmarksBackupFile);
importBookmarks = false;
}
else {

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

@ -1,15 +1,8 @@
%ifdef PLACES_QUERY_BUILDER
.history-calendar {
-moz-binding: url("chrome://browser/content/places/places.xml#calendar");
}
button.commandButton {
-moz-binding: url("chrome://browser/content/places/places.xml#command-button");
}
.filterList {
-moz-binding: url("chrome://browser/content/places/places.xml#filter-button");
}
%endif
#contentTitle {
width: 0px;

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

@ -511,7 +511,7 @@ var PlacesOrganizer = {
return;
try {
PlacesUtils.backups.restoreBookmarksFromJSONFile(aFile);
PlacesUtils.restoreBookmarksFromJSONFile(aFile);
}
catch(ex) {
this._showErrorAlert(PlacesUIUtils.getString("bookmarksRestoreParseError"));

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

@ -3,38 +3,7 @@
<bindings id="placesBindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xbl="http://www.mozilla.org/xbl"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<binding id="command-button" extends="chrome://global/content/bindings/button.xml#button">
<implementation>
<method name="updateActiveView">
<body><![CDATA[
if (this.hasAttribute("view"))
PlacesController.activeView = document.getElementById(this.getAttribute("view"));
]]></body>
</method>
</implementation>
<handlers>
<handler event="click" button="0" action="this.updateActiveView();"/>
<handler event="keypress" keycode="VK_SPACE" action="this.updateActiveView();"/>
</handlers>
</binding>
<binding id="filter-button" extends="chrome://global/content/bindings/button.xml#menu">
<content>
<xul:stack flex="1" class="box-inherit button-box">
<xul:image class="button-icon" xbl:inherits="src=image"/>
<xul:dropmarker class="button-menu-dropmarker" xbl:inherits="open,disabled"/>
</xul:stack>
<children includes="menupopup"/>
</content>
<handlers>
<handler event="command"><![CDATA[
PlacesSearchBox.filterCollection = event.target.getAttribute("value");
]]></handler>
</handlers>
</binding>
#ifdef PLACES_QUERY_BUILDER
<binding id="calendar">

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

@ -1311,7 +1311,7 @@ var PlacesUIUtils = {
if (this.__lookupGetter__("leftPaneFolderId")) {
try {
queryName = PlacesUtils.annotations.
getItemAnnotation(itemId, ORGANIZER_QUERY_ANNO);
getItemAnnotation(aItemId, ORGANIZER_QUERY_ANNO);
}
catch (ex) {
// doesn't have the annotation

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

@ -6,7 +6,7 @@ browser.jar:
* content/browser/places/places.js (content/places.js)
* content/browser/places/places.xml (content/places.xml)
content/browser/places/places.css (content/places.css)
content/browser/places/organizer.css (content/organizer.css)
* content/browser/places/organizer.css (content/organizer.css)
* content/browser/places/bookmarkProperties.xul (content/bookmarkProperties.xul)
* content/browser/places/bookmarkProperties.js (content/bookmarkProperties.js)
* content/browser/places/placesOverlay.xul (content/placesOverlay.xul)

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

@ -48,6 +48,7 @@ _CHROME_TEST_FILES = \
test_bug485100-change-case-loses-tag.xul \
test_bug427633_no_newfolder_if_noip.xul \
test_multiple_left_pane.xul \
test_bug510634.xul \
$(NULL)
libs:: $(_CHROME_TEST_FILES)

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

@ -0,0 +1,135 @@
<?xml version="1.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 the Places test code.
-
- The Initial Developer of the Original Code is Mozilla Foundation.
- Portions created by the Initial Developer are Copyright (C) 2009
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
- Asaf Romano (Original Author)
-
- Alternatively, the contents of this file may be used under the terms of
- either the GNU General Public License Version 2 or later (the "GPL"), or
- the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- in which case the provisions of the GPL or the LGPL are applicable instead
- of those above. If you wish to allow use of your version of this file only
- under the terms of either the GPL or the LGPL, and not to allow others to
- use your version of this file under the terms of the MPL, indicate your
- decision by deleting the provisions above and replace them with the notice
- and other provisions required by the GPL or the LGPL. If you do not delete
- the provisions above, a recipient may use your version of this file under
- the terms of any one of the MPL, the GPL or the LGPL.
-
- ***** END LICENSE BLOCK ***** -->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/places/places.css"?>
<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
<?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="510634: Wrong icons on bookmarks sidebar"
onload="runTest();">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<body xmlns="http://www.w3.org/1999/xhtml" />
<tree id="tree"
type="places"
flex="1">
<treecols>
<treecol label="Title" id="title" anonid="title" primary="true" ordinal="1" flex="1"/>
</treecols>
<treechildren flex="1"/>
</tree>
<script type="application/javascript">
<![CDATA[
/**
* Bug 510634 - Wrong icons on bookmarks sidebar
* https://bugzilla.mozilla.org/show_bug.cgi?id=510634
*
* Ensures that properties for special queries are set on their tree nodes,
* even if PlacesUIUtils.leftPaneFolderId was not initialized.
*/
SimpleTest.waitForExplicitFinish();
function createSupportsArray() {
return Cc["@mozilla.org/supports-array;1"].
createInstance(Ci.nsISupportsArray);
}
// converts nsISupportsArray of atoms to a simple JS-strings array
function convertPropertiesToJSArray(aSupportsArray) {
var results = [];
var count = aSupportsArray.Count();
for (var i = 0; i < count; i++)
results.push(aSupportsArray.QueryElementAt(i, Ci.nsIAtom).toString());
return results;
}
function runTest() {
// We need to cache and restore this getter in order to simulate
// Bug 510634
let cachedLeftPaneFolderIdGetter =
PlacesUIUtils.__lookupGetter__("leftPaneFolderId");
let leftPaneFolderId = PlacesUIUtils.leftPaneFolderId;
// restore the getter
PlacesUIUtils.__defineGetter__("leftPaneFolderId", cachedLeftPaneFolderIdGetter);
// Setup the places tree contents.
let tree = document.getElementById("tree");
tree.place = "place:queryType=1&folder=" + leftPaneFolderId;
// Open All Bookmarks
asContainer(tree.view.nodeForTreeIndex(2)).containerOpen = true;
// The query-property is set on the title column for each row.
let titleColumn = tree.treeBoxObject.columns.getColumnAt(0);
["History", "Tags", "AllBookmarks", "BookmarksToolbar",
"BookmarksMenu", "UnfiledBookmarks"].forEach(
function(aQueryName, aRow) {
let rowProperties = createSupportsArray();
tree.view.getCellProperties(aRow, titleColumn, rowProperties);
rowProperties = convertPropertiesToJSArray(rowProperties);
ok(rowProperties.indexOf("OrganizerQuery_" + aQueryName) != -1,
"OrganizerQuery_" + aQueryName + " is set");
}
);
// Close the root node
tree.getResult().root.containerOpen = false;
SimpleTest.finish();
}
]]>
</script>
</window>

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

@ -103,7 +103,7 @@ function run_test() {
} catch(ex) { do_throw("couldn't export to file: " + ex); }
LOG("exported json");
try {
PlacesUtils.backups.restoreBookmarksFromJSONFile(jsonFile);
PlacesUtils.restoreBookmarksFromJSONFile(jsonFile);
} catch(ex) { do_throw("couldn't import the exported file: " + ex); }
LOG("imported json");
validate();

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

@ -83,7 +83,7 @@ var tests = [
PlacesUtils.backups.saveBookmarksToJSONFile(this.file);
remove_all_bookmarks();
try {
PlacesUtils.backups.restoreBookmarksFromJSONFile(this.file);
PlacesUtils.restoreBookmarksFromJSONFile(this.file);
}
catch (e) {
do_throw(" Restore should not have failed");
@ -100,7 +100,7 @@ var tests = [
run: function () {
this.file = createFile("bookmarks-test_restoreNotification.json");
try {
PlacesUtils.backups.restoreBookmarksFromJSONFile(this.file);
PlacesUtils.restoreBookmarksFromJSONFile(this.file);
}
catch (e) {
do_throw(" Restore should not have failed");
@ -118,7 +118,7 @@ var tests = [
this.file = dirSvc.get("ProfD", Ci.nsILocalFile);
this.file.append("this file doesn't exist because nobody created it");
try {
PlacesUtils.backups.restoreBookmarksFromJSONFile(this.file);
PlacesUtils.restoreBookmarksFromJSONFile(this.file);
do_throw(" Restore should have failed");
}
catch (e) {}

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

@ -58,7 +58,7 @@ function run_test() {
do_check_false(db.exists());
}
// Create a corrupt database.
corruptDB = gTestDir.clone();
let corruptDB = gTestDir.clone();
corruptDB.append("corruptDB.sqlite");
corruptDB.copyTo(gProfD, "places.sqlite");
do_check_true(db.exists());

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

@ -83,7 +83,7 @@ function run_test() {
do_check_false(db.exists());
}
// Create a corrupt database.
corruptDB = gTestDir.clone();
var corruptDB = gTestDir.clone();
corruptDB.append("corruptDB.sqlite");
corruptDB.copyTo(gProfD, "places.sqlite");
do_check_true(db.exists());

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

@ -83,7 +83,7 @@ function run_test() {
do_check_false(db.exists());
}
// Create a corrupt database.
corruptDB = gTestDir.clone();
var corruptDB = gTestDir.clone();
corruptDB.append("corruptDB.sqlite");
corruptDB.copyTo(gProfD, "places.sqlite");
do_check_true(db.exists());

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

@ -73,7 +73,7 @@ function run_test() {
// A migrator would run before nsBrowserGlue, so we mimic that behavior
// adding a bookmark.
bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
let bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
getService(Ci.nsINavBookmarksService);
bs.insertBookmark(bs.bookmarksMenuFolder, uri("http://mozilla.org/"),
bs.DEFAULT_INDEX, "migrated");

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

@ -789,7 +789,7 @@ function run_test() {
folderWChildItemTxn.undoTransaction();
do_check_false(bmsvc.isBookmarked(uri("http://www.childItem.com")));
folderWChildItemTxn.redoTransaction();
newchildItemId = (bmsvc.getBookmarkIdsForURI(uri("http://www.childItem.com"), {}))[0];
var newchildItemId = (bmsvc.getBookmarkIdsForURI(uri("http://www.childItem.com"), {}))[0];
do_check_eq(observer._itemAddedIndex, 0);
do_check_eq(observer._itemAddedId, newchildItemId);
do_check_true(bmsvc.isBookmarked(uri("http://www.childItem.com")));

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

@ -364,7 +364,7 @@ PrivateBrowsingService.prototype = {
},
get helpInfo PBS_get_helpInfo() {
return " -private Enable private browsing mode.\n";
return " -private Enable private browsing mode.\n";
},
// nsIPrivateBrowsingService

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

@ -80,35 +80,44 @@ function test() {
let tab = gBrowser.selectedTab = gBrowser.addTab();
let browser = gBrowser.selectedBrowser;
browser.addEventListener("load", function() {
browser.removeEventListener("load", arguments.callee, true);
// ensure that the test is run after the titlebar has been updated
let timer = null;
let _updateTitlebar = gBrowser.updateTitlebar;
gBrowser.updateTitlebar = function() {
if (timer) {
timer.cancel();
timer = null;
}
timer = Cc["@mozilla.org/timer;1"].
createInstance(Ci.nsITimer);
timer.initWithCallback(function () {
_updateTitlebar.apply(gBrowser, arguments);
gBrowser.updateTitlebar = _updateTitlebar;
is(document.title, expected_title, "The window title for " + url +
" is correct (" + (insidePB ? "inside" : "outside") +
" private browsing mode)");
// ensure that the test is run after the page onload event
setTimeout(function() {
setTimeout(function() {
is(document.title, expected_title, "The window title for " + url +
" is correct (" + (insidePB ? "inside" : "outside") +
" private browsing mode)");
let win = gBrowser.replaceTabWithWindow(tab);
win.addEventListener("load", function() {
win.removeEventListener("load", arguments.callee, false);
let win = gBrowser.replaceTabWithWindow(tab);
win.addEventListener("load", function() {
win.removeEventListener("load", arguments.callee, false);
// ensure that the test is run after delayedStartup
let _delayedStartup = win.delayedStartup;
win.delayedStartup = function() {
_delayedStartup.apply(win, arguments);
win.delayedStartup = _delayedStartup;
// ensure that the test is run after delayedStartup
setTimeout(function() {
setTimeout(function() {
is(win.document.title, expected_title, "The window title for " + url +
" detahced tab is correct (" + (insidePB ? "inside" : "outside") +
" private browsing mode)");
win.close();
is(win.document.title, expected_title, "The window title for " + url +
" detached tab is correct (" + (insidePB ? "inside" : "outside") +
" private browsing mode)");
win.close();
setTimeout(funcNext, 0);
};
}, false);
}, 300, Ci.nsITimer.TYPE_ONE_SHOT);
};
funcNext();
}, 0);
}, 0);
}, false);
}, 0);
}, 0);
}, true);
browser.loadURI(url);
}

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

@ -47,7 +47,6 @@ include $(topsrcdir)/config/rules.mk
# browser_477657.js is disabled, because it's unreliable (bug 482975).
# browser_480148.js is disabled, because it breaks browser_420786.js (see bug 483382).
# tests for 459906, 463205, and 464620 disabled because they are broken.
_BROWSER_TEST_FILES = \
browser_248970_a.js \
@ -75,13 +74,23 @@ _BROWSER_TEST_FILES = \
browser_454908_sample.html \
browser_456342.js \
browser_456342_sample.xhtml \
browser_459906.js \
browser_459906_empty.html \
browser_459906_sample.html \
browser_461634.js \
browser_461743.js \
browser_461743_sample.html \
browser_463205.js \
browser_463205_helper.html \
browser_463205_sample.html \
browser_463206.js \
browser_463206_sample.html \
browser_464199.js \
browser_464620_a.js \
browser_464620_a.html \
browser_464620_b.js \
browser_464620_b.html \
browser_464620_xd.html \
browser_465215.js \
browser_465223.js \
browser_466937.js \

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

@ -58,54 +58,56 @@ function test() {
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no", testURL);
newWin.addEventListener("load", function(aEvent) {
newWin.removeEventListener("load", arguments.callee, false);
newWin.gBrowser.addEventListener("load", function(aEvent) {
newWin.gBrowser.removeEventListener("load", arguments.callee, true);
executeSoon(function() {
newWin.gBrowser.addTab();
executeSoon(function() {
// mark the window with some unique data to be restored later on
ss.setWindowValue(newWin, uniqueKey, uniqueValue);
let textbox = newWin.content.document.getElementById("textbox");
textbox.wrappedJSObject.value = uniqueText;
// mark the window with some unique data to be restored later on
ss.setWindowValue(newWin, uniqueKey, uniqueValue);
let textbox = newWin.content.document.getElementById("textbox");
textbox.wrappedJSObject.value = uniqueText;
newWin.close();
newWin.close();
is(ss.getClosedWindowCount(), closedWindowCount + 1,
"The closed window was added to Recently Closed Windows");
let data = JSON.parse(ss.getClosedWindowData())[0];
ok(data.title == testURL && data.toSource().indexOf(uniqueText) > -1,
"The closed window data was stored correctly");
is(ss.getClosedWindowCount(), closedWindowCount + 1,
"The closed window was added to Recently Closed Windows");
let data = JSON.parse(ss.getClosedWindowData())[0];
ok(data.title == testURL && data.toSource().indexOf(uniqueText) > -1,
"The closed window data was stored correctly");
// reopen the closed window and ensure its integrity
let newWin2 = ss.undoCloseWindow(0);
// reopen the closed window and ensure its integrity
let newWin2 = ss.undoCloseWindow(0);
ok(newWin2 instanceof ChromeWindow,
"undoCloseWindow actually returned a window");
is(ss.getClosedWindowCount(), closedWindowCount,
"The reopened window was removed from Recently Closed Windows");
ok(newWin2 instanceof ChromeWindow,
"undoCloseWindow actually returned a window");
is(ss.getClosedWindowCount(), closedWindowCount,
"The reopened window was removed from Recently Closed Windows");
newWin2.addEventListener("load", function(aEvent) {
newWin2.gBrowser.addEventListener("SSTabRestored", function(aEvent) {
newWin2.gBrowser.removeEventListener("SSTabRestored", arguments.callee, true);
newWin2.addEventListener("load", function(aEvent) {
newWin2.gBrowser.addEventListener("SSTabRestored", function(aEvent) {
newWin2.gBrowser.removeEventListener("SSTabRestored", arguments.callee, true);
is(newWin2.gBrowser.tabContainer.childNodes.length, 2,
"The window correctly restored 2 tabs");
is(newWin2.gBrowser.currentURI.spec, testURL,
"The window correctly restored the URL");
is(newWin2.gBrowser.tabContainer.childNodes.length, 2,
"The window correctly restored 2 tabs");
is(newWin2.gBrowser.currentURI.spec, testURL,
"The window correctly restored the URL");
let textbox = newWin2.content.document.getElementById("textbox");
is(textbox.wrappedJSObject.value, uniqueText,
"The window correctly restored the form");
is(ss.getWindowValue(newWin2, uniqueKey), uniqueValue,
"The window correctly restored the data associated with it");
let textbox = newWin2.content.document.getElementById("textbox");
is(textbox.wrappedJSObject.value, uniqueText,
"The window correctly restored the form");
is(ss.getWindowValue(newWin2, uniqueKey), uniqueValue,
"The window correctly restored the data associated with it");
// clean up
newWin2.close();
gPrefService.clearUserPref("browser.sessionstore.max_windows_undo");
executeSoon(callback);
}, true);
}, false);
// clean up
newWin2.close();
gPrefService.clearUserPref("browser.sessionstore.max_windows_undo");
executeSoon(callback);
}, true);
}, false);
});
});
}, true);
}, false);

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

@ -77,6 +77,7 @@ function test() {
ss.setBrowserState(blankState);
let closedWindowCount = ss.getClosedWindowCount();
is(closedWindowCount, 0, "Correctly set window count");
let testURL_A = "about:config";
let testURL_B = "about:mozilla";
@ -90,77 +91,81 @@ function test() {
// Open a window
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no", testURL_A);
newWin.addEventListener("load", function(aEvent) {
newWin.removeEventListener("load", arguments.callee, false);
newWin.gBrowser.addEventListener("load", function(aEvent) {
newWin.gBrowser.removeEventListener("load", arguments.callee, true);
info("Window has been loaded");
executeSoon(function() {
newWin.gBrowser.addTab();
executeSoon(function() {
// mark the window with some unique data to be restored later on
ss.setWindowValue(newWin, uniqueKey_A, uniqueValue_A);
// mark the window with some unique data to be restored later on
ss.setWindowValue(newWin, uniqueKey_A, uniqueValue_A);
newWin.close();
newWin.close();
// ensure that we incremented # of close windows
is(ss.getClosedWindowCount(), closedWindowCount + 1,
"The closed window was added to the list");
// ensure that we incremented # of close windows
is(ss.getClosedWindowCount(), closedWindowCount + 1,
"The closed window was added to the list");
// ensure we added window to undo list
let data = JSON.parse(ss.getClosedWindowData())[0];
ok(data.toSource().indexOf(uniqueValue_A) > -1,
"The closed window data was stored correctly");
// ensure we added window to undo list
let data = JSON.parse(ss.getClosedWindowData())[0];
ok(data.toSource().indexOf(uniqueValue_A) > -1,
"The closed window data was stored correctly");
// enter private browsing mode
pb.privateBrowsingEnabled = true;
ok(pb.privateBrowsingEnabled, "private browsing enabled");
// enter private browsing mode
pb.privateBrowsingEnabled = true;
ok(pb.privateBrowsingEnabled, "private browsing enabled");
// ensure that we have 0 undo windows when entering PB
is(ss.getClosedWindowCount(), 0,
"Recently Closed Windows are removed when entering Private Browsing");
is(ss.getClosedWindowData(), "[]",
"Recently Closed Windows data is cleared when entering Private Browsing");
// ensure that we have 0 undo windows when entering PB
is(ss.getClosedWindowCount(), 0,
"Recently Closed Windows are removed when entering Private Browsing");
is(ss.getClosedWindowData(), "[]",
"Recently Closed Windows data is cleared when entering Private Browsing");
// open another window in PB
let pbWin = openDialog(location, "_blank", "chrome,all,dialog=no", testURL_B);
pbWin.addEventListener("load", function(aEvent) {
pbWin.removeEventListener("load", arguments.callee, false);
pbWin.gBrowser.addEventListener("load", function(aEvent) {
pbWin.gBrowser.removeEventListener("load", arguments.callee, true);
// open another window in PB
let pbWin = openDialog(location, "_blank", "chrome,all,dialog=no", testURL_B);
pbWin.addEventListener("load", function(aEvent) {
pbWin.gBrowser.addEventListener("load", function(aEvent) {
pbWin.gBrowser.removeEventListener("load", arguments.callee, true);
executeSoon(function() {
// Add another tab, though it's not strictly needed
pbWin.gBrowser.addTab();
executeSoon(function() {
// mark the window with some unique data to be restored later on
ss.setWindowValue(pbWin, uniqueKey_B, uniqueValue_B);
executeSoon(function() {
// Add another tab, though it's not strictly needed
pbWin.gBrowser.addTab();
pbWin.close();
// mark the window with some unique data to be restored later on
ss.setWindowValue(pbWin, uniqueKey_B, uniqueValue_B);
// ensure we added window to undo list
let data = JSON.parse(ss.getClosedWindowData())[0];
ok(data.toSource().indexOf(uniqueValue_B) > -1,
"The closed window data was stored correctly in PB mode");
pbWin.close();
// exit private browsing mode
pb.privateBrowsingEnabled = false;
ok(!pb.privateBrowsingEnabled, "private browsing disabled");
// ensure we added window to undo list
let data = JSON.parse(ss.getClosedWindowData())[0];
ok(data.toSource().indexOf(uniqueValue_B) > -1,
"The closed window data was stored correctly in PB mode");
// ensure that we still have the closed windows from before
is(ss.getClosedWindowCount(), closedWindowCount + 1,
"The correct number of recently closed windows were restored " +
"when exiting PB mode");
// exit private browsing mode
pb.privateBrowsingEnabled = false;
ok(!pb.privateBrowsingEnabled, "private browsing disabled");
let data = JSON.parse(ss.getClosedWindowData())[0];
ok(data.toSource().indexOf(uniqueValue_A) > -1,
"The data associated with the recently closed window was " +
"restored when exiting PB mode");
// ensure that we still have the closed windows from before
is(ss.getClosedWindowCount(), closedWindowCount + 1,
"The correct number of recently closed windows were restored " +
"when exiting PB mode");
let data = JSON.parse(ss.getClosedWindowData())[0];
ok(data.toSource().indexOf(uniqueValue_A) > -1,
"The data associated with the recently closed window was " +
"restored when exiting PB mode");
// cleanup
gPrefService.clearUserPref("browser.sessionstore.interval");
finish();
});
}, true);
}, true);
// cleanup
gPrefService.clearUserPref("browser.sessionstore.interval");
finish();
});
});
}, true);
}, false);
});
});
}, true);
}, true);
}, false);
}

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

@ -55,7 +55,7 @@ nsSetDefaultBrowser.prototype = {
}
},
helpInfo: " -setDefaultBrowser Set this app as the default browser.\n",
helpInfo: " -setDefaultBrowser Set this app as the default browser.\n",
classDescription: "Default Browser Cmdline Handler",
contractID: "@mozilla.org/browser/default-browser-clh;1",

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

@ -11,14 +11,15 @@
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
# The Original Code is Aero Peek
#
# The Initial Developer of the Original Code is
# Netscape Communications.
# Portions created by the Initial Developer are Copyright (C) 2001
# Mozilla Corporation
# Portions created by the Initial Developer are Copyright (C) 2009
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Rob Arnold <tellrob@gmail.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
@ -34,47 +35,22 @@
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../../../../..
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = printpde
ifdef ENABLE_TESTS
DIRS += test
endif
MODULE = wintaskbar
EXTRA_JS_MODULES = \
WindowsPreviewPerTab.jsm \
WindowsJumpLists.jsm \
$(NULL)
include $(topsrcdir)/config/rules.mk
ifdef MOZ_DEBUG
BUILDSTYLE = Development
else
BUILDSTYLE = Deployment
endif
# pbbuild or xcodebuild indicates Xcode; the Xcode project contains
# native targets needed for proper SDK builds.
PROJECT=PrintPDE.xcode
PROJECT_ARG=-project $(PROJECT)
PBBUILD_ARG=$(PBBUILD_SETTINGS)
unexport CC CXX
ABS_topsrcdir := $(shell cd $(topsrcdir); pwd)
ifneq ($(ABS_topsrcdir),$(MOZ_BUILD_ROOT))
export::
rsync -a --exclude .DS_Store --exclude "CVS/" $(srcdir)/$(PROJECT) .
ln -fs $(srcdir)/src
ln -fs $(srcdir)/res
ln -fs $(srcdir)/public
ln -fs $(srcdir)/Info-*.plist .
GARBAGE += src res public Info-*.plist
GARBAGE_DIRS += $(PROJECT)
endif
GARBAGE_DIRS += build
libs::
$(PBBUILD) $(PROJECT_ARG) -target PrintPDE -buildstyle $(BUILDSTYLE) $(PBBUILD_ARG)
mkdir -p $(DIST)/package
$(INSTALL) $(XCODE_PRODUCT_DIR)/PrintPDE.plugin $(DIST)/package

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

@ -0,0 +1,528 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Jim Mathies <jmathies@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 ***** */
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
/**
* Constants
*/
const Cc = Components.classes;
const Ci = Components.interfaces;
// Prefs
const PREF_TASKBAR_BRANCH = "browser.taskbar.lists.";
const PREF_TASKBAR_ENABLED = "enabled";
const PREF_TASKBAR_ITEMCOUNT = "maxListItemCount";
const PREF_TASKBAR_FREQUENT = "frequent.enabled";
const PREF_TASKBAR_RECENT = "recent.enabled";
const PREF_TASKBAR_TASKS = "tasks.enabled";
// The amount of time between updates for jump lists
const TIMER_TASKBAR_REFRESH = 1000*60*2; // 2 min.
/**
* Exports
*/
let EXPORTED_SYMBOLS = [
"WinTaskbarJumpList",
];
/**
* Smart getters
*/
XPCOMUtils.defineLazyGetter(this, "_prefs", function() {
return Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefService)
.getBranch(PREF_TASKBAR_BRANCH)
.QueryInterface(Ci.nsIPrefBranch2);
});
XPCOMUtils.defineLazyGetter(this, "_stringBundle", function() {
return Cc["@mozilla.org/intl/stringbundle;1"]
.getService(Ci.nsIStringBundleService)
.createBundle("chrome://browser/locale/taskbar.properties");
});
XPCOMUtils.defineLazyServiceGetter(this, "_taskbarService",
"@mozilla.org/windows-taskbar;1",
"nsIWinTaskbar");
XPCOMUtils.defineLazyServiceGetter(this, "_navHistoryService",
"@mozilla.org/browser/nav-history-service;1",
"nsINavHistoryService");
XPCOMUtils.defineLazyServiceGetter(this, "_observerService",
"@mozilla.org/observer-service;1",
"nsIObserverService");
XPCOMUtils.defineLazyServiceGetter(this, "_directoryService",
"@mozilla.org/file/directory_service;1",
"nsIProperties");
XPCOMUtils.defineLazyServiceGetter(this, "_ioService",
"@mozilla.org/network/io-service;1",
"nsIIOService");
/**
* Global functions
*/
function _getString(name) {
return _stringBundle.GetStringFromName(name);
}
/////////////////////////////////////////////////////////////////////////////
// Task list configuration data object.
var tasksCfg = [
/**
* Task configuration options: title, description, args, iconIndex, open, close.
*
* title - Task title displayed in the list. (strings in the table are temp fillers.)
* description - Tooltip description on the list item.
* args - Command line args to invoke the task.
* iconIndex - Optional win icon index into the main application for the
* list item.
* open - Boolean indicates if the command should be visible after the browser opens.
* close - Boolean indicates if the command should be visible after the browser closes.
*/
// Open new window
{
get title() _getString("taskbar.tasks.newTab.label"),
get description() _getString("taskbar.tasks.newTab.description"),
args: "-new-tab about:blank",
iconIndex: 0, // Fx app icon
open: true,
close: false, // The jump list already has an app launch icon
},
// Open new tab
{
get title() _getString("taskbar.tasks.newWindow.label"),
get description() _getString("taskbar.tasks.newWindow.description"),
args: "-browser",
iconIndex: 0, // Fx app icon
open: true,
close: false, // no point
},
];
/////////////////////////////////////////////////////////////////////////////
// Implementation
var WinTaskbarJumpList =
{
_builder: null,
_tasks: null,
_shuttingDown: false,
/**
* Startup, shutdown, and update
*/
startup: function WTBJL_startup() {
// exit if this isn't win7 or higher.
if (!this._initTaskbar())
return;
// Store our task list config data
this._tasks = tasksCfg;
// retrieve taskbar related prefs.
this._refreshPrefs();
// observer for private browsing and our prefs branch
this._initObs();
// jump list refresh timer
this._initTimer();
// build the list
this.update();
},
update: function WTBJL_update() {
// are we disabled via prefs? don't do anything!
if (!this._enabled)
return;
// hide jump lists when we're enabled and in private browsing mode
if (this._inPrivateBrowsing) {
this._deleteActiveJumpList();
return;
}
// do what we came here to do, update the taskbar jumplist
this._buildList();
},
_shutdown: function WTBJL__shutdown() {
this._shuttingDown = true;
this.update();
this._free();
},
/**
* List building
*/
_buildList: function WTBJL__buildList() {
// anything to build?
if (!this._showFrequent && !this._showRecent && !this._showTasks) {
// don't leave the last list hanging on the taskbar.
this._deleteActiveJumpList();
return;
}
if (!this._startBuild())
return;
if (this._showTasks && !this._buildTasks())
return;
// Space for frequent items takes priority over recent.
if (this._showFrequent && !this._buildFrequent())
return;
if (this._showRecent && !this._buildRecent())
return;
this._commitBuild();
},
/**
* Taskbar api wrappers
*/
_startBuild: function WTBJL__startBuild() {
var removedItems = Cc["@mozilla.org/array;1"].
createInstance(Ci.nsIMutableArray);
this._builder.abortListBuild();
if (this._builder.initListBuild(removedItems)) {
// Prior to building, delete removed items from history.
this._clearHistory(removedItems);
return true;
}
return false;
},
_commitBuild: function WTBJL__commitBuild() {
if (!this._builder.commitListBuild())
this._builder.abortListBuild();
},
_buildTasks: function WTBJL__buildTasks() {
var items = Cc["@mozilla.org/array;1"].
createInstance(Ci.nsIMutableArray);
this._tasks.forEach(function (task) {
if ((this._shuttingDown && !task.close) || (!this._shuttingDown && !task.open))
return;
var item = this._getHandlerAppItem(task.title, task.description,
task.args, task.iconIndex);
items.appendElement(item, false);
}, this);
if (items.length == 0)
return true;
return this._builder.addListToBuild(this._builder.JUMPLIST_CATEGORY_TASKS, items);
},
_buildCustom: function WTBJL__buildCustom(title, items) {
if (items.length == 0)
return true;
return this._builder.addListToBuild(this._builder.JUMPLIST_CATEGORY_CUSTOMLIST, items, title);
},
_buildFrequent: function WTBJL__buildFrequent() {
// Windows supports default frequent and recent lists,
// but those depend on internal windows visit tracking
// which we don't populate. So we build our own custom
// frequent and recent lists using our nav history data.
var items = Cc["@mozilla.org/array;1"].
createInstance(Ci.nsIMutableArray);
var list = this._getNavFrequent(this._maxItemCount);
if (!list || list.length == 0)
return true;
// track frequent items so that we don't add them to
// the recent list.
this._frequentHashList = [];
list.forEach(function (entry) {
let shortcut = this._getHandlerAppItem(entry.title, entry.title, entry.uri, 1);
items.appendElement(shortcut, false);
this._frequentHashList.push(entry.uri);
}, this);
return this._buildCustom(_getString("taskbar.frequent.label"), items);
},
_buildRecent: function WTBJL__buildRecent() {
var items = Cc["@mozilla.org/array;1"].
createInstance(Ci.nsIMutableArray);
var list = this._getNavRecent(this._maxItemCount*2);
if (!list || list.length == 0)
return true;
let count = 0;
for (let idx = 0; idx < list.length; idx++) {
if (count >= this._maxItemCount)
break;
let entry = list[idx];
// do not add items to recent that have already been added
// to frequent.
if (this._frequentHashList &&
this._frequentHashList.indexOf(entry.uri) != -1)
continue;
let shortcut = this._getHandlerAppItem(entry.title, entry.title, entry.uri, 1);
items.appendElement(shortcut, false);
count++;
}
return this._buildCustom(_getString("taskbar.recent.label"), items);
},
_deleteActiveJumpList: function WTBJL__deleteAJL() {
return this._builder.deleteActiveList();
},
/**
* Jump list item creation helpers
*/
_getHandlerAppItem: function WTBJL__getHandlerAppItem(name, description, args, icon) {
var file = _directoryService.get("XCurProcD", Ci.nsILocalFile);
// XXX where can we grab this from in the build? Do we need to?
file.append("firefox.exe");
var handlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"].
createInstance(Ci.nsILocalHandlerApp);
handlerApp.executable = file;
// handlers default to the leaf name if a name is not specified
if (name.length != 0)
handlerApp.name = name;
handlerApp.detailedDescription = description;
handlerApp.appendParameter(args);
var item = Cc["@mozilla.org/windows-jumplistshortcut;1"].
createInstance(Ci.nsIJumpListShortcut);
item.app = handlerApp;
item.iconIndex = icon;
return item;
},
_getSeparatorItem: function WTBJL__getSeparatorItem() {
var item = Cc["@mozilla.org/windows-jumplistseparator;1"].
createInstance(Ci.nsIJumpListSeparator);
return item;
},
/**
* Nav history helpers
*/
_getNavFrequent: function WTBJL__getNavFrequent(depth) {
var options = _navHistoryService.getNewQueryOptions();
var query = _navHistoryService.getNewQuery();
query.beginTimeReference = query.TIME_RELATIVE_NOW;
query.beginTime = -24 * 30 * 60 * 60 * 1000000; // one month
query.endTimeReference = query.TIME_RELATIVE_NOW;
options.maxResults = depth;
options.queryType = options.QUERY_TYPE_HISTORY;
options.sortingMode = options.SORT_BY_VISITCOUNT_DESCENDING;
options.resultType = options.RESULT_TYPE_URI;
var result = _navHistoryService.executeQuery(query, options);
var list = [];
var rootNode = result.root;
rootNode.containerOpen = true;
for (let idx = 0; idx < rootNode.childCount; idx++) {
let node = rootNode.getChild(idx);
list.push({uri: node.uri, title: node.title});
}
rootNode.containerOpen = false;
return list;
},
_getNavRecent: function WTBJL__getNavRecent(depth) {
var options = _navHistoryService.getNewQueryOptions();
var query = _navHistoryService.getNewQuery();
query.beginTimeReference = query.TIME_RELATIVE_NOW;
query.beginTime = -48 * 60 * 60 * 1000000; // two days
query.endTimeReference = query.TIME_RELATIVE_NOW;
options.maxResults = depth;
options.queryType = options.QUERY_TYPE_HISTORY;
options.sortingMode = options.SORT_BY_LASTMODIFIED_DESCENDING;
options.resultType = options.RESULT_TYPE_URI;
var result = _navHistoryService.executeQuery(query, options);
var list = [];
var rootNode = result.root;
rootNode.containerOpen = true;
for (var idx = 0; idx < rootNode.childCount; idx++) {
var node = rootNode.getChild(idx);
list.push({uri: node.uri, title: node.title});
}
rootNode.containerOpen = false;
return list;
},
_clearHistory: function WTBJL__clearHistory(items) {
if (!items)
return;
var enum = items.enumerate();
while (enum.hasMoreElements()) {
let oldItem = enum.getNext().QueryInterface(Ci.nsIJumpListShortcut);
if (oldItem) {
try { // in case we get a bad uri
let uriSpec = oldItem.app.getParameter(0);
_navHistoryService.QueryInterface(Ci.nsIBrowserHistory).removePage(
_ioService.newURI(uriSpec));
} catch (err) { }
}
}
},
/**
* Prefs utilities
*/
_refreshPrefs: function WTBJL__refreshPrefs() {
this._enabled = _prefs.getBoolPref(PREF_TASKBAR_ENABLED);
this._showFrequent = _prefs.getBoolPref(PREF_TASKBAR_FREQUENT);
this._showRecent = _prefs.getBoolPref(PREF_TASKBAR_RECENT);
this._showTasks = _prefs.getBoolPref(PREF_TASKBAR_TASKS);
this._maxItemCount = _prefs.getIntPref(PREF_TASKBAR_ITEMCOUNT);
// retrieve the initial status of the Private Browsing mode.
this._inPrivateBrowsing = Cc["@mozilla.org/privatebrowsing;1"].
getService(Ci.nsIPrivateBrowsingService).
privateBrowsingEnabled;
},
/**
* Init and shutdown utilities
*/
_initTaskbar: function WTBJL__initTaskbar() {
this._builder = _taskbarService.createJumpListBuilder();
if (!this._builder || !this._builder.available)
return false;
return true;
},
_initObs: function WTBJL__initObs() {
_observerService.addObserver(this, "private-browsing", false);
_observerService.addObserver(this, "quit-application-granted", false);
_prefs.addObserver("", this, false);
},
_freeObs: function WTBJL__freeObs() {
_observerService.removeObserver(this, "private-browsing");
_observerService.removeObserver(this, "quit-application-granted");
_prefs.removeObserver("", this);
},
_initTimer: function WTBJL__initTimer(aTimer) {
this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
this._timer.initWithCallback(this, TIMER_TASKBAR_REFRESH, this._timer.TYPE_REPEATING_SLACK);
},
_free: function WTBJL__free() {
this._freeObs();
delete this._builder;
delete this._timer;
},
/**
* Notification handlers
*/
notify: function WTBJL_notify(aTimer) {
this.update();
},
observe: function WTBJL_observe(aSubject, aTopic, aData) {
switch (aTopic) {
case "nsPref:changed":
this._refreshPrefs();
this.update();
break;
case "quit-application-granted":
this._shutdown();
break;
case "browser:purge-session-history":
this.update();
break;
case "private-browsing":
switch (aData) {
case "enter":
this._inPrivateBrowsing = true;
break;
case "exit":
this._inPrivateBrowsing = false;
break;
}
this.update();
break;
}
},
};

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

@ -0,0 +1,653 @@
/* vim: se cin sw=2 ts=2 et :
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Rob Arnold <robarnold@cmu.edu> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* This module implements the front end behavior for AeroPeek. Starting in
* Windows Vista, the taskbar began showing live thumbnail previews of windows
* when the user hovered over the window icon in the taskbar. Starting with
* Windows 7, the taskbar allows an application to expose its tabbed interface
* in the taskbar by showing thumbnail previews rather than the default window
* preview. Additionally, when a user hovers over a thumbnail (tab or window),
* they are shown a live preview of the window (or tab + its containing window).
*
* In Windows 7, a title, icon, close button and optional toolbar are shown for
* each preview. This feature does not make use of the toolbar. For window
* previews, the title is the window title and the icon the window icon. For
* tab previews, the title is the page title and the page's favicon. In both
* cases, the close button "does the right thing."
*
* The primary objects behind this feature are nsITaskbarTabPreview and
* nsITaskbarPreviewController. Each preview has a controller. The controller
* responds to the user's interactions on the taskbar and provides the required
* data to the preview for determining the size of the tab and thumbnail. The
* PreviewController class implements this interface. The preview will request
* the controller to provide a thumbnail or preview when the user interacts with
* the taskbar. To reduce the overhead of drawing the tab area, the controller
* implementation caches the tab's contents in a <canvas> element. If no
* previews or thumbnails have been requested for some time, the controller will
* discard its cached tab contents.
*
* Screen real estate is limited so when there are too many thumbnails to fit
* on the screen, the taskbar stops displaying thumbnails and instead displays
* just the title, icon and close button in a similar fashion to previous
* versions of the taskbar. If there are still too many previews to fit on the
* screen, the taskbar resorts to a scroll up and scroll down button pair to let
* the user scroll through the list of tabs. Since this is undoubtedly
* inconvenient for users with many tabs, the AeroPeek objects turns off all of
* the tab previews. This tells the taskbar to revert to one preview per window.
* If the number of tabs falls below this magic threshold, the preview-per-tab
* behavior returns. There is no reliable way to determine when the scroll
* buttons appear on the taskbar, so a magic pref-controlled number determines
* when this threshold has been crossed.
*/
var EXPORTED_SYMBOLS = ["AeroPeek"];
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/NetUtil.jsm");
// Pref to enable/disable preview-per-tab
const TOGGLE_PREF_NAME = "browser.taskbar.previews.enable";
// Pref to determine the magic auto-disable threshold
const DISABLE_THRESHOLD_PREF_NAME = "browser.taskbar.previews.max";
// Pref to control the time in seconds that tab contents live in the cache
const CACHE_EXPIRATION_TIME_PREF_NAME = "browser.taskbar.previews.cachetime";
const WINTASKBAR_CONTRACTID = "@mozilla.org/windows-taskbar;1";
////////////////////////////////////////////////////////////////////////////////
//// Various utility properties
XPCOMUtils.defineLazyServiceGetter(this, "ioSvc",
"@mozilla.org/network/io-service;1",
"nsIIOService");
XPCOMUtils.defineLazyServiceGetter(this, "imgTools",
"@mozilla.org/image/tools;1",
"imgITools");
XPCOMUtils.defineLazyServiceGetter(this, "faviconSvc",
"@mozilla.org/browser/favicon-service;1",
"nsIFaviconService");
// nsIURI -> imgIContainer
function _imageFromURI(uri) {
let channel = ioSvc.newChannelFromURI(uri);
let out_img = { value: null };
let inputStream = channel.open();
try {
imgTools.decodeImageData(inputStream, channel.contentType, out_img);
return out_img.value;
} catch (e) {
return null;
}
}
// string -> imgIContainer
function _imageFromURL(url) {
return _imageFromURI(NetUtil.newURI(url));
}
// string? -> imgIContainer
function getFaviconAsImage(iconurl) {
return (iconurl ? _imageFromURL(iconurl) : false) ||
_imageFromURI(faviconSvc.defaultFavicon);
}
////////////////////////////////////////////////////////////////////////////////
//// PreviewController
/*
* This class manages the behavior of the preview.
*
* To give greater performance when drawing, the dirty areas of the content
* window are tracked and drawn on demand into a canvas of the same size.
* This provides a great increase in responsiveness when drawing a preview
* for unchanged (or even only slightly changed) tabs.
*
* @param win
* The TabWindow (see below) that owns the preview that this controls
* @param tab
* The <tab> that this preview is associated with
*/
function PreviewController(win, tab) {
this.win = win;
this.tab = tab;
this.linkedBrowser = tab.linkedBrowser;
this.linkedBrowser.addEventListener("MozAfterPaint", this, false);
this.linkedBrowser.addEventListener("DOMTitleChanged", this, false);
// pageshow is needed for when a tab is dragged across windows.
this.linkedBrowser.addEventListener("pageshow", this, false);
// Cannot perform the lookup during construction. See TabWindow.newTab
XPCOMUtils.defineLazyGetter(this, "preview", function () this.win.previewFromTab(this.tab));
XPCOMUtils.defineLazyGetter(this, "canvasPreview", function ()
this.win.win.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas"));
XPCOMUtils.defineLazyGetter(this, "dirtyRegion",
function () {
let dirtyRegion = Cc["@mozilla.org/gfx/region;1"]
.createInstance(Ci.nsIScriptableRegion);
dirtyRegion.init();
return dirtyRegion;
});
}
PreviewController.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsITaskbarPreviewController,
Ci.nsIDOMEventListener]),
destroy: function () {
this.linkedBrowser.removeEventListener("pageshow", this, false);
this.linkedBrowser.removeEventListener("DOMTitleChanged", this, false);
this.linkedBrowser.removeEventListener("MozAfterPaint", this, false);
},
get wrappedJSObject() {
return this;
},
get dirtyRects() {
let rectstream = this.dirtyRegion.getRects();
if (!rectstream)
return [];
let rects = [];
for (let i = 0; i < rectstream.length; i+= 4) {
let r = {x: rectstream[i],
y: rectstream[i+1],
width: rectstream[i+2],
height: rectstream[i+3]};
rects.push(r);
}
return rects;
},
// Resizes the canvasPreview to 0x0, essentially freeing its memory.
// updateCanvasPreview() will detect the size mismatch as a resize event
// the next time it is called.
resetCanvasPreview: function () {
this.canvasPreview.width = 0;
this.canvasPreview.height = 0;
},
// Updates the controller's canvas with the parts of the <browser> that need
// to be redrawn.
updateCanvasPreview: function () {
let win = this.linkedBrowser.contentWindow;
let bx = this.linkedBrowser.boxObject;
// Check for resize
if (bx.width != this.canvasPreview.width ||
bx.height != this.canvasPreview.height) {
// Invalidate the entire area and repaint
this.onTabPaint({left:0, top:0, width:bx.width, height:bx.height});
this.canvasPreview.width = bx.width;
this.canvasPreview.height = bx.height;
}
// Draw dirty regions
let ctx = this.canvasPreview.getContext("2d");
let flags = this.canvasPreviewFlags;
// width/height are occasionally bogus and too large for drawWindow
// so we clip to the canvas region
this.dirtyRegion.intersectRect(0, 0, bx.width, bx.height);
this.dirtyRects.forEach(function (r) {
let x = r.x;
let y = r.y;
let width = r.width;
let height = r.height;
ctx.save();
ctx.translate(x, y);
ctx.drawWindow(win, x, y, width, height, "white", flags);
ctx.restore();
});
this.dirtyRegion.setToRect(0,0,0,0);
// If we're updating the canvas, then we're in the middle of a peek so
// don't discard the cache of previews.
AeroPeek.resetCacheTimer();
},
onTabPaint: function (rect) {
// Ignore spurious dirty rects
if (!rect.width || !rect.height)
return;
let r = { x: Math.floor(rect.left),
y: Math.floor(rect.top),
width: Math.ceil(rect.width),
height: Math.ceil(rect.height)
};
this.dirtyRegion.unionRect(r.x, r.y, r.width, r.height);
},
//////////////////////////////////////////////////////////////////////////////
//// nsITaskbarPreviewController
get width() {
return this.win.width;
},
get height() {
return this.win.height;
},
get thumbnailAspectRatio() {
let boxObject = this.tab.linkedBrowser.boxObject;
// Avoid returning 0
let tabWidth = boxObject.width || 1;
// Avoid divide by 0
let tabHeight = boxObject.height || 1;
return tabWidth / tabHeight;
},
drawPreview: function (ctx) {
let self = this;
this.win.tabbrowser.previewTab(this.tab, function () self.previewTabCallback(ctx));
// We want a frame drawn around the preview
return true;
},
previewTabCallback: function (ctx) {
let width = this.win.width;
let height = this.win.height;
// Draw our toplevel window
ctx.drawWindow(this.win.win, 0, 0, width, height, "transparent");
// Compositor, where art thou?
// Draw the tab content on top of the toplevel window
this.updateCanvasPreview();
let boxObject = this.linkedBrowser.boxObject;
ctx.translate(boxObject.x, boxObject.y);
ctx.drawImage(this.canvasPreview, 0, 0);
},
drawThumbnail: function (ctx, width, height) {
this.updateCanvasPreview();
let scale = width/this.linkedBrowser.boxObject.width;
ctx.scale(scale, scale);
ctx.drawImage(this.canvasPreview, 0, 0);
// Don't draw a frame around the thumbnail
return false;
},
onClose: function () {
this.win.tabbrowser.removeTab(this.tab);
},
onActivate: function () {
this.win.tabbrowser.selectedTab = this.tab;
// Accept activation - this will restore the browser window
// if it's minimized
return true;
},
//// nsIDOMEventListener
handleEvent: function (evt) {
switch (evt.type) {
case "MozAfterPaint":
if (evt.originalTarget === this.linkedBrowser.contentWindow) {
let clientRects = evt.clientRects;
let length = clientRects.length;
for (let i = 0; i < length; i++) {
let r = clientRects.item(i);
this.onTabPaint(r);
}
}
let preview = this.preview;
if (preview.visible)
preview.invalidate();
break;
case "pageshow":
case "DOMTitleChanged":
// The tab's label is sometimes empty when dragging tabs between windows
// so we force the tab title to be updated (see bug 520579)
this.win.tabbrowser.setTabTitle(this.tab);
let title = this.tab.label;
this.preview.title = title;
this.preview.tooltip = title;
break;
}
}
};
XPCOMUtils.defineLazyGetter(PreviewController.prototype, "canvasPreviewFlags",
function () { let canvasInterface = Ci.nsIDOMCanvasRenderingContext2D;
return canvasInterface.DRAWWINDOW_DRAW_VIEW
| canvasInterface.DRAWWINDOW_DRAW_CARET
| canvasInterface.DRAWWINDOW_DO_NOT_FLUSH;
});
////////////////////////////////////////////////////////////////////////////////
//// TabWindow
/*
* This class monitors a browser window for changes to its tabs
*
* @param win
* The nsIDOMWindow browser window
*/
function TabWindow(win) {
this.win = win;
this.tabbrowser = win.gBrowser;
this.previews = [];
for (let i = 0; i < this.events.length; i++)
this.tabbrowser.tabContainer.addEventListener(this.events[i], this, false);
this.tabbrowser.addTabsProgressListener(this);
AeroPeek.windows.push(this);
let tabs = this.tabbrowser.mTabs;
for (let i = 0; i < tabs.length; i++)
this.newTab(tabs[i]);
this.updateTabOrdering();
AeroPeek.checkPreviewCount();
}
TabWindow.prototype = {
_enabled: false,
events: ["TabOpen", "TabClose", "TabSelect", "TabMove"],
destroy: function () {
this._destroying = true;
let tabs = this.tabbrowser.mTabs;
for (let i = 0; i < this.events.length; i++)
this.tabbrowser.tabContainer.removeEventListener(this.events[i], this, false);
for (let i = 0; i < tabs.length; i++)
this.removeTab(tabs[i]);
let idx = AeroPeek.windows.indexOf(this.win.gTaskbarTabGroup);
AeroPeek.windows.splice(idx, 1);
AeroPeek.checkPreviewCount();
},
get width () {
return this.win.innerWidth;
},
get height () {
return this.win.innerHeight;
},
// Invoked when the given tab is added to this window
newTab: function (tab) {
let controller = new PreviewController(this, tab);
let preview = AeroPeek.taskbar.createTaskbarTabPreview(this.tabbrowser.docShell, controller);
preview.title = tab.label;
preview.tooltip = tab.label;
preview.visible = AeroPeek.enabled;
preview.active = this.tabbrowser.selectedTab == tab;
// Grab the default favicon
preview.icon = getFaviconAsImage(null);
this.previews.splice(tab._tPos, 0, preview);
AeroPeek.addPreview(preview);
},
// Invoked when the given tab is closed
removeTab: function (tab) {
let preview = this.previewFromTab(tab);
preview.active = false;
preview.visible = false;
preview.move(null);
preview.controller.wrappedJSObject.destroy();
// We don't want to splice from the array if the tabs aren't being removed
// from the tab bar as well (as is the case when the window closes).
if (!this._destroying)
this.previews.splice(tab._tPos, 1);
AeroPeek.removePreview(preview);
},
get enabled () {
return this._enabled;
},
set enabled (enable) {
this._enabled = enable;
// Because making a tab visible requires that the tab it is next to be
// visible, it is far simpler to unset the 'next' tab and recreate them all
// at once.
this.previews.forEach(function (preview) {
preview.move(null);
preview.visible = enable;
});
this.updateTabOrdering();
},
previewFromTab: function (tab) {
return this.previews[tab._tPos];
},
updateTabOrdering: function () {
for (let i = 0; i < this.previews.length; i++) {
let p = this.previews[i];
let next = i == this.previews.length - 1 ? null : this.previews[i+1];
p.move(next);
}
},
//// nsIDOMEventListener
handleEvent: function (evt) {
let tab = evt.originalTarget;
switch (evt.type) {
case "TabOpen":
this.newTab(tab);
this.updateTabOrdering();
break;
case "TabClose":
this.removeTab(tab);
this.updateTabOrdering();
break;
case "TabSelect":
this.previewFromTab(tab).active = true;
break;
case "TabMove":
let oldPos = evt.detail;
let newPos = tab._tPos;
let preview = this.previews[oldPos];
this.previews.splice(oldPos, 1);
this.previews.splice(newPos, 0, preview);
this.updateTabOrdering();
break;
}
},
//// Browser progress listener
onLocationChange: function () {
},
onProgressChange: function () {
},
onSecurityChange: function () {
},
onStateChange: function () {
},
onStatusChange: function () {
},
onLinkIconAvailable: function (aBrowser) {
let img = getFaviconAsImage(aBrowser.mIconURL);
let index = this.tabbrowser.browsers.indexOf(aBrowser);
this.previews[index].icon = img;
}
}
////////////////////////////////////////////////////////////////////////////////
//// AeroPeek
/*
* This object acts as global storage and external interface for this feature.
* It maintains the values of the prefs.
*/
var AeroPeek = {
available: false,
// Does the pref say we're enabled?
_prefenabled: true,
_enabled: true,
// nsITaskbarTabPreview array
previews: [],
// TabWindow array
windows: [],
// nsIWinTaskbar service
taskbar: null,
// Maximum number of previews
maxpreviews: 20,
// Length of time in seconds that previews are cached
cacheLifespan: 20,
initialize: function () {
if (!(WINTASKBAR_CONTRACTID in Cc))
return;
this.taskbar = Cc[WINTASKBAR_CONTRACTID].getService(Ci.nsIWinTaskbar);
this.available = this.taskbar.available;
if (!this.available)
return;
this.prefs.addObserver(TOGGLE_PREF_NAME, this, false);
this.prefs.addObserver(DISABLE_THRESHOLD_PREF_NAME, this, false);
this.prefs.addObserver(CACHE_EXPIRATION_TIME_PREF_NAME, this, false);
this.cacheLifespan = this.prefs.getIntPref(CACHE_EXPIRATION_TIME_PREF_NAME);
this.maxpreviews = this.prefs.getIntPref(DISABLE_THRESHOLD_PREF_NAME);
this.enabled = this._prefenabled = this.prefs.getBoolPref(TOGGLE_PREF_NAME);
},
get enabled() {
return this._enabled;
},
set enabled(enable) {
if (this._enabled == enable)
return;
this._enabled = enable;
this.windows.forEach(function (win) {
win.enabled = enable;
});
},
addPreview: function (preview) {
this.previews.push(preview);
this.checkPreviewCount();
},
removePreview: function (preview) {
let idx = this.previews.indexOf(preview);
this.previews.splice(idx, 1);
this.checkPreviewCount();
},
checkPreviewCount: function () {
if (this.previews.length > this.maxpreviews)
this.enabled = false;
else
this.enabled = this._prefenabled;
},
onOpenWindow: function (win) {
// This occurs when the taskbar service is not available (xp, vista)
if (!this.available)
return;
win.gTaskbarTabGroup = new TabWindow(win);
},
onCloseWindow: function (win) {
// This occurs when the taskbar service is not available (xp, vista)
if (!this.available)
return;
win.gTaskbarTabGroup.destroy();
win.gTaskbarTabGroup = null;
},
resetCacheTimer: function () {
this.cacheTimer.cancel();
this.cacheTimer.init(this, 1000*this.cacheLifespan, Ci.nsITimer.TYPE_ONE_SHOT);
},
//// nsIObserver
observe: function (aSubject, aTopic, aData) {
switch (aTopic) {
case "nsPref:changed":
if (aData == CACHE_EXPIRATION_TIME_PREF_NAME)
break;
if (aData == TOGGLE_PREF_NAME)
this._prefenabled = this.prefs.getBoolPref(TOGGLE_PREF_NAME);
else if (aData == DISABLE_THRESHOLD_PREF_NAME)
this.maxpreviews = this.prefs.getIntPref(DISABLE_THRESHOLD_PREF_NAME);
// Might need to enable/disable ourselves
this.checkPreviewCount();
break;
case "timer-callback":
this.previews.forEach(function (preview) {
let controller = preview.controller.wrappedJSObject;
controller.resetCanvasPreview();
});
break;
}
}
};
XPCOMUtils.defineLazyGetter(AeroPeek, "cacheTimer", function ()
Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer)
);
XPCOMUtils.defineLazyServiceGetter(AeroPeek, "prefs",
"@mozilla.org/preferences-service;1",
"nsIPrefBranch2");
AeroPeek.initialize();

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

@ -0,0 +1,54 @@
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is
# Mozilla Corporation.
# Portions created by the Initial Developer are Copyright (C) 2009
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Rob Arnold <robarnold@cmu.edu>
#
# Alternatively, the contents of this file may be used under the terms of
# either of 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 *****
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = browser/components/wintaskbar/test
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_BROWSER_FILES = browser_taskbar_preview.js \
$(NULL)
libs:: $(_BROWSER_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)

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

@ -0,0 +1,136 @@
function test() {
var isWin7OrHigher = false;
try {
let version = Cc["@mozilla.org/system-info;1"]
.getService(Ci.nsIPropertyBag2)
.getProperty("version");
isWin7OrHigher = (parseFloat(version) >= 6.1);
} catch (ex) { }
is(!!Win7Features, isWin7OrHigher, "Win7Features available when it should be");
if (!isWin7OrHigher)
return;
let temp = {};
Cu.import("resource://gre/modules/WindowsPreviewPerTab.jsm", temp);
let AeroPeek = temp.AeroPeek;
waitForExplicitFinish();
gPrefService.setBoolPref("aeropeek.enable", true);
is(1, AeroPeek.windows.length, "Got the expected number of windows");
checkPreviews(1, "Browser starts with one preview");
gBrowser.addTab();
gBrowser.addTab();
gBrowser.addTab();
checkPreviews(4, "Correct number of previews after adding");
for each (let preview in AeroPeek.previews)
ok(preview.visible, "Preview is shown as expected");
gPrefService.setBoolPref("aeropeek.enable", false);
checkPreviews(4, "Previews are unchanged when disabling");
for each (let preview in AeroPeek.previews)
ok(!preview.visible, "Preview is not shown as expected after disabling");
gPrefService.setBoolPref("aeropeek.enable", true);
checkPreviews(4, "Previews are unchanged when re-enabling");
for each (let preview in AeroPeek.previews)
ok(preview.visible, "Preview is shown as expected after re-enabling");
[1,2,3,4].forEach(function (idx) {
gBrowser.selectedTab = gBrowser.mTabs[idx];
ok(checkSelectedTab(), "Current tab is correctly selected");
});
let currentSelectedTab = gBrowser.selectedTab;
for each (let idx in [1,2,3,4]) {
let preview = getPreviewForTab(gBrowser.mTabs[0]);
let canvas = createThumbnailSurface(preview);
let ctx = canvas.getContext("2d");
preview.controller.drawThumbnail(ctx, canvas.width, canvas.height);
ok(currentSelectedTab == gBrowser.selectedTab, "Drawing thumbnail does not change selection");
canvas = getCanvas(preview.controller.width, preview.controller.height);
ctx = canvas.getContext("2d");
preview.controller.drawPreview(ctx);
ok(currentSelectedTab == gBrowser.selectedTab, "Drawing preview does not change selection");
}
// Close #4
getPreviewForTab(gBrowser.selectedTab).controller.onClose();
checkPreviews(3, "Expected number of previews after closing selected tab via controller");
ok(gBrowser.mTabs.length == 3, "Successfully closed a tab");
// Select #1
ok(getPreviewForTab(gBrowser.mTabs[0]).controller.onActivate(), "Activation was accepted");
ok(gBrowser.mTabs[0] == gBrowser.selectedTab, "Correct tab was selected");
checkSelectedTab();
// Remove #3 (non active)
gBrowser.removeTab(gBrowser.tabContainer.lastChild);
checkPreviews(2, "Expected number of previews after closing unselected via browser");
// Remove #1 (active)
gBrowser.removeTab(gBrowser.tabContainer.firstChild);
checkPreviews(1, "Expected number of previews after closing selected tab via browser");
// Add a new tab
gBrowser.addTab();
checkPreviews(2);
// Check default selection
checkSelectedTab();
// Change selection
gBrowser.selectedTab = gBrowser.mTabs[0];
checkSelectedTab();
// Close nonselected tab via controller
getPreviewForTab(gBrowser.mTabs[1]).controller.onClose();
checkPreviews(1);
gPrefService.clearUserPref("aeropeek.enable");
finish();
function checkPreviews(aPreviews, msg) {
let nPreviews = AeroPeek.previews.length;
is(aPreviews, gBrowser.mTabs.length, "Browser has expected number of tabs");
is(nPreviews, gBrowser.mTabs.length, "Browser has one preview per tab");
is(nPreviews, aPreviews, msg || "Got expected number of previews");
}
function getPreviewForTab(tab)
window.gTaskbarTabGroup.previewFromTab(tab);
function checkSelectedTab()
getPreviewForTab(gBrowser.selectedTab).active;
function isTabSelected(idx)
gBrowser.selectedTab == gBrowser.mTabs[idx];
function createThumbnailSurface(p) {
let thumbnailWidth = 200,
thumbnailHeight = 120;
let ratio = p.controller.thumbnailAspectRatio;
if (thumbnailWidth/thumbnailHeight > ratio)
thumbnailWidth = thumbnailHeight * ratio;
else
thumbnailHeight = thumbnailWidth / ratio;
return getCanvas(thumbnailWidth, thumbnailHeight);
}
function getCanvas(width, height) {
let win = window.QueryInterface(Ci.nsIDOMWindowInternal);
let doc = win.document;
let canvas = doc.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
canvas.width = width;
canvas.height = height;
return canvas;
}
}

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

@ -40,11 +40,7 @@
#endif
[xpcom]
#ifdef XP_WIN32
@BINPATH@/js3250.dll
#else
@BINPATH@/@DLL_PREFIX@mozjs@DLL_SUFFIX@
#endif
@BINPATH@/@DLL_PREFIX@plc4@DLL_SUFFIX@
@BINPATH@/@DLL_PREFIX@plds4@DLL_SUFFIX@
@BINPATH@/@DLL_PREFIX@xpcom@DLL_SUFFIX@
@ -177,7 +173,6 @@
@BINPATH@/components/inspector.xpt
@BINPATH@/components/intl.xpt
@BINPATH@/components/jar.xpt
@BINPATH@/components/jsctypes.xpt
@BINPATH@/components/jsdservice.xpt
@BINPATH@/components/layout_base.xpt
#ifdef NS_PRINTING

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

@ -636,6 +636,12 @@ plugins/Default Plugin.plugin/Contents/MacOS/Default Plugin
plugins/Default Plugin.plugin/Contents/PkgInfo
plugins/Default Plugin.plugin/Contents/Resources/Default Plugin.rsrc
plugins/Default Plugin.plugin/Contents/Resources/English.lproj/InfoPlist.strings
../Plug-Ins/PrintPDE.plugin/Contents/Info.plist
../Plug-Ins/PrintPDE.plugin/Contents/MacOS/PrintPDE
../Plug-Ins/PrintPDE.plugin/Contents/Resources/English.lproj/Localizable.strings
../Plug-Ins/PrintPDE.plugin/Contents/Resources/English.lproj/PrintPDE.nib/classes.nib
../Plug-Ins/PrintPDE.plugin/Contents/Resources/English.lproj/PrintPDE.nib/info.nib
../Plug-Ins/PrintPDE.plugin/Contents/Resources/English.lproj/PrintPDE.nib/objects.xib
res/cursors/CVS/Entries
res/cursors/CVS/Repository
res/cursors/CVS/Root
@ -812,5 +818,8 @@ chrome.manifest
install.rdf
@DLL_PREFIX@jsj@DLL_SUFFIX@
#ifdef XP_WIN
js3250.dll
#endif
#ifdef XP_WIN
components/brwsrcmp.dll
#endif

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

@ -39,6 +39,12 @@ lwthemeInstallRequest.message=This site (%S) attempted to install a theme.
lwthemeInstallRequest.allowButton=Allow
lwthemeInstallRequest.allowButton.accesskey=a
lwthemePostInstallNotification.message=A new theme has been installed.
lwthemePostInstallNotification.undoButton=Undo
lwthemePostInstallNotification.undoButton.accesskey=U
lwthemePostInstallNotification.manageButton=Manage Themes…
lwthemePostInstallNotification.manageButton.accesskey=M
popupWarning=%S prevented this site from opening a pop-up window.
popupWarningMultiple=%S prevented this site from opening %S pop-up windows.
popupWarningButton=Options

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

@ -0,0 +1,6 @@
taskbar.tasks.newTab.label=Open new tab
taskbar.tasks.newTab.description=Open a new browser tab.
taskbar.tasks.newWindow.label=Open new window
taskbar.tasks.newWindow.description=Open a new browser window.
taskbar.frequent.label=Frequent
taskbar.recent.label=Recent

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

@ -28,6 +28,7 @@
locale/browser/shellservice.properties (%chrome/browser/shellservice.properties)
locale/browser/tabbrowser.dtd (%chrome/browser/tabbrowser.dtd)
locale/browser/tabbrowser.properties (%chrome/browser/tabbrowser.properties)
locale/browser/taskbar.properties (%chrome/browser/taskbar.properties)
locale/browser/places/places.dtd (%chrome/browser/places/places.dtd)
locale/browser/places/places.properties (%chrome/browser/places/places.properties)
locale/browser/places/editBookmarkOverlay.dtd (%chrome/browser/places/editBookmarkOverlay.dtd)

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

@ -1,55 +1 @@
af
ar
be
bg
bn-IN
ca
cs
cy
de
el
en-GB
en-US
eo
es-AR
es-ES
et
eu
fi
fr
fy-NL
ga-IE
gu-IN
he
hi-IN
hu
id
is
it
ja linux win32
ja-JP-mac osx
ka
kn
ko
lt
lv
mr
nb-NO
nl
nn-NO
pa-IN
pl
pt-BR
pt-PT
ro
ru
si
sk
sl
sq
sv-SE
te
tr
uk
zh-CN
zh-TW

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

@ -69,6 +69,7 @@ browser/components/sidebar/src/Makefile
browser/components/shell/Makefile
browser/components/shell/public/Makefile
browser/components/shell/src/Makefile
browser/components/wintaskbar/Makefile
browser/fuel/Makefile
browser/fuel/public/Makefile
browser/fuel/src/Makefile
@ -105,6 +106,7 @@ if [ "$ENABLE_TESTS" ]; then
browser/components/privatebrowsing/test/Makefile
browser/components/privatebrowsing/test/browser/Makefile
browser/components/safebrowsing/content/test/Makefile
browser/components/wintaskbar/test/Makefile
browser/fuel/test/Makefile
"
fi

Двоичные данные
browser/themes/pinstripe/browser/Search-bar.png

Двоичный файл не отображается.

До

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

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

@ -60,7 +60,9 @@
#nav-bar:-moz-lwtheme {
-moz-appearance: none !important;
background: none !important;
border-style: none !important;
/* Switching to a lightweight theme shouldn't move the content area,
so avoid changing border widths here. */
border-color: transparent !important;
}
.tabbrowser-strip:-moz-lwtheme,

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

@ -43,7 +43,6 @@ browser.jar:
skin/classic/browser/searchbar.css
skin/classic/browser/Search.png
skin/classic/browser/Search-addengines.png
skin/classic/browser/Search-bar.png
skin/classic/browser/section_collapsed.png
skin/classic/browser/section_expanded.png
skin/classic/browser/Secure-Glyph-White.png

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

@ -256,29 +256,6 @@ window:not([active="true"]) #placesList > treechildren::-moz-tree-row(selected)
border: 0px;
}
.filterList {
-moz-appearance: none;
background-color: transparent;
border: 0px;
margin: 2px;
padding: 0px;
min-width: 0px;
width: 16px;
height: 16px;
list-style-image: url("chrome://browser/skin/Search-bar.png");
-moz-user-focus: ignore;
cursor: default;
}
.filterList .button-box {
border: 0px;
padding: 0px;
}
.filterList .button-menu-dropmarker {
margin: 9px -3px -4px 8px;
}
/* Scope Bar */
#advancedSearch > hbox,

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

@ -413,6 +413,8 @@ def environment(env = None, xrePath = DIST_BIN, crashreporter = True):
envVar = "LD_LIBRARY_PATH"
if IS_MAC:
envVar = "DYLD_LIBRARY_PATH"
else: # unixish
env['MOZILLA_FIVE_HOME'] = xrePath
if envVar in env:
ldLibraryPath = ldLibraryPath + ":" + env[envVar]
env[envVar] = ldLibraryPath
@ -422,7 +424,7 @@ def environment(env = None, xrePath = DIST_BIN, crashreporter = True):
if crashreporter:
env['MOZ_CRASHREPORTER_NO_REPORT'] = '1'
env['MOZ_CRASHREPORTER'] = '1'
env['GNOME_DISABLE_CRASH_DIALOG'] = "1"
return env
@ -438,6 +440,7 @@ def runApp(testURL, env, app, profileDir, extraArgs,
# copy env so we don't munge the caller's environment
env = dict(env);
env["NO_EM_RESTART"] = "1"
if IS_TEST_BUILD and runSSLTunnel:
# create certificate database for the profile

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

@ -72,16 +72,10 @@ if __name__ == '__main__':
t.start()
automation.initializeProfile(PROFILE_DIRECTORY)
browserEnv = dict(os.environ)
browserEnv = automation.environment()
browserEnv["NO_EM_RESTART"] = "1"
if not "XPCOM_DEBUG_BREAK" in browserEnv:
browserEnv["XPCOM_DEBUG_BREAK"] = "stack"
if automation.UNIXISH:
browserEnv["LD_LIBRARY_PATH"] = os.path.join(SCRIPT_DIR, DIST_BIN)
browserEnv["MOZILLA_FIVE_HOME"] = os.path.join(SCRIPT_DIR, DIST_BIN)
browserEnv["GNOME_DISABLE_CRASH_DIALOG"] = "1"
url = "http://localhost:%d/bloatcycle.html" % PORT
appPath = os.path.join(SCRIPT_DIR, automation.DEFAULT_APP)
status = automation.runApp(url, browserEnv, appPath, PROFILE_DIRECTORY,

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

@ -63,15 +63,8 @@ if __name__ == '__main__':
t.start()
automation.initializeProfile(PROFILE_DIRECTORY)
browserEnv = dict(os.environ)
# These variables are necessary for correct application startup; change
# via the commandline at your own risk.
browserEnv["NO_EM_RESTART"] = "1"
browserEnv = automation.environment()
browserEnv["XPCOM_DEBUG_BREAK"] = "warn"
if automation.UNIXISH:
browserEnv["LD_LIBRARY_PATH"] = os.path.join(SCRIPT_DIR, automation.DIST_BIN)
browserEnv["MOZILLA_FIVE_HOME"] = os.path.join(SCRIPT_DIR, automation.DIST_BIN)
url = "http://localhost:%d/index.html" % PORT
appPath = os.path.join(SCRIPT_DIR, automation.DEFAULT_APP)

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

@ -89,7 +89,6 @@ MOZ_X11 = @MOZ_X11@
MOZ_PANGO = @MOZ_PANGO@
MOZ_CORETEXT = @MOZ_CORETEXT@
MOZ_COCOA_PRINTING = @MOZ_COCOA_PRINTING@
MOZ_JS_LIBS = @MOZ_JS_LIBS@

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

@ -707,18 +707,6 @@ endif
endif
endif
# Flags needed to link against the component library
ifdef MOZ_COMPONENTLIB
MOZ_COMPONENTLIB_EXTRA_DSO_LIBS = mozcomps
# Tell the linker where NSS is, if we're building crypto
ifeq ($(OS_ARCH),Darwin)
ifeq (,$(findstring crypto,$(MOZ_META_COMPONENTS)))
MOZ_COMPONENTLIB_EXTRA_LIBS = $(foreach library, $(patsubst -l%, $(LIB_PREFIX)%$(DLL_SUFFIX), $(filter -l%, $(NSS_LIBS))), -dylib_file @executable_path/$(library):$(DIST)/bin/$(library))
endif
endif
endif
# If we're building a component on MSVC, we don't want to generate an
# import lib, because that import lib will collide with the name of a
# static version of the same library.
@ -758,7 +746,7 @@ else
ifeq (OS2,$(CROSS_COMPILE)$(OS_ARCH))
NSINSTALL = $(MOZ_TOOLS_DIR)/nsinstall
else
NSINSTALL = $(CONFIG_TOOLS)/nsinstall
NSINSTALL = $(CONFIG_TOOLS)/nsinstall$(HOST_BIN_SUFFIX)
endif # OS2
endif # NSINSTALL_BIN
@ -786,7 +774,7 @@ endif # WINNT/OS2
ifeq (,$(filter-out WINCE,$(OS_ARCH)))
NSINSTALL = $(CYGWIN_WRAPPER) nsinstall
INSTALL = $(CYGWIN_WRAPPER) nsinstall
INSTALL = $(CYGWIN_WRAPPER) nsinstall
endif
# Use nsinstall in copy mode to install files on the system

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

@ -230,9 +230,11 @@ endif # ENABLE_TESTS
ifndef LIBRARY
ifdef STATIC_LIBRARY_NAME
ifeq (OS2,$(OS_ARCH))
ifdef SHORT_LIBNAME
STATIC_LIBRARY_NAME := $(SHORT_LIBNAME)
SHARED_LIBRARY_NAME := $(SHORT_LIBNAME)
endif
endif
LIBRARY := $(LIB_PREFIX)$(STATIC_LIBRARY_NAME).$(LIB_SUFFIX)
endif # STATIC_LIBRARY_NAME
endif # LIBRARY

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

@ -42,6 +42,8 @@ dnl Mac OS X 10.4 support
dnl Giorgio Maone <g.maone@informaction.com>
dnl MSVC l10n compatible version check
dnl Ben Turner <mozilla@songbirdnest.com>
dnl Windows x64 support
dnl Makoto Kato <m_kato@ga2.so-net.ne.jp>
dnl
dnl Alternatively, the contents of this file may be used under the terms of
dnl either the GNU General Public License Version 2 or later (the "GPL"), or
@ -192,7 +194,16 @@ case "$target" in
if test -z "$CPP"; then CPP="cl -E -nologo"; fi
if test -z "$CXXCPP"; then CXXCPP="cl -TP -E -nologo"; ac_cv_prog_CXXCPP="$CXXCPP"; fi
if test -z "$LD"; then LD=link; fi
if test -z "$AS"; then AS=ml; fi
if test -z "$AS"; then
case "${target_cpu}" in
i*86)
AS=ml;
;;
x86_64)
AS=ml64;
;;
esac
fi
if test -z "$MIDL"; then MIDL=midl; fi
;;
*-darwin*)
@ -635,6 +646,9 @@ case "$target" in
AC_MSG_RESULT([none needed])
fi
;;
x86_64-*)
MIDL_FLAGS="${MIDL_FLAGS} -env x64"
;;
*)
AC_MSG_RESULT([none needed])
;;
@ -1586,7 +1600,7 @@ AC_LANG_SAVE
AC_LANG_C
AC_MSG_CHECKING(for 64-bit OS)
AC_TRY_COMPILE([$configure_static_assert_macros],
[CONFIGURE_STATIC_ASSERT(sizeof(long) == 8)],
[CONFIGURE_STATIC_ASSERT(sizeof(void*) == 8)],
result="yes", result="no")
AC_MSG_RESULT("$result")
if test "$result" = "yes"; then
@ -1653,6 +1667,12 @@ case "$host" in
fi
;;
esac
case "${host_cpu}" in
x86_64)
HOST_CFLAGS="$HOST_CFLAGS -D_AMD64_"
;;
esac
;;
*-darwin*)
@ -2037,7 +2057,7 @@ case "$target" in
MOZ_DEBUG_FLAGS='-Zi'
MOZ_DEBUG_LDFLAGS='-DEBUG -DEBUGTYPE:CV'
MOZ_FIX_LINK_PATHS=
MOZ_JS_LIBS='$(LIBXUL_DIST)/lib/js$(MOZ_BITS)$(VERSION_NUMBER).lib'
MOZ_JS_LIBS='$(LIBXUL_DIST)/lib/mozjs.lib'
OBJ_SUFFIX=obj
RANLIB='echo not_ranlib'
STRIP='echo not_strip'
@ -2101,7 +2121,7 @@ case "$target" in
RCFLAGS='-O coff --use-temp-file'
# mingw doesn't require kernel32, user32, and advapi32 explicitly
LIBS="$LIBS -lgdi32 -lwinmm -lwsock32"
MOZ_JS_LIBS='-L$(LIBXUL_DIST)/lib -ljs$(MOZ_BITS)$(VERSION_NUMBER)'
MOZ_JS_LIBS='-L$(LIBXUL_DIST)/lib -lmozjs'
MOZ_FIX_LINK_PATHS=
DYNAMIC_XPCOM_LIBS='-L$(LIBXUL_DIST)/lib -lxpcom -lxpcom_core'
XPCOM_FROZEN_LDOPTS='-L$(LIBXUL_DIST)/lib -lxpcom'
@ -2112,6 +2132,9 @@ case "$target" in
HOST_CC='$(CC)'
HOST_CXX='$(CXX)'
HOST_LD='$(LD)'
if test "$AS_BIN"; then
AS="$(basename "$AS_BIN")"
fi
AR='lib -NOLOGO -OUT:"$@"'
AR_FLAGS=
RANLIB='echo not_ranlib'
@ -2121,6 +2144,7 @@ case "$target" in
UNZIP=unzip
DOXYGEN=:
GARBAGE='$(OBJDIR)/vc20.pdb $(OBJDIR)/vc40.pdb'
ASM_SUFFIX=asm
OBJ_SUFFIX=obj
LIB_SUFFIX=lib
DLL_PREFIX=
@ -2141,14 +2165,14 @@ case "$target" in
MOZ_DEBUG_LDFLAGS='-DEBUG -DEBUGTYPE:CV'
WARNINGS_AS_ERRORS='-WX'
MOZ_OPTIMIZE_FLAGS='-O1'
MOZ_JS_LIBS='$(LIBXUL_DIST)/lib/js$(MOZ_BITS)$(VERSION_NUMBER).lib'
MOZ_JS_LIBS='$(LIBXUL_DIST)/lib/mozjs.lib'
MOZ_FIX_LINK_PATHS=
DYNAMIC_XPCOM_LIBS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xpcom_core.lib'
XPCOM_FROZEN_LDOPTS='$(LIBXUL_DIST)/lib/xpcom.lib'
LIBXUL_LIBS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xul.lib'
MOZ_COMPONENT_NSPR_LIBS='$(NSPR_LIBS)'
if test $_MSC_VER -ge 1400; then
LDFLAGS="$LDFLAGS -NXCOMPAT -SAFESEH"
LDFLAGS="$LDFLAGS -NXCOMPAT"
dnl For profile-guided optimization
PROFILE_GEN_CFLAGS="-GL"
PROFILE_GEN_LDFLAGS="-LTCG:PGINSTRUMENT"
@ -2308,7 +2332,7 @@ case "$target" in
;;
*)
AC_CHECK_HEADERS(mmintrin.h oleacc.idl)
AC_CHECK_HEADERS(oleacc.idl)
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
@ -2319,6 +2343,14 @@ case "$target" in
case "$target" in
i*86-*)
if test "$HAVE_64BIT_OS"; then
AC_MSG_ERROR([You are targeting i386 but using the 64-bit compiler.])
fi
if test $_MSC_VER -ge 1400; then
LDFLAGS="$LDFLAGS -SAFESEH"
fi
AC_CHECK_HEADERS(mmintrin.h)
AC_DEFINE(_X86_)
;;
alpha-*)
@ -2327,10 +2359,17 @@ case "$target" in
mips-*)
AC_DEFINE(_MIPS_)
;;
x86_64-*)
AC_DEFINE(_AMD64_)
;;
*)
AC_DEFINE(_CPU_ARCH_NOT_DEFINED)
;;
esac
if test "$HAVE_64BIT_OS"; then
AC_DEFINE(_WIN64)
fi
;;
*-netbsd*)
@ -3150,8 +3189,7 @@ case $target in
esac
dnl ========================================================
dnl Check whether we can compile code for Core Text and
dnl Cocoa printing
dnl Check whether we can compile code for Core Text
dnl (Mac OS X 10.5 or later)
dnl ========================================================
case "$target" in
@ -3159,9 +3197,9 @@ case "$target" in
AC_MSG_CHECKING([for Core Text])
AC_TRY_COMPILE([#include <ApplicationServices/ApplicationServices.h>],
[CTLineRef lineRef;],
ac_cv_have_leopard="yes",
ac_cv_have_leopard="no")
AC_MSG_RESULT([$ac_cv_have_leopard])
ac_cv_have_core_text="yes",
ac_cv_have_core_text="no")
AC_MSG_RESULT([$ac_cv_have_core_text])
MOZ_CORETEXT=1
@ -3171,30 +3209,15 @@ case "$target" in
MOZ_CORETEXT=1)
if test -n "$MOZ_CORETEXT"; then
if test "$ac_cv_have_leopard" = "no"; then
if test "$ac_cv_have_core_text" = "no"; then
AC_MSG_ERROR([--enable-coretext requires MacOS SDK 10.5 or newer])
fi
AC_DEFINE(MOZ_CORETEXT)
fi
MOZ_COCOA_PRINTING=1
MOZ_ARG_DISABLE_BOOL(cocoa-printing,
[ --disable-cocoa-printing
Use a Carbon print dialog instead of a Cocoa one],
MOZ_COCOA_PRINTING=,
MOZ_COCOA_PRINTING=1)
if test -n "$MOZ_COCOA_PRINTING"; then
if test "$ac_cv_have_leopard" = "no"; then
AC_MSG_ERROR([--enable-cocoa-printing requires MacOS SDK 10.5 or newer])
fi
AC_DEFINE(MOZ_COCOA_PRINTING)
fi
;;
esac
AC_SUBST(MOZ_COCOA_PRINTING)
AC_SUBST(MOZ_CORETEXT)
XLDFLAGS="$X_LIBS"
XLIBS="$X_EXTRA_LIBS"
@ -6511,13 +6534,22 @@ if test "$MOZ_MEMORY"; then
WIN32_CRT_SRC_DIR="$VCINSTALLDIR\crt\src"
fi
fi
dnl cpu check
case "${target_cpu}" in
i*86)
_WIN32_CRT_CPU=intel
;;
*)
AC_MSG_ERROR([--enable-jemalloc not supported on ${target}])
;;
esac
if test ! -d "$WIN32_CRT_SRC_DIR"; then
AC_MSG_ERROR([Invalid Win32 CRT source directory: ${WIN32_CRT_SRC_DIR}])
fi
WIN32_CRT_SRC_DIR=`cd "$WIN32_CRT_SRC_DIR" && pwd -W`
_objdir_win=`pwd -W`
WIN32_CUSTOM_CRT_DIR="$_objdir_win/memory/jemalloc/crtsrc/build/intel"
WIN32_CUSTOM_CRT_DIR="$_objdir_win/memory/jemalloc/crtsrc/build/$_WIN32_CRT_CPU"
MOZ_MEMORY_LDFLAGS="-MANIFEST:NO -LIBPATH:\"$WIN32_CUSTOM_CRT_DIR\" -NODEFAULTLIB:msvcrt -NODEFAULTLIB:msvcrtd -NODEFAULTLIB:msvcprt -NODEFAULTLIB:msvcprtd -DEFAULTLIB:mozcrt19 -DEFAULTLIB:mozcpp19"
dnl Also pass this to NSPR/NSS
DLLFLAGS="$DLLFLAGS $MOZ_MEMORY_LDFLAGS"

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

@ -93,9 +93,11 @@ XPIDLSRCS = \
nsIContentPolicy.idl \
nsIDocumentEncoder.idl \
nsIDOMFile.idl \
nsIDOMFileRequest.idl \
nsIDOMFileInternal.idl \
nsIDOMFileList.idl \
nsIDOMFileException.idl \
nsIDOMFileError.idl \
nsIDOMParser.idl \
nsIDOMSerializer.idl \
nsISelection2.idl \

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

@ -43,6 +43,7 @@
#include "nsIDOMFile.h"
#include "nsIDOMFileInternal.h"
#include "nsIDOMFileList.h"
#include "nsIDOMFileError.h"
#include "nsIInputStream.h"
#include "nsCOMArray.h"
#include "nsCOMPtr.h"
@ -117,4 +118,16 @@ private:
nsCOMArray<nsIDOMFile> mFiles;
};
class nsDOMFileError : public nsIDOMFileError
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMFILEERROR
nsDOMFileError(PRUint16 aErrorCode) : mCode(aErrorCode) {}
private:
PRUint16 mCode;
};
#endif

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

@ -37,16 +37,20 @@
#include "domstubs.idl"
[scriptable, uuid(4a17d83b-424f-43f3-8a7c-430f406921be)]
interface nsIDOMFileError;
[scriptable, uuid(0845E8AE-56BD-4F0E-962A-3B3E92638A0B)]
interface nsIDOMFile : nsISupports
{
//fileName and fileSize are now deprecated attributes
readonly attribute DOMString fileName;
readonly attribute unsigned long long fileSize;
DOMString getAsText(in DOMString encoding);
// raises(FileException) on retrieval
DOMString getAsDataURL();
// raises(FileException) on retrieval
DOMString getAsBinary();
// raises(FileException) on retrieval
readonly attribute DOMString name;
readonly attribute unsigned long long size;
readonly attribute DOMString mediaType;
DOMString getAsText(in DOMString encoding); // raises(FileException) on retrieval
DOMString getAsDataURL(); // raises(FileException) on retrieval
DOMString getAsBinary(); // raises(FileException) on retrieval
};

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

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
@ -15,16 +15,15 @@
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2000
* Mozilla Corporation
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Conrad Carlen <ccarlen@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of 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"),
* 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
@ -36,26 +35,18 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsPrintSessionX_h_
#define nsPrintSessionX_h_
#include "domstubs.idl"
#include "nsPrintSession.h"
#include "nsIPrintSessionX.h"
class nsPrintSessionX : public nsPrintSession,
public nsIPrintSessionX
[scriptable, uuid(4BDAFB64-15E2-49C1-A090-4315A7884A56)]
interface nsIDOMFileError : nsISupports
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIPRINTSESSIONX
//File error codes
const unsigned short NOT_FOUND_ERR = 8;
const unsigned short NOT_READABLE_ERR = 24;
const unsigned short SECURITY_ERR = 18;
const unsigned short ABORT_ERR = 25;
const unsigned short ENCODING_ERR = 26;
nsPrintSessionX();
virtual ~nsPrintSessionX();
nsresult Init();
protected:
PMPrintSession mSession;
readonly attribute unsigned short code;
};
#endif // nsPrintSessionX_h_

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

@ -1,4 +1,4 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
@ -12,8 +12,7 @@
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
@ -21,7 +20,6 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Daniel Veditz <dveditz@netscape.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
@ -37,24 +35,37 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef _zipfile_h
#define _zipfile_h
/*
* This module implements a simple archive extractor for the PKZIP format.
*
* All functions return a status/error code, and have an opaque hZip argument
* that represents an open archive.
*
* Currently only compression mode 8 (or none) is supported.
*/
#include "nsIDOMEventTarget.idl"
#define ZIP_OK NS_OK
#define ZIP_ERR_MEMORY NS_ERROR_OUT_OF_MEMORY
#define ZIP_ERR_DISK NS_ERROR_FILE_DISK_FULL
#define ZIP_ERR_CORRUPT NS_ERROR_FILE_CORRUPTED
#define ZIP_ERR_PARAM NS_ERROR_ILLEGAL_VALUE
#define ZIP_ERR_FNF NS_ERROR_FILE_TARGET_DOES_NOT_EXIST
#define ZIP_ERR_UNSUPPORTED NS_ERROR_NOT_IMPLEMENTED
#define ZIP_ERR_GENERAL NS_ERROR_FAILURE
interface nsIDOMEventListener;
interface nsIDOMFile;
interface nsIDOMFileError;
#endif /* _zipfile_h */
[scriptable, uuid(074FEC26-7FAB-4E05-9E60-EC49E148F5EF)]
interface nsIDOMFileRequest : nsISupports
{
void readAsBinaryString(in nsIDOMFile filedata);
void readAsText(in nsIDOMFile filedata, [optional] in DOMString encoding);
void readAsDataURL(in nsIDOMFile file);
void abort();
const unsigned short INITIAL = 0;
const unsigned short LOADING = 1;
const unsigned short DONE = 2;
readonly attribute unsigned short readyState;
readonly attribute DOMString response;
readonly attribute nsIDOMFileError error;
// event handler attributes
attribute nsIDOMEventListener onloadend;
};
%{ C++
#define NS_FILEREQUEST_CID \
{0x06aa7c21, 0xfe05, 0x4cf2, \
{0xb1, 0xc4, 0x0c, 0x71, 0x26, 0xa4, 0xf7, 0x13}}
#define NS_FILEREQUEST_CONTRACTID \
"@mozilla.org/files/filerequest;1"
%}

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

@ -84,6 +84,7 @@ CPPSRCS = \
nsDOMAttributeMap.cpp \
nsDOMDocumentType.cpp \
nsDOMFile.cpp \
nsDOMFileRequest.cpp \
nsDOMLists.cpp \
nsDOMParser.cpp \
nsDOMSerializer.cpp \

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

@ -375,13 +375,6 @@ NS_INTERFACE_MAP_END_INHERITING(nsBaseContentList)
NS_IMPL_ADDREF_INHERITED(nsContentList, nsBaseContentList)
NS_IMPL_RELEASE_INHERITED(nsContentList, nsBaseContentList)
nsISupports *
nsContentList::GetParentObject()
{
return mRootNode;
}
PRUint32
nsContentList::Length(PRBool aDoFlush)
{

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

@ -269,7 +269,7 @@ public:
virtual nsISupports* GetNamedItem(const nsAString& aName, nsresult* aResult);
// nsContentList public methods
NS_HIDDEN_(nsISupports*) GetParentObject();
NS_HIDDEN_(nsINode*) GetParentObject() { return mRootNode; }
NS_HIDDEN_(PRUint32) Length(PRBool aDoFlush);
NS_HIDDEN_(nsIContent*) Item(PRUint32 aIndex, PRBool aDoFlush);
NS_HIDDEN_(nsIContent*) NamedItem(const nsAString& aName, PRBool aDoFlush);

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

@ -357,11 +357,6 @@ nsContentSink::ScriptAvailable(nsresult aResult,
// Check if this is the element we were waiting for
if (count == 0 || aElement != mScriptElements[count - 1]) {
if (mDidGetReadyToCallDidBuildModelCall &&
!mScriptLoader->HasPendingOrCurrentScripts() &&
mParser && mParser->IsParserEnabled()) {
ContinueInterruptedParsingAsync();
}
return NS_OK;
}
@ -404,11 +399,6 @@ nsContentSink::ScriptEvaluated(nsresult aResult,
// Check if this is the element we were waiting for
PRInt32 count = mScriptElements.Count();
if (count == 0 || aElement != mScriptElements[count - 1]) {
if (mDidGetReadyToCallDidBuildModelCall &&
!mScriptLoader->HasPendingOrCurrentScripts() &&
mParser && mParser->IsParserEnabled()) {
ContinueInterruptedParsingAsync();
}
return NS_OK;
}
@ -1642,8 +1632,16 @@ nsContentSink::EndUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType)
}
void
nsContentSink::DidBuildModelImpl(void)
nsContentSink::DidBuildModelImpl(PRBool aTerminated)
{
if (mDocument && !aTerminated) {
mDocument->SetReadyStateInternal(nsIDocument::READYSTATE_INTERACTIVE);
}
if (mScriptLoader) {
mScriptLoader->ParsingComplete(aTerminated);
}
if (!mDocument->HaveFiredDOMTitleChange()) {
mDocument->NotifyPossibleTitleChange(PR_FALSE);
}
@ -1768,26 +1766,6 @@ nsContentSink::ContinueInterruptedParsingAsync()
NS_DispatchToCurrentThread(ev);
}
PRBool
nsContentSink::ReadyToCallDidBuildModelImpl(PRBool aTerminated)
{
if (!mDidGetReadyToCallDidBuildModelCall) {
if (mDocument && !aTerminated) {
mDocument->SetReadyStateInternal(nsIDocument::READYSTATE_INTERACTIVE);
}
if (mScriptLoader) {
mScriptLoader->ParsingComplete(aTerminated);
}
}
mDidGetReadyToCallDidBuildModelCall = PR_TRUE;
// If we're terminated we always want to call DidBuildModel.
return aTerminated || !mScriptLoader ||
!mScriptLoader->HasPendingOrCurrentScripts();
}
// URIs: action, href, src, longdesc, usemap, cite
PRBool
IsAttrURI(nsIAtom *aName)

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

@ -133,8 +133,7 @@ class nsContentSink : public nsICSSLoaderObserver,
NS_HIDDEN_(nsresult) WillResumeImpl(void);
NS_HIDDEN_(nsresult) DidProcessATokenImpl(void);
NS_HIDDEN_(void) WillBuildModelImpl(void);
NS_HIDDEN_(void) DidBuildModelImpl(void);
NS_HIDDEN_(PRBool) ReadyToCallDidBuildModelImpl(PRBool aTerminated);
NS_HIDDEN_(void) DidBuildModelImpl(PRBool aTerminated);
NS_HIDDEN_(void) DropParserAndPerfHint(void);
PRBool IsScriptExecutingImpl();
@ -338,8 +337,6 @@ protected:
PRUint8 mDeferredLayoutStart : 1;
// If true, we deferred notifications until sheets load
PRUint8 mDeferredFlushTags : 1;
// If true, we did get a ReadyToCallDidBuildModel call
PRUint8 mDidGetReadyToCallDidBuildModelCall : 1;
// If false, we're not ourselves a document observer; that means we
// shouldn't be performing any more content model notifications,
// since we're not longer updating our child counts.

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

@ -93,11 +93,23 @@ DOMFileResult(nsresult rv)
NS_IMETHODIMP
nsDOMFile::GetFileName(nsAString &aFileName)
{
return mFile->GetLeafName(aFileName);
return GetName(aFileName);
}
NS_IMETHODIMP
nsDOMFile::GetFileSize(PRUint64 *aFileSize)
{
return GetSize(aFileSize);
}
NS_IMETHODIMP
nsDOMFile::GetName(nsAString &aFileName)
{
return mFile->GetLeafName(aFileName);
}
NS_IMETHODIMP
nsDOMFile::GetSize(PRUint64 *aFileSize)
{
PRInt64 fileSize;
nsresult rv = mFile->GetFileSize(&fileSize);
@ -112,6 +124,30 @@ nsDOMFile::GetFileSize(PRUint64 *aFileSize)
return NS_OK;
}
NS_IMETHODIMP
nsDOMFile::GetMediaType(nsAString &aMediaType)
{
if (!mContentType.Length()) {
nsresult rv;
nsCOMPtr<nsIMIMEService> mimeService =
do_GetService(NS_MIMESERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString mediaType;
rv = mimeService->GetTypeFromFile(mFile, mediaType);
if (NS_FAILED(rv)) {
SetDOMStringToNull(aMediaType);
return NS_OK;
}
AppendUTF8toUTF16(mediaType, mContentType);
}
aMediaType = mContentType;
return NS_OK;
}
NS_IMETHODIMP
nsDOMFile::GetAsText(const nsAString &aCharset, nsAString &aResult)
{
@ -405,3 +441,21 @@ nsDOMFileList::Item(PRUint32 aIndex, nsIDOMFile **aFile)
return NS_OK;
}
// nsDOMFileError implementation
NS_INTERFACE_MAP_BEGIN(nsDOMFileError)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFileError)
NS_INTERFACE_MAP_ENTRY(nsIDOMFileError)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(FileError)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(nsDOMFileError)
NS_IMPL_RELEASE(nsDOMFileError)
NS_IMETHODIMP
nsDOMFileError::GetCode(PRUint16* aCode)
{
*aCode = mCode;
return NS_OK;
}

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

@ -0,0 +1,737 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** 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 mozila.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsDOMFileRequest.h"
#include "nsContentCID.h"
#include "nsContentUtils.h"
#include "nsDOMClassInfo.h"
#include "nsDOMFile.h"
#include "nsDOMError.h"
#include "nsICharsetAlias.h"
#include "nsICharsetDetector.h"
#include "nsICharsetConverterManager.h"
#include "nsIConverterInputStream.h"
#include "nsIFile.h"
#include "nsIFileStreams.h"
#include "nsIInputStream.h"
#include "nsIMIMEService.h"
#include "nsIPlatformCharset.h"
#include "nsIUnicharInputStream.h"
#include "nsIUnicodeDecoder.h"
#include "nsNetCID.h"
#include "nsNetUtil.h"
#include "plbase64.h"
#include "prmem.h"
#include "nsLayoutCID.h"
#include "nsXPIDLString.h"
#include "nsReadableUtils.h"
#include "nsIURI.h"
#include "nsStreamUtils.h"
#include "nsXPCOM.h"
#include "nsIPrivateDOMEvent.h"
#include "nsIDOMEventListener.h"
#include "nsIJSContextStack.h"
#include "nsJSEnvironment.h"
#include "nsIScriptGlobalObject.h"
#include "nsIDOMClassInfo.h"
#include "nsIDOMFileInternal.h"
#include "nsCExternalHandlerService.h"
#include "nsIStreamConverterService.h"
#include "nsEventDispatcher.h"
#include "nsCycleCollectionParticipant.h"
#include "nsLayoutStatics.h"
#include "nsIScriptObjectPrincipal.h"
#define LOAD_STR "load"
#define ERROR_STR "error"
#define ABORT_STR "abort"
#define LOADSTART_STR "loadstart"
#define PROGRESS_STR "progress"
#define UPLOADPROGRESS_STR "uploadprogress"
#define LOADEND_STR "loadend"
#define NS_PROGRESS_EVENT_INTERVAL 50
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMFileRequest)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMFileRequest,
nsXHREventTarget)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnLoadEndListener)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFile)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mProgressNotifier)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPrincipal)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChannel)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMFileRequest,
nsXHREventTarget)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnLoadEndListener)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFile)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mProgressNotifier)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mPrincipal)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChannel)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMFileRequest)
NS_INTERFACE_MAP_ENTRY(nsIDOMFileRequest)
NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
NS_INTERFACE_MAP_ENTRY(nsICharsetDetectionObserver)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(FileRequest)
NS_INTERFACE_MAP_END_INHERITING(nsXHREventTarget)
NS_IMPL_ADDREF_INHERITED(nsDOMFileRequest, nsXHREventTarget)
NS_IMPL_RELEASE_INHERITED(nsDOMFileRequest, nsXHREventTarget)
static const PRUint32 FILE_AS_BINARY = 1;
static const PRUint32 FILE_AS_TEXT = 2;
static const PRUint32 FILE_AS_DATAURL = 3;
NS_IMETHODIMP
nsDOMFileRequest::GetOnloadend(nsIDOMEventListener** aOnloadend)
{
return GetInnerEventListener(mOnLoadEndListener, aOnloadend);
}
NS_IMETHODIMP
nsDOMFileRequest::SetOnloadend(nsIDOMEventListener* aOnloadend)
{
return RemoveAddEventListener(NS_LITERAL_STRING(LOADEND_STR),
mOnLoadEndListener, aOnloadend);
}
//nsICharsetDetectionObserver
NS_IMETHODIMP
nsDOMFileRequest::Notify(const char *aCharset, nsDetectionConfident aConf)
{
CopyASCIItoUTF16(aCharset, mCharset);
return NS_OK;
}
//nsDOMFileRequest constructors/initializers
nsDOMFileRequest::nsDOMFileRequest()
: mFileData(nsnull), mReadCount(0),
mDataLen(0), mDataFormat(0),
mReadyState(nsIDOMFileRequest::INITIAL),
mProgressEventWasDelayed(PR_FALSE),
mTimerIsActive(PR_FALSE),
mReadTotal(0), mReadTransferred(0),
mReadComplete(PR_TRUE)
{
nsLayoutStatics::AddRef();
}
nsDOMFileRequest::~nsDOMFileRequest()
{
if (mListenerManager)
mListenerManager->Disconnect();
nsLayoutStatics::Release();
}
nsresult
nsDOMFileRequest::Init()
{
// Set the original mScriptContext and mPrincipal, if available.
// Get JSContext from stack.
nsCOMPtr<nsIJSContextStack> stack =
do_GetService("@mozilla.org/js/xpc/ContextStack;1");
if (!stack) {
return NS_OK;
}
JSContext *cx;
if (NS_FAILED(stack->Peek(&cx)) || !cx) {
return NS_OK;
}
nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
nsCOMPtr<nsIPrincipal> subjectPrincipal;
if (secMan) {
secMan->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
}
NS_ENSURE_STATE(subjectPrincipal);
mPrincipal = subjectPrincipal;
nsIScriptContext* context = GetScriptContextFromJSContext(cx);
if (context) {
mScriptContext = context;
nsCOMPtr<nsPIDOMWindow> window =
do_QueryInterface(context->GetGlobalObject());
if (window) {
mOwner = window->GetCurrentInnerWindow();
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMFileRequest::Initialize(nsISupports* aOwner, JSContext* cx, JSObject* obj,
PRUint32 argc, jsval *argv)
{
mOwner = do_QueryInterface(aOwner);
if (!mOwner) {
NS_WARNING("Unexpected nsIJSNativeInitializer owner");
return NS_OK;
}
// This object is bound to a |window|,
// so reset the principal and script context.
nsCOMPtr<nsIScriptObjectPrincipal> scriptPrincipal = do_QueryInterface(aOwner);
NS_ENSURE_STATE(scriptPrincipal);
mPrincipal = scriptPrincipal->GetPrincipal();
nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aOwner);
NS_ENSURE_STATE(sgo);
mScriptContext = sgo->GetContext();
NS_ENSURE_STATE(mScriptContext);
return NS_OK;
}
// nsIInterfaceRequestor
NS_IMETHODIMP
nsDOMFileRequest::GetInterface(const nsIID & aIID, void **aResult)
{
return QueryInterface(aIID, aResult);
}
// nsIDOMFileRequest
NS_IMETHODIMP
nsDOMFileRequest::GetReadyState(PRUint16 *aReadyState)
{
*aReadyState = mReadyState;
return NS_OK;
}
NS_IMETHODIMP
nsDOMFileRequest::GetResponse(nsAString& aResponse)
{
aResponse = mResponse;
return NS_OK;
}
NS_IMETHODIMP
nsDOMFileRequest::GetError(nsIDOMFileError** aError)
{
NS_IF_ADDREF(*aError = mError);
return NS_OK;
}
NS_IMETHODIMP
nsDOMFileRequest::ReadAsBinaryString(nsIDOMFile* aFile)
{
return ReadFileContent(aFile, EmptyString(), FILE_AS_BINARY);
}
NS_IMETHODIMP
nsDOMFileRequest::ReadAsText(nsIDOMFile* aFile,
const nsAString &aCharset)
{
return ReadFileContent(aFile, aCharset, FILE_AS_TEXT);
}
NS_IMETHODIMP
nsDOMFileRequest::ReadAsDataURL(nsIDOMFile* aFile)
{
return ReadFileContent(aFile, EmptyString(), FILE_AS_DATAURL);
}
NS_IMETHODIMP
nsDOMFileRequest::Abort()
{
if (mReadyState != nsIDOMFileRequest::LOADING)
return NS_OK;
//Clear progress and file data
mProgressEventWasDelayed = PR_FALSE;
mTimerIsActive = PR_FALSE;
if (mProgressNotifier) {
mProgressNotifier->Cancel();
}
mReadCount = 0;
mDataLen = 0;
//Revert status, response and readystate attributes
SetDOMStringToNull(mResponse);
mReadyState = nsIDOMFileRequest::DONE;
mError = new nsDOMFileError(nsIDOMFileError::ABORT_ERR);
//Non-null channel indicates a read is currently active
if (mChannel) {
//Cancel request requires an error status
mChannel->Cancel(NS_ERROR_FAILURE);
mChannel = nsnull;
}
mFile = nsnull;
//Clean up memory buffer
PR_Free(mFileData);
mFileData = nsnull;
//Dispatch the abort event
DispatchProgressEvent(NS_LITERAL_STRING(ABORT_STR));
DispatchProgressEvent(NS_LITERAL_STRING(LOADEND_STR));
mReadyState = nsIDOMFileRequest::INITIAL;
return NS_OK;
}
// nsITimerCallback
NS_IMETHODIMP
nsDOMFileRequest::Notify(nsITimer* aTimer)
{
mTimerIsActive = PR_FALSE;
if (mProgressEventWasDelayed) {
DispatchProgressEvent(NS_LITERAL_STRING(PROGRESS_STR));
StartProgressEventTimer();
}
return NS_OK;
}
void
nsDOMFileRequest::StartProgressEventTimer()
{
if (!mProgressNotifier) {
mProgressNotifier = do_CreateInstance(NS_TIMER_CONTRACTID);
}
if (mProgressNotifier) {
mProgressEventWasDelayed = PR_FALSE;
mTimerIsActive = PR_TRUE;
mProgressNotifier->Cancel();
mProgressNotifier->InitWithCallback(this, NS_PROGRESS_EVENT_INTERVAL,
nsITimer::TYPE_ONE_SHOT);
}
}
// nsIStreamListener
NS_IMETHODIMP
nsDOMFileRequest::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
{
return NS_OK;
}
NS_IMETHODIMP
nsDOMFileRequest::OnDataAvailable(nsIRequest *aRequest,
nsISupports *aContext,
nsIInputStream *aInputStream,
PRUint32 aOffset,
PRUint32 aCount)
{
//Update memory buffer to reflect the contents of the file
mFileData = (char *)PR_Realloc(mFileData, aOffset + aCount);
NS_ENSURE_TRUE(mFileData, NS_ERROR_OUT_OF_MEMORY);
aInputStream->Read(mFileData + aOffset, aCount, &mReadCount);
mDataLen += aCount;
mReadTransferred = mDataLen;
//Continuously update our binary string as data comes in
if (mDataFormat == FILE_AS_BINARY) {
PRUint32 oldLen = mResponse.Length();
PRUint32 newLen = oldLen + aCount;
PRUnichar *buf;
if (mResponse.GetMutableData(&buf, newLen) != newLen) {
return NS_ERROR_OUT_OF_MEMORY;
}
PRUnichar *bufEnd = buf + newLen;
buf += oldLen;
char *source = mFileData + aOffset;
while (buf < bufEnd) {
*buf = *source;
++buf;
++source;
}
}
//Notify the timer is the appropriate timeframe has passed
if (mTimerIsActive) {
mProgressEventWasDelayed = PR_TRUE;
}
else {
DispatchProgressEvent(NS_LITERAL_STRING(PROGRESS_STR));
StartProgressEventTimer();
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMFileRequest::OnStopRequest(nsIRequest *aRequest,
nsISupports *aContext,
nsresult aStatus)
{
//If we're here as a result of a call from Abort(),
//simply ignore the request.
if (aRequest != mChannel)
return NS_OK;
//Cancel the progress event timer
mProgressEventWasDelayed = PR_FALSE;
mTimerIsActive = PR_FALSE;
if (mProgressNotifier) {
mProgressNotifier->Cancel();
}
//FileRequest must be in DONE stage after a load
mReadyState = nsIDOMFileRequest::DONE;
//Set the status field as appropriate
if (NS_FAILED(aStatus)) {
DispatchError(aStatus);
return NS_OK;
}
nsresult rv;
switch (mDataFormat) {
case FILE_AS_BINARY:
break; //Already accumulated mResponse
case FILE_AS_TEXT:
rv = GetAsText(mCharset, mFileData, mDataLen, mResponse);
break;
case FILE_AS_DATAURL:
rv = GetAsDataURL(mFile, mFileData, mDataLen, mResponse);
break;
default:
return NS_ERROR_FAILURE;
}
//Dispatch load event to signify end of a successful load
DispatchProgressEvent(NS_LITERAL_STRING(LOAD_STR));
DispatchProgressEvent(NS_LITERAL_STRING(LOADEND_STR));
return rv;
}
// Helper methods
nsresult
nsDOMFileRequest::ReadFileContent(nsIDOMFile* aFile,
const nsAString &aCharset,
PRUint32 aDataFormat)
{
NS_ENSURE_TRUE(aFile, NS_ERROR_NULL_POINTER);
//Implicit abort to clear any other activity going on
Abort();
mDataFormat = aDataFormat;
mCharset = aCharset;
mError = nsnull;
//Obtain the nsDOMFile's underlying nsIFile
nsresult rv;
nsCOMPtr<nsIDOMFileInternal> domFile(do_QueryInterface(aFile));
rv = domFile->GetInternalFile(getter_AddRefs(mFile));
NS_ENSURE_SUCCESS(rv, rv);
//Establish a channel with our file
nsCOMPtr<nsIURI> uri;
rv = NS_NewFileURI(getter_AddRefs(uri), mFile);
NS_ENSURE_SUCCESS(rv, rv);
rv = NS_NewChannel(getter_AddRefs(mChannel), uri);
NS_ENSURE_SUCCESS(rv, rv);
//Obtain the total size of the file before reading
aFile->GetSize(&mReadTotal);
rv = mChannel->AsyncOpen(this, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
//FileRequest should be in loading state here
mReadyState = nsIDOMFileRequest::LOADING;
DispatchProgressEvent(NS_LITERAL_STRING(LOADSTART_STR));
return NS_OK;
}
void
nsDOMFileRequest::DispatchError(nsresult rv)
{
//Set the status attribute, and dispatch the error event
switch (rv) {
case NS_ERROR_FILE_NOT_FOUND:
mError = new nsDOMFileError(nsIDOMFileError::NOT_FOUND_ERR);
break;
case NS_ERROR_FILE_ACCESS_DENIED:
mError = new nsDOMFileError(nsIDOMFileError::SECURITY_ERR);
break;
default:
mError = new nsDOMFileError(nsIDOMFileError::NOT_READABLE_ERR);
break;
}
//Dispatch error event to signify load failure
DispatchProgressEvent(NS_LITERAL_STRING(ERROR_STR));
DispatchProgressEvent(NS_LITERAL_STRING(LOADEND_STR));
}
void
nsDOMFileRequest::DispatchProgressEvent(const nsAString& aType)
{
nsCOMPtr<nsIDOMEvent> event;
nsresult rv = nsEventDispatcher::CreateEvent(nsnull, nsnull,
NS_LITERAL_STRING("ProgressEvent"),
getter_AddRefs(event));
if (NS_FAILED(rv))
return;
nsCOMPtr<nsIPrivateDOMEvent> privevent(do_QueryInterface(event));
if (!privevent)
return;
privevent->SetTrusted(PR_TRUE);
nsCOMPtr<nsIDOMProgressEvent> progress = do_QueryInterface(event);
if (!progress)
return;
progress->InitProgressEvent(aType, PR_FALSE, PR_FALSE, mReadComplete,
mReadTransferred, (mReadTotal == LL_MAXUINT) ? 0 : mReadTotal);
this->DispatchDOMEvent(nsnull, event, nsnull, nsnull);
}
nsresult
nsDOMFileRequest::GetAsText(const nsAString &aCharset,
const char *aFileData,
PRUint32 aDataLen,
nsAString& aResult)
{
nsresult rv;
nsCAutoString charsetGuess;
if (!aCharset.IsEmpty()) {
CopyUTF16toUTF8(aCharset, charsetGuess);
} else {
rv = GuessCharset(aFileData, aDataLen, charsetGuess);
NS_ENSURE_SUCCESS(rv, rv);
}
nsCAutoString charset;
nsCOMPtr<nsICharsetAlias> alias = do_GetService(NS_CHARSETALIAS_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = alias->GetPreferred(charsetGuess, charset);
NS_ENSURE_SUCCESS(rv, rv);
rv = ConvertStream(aFileData, aDataLen, charset.get(), aResult);
return NS_OK;
}
nsresult
nsDOMFileRequest::GetAsDataURL(nsIFile *aFile,
const char *aFileData,
PRUint32 aDataLen,
nsAString& aResult)
{
aResult.AssignLiteral("data:");
nsresult rv;
nsCOMPtr<nsIMIMEService> mimeService =
do_GetService(NS_MIMESERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString contentType;
rv = mimeService->GetTypeFromFile(aFile, contentType);
if (NS_SUCCEEDED(rv)) {
AppendUTF8toUTF16(contentType, aResult);
} else {
aResult.AppendLiteral("application/octet-stream");
}
aResult.AppendLiteral(";base64,");
PRUint32 totalRead = 0;
do {
PRUint32 numEncode = 4096;
PRUint32 amtRemaining = aDataLen - totalRead;
if (numEncode > amtRemaining)
numEncode = amtRemaining;
//Unless this is the end of the file, encode in multiples of 3
if (numEncode > 3) {
PRUint32 leftOver = numEncode % 3;
numEncode -= leftOver;
}
//Out buffer should be at least 4/3rds the read buf, plus a terminator
char *base64 = PL_Base64Encode(aFileData + totalRead, numEncode, nsnull);
AppendASCIItoUTF16(nsDependentCString(base64), aResult);
PR_Free(base64);
totalRead += numEncode;
} while (aDataLen > totalRead);
return NS_OK;
}
nsresult
nsDOMFileRequest::ConvertStream(const char *aFileData,
PRUint32 aDataLen,
const char *aCharset,
nsAString &aResult)
{
nsresult rv;
nsCOMPtr<nsICharsetConverterManager> charsetConverter =
do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIUnicodeDecoder> unicodeDecoder;
rv = charsetConverter->GetUnicodeDecoder(aCharset, getter_AddRefs(unicodeDecoder));
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 destLength;
rv = unicodeDecoder->GetMaxLength(aFileData, aDataLen, &destLength);
NS_ENSURE_SUCCESS(rv, rv);
aResult.SetLength(destLength); //Make sure we have enough space for the conversion
destLength = aResult.Length();
PRInt32 srcLength = aDataLen;
rv = unicodeDecoder->Convert(aFileData, &srcLength, aResult.BeginWriting(), &destLength);
aResult.SetLength(destLength); //Trim down to the correct size
return rv;
}
nsresult
nsDOMFileRequest::GuessCharset(const char *aFileData,
PRUint32 aDataLen,
nsACString &aCharset)
{
// First try the universal charset detector
nsCOMPtr<nsICharsetDetector> detector
= do_CreateInstance(NS_CHARSET_DETECTOR_CONTRACTID_BASE
"universal_charset_detector");
if (!detector) {
// No universal charset detector, try the default charset detector
const nsAdoptingString& detectorName =
nsContentUtils::GetLocalizedStringPref("intl.charset.detector");
if (!detectorName.IsEmpty()) {
nsCAutoString detectorContractID;
detectorContractID.AssignLiteral(NS_CHARSET_DETECTOR_CONTRACTID_BASE);
AppendUTF16toUTF8(detectorName, detectorContractID);
detector = do_CreateInstance(detectorContractID.get());
}
}
nsresult rv;
if (detector) {
mCharset.Truncate();
detector->Init(this);
PRBool done;
rv = detector->DoIt(aFileData, aDataLen, &done);
NS_ENSURE_SUCCESS(rv, rv);
rv = detector->Done();
NS_ENSURE_SUCCESS(rv, rv);
CopyUTF16toUTF8(mCharset, aCharset);
} else {
// no charset detector available, check the BOM
unsigned char sniffBuf[4];
PRUint32 numRead = (aDataLen >= sizeof(sniffBuf) ? sizeof(sniffBuf) : aDataLen);
memcpy(sniffBuf, aFileData, numRead);
if (numRead >= 4 &&
sniffBuf[0] == 0x00 &&
sniffBuf[1] == 0x00 &&
sniffBuf[2] == 0xfe &&
sniffBuf[3] == 0xff) {
aCharset = "UTF-32BE";
} else if (numRead >= 4 &&
sniffBuf[0] == 0xff &&
sniffBuf[1] == 0xfe &&
sniffBuf[2] == 0x00 &&
sniffBuf[3] == 0x00) {
aCharset = "UTF-32LE";
} else if (numRead >= 2 &&
sniffBuf[0] == 0xfe &&
sniffBuf[1] == 0xff) {
aCharset = "UTF-16BE";
} else if (numRead >= 2 &&
sniffBuf[0] == 0xff &&
sniffBuf[1] == 0xfe) {
aCharset = "UTF-16LE";
} else if (numRead >= 3 &&
sniffBuf[0] == 0xef &&
sniffBuf[1] == 0xbb &&
sniffBuf[2] == 0xbf) {
aCharset = "UTF-8";
}
}
if (aCharset.IsEmpty()) {
// no charset detected, default to the system charset
nsCOMPtr<nsIPlatformCharset> platformCharset =
do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv)) {
rv = platformCharset->GetCharset(kPlatformCharsetSel_PlainTextInFile,
aCharset);
}
}
if (aCharset.IsEmpty()) {
// no sniffed or default charset, try UTF-8
aCharset.AssignLiteral("UTF-8");
}
return NS_OK;
}

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

@ -0,0 +1,147 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** 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 mozila.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsDOMFileRequest_h__
#define nsDOMFileRequest_h__
#include "nsISupportsUtils.h"
#include "nsString.h"
#include "nsIStreamListener.h"
#include "nsIScriptContext.h"
#include "nsIInterfaceRequestor.h"
#include "nsJSUtils.h"
#include "nsTArray.h"
#include "nsIJSNativeInitializer.h"
#include "prtime.h"
#include "nsITimer.h"
#include "nsDOMEventTargetHelper.h"
#include "nsICharsetDetector.h"
#include "nsICharsetDetectionObserver.h"
#include "nsIDOMFile.h"
#include "nsIDOMFileRequest.h"
#include "nsIDOMFileList.h"
#include "nsIDOMFileError.h"
#include "nsIInputStream.h"
#include "nsCOMPtr.h"
#include "nsIStreamLoader.h"
#include "nsIChannel.h"
#include "nsXMLHttpRequest.h"
class nsDOMFileRequest : public nsXHREventTarget,
public nsIDOMFileRequest,
public nsIStreamListener,
public nsIInterfaceRequestor,
public nsSupportsWeakReference,
public nsIJSNativeInitializer,
public nsITimerCallback,
public nsICharsetDetectionObserver
{
public:
nsDOMFileRequest();
virtual ~nsDOMFileRequest();
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIDOMFILEREQUEST
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDOMFileRequest, nsXHREventTarget)
NS_FORWARD_NSIXMLHTTPREQUESTEVENTTARGET(nsXHREventTarget::);
// nsIStreamListener
NS_DECL_NSISTREAMLISTENER
// nsIRequestObserver
NS_DECL_NSIREQUESTOBSERVER
// nsIInterfaceRequestor
NS_DECL_NSIINTERFACEREQUESTOR
// nsITimerCallback
NS_DECL_NSITIMERCALLBACK
// nsIJSNativeInitializer
NS_IMETHOD Initialize(nsISupports* aOwner, JSContext* cx, JSObject* obj,
PRUint32 argc, jsval* argv);
NS_FORWARD_NSIDOMEVENTTARGET(nsXHREventTarget::)
NS_FORWARD_NSIDOMNSEVENTTARGET(nsXHREventTarget::)
// nsICharsetDetectionObserver
NS_IMETHOD Notify(const char *aCharset, nsDetectionConfident aConf);
void DispatchProgressEvent(const nsAString& aType);
nsresult Init();
protected:
nsresult ReadFileContent(nsIDOMFile *aFile, const nsAString &aCharset, PRUint32 aDataFormat);
nsresult GetAsText(const nsAString &aCharset,
const char *aFileData, PRUint32 aDataLen, nsAString &aResult);
nsresult GetAsDataURL(nsIFile *aFile, const char *aFileData, PRUint32 aDataLen, nsAString &aResult);
nsresult GuessCharset(const char *aFileData, PRUint32 aDataLen, nsACString &aCharset);
nsresult ConvertStream(const char *aFileData, PRUint32 aDataLen, const char *aCharset, nsAString &aResult);
void DispatchError(nsresult rv);
void StartProgressEventTimer();
char *mFileData;
nsCOMPtr<nsIFile> mFile;
nsString mCharset;
PRUint32 mReadCount;
PRUint32 mDataLen;
PRUint32 mDataFormat;
nsString mResponse;
PRUint16 mReadyState;
PRBool mProgressEventWasDelayed;
PRBool mTimerIsActive;
nsCOMPtr<nsIDOMFileError> mError;
nsCOMPtr<nsITimer> mProgressNotifier;
nsCOMPtr<nsIPrincipal> mPrincipal;
nsCOMPtr<nsIChannel> mChannel;
PRUint64 mReadTotal;
PRUint64 mReadTransferred;
PRPackedBool mReadComplete;
nsRefPtr<nsDOMEventListenerWrapper> mOnLoadEndListener;
};
#endif

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

@ -2691,6 +2691,16 @@ nsGenericElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
document->ClearBoxObjectFor(this);
}
// Ensure that CSS transitions don't continue on an element at a
// different place in the tree (even if reinserted before next
// animation refresh).
// FIXME: Need a test for this.
if (HasFlag(NODE_HAS_PROPERTIES)) {
DeleteProperty(nsGkAtoms::transitionsOfBeforeProperty);
DeleteProperty(nsGkAtoms::transitionsOfAfterProperty);
DeleteProperty(nsGkAtoms::transitionsProperty);
}
// Unset this since that's what the old code effectively did.
UnsetFlags(NODE_FORCE_XBL_BINDINGS);

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

@ -117,7 +117,7 @@ public:
mNode = nsnull;
}
nsISupports* GetParentObject()
nsINode* GetParentObject()
{
return mNode;
}

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

@ -1674,6 +1674,9 @@ GK_ATOM(preTransformBBoxProperty, "PreTransformBBoxProperty") // nsRect*
GK_ATOM(rowUnpaginatedHeightProperty, "RowUnpaginatedHeightProperty") // nscoord*
GK_ATOM(tabWidthProperty, "TabWidthProperty") // nsTArray<TabSetting>* array of tab widths
GK_ATOM(tableBCProperty, "TableBCProperty") // table border collapsing info (e.g. damage area, table border widths)
GK_ATOM(transitionsProperty, "TransitionsProperty") // FrameTransitions*
GK_ATOM(transitionsOfBeforeProperty, "TransitionsOfBeforeProperty") // FrameTransitions*
GK_ATOM(transitionsOfAfterProperty, "TransitionsOfAfterProperty") // FrameTransitions*
GK_ATOM(usedMarginProperty, "UsedMarginProperty") // nsMargin*
GK_ATOM(usedPaddingProperty, "UsedPaddingProperty") // nsMargin*
GK_ATOM(viewProperty, "ViewProperty")

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

@ -464,8 +464,9 @@ nsNodeUtils::CloneNodeImpl(nsINode *aNode, PRBool aDeep, nsIDOMNode **aResult)
class AdoptFuncData {
public:
AdoptFuncData(nsIDOMElement *aElement, nsNodeInfoManager *aNewNodeInfoManager,
JSContext *aCx, JSObject *aOldScope, JSObject *aNewScope,
AdoptFuncData(nsGenericElement *aElement,
nsNodeInfoManager *aNewNodeInfoManager, JSContext *aCx,
JSObject *aOldScope, JSObject *aNewScope,
nsCOMArray<nsINode> &aNodesWithProperties)
: mElement(aElement),
mNewNodeInfoManager(aNewNodeInfoManager),
@ -476,7 +477,7 @@ public:
{
}
nsIDOMElement *mElement;
nsGenericElement *mElement;
nsNodeInfoManager *mNewNodeInfoManager;
JSContext *mCx;
JSObject *mOldScope;
@ -495,7 +496,7 @@ AdoptFunc(nsAttrHashKey::KeyType aKey, nsIDOMNode *aData, void* aUserArg)
// If we were passed an element we need to clone the attribute nodes and
// insert them into the element.
PRBool clone = data->mElement != nsnull;
nsCOMPtr<nsIDOMNode> node;
nsCOMPtr<nsINode> node;
nsresult rv = nsNodeUtils::CloneAndAdopt(attr, clone, PR_TRUE,
data->mNewNodeInfoManager,
data->mCx, data->mOldScope,
@ -520,14 +521,14 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, PRBool aClone, PRBool aDeep,
JSContext *aCx, JSObject *aOldScope,
JSObject *aNewScope,
nsCOMArray<nsINode> &aNodesWithProperties,
nsINode *aParent, nsIDOMNode **aResult)
nsINode *aParent, nsINode **aResult)
{
NS_PRECONDITION((!aClone && aNewNodeInfoManager) || !aCx,
"If cloning or not getting a new nodeinfo we shouldn't "
"rewrap");
NS_PRECONDITION(!aCx || (aOldScope && aNewScope), "Must have scopes");
NS_PRECONDITION(!aParent || !aNode->IsNodeOfType(nsINode::eDOCUMENT),
"Can't insert document nodes into a parent");
NS_PRECONDITION(!aParent || aNode->IsNodeOfType(nsINode::eCONTENT),
"Can't insert document or attribute nodes into a parent");
*aResult = nsnull;
@ -578,10 +579,8 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, PRBool aClone, PRBool aDeep,
if (aParent) {
// If we're cloning we need to insert the cloned children into the cloned
// parent.
nsCOMPtr<nsIContent> cloneContent = do_QueryInterface(clone, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = aParent->AppendChildTo(cloneContent, PR_FALSE);
rv = aParent->AppendChildTo(static_cast<nsIContent*>(clone.get()),
PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
}
else if (aDeep && clone->IsNodeOfType(nsINode::eDOCUMENT)) {
@ -644,16 +643,13 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, PRBool aClone, PRBool aDeep,
// aNode's attributes.
const nsDOMAttributeMap *map = elem->GetAttributeMap();
if (map) {
nsCOMPtr<nsIDOMElement> element;
if (aClone) {
// If we're cloning we need to insert the cloned attribute nodes into
// the cloned element.
element = do_QueryInterface(clone, &rv);
NS_ENSURE_SUCCESS(rv, rv);
}
AdoptFuncData data(element, nodeInfoManager, aCx, aOldScope,
aNewScope, aNodesWithProperties);
// If we're cloning we need to insert the cloned attribute nodes into the
// cloned element. We assume that the clone of an nsGenericElement is also
// an nsGenericElement.
nsGenericElement* elemClone =
aClone ? static_cast<nsGenericElement*>(clone.get()) : nsnull;
AdoptFuncData data(elemClone, nodeInfoManager, aCx, aOldScope, aNewScope,
aNodesWithProperties);
PRUint32 count = map->Enumerate(AdoptFunc, &data);
NS_ENSURE_TRUE(count == map->Count(), NS_ERROR_FAILURE);
@ -685,17 +681,17 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, PRBool aClone, PRBool aDeep,
// aNode's children.
PRUint32 i, length = aNode->GetChildCount();
for (i = 0; i < length; ++i) {
nsCOMPtr<nsIDOMNode> child;
nsCOMPtr<nsINode> child;
rv = CloneAndAdopt(aNode->GetChildAt(i), aClone, PR_TRUE, nodeInfoManager,
aCx, aOldScope, aNewScope, aNodesWithProperties,
clone, getter_AddRefs(child));
NS_ENSURE_SUCCESS(rv, rv);
if (isDeepDocumentClone) {
nsCOMPtr<nsIContent> content = do_QueryInterface(child);
if (content) {
static_cast<nsDocument*>(clone.get())->
RegisterNamedItems(content);
}
NS_ASSERTION(child->IsNodeOfType(nsINode::eCONTENT),
"A clone of a child of a node is not nsIContent?");
nsIContent* content = static_cast<nsIContent*>(child.get());
static_cast<nsDocument*>(clone.get())->RegisterNamedItems(content);
}
}
}
@ -729,7 +725,9 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, PRBool aClone, PRBool aDeep,
NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
}
return clone ? CallQueryInterface(clone, aResult) : NS_OK;
clone.forget(aResult);
return NS_OK;
}

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

@ -167,8 +167,7 @@ public:
nsIDOMNode **aResult)
{
return CloneAndAdopt(aNode, PR_TRUE, aDeep, aNewNodeInfoManager, nsnull,
nsnull, nsnull, aNodesWithProperties, nsnull,
aResult);
nsnull, nsnull, aNodesWithProperties, aResult);
}
/**
@ -199,7 +198,7 @@ public:
nsCOMPtr<nsIDOMNode> dummy;
return CloneAndAdopt(aNode, PR_FALSE, PR_TRUE, aNewNodeInfoManager, aCx,
aOldScope, aNewScope, aNodesWithProperties,
nsnull, getter_AddRefs(dummy));
getter_AddRefs(dummy));
}
/**
@ -312,8 +311,6 @@ private:
* descendants) with properties. If aClone is
* PR_TRUE every node will be followed by its
* clone.
* @param aParent If aClone is PR_TRUE the cloned node will be appended to
* aParent's children. May be null.
* @param aResult *aResult will contain the cloned node (if aClone is
* PR_TRUE).
*/
@ -322,7 +319,30 @@ private:
JSContext *aCx, JSObject *aOldScope,
JSObject *aNewScope,
nsCOMArray<nsINode> &aNodesWithProperties,
nsINode *aParent, nsIDOMNode **aResult);
nsIDOMNode **aResult)
{
nsCOMPtr<nsINode> clone;
nsresult rv = CloneAndAdopt(aNode, aClone, aDeep, aNewNodeInfoManager,
aCx, aOldScope, aNewScope, aNodesWithProperties,
nsnull, getter_AddRefs(clone));
NS_ENSURE_SUCCESS(rv, rv);
return clone ? CallQueryInterface(clone, aResult) : NS_OK;
}
/**
* See above for arguments that aren't described here.
*
* @param aParent If aClone is PR_TRUE the cloned node will be appended to
* aParent's children. May be null. If not null then aNode
* must be an nsIContent.
*/
static nsresult CloneAndAdopt(nsINode *aNode, PRBool aClone, PRBool aDeep,
nsNodeInfoManager *aNewNodeInfoManager,
JSContext *aCx, JSObject *aOldScope,
JSObject *aNewScope,
nsCOMArray<nsINode> &aNodesWithProperties,
nsINode *aParent, nsINode **aResult);
};
#endif // nsNodeUtils_h___

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

@ -143,6 +143,7 @@ _TEST_FILES = test_bug5141.html \
test_bug402150.html^headers^ \
test_bug401662.html \
test_bug403852.html \
test_fileapi.html \
test_bug403868.xml \
test_bug405182.html \
test_bug403841.html \
@ -154,6 +155,10 @@ _TEST_FILES = test_bug5141.html \
test_bug414796.html \
test_bug416317-1.html \
test_bug416317-2.html \
test_XHRSendData.html \
file_XHRSendData.sjs \
file_XHRSendData_doc.xml \
file_XHRSendData_doc.xml^headers^ \
file_bug416317.xhtml \
test_bug416383.html \
test_bug417255.html \
@ -238,6 +243,7 @@ _TEST_FILES = test_bug5141.html \
test_bug454326.html \
test_bug505783.html \
test_bug457746.html \
test_bug518104.html \
bug457746.sjs \
test_CrossSiteXHR.html \
file_CrossSiteXHR_inner.html \

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

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:svg="http://www.w3.org/2000/svg"
xml:lang="en" lang="en" dir="ltr" id="html" class="unitTest" title=":root selector">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>selectorTest</title>
<!-- (c) Disruptive Innovations 2008 -->
<style type="text/css">
@ -352,14 +352,14 @@
pass = false;
try {
root.querySelectorAll(null);
} catch(e){ pass = e.code == DOMException.SYNTAX_ERR; }
pass = root.querySelectorAll(null).length === 0;
} catch(e){ pass = false; }
assert( pass, type + ".querySelectorAll null" );
pass = false;
try {
root.querySelectorAll(undefined);
} catch(e){ pass = e.code == DOMException.SYNTAX_ERR; }
pass = root.querySelectorAll(undefined).length === 0;
} catch(e){ pass = false; }
assert( pass, type + ".querySelectorAll undefined" );
pass = false;
@ -369,7 +369,7 @@
} catch(e){ pass = true; }
assert( pass, type + ".querySelectorAll no value" );
var pass = false;
pass = false;
try {
root.querySelector("");
} catch(e){ pass = e.code == DOMException.SYNTAX_ERR; }
@ -377,14 +377,14 @@
pass = false;
try {
root.querySelector(null);
} catch(e){ pass = e.code == DOMException.SYNTAX_ERR; }
pass = root.querySelector(null) === null;
} catch(e){ pass = false; }
assert( pass, type + ".querySelector null" );
pass = false;
try {
root.querySelector(undefined);
} catch(e){ pass = e.code == DOMException.SYNTAX_ERR; }
pass = root.querySelector(undefined) === null;
} catch(e){ pass = false; }
assert( pass, type + ".querySelector undefined" );
pass = false;

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

@ -36,12 +36,21 @@ is(testDoc2.inputEncoding, null, "wrong encoding");
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var testData = "blahblahblahblahblahblahblaaaaaaaah. blah.";
testFileTxt = createFileWithDataExt(testData, ".txt");
testFilePng = createFileWithDataExt(testData, ".png");
testFileJpg = createFileWithDataExt(testData, ".jpg");
testFileGif = createFileWithDataExt(testData, ".gif");
testFileXml = createFileWithDataExt(testData, ".xml");
testFileUnknown = createFileWithDataExt(testData, "noext");
var extensions = [".txt",".png",".jpg",".gif",".xml", "noext"];
var fileTypes = ["text/plain", "image/png", "image/jpeg", "image/gif", "text/xml", null];
var testFiles = new Array;
var testDOMFiles = new Array;
extensions.forEach(
function (extension) {
var testFile = createFileWithDataExt(testData, extension);
testFiles.push(testFile);
var fileList = document.getElementById('fileList');
fileList.value = testFile.path;
testDOMFiles.push(fileList.files[0]);
}
);
function createFileWithDataExt(fileData, extension) {
var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties);
@ -52,10 +61,7 @@ function createFileWithDataExt(fileData, extension) {
outStream.write(fileData, fileData.length);
outStream.close();
var fileList = document.getElementById('fileList');
fileList.value = testFile.path;
return fileList.files[0];
return testFile;
}
tests = [{ body: null,
@ -135,42 +141,20 @@ tests = [{ body: null,
resBody: "<!-- doc 2 -->\n<res>text</res>",
resContentType: "foo/bar; charset=uTf-8",
},
{ body: testFileTxt,
resBody: testData,
resContentType: "text/plain",
resContentLength: testData.length,
},
{ body: testFilePng,
resBody: testData,
resContentType: "image/png",
resContentLength: testData.length,
},
{ body: testFileJpg,
resBody: testData,
resContentType: "image/jpeg",
resContentLength: testData.length,
},
{ body: testFileGif,
resBody: testData,
resContentType: "image/gif",
resContentLength: testData.length,
},
{ body: testFileXml,
resBody: testData,
resContentType: "text/xml",
resContentLength: testData.length,
},
{ body: testFileUnknown,
resBody: testData,
resContentType: "",
resContentLength: testData.length,
},
{ //will trigger a redirect test server-side
body: ("TEST_REDIRECT_STR&url=" + window.location.host + window.location.pathname),
redirect: true,
},
];
for (var i = 0; i < testDOMFiles.length; i++) {
tests.push({ body: testDOMFiles[i],
resBody: testData,
resContentType: fileTypes[i],
resContentLength: testData.length,
});
}
try {
for each(test in tests) {
xhr = new XMLHttpRequest;
@ -210,25 +194,15 @@ finally {
}
function cleanUpData() {
removeFileWithExt(".txt");
removeFileWithExt(".png");
removeFileWithExt(".jpg");
removeFileWithExt(".gif");
removeFileWithExt(".xml");
removeFileWithExt("noext");
testFiles.forEach(
function (testFile) {
try {
testFile.remove(false);
} catch (e) {}
}
);
}
function removeFileWithExt(extension)
{
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties);
var testFile = dirSvc.get("ProfD", Components.interfaces.nsIFile);
testFile.append("testfile" + extension);
testFile.remove(false);
}
</script>
</pre>
</body>

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

@ -37,7 +37,7 @@ onload = function () {
}
function done() {
is(res, "ABCDEFGHIJabcdef1M2g34hi", "scripts executed in the wrong order");
is(res, "AacBCDEFGeHIJfbd1M2g34hi", "scripts executed in the wrong order");
ok(!fHadExecuted, "Dynamic script executed too late");
SimpleTest.finish();
}

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

@ -36,7 +36,7 @@ onload = function () {
}
function done() {
is(res, "ABCDEFGHIJabcdef1M2g34hi", "scripts executed in the wrong order");
is(res, "AacBCDEFGeHIJfbd1M2g34hi", "scripts executed in the wrong order");
ok(!fHadExecuted, "Dynamic script executed too late");
SimpleTest.finish();
}

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

@ -33,7 +33,7 @@ fileList.value = testFile.path;
// Make sure the file is accessible with indexed notation
var domFile = fileList.files[0];
is(domFile.fileName, "prefs.js", "fileName should be prefs.js");
is(domFile.name, "prefs.js", "fileName should be prefs.js");
</script>
</pre>

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

@ -23,24 +23,9 @@ function writeIt(n) {
document.write("<span>" + n + "</span>");
}
var recur = 0;
function externalScript() {
if (++recur == 3) {
return;
}
base = (recur-1) * 4
writeIt(6 + base);
s = document.createElement("script");
s.src = "data:text/plain,writeIt(" + (8+base) + ");writeIt(" + (9+base) + ");externalScript();";
document.body.appendChild(s);
writeIt(7 + base);
}
function done() {
nodes = document.getElementsByTagName('span');
is(nodes.length, 13, "wrong length");
is(nodes.length, 3, "wrong length");
for (i = 0; i < nodes.length; ++i) {
is(nodes[i].textContent, i+1, "wrong order");
}
@ -55,10 +40,8 @@ writeIt(1);
</script>
<script defer>
writeIt(3);
</script>
<script>
writeIt(2);
</script>
<script defer src="data:text/plain,writeIt(4);writeIt(5);"></script>
<script defer src="data:text/plain,externalScript();"></script>
<script>
writeIt(3);
</script>

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

@ -0,0 +1,37 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=518104
-->
<head>
<title>Test for Bug 518104</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<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=518104">Mozilla Bug 518104</a>
<p id="display"></p>
<div id="content" style="display: none">
<iframe id='iframe' src="data:text/html,
<div></div><div></div>
<script defer src='data:application/javascript,document.write(%2522<p></p>%2522);parent.done();document.close();'></script>">
</iframe>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Bug 518104 **/
SimpleTest.waitForExplicitFinish();
function done() {
var iframe = document.getElementById("iframe");
var divs = iframe.contentWindow.document.getElementsByTagName("div").length;
is(divs, 0, "Div wasn't blown away.")
SimpleTest.finish();
}
</script>
</pre>
</body>
</html>

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

@ -0,0 +1,293 @@
<!DOCTYPE HTML>
<html>
<head>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=414796
-->
<title>Test for Bug 414796</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<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=414796">Mozilla Bug 414796</a>
<p id="display">
<input id="fileList" type="file"></input>
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
var testCounter = 0;
SimpleTest.waitForExplicitFinish();
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
// Write a test file > 8192 characters
var testData = "asdfblahqwer";
for (var i = 0; i < 10; i++) {
testData = testData + testData;
}
var testData2 = testData + "a";
var testData3 = testData + "as";
//Ensure we have different sizes of data for thoroughly testing data URI retrieval
is(testData.length % 3, 0, "Need to have data length % 3 == 0");
is(testData2.length % 3, 1, "Need to have data length % 3 == 1");
is(testData3.length % 3, 2, "Need to have data lenght % 3 == 2");
//Create UTF data that should be the same for UTF-16
var utf16Data = "\0a\0s\0d\0f\0b\0l\0a\0h\0q\0w\0e\0r";
for (var i = 0; i < 10; i++) {
utf16Data = utf16Data + utf16Data;
}
var utf16File = createFileWithData(utf16Data, "01");
//Create UTF data that should be the same for UTF-32
var utf32Data = "\0\0\0a\0\0\0s\0\0\0d\0\0\0f\0\0\0b\0\0\0l\0\0\0a\0\0\0h\0\0\0q\0\0\0w\0\0\0e\0\0\0r";
for (var i = 0; i < 10; i++) {
utf32Data = utf32Data + utf32Data;
}
var utf32File = createFileWithData(utf32Data, "001");
//Obtain a variety of encodings so we can test async return values
var file = createFileWithData(testData, "00");
var domFileData = file.getAsDataURL();
var domFileBinary = file.getAsBinary();
var domFileBinary2 = utf16File.getAsBinary();
var domFileBinary3 = utf32File.getAsBinary();
var request1 = new FileRequest();
request1.onload = handleTextISO1;
request1.readAsText(file, "iso-8859-1");
var request2 = new FileRequest();
request2.onload = handleTextUTF8;
request2.readAsText(file);
var request3 = new FileRequest();
request3.onload = handleTextUTF8;
request3.readAsText(file, "");
var request4 = new FileRequest();
request4.onload = handleTextUTF8;
request4.readAsText(file, "UTF-8");
//Test a variety of encodings, and make sure they work properly
//Also, test a variety of the same calls with different numbers of arguments
var request5 = new FileRequest();
request5.onload = handleTextUTF16;
request5.readAsText(utf16File, "UTF-16");
var request6 = new FileRequest();
request6.onload = handleTextUTF32;
request6.readAsText(utf32File, "UTF-32");
//Test binary data accessor
var request7 = new FileRequest();
request7.onload = handleDataBinary;
request7.readAsBinaryString(file);
var request71 = new FileRequest();
request71.onload = handleDataBinary16;
request71.readAsBinaryString(utf16File);
var request72 = new FileRequest();
request72.onload = handleDataBinary32;
request72.readAsBinaryString(utf32File);
//Test data URI encoding on differing file sizes
//Testing data URI when length % 3 == 0
var request8 = new FileRequest();
request8.onload = handleDataURI;
request8.readAsDataURL(file);
//Testing data URI when length % 3 == 1
var file2 = createFileWithData(testData2, "02");
var domFileData1 = file2.getAsDataURL();
var request9 = new FileRequest();
request9.onload = handleDataURI1;
request9.readAsDataURL(file2);
//Testing data URI when length % 3 == 2
var file3 = createFileWithData(testData3, "03");
var domFileData2 = file3.getAsDataURL();
var request10 = new FileRequest();
request10.onload = handleDataURI2;
request10.readAsDataURL(file3);
//Test asynchronous property of file access
var globalVar = 0;
var request105 = new FileRequest();
request105.onload = incGlobalVar;
request105.readAsText(file, "");
is(globalVar, 0, "testing to make sure getAsText doesn't block subsequent execution");
//Create second file for testing cancelReads()
var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties);
var testFile4 = dirSvc.get("ProfD", Components.interfaces.nsIFile);
testFile4.append("testfile04");
var outStream4 = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);
outStream4.init(testFile4, 0x02 | 0x08 | 0x20, 0666, 0);
outStream4.write(testData, testData.length);
outStream4.close();
var fileList = document.getElementById('fileList');
fileList.value = testFile4.path;
var file4 = fileList.files[0];
var request11 = new FileRequest();
request11.onabort = handleCancel;
request11.readAsText(file4);
request11.abort();
//Test error handling - Note: currently throws exceptions
/*testFile4.permissions = 0;
var request12 = new FileRequest();
request12.onerror = handleSecurityError;
request12.readAsText(file4, "");
testFile4.remove(false);
var request13 = new FileRequest();
request13.onerror = handleNotFoundError;
request13.readAsText(file4, "");*/
//Corresponding callback functions
function incGlobalVar(fileAsText) {
globalVar++;
}
function handleCancel(event) {
var fileAsText = event.target.response;
var error = event.target.error;
is(error.code, FileError.ABORT_ERR, "error code set to CANCELED for canceled reads");
is(fileAsText, null, "file data should be null on canceled reads");
testHasRun();
}
function handleTextISO1(event) {
var fileAsText = event.target.response;
var error = event.target.error;
is(error, null, "error code set to null for successful data accesses");
is(testData.length, fileAsText.length, "iso-1 async length should match testdata");
is(testData, fileAsText, "iso-1 async string result should match testdata");
testHasRun();
}
function handleTextUTF8(event) {
var fileAsUTF8 = event.target.response;
var error = event.target.error;
is(error, null, "error code set to null for successful data accesses");
is(testData.length, fileAsUTF8.length, "UTF-8 async length should match testdata");
is(testData, fileAsUTF8, "UTF-8 async string result should match testdata");
testHasRun();
}
function handleTextUTF16(event) {
var fileAsUTF16 = event.target.response;
var error = event.target.error;
is(error, null, "error code set to SUCCESS for successful data accesses");
is(testData.length, fileAsUTF16.length, "UTF-16 async length should match testdata");
is(testData, fileAsUTF16, "UTF-16 async string result should match testdata");
testHasRun();
}
function handleTextUTF32(event) {
var fileAsUTF32 = event.target.response;
var error = event.target.error;
is(error, null, "error code set to SUCCESS for successful data accesses");
is(testData.length, fileAsUTF32.length, "UTF-32 async length should match testdata");
is(testData, fileAsUTF32, "UTF-32 async string result should match testdata");
testHasRun();
}
//Tests dataURI.length % 3 == 0
function handleDataURI(event) {
var fileAsDataURI = event.target.response;
is(domFileData.length, fileAsDataURI.length, "data URI async length should match dom file data");
is(domFileData, fileAsDataURI, "data URI async string result should match dom file data");
testHasRun();
}
//Tests dataURI.length % 3 == 1
function handleDataURI1(event) {
var fileAsDataURI = event.target.response;
is(domFileData1.length, fileAsDataURI.length, "data URI async length should match dom file data1");
is(domFileData1, fileAsDataURI, "data URI async string result should match dom file data1");
testHasRun();
}
//Tests dataURI.length % 3 == 2
function handleDataURI2(event) {
var fileAsDataURI = event.target.response;
is(domFileData2.length, fileAsDataURI.length, "data URI async length should match dom file data2");
is(domFileData2, fileAsDataURI, "data URI async string result should match dom file data2");
testHasRun();
}
function handleDataBinary(event) {
var fileAsBinary = event.target.response;
is(domFileBinary.length, fileAsBinary.length, "binary data async length should match dom file binary");
is(domFileBinary, fileAsBinary, "binary data async string result should match dom file binary");
testHasRun();
}
function handleDataBinary16(event) {
var fileAsBinary = event.target.response;
is(domFileBinary2.length, fileAsBinary.length, "binary data async length should match dom file binary16");
is(domFileBinary2, fileAsBinary, "binary data async string result should match dom file binary16");
testHasRun();
}
function handleDataBinary32(event) {
var fileAsBinary = event.target.response;
is(domFileBinary3.length, fileAsBinary.length, "binary data async length should match dom file binary32");
is(domFileBinary3, fileAsBinary, "binary data async string result should match dom file binary32");
testHasRun();
}
function handleSecurityError(event) {
var fileAsText = event.target.response;
var error = event.target.error;
is(error.code, FileError.SECURITY_ERR, "code for file security error should have value 18");
is(fileAsText, null, "file content should be null when error is encountered");
testHasRun();
}
function handleNotFoundError(event) {
var fileAsText = event.target.response;
var error = event.target.error;
is(error.code, FileError.NOT_FOUND_ERR, "code for file not found error should have value 8");
is(fileAsText, null, "file content should be null when error is encountered");
testHasRun();
}
function testHasRun() {
if (++testCounter == 13) SimpleTest.finish();
}
function createFileWithData(fileData, fileNum) {
var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties);
var testFile = dirSvc.get("ProfD", Components.interfaces.nsIFile);
testFile.append("testfile" + fileNum);
var outStream = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);
outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
0666, 0);
outStream.write(fileData, fileData.length);
outStream.close();
var fileList = document.getElementById('fileList');
fileList.value = testFile.path;
return fileList.files[0];
}
</script>
</pre>
</body> </html>

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

@ -3051,6 +3051,12 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
nsCOMPtr<nsIDOMNSDataTransfer> initialDataTransferNS =
do_QueryInterface(initialDataTransfer);
nsDragEvent *dragEvent = (nsDragEvent*)aEvent;
// collect any changes to moz cursor settings stored in the event's
// data transfer.
UpdateDragDataTransfer(dragEvent);
// cancelling a dragenter or dragover event means that a drop should be
// allowed, so update the dropEffect and the canDrop state to indicate
// that a drag is allowed. If the event isn't cancelled, a drop won't be
@ -3063,7 +3069,6 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
PRUint32 dropEffect = nsIDragService::DRAGDROP_ACTION_NONE;
if (nsEventStatus_eConsumeNoDefault == *aStatus) {
// if the event has a dataTransfer set, use it.
nsDragEvent *dragEvent = (nsDragEvent*)aEvent;
if (dragEvent->dataTransfer) {
// get the dataTransfer and the dropEffect that was set on it
dataTransfer = do_QueryInterface(dragEvent->dataTransfer);
@ -3852,6 +3857,12 @@ nsEventStateManager::FireDragEnterOrExit(nsPresContext* aPresContext,
if (status == nsEventStatus_eConsumeNoDefault || aMsg == NS_DRAGDROP_EXIT)
SetContentState((aMsg == NS_DRAGDROP_ENTER) ? aTargetContent : nsnull,
NS_EVENT_STATE_DRAGOVER);
// collect any changes to moz cursor settings stored in the event's
// data transfer.
if (aMsg == NS_DRAGDROP_LEAVE_SYNTH || aMsg == NS_DRAGDROP_EXIT_SYNTH ||
aMsg == NS_DRAGDROP_ENTER)
UpdateDragDataTransfer(&event);
}
// Finally dispatch the event to the frame
@ -3859,6 +3870,36 @@ nsEventStateManager::FireDragEnterOrExit(nsPresContext* aPresContext,
aTargetFrame->HandleEvent(aPresContext, &event, &status);
}
void
nsEventStateManager::UpdateDragDataTransfer(nsDragEvent* dragEvent)
{
NS_ASSERTION(dragEvent, "drag event is null in UpdateDragDataTransfer!");
if (!dragEvent->dataTransfer)
return;
nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession();
if (dragSession) {
// the initial dataTransfer is the one from the dragstart event that
// was set on the dragSession when the drag began.
nsCOMPtr<nsIDOMDataTransfer> initialDataTransfer;
dragSession->GetDataTransfer(getter_AddRefs(initialDataTransfer));
// grab the interface that has GetMozCursor.
nsCOMPtr<nsIDOMNSDataTransfer> initialDataTransferNS =
do_QueryInterface(initialDataTransfer);
nsCOMPtr<nsIDOMNSDataTransfer> eventTransferNS =
do_QueryInterface(dragEvent->dataTransfer);
if (initialDataTransferNS && eventTransferNS) {
// retrieve the current moz cursor setting and save it.
nsAutoString mozCursor;
eventTransferNS->GetMozCursor(mozCursor);
initialDataTransferNS->SetMozCursor(mozCursor);
}
}
}
nsresult
nsEventStateManager::SetClickCount(nsPresContext* aPresContext,
nsMouseEvent *aEvent,

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

@ -199,6 +199,12 @@ protected:
nsIContent* aRelatedTarget,
nsIContent* aTargetContent,
nsWeakFrame& aTargetFrame);
/**
* Update the initial drag session data transfer with any changes that occur
* on cloned data transfer objects used for events.
*/
void UpdateDragDataTransfer(nsDragEvent* dragEvent);
nsresult SetClickCount(nsPresContext* aPresContext, nsMouseEvent *aEvent, nsEventStatus* aStatus);
nsresult CheckForAndDispatchClick(nsPresContext* aPresContext, nsMouseEvent *aEvent, nsEventStatus* aStatus);
void EnsureDocument(nsPresContext* aPresContext);

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

@ -521,8 +521,9 @@ nsHTMLScriptElement::GetScriptDeferred()
{
PRBool defer;
GetDefer(&defer);
nsCOMPtr<nsIURI> uri = GetScriptURI();
return defer;
return defer && uri;
}
PRBool

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

@ -183,8 +183,7 @@ public:
// nsIContentSink
NS_IMETHOD WillParse(void);
NS_IMETHOD WillBuildModel(nsDTDMode aDTDMode);
NS_IMETHOD DidBuildModel(void);
virtual PRBool ReadyToCallDidBuildModel(PRBool aTerminated);
NS_IMETHOD DidBuildModel(PRBool aTerminated);
NS_IMETHOD WillInterrupt(void);
NS_IMETHOD WillResume(void);
NS_IMETHOD SetParser(nsIParser* aParser);
@ -1755,9 +1754,9 @@ HTMLContentSink::WillBuildModel(nsDTDMode aDTDMode)
}
NS_IMETHODIMP
HTMLContentSink::DidBuildModel(void)
HTMLContentSink::DidBuildModel(PRBool aTerminated)
{
DidBuildModelImpl();
DidBuildModelImpl(aTerminated);
// Reflow the last batch of content
if (mBody || mFrameset) {
@ -1805,12 +1804,6 @@ HTMLContentSink::DidBuildModel(void)
return NS_OK;
}
PRBool
HTMLContentSink::ReadyToCallDidBuildModel(PRBool aTerminated)
{
return ReadyToCallDidBuildModelImpl(aTerminated);
}
NS_IMETHODIMP
HTMLContentSink::SetParser(nsIParser* aParser)
{

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

@ -90,7 +90,7 @@ public:
// nsIContentSink
NS_IMETHOD WillParse(void) { return NS_OK; }
NS_IMETHOD WillBuildModel(nsDTDMode aDTDMode);
NS_IMETHOD DidBuildModel(void);
NS_IMETHOD DidBuildModel(PRBool aTerminated);
NS_IMETHOD WillInterrupt(void);
NS_IMETHOD WillResume(void);
NS_IMETHOD SetParser(nsIParser* aParser);
@ -279,7 +279,7 @@ nsHTMLFragmentContentSink::WillBuildModel(nsDTDMode)
}
NS_IMETHODIMP
nsHTMLFragmentContentSink::DidBuildModel(void)
nsHTMLFragmentContentSink::DidBuildModel(PRBool aTerminated)
{
FlushText();
@ -667,7 +667,7 @@ nsHTMLFragmentContentSink::DidBuildContent()
{
if (!mAllContent) {
FlushText();
DidBuildModel(); // Release our ref to the parser now.
DidBuildModel(PR_FALSE); // Release our ref to the parser now.
mProcessing = PR_FALSE;
}

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

@ -75,8 +75,9 @@ static PRLogModuleInfo* gOggDecoderLog;
// The number of entries in oggplay buffer list. This value is totally
// arbitrary. Note that the actual number of video/audio frames buffered is
// twice this, because the current implementation frees OggPlay's buffer
// entries and stores copies of the underlying data in the FrameQueue.
// twice this, because the current implementation releases OggPlay's buffer
// entries and stores references or copies of the underlying data in the
// FrameQueue.
#define OGGPLAY_BUFFER_SIZE 5
// The number of frames to read before audio callback is called.

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

@ -81,6 +81,7 @@ EXPORTS = \
nsISMILAttr.h \
nsSMILAnimationController.h \
nsSMILCompositorTable.h \
nsSMILKeySpline.h \
nsSMILTimeContainer.h \
nsSMILTypes.h \
$(NULL)

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

@ -243,14 +243,14 @@ nsSMILCSSProperty::IsPropertyAnimatable(nsCSSProperty aPropID)
// case eCSSProperty_color_interpolation_filters:
// case eCSSProperty_display:
// case eCSSProperty_dominant_baseline:
// case eCSSProperty_fill_opacity:
case eCSSProperty_fill_opacity:
// case eCSSProperty_fill_rule:
// case eCSSProperty_filter:
case eCSSProperty_flood_color:
// case eCSSProperty_flood_opacity:
case eCSSProperty_flood_opacity:
// case eCSSProperty_font_family:
case eCSSProperty_font_size:
// case eCSSProperty_font_size_adjust:
case eCSSProperty_font_size_adjust:
// case eCSSProperty_font_stretch:
// case eCSSProperty_font_style:
// case eCSSProperty_font_variant:
@ -262,16 +262,16 @@ nsSMILCSSProperty::IsPropertyAnimatable(nsCSSProperty aPropID)
// case eCSSProperty_marker_mid:
// case eCSSProperty_marker_start:
// case eCSSProperty_mask:
// case eCSSProperty_opacity:
case eCSSProperty_opacity:
// case eCSSProperty_pointer_events:
// case eCSSProperty_shape_rendering:
case eCSSProperty_stop_color:
// case eCSSProperty_stop_opacity:
case eCSSProperty_stop_opacity:
case eCSSProperty_stroke_dashoffset:
// case eCSSProperty_stroke_linecap:
// case eCSSProperty_stroke_linejoin:
// case eCSSProperty_stroke_miterlimit:
// case eCSSProperty_stroke_opacity:
case eCSSProperty_stroke_miterlimit:
case eCSSProperty_stroke_opacity:
case eCSSProperty_stroke_width:
// case eCSSProperty_text_anchor:
// case eCSSProperty_text_decoration:

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

@ -65,6 +65,7 @@ struct ValueWrapper {
// -------------------------------------
static const nsStyleCoord sZeroCoord(0);
static const nsStyleCoord sZeroPercent(0.0f, eStyleUnit_Percent);
static const nsStyleCoord sZeroFactor(0.0f, eStyleUnit_Factor);
static const nsStyleCoord sZeroColor(NS_RGB(0,0,0));
// Helper Methods
@ -79,6 +80,8 @@ GetZeroValueForUnit(nsStyleUnit aUnit)
return &sZeroCoord;
case eStyleUnit_Percent:
return &sZeroPercent;
case eStyleUnit_Factor:
return &sZeroFactor;
case eStyleUnit_Color:
return &sZeroColor;
default:
@ -97,6 +100,9 @@ InvertStyleCoordSign(nsStyleCoord& aStyleCoord)
case eStyleUnit_Percent:
aStyleCoord.SetPercentValue(-aStyleCoord.GetPercentValue());
break;
case eStyleUnit_Factor:
aStyleCoord.SetFactorValue(-aStyleCoord.GetFactorValue());
break;
default:
NS_NOTREACHED("Calling InvertStyleCoordSign with an unsupported unit");
break;
@ -174,18 +180,6 @@ nsSMILCSSValueType::Add(nsSMILValue& aDest, const nsSMILValue& aValueToAdd,
NS_ABORT_IF_FALSE(destWrapper && valueToAddWrapper,
"these pointers shouldn't be null");
// At most one of our two inputs might be "unknown" (zero) values.
// If so, replace with an actual zero value
const nsStyleCoord* valueToAddCSSValue;
if (valueToAddWrapper->mPropID == eCSSProperty_UNKNOWN) {
NS_ABORT_IF_FALSE(destWrapper->mPropID != eCSSProperty_UNKNOWN,
"At least one of our inputs should have known value");
NS_ABORT_IF_FALSE(valueToAddWrapper->mCSSValue.GetUnit() == eStyleUnit_Null,
"If property ID is unset, then the unit should be, too");
valueToAddCSSValue = GetZeroValueForUnit(destWrapper->mCSSValue.GetUnit());
} else {
valueToAddCSSValue = &valueToAddWrapper->mCSSValue;
}
if (destWrapper->mPropID == eCSSProperty_UNKNOWN) {
NS_ABORT_IF_FALSE(destWrapper->mCSSValue.IsNull(),
"If property ID is unset, then the unit should be, too");
@ -195,9 +189,16 @@ nsSMILCSSValueType::Add(nsSMILValue& aDest, const nsSMILValue& aValueToAdd,
destWrapper->mPropID = valueToAddWrapper->mPropID;
destWrapper->mPresContext = valueToAddWrapper->mPresContext;
}
NS_ABORT_IF_FALSE(valueToAddWrapper->mPropID != eCSSProperty_UNKNOWN &&
!valueToAddWrapper->mCSSValue.IsNull(),
"Added amount should be a parsed value");
// Special case: font-size-adjust is explicitly non-additive
if (destWrapper->mPropID == eCSSProperty_font_size_adjust) {
return NS_ERROR_FAILURE;
}
return nsStyleAnimation::Add(destWrapper->mCSSValue,
*valueToAddCSSValue, aCount) ?
valueToAddWrapper->mCSSValue, aCount) ?
NS_OK : NS_ERROR_FAILURE;
}
@ -227,10 +228,9 @@ nsSMILCSSValueType::ComputeDistance(const nsSMILValue& aFrom,
!toWrapper->mCSSValue.IsNull(),
"ComputeDistance endpoint should be a parsed value");
PRBool success = nsStyleAnimation::ComputeDistance(*fromCSSValue,
toWrapper->mCSSValue,
aDistance);
return success ? NS_OK : NS_ERROR_FAILURE;
return nsStyleAnimation::ComputeDistance(*fromCSSValue, toWrapper->mCSSValue,
aDistance) ?
NS_OK : NS_ERROR_FAILURE;
}
nsresult

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

@ -47,15 +47,17 @@
const double nsSMILKeySpline::kSampleStepSize =
1.0 / double(kSplineTableSize - 1);
nsSMILKeySpline::nsSMILKeySpline(double aX1,
double aY1,
double aX2,
double aY2)
: mX1(aX1),
mY1(aY1),
mX2(aX2),
mY2(aY2)
void
nsSMILKeySpline::Init(double aX1,
double aY1,
double aX2,
double aY2)
{
mX1 = aX1;
mY1 = aY1;
mX2 = aX2;
mY2 = aY2;
if (mX1 != mY1 || mX2 != mY2)
CalcSampleValues();
}

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

@ -44,6 +44,8 @@
class nsSMILKeySpline
{
public:
nsSMILKeySpline() { /* caller must call Init later */ }
/**
* Creates a new key spline control point description.
*
@ -51,7 +53,13 @@ public:
* SMILANIM 3.2.3. They must each be in the range 0.0 <= x <= 1.0
*/
nsSMILKeySpline(double aX1, double aY1,
double aX2, double aY2);
double aX2, double aY2)
{
Init(aX1, aY1, aX2, aY2);
}
void Init(double aX1, double aY1,
double aX2, double aY2);
/**
* Gets the output (y) value for an input (x).
@ -104,10 +112,10 @@ private:
return 3.0 * aA1;
}
const double mX1;
const double mY1;
const double mX2;
const double mY2;
double mX1;
double mY1;
double mX2;
double mY2;
enum { kSplineTableSize = 11 };
double mSampleValues[kSplineTableSize];

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