Merge m-c to s-c

This commit is contained in:
Philipp von Weitershausen 2011-09-06 09:07:39 -07:00
commit 0910ed33c2
559 changed files with 11995 additions and 11739 deletions

View File

@ -56,7 +56,7 @@ interface nsIAccessibleRelation;
* Mozilla creates the implementations of nsIAccessible on demand.
* See http://www.mozilla.org/projects/ui/accessibility for more information.
*/
[scriptable, uuid(c7ac764a-b4c5-4479-9fb7-06e3c9f3db34)]
[scriptable, uuid(3126544c-826c-4694-a2ed-67bfe56a1f37)]
interface nsIAccessible : nsISupports
{
/**
@ -221,26 +221,6 @@ interface nsIAccessible : nsISupports
*/
nsIAccessible getChildAt(in long aChildIndex);
/**
* Accessible node geometrically to the right of this one
*/
nsIAccessible getAccessibleToRight();
/**
* Accessible node geometrically to the left of this one
*/
nsIAccessible getAccessibleToLeft();
/**
* Accessible node geometrically above this one
*/
nsIAccessible getAccessibleAbove();
/**
* Accessible node geometrically below this one
*/
nsIAccessible getAccessibleBelow();
/**
* Return accessible relation by the given relation type (see.
* constants defined in nsIAccessibleRelation).

View File

@ -681,10 +681,15 @@ NotificationController::TextEnumerator(nsCOMPtrHashKey<nsIContent>* aEntry,
tag.get(), id.get(), index);
#endif
// Make sure the text node is in accessible document still.
nsAccessible* container = document->GetAccessibleOrContainer(containerNode);
nsTArray<nsCOMPtr<nsIContent> > insertedContents;
insertedContents.AppendElement(textNode);
document->ProcessContentInserted(container, &insertedContents);
NS_ASSERTION(container,
"Text node having rendered text hasn't accessible document!");
if (container) {
nsTArray<nsCOMPtr<nsIContent> > insertedContents;
insertedContents.AppendElement(textNode);
document->ProcessContentInserted(container, &insertedContents);
}
}
return PL_DHASH_NEXT;

View File

@ -643,6 +643,9 @@ nsAccessibilityService::GetAccessibleFor(nsIDOMNode *aNode,
return NS_OK;
nsCOMPtr<nsINode> node(do_QueryInterface(aNode));
if (!node)
return NS_ERROR_INVALID_ARG;
NS_IF_ADDREF(*aAccessible = GetAccessible(node));
return NS_OK;
}
@ -812,6 +815,13 @@ nsAccessibilityService::GetAccessibleFromCache(nsIDOMNode* aNode,
nsIAccessible** aAccessible)
{
NS_ENSURE_ARG_POINTER(aAccessible);
*aAccessible = nsnull;
if (!aNode)
return NS_OK;
nsCOMPtr<nsINode> node(do_QueryInterface(aNode));
if (!node)
return NS_ERROR_INVALID_ARG;
// Search for an accessible in each of our per document accessible object
// caches. If we don't find it, and the given node is itself a document, check
@ -819,7 +829,6 @@ nsAccessibilityService::GetAccessibleFromCache(nsIDOMNode* aNode,
// document accessibles are not stored in the document cache, however an
// "unofficially" shutdown document (i.e. not from nsAccDocManager) can still
// exist in the document cache.
nsCOMPtr<nsINode> node(do_QueryInterface(aNode));
nsAccessible* accessible = FindAccessibleInCache(node);
if (!accessible) {
nsCOMPtr<nsIDocument> document(do_QueryInterface(node));

View File

@ -1974,30 +1974,6 @@ NS_IMETHODIMP nsAccessible::GetHelp(nsAString& _retval)
return NS_ERROR_NOT_IMPLEMENTED;
}
/* nsIAccessible getAccessibleToRight(); */
NS_IMETHODIMP nsAccessible::GetAccessibleToRight(nsIAccessible **_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* nsIAccessible getAccessibleToLeft(); */
NS_IMETHODIMP nsAccessible::GetAccessibleToLeft(nsIAccessible **_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* nsIAccessible getAccessibleAbove(); */
NS_IMETHODIMP nsAccessible::GetAccessibleAbove(nsIAccessible **_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* nsIAccessible getAccessibleBelow(); */
NS_IMETHODIMP nsAccessible::GetAccessibleBelow(nsIAccessible **_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
nsIContent*
nsAccessible::GetAtomicRegion() const
{

View File

@ -1417,11 +1417,9 @@ nsDocAccessible::RecreateAccessible(nsIContent* aContent)
// coalescence with normal hide and show events. Note, in this case they
// should be coalesced with normal show/hide events.
// Check if the node is in DOM still.
nsIContent* parentContent = aContent->GetParent();
if (parentContent && parentContent->IsInDoc()) {
nsAccessible* container = GetAccessibleOrContainer(parentContent);
// Check if the node is in accessible document.
nsAccessible* container = GetContainerAccessible(aContent);
if (container) {
// Remove and reinsert.
UpdateTree(container, aContent, false);
container->UpdateChildren();
@ -1440,8 +1438,6 @@ nsDocAccessible::ProcessInvalidationList()
nsAccessible* accessible = GetAccessible(content);
if (!accessible) {
nsAccessible* container = GetContainerAccessible(content);
NS_ASSERTION(container,
"Got a referenced element that is not in document!");
if (container) {
container->UpdateChildren();
accessible = GetAccessible(content);

View File

@ -446,6 +446,15 @@ NS_IMETHODIMP nsHTMLTextFieldAccessible::GetValue(nsAString& _retval)
return NS_ERROR_FAILURE;
}
void
nsHTMLTextFieldAccessible::ApplyARIAState(PRUint64* aState)
{
nsHyperTextAccessibleWrap::ApplyARIAState(aState);
nsStateMapEntry::MapToStates(mContent, aState, eARIAAutoComplete);
}
PRUint64
nsHTMLTextFieldAccessible::NativeState()
{

View File

@ -159,6 +159,7 @@ public:
NS_IMETHOD GetAssociatedEditor(nsIEditor **aEditor);
// nsAccessible
virtual void ApplyARIAState(PRUint64* aState);
virtual nsresult GetNameInternal(nsAString& aName);
virtual PRUint32 NativeRole();
virtual PRUint64 NativeState();

View File

@ -810,42 +810,35 @@ __try {
if (!pvarEndUpAt)
return E_INVALIDARG;
nsAccessible *xpAccessibleStart = GetXPAccessibleFor(varStart);
if (!xpAccessibleStart || IsDefunct())
nsAccessible* accessible = GetXPAccessibleFor(varStart);
if (!accessible || accessible->IsDefunct())
return E_FAIL;
VariantInit(pvarEndUpAt);
nsCOMPtr<nsIAccessible> xpAccessibleResult;
nsAccessible* navAccessible = nsnull;
PRUint32 xpRelation = 0;
switch(navDir) {
case NAVDIR_DOWN:
xpAccessibleStart->GetAccessibleBelow(getter_AddRefs(xpAccessibleResult));
break;
case NAVDIR_FIRSTCHILD:
if (!nsAccUtils::MustPrune(xpAccessibleStart))
xpAccessibleStart->GetFirstChild(getter_AddRefs(xpAccessibleResult));
if (!nsAccUtils::MustPrune(accessible))
navAccessible = accessible->FirstChild();
break;
case NAVDIR_LASTCHILD:
if (!nsAccUtils::MustPrune(xpAccessibleStart))
xpAccessibleStart->GetLastChild(getter_AddRefs(xpAccessibleResult));
break;
case NAVDIR_LEFT:
xpAccessibleStart->GetAccessibleToLeft(getter_AddRefs(xpAccessibleResult));
if (!nsAccUtils::MustPrune(accessible))
navAccessible = accessible->LastChild();
break;
case NAVDIR_NEXT:
xpAccessibleStart->GetNextSibling(getter_AddRefs(xpAccessibleResult));
navAccessible = accessible->NextSibling();
break;
case NAVDIR_PREVIOUS:
xpAccessibleStart->GetPreviousSibling(getter_AddRefs(xpAccessibleResult));
navAccessible = accessible->PrevSibling();
break;
case NAVDIR_DOWN:
case NAVDIR_LEFT:
case NAVDIR_RIGHT:
xpAccessibleStart->GetAccessibleToRight(getter_AddRefs(xpAccessibleResult));
break;
case NAVDIR_UP:
xpAccessibleStart->GetAccessibleAbove(getter_AddRefs(xpAccessibleResult));
break;
return E_NOTIMPL;
// MSAA relationship extensions to accNavigate
case NAVRELATION_CONTROLLED_BY:
@ -896,17 +889,20 @@ __try {
case NAVRELATION_DESCRIPTION_FOR:
xpRelation = nsIAccessibleRelation::RELATION_DESCRIPTION_FOR;
break;
default:
return E_INVALIDARG;
}
pvarEndUpAt->vt = VT_EMPTY;
if (xpRelation) {
Relation rel = RelationByType(xpRelation);
xpAccessibleResult = rel.Next();
navAccessible = rel.Next();
}
if (xpAccessibleResult) {
pvarEndUpAt->pdispVal = NativeAccessible(xpAccessibleResult);
if (navAccessible) {
pvarEndUpAt->pdispVal = NativeAccessible(navAccessible);
pvarEndUpAt->vt = VT_DISPATCH;
return S_OK;
}

View File

@ -67,6 +67,9 @@
testStates("combobox_autocomplete_list", STATE_HASPOPUP, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
testStates("combobox_autocomplete_both", STATE_HASPOPUP, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
testStates("htmltext_autocomplete_list", STATE_HASPOPUP, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
testStates("htmltextarea_autocomplete_list", STATE_HASPOPUP, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
// aria-busy
testStates("textbox_busy_false", 0, 0, STATE_BUSY);
testStates("textbox_busy_true", STATE_BUSY);
@ -152,6 +155,11 @@
title="Unify ARIA state attributes mapping rules">
Mozilla Bug 499653
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=681674"
title="aria-autocomplete not supported on standard form text input controls">
Mozilla Bug 681674
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
@ -164,6 +172,9 @@
<div id="combobox_autocomplete_list" role="combobox" aria-autocomplete="list"></div>
<div id="combobox_autocomplete_both" role="combobox" aria-autocomplete="both"></div>
<input id="htmltext_autocomplete_list" type="text" aria-autocomplete="list" />
<textarea id="htmltextarea_autocomplete_list" aria-autocomplete="list"></textarea>
<div id="textbox_busy_false" role="textbox" aria-busy="false"></div>
<div id="textbox_busy_true" role="textbox" aria-busy="true"></div>
<div id="textbox_busy_error" role="textbox" aria-busy="error"></div>

1
aclocal.m4 vendored
View File

@ -16,6 +16,7 @@ builtin(include, build/autoconf/mozheader.m4)dnl
builtin(include, build/autoconf/acwinpaths.m4)dnl
builtin(include, build/autoconf/lto.m4)dnl
builtin(include, build/autoconf/gcc-pr49911.m4)dnl
builtin(include, build/autoconf/frameptr.m4)dnl
MOZ_PROG_CHECKMSYS()

View File

@ -68,11 +68,8 @@ var FullZoom = {
// browser.zoom.updateBackgroundTabs preference cache
updateBackgroundTabs: undefined,
// whether we are in private browsing mode
_inPrivateBrowsing: false,
get siteSpecific() {
return !this._inPrivateBrowsing && this._siteSpecificPref;
return this._siteSpecificPref;
},
//**************************************************************************//
@ -94,15 +91,6 @@ var FullZoom = {
// Register ourselves with the service so we know when our pref changes.
Services.contentPrefs.addObserver(this.name, this);
// We disable site-specific preferences in Private Browsing mode, because the
// content preferences module is disabled
Services.obs.addObserver(this, "private-browsing", true);
// Retrieve the initial status of the Private Browsing mode.
this._inPrivateBrowsing = Cc["@mozilla.org/privatebrowsing;1"].
getService(Ci.nsIPrivateBrowsingService).
privateBrowsingEnabled;
this._siteSpecificPref =
gPrefService.getBoolPref("browser.zoom.siteSpecific");
this.updateBackgroundTabs =
@ -113,7 +101,6 @@ var FullZoom = {
},
destroy: function FullZoom_destroy() {
Services.obs.removeObserver(this, "private-browsing");
gPrefService.removeObserver("browser.zoom.", this);
Services.contentPrefs.removeObserver(this.name, this);
window.removeEventListener("DOMMouseScroll", this, false);
@ -187,16 +174,6 @@ var FullZoom = {
break;
}
break;
case "private-browsing":
switch (aData) {
case "enter":
this._inPrivateBrowsing = true;
break;
case "exit":
this._inPrivateBrowsing = false;
break;
}
break;
}
},
@ -321,14 +298,12 @@ var FullZoom = {
* one.
**/
_applyPrefToSetting: function FullZoom__applyPrefToSetting(aValue, aBrowser) {
if ((!this.siteSpecific && !this._inPrivateBrowsing) ||
gInPrintPreviewMode)
if ((!this.siteSpecific) || gInPrintPreviewMode)
return;
var browser = aBrowser || (gBrowser && gBrowser.selectedBrowser);
try {
if (browser.contentDocument instanceof Ci.nsIImageDocument ||
this._inPrivateBrowsing)
if (browser.contentDocument instanceof Ci.nsIImageDocument)
ZoomManager.setZoomForBrowser(browser, 1);
else if (typeof aValue != "undefined")
ZoomManager.setZoomForBrowser(browser, this._ensureValid(aValue));

View File

@ -321,10 +321,8 @@ nsContextMenu.prototype = {
var onMisspelling = InlineSpellCheckerUI.overMisspelling;
this.showItem("spell-check-enabled", canSpell);
this.showItem("spell-separator", canSpell || this.onEditableArea);
if (canSpell) {
document.getElementById("spell-check-enabled")
.setAttribute("checked", InlineSpellCheckerUI.enabled);
}
document.getElementById("spell-check-enabled")
.setAttribute("checked", canSpell && InlineSpellCheckerUI.enabled);
this.showItem("spell-add-to-dictionary", onMisspelling);

View File

@ -34,13 +34,156 @@
*
* ***** END LICENSE BLOCK ***** */
addEventListener("DOMWillOpenModalDialog", function (event) {
// (event.isTrusted == true) when the event is generated by a user action
// and does not originate from a script.
if (event.isTrusted) {
"use strict";
const Cu = Components.utils;
Cu.import("resource:///modules/tabview/utils.jsm");
// Bug 671101 - directly using webProgress in this context
// causes docShells to leak
__defineGetter__("webProgress", function () {
let ifaceReq = docShell.QueryInterface(Ci.nsIInterfaceRequestor);
return ifaceReq.getInterface(Ci.nsIWebProgress);
});
// ----------
// WindowEventHandler
//
// Handles events dispatched by the content window.
let WindowEventHandler = {
// ----------
// Function: onDOMContentLoaded
// Sends an asynchronous message when the "onDOMContentLoaded" event for the
// current page is fired.
onDOMContentLoaded: function WEH_onDOMContentLoaded(event) {
sendAsyncMessage("Panorama:DOMContentLoaded");
},
// ----------
// Function: onDOMWillOpenModalDialog
// Sends a synchronous message when the "onDOMWillOpenModalDialog" event
// is fired right before a modal dialog will be opened by the current page.
onDOMWillOpenModalDialog: function WEH_onDOMWillOpenModalDialog(event) {
// (event.isTrusted == true) when the event is generated by a user action
// and does not originate from a script.
if (!event.isTrusted)
return;
// we're intentionally sending a synchronous message to handle this event
// as quick as possible, switch the selected tab and hide the tabview
// before the modal dialog is shown
sendSyncMessage("Panorama:DOMWillOpenModalDialog");
}
}, true);
};
// add event listeners
addEventListener("DOMContentLoaded", WindowEventHandler.onDOMContentLoaded, false);
addEventListener("DOMWillOpenModalDialog", WindowEventHandler.onDOMWillOpenModalDialog, false);
// ----------
// WindowMessageHandler
//
// Handles messages sent by the chrome process.
let WindowMessageHandler = {
// ----------
// Function: isDocumentLoaded
// Checks if the currently active document is loaded.
isDocumentLoaded: function WMH_isDocumentLoaded(cx) {
let isLoaded = (content.document.readyState == "complete" &&
!webProgress.isLoadingDocument);
sendAsyncMessage(cx.name, {isLoaded: isLoaded});
}
};
// add message listeners
addMessageListener("Panorama:isDocumentLoaded", WindowMessageHandler.isDocumentLoaded);
// ----------
// WebProgressListener
//
// Observe the web progress of content pages loaded into this browser. When the
// state of a page changes we check if we're still allowed to store page
// information permanently.
let WebProgressListener = {
// ----------
// Function: onStateChange
// Called by the webProgress when its state changes.
onStateChange: function WPL_onStateChange(webProgress, request, flag, status) {
// The browser just started loading (again). Explicitly grant storage
// because the browser might have been blocked before (e.g. when navigating
// from a https-page to a http-page).
if (flag & Ci.nsIWebProgressListener.STATE_START) {
// ensure the dom window is the top one
if (this._isTopWindow(webProgress))
sendAsyncMessage("Panorama:StoragePolicy:granted");
}
// The browser finished loading - check the cache control headers. Send
// a message if we're not allowed to store information about this page.
if (flag & Ci.nsIWebProgressListener.STATE_STOP) {
// ensure the dom window is the top one
if (this._isTopWindow(webProgress) &&
request && request instanceof Ci.nsIHttpChannel) {
request.QueryInterface(Ci.nsIHttpChannel);
let exclude = false;
let reason = "";
// Check if the "Cache-Control" header is "no-store". In this case we're
// not allowed to store information about the current page.
if (this._isNoStoreResponse(request)) {
exclude = true;
reason = "no-store";
}
// Otherwise we'll deny storage if we're currently viewing a https
// page without a "Cache-Control: public" header.
else if (request.URI.schemeIs("https")) {
let cacheControlHeader = this._getCacheControlHeader(request);
if (cacheControlHeader && !(/public/i).test(cacheControlHeader)) {
exclude = true;
reason = "https";
}
}
if (exclude)
sendAsyncMessage("Panorama:StoragePolicy:denied", {reason: reason});
}
}
},
// ----------
// Function: _isTopWindow
// Returns whether the DOMWindow associated with the webProgress is the
// top content window (and not an iframe or similar).
_isTopWindow: function WPL__isTopWindow(webProgress) {
// can throw if there's no associated DOMWindow
return !!Utils.attempt(function () webProgress.DOMWindow == content);
},
// ----------
// Function: _isNoStoreResponse
// Checks if the "Cache-Control" header is "no-store".
_isNoStoreResponse: function WPL__isNoStoreResponse(req) {
// can throw if called before the response has been received
return !!Utils.attempt(function () req.isNoStoreResponse());
},
// ----------
// Function: _getCacheControlHeader
// Returns the value of the "Cache-Control" header.
_getCacheControlHeader: function WPL__getCacheControlHeader(req) {
// can throw when the "Cache-Control" header doesn't exist
return Utils.attempt(function () req.getResponseHeader("Cache-Control"));
},
// ----------
// Implements progress listener interface.
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
Ci.nsISupportsWeakReference,
Ci.nsISupports])
};
// add web progress listener
webProgress.addProgressListener(WebProgressListener, Ci.nsIWebProgress.NOTIFY_STATE_WINDOW);

View File

@ -776,5 +776,22 @@ let Utils = {
// Return the modified object
return target;
},
// ----------
// Function: attempt
// Tries to execute a number of functions. Returns immediately the return
// value of the first non-failed function without executing successive
// functions, or null.
attempt: function () {
let args = arguments;
for (let i = 0; i < args.length; i++) {
try {
return args[i]();
} catch (e) {}
}
return null;
}
};

View File

@ -99,47 +99,27 @@ let Storage = {
saveTab: function Storage_saveTab(tab, data) {
Utils.assert(tab, "tab");
if (data != null) {
let imageData = data.imageData;
// Remove imageData from payload
delete data.imageData;
if (imageData != null)
ThumbnailStorage.saveThumbnail(tab, imageData);
}
this._sessionStore.setTabValue(tab, this.TAB_DATA_IDENTIFIER,
JSON.stringify(data));
},
// ----------
// Function: getTabData
// Load tab data from session store and return it. Asynchrously loads the tab's
// thumbnail from the cache and calls <callback>(imageData) when done.
getTabData: function Storage_getTabData(tab, callback) {
// Load tab data from session store and return it.
getTabData: function Storage_getTabData(tab) {
Utils.assert(tab, "tab");
Utils.assert(typeof callback == "function", "callback arg must be a function");
let existingData = null;
try {
let tabData = this._sessionStore.getTabValue(tab, this.TAB_DATA_IDENTIFIER);
if (tabData != "") {
if (tabData != "")
existingData = JSON.parse(tabData);
}
} catch (e) {
// getTabValue will fail if the property doesn't exist.
Utils.log(e);
}
if (existingData) {
ThumbnailStorage.loadThumbnail(
tab, existingData.url,
function(status, imageData) {
callback(imageData);
}
);
}
return existingData;
},

View File

@ -0,0 +1,208 @@
/* ***** 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 storagePolicy.js.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Tim Taubert <ttaubert@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
// **********
// Title: storagePolicy.js
// ##########
// Class: StoragePolicy
// Singleton for implementing a storage policy for sensitive data.
let StoragePolicy = {
// Pref that controls whether we can store SSL content on disk
PREF_DISK_CACHE_SSL: "browser.cache.disk_cache_ssl",
// Used to keep track of disk_cache_ssl preference
_enablePersistentHttpsCaching: null,
// Used to keep track of browsers whose data we shouldn't store permanently
_deniedBrowsers: [],
// ----------
// Function: toString
// Prints [StoragePolicy] for debug use.
toString: function StoragePolicy_toString() {
return "[StoragePolicy]";
},
// ----------
// Function: init
// Initializes the StoragePolicy object.
init: function StoragePolicy_init() {
// store the preference value
this._enablePersistentHttpsCaching =
Services.prefs.getBoolPref(this.PREF_DISK_CACHE_SSL);
Services.prefs.addObserver(this.PREF_DISK_CACHE_SSL, this, false);
// tabs are already loaded before UI is initialized so cache-control
// values are unknown. We add browsers with https to the list for now.
if (!this._enablePersistentHttpsCaching)
Array.forEach(gBrowser.browsers, this._initializeBrowser.bind(this));
// make sure to remove tab browsers when tabs get closed
this._onTabClose = this._onTabClose.bind(this);
gBrowser.tabContainer.addEventListener("TabClose", this._onTabClose, false);
let mm = gWindow.messageManager;
// add message listeners for storage granted
this._onGranted = this._onGranted.bind(this);
mm.addMessageListener("Panorama:StoragePolicy:granted", this._onGranted);
// add message listeners for storage denied
this._onDenied = this._onDenied.bind(this);
mm.addMessageListener("Panorama:StoragePolicy:denied", this._onDenied);
},
// ----------
// Function: _initializeBrowser
// Initializes the given browser and checks if we need to add it to our
// internal exclusion list.
_initializeBrowser: function StoragePolicy__initializeBrowser(browser) {
let self = this;
function checkExclusion() {
if (browser.currentURI.schemeIs("https"))
self._deniedBrowsers.push(browser);
}
function waitForDocumentLoad() {
let mm = browser.messageManager;
mm.addMessageListener("Panorama:DOMContentLoaded", function onLoad(cx) {
mm.removeMessageListener(cx.name, onLoad);
checkExclusion(browser);
});
}
this._isDocumentLoaded(browser, function (isLoaded) {
if (isLoaded)
checkExclusion();
else
waitForDocumentLoad();
});
},
// ----------
// Function: _isDocumentLoaded
// Check if the given browser's document is loaded.
_isDocumentLoaded: function StoragePolicy__isDocumentLoaded(browser, callback) {
let mm = browser.messageManager;
let message = "Panorama:isDocumentLoaded";
mm.addMessageListener(message, function onMessage(cx) {
mm.removeMessageListener(cx.name, onMessage);
callback(cx.json.isLoaded);
});
mm.sendAsyncMessage(message);
},
// ----------
// Function: uninit
// Is called by UI.init() when the browser windows is closed.
uninit: function StoragePolicy_uninit() {
Services.prefs.removeObserver(this.PREF_DISK_CACHE_SSL, this);
gBrowser.removeTabsProgressListener(this);
gBrowser.tabContainer.removeEventListener("TabClose", this._onTabClose, false);
let mm = gWindow.messageManager;
// remove message listeners
mm.removeMessageListener("Panorama:StoragePolicy:granted", this._onGranted);
mm.removeMessageListener("Panorama:StoragePolicy:denied", this._onDenied);
},
// ----------
// Function: _onGranted
// Handle the 'granted' message and remove the given browser from the list
// of denied browsers.
_onGranted: function StoragePolicy__onGranted(cx) {
let index = this._deniedBrowsers.indexOf(cx.target);
if (index > -1)
this._deniedBrowsers.splice(index, 1);
},
// ----------
// Function: _onDenied
// Handle the 'denied' message and add the given browser to the list of denied
// browsers.
_onDenied: function StoragePolicy__onDenied(cx) {
// exclusion is optional because cache-control is not no-store or public and
// the protocol is https. don't exclude when persistent https caching is
// enabled.
if ("https" == cx.json.reason && this._enablePersistentHttpsCaching)
return;
let browser = cx.target;
if (this._deniedBrowsers.indexOf(browser) == -1)
this._deniedBrowsers.push(browser);
},
// ----------
// Function: _onTabClose
// Remove the browser from our internal exclusion list when a tab gets closed.
_onTabClose: function StoragePolicy__onTabClose(event) {
let browser = event.target.linkedBrowser;
let index = this._deniedBrowsers.indexOf(browser);
if (index > -1)
this._deniedBrowsers.splice(index, 1);
},
// ----------
// Function: canStoreThumbnailForTab
// Returns whether we're allowed to store the thumbnail of the given tab.
canStoreThumbnailForTab: function StoragePolicy_canStoreThumbnailForTab(tab) {
// deny saving thumbnails in private browsing mode
if (gPrivateBrowsing.privateBrowsingEnabled &&
UI._privateBrowsing.transitionMode != "enter")
return false;
return (this._deniedBrowsers.indexOf(tab.linkedBrowser) == -1);
},
// ----------
// Function: observe
// Observe pref changes.
observe: function StoragePolicy_observe(subject, topic, data) {
this._enablePersistentHttpsCaching =
Services.prefs.getBoolPref(this.PREF_DISK_CACHE_SSL);
}
};

View File

@ -69,6 +69,7 @@ function TabItem(tab, options) {
let $div = iQ(div);
this._cachedImageData = null;
this._thumbnailNeedsSaving = false;
this.canvasSizeForced = false;
this.$thumb = iQ('.thumb', $div);
this.$fav = iQ('.favicon', $div);
@ -80,19 +81,23 @@ function TabItem(tab, options) {
this.tabCanvas = new TabCanvas(this.tab, this.$canvas[0]);
let self = this;
// when we paint onto the canvas make sure our thumbnail gets saved
this.tabCanvas.addSubscriber("painted", function () {
self._thumbnailNeedsSaving = true;
});
this.defaultSize = new Point(TabItems.tabWidth, TabItems.tabHeight);
this._hidden = false;
this.isATabItem = true;
this.keepProportional = true;
this._hasBeenDrawn = false;
this._reconnected = false;
this.isDragging = false;
this.isStacked = false;
this.url = "";
var self = this;
this.isDragging = false;
// Read off the total vertical and horizontal padding on the tab container
// and cache this value, as it must be the same for every TabItem.
if (Utils.isEmptyObject(TabItems.tabItemPadding)) {
@ -194,11 +199,14 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), {
//
// Parameters:
// tabData - the tab data
showCachedData: function TabItem_showCachedData(tabData) {
this._cachedImageData = tabData.imageData;
// imageData - the image data
showCachedData: function TabItem_showCachedData(tabData, imageData) {
this._cachedImageData = imageData;
this.$cachedThumb.attr("src", this._cachedImageData).show();
this.$canvas.css({opacity: 0.0});
this.$canvas.css({opacity: 0});
this.$tabTitle.text(tabData.title ? tabData.title : "");
this._sendToSubscribers("showingCachedData");
},
// ----------
@ -214,39 +222,23 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), {
// ----------
// Function: getStorageData
// Get data to be used for persistent storage of this object.
//
// Parameters:
// getImageData - true to include thumbnail pixels (and page title as well); default false
getStorageData: function TabItem_getStorageData(getImageData) {
let imageData = null;
if (getImageData) {
if (this._cachedImageData)
imageData = this._cachedImageData;
else if (this.tabCanvas)
imageData = this.tabCanvas.toImageData();
}
getStorageData: function TabItem_getStorageData() {
return {
url: this.tab.linkedBrowser.currentURI.spec,
groupID: (this.parent ? this.parent.id : 0),
imageData: imageData,
title: getImageData && this.tab.label || null
title: this.tab.label
};
},
// ----------
// Function: save
// Store persistent for this object.
//
// Parameters:
// saveImageData - true to include thumbnail pixels (and page title as well); default false
save: function TabItem_save(saveImageData) {
try{
save: function TabItem_save() {
try {
if (!this.tab || this.tab.parentNode == null || !this._reconnected) // too soon/late to save
return;
var data = this.getStorageData(saveImageData);
let data = this.getStorageData();
if (TabItems.storageSanity(data))
Storage.saveTab(this.tab, data);
} catch(e) {
@ -254,6 +246,91 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), {
}
},
// ----------
// Function: loadThumbnail
// Loads the tabItems thumbnail.
loadThumbnail: function TabItem_loadThumbnail(tabData) {
Utils.assert(tabData, "invalid or missing argument <tabData>");
let self = this;
function TabItem_loadThumbnail_callback(error, imageData) {
// we could have been unlinked while waiting for the thumbnail to load
if (error || !imageData || !self.tab)
return;
self._sendToSubscribers("loadedCachedImageData");
// If we have a cached image, then show it if the loaded URL matches
// what the cache is from, OR the loaded URL is blank, which means
// that the page hasn't loaded yet.
let currentUrl = self.tab.linkedBrowser.currentURI.spec;
if (tabData.url == currentUrl || currentUrl == "about:blank")
self.showCachedData(tabData, imageData);
}
ThumbnailStorage.loadThumbnail(tabData.url, TabItem_loadThumbnail_callback);
},
// ----------
// Function: saveThumbnail
// Saves the tabItems thumbnail.
saveThumbnail: function TabItem_saveThumbnail(options) {
if (!this.tabCanvas)
return;
// nothing to do if the thumbnail hasn't changed
if (!this._thumbnailNeedsSaving)
return;
// check the storage policy to see if we're allowed to store the thumbnail
if (!StoragePolicy.canStoreThumbnailForTab(this.tab)) {
this._sendToSubscribers("deniedToSaveImageData");
return;
}
let url = this.tab.linkedBrowser.currentURI.spec;
let delayed = this._saveThumbnailDelayed;
let synchronously = (options && options.synchronously);
// is there a delayed save waiting?
if (delayed) {
// check if url has changed since last call to saveThumbnail
if (!synchronously && url == delayed.url)
return;
// url has changed in the meantime, clear the timeout
clearTimeout(delayed.timeout);
}
let self = this;
function callback(error) {
if (!error) {
self._thumbnailNeedsSaving = false;
self._sendToSubscribers("savedCachedImageData");
}
}
function doSaveThumbnail() {
self._saveThumbnailDelayed = null;
// we could have been unlinked in the meantime
if (!self.tabCanvas)
return;
let imageData = self.tabCanvas.toImageData();
ThumbnailStorage.saveThumbnail(url, imageData, callback, options);
}
if (synchronously) {
doSaveThumbnail();
} else {
let timeout = setTimeout(doSaveThumbnail, 2000);
this._saveThumbnailDelayed = {url: url, timeout: timeout};
}
},
// ----------
// Function: _reconnect
// Load the reciever's persistent data from storage. If there is none,
@ -262,29 +339,12 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), {
Utils.assertThrow(!this._reconnected, "shouldn't already be reconnected");
Utils.assertThrow(this.tab, "should have a xul:tab");
let tabData = null;
let self = this;
let imageDataCb = function(imageData) {
// we could have been unlinked while waiting for the thumbnail to load
if (!self.tab)
return;
let tabData = Storage.getTabData(this.tab);
Utils.assertThrow(tabData, "tabData");
tabData.imageData = imageData;
let currentUrl = self.tab.linkedBrowser.currentURI.spec;
// If we have a cached image, then show it if the loaded URL matches
// what the cache is from, OR the loaded URL is blank, which means
// that the page hasn't loaded yet.
if (tabData.imageData &&
(tabData.url == currentUrl || currentUrl == 'about:blank')) {
self.showCachedData(tabData);
}
};
// getTabData returns the sessionstore contents, but passes
// a callback to run when the thumbnail is finally loaded.
tabData = Storage.getTabData(this.tab, imageDataCb);
if (tabData && TabItems.storageSanity(tabData)) {
this.loadThumbnail(tabData);
if (self.parent)
self.parent.remove(self, {immediately: true});
@ -936,6 +996,7 @@ let TabItems = {
tabItem._lastTabUpdateTime = this._lastUpdateTime;
tabItem.tabCanvas.paint();
tabItem.saveThumbnail();
// ___ cache
if (tabItem.isShowingCachedData())
@ -1146,13 +1207,22 @@ let TabItems = {
// ----------
// Function: saveAll
// Saves all open <TabItem>s.
//
// Parameters:
// saveImageData - true to include thumbnail pixels (and page title as well); default false
saveAll: function TabItems_saveAll(saveImageData) {
var items = this.getItems();
items.forEach(function(item) {
item.save(saveImageData);
saveAll: function TabItems_saveAll() {
let tabItems = this.getItems();
tabItems.forEach(function TabItems_saveAll_forEach(tabItem) {
tabItem.save();
});
},
// ----------
// Function: saveAllThumbnails
// Saves thumbnails of all open <TabItem>s.
saveAllThumbnails: function TabItems_saveAllThumbnails(options) {
let tabItems = this.getItems();
tabItems.forEach(function TabItems_saveAllThumbnails_forEach(tabItem) {
tabItem.saveThumbnail(options);
});
},
@ -1342,7 +1412,7 @@ function TabCanvas(tab, canvas) {
this.canvas = canvas;
};
TabCanvas.prototype = {
TabCanvas.prototype = Utils.extend(new Subscribable(), {
// ----------
// Function: toString
// Prints [TabCanvas (tab)] for debug use
@ -1386,6 +1456,8 @@ TabCanvas.prototype = {
// Draw directly to the destination canvas
this._drawWindow(ctx, w, h, bgColor);
}
this._sendToSubscribers("painted");
},
// ----------
@ -1454,4 +1526,4 @@ TabCanvas.prototype = {
toImageData: function TabCanvas_toImageData() {
return this.canvas.toDataURL("image/png");
}
};
});

View File

@ -71,6 +71,7 @@ let AllTabs = {
#include iq.js
#include storage.js
#include storagePolicy.js
#include items.js
#include groupitems.js
#include tabitems.js

View File

@ -44,7 +44,6 @@
let ThumbnailStorage = {
CACHE_CLIENT_IDENTIFIER: "tabview-cache",
CACHE_PREFIX: "moz-panorama:",
PREF_DISK_CACHE_SSL: "browser.cache.disk_cache_ssl",
// Holds the cache session reference
_cacheSession: null,
@ -55,15 +54,6 @@ let ThumbnailStorage = {
// Holds the storage stream reference
_storageStream: null,
// Holds the progress listener reference
_progressListener: null,
// Used to keep track of disk_cache_ssl preference
enablePersistentHttpsCaching: null,
// Used to keep track of browsers whose thumbs we shouldn't save
excludedBrowsers: [],
// ----------
// Function: toString
// Prints [ThumbnailStorage] for debug use.
@ -87,40 +77,6 @@ let ThumbnailStorage = {
this._storageStream = Components.Constructor(
"@mozilla.org/storagestream;1", "nsIStorageStream",
"init");
// store the preference value
this.enablePersistentHttpsCaching =
Services.prefs.getBoolPref(this.PREF_DISK_CACHE_SSL);
Services.prefs.addObserver(this.PREF_DISK_CACHE_SSL, this, false);
let self = this;
// tabs are already loaded before UI is initialized so cache-control
// values are unknown. We add browsers with https to the list for now.
gBrowser.browsers.forEach(function(browser) {
let checkAndAddToList = function(browserObj) {
if (!self.enablePersistentHttpsCaching &&
browserObj.currentURI.schemeIs("https"))
self.excludedBrowsers.push(browserObj);
};
if (browser.contentDocument.readyState != "complete" ||
browser.webProgress.isLoadingDocument) {
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
checkAndAddToList(browser);
}, true);
} else {
checkAndAddToList(browser);
}
});
gBrowser.addTabsProgressListener(this);
},
// Function: uninit
// Should be called when window is unloaded.
uninit: function ThumbnailStorage_uninit() {
gBrowser.removeTabsProgressListener(this);
Services.prefs.removeObserver(this.PREF_DISK_CACHE_SSL, this);
},
// ----------
@ -128,20 +84,38 @@ let ThumbnailStorage = {
// Opens a cache entry for the given <url> and requests access <access>.
// Calls <successCallback>(entry) when the entry was successfully opened with
// requested access rights. Otherwise calls <errorCallback>().
_openCacheEntry: function ThumbnailStorage__openCacheEntry(url, access, successCallback, errorCallback) {
let onCacheEntryAvailable = function(entry, accessGranted, status) {
//
// Parameters:
// url - the url to use as the storage key
// access - access flags, see Ci.nsICache.ACCESS_*
// successCallback - the callback to be called on success
// errorCallback - the callback to be called when an error occured
// options - an object with additional parameters, see below
//
// Possible options:
// synchronously - set to true to force sync mode
_openCacheEntry:
function ThumbnailStorage__openCacheEntry(url, access, successCallback,
errorCallback, options) {
Utils.assert(url, "invalid or missing argument <url>");
Utils.assert(access, "invalid or missing argument <access>");
Utils.assert(successCallback, "invalid or missing argument <successCallback>");
Utils.assert(errorCallback, "invalid or missing argument <errorCallback>");
function onCacheEntryAvailable(entry, accessGranted, status) {
if (entry && access == accessGranted && Components.isSuccessCode(status)) {
successCallback(entry);
} else {
entry && entry.close();
if (entry)
entry.close();
errorCallback();
}
}
let key = this.CACHE_PREFIX + url;
// switch to synchronous mode if parent window is about to close
if (UI.isDOMWindowClosing) {
if (options && options.synchronously) {
let entry = this._cacheSession.openCacheEntry(key, access, true);
let status = Cr.NS_OK;
onCacheEntryAvailable(entry, entry.accessGranted, status);
@ -151,55 +125,40 @@ let ThumbnailStorage = {
}
},
// Function: _shouldSaveThumbnail
// Checks whether to save tab's thumbnail or not.
_shouldSaveThumbnail : function ThumbnailStorage__shouldSaveThumbnail(tab) {
return (this.excludedBrowsers.indexOf(tab.linkedBrowser) == -1);
},
// ----------
// Function: saveThumbnail
// Saves the <imageData> to the cache using the given <url> as key.
// Calls <callback>(status, data) when finished, passing true or false
// (indicating whether the operation succeeded).
saveThumbnail: function ThumbnailStorage_saveThumbnail(tab, imageData, callback) {
Utils.assert(tab, "tab");
Utils.assert(imageData, "imageData");
if (!this._shouldSaveThumbnail(tab)) {
tab._tabViewTabItem._sendToSubscribers("deniedToCacheImageData");
if (callback)
callback(false);
return;
}
// Saves the given thumbnail in the cache.
//
// Parameters:
// url - the url to use as the storage key
// imageData - the image data to save for the given key
// callback - the callback that is called when the operation is finished
// options - an object with additional parameters, see below
//
// Possible options:
// synchronously - set to true to force sync mode
saveThumbnail:
function ThumbnailStorage_saveThumbnail(url, imageData, callback, options) {
Utils.assert(url, "invalid or missing argument <url>");
Utils.assert(imageData, "invalid or missing argument <imageData>");
Utils.assert(callback, "invalid or missing argument <callback>");
let synchronously = (options && options.synchronously);
let self = this;
let completed = function(status) {
if (callback)
callback(status);
if (status) {
// Notify subscribers
tab._tabViewTabItem._sendToSubscribers("savedCachedImageData");
} else {
Utils.log("Error while saving thumbnail: " + e);
}
};
let onCacheEntryAvailable = function(entry) {
function onCacheEntryAvailable(entry) {
let outputStream = entry.openOutputStream(0);
let cleanup = function() {
function cleanup() {
outputStream.close();
entry.close();
}
// switch to synchronous mode if parent window is about to close
if (UI.isDOMWindowClosing) {
// synchronous mode
if (synchronously) {
outputStream.write(imageData, imageData.length);
cleanup();
completed(true);
callback();
return;
}
@ -208,43 +167,32 @@ let ThumbnailStorage = {
gNetUtil.asyncCopy(inputStream, outputStream, function (result) {
cleanup();
inputStream.close();
completed(Components.isSuccessCode(result));
callback(Components.isSuccessCode(result) ? "" : "failure");
});
}
let onCacheEntryUnavailable = function() {
completed(false);
function onCacheEntryUnavailable() {
callback("unavailable");
}
this._openCacheEntry(tab.linkedBrowser.currentURI.spec,
Ci.nsICache.ACCESS_WRITE, onCacheEntryAvailable,
onCacheEntryUnavailable);
this._openCacheEntry(url, Ci.nsICache.ACCESS_WRITE, onCacheEntryAvailable,
onCacheEntryUnavailable, options);
},
// ----------
// Function: loadThumbnail
// Asynchrously loads image data from the cache using the given <url> as key.
// Calls <callback>(status, data) when finished, passing true or false
// (indicating whether the operation succeeded) and the retrieved image data.
loadThumbnail: function ThumbnailStorage_loadThumbnail(tab, url, callback) {
Utils.assert(tab, "tab");
Utils.assert(url, "url");
Utils.assert(typeof callback == "function", "callback arg must be a function");
// Loads a thumbnail from the cache.
//
// Parameters:
// url - the url to use as the storage key
// callback - the callback that is called when the operation is finished
loadThumbnail: function ThumbnailStorage_loadThumbnail(url, callback) {
Utils.assert(url, "invalid or missing argument <url>");
Utils.assert(callback, "invalid or missing argument <callback>");
let self = this;
let completed = function(status, imageData) {
callback(status, imageData);
if (status) {
// Notify subscribers
tab._tabViewTabItem._sendToSubscribers("loadedCachedImageData");
} else {
Utils.log("Error while loading thumbnail");
}
}
let onCacheEntryAvailable = function(entry) {
function onCacheEntryAvailable(entry) {
let imageChunks = [];
let nativeInputStream = entry.openInputStream(0);
@ -278,71 +226,16 @@ let ThumbnailStorage = {
}
cleanup();
completed(isSuccess, imageData);
callback(isSuccess ? "" : "failure", imageData);
});
}
let onCacheEntryUnavailable = function() {
completed(false);
function onCacheEntryUnavailable() {
callback("unavailable");
}
this._openCacheEntry(url, Ci.nsICache.ACCESS_READ,
onCacheEntryAvailable, onCacheEntryUnavailable);
},
// ----------
// Function: observe
// Implements the observer interface.
observe: function ThumbnailStorage_observe(subject, topic, data) {
this.enablePersistentHttpsCaching =
Services.prefs.getBoolPref(this.PREF_DISK_CACHE_SSL);
},
// ----------
// Implements progress listener interface.
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
Ci.nsISupportsWeakReference,
Ci.nsISupports]),
onStateChange: function ThumbnailStorage_onStateChange(
browser, webProgress, request, flag, status) {
if (flag & Ci.nsIWebProgressListener.STATE_START &&
flag & Ci.nsIWebProgressListener.STATE_IS_WINDOW) {
// ensure the dom window is the top one
if (webProgress.DOMWindow.parent == webProgress.DOMWindow) {
let index = this.excludedBrowsers.indexOf(browser);
if (index != -1)
this.excludedBrowsers.splice(index, 1);
}
}
if (flag & Ci.nsIWebProgressListener.STATE_STOP &&
flag & Ci.nsIWebProgressListener.STATE_IS_WINDOW) {
// ensure the dom window is the top one
if (webProgress.DOMWindow.parent == webProgress.DOMWindow &&
request && request instanceof Ci.nsIHttpChannel) {
request.QueryInterface(Ci.nsIHttpChannel);
let inhibitPersistentThumb = false;
if (request.isNoStoreResponse()) {
inhibitPersistentThumb = true;
} else if (!this.enablePersistentHttpsCaching &&
request.URI.schemeIs("https")) {
let cacheControlHeader;
try {
cacheControlHeader = request.getResponseHeader("Cache-Control");
} catch(e) {
// this error would occur when "Cache-Control" doesn't exist in
// the eaders
}
if (cacheControlHeader && !(/public/i).test(cacheControlHeader))
inhibitPersistentThumb = true;
}
if (inhibitPersistentThumb &&
this.excludedBrowsers.indexOf(browser) == -1)
this.excludedBrowsers.push(browser);
}
}
this._openCacheEntry(url, Ci.nsICache.ACCESS_READ, onCacheEntryAvailable,
onCacheEntryUnavailable);
}
}

View File

@ -175,6 +175,9 @@ let UI = {
// ___ storage
Storage.init();
// ___ storage policy
StoragePolicy.init();
if (Storage.readWindowBusyState(gWindow))
this.storageBusy();
@ -280,13 +283,16 @@ let UI = {
gWindow.addEventListener("SSWindowClosing", function onWindowClosing() {
gWindow.removeEventListener("SSWindowClosing", onWindowClosing, false);
// XXX bug #635975 - don't unlink the tab if the dom window is closing.
self.isDOMWindowClosing = true;
if (self.isTabViewVisible())
GroupItems.removeHiddenGroups();
TabItems.saveAll();
TabItems.saveAllThumbnails({synchronously: true});
Storage.saveActiveGroupName(gWindow);
TabItems.saveAll(true);
self._save();
}, false);
@ -323,7 +329,7 @@ let UI = {
TabItems.uninit();
GroupItems.uninit();
Storage.uninit();
ThumbnailStorage.uninit();
StoragePolicy.uninit();
this._removeTabActionHandlers();
this._currentTab = null;
@ -713,6 +719,11 @@ let UI = {
if (data == "enter" || data == "exit") {
hideSearch();
self._privateBrowsing.transitionMode = data;
// make sure to save all thumbnails that haven't been saved yet
// before we enter the private browsing mode
if (data == "enter")
TabItems.saveAllThumbnails({synchronously: true});
}
} else if (topic == "private-browsing-transition-complete") {
// We use .transitionMode here, as aData is empty.

View File

@ -82,7 +82,6 @@ _BROWSER_FILES = \
browser_tabview_bug600812.js \
browser_tabview_bug602432.js \
browser_tabview_bug604098.js \
browser_tabview_bug604699.js \
browser_tabview_bug606657.js \
browser_tabview_bug606905.js \
browser_tabview_bug607108.js \
@ -114,7 +113,6 @@ _BROWSER_FILES = \
browser_tabview_bug626455.js \
browser_tabview_bug626525.js \
browser_tabview_bug626791.js \
browser_tabview_bug627239.js \
browser_tabview_bug627288.js \
browser_tabview_bug627736.js \
browser_tabview_bug628061.js \
@ -155,6 +153,7 @@ _BROWSER_FILES = \
browser_tabview_bug669694.js \
browser_tabview_bug673196.js \
browser_tabview_bug673729.js \
browser_tabview_bug677310.js \
browser_tabview_bug679853.js \
browser_tabview_bug681599.js \
browser_tabview_click_group.js \
@ -170,6 +169,8 @@ _BROWSER_FILES = \
browser_tabview_search.js \
browser_tabview_snapping.js \
browser_tabview_startup_transitions.js \
browser_tabview_storage_policy.js \
browser_tabview_thumbnail_storage.js \
browser_tabview_undo_group.js \
dummy_page.html \
head.js \

View File

@ -34,7 +34,9 @@ function setupTwo(win) {
// force all canvases to update, and hook in imageData save detection
tabItems.forEach(function(tabItem) {
contentWindow.TabItems.update(tabItem.tab);
// mark thumbnail as dirty
tabItem.tabCanvas.paint();
tabItem.addSubscriber("savedCachedImageData", function onSaved(item) {
item.removeSubscriber("savedCachedImageData", onSaved);
@ -81,8 +83,8 @@ function setupTwo(win) {
let count = tabItems.length;
tabItems.forEach(function(tabItem) {
tabItem.addSubscriber("loadedCachedImageData", function onLoaded() {
tabItem.removeSubscriber("loadedCachedImageData", onLoaded);
tabItem.addSubscriber("showingCachedData", function onLoaded() {
tabItem.removeSubscriber("showingCachedData", onLoaded);
ok(tabItem.isShowingCachedData(),
"Tab item is showing cached data and is just connected. " +
tabItem.tab.linkedBrowser.currentURI.spec);

View File

@ -1,85 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
let url = "http://www.example.com/";
let cw;
let tab = gBrowser.tabs[0];
let finishTest = function () {
is(1, gBrowser.tabs.length, "there is one tab, only");
ok(!TabView.isVisible(), "tabview is not visible");
finish();
}
waitForExplicitFinish();
let testErroneousLoading = function () {
cw.ThumbnailStorage.loadThumbnail(tab, url, function (status, data) {
ok(!status, "thumbnail entry failed to load");
is(null, data, "no thumbnail data received");
next();
});
}
let testAsynchronousSaving = function () {
let saved = false;
let data = "thumbnail-data-asynchronous";
cw.ThumbnailStorage.saveThumbnail(tab, data, function (status) {
ok(status, "thumbnail entry was saved");
ok(saved, "thumbnail was saved asynchronously");
cw.ThumbnailStorage.loadThumbnail(tab, url, function (status, imageData) {
ok(status, "thumbnail entry was loaded");
is(imageData, data, "valid thumbnail data received");
next();
});
});
saved = true;
}
let testSynchronousSaving = function () {
let saved = false;
let data = "thumbnail-data-synchronous";
cw.UI.isDOMWindowClosing = true;
registerCleanupFunction(function () cw.UI.isDOMWindowClosing = false);
cw.ThumbnailStorage.saveThumbnail(tab, data, function (status) {
ok(status, "thumbnail entry was saved");
ok(!saved, "thumbnail was saved synchronously");
cw.ThumbnailStorage.loadThumbnail(tab, url, function (status, imageData) {
ok(status, "thumbnail entry was loaded");
is(imageData, data, "valid thumbnail data received");
cw.UI.isDOMWindowClosing = false;
next();
});
});
saved = true;
}
let tests = [testErroneousLoading, testAsynchronousSaving, testSynchronousSaving];
let next = function () {
let test = tests.shift();
if (test)
test();
else
hideTabView(finishTest);
}
tab.linkedBrowser.loadURI(url);
afterAllTabsLoaded(function() {
showTabView(function () {
registerCleanupFunction(function () TabView.hide());
cw = TabView.getContentWindow();
next();
});
});
}

View File

@ -22,8 +22,8 @@ function test() {
tabItem.addSubscriber("savedCachedImageData", function onSaved() {
tabItem.removeSubscriber("savedCachedImageData", onSaved);
tabItem.addSubscriber("loadedCachedImageData", function onLoaded() {
tabItem.removeSubscriber("loadedCachedImageData", onLoaded);
tabItem.addSubscriber("showingCachedData", function onLoaded() {
tabItem.removeSubscriber("showingCachedData", onLoaded);
ok(tabItem.isShowingCachedData(), 'tabItem shows cached data');
testChangeUrlAfterReconnect();
@ -33,6 +33,7 @@ function test() {
});
cw.Storage.saveTab(tab, data);
tabItem.saveThumbnail();
});
});
}

View File

@ -0,0 +1,48 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
let pb = Cc["@mozilla.org/privatebrowsing;1"].
getService(Ci.nsIPrivateBrowsingService);
function test() {
let thumbnailsSaved = false;
waitForExplicitFinish();
registerCleanupFunction(function () {
ok(thumbnailsSaved, "thumbs have been saved before entering pb mode");
pb.privateBrowsingEnabled = false;
});
afterAllTabsLoaded(function () {
showTabView(function () {
hideTabView(function () {
let numConditions = 2;
function check() {
if (--numConditions)
return;
togglePrivateBrowsing(finish);
}
let tabItem = gBrowser.tabs[0]._tabViewTabItem;
// save all thumbnails synchronously to cancel all delayed thumbnail
// saves that might be active
tabItem.saveThumbnail({synchronously: true});
// force a tabCanvas paint to flag the thumbnail as dirty
tabItem.tabCanvas.paint();
tabItem.addSubscriber("savedCachedImageData", function onSaved() {
tabItem.removeSubscriber("savedCachedImageData", onSaved);
thumbnailsSaved = true;
check();
});
togglePrivateBrowsing(check);
});
});
});
}

View File

@ -1,7 +1,12 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const PREF_DISK_CACHE_SSL = "browser.cache.disk_cache_ssl";
let pb = Cc["@mozilla.org/privatebrowsing;1"].
getService(Ci.nsIPrivateBrowsingService);
let contentWindow;
let enablePersistentHttpsCaching;
let newTab;
function test() {
@ -17,8 +22,8 @@ function test() {
gBrowser.removeTab(gBrowser.tabs[1]);
hideTabView();
contentWindow.ThumbnailStorage.enablePersistentHttpsCaching =
enablePersistentHttpsCaching;
Services.prefs.clearUserPref(PREF_DISK_CACHE_SSL);
pb.privateBrowsingEnabled = false;
});
showTabView(function() {
@ -31,18 +36,19 @@ function test() {
function test1() {
// page with cache-control: no-store, should not save thumbnail
HttpRequestObserver.cacheControlValue = "no-store";
newTab.linkedBrowser.loadURI("http://www.example.com/browser/browser/base/content/test/tabview/dummy_page.html");
afterAllTabsLoaded(function() {
whenStorageDenied(newTab, function () {
let tabItem = newTab._tabViewTabItem;
ok(!contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab),
ok(!contentWindow.StoragePolicy.canStoreThumbnailForTab(newTab),
"Should not save the thumbnail for tab");
whenDeniedToCacheImageData(tabItem, test2);
tabItem.save(true);
whenDeniedToSaveImageData(tabItem, test2);
tabItem.saveThumbnail({synchronously: true});
HttpRequestObserver.cacheControlValue = null;
});
newTab.linkedBrowser.loadURI("http://www.example.com/browser/browser/base/content/test/tabview/dummy_page.html");
}
function test2() {
@ -53,11 +59,11 @@ function test2() {
afterAllTabsLoaded(function() {
let tabItem = newTab._tabViewTabItem;
ok(contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab),
ok(contentWindow.StoragePolicy.canStoreThumbnailForTab(newTab),
"Should save the thumbnail for tab");
whenSavedCachedImageData(tabItem, test3);
tabItem.save(true);
tabItem.saveThumbnail({synchronously: true});
});
}
@ -65,19 +71,17 @@ function test3() {
// page with cache-control: private with https caching enabled, should save thumbnail
HttpRequestObserver.cacheControlValue = "private";
enablePersistentHttpsCaching =
contentWindow.ThumbnailStorage.enablePersistentHttpsCaching;
contentWindow.ThumbnailStorage.enablePersistentHttpsCaching = true;
Services.prefs.setBoolPref(PREF_DISK_CACHE_SSL, true);
newTab.linkedBrowser.loadURI("https://example.com/browser/browser/base/content/test/tabview/dummy_page.html");
afterAllTabsLoaded(function() {
let tabItem = newTab._tabViewTabItem;
ok(contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab),
ok(contentWindow.StoragePolicy.canStoreThumbnailForTab(newTab),
"Should save the thumbnail for tab");
whenSavedCachedImageData(tabItem, test4);
tabItem.save(true);
tabItem.saveThumbnail({synchronously: true});
});
}
@ -85,38 +89,52 @@ function test4() {
// page with cache-control: public with https caching disabled, should save thumbnail
HttpRequestObserver.cacheControlValue = "public";
contentWindow.ThumbnailStorage.enablePersistentHttpsCaching = false;
Services.prefs.setBoolPref(PREF_DISK_CACHE_SSL, false);
newTab.linkedBrowser.loadURI("https://example.com/browser/browser/base/content/test/tabview/");
afterAllTabsLoaded(function() {
let tabItem = newTab._tabViewTabItem;
ok(contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab),
ok(contentWindow.StoragePolicy.canStoreThumbnailForTab(newTab),
"Should save the thumbnail for tab");
whenSavedCachedImageData(tabItem, test5);
tabItem.save(true);
tabItem.saveThumbnail({synchronously: true});
});
}
function test5() {
// page with cache-control: private with https caching disabled, should not save thumbnail
HttpRequestObserver.cacheControlValue = "private";
newTab.linkedBrowser.loadURI("https://example.com/");
afterAllTabsLoaded(function() {
whenStorageDenied(newTab, function () {
let tabItem = newTab._tabViewTabItem;
ok(!contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab),
"Should not the thumbnail for tab");
ok(!contentWindow.StoragePolicy.canStoreThumbnailForTab(newTab),
"Should not save the thumbnail for tab");
whenDeniedToCacheImageData(tabItem, function () {
hideTabView(function () {
gBrowser.removeTab(gBrowser.tabs[1]);
finish();
});
whenDeniedToSaveImageData(tabItem, function () {
gBrowser.removeTab(newTab);
test6();
});
tabItem.save(true);
tabItem.saveThumbnail({synchronously: true});
});
newTab.linkedBrowser.loadURI("https://example.com/");
}
// ensure that no thumbnails are saved while in private browsing mode
function test6() {
HttpRequestObserver.cacheControlValue = "public";
togglePrivateBrowsing(function () {
let tab = gBrowser.tabs[0];
ok(!contentWindow.StoragePolicy.canStoreThumbnailForTab(tab),
"Should not save the thumbnail for tab");
togglePrivateBrowsing(finish);
});
}
@ -146,9 +164,18 @@ function whenSavedCachedImageData(tabItem, callback) {
});
}
function whenDeniedToCacheImageData(tabItem, callback) {
tabItem.addSubscriber("deniedToCacheImageData", function onDenied() {
tabItem.removeSubscriber("deniedToCacheImageData", onDenied);
function whenDeniedToSaveImageData(tabItem, callback) {
tabItem.addSubscriber("deniedToSaveImageData", function onDenied() {
tabItem.removeSubscriber("deniedToSaveImageData", onDenied);
callback();
});
}
function whenStorageDenied(tab, callback) {
let mm = tab.linkedBrowser.messageManager;
mm.addMessageListener("Panorama:StoragePolicy:denied", function onDenied() {
mm.removeMessageListener("Panorama:StoragePolicy:denied", onDenied);
executeSoon(callback);
});
}

View File

@ -0,0 +1,161 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
let tests = [testRawSyncSave, testRawAsyncSave, testRawLoadError,
testAsyncSave, testSyncSave, testOverrideAsyncSave,
testSaveCleanThumbnail];
function test() {
waitForExplicitFinish();
loadTabView(next);
}
function testRawSyncSave() {
let cw = TabView.getContentWindow();
let url = "http://example.com/sync-url";
let data = "thumbnail-data-sync";
let saved = false;
cw.ThumbnailStorage.saveThumbnail(url, data, function (error) {
ok(!error, "thumbnail entry was saved");
ok(!saved, "thumbnail was saved synchronously");
cw.ThumbnailStorage.loadThumbnail(url, function (error, imageData) {
ok(!error, "thumbnail entry was loaded");
is(imageData, data, "valid thumbnail data received");
next();
});
}, {synchronously: true});
saved = true;
}
function testRawAsyncSave() {
let cw = TabView.getContentWindow();
let url = "http://example.com/async-url";
let data = "thumbnail-data-async";
let saved = false;
cw.ThumbnailStorage.saveThumbnail(url, data, function (error) {
ok(!error, "thumbnail entry was saved");
ok(saved, "thumbnail was saved asynchronously");
cw.ThumbnailStorage.loadThumbnail(url, function (error, imageData) {
ok(!error, "thumbnail entry was loaded");
is(imageData, data, "valid thumbnail data received");
next();
});
});
saved = true;
}
function testRawLoadError() {
let cw = TabView.getContentWindow();
cw.ThumbnailStorage.loadThumbnail("non-existant-url", function (error, data) {
ok(error, "thumbnail entry failed to load");
is(null, data, "no thumbnail data received");
next();
});
}
function testSyncSave() {
let tabItem = gBrowser.tabs[0]._tabViewTabItem;
// set the thumbnail to dirty
tabItem.tabCanvas.paint();
let saved = false;
whenThumbnailSaved(tabItem, function () {
ok(!saved, "thumbnail was saved synchronously");
next();
});
tabItem.saveThumbnail({synchronously: true});
saved = true;
}
function testAsyncSave() {
let tabItem = gBrowser.tabs[0]._tabViewTabItem;
// set the thumbnail to dirty
tabItem.tabCanvas.paint();
let saved = false;
whenThumbnailSaved(tabItem, function () {
ok(saved, "thumbnail was saved asynchronously");
next();
});
tabItem.saveThumbnail();
saved = true;
}
function testOverrideAsyncSave() {
let tabItem = gBrowser.tabs[0]._tabViewTabItem;
// set the thumbnail to dirty
tabItem.tabCanvas.paint();
// initiate async save
tabItem.saveThumbnail();
let saveCount = 0;
whenThumbnailSaved(tabItem, function () {
saveCount = 1;
});
tabItem.saveThumbnail({synchronously: true});
is(saveCount, 1, "thumbnail got saved once");
next();
}
function testSaveCleanThumbnail() {
let tabItem = gBrowser.tabs[0]._tabViewTabItem;
// set the thumbnail to dirty
tabItem.tabCanvas.paint();
let saveCount = 0;
whenThumbnailSaved(tabItem, function () saveCount++);
tabItem.saveThumbnail({synchronously: true});
tabItem.saveThumbnail({synchronously: true});
is(saveCount, 1, "thumbnail got saved once, only");
next();
}
// ----------
function whenThumbnailSaved(tabItem, callback) {
tabItem.addSubscriber("savedCachedImageData", function onSaved() {
tabItem.removeSubscriber("savedCachedImageData", onSaved);
callback();
});
}
// ----------
function loadTabView(callback) {
afterAllTabsLoaded(function () {
showTabView(function () {
hideTabView(callback);
});
});
}
// ----------
function next() {
let test = tests.shift();
if (test) {
info("* running " + test.name + "...");
test();
} else {
finish();
}
}

View File

@ -1,8 +1,7 @@
pref("startup.homepage_override_url","http://www.mozilla.org/projects/%APP%/%VERSION%/whatsnew/");
pref("startup.homepage_welcome_url","http://www.mozilla.org/projects/%APP%/%VERSION%/firstrun/");
// The time interval between checks for a new version (in seconds)
// nightly=8 hours, official=24 hours
pref("app.update.interval", 28800);
pref("app.update.interval", 7200); // 2 hours
// The time interval between the downloading of mar file chunks in the
// background (in seconds)
pref("app.update.download.backgroundInterval", 60);

View File

@ -1,8 +1,7 @@
pref("startup.homepage_override_url","http://www.mozilla.org/projects/%APP%/%VERSION%/whatsnew/");
pref("startup.homepage_welcome_url","http://www.mozilla.org/projects/%APP%/%VERSION%/firstrun/");
// The time interval between checks for a new version (in seconds)
// nightly=8 hours, official=24 hours
pref("app.update.interval", 28800);
pref("app.update.interval", 86400); // 24 hours
// The time interval between the downloading of mar file chunks in the
// background (in seconds)
pref("app.update.download.backgroundInterval", 60);

View File

@ -486,6 +486,11 @@ SessionStoreService.prototype = {
this._forEachBrowserWindow(function(aWindow) {
this._collectWindowData(aWindow);
});
// we must cache this because _getMostRecentBrowserWindow will always
// return null by the time quit-application occurs
var activeWindow = this._getMostRecentBrowserWindow();
if (activeWindow)
this.activeWindowSSiCache = activeWindow.__SSi || "";
this._dirtyWindows = [];
break;
case "quit-application-granted":
@ -1512,6 +1517,13 @@ SessionStoreService.prototype = {
let lastWindow = this._getMostRecentBrowserWindow();
let canUseLastWindow = lastWindow &&
!lastWindow.__SS_lastSessionWindowID;
let lastSessionFocusedWindow = null;
this.windowToFocus = lastWindow;
// move the last focused window to the start of the array so that we
// minimize window movement (see bug 669272)
lastSessionState.windows.unshift(
lastSessionState.windows.splice(lastSessionState.selectedWindow - 1, 1)[0]);
// Restore into windows or open new ones as needed.
for (let i = 0; i < lastSessionState.windows.length; i++) {
@ -1549,9 +1561,18 @@ SessionStoreService.prototype = {
// weirdness but we will still merge other extData.
// Bug 588217 should make this go away by merging the group data.
this.restoreWindow(windowToUse, { windows: [winState] }, canOverwriteTabs, true);
if (i == 0)
lastSessionFocusedWindow = windowToUse;
// if we overwrote the tabs for our last focused window, we should
// give focus to the window that had it in the previous session
if (canOverwriteTabs && windowToUse == lastWindow)
this.windowToFocus = lastSessionFocusedWindow;
}
else {
this._openWindowWithState({ windows: [winState] });
let win = this._openWindowWithState({ windows: [winState] });
if (i == 0)
lastSessionFocusedWindow = win;
}
}
@ -2544,8 +2565,12 @@ SessionStoreService.prototype = {
this._closedWindows = root._closedWindows;
var winData;
if (!aState.selectedWindow) {
aState.selectedWindow = 0;
if (!root.selectedWindow) {
root.selectedWindow = 0;
} else {
// put the selected window at the beginning of the array to ensure that
// it gets restored first
root.windows.unshift(root.windows.splice(root.selectedWindow - 1, 1)[0]);
}
// open new windows for all further window entries of a multi-window session
// (unless they don't contain any tab data)
@ -2553,9 +2578,6 @@ SessionStoreService.prototype = {
winData = root.windows[w];
if (winData && winData.tabs && winData.tabs[0]) {
var window = this._openWindowWithState({ windows: [winData] });
if (w == aState.selectedWindow - 1) {
this.windowToFocus = window;
}
}
}
winData = root.windows[0];

View File

@ -55,7 +55,13 @@ var StyleInspector = {
return Services.prefs.getBoolPref("devtools.styleinspector.enabled");
},
createPanel: function SI_createPanel()
/**
* Factory method to create the actual style panel
* @param {Boolean} aPreserveOnHide Prevents destroy from being called
* onpopuphide. USE WITH CAUTION: When this value is set to true then you are
* responsible to manually call destroy from outside the style inspector.
*/
createPanel: function SI_createPanel(aPreserveOnHide)
{
let win = Services.wm.getMostRecentWindow("navigator:browser");
let popupSet = win.document.getElementById("mainPopupSet");
@ -98,7 +104,10 @@ var StyleInspector = {
hbox.appendChild(resizer);
popupSet.appendChild(panel);
panel.addEventListener("popupshown", function SI_popup_shown() {
/**
* Initialize the popup when it is first shown
*/
function SI_popupShown() {
if (!this.cssHtmlTree) {
this.cssLogic = new CssLogic();
this.cssHtmlTree = new CssHtmlTree(iframe, this.cssLogic, this);
@ -107,12 +116,23 @@ var StyleInspector = {
this.cssLogic.highlight(this.selectedNode);
this.cssHtmlTree.highlight(this.selectedNode);
Services.obs.notifyObservers(null, "StyleInspector-opened", null);
}, false);
}
/**
* Hide the popup and conditionally destroy it
*/
function SI_popupHidden() {
if (panel.preserveOnHide) {
Services.obs.notifyObservers(null, "StyleInspector-closed", null);
} else {
panel.destroy();
}
}
panel.addEventListener("popupshown", SI_popupShown);
panel.addEventListener("popuphidden", SI_popupHidden);
panel.preserveOnHide = !!aPreserveOnHide;
panel.addEventListener("popuphidden", function SI_popup_hidden() {
Services.obs.notifyObservers(null, "StyleInspector-closed", null);
}, false);
/**
* Check if the style inspector is open
*/
@ -138,6 +158,19 @@ var StyleInspector = {
}
};
/**
* Destroy the style panel, remove listeners etc.
*/
panel.destroy = function SI_destroy()
{
this.cssLogic = null;
this.cssHtmlTree = null;
this.removeEventListener("popupshown", SI_popupShown);
this.removeEventListener("popuphidden", SI_popupHidden);
this.parentNode.removeChild(this);
Services.obs.notifyObservers(null, "StyleInspector-closed", null);
};
/**
* Is the Style Inspector initialized?
* @returns {Boolean} true or false

View File

@ -1786,7 +1786,6 @@ HUD_SERVICE.prototype =
panels = popupset.querySelectorAll("panel[hudToolId=" + aHUDId + "]");
for (let i = 0; i < panels.length; i++) {
panels[i].hidePopup();
popupset.removeChild(panels[i]);
}
let id = ConsoleUtils.supString(aHUDId);

View File

@ -179,6 +179,7 @@
@BINPATH@/components/jar.xpt
@BINPATH@/components/jetpack.xpt
@BINPATH@/components/jsdservice.xpt
@BINPATH@/components/jsdebugger.xpt
@BINPATH@/components/layout_base.xpt
@BINPATH@/components/layout_forms.xpt
#ifdef NS_PRINTING

View File

@ -811,9 +811,22 @@ toolbar[mode="icons"] #zoom-in-button {
background-clip: padding-box;
}
#urlbar:-moz-window-inactive,
.searchbar-textbox:-moz-window-inactive {
border-color: @toolbarbuttonInactiveBorderColor@;
@media (-moz-mac-lion-theme) {
#urlbar,
.searchbar-textbox {
background-image: -moz-linear-gradient(hsl(0,0%,97%), hsl(0,0%,100%));
border-color: hsla(0,0%,0%,.35) hsla(0,0%,0%,.25) hsla(0,0%,0%,.15);
box-shadow: 0 1px 0 hsla(0,0%,100%,.2),
inset 0 0 1px hsla(0,0%,0%,.05),
inset 0 1px 2px hsla(0,0%,0%,.1);
}
}
@media not all and (-moz-mac-lion-theme) {
#urlbar:-moz-window-inactive,
.searchbar-textbox:-moz-window-inactive {
border-color: @toolbarbuttonInactiveBorderColor@;
}
}
#urlbar[focused="true"],
@ -2566,3 +2579,48 @@ panel[dimmed="true"] {
box-shadow: 0 0 0 1px black;
outline-color: white;
}
/* Highlighter toolbar */
#inspector-toolbar {
-moz-appearance: none;
height: 32px;
padding: 0 3px;
border-top: 1px solid hsla(210, 8%, 5%, .65);
box-shadow: 0 1px 0 0 hsla(210, 16%, 76%, .2) inset;
background-image: -moz-linear-gradient(top, hsl(210,11%,36%), hsl(210,11%,18%));
}
#inspector-inspect-toolbutton,
#inspector-tools > toolbarbutton {
-moz-appearance: none;
width: 78px;
margin: 3px 5px;
color: hsl(210,30%,85%);
text-shadow: 0 -1px 0 hsla(210,8%,5%,.45);
border: 1px solid hsla(210,8%,5%,.45);
border-radius: @toolbarbuttonCornerRadius@;
background: -moz-linear-gradient(hsla(212,7%,57%,.35), hsla(212,7%,57%,.1));
background-clip: padding-box;
box-shadow: 0 1px 0 hsla(210,16%,76%,.15) inset, 0 0 0 1px hsla(210,16%,76%,.15) inset, 0 1px 0 hsla(210,16%,76%,.15);
}
#inspector-inspect-toolbutton:not([checked]):hover:active,
#inspector-tools > toolbarbutton:not([checked]):hover:active {
border-color: hsla(210,8%,5%,.6);
background: -moz-linear-gradient(hsla(220,6%,10%,.3), hsla(212,7%,57%,.15) 65%, hsla(212,7%,57%,.3));
box-shadow: 0 0 3px hsla(210,8%,5%,.25) inset, 0 1px 3px hsla(210,8%,5%,.25) inset, 0 1px 0 hsla(210,16%,76%,.15);
}
#inspector-inspect-toolbutton[checked],
#inspector-tools > toolbarbutton[checked] {
color: hsl(208,100%,60%) !important;
border-color: hsla(210,8%,5%,.6);
background: -moz-linear-gradient(hsla(220,6%,10%,.6), hsla(210,11%,18%,.45) 75%, hsla(210,11%,30%,.4));
box-shadow: 0 1px 3px hsla(210,8%,5%,.25) inset, 0 1px 3px hsla(210,8%,5%,.25) inset, 0 1px 0 hsla(210,16%,76%,.15);
}
#inspector-inspect-toolbutton[checked]:hover:active,
#inspector-tools > toolbarbutton[checked]:hover:active {
background-color: hsla(210,8%,5%,.2);
}

View File

@ -0,0 +1,25 @@
dnl Set MOZ_FRAMEPTR_FLAGS to the flags that should be used for enabling or
dnl disabling frame pointers in this architecture based on the configure
dnl options
AC_DEFUN([MOZ_SET_FRAMEPTR_FLAGS], [
if test "$GNU_CC"; then
MOZ_ENABLE_FRAME_PTR="-fno-omit-frame-pointer"
MOZ_DISABLE_FRAME_PTR="-fomit-frame-pointer"
else
case "$target" in
*-mingw*)
MOZ_ENABLE_FRAME_PTR="-Oy-"
MOZ_DISABLE_FRAME_PTR="-Oy"
;;
esac
fi
# if we are debugging or profiling, we want a frame pointer.
if test -z "$MOZ_OPTIMIZE" -o \
-n "$MOZ_PROFILING" -o -n "$MOZ_DEBUG"; then
MOZ_FRAMEPTR_FLAGS="$MOZ_ENABLE_FRAME_PTR"
else
MOZ_FRAMEPTR_FLAGS="$MOZ_DISABLE_FRAME_PTR"
fi
])

View File

@ -2423,7 +2423,7 @@ nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj
// avoid wasting time checking properties of their classes etc in
// the loop.
if (jsClass == &js_FunctionClass) {
if (jsClass == &js::FunctionClass) {
aObj = aObj->getParent();
if (!aObj)
@ -2431,7 +2431,7 @@ nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj
jsClass = aObj->getClass();
if (jsClass == &js_CallClass) {
if (jsClass == &js::CallClass) {
aObj = aObj->getParent();
if (!aObj)

View File

@ -251,7 +251,6 @@ MOZ_XTF = @MOZ_XTF@
MOZ_SVG_DLISTS = @MOZ_SVG_DLISTS@
MOZ_CAIRO_CFLAGS = @MOZ_CAIRO_CFLAGS@
MOZ_SMIL = @MOZ_SMIL@
MOZ_XSLT_STANDALONE = @MOZ_XSLT_STANDALONE@
MOZ_PREF_EXTENSIONS = @MOZ_PREF_EXTENSIONS@
@ -304,6 +303,7 @@ ACDEFINES = @MOZ_DEFINES@
WARNINGS_AS_ERRORS = @WARNINGS_AS_ERRORS@
MOZ_OPTIMIZE = @MOZ_OPTIMIZE@
MOZ_FRAMEPTR_FLAGS = @MOZ_FRAMEPTR_FLAGS@
MOZ_OPTIMIZE_FLAGS = @MOZ_OPTIMIZE_FLAGS@
MOZ_PGO_OPTIMIZE_FLAGS = @MOZ_PGO_OPTIMIZE_FLAGS@
MOZ_OPTIMIZE_LDFLAGS = @MOZ_OPTIMIZE_LDFLAGS@

View File

@ -463,6 +463,9 @@ endif # MOZ_OPTIMIZE == 1
endif # MOZ_OPTIMIZE
endif # CROSS_COMPILE
CFLAGS += $(MOZ_FRAMEPTR_FLAGS)
CXXFLAGS += $(MOZ_FRAMEPTR_FLAGS)
# Check for FAIL_ON_WARNINGS & FAIL_ON_WARNINGS_DEBUG (Shorthand for Makefiles
# to request that we use the 'warnings as errors' compile flags)

View File

@ -2071,12 +2071,7 @@ case "$target" in
*-darwin*)
MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -o $@'
MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -o $@'
# If we're building with --enable-profiling, we need a frame pointer.
if test -z "$MOZ_PROFILING"; then
MOZ_OPTIMIZE_FLAGS="-O3 -fomit-frame-pointer"
else
MOZ_OPTIMIZE_FLAGS="-O3 -fno-omit-frame-pointer"
fi
MOZ_OPTIMIZE_FLAGS="-O3"
_PEDANTIC=
CFLAGS="$CFLAGS -fno-common"
CXXFLAGS="$CXXFLAGS -fno-common"
@ -2188,12 +2183,7 @@ ia64*-hpux*)
TARGET_NSPR_MDCPUCFG='\"md/_linux.cfg\"'
MOZ_GFX_OPTIMIZE_MOBILE=1
# If we're building with --enable-profiling, we need a frame pointer.
if test -z "$MOZ_PROFILING"; then
MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks -fno-reorder-functions -fomit-frame-pointer"
else
MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks -fno-reorder-functions -fno-omit-frame-pointer"
fi
MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks -fno-reorder-functions"
;;
*-*linux*)
@ -2211,14 +2201,8 @@ ia64*-hpux*)
# -Os is broken on gcc 4.1.x 4.2.x, 4.5.x we need to tweak it to get good results.
MOZ_OPTIMIZE_SIZE_TWEAK="-finline-limit=50"
esac
# If we're building with --enable-profiling, we need a frame pointer.
if test -z "$MOZ_PROFILING"; then
MOZ_FRAMEPTR_FLAGS="-fomit-frame-pointer"
else
MOZ_FRAMEPTR_FLAGS="-fno-omit-frame-pointer"
fi
MOZ_PGO_OPTIMIZE_FLAGS="-O3 $MOZ_FRAMEPTR_FLAGS"
MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks $MOZ_OPTIMIZE_SIZE_TWEAK $MOZ_FRAMEPTR_FLAGS"
MOZ_PGO_OPTIMIZE_FLAGS="-O3"
MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks $MOZ_OPTIMIZE_SIZE_TWEAK"
MOZ_DEBUG_FLAGS="-g"
fi
@ -2315,12 +2299,7 @@ ia64*-hpux*)
MOZ_DEBUG_FLAGS='-Zi'
MOZ_DEBUG_LDFLAGS='-DEBUG -DEBUGTYPE:CV'
WARNINGS_AS_ERRORS='-WX'
# If we're building with --enable-profiling, we need -Oy-, which forces a frame pointer.
if test -z "$MOZ_PROFILING"; then
MOZ_OPTIMIZE_FLAGS='-O1'
else
MOZ_OPTIMIZE_FLAGS='-O1 -Oy-'
fi
MOZ_OPTIMIZE_FLAGS='-O1'
MOZ_FIX_LINK_PATHS=
DYNAMIC_XPCOM_LIBS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xpcom_core.lib $(LIBXUL_DIST)/lib/mozalloc.lib'
XPCOM_FROZEN_LDOPTS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/mozalloc.lib'
@ -4485,7 +4464,6 @@ MOZ_TOOLKIT_SEARCH=1
MOZ_UI_LOCALE=en-US
MOZ_UNIVERSALCHARDET=1
MOZ_URL_CLASSIFIER=
MOZ_XSLT_STANDALONE=
MOZ_XTF=1
MOZ_XUL=1
MOZ_ZIPWRITER=1
@ -4541,8 +4519,6 @@ MOZ_ARG_ENABLE_STRING(application,
Options include:
browser (Firefox)
xulrunner
content/xslt (Standalone Transformiix XSLT)
netwerk (Standalone Necko)
tools/update-packaging (AUS-related packaging tools)],
[ MOZ_BUILD_APP=$enableval ] )
@ -4616,11 +4592,6 @@ browser)
xulrunner)
AC_DEFINE(MOZ_XULRUNNER)
;;
content/xslt)
AC_DEFINE(TX_EXE)
;;
esac
AC_SUBST(MOZ_BUILD_APP)
@ -6905,6 +6876,8 @@ else
MOZ_OPTIMIZE=
fi ], MOZ_OPTIMIZE=1)
MOZ_SET_FRAMEPTR_FLAGS
if test "$COMPILE_ENVIRONMENT"; then
if test -n "$MOZ_OPTIMIZE"; then
AC_MSG_CHECKING([for valid optimization flags])
@ -6923,6 +6896,7 @@ fi
fi # COMPILE_ENVIRONMENT
AC_SUBST(MOZ_OPTIMIZE)
AC_SUBST(MOZ_FRAMEPTR_FLAGS)
AC_SUBST(MOZ_OPTIMIZE_FLAGS)
AC_SUBST(MOZ_OPTIMIZE_LDFLAGS)
AC_SUBST(MOZ_OPTIMIZE_SIZE_TWEAK)
@ -8543,7 +8517,6 @@ AC_SUBST(MOZ_PERMISSIONS)
AC_SUBST(MOZ_XTF)
AC_SUBST(MOZ_PREF_EXTENSIONS)
AC_SUBST(MOZ_SMIL)
AC_SUBST(MOZ_XSLT_STANDALONE)
AC_SUBST(MOZ_JS_LIBS)
AC_SUBST(MOZ_PSM)
AC_SUBST(MOZ_DEBUG)

View File

@ -0,0 +1,2 @@
<!DOCTYPE html>
<img crossorigin>

View File

@ -93,3 +93,4 @@ load 642022-1.html
load 646184.html
load 658845-1.svg
load 667336-1.html
load 679689-1.html

View File

@ -1700,6 +1700,26 @@ public:
*/
static PRBool IsFocusedContent(const nsIContent *aContent);
/**
* Returns PR_TRUE if the DOM full-screen API is enabled.
*/
static PRBool IsFullScreenApiEnabled();
/**
* Returns PR_TRUE if requests for full-screen are allowed in the current
* context. Requests are only allowed if the user initiated them (like with
* a mouse-click or key press), unless this check has been disabled by
* setting the pref "full-screen-api.allow-trusted-requests-only" to false.
*/
static PRBool IsRequestFullScreenAllowed();
/**
* Returns PR_TRUE if key input is restricted in DOM full-screen mode
* to non-alpha-numeric key codes only. This mirrors the
* "full-screen-api.key-input-restricted" pref.
*/
static PRBool IsFullScreenKeyInputRestricted();
static void GetShiftText(nsAString& text);
static void GetControlText(nsAString& text);
static void GetMetaText(nsAString& text);
@ -1864,6 +1884,9 @@ private:
static PRBool sIsHandlingKeyBoardEvent;
static PRBool sAllowXULXBL_for_file;
static PRBool sIsFullScreenApiEnabled;
static PRBool sTrustedFullScreenOnly;
static PRBool sFullScreenKeyInputRestricted;
static nsHtml5Parser* sHTMLFragmentParser;
static nsIParser* sXMLFragmentParser;

View File

@ -125,10 +125,9 @@ class Element;
} // namespace dom
} // namespace mozilla
#define NS_IDOCUMENT_IID \
{ 0x455e4d79, 0x756b, 0x4f73, \
{ 0x95, 0xea, 0x3f, 0xf6, 0x0c, 0x6a, 0x8c, 0xa6 } }
{ 0x170d5a75, 0xff0b, 0x4599, \
{ 0x9b, 0x68, 0x18, 0xb7, 0x42, 0xe0, 0xf9, 0xf7 } }
// Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
@ -742,6 +741,43 @@ public:
virtual void AddToNameTable(Element* aElement, nsIAtom* aName) = 0;
virtual void RemoveFromNameTable(Element* aElement, nsIAtom* aName) = 0;
/**
* Resets the current full-screen element to nsnull.
*/
virtual void ResetFullScreenElement() = 0;
/**
* Returns the element which either is the full-screen element, or
* contains the full-screen element if a child of this document contains
* the fullscreen element.
*/
virtual Element* GetFullScreenElement() = 0;
/**
* Requests that the document make aElement the full-screen element,
* and move into full-screen mode.
*/
virtual void RequestFullScreen(Element* aElement) = 0;
/**
* Requests that the document, and all documents in its hierarchy exit
* from DOM full-screen mode.
*/
virtual void CancelFullScreen() = 0;
/**
* Updates the full-screen status on this document, setting the full-screen
* mode to aIsFullScreen. This doesn't affect the window's full-screen mode,
* this updates the document's internal state which determines whether the
* document reports as being in full-screen mode.
*/
virtual void UpdateFullScreenStatus(PRBool aIsFullScreen) = 0;
/**
* Returns PR_TRUE if this document is in full-screen mode.
*/
virtual PRBool IsFullScreenDoc() = 0;
//----------------------------------------------------------------------
// Document notification API's

View File

@ -282,8 +282,8 @@ private:
// IID for the nsINode interface
#define NS_INODE_IID \
{ 0x5572c8a9, 0xbda9, 0x4b78, \
{ 0xb4, 0x1a, 0xdb, 0x1a, 0x83, 0xef, 0x53, 0x7e } }
{ 0xb59269fe, 0x7f60, 0x4672, \
{ 0x8e, 0x56, 0x01, 0x84, 0xb2, 0x58, 0x14, 0xb0 } }
/**
* An internal interface that abstracts some DOMNode-related parts that both
@ -1085,6 +1085,14 @@ public:
return GetNextNodeImpl(aRoot, PR_TRUE);
}
/**
* Returns true if 'this' is either document or element or
* document fragment and aOther is a descendant in the same
* anonymous tree.
*/
PRBool Contains(const nsINode* aOther) const;
nsresult Contains(nsIDOMNode* aOther, PRBool* aReturn);
private:
nsIContent* GetNextNodeImpl(const nsINode* aRoot,

View File

@ -1112,7 +1112,7 @@ nsAttrValue::ParseNonNegativeIntValue(const nsAString& aString)
return PR_FALSE;
}
SetIntValueAndType(originalVal, eInteger, nsnull);
SetIntValueAndType(originalVal, eInteger, strict ? nsnull : &aString);
return PR_TRUE;
}
@ -1129,7 +1129,7 @@ nsAttrValue::ParsePositiveIntValue(const nsAString& aString)
return PR_FALSE;
}
SetIntValueAndType(originalVal, eInteger, nsnull);
SetIntValueAndType(originalVal, eInteger, strict ? nsnull : &aString);
return PR_TRUE;
}
@ -1250,10 +1250,14 @@ nsAttrValue::SetMiscAtomOrString(const nsAString* aValue)
"Trying to re-set atom or string!");
if (aValue) {
PRUint32 len = aValue->Length();
// We're allowing eCSSStyleRule attributes to store empty strings as it
// can be beneficial to store an empty style attribute as a parsed rule.
// * We're allowing eCSSStyleRule attributes to store empty strings as it
// can be beneficial to store an empty style attribute as a parsed rule.
// * We're allowing enumerated values because sometimes the empty
// string corresponds to a particular enumerated value, especially
// for enumerated values that are not limited enumerated.
// Add other types as needed.
NS_ASSERTION(len || Type() == eCSSStyleRule, "Empty string?");
NS_ASSERTION(len || Type() == eCSSStyleRule || Type() == eEnum,
"Empty string?");
MiscContainer* cont = GetMiscContainer();
if (len <= NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM) {
nsIAtom* atom = NS_NewAtom(*aValue);

View File

@ -176,6 +176,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
#include "nsIPluginHost.h"
#include "nsICategoryManager.h"
#include "nsIViewManager.h"
#include "nsEventStateManager.h"
#ifdef IBMBIDI
#include "nsIBidiKeyboard.h"
@ -261,6 +262,9 @@ nsString* nsContentUtils::sAltText = nsnull;
nsString* nsContentUtils::sModifierSeparator = nsnull;
PRBool nsContentUtils::sInitialized = PR_FALSE;
PRBool nsContentUtils::sIsFullScreenApiEnabled = PR_FALSE;
PRBool nsContentUtils::sTrustedFullScreenOnly = PR_TRUE;
PRBool nsContentUtils::sFullScreenKeyInputRestricted = PR_TRUE;
nsHtml5Parser* nsContentUtils::sHTMLFragmentParser = nsnull;
nsIParser* nsContentUtils::sXMLFragmentParser = nsnull;
@ -384,6 +388,15 @@ nsContentUtils::Init()
Preferences::AddBoolVarCache(&sAllowXULXBL_for_file,
"dom.allow_XUL_XBL_for_file");
Preferences::AddBoolVarCache(&sIsFullScreenApiEnabled,
"full-screen-api.enabled");
Preferences::AddBoolVarCache(&sTrustedFullScreenOnly,
"full-screen-api.allow-trusted-requests-only");
Preferences::AddBoolVarCache(&sFullScreenKeyInputRestricted,
"full-screen-api.key-input-restricted");
sInitialized = PR_TRUE;
return NS_OK;
@ -5696,3 +5709,20 @@ nsContentUtils::IsPatternMatching(nsAString& aValue, nsAString& aPattern,
return res == JS_FALSE || rval != JSVAL_NULL;
}
PRBool
nsContentUtils::IsFullScreenApiEnabled()
{
return sIsFullScreenApiEnabled;
}
PRBool nsContentUtils::IsRequestFullScreenAllowed()
{
return !sTrustedFullScreenOnly || nsEventStateManager::IsHandlingUserInput();
}
PRBool
nsContentUtils::IsFullScreenKeyInputRestricted()
{
return sFullScreenKeyInputRestricted;
}

View File

@ -657,6 +657,12 @@ nsDOMAttribute::IsSameNode(nsIDOMNode *other, PRBool *aResult)
return NS_OK;
}
NS_IMETHODIMP
nsDOMAttribute::Contains(nsIDOMNode* aOther, PRBool* aReturn)
{
return nsINode::Contains(aOther, aReturn);
}
NS_IMETHODIMP
nsDOMAttribute::LookupPrefix(const nsAString & namespaceURI,
nsAString & aResult)

View File

@ -181,6 +181,7 @@
#include "nsGlobalWindow.h"
#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
#include "nsDOMNavigationTiming.h"
#include "nsEventStateManager.h"
#ifdef MOZ_SMIL
#include "nsSMILAnimationController.h"
@ -1544,6 +1545,7 @@ nsDOMImplementation::CreateHTMLDocument(const nsAString& aTitle,
nsDocument::nsDocument(const char* aContentType)
: nsIDocument()
, mAnimatingImages(PR_TRUE)
, mIsFullScreen(PR_FALSE)
{
SetContentTypeInternal(nsDependentCString(aContentType));
@ -1871,6 +1873,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument)
nsIDOMNodeList)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOriginalDocument)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCachedEncoder)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFullScreenElement)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mStateObjectCached)
// Traverse all our nsCOMArrays.
@ -1927,6 +1930,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mImageMaps)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOriginalDocument)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCachedEncoder)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFullScreenElement)
tmp->mParentDocument = nsnull;
@ -5874,6 +5878,12 @@ nsDocument::GetUserData(const nsAString & key,
return nsINode::GetUserData(key, aResult);
}
NS_IMETHODIMP
nsDocument::Contains(nsIDOMNode* aOther, PRBool* aReturn)
{
return nsINode::Contains(aOther, aReturn);
}
NS_IMETHODIMP
nsDocument::GetInputEncoding(nsAString& aInputEncoding)
{
@ -8459,6 +8469,221 @@ nsIDocument::SizeOf() const
return size;
}
// Returns the root document in a document hierarchy.
static nsIDocument*
GetRootDocument(nsIDocument* aDoc)
{
if (!aDoc) {
return nsnull;
}
nsCOMPtr<nsIPresShell> shell = aDoc->GetShell();
if (!shell) {
return nsnull;
}
nsPresContext* ctx = shell->GetPresContext();
if (!ctx) {
return nsnull;
}
nsRootPresContext* rpc = ctx->GetRootPresContext();
if (!rpc) {
return nsnull;
}
return rpc->Document();
}
class nsDispatchFullScreenChange : public nsRunnable
{
public:
nsDispatchFullScreenChange(nsIDocument *aDoc)
: mDoc(aDoc)
{
mTarget = aDoc->GetFullScreenElement();
if (!mTarget) {
mTarget = aDoc;
}
}
NS_IMETHOD Run()
{
nsContentUtils::DispatchTrustedEvent(mDoc,
mTarget,
NS_LITERAL_STRING("mozfullscreenchange"),
PR_TRUE,
PR_FALSE);
return NS_OK;
}
nsCOMPtr<nsIDocument> mDoc;
nsCOMPtr<nsISupports> mTarget;
};
void
nsDocument::UpdateFullScreenStatus(PRBool aIsFullScreen)
{
if (mIsFullScreen != aIsFullScreen) {
nsCOMPtr<nsIRunnable> event(new nsDispatchFullScreenChange(this));
NS_DispatchToCurrentThread(event);
}
mIsFullScreen = aIsFullScreen;
if (!mIsFullScreen) {
// Full-screen is being turned off. Reset the full-screen element, to
// save us from having to traverse the document hierarchy again in
// MozCancelFullScreen().
ResetFullScreenElement();
}
}
static PRBool
UpdateFullScreenStatus(nsIDocument* aDocument, void* aData)
{
aDocument->UpdateFullScreenStatus(*static_cast<PRBool*>(aData));
aDocument->EnumerateSubDocuments(UpdateFullScreenStatus, aData);
return PR_TRUE;
}
static void
UpdateFullScreenStatusInDocTree(nsIDocument* aDoc, PRBool aIsFullScreen)
{
nsIDocument* root = GetRootDocument(aDoc);
if (root) {
UpdateFullScreenStatus(root, static_cast<void*>(&aIsFullScreen));
}
}
void
nsDocument::ResetFullScreenElement()
{
if (mFullScreenElement) {
nsEventStateManager::SetFullScreenState(mFullScreenElement, PR_FALSE);
}
mFullScreenElement = nsnull;
}
static PRBool
ResetFullScreenElement(nsIDocument* aDocument, void* aData)
{
aDocument->ResetFullScreenElement();
aDocument->EnumerateSubDocuments(ResetFullScreenElement, aData);
return PR_TRUE;
}
static void
ResetFullScreenElementInDocTree(nsIDocument* aDoc)
{
nsIDocument* root = GetRootDocument(aDoc);
if (root) {
ResetFullScreenElement(root, nsnull);
}
}
NS_IMETHODIMP
nsDocument::MozCancelFullScreen()
{
if (!nsContentUtils::IsRequestFullScreenAllowed()) {
return NS_OK;
}
CancelFullScreen();
return NS_OK;
}
void
nsDocument::CancelFullScreen()
{
if (!nsContentUtils::IsFullScreenApiEnabled() ||
!IsFullScreenDoc() ||
!GetWindow()) {
return;
}
// Disable full-screen mode in all documents in this hierarchy.
UpdateFullScreenStatusInDocTree(this, PR_FALSE);
// Move the window out of full-screen mode.
GetWindow()->SetFullScreen(PR_FALSE);
return;
}
PRBool
nsDocument::IsFullScreenDoc()
{
return nsContentUtils::IsFullScreenApiEnabled() && mIsFullScreen;
}
void
nsDocument::RequestFullScreen(Element* aElement)
{
if (!aElement || !nsContentUtils::IsFullScreenApiEnabled() || !GetWindow()) {
return;
}
// Reset the full-screen elements of every document in this document
// hierarchy.
ResetFullScreenElementInDocTree(this);
if (aElement->IsInDoc()) {
// Propagate up the document hierarchy, setting the full-screen element as
// the element's container in ancestor documents. Note we don't propagate
// down the document hierarchy, the full-screen element (or its container)
// is not visible there.
mFullScreenElement = aElement;
// Set the full-screen state on the element, so the css-pseudo class
// applies to the element.
nsEventStateManager::SetFullScreenState(mFullScreenElement, PR_TRUE);
nsIDocument* child = this;
nsIDocument* parent;
while (parent = child->GetParentDocument()) {
nsIContent* content = parent->FindContentForSubDocument(child);
nsCOMPtr<Element> element(do_QueryInterface(content));
// Containing frames also need the css-pseudo class applied.
nsEventStateManager::SetFullScreenState(element, PR_TRUE);
static_cast<nsDocument*>(parent)->mFullScreenElement = element;
child = parent;
}
}
// Set all documents in hierarchy to full-screen mode.
UpdateFullScreenStatusInDocTree(this, PR_TRUE);
// Make the window full-screen. Note we must make the state changes above
// before making the window full-screen, as then the document reports as
// being in full-screen mode when the Chrome "fullscreen" event fires,
// enabling browser.js to distinguish between browser and dom full-screen
// modes.
GetWindow()->SetFullScreen(PR_TRUE);
}
NS_IMETHODIMP
nsDocument::GetMozFullScreenElement(nsIDOMHTMLElement **aFullScreenElement)
{
NS_ENSURE_ARG_POINTER(aFullScreenElement);
if (!nsContentUtils::IsFullScreenApiEnabled() || !IsFullScreenDoc()) {
*aFullScreenElement = nsnull;
return NS_OK;
}
nsCOMPtr<nsIDOMHTMLElement> e(do_QueryInterface(GetFullScreenElement()));
NS_IF_ADDREF(*aFullScreenElement = e);
return NS_OK;
}
Element*
nsDocument::GetFullScreenElement()
{
if (!nsContentUtils::IsFullScreenApiEnabled() ||
(mFullScreenElement && !mFullScreenElement->IsInDoc())) {
return nsnull;
}
return mFullScreenElement;
}
NS_IMETHODIMP
nsDocument::GetMozFullScreen(PRBool *aFullScreen)
{
NS_ENSURE_ARG_POINTER(aFullScreen);
*aFullScreen = nsContentUtils::IsFullScreenApiEnabled() && IsFullScreenDoc();
return NS_OK;
}
PRInt64
nsDocument::SizeOf() const
{

View File

@ -941,6 +941,13 @@ public:
virtual Element* FindImageMap(const nsAString& aNormalizedMapName);
virtual void ResetFullScreenElement();
virtual Element* GetFullScreenElement();
virtual void RequestFullScreen(Element* aElement);
virtual void CancelFullScreen();
virtual void UpdateFullScreenStatus(PRBool aIsFullScreen);
virtual PRBool IsFullScreenDoc();
protected:
friend class nsNodeUtils;
@ -1078,6 +1085,9 @@ protected:
// Recorded time of change to 'loading' state.
mozilla::TimeStamp mLoadingTimeStamp;
// The current full-screen element of this document.
nsCOMPtr<Element> mFullScreenElement;
// True if the document has been detached from its content viewer.
PRPackedBool mIsGoingAway:1;
// True if the document is being destroyed.
@ -1110,6 +1120,9 @@ protected:
// Whether we currently require our images to animate
PRPackedBool mAnimatingImages:1;
// Whether we are currently in full-screen mode, as per the DOM API.
PRPackedBool mIsFullScreen:1;
PRUint8 mXMLDeclarationBits;
PRUint8 mDefaultElementType;

View File

@ -5530,3 +5530,44 @@ nsGenericElement::SizeOf() const
#include "nsEventNameList.h"
#undef TOUCH_EVENT
#undef EVENT
PRBool
nsINode::Contains(const nsINode* aOther) const
{
if (!aOther ||
aOther == this ||
GetOwnerDoc() != aOther->GetOwnerDoc() ||
IsInDoc() != aOther->IsInDoc() ||
!(aOther->IsElement() ||
aOther->IsNodeOfType(nsINode::eCONTENT)) ||
!GetFirstChild()) {
return PR_FALSE;
}
const nsIContent* other = static_cast<const nsIContent*>(aOther);
if (this == GetOwnerDoc()) {
// document.contains(aOther) returns true if aOther is in the document,
// but is not in any anonymous subtree.
// IsInDoc() check is done already before this.
return !other->IsInAnonymousSubtree();
}
if (!IsElement() && !IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT)) {
return PR_FALSE;
}
const nsIContent* thisContent = static_cast<const nsIContent*>(this);
if (thisContent->GetBindingParent() != other->GetBindingParent()) {
return PR_FALSE;
}
return nsContentUtils::ContentIsDescendantOf(other, this);
}
nsresult
nsINode::Contains(nsIDOMNode* aOther, PRBool* aReturn)
{
nsCOMPtr<nsINode> node = do_QueryInterface(aOther);
*aReturn = Contains(node);
return NS_OK;
}

View File

@ -63,6 +63,7 @@
GK_ATOM(_empty, "")
GK_ATOM(moz, "_moz")
GK_ATOM(mozallowfullscreen, "mozallowfullscreen")
GK_ATOM(moztype, "_moz-type")
GK_ATOM(mozdirty, "_moz_dirty")
GK_ATOM(mozdonotsend, "moz-do-not-send")
@ -583,6 +584,7 @@ GK_ATOM(mouseout, "mouseout")
GK_ATOM(mouseover, "mouseover")
GK_ATOM(mousethrough, "mousethrough")
GK_ATOM(mouseup, "mouseup")
GK_ATOM(mozfullscreenchange, "mozfullscreenchange")
GK_ATOM(moz_opaque, "moz-opaque")
GK_ATOM(moz_action_hint, "mozactionhint")
GK_ATOM(x_moz_errormessage, "x-moz-errormessage")
@ -695,6 +697,7 @@ GK_ATOM(onMozMouseHittest, "onMozMouseHittest")
GK_ATOM(onmouseup, "onmouseup")
GK_ATOM(onMozAfterPaint, "onMozAfterPaint")
GK_ATOM(onMozBeforePaint, "onMozBeforePaint")
GK_ATOM(onmozfullscreenchange, "onmozfullscreenchange")
GK_ATOM(onMozMousePixelScroll, "onMozMousePixelScroll")
GK_ATOM(onMozScrolledAreaChanged, "onMozScrolledAreaChanged")
GK_ATOM(ononline, "ononline")

View File

@ -69,6 +69,7 @@ _CHROME_FILES = \
test_bug357450.xul \
test_bug571390.xul \
test_bug574596.html \
test_bug683852.xul \
$(NULL)
libs:: $(_TEST_FILES)

View File

@ -0,0 +1,67 @@
<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=683852
-->
<window title="Mozilla Bug 683852"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<button value="testbutton" id="testbutton"/>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml">
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=683852"
target="_blank" id="link">Mozilla Bug 683852</a>
</body>
<!-- test code goes here -->
<script type="application/javascript">
<![CDATA[
/** Test for Bug 683852 **/
SimpleTest.waitForExplicitFinish();
function startTest() {
is(document.contains(document), false, "Document should not contain itself!");
var tb = document.getElementById("testbutton");
is(document.contains(tb), true, "Document should contain element in it!");
var anon = document.getAnonymousElementByAttribute(tb, "anonid", "button-box");
is(document.contains(anon), false, "Document should not contain anonymous element in it!");
is(tb.contains(anon), false, "Element should not contain anonymous element in it!");
is(document.documentElement.contains(tb), true, "Element should contain element in it!");
is(document.contains(document.createElement("foo")), false, "Document shouldn't contain element which is't in the document");
is(document.contains(document.createTextNode("foo")), false, "Document shouldn't contain text node which is't in the document");
var link = document.getElementById("link");
is(document.contains(link.firstChild), true,
"Document should contain a text node in it.");
is(link.contains(link.firstChild), true,
"Element should contain a text node in it.");
is(link.firstChild.contains(link), false, "text node shouldn't contain its parent.");
is(document.contains(null), false, "Document shouldn't contain null.");
var pi = document.createProcessingInstruction("adf", "asd");
is(pi.contains(document), false, "Processing instruction shouldn't contain document");
document.documentElement.appendChild(pi);
document.contains(pi, true, "Document should contain processing instruction");
var df = document.createRange().createContextualFragment("<div>foo</div>");
is(df.contains(df.firstChild), true, "Document fragment should contain its child");
is(df.contains(df.firstChild.firstChild), true,
"Document fragment should contain its descendant");
is(df.contains(df), false, "Document fragment shouldn't contain itself.");
var d = document.implementation.createHTMLDocument("");
is(document.contains(d), false,
"Document shouldn't contain another document.");
is(document.contains(d.createElement("div")), false,
"Document shouldn't contain an element from another document.");
SimpleTest.finish();
}
addLoadEvent(startTest);
]]>
</script>
</window>

View File

@ -38,51 +38,6 @@ function testCancelInPhase4() {
xhr2.addEventListener("load", function() {
is(xhr2.responseText, "0", "Received fresh value for second request");
testCancelBeforePhase4();
}, false);
xhr2.open("GET", url);
xhr2.setRequestHeader("X-Request", "1", false);
try { xhr2.send(); }
catch(e) {
is(xhr2.status, "200", "Exception!");
}
}, 0);
}, false);
xhr.abort();
}
}, false);
xhr.open("GET", url, true);
xhr.setRequestHeader("X-Request", "0", false);
try { xhr.send(); }
catch(e) {
is("Nothing", "Exception", "Boom: " + e);
}
}
// Tests that response is NOT cached if the request is cancelled
// before it has reached state 4
function testCancelBeforePhase4() {
clearCache();
// First request - should be loaded from server
var xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function(e) {
if (xhr.readyState == 3) {
xhr.addEventListener("abort", function() {
setTimeout(function() {
// This request was cancelled, so the responseText should be empty string
is(xhr.responseText, "", "Expected empty response to cancelled request");
// Second request - should be found in cache
var xhr2 = new XMLHttpRequest();
xhr2.addEventListener("load", function() {
is(xhr2.responseText, "1", "Received cached value for second request");
SimpleTest.finish();
}, false);

View File

@ -1207,6 +1207,22 @@ NS_INTERFACE_MAP_BEGIN(WebGLExtension)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtension)
NS_INTERFACE_MAP_END
/* readonly attribute WebGLsizei drawingBufferWidth; */
NS_IMETHODIMP
WebGLContext::GetDrawingBufferWidth(WebGLsizei *aWidth)
{
*aWidth = mWidth;
return NS_OK;
}
/* readonly attribute WebGLsizei drawingBufferHeight; */
NS_IMETHODIMP
WebGLContext::GetDrawingBufferHeight(WebGLsizei *aHeight)
{
*aHeight = mHeight;
return NS_OK;
}
/* [noscript] attribute WebGLint location; */
NS_IMETHODIMP
WebGLUniformLocation::GetLocation(WebGLint *aLocation)

View File

@ -428,6 +428,16 @@ protected:
void UndoFakeVertexAttrib0();
void InvalidateFakeVertexAttrib0();
static CheckedUint32 GetImageSize(WebGLsizei height,
WebGLsizei width,
PRUint32 pixelSize,
PRUint32 alignment);
// Returns x rounded to the next highest multiple of y.
static CheckedUint32 RoundedToNextMultipleOf(CheckedUint32 x, CheckedUint32 y) {
return ((x + y - 1) / y) * y;
}
nsCOMPtr<nsIDOMHTMLCanvasElement> mCanvasElement;
nsHTMLCanvasElement *HTMLCanvasElement() {
return static_cast<nsHTMLCanvasElement*>(mCanvasElement.get());
@ -492,9 +502,7 @@ protected:
PRBool ValidateAttribIndex(WebGLuint index, const char *info);
PRBool ValidateStencilParamsForDrawCall();
bool ValidateGLSLVariableName(const nsAString& name, const char *info);
bool ValidateGLSLCharacter(PRUnichar c);
bool ValidateGLSLString(const nsAString& string, const char *info);
bool ValidateGLSLIdentifier(const nsAString& name, const char *info);
static PRUint32 GetTexelSize(WebGLenum format, WebGLenum type);

View File

@ -62,7 +62,6 @@
#endif
#include "WebGLTexelConversions.h"
#include "WebGLValidateStrings.h"
using namespace mozilla;
@ -183,8 +182,8 @@ WebGLContext::BindAttribLocation(nsIWebGLProgram *pobj, WebGLuint location, cons
if (!GetGLName<WebGLProgram>("bindAttribLocation: program", pobj, &progname))
return NS_OK;
if (!ValidateGLSLVariableName(name, "bindAttribLocation"))
return NS_OK;
if (name.IsEmpty())
return ErrorInvalidValue("BindAttribLocation: name can't be null or empty");
if (!ValidateAttribIndex(location, "bindAttribLocation"))
return NS_OK;
@ -201,8 +200,13 @@ WebGLContext::BindBuffer(WebGLenum target, nsIWebGLBuffer *bobj)
{
WebGLuint bufname;
WebGLBuffer* buf;
PRBool isNull;
if (!GetConcreteObjectAndGLName("bindBuffer", bobj, &buf, &bufname, &isNull))
PRBool isNull; // allow null objects
PRBool isDeleted; // allow deleted objects
if (!GetConcreteObjectAndGLName("bindBuffer", bobj, &buf, &bufname, &isNull, &isDeleted))
return NS_OK;
// silently ignore a deleted buffer
if (isDeleted)
return NS_OK;
if (target != LOCAL_GL_ARRAY_BUFFER &&
@ -237,13 +241,18 @@ NS_IMETHODIMP
WebGLContext::BindFramebuffer(WebGLenum target, nsIWebGLFramebuffer *fbobj)
{
WebGLuint framebuffername;
PRBool isNull;
PRBool isNull; // allow null objects
PRBool isDeleted; // allow deleted objects
WebGLFramebuffer *wfb;
if (target != LOCAL_GL_FRAMEBUFFER)
return ErrorInvalidEnum("BindFramebuffer: target must be GL_FRAMEBUFFER");
if (!GetConcreteObjectAndGLName("bindFramebuffer", fbobj, &wfb, &framebuffername, &isNull))
if (!GetConcreteObjectAndGLName("bindFramebuffer", fbobj, &wfb, &framebuffername, &isNull, &isDeleted))
return NS_OK;
// silently ignore a deleted frame buffer
if (isDeleted)
return NS_OK;
MakeContextCurrent();
@ -264,13 +273,18 @@ NS_IMETHODIMP
WebGLContext::BindRenderbuffer(WebGLenum target, nsIWebGLRenderbuffer *rbobj)
{
WebGLuint renderbuffername;
PRBool isNull;
PRBool isNull; // allow null objects
PRBool isDeleted; // allow deleted objects
WebGLRenderbuffer *wrb;
if (target != LOCAL_GL_RENDERBUFFER)
return ErrorInvalidEnumInfo("bindRenderbuffer: target", target);
if (!GetConcreteObjectAndGLName("bindRenderBuffer", rbobj, &wrb, &renderbuffername, &isNull))
if (!GetConcreteObjectAndGLName("bindRenderBuffer", rbobj, &wrb, &renderbuffername, &isNull, &isDeleted))
return NS_OK;
// silently ignore a deleted buffer
if (isDeleted)
return NS_OK;
if (!isNull)
@ -290,8 +304,13 @@ WebGLContext::BindTexture(WebGLenum target, nsIWebGLTexture *tobj)
{
WebGLuint texturename;
WebGLTexture *tex;
PRBool isNull; // allow null object
if (!GetConcreteObjectAndGLName("bindTexture", tobj, &tex, &texturename, &isNull))
PRBool isNull; // allow null objects
PRBool isDeleted; // allow deleted objects
if (!GetConcreteObjectAndGLName("bindTexture", tobj, &tex, &texturename, &isNull, &isDeleted))
return NS_OK;
// silently ignore a deleted texture
if (isDeleted)
return NS_OK;
if (target == LOCAL_GL_TEXTURE_2D) {
@ -746,16 +765,8 @@ WebGLContext::CopyTexSubImage2D_base(WebGLenum target,
if (!ValidateTexFormatAndType(internalformat, LOCAL_GL_UNSIGNED_BYTE, -1, &texelSize, info))
return NS_OK;
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * texelSize;
PRUint32 unpackAlignment = mPixelStoreUnpackAlignment;
// alignedRowSize = row size rounded up to next multiple of packAlignment
CheckedUint32 checked_alignedRowSize
= ((checked_plainRowSize + unpackAlignment-1) / unpackAlignment) * unpackAlignment;
CheckedUint32 checked_neededByteLength
= (height-1) * checked_alignedRowSize + checked_plainRowSize;
CheckedUint32 checked_neededByteLength =
GetImageSize(height, width, texelSize, mPixelStoreUnpackAlignment);
if (!checked_neededByteLength.valid())
return ErrorInvalidOperation("%s: integer overflow computing the needed buffer size", info);
@ -1063,6 +1074,9 @@ WebGLContext::DeleteFramebuffer(nsIWebGLFramebuffer *fbobj)
fbuf->Delete();
mMapFramebuffers.Remove(fbufname);
if (mBoundFramebuffer && mBoundFramebuffer->GLName() == fbufname)
mBoundFramebuffer = NULL;
return NS_OK;
}
@ -1093,10 +1107,12 @@ WebGLContext::DeleteRenderbuffer(nsIWebGLRenderbuffer *rbobj)
*/
gl->fDeleteRenderbuffers(1, &rbufname);
rbuf->Delete();
mMapRenderbuffers.Remove(rbufname);
if (mBoundRenderbuffer && mBoundRenderbuffer->GLName() == rbufname)
mBoundRenderbuffer = NULL;
return NS_OK;
}
@ -1840,7 +1856,7 @@ WebGLContext::GetAttribLocation(nsIWebGLProgram *pobj,
if (!GetGLName<WebGLProgram>("getAttribLocation: program", pobj, &progname))
return NS_OK;
if (!ValidateGLSLVariableName(name, "getAttribLocation"))
if (!ValidateGLSLIdentifier(name, "getAttribLocation"))
return NS_OK;
MakeContextCurrent();
@ -2197,10 +2213,6 @@ WebGLContext::GetFramebufferAttachmentParameter(WebGLenum target, WebGLenum atta
wrval->SetAsInt32(LOCAL_GL_NONE);
break;
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
wrval->SetAsEmpty();
break;
default:
return ErrorInvalidEnumInfo("GetFramebufferAttachmentParameter: pname", pname);
}
@ -2340,14 +2352,8 @@ WebGLContext::GetProgramParameter(nsIWebGLProgram *pobj, PRUint32 pname, nsIVari
{
GLint i = 0;
#ifdef XP_MACOSX
if (pname == LOCAL_GL_VALIDATE_STATUS &&
gl->Vendor() == gl::GLContext::VendorNVIDIA)
{
// See comment in ValidateProgram below.
i = 1;
} else {
gl->fGetProgramiv(progname, pname, &i);
}
// See comment in ValidateProgram below.
i = 1;
#else
gl->fGetProgramiv(progname, pname, &i);
#endif
@ -2665,7 +2671,7 @@ WebGLContext::GetUniformLocation(nsIWebGLProgram *pobj, const nsAString& name, n
if (!GetConcreteObjectAndGLName("getUniformLocation: program", pobj, &prog, &progname))
return NS_OK;
if (!ValidateGLSLVariableName(name, "getUniformLocation"))
if (!ValidateGLSLIdentifier(name, "getUniformLocation"))
return NS_OK;
MakeContextCurrent();
@ -3000,16 +3006,13 @@ WebGLContext::ReadPixels_base(WebGLint x, WebGLint y, WebGLsizei width, WebGLsiz
if (badType)
return ErrorInvalidEnumInfo("ReadPixels: type", type);
CheckedUint32 checked_neededByteLength =
GetImageSize(height, width, size, mPixelStorePackAlignment);
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * size;
PRUint32 packAlignment = mPixelStorePackAlignment;
// alignedRowSize = row size rounded up to next multiple of packAlignment
CheckedUint32 checked_alignedRowSize
= ((checked_plainRowSize + packAlignment-1) / packAlignment) * packAlignment;
CheckedUint32 checked_neededByteLength
= (height-1) * checked_alignedRowSize + checked_plainRowSize;
CheckedUint32 checked_alignedRowSize =
RoundedToNextMultipleOf(checked_plainRowSize, mPixelStorePackAlignment);
if (!checked_neededByteLength.valid())
return ErrorInvalidOperation("ReadPixels: integer overflow computing the needed buffer size");
@ -3070,8 +3073,9 @@ WebGLContext::ReadPixels_base(WebGLint x, WebGLint y, WebGLsizei width, WebGLsiz
// now, same computation as above to find the size of the intermediate buffer to allocate for the subrect
// no need to check again for integer overflow here, since we already know the sizes aren't greater than before
PRUint32 subrect_plainRowSize = subrect_width * size;
PRUint32 subrect_alignedRowSize = (subrect_plainRowSize + packAlignment-1) &
~PRUint32(packAlignment-1);
// There are checks above to ensure that this doesn't overflow.
PRUint32 subrect_alignedRowSize =
RoundedToNextMultipleOf(subrect_plainRowSize, mPixelStorePackAlignment).value();
PRUint32 subrect_byteLength = (subrect_height-1)*subrect_alignedRowSize + subrect_plainRowSize;
// create subrect buffer, call glReadPixels, copy pixels into destination buffer, delete subrect buffer
@ -4133,10 +4137,7 @@ WebGLContext::ShaderSource(nsIWebGLShader *sobj, const nsAString& source)
WebGLuint shadername;
if (!GetConcreteObjectAndGLName("shaderSource: shader", sobj, &shader, &shadername))
return NS_OK;
if (!ValidateGLSLString(source, "shaderSource"))
return NS_OK;
const nsPromiseFlatString& flatSource = PromiseFlatString(source);
if (!NS_IsAscii(flatSource.get()))
@ -4290,7 +4291,7 @@ WebGLContext::TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum intern
return ErrorInvalidEnumInfo("texImage2D: target", target);
}
switch (internalformat) {
switch (format) {
case LOCAL_GL_RGB:
case LOCAL_GL_RGBA:
case LOCAL_GL_ALPHA:
@ -4331,16 +4332,13 @@ WebGLContext::TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum intern
if (!ValidateTexFormatAndType(format, type, jsArrayType, &texelSize, "texImage2D"))
return NS_OK;
CheckedUint32 checked_neededByteLength =
GetImageSize(height, width, texelSize, mPixelStoreUnpackAlignment);
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * texelSize;
PRUint32 unpackAlignment = mPixelStoreUnpackAlignment;
// alignedRowSize = row size rounded up to next multiple of packAlignment
CheckedUint32 checked_alignedRowSize
= ((checked_plainRowSize + unpackAlignment-1) / unpackAlignment) * unpackAlignment;
CheckedUint32 checked_neededByteLength
= (height-1) * checked_alignedRowSize + checked_plainRowSize;
CheckedUint32 checked_alignedRowSize =
RoundedToNextMultipleOf(checked_plainRowSize.value(), mPixelStoreUnpackAlignment);
if (!checked_neededByteLength.valid())
return ErrorInvalidOperation("texImage2D: integer overflow computing the needed buffer size");
@ -4531,16 +4529,13 @@ WebGLContext::TexSubImage2D_base(WebGLenum target, WebGLint level,
if (width == 0 || height == 0)
return NS_OK; // ES 2.0 says it has no effect, we better return right now
CheckedUint32 checked_neededByteLength =
GetImageSize(height, width, texelSize, mPixelStoreUnpackAlignment);
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * texelSize;
PRUint32 unpackAlignment = mPixelStoreUnpackAlignment;
// alignedRowSize = row size rounded up to next multiple of packAlignment
CheckedUint32 checked_alignedRowSize
= ((checked_plainRowSize + unpackAlignment-1) / unpackAlignment) * unpackAlignment;
CheckedUint32 checked_neededByteLength
= (height-1) * checked_alignedRowSize + checked_plainRowSize;
CheckedUint32 checked_alignedRowSize =
RoundedToNextMultipleOf(checked_plainRowSize.value(), mPixelStoreUnpackAlignment);
if (!checked_neededByteLength.valid())
return ErrorInvalidOperation("texSubImage2D: integer overflow computing the needed buffer size");
@ -4571,7 +4566,8 @@ WebGLContext::TexSubImage2D_base(WebGLenum target, WebGLint level,
size_t srcStride = srcStrideOrZero ? srcStrideOrZero : checked_alignedRowSize.value();
size_t dstPlainRowSize = texelSize * width;
size_t dstStride = ((dstPlainRowSize + unpackAlignment-1) / unpackAlignment) * unpackAlignment;
// There are checks above to ensure that this won't overflow.
size_t dstStride = RoundedToNextMultipleOf(dstPlainRowSize, mPixelStoreUnpackAlignment).value();
if (actualSrcFormat == dstFormat &&
srcPremultiplied == mPixelStorePremultiplyAlpha &&

View File

@ -117,6 +117,24 @@ WebGLContext::LogMessageIfVerbose(const char *fmt, va_list ap)
firstTime = PR_FALSE;
}
CheckedUint32
WebGLContext::GetImageSize(WebGLsizei height,
WebGLsizei width,
PRUint32 pixelSize,
PRUint32 packOrUnpackAlignment)
{
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * pixelSize;
// alignedRowSize = row size rounded up to next multiple of packAlignment
CheckedUint32 checked_alignedRowSize = RoundedToNextMultipleOf(checked_plainRowSize, packOrUnpackAlignment);
// if height is 0, we don't need any memory to store this; without this check, we'll get an overflow
CheckedUint32 checked_neededByteLength
= height <= 0 ? 0 : (height-1) * checked_alignedRowSize + checked_plainRowSize;
return checked_neededByteLength;
}
nsresult
WebGLContext::SynthesizeGLError(WebGLenum err)
{

View File

@ -328,31 +328,14 @@ PRBool WebGLContext::ValidateDrawModeEnum(WebGLenum mode, const char *info)
}
}
bool WebGLContext::ValidateGLSLVariableName(const nsAString& name, const char *info)
bool WebGLContext::ValidateGLSLIdentifier(const nsAString& name, const char *info)
{
const PRUint32 maxSize = 255;
const PRUint32 maxSize = 4095;
if (name.Length() > maxSize) {
ErrorInvalidValue("%s: identifier is %d characters long, exceeds the maximum allowed length of %d characters",
info, name.Length(), maxSize);
return false;
}
if (!ValidateGLSLString(name, info)) {
return false;
}
return true;
}
bool WebGLContext::ValidateGLSLString(const nsAString& string, const char *info)
{
for (PRUint32 i = 0; i < string.Length(); ++i) {
if (!ValidateGLSLCharacter(string.CharAt(i))) {
ErrorInvalidValue("%s: string contains the illegal character '%d'", info, string.CharAt(i));
return false;
}
}
return true;
}

View File

@ -1,58 +0,0 @@
/*
* Copyright (C) 2011 Apple Inc. All rights reserved.
* Copyright (C) 2011 Mozilla Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef WEBGLVALIDATESTRINGS_H_
#define WEBGLVALIDATESTRINGS_H_
#include "WebGLContext.h"
namespace mozilla {
// The following function was taken from the WebKit WebGL implementation,
// which can be found here:
// http://trac.webkit.org/browser/trunk/Source/WebCore/html/canvas/WebGLRenderingContext.cpp#L123
/****** BEGIN CODE TAKEN FROM WEBKIT ******/
bool WebGLContext::ValidateGLSLCharacter(PRUnichar c)
{
// Printing characters are valid except " $ ` @ \ ' DEL.
if (c >= 32 && c <= 126 &&
c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' && c != '\'')
{
return true;
}
// Horizontal tab, line feed, vertical tab, form feed, carriage return are also valid.
if (c >= 9 && c <= 13) {
return true;
}
return false;
}
/****** END CODE TAKEN FROM WEBKIT ******/
} // end namespace mozilla
#endif // WEBGLVALIDATESTRINGS_H_

View File

@ -1,4 +1,3 @@
conformance/buffer-offscreen-test.html
conformance/drawingbuffer-static-canvas-test.html
conformance/drawingbuffer-test.html
conformance/framebuffer-object-attachment.html
@ -13,14 +12,12 @@ conformance/gl-getshadersource.html
conformance/gl-uniform-bool.html
conformance/glsl-conformance.html
conformance/glsl-long-variable-names.html
conformance/object-deletion-behaviour.html
conformance/invalid-passed-params.html
conformance/premultiplyalpha-test.html
conformance/read-pixels-test.html
conformance/uninitialized-test.html
conformance/webgl-specific.html
conformance/more/conformance/quickCheckAPI.html
conformance/more/functions/copyTexImage2D.html
conformance/more/functions/copyTexSubImage2D.html
conformance/more/functions/deleteBufferBadArgs.html
conformance/more/functions/texImage2DBadArgs.html
conformance/more/functions/uniformfArrayLen1.html

View File

@ -1,4 +1,3 @@
conformance/buffer-offscreen-test.html
conformance/context-attributes-alpha-depth-stencil-antialias.html
conformance/drawingbuffer-static-canvas-test.html
conformance/drawingbuffer-test.html
@ -7,17 +6,15 @@ conformance/gl-getshadersource.html
conformance/gl-object-get-calls.html
conformance/glsl-conformance.html
conformance/glsl-long-variable-names.html
conformance/object-deletion-behaviour.html
conformance/invalid-passed-params.html
conformance/premultiplyalpha-test.html
conformance/program-test.html
conformance/read-pixels-test.html
conformance/tex-input-validation.html
conformance/texture-npot.html
conformance/webgl-specific.html
conformance/more/conformance/quickCheckAPI.html
conformance/more/functions/copyTexImage2D.html
conformance/more/functions/copyTexSubImage2D.html
conformance/more/functions/deleteBufferBadArgs.html
conformance/more/functions/texImage2DBadArgs.html
conformance/more/functions/uniformfBadArgs.html
conformance/more/functions/uniformiBadArgs.html

View File

@ -1,17 +1,14 @@
conformance/buffer-offscreen-test.html
conformance/drawingbuffer-static-canvas-test.html
conformance/drawingbuffer-test.html
conformance/framebuffer-object-attachment.html
conformance/gl-getshadersource.html
conformance/glsl-conformance.html
conformance/glsl-long-variable-names.html
conformance/object-deletion-behaviour.html
conformance/invalid-passed-params.html
conformance/premultiplyalpha-test.html
conformance/read-pixels-test.html
conformance/webgl-specific.html
conformance/more/conformance/quickCheckAPI.html
conformance/more/functions/copyTexImage2D.html
conformance/more/functions/copyTexSubImage2D.html
conformance/more/functions/deleteBufferBadArgs.html
conformance/more/functions/texImage2DBadArgs.html
conformance/more/functions/uniformfArrayLen1.html

View File

@ -392,35 +392,39 @@ function start() {
<div id="content" style="display: none">
</div>
<table border="2">
<tr style="height: 300px;">
<td>
<table>
<tr><td><h4>WebGL Conformance Test Runner</h4>
<tr><td>
<div style="border: 1px">
<b>Status:</b> <div><span id="status"></span></div><br />
<b>Results:</b>
<div><span id="results-default"></span></div>
<br />
<div><span id="expectedtofail"></span></div>
<br />
<div><span id="ignoredtests"></span></div>
</div>
</td></tr>
</table>
</td>
<td>
<iframe id="testframe" scrolling="yes" width="100%" height="100%"></iframe>
</td>
</tr>
<tr>
<td colspan="2">
<div style="text-align: left; width: 100%; height: 100%; overflow: auto;">
<div><ul id="results"></ul></div>
</div>
</td>
</tr>
<table border="2px">
<tr style="height: 500px;">
<td style="width: 500px;">
<iframe id="testframe" scrolling="no" width="500px" height="500px"></iframe>
</td>
<td>
<table>
<tr>
<td><h4>WebGL Conformance Test Runner</h4></td>
</tr>
<tr>
<td>
<div style="border: 1px">
<b>Status:</b> <div><span id="status"></span></div><br />
<b>Results:</b>
<div><span id="results-default"></span></div>
<br />
<div><span id="expectedtofail"></span></div>
<br />
<div><span id="ignoredtests"></span></div>
</div>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td colspan="2">
<div style="text-align: left; width: 100%; height: 100%; overflow: auto;">
<div><ul id="results"></ul></div>
</div>
</td>
</tr>
</table>
<canvas id="webglcheck-default" style="display: none;"></canvas>
</body>

View File

@ -243,6 +243,10 @@ EVENT(mouseup,
NS_MOUSE_BUTTON_UP,
EventNameType_All,
NS_MOUSE_EVENT)
EVENT(mozfullscreenchange,
NS_FULLSCREENCHANGE,
EventNameType_HTML,
NS_EVENT_NULL)
// Not supported yet; probably never because "wheel" is a better idea.
// EVENT(mousewheel)
EVENT(pause,

View File

@ -261,6 +261,9 @@ private:
#define NS_EVENT_STATE_MOZ_UI_INVALID NS_DEFINE_EVENT_STATE_MACRO(32)
// UI friendly version of :valid pseudo-class.
#define NS_EVENT_STATE_MOZ_UI_VALID NS_DEFINE_EVENT_STATE_MACRO(33)
// Content is the full screen element, or a frame containing the
// current full-screen element.
#define NS_EVENT_STATE_FULL_SCREEN NS_DEFINE_EVENT_STATE_MACRO(34)
/**
* NOTE: do not go over 63 without updating nsEventStates::InternalType!
@ -268,7 +271,8 @@ private:
#define ESM_MANAGED_STATES (NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS | \
NS_EVENT_STATE_HOVER | NS_EVENT_STATE_DRAGOVER | \
NS_EVENT_STATE_URLTARGET | NS_EVENT_STATE_FOCUSRING)
NS_EVENT_STATE_URLTARGET | NS_EVENT_STATE_FOCUSRING | \
NS_EVENT_STATE_FULL_SCREEN)
#define INTRINSIC_STATES (~ESM_MANAGED_STATES)

View File

@ -92,6 +92,7 @@ static const char* const sEventNames[] = {
"MozAfterPaint",
"MozBeforePaint",
"MozBeforeResize",
"mozfullscreenchange",
"MozSwipeGesture",
"MozMagnifyGestureStart",
"MozMagnifyGestureUpdate",
@ -1366,6 +1367,8 @@ const char* nsDOMEvent::GetEventName(PRUint32 aEventType)
return sEventNames[eDOMEvents_devicemotion];
case NS_DEVICE_ORIENTATION:
return sEventNames[eDOMEvents_deviceorientation];
case NS_FULLSCREENCHANGE:
return sEventNames[eDOMEvents_mozfullscreenchange];
default:
break;
}

View File

@ -177,6 +177,7 @@ public:
eDOMEvents_afterpaint,
eDOMEvents_beforepaint,
eDOMEvents_beforeresize,
eDOMEvents_mozfullscreenchange,
eDOMEvents_MozSwipeGesture,
eDOMEvents_MozMagnifyGestureStart,
eDOMEvents_MozMagnifyGestureUpdate,

View File

@ -4384,6 +4384,14 @@ static nsIContent* FindCommonAncestor(nsIContent *aNode1, nsIContent *aNode2)
return nsnull;
}
/* static */
void
nsEventStateManager::SetFullScreenState(Element* aElement,
PRBool aIsFullScreen)
{
DoStateChange(aElement, NS_EVENT_STATE_FULL_SCREEN, aIsFullScreen);
}
/* static */
inline void
nsEventStateManager::DoStateChange(Element* aElement, nsEventStates aState,

View File

@ -203,6 +203,10 @@ public:
// if aContent is non-null, marks the object as active.
static void SetActiveManager(nsEventStateManager* aNewESM,
nsIContent* aContent);
// Sets the full-screen event state on aElement to aIsFullScreen.
static void SetFullScreenState(mozilla::dom::Element* aElement, PRBool aIsFullScreen);
protected:
void UpdateCursor(nsPresContext* aPresContext, nsEvent* aEvent, nsIFrame* aTargetFrame, nsEventStatus* aStatus);
/**

View File

@ -3379,6 +3379,50 @@ nsGenericHTMLElement::Focus()
return fm ? fm->SetFocus(elem, 0) : NS_OK;
}
nsresult nsGenericHTMLElement::MozRequestFullScreen()
{
// Only grant full-screen requests if this is called from inside a trusted
// event handler (i.e. inside an event handler for a user initiated event).
// This stops the full-screen from being abused similar to the popups of old,
// and it also makes it harder for bad guys' script to go full-screen and
// spoof the browser chrome/window and phish logins etc.
if (!nsContentUtils::IsFullScreenApiEnabled() ||
!nsContentUtils::IsRequestFullScreenAllowed()) {
return NS_OK;
}
// Ensure that all ancestor <iframe> elements have the mozallowfullscreen
// boolean attribute set.
nsINode* node = static_cast<nsINode*>(this);
do {
nsIContent* content = static_cast<nsIContent*>(node);
if (content->IsHTML(nsGkAtoms::iframe) &&
!content->HasAttr(kNameSpaceID_None, nsGkAtoms::mozallowfullscreen)) {
// The node requesting fullscreen, or one of its crossdoc ancestors,
// is an iframe which doesn't have the "mozalllowfullscreen" attribute.
// This request is not authorized by the parent document.
return NS_OK;
}
node = nsContentUtils::GetCrossDocParentNode(node);
} while (node);
nsIDocument* doc = GetOwnerDoc();
NS_ENSURE_STATE(doc);
doc->RequestFullScreen(this);
#ifdef DEBUG
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(doc->GetWindow());
NS_ENSURE_STATE(window);
PRBool fullscreen;
window->GetFullScreen(&fullscreen);
NS_ASSERTION(fullscreen, "Windows should report fullscreen");
nsCOMPtr<nsIDOMDocument> domDocument(do_QueryInterface(doc));
domDocument->GetMozFullScreen(&fullscreen);
NS_ASSERTION(fullscreen, "Document should report fullscreen");
NS_ASSERTION(doc->IsFullScreenDoc(), "Should be in full screen state!");
#endif
return NS_OK;
}
nsresult nsGenericHTMLElement::Click()
{
if (HasFlag(NODE_HANDLING_CLICK))

View File

@ -139,6 +139,7 @@ public:
virtual nsresult InsertAdjacentHTML(const nsAString& aPosition,
const nsAString& aText);
nsresult ScrollIntoView(PRBool aTop, PRUint8 optional_argc);
nsresult MozRequestFullScreen();
// Declare Focus(), Blur(), GetTabIndex(), SetTabIndex(), GetHidden(),
// SetHidden(), GetSpellcheck(), SetSpellcheck(), and GetDraggable() such that
// classes that inherit interfaces with those methods properly override them.

View File

@ -131,6 +131,7 @@ NS_IMPL_STRING_ATTR(nsHTMLIFrameElement, Name, name)
NS_IMPL_STRING_ATTR(nsHTMLIFrameElement, Scrolling, scrolling)
NS_IMPL_URI_ATTR(nsHTMLIFrameElement, Src, src)
NS_IMPL_STRING_ATTR(nsHTMLIFrameElement, Width, width)
NS_IMPL_BOOL_ATTR(nsHTMLIFrameElement, MozAllowFullScreen, mozallowfullscreen)
NS_IMETHODIMP
nsHTMLIFrameElement::GetContentDocument(nsIDOMDocument** aContentDocument)

View File

@ -104,8 +104,6 @@
#include "nsDOMFile.h"
#include "nsIFilePicker.h"
#include "nsDirectoryServiceDefs.h"
#include "nsIPrivateBrowsingService.h"
#include "nsIContentURIGrouper.h"
#include "nsIContentPrefService.h"
#include "nsIObserverService.h"
#include "nsIPopupWindowManager.h"
@ -453,7 +451,6 @@ nsHTMLInputElement::InitUploadLastDir() {
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
if (observerService && gUploadLastDir) {
observerService->AddObserver(gUploadLastDir, NS_PRIVATE_BROWSING_SWITCH_TOPIC, PR_TRUE);
observerService->AddObserver(gUploadLastDir, "browser:purge-session-history", PR_TRUE);
}
}
@ -463,38 +460,11 @@ nsHTMLInputElement::DestroyUploadLastDir() {
NS_IF_RELEASE(gUploadLastDir);
}
UploadLastDir::UploadLastDir():
mInPrivateBrowsing(PR_FALSE)
{
nsCOMPtr<nsIPrivateBrowsingService> pbService =
do_GetService(NS_PRIVATE_BROWSING_SERVICE_CONTRACTID);
if (pbService) {
pbService->GetPrivateBrowsingEnabled(&mInPrivateBrowsing);
}
mUploadLastDirStore.Init();
}
nsresult
UploadLastDir::FetchLastUsedDirectory(nsIURI* aURI, nsILocalFile** aFile)
{
NS_PRECONDITION(aURI, "aURI is null");
NS_PRECONDITION(aFile, "aFile is null");
// Retrieve the data from memory if it's present during private browsing mode,
// otherwise fall through to check the CPS
if (mInPrivateBrowsing) {
nsCOMPtr<nsIContentURIGrouper> hostnameGrouperService =
do_GetService(NS_HOSTNAME_GROUPER_SERVICE_CONTRACTID);
if (!hostnameGrouperService)
return NS_ERROR_NOT_AVAILABLE;
nsString group;
hostnameGrouperService->Group(aURI, group);
if (mUploadLastDirStore.Get(group, aFile)) {
return NS_OK;
}
}
// Attempt to get the CPS, if it's not present we'll just return
nsCOMPtr<nsIContentPrefService> contentPrefService =
do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
@ -536,18 +506,6 @@ UploadLastDir::StoreLastUsedDirectory(nsIURI* aURI, nsILocalFile* aFile)
}
nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(parentFile);
// Store the data in memory instead of the CPS during private browsing mode
if (mInPrivateBrowsing) {
nsCOMPtr<nsIContentURIGrouper> hostnameGrouperService =
do_GetService(NS_HOSTNAME_GROUPER_SERVICE_CONTRACTID);
if (!hostnameGrouperService)
return NS_ERROR_NOT_AVAILABLE;
nsString group;
hostnameGrouperService->Group(aURI, group);
return mUploadLastDirStore.Put(group, localFile);
}
// Attempt to get the CPS, if it's not present we'll just return
nsCOMPtr<nsIContentPrefService> contentPrefService =
do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
@ -573,19 +531,7 @@ UploadLastDir::StoreLastUsedDirectory(nsIURI* aURI, nsILocalFile* aFile)
NS_IMETHODIMP
UploadLastDir::Observe(nsISupports *aSubject, char const *aTopic, PRUnichar const *aData)
{
if (strcmp(aTopic, NS_PRIVATE_BROWSING_SWITCH_TOPIC) == 0) {
if (NS_LITERAL_STRING(NS_PRIVATE_BROWSING_ENTER).Equals(aData)) {
mInPrivateBrowsing = PR_TRUE;
} else if (NS_LITERAL_STRING(NS_PRIVATE_BROWSING_LEAVE).Equals(aData)) {
mInPrivateBrowsing = PR_FALSE;
if (mUploadLastDirStore.IsInitialized()) {
mUploadLastDirStore.Clear();
}
}
} else if (strcmp(aTopic, "browser:purge-session-history") == 0) {
if (mUploadLastDirStore.IsInitialized()) {
mUploadLastDirStore.Clear();
}
if (strcmp(aTopic, "browser:purge-session-history") == 0) {
nsCOMPtr<nsIContentPrefService> contentPrefService =
do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
if (contentPrefService)

View File

@ -85,8 +85,6 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
UploadLastDir();
/**
* Fetch the last used directory for this location from the content
* pref service, if it is available.
@ -104,10 +102,6 @@ public:
* file will be stored
*/
nsresult StoreLastUsedDirectory(nsIURI* aURI, nsILocalFile* aFile);
private:
// Directories are stored here during private browsing mode
nsInterfaceHashtable<nsStringHashKey, nsILocalFile> mUploadLastDirStore;
PRBool mInPrivateBrowsing;
};
class nsHTMLInputElement : public nsGenericHTMLFormElement,

View File

@ -277,6 +277,9 @@ _TEST_FILES = \
test_checked.html \
test_bug677658.html \
test_bug677463.html \
file_fullscreen-api.html \
file_fullscreen-api-keys.html \
test_fullscreen-api.html \
$(NULL)
libs:: $(_TEST_FILES)

View File

@ -0,0 +1,250 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=545812
Test that restricted key pressed drop documents out of DOM full-screen mode.
-->
<head>
<title>Test for Bug 545812</title>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
</head>
<body onload="document.body.mozRequestFullScreen();">
<script type="application/javascript">
/** Test for Bug 545812 **/
// List of key codes, and whether they're restricted in full-screen mode.
var keyList = [
// Allowed: DOM_VK_CANCEL to DOM_VK_CAPS_LOCK, inclusive
{ code: "VK_CANCEL", allowed: true},
{ code: "VK_HELP", allowed: true},
{ code: "VK_BACK_SPACE", allowed: true},
{ code: "VK_TAB", allowed: true},
{ code: "VK_CLEAR", allowed: true},
{ code: "VK_RETURN", allowed: true},
{ code: "VK_ENTER", allowed: true},
{ code: "VK_SHIFT", allowed: true},
{ code: "VK_CONTROL", allowed: true},
{ code: "VK_ALT", allowed: true},
{ code: "VK_PAUSE", allowed: true},
{ code: "VK_CAPS_LOCK", allowed: true},
{ code: "VK_KANA", allowed: false},
{ code: "VK_HANGUL", allowed: false},
{ code: "VK_JUNJA", allowed: false},
{ code: "VK_FINAL", allowed: false},
{ code: "VK_HANJA", allowed: false},
{ code: "VK_KANJI", allowed: false},
{ code: "VK_ESCAPE", allowed: false},
{ code: "VK_CONVERT", allowed: false},
{ code: "VK_NONCONVERT", allowed: false},
{ code: "VK_ACCEPT", allowed: false},
{ code: "VK_MODECHANGE", allowed: false},
// Allowed: DOM_VK_SPACE to DOM_VK_DELETE, inclusive
{ code: "VK_SPACE", allowed: true},
{ code: "VK_PAGE_UP", allowed: true},
{ code: "VK_PAGE_DOWN", allowed: true},
{ code: "VK_END", allowed: true},
{ code: "VK_HOME", allowed: true},
{ code: "VK_LEFT", allowed: true},
{ code: "VK_UP", allowed: true},
{ code: "VK_RIGHT", allowed: true},
{ code: "VK_DOWN", allowed: true},
{ code: "VK_SELECT", allowed: true},
{ code: "VK_PRINT", allowed: true},
{ code: "VK_EXECUTE", allowed: true},
{ code: "VK_PRINTSCREEN", allowed: true},
{ code: "VK_INSERT", allowed: true},
{ code: "VK_DELETE", allowed: true},
{ code: "VK_0", allowed: false},
{ code: "VK_1", allowed: false},
{ code: "VK_2", allowed: false},
{ code: "VK_3", allowed: false},
{ code: "VK_4", allowed: false},
{ code: "VK_5", allowed: false},
{ code: "VK_6", allowed: false},
{ code: "VK_7", allowed: false},
{ code: "VK_8", allowed: false},
{ code: "VK_9", allowed: false},
// Allowed: DOM_VK_SPACE to DOM_VK_DELETE, inclusive
{ code: "VK_SEMICOLON", allowed: true},
{ code: "VK_EQUALS", allowed: true},
{ code: "VK_A", allowed: false},
{ code: "VK_B", allowed: false},
{ code: "VK_C", allowed: false},
{ code: "VK_D", allowed: false},
{ code: "VK_E", allowed: false},
{ code: "VK_F", allowed: false},
{ code: "VK_G", allowed: false},
{ code: "VK_H", allowed: false},
{ code: "VK_I", allowed: false},
{ code: "VK_J", allowed: false},
{ code: "VK_K", allowed: false},
{ code: "VK_L", allowed: false},
{ code: "VK_M", allowed: false},
{ code: "VK_N", allowed: false},
{ code: "VK_O", allowed: false},
{ code: "VK_P", allowed: false},
{ code: "VK_Q", allowed: false},
{ code: "VK_R", allowed: false},
{ code: "VK_S", allowed: false},
{ code: "VK_T", allowed: false},
{ code: "VK_U", allowed: false},
{ code: "VK_V", allowed: false},
{ code: "VK_W", allowed: false},
{ code: "VK_X", allowed: false},
{ code: "VK_Y", allowed: false},
{ code: "VK_Z", allowed: false},
{ code: "VK_CONTEXT_MENU", allowed: false},
{ code: "VK_SLEEP", allowed: false},
{ code: "VK_NUMPAD0", allowed: false},
{ code: "VK_NUMPAD1", allowed: false},
{ code: "VK_NUMPAD2", allowed: false},
{ code: "VK_NUMPAD3", allowed: false},
{ code: "VK_NUMPAD4", allowed: false},
{ code: "VK_NUMPAD5", allowed: false},
{ code: "VK_NUMPAD6", allowed: false},
{ code: "VK_NUMPAD7", allowed: false},
{ code: "VK_NUMPAD8", allowed: false},
{ code: "VK_NUMPAD9", allowed: false},
// Allowed: DOM_VK_MULTIPLY to DOM_VK_META, inclusive
{ code: "VK_MULTIPLY", allowed: true},
{ code: "VK_ADD", allowed: true},
{ code: "VK_SEPARATOR", allowed: true},
{ code: "VK_SUBTRACT", allowed: true},
{ code: "VK_DECIMAL", allowed: true},
{ code: "VK_DIVIDE", allowed: true},
{ code: "VK_F1", allowed: true},
{ code: "VK_F2", allowed: true},
{ code: "VK_F3", allowed: true},
{ code: "VK_F4", allowed: true},
{ code: "VK_F5", allowed: true},
{ code: "VK_F6", allowed: true},
{ code: "VK_F7", allowed: true},
{ code: "VK_F8", allowed: true},
{ code: "VK_F9", allowed: true},
{ code: "VK_F10", allowed: true},
{ code: "VK_F11", allowed: true},
{ code: "VK_F12", allowed: true},
{ code: "VK_F13", allowed: true},
{ code: "VK_F14", allowed: true},
{ code: "VK_F15", allowed: true},
{ code: "VK_F16", allowed: true},
{ code: "VK_F17", allowed: true},
{ code: "VK_F18", allowed: true},
{ code: "VK_F19", allowed: true},
{ code: "VK_F20", allowed: true},
{ code: "VK_F21", allowed: true},
{ code: "VK_F22", allowed: true},
{ code: "VK_F23", allowed: true},
{ code: "VK_F24", allowed: true},
{ code: "VK_NUM_LOCK", allowed: true},
{ code: "VK_SCROLL_LOCK", allowed: true},
{ code: "VK_COMMA", allowed: true},
{ code: "VK_PERIOD", allowed: true},
{ code: "VK_SLASH", allowed: true},
{ code: "VK_BACK_QUOTE", allowed: true},
{ code: "VK_OPEN_BRACKET", allowed: true},
{ code: "VK_BACK_SLASH", allowed: true},
{ code: "VK_CLOSE_BRACKET", allowed: true},
{ code: "VK_QUOTE", allowed: true},
{ code: "VK_META", allowed: true},
];
function ok(condition, msg) {
opener.ok(condition, msg);
}
function is(a, b, msg) {
opener.is(a, b, msg);
}
var gKeyTestIndex = 0;
var gKeyName;
var gKeyCode;
var gKeyAllowed;
var gKeyReceived = false;
function keyHandler(event) {
event.preventDefault()
gKeyReceived = true;
}
function checkKeyEffect() {
is(document.mozFullScreen, gKeyAllowed,
(gKeyAllowed ? ("Should remain in full-screen mode for allowed key press " + gKeyName)
: ("Should drop out of full-screen mode for restricted key press " + gKeyName)));
if (gKeyTestIndex < keyList.length) {
setTimeout(testNextKey, 0);
} else {
opener.keysTestFinished();
}
}
function testTrustedKeyEvents() {
document.body.focus();
gKeyReceived = false;
synthesizeKey(gKeyName, {});
setTimeout(checkKeyEffect, 0);
}
function testScriptInitiatedKeyEvents() {
// Script initiated untrusted key events should not be blocked.
document.body.focus();
gKeyReceived = false;
var evt = document.createEvent("KeyEvents");
evt.initKeyEvent("keydown", true, true, window,
false, false, false, false,
gKeyCode, 0);
document.body.dispatchEvent(evt);
evt = document.createEvent("KeyEvents");
evt.initKeyEvent("keypress", true, true, window,
false, false, false, false,
gKeyCode, 0);
document.body.dispatchEvent(evt);
evt = document.createEvent("KeyEvents");
evt.initKeyEvent("keyup", true, true, window,
false, false, false, false,
gKeyCode, 0);
document.body.dispatchEvent(evt);
ok(gKeyReceived, "dispatchEvent should dispatch events synchronously");
ok(document.mozFullScreen,
"Should remain in full-screen mode for script initiated key events for " + gKeyName);
}
function testNextKey() {
if (!document.mozFullScreen) {
document.body.mozRequestFullScreen();
}
ok(document.mozFullScreen, "Must be in full-screen mode");
gKeyName = keyList[gKeyTestIndex].code;
gKeyCode = KeyEvent["DOM_" + gKeyName];
gKeyAllowed = keyList[gKeyTestIndex].allowed;
gKeyTestIndex++;
testScriptInitiatedKeyEvents();
testTrustedKeyEvents();
}
window.addEventListener("keydown", keyHandler, true);
window.addEventListener("keyup", keyHandler, true);
window.addEventListener("keypress", keyHandler, true);
setTimeout(testNextKey, 0);
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,161 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=545812
Test DOM full-screen API.
-->
<head>
<title>Test for Bug 545812</title>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<style>
body:-moz-full-screen, div:-moz-full-screen {
background-color: red;
}
</style>
</head>
<body onload="document.body.mozRequestFullScreen();">
<script type="application/javascript">
/** Test for Bug 545812 **/
function ok(condition, msg) {
opener.ok(condition, msg);
}
function is(a, b, msg) {
opener.is(a, b, msg);
}
/*
<html>
<body onload='document.body.mozRequestFullScreen();'>
</body>
</html>
*/
var iframeContents = "data:text/html;charset=utf-8,<html>%0D%0A <body onload%3D'document.body.mozRequestFullScreen()%3B'>%0D%0A <%2Fbody>%0D%0A<%2Fhtml>";
var iframe = null;
var outOfDocElement = null;
var inDocElement = null;
var button = null;
var fullScreenChangeCount = 0;
function sendMouseClick(element) {
synthesizeMouseAtCenter(element, {});
}
function setRequireTrustedContext(value) {
opener.SpecialPowers.setBoolPref("full-screen-api.allow-trusted-requests-only", value);
}
function fullScreenChange(event) {
switch (fullScreenChangeCount) {
case 0: {
ok(document.mozFullScreen, "Should be in full-screen mode (first time)");
is(event.target, document.body, "Event target should be full-screen element");
is(document.mozFullScreenElement, document.body,
"Full-screen element should be body element.");
document.mozCancelFullScreen();
break;
}
case 1: {
ok(!document.mozFullScreen, "Should have left full-screen mode (first time)");
is(event.target, document.body, "Event target should be full-screen element");
is(document.mozFullScreenElement, null, "Full-screen element should be null.");
iframe = document.createElement("iframe");
iframe.mozAllowFullScreen = true;
document.body.appendChild(iframe);
iframe.src = iframeContents;
break;
}
case 2: {
ok(document.mozFullScreen, "Should be back in full-screen mode (second time)");
is(event.target, iframe,
"Event target should be full-screen element container");
is(document.mozFullScreenElement, iframe,
"Full-screen element should be iframe element.");
document.mozCancelFullScreen();
break;
}
case 3: {
ok(!document.mozFullScreen, "Should be back in non-full-screen mode (second time)");
is(event.target, iframe,
"Event target should be full-screen element container");
is(document.mozFullScreenElement, null, "Full-screen element should be null.");
document.body.removeChild(iframe);
iframe = null;
outOfDocElement = document.createElement("div");
outOfDocElement.mozRequestFullScreen();
break;
}
case 4: {
ok(document.mozFullScreen, "Should be back in full-screen mode (third time)");
is(event.target, document, "Event target should be document");
is(document.mozFullScreenElement, null,
"Should not have a full-screen element when element not in document requests full-screen.");
// Set another element to be the full-screen element. It should immediately
// become the current full-screen element.
inDocElement = document.createElement("div");
document.body.appendChild(inDocElement);
inDocElement.mozRequestFullScreen();
ok(document.mozFullScreen, "Should remain in full-screen mode (third and a half time)");
is(document.mozFullScreenElement, inDocElement,
"Full-screen element should be in doc again.");
// Remove full-screen element from document before exiting full screen.
document.body.removeChild(inDocElement);
ok(document.mozFullScreen,
"Should remain in full-screen mode after removing full-screen element from document");
is(document.mozFullScreenElement, null,
"Should not have a full-screen element again.");
document.mozCancelFullScreen();
break;
}
case 5: {
ok(!document.mozFullScreen, "Should be back in non-full-screen mode (third time)");
setRequireTrustedContext(true);
document.body.mozRequestFullScreen();
ok(!document.mozFullScreen, "Should still be in normal mode, because calling context isn't trusted.");
button = document.createElement("button");
button.onclick = function(){document.body.mozRequestFullScreen();}
document.body.appendChild(button);
sendMouseClick(button);
break;
}
case 6: {
ok(document.mozFullScreen, "Moved to full-screen after mouse click");
document.mozCancelFullScreen();
ok(document.mozFullScreen, "Should still be in full-screen mode, because calling context isn't trusted.");
setRequireTrustedContext(false);
document.mozCancelFullScreen();
ok(!document.mozFullScreen, "Should have left full-screen mode.");
break;
}
case 7: {
ok(!document.mozFullScreen, "Should have left full-screen mode (last time).");
// Set timeout for calling finish(), so that any pending "mozfullscreenchange" events
// would have a chance to fire.
setTimeout(function(){opener.apiTestFinished();}, 0);
break;
}
default: {
ok(false, "Should not receive any more fullscreenchange events!");
}
}
fullScreenChangeCount++;
}
document.addEventListener("mozfullscreenchange", fullScreenChange, false);
</script>
</pre>
</body>
</html>

View File

@ -40,7 +40,6 @@ function test() {
SimpleTest.waitForExplicitFinish();
addLoadEvent(test);
addLoadEvent(SimpleTest.finish);
</script>
</pre>

View File

@ -74,7 +74,7 @@ i.onchange = function(event) {
i.oninvalid = function(event) {
eventHandler(event);
i.oninvad = null;
i.oninvalid = null;
endTest();
};

View File

@ -0,0 +1,83 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Bug 545812</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=545812">Mozilla Bug 545812</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 545812 **/
var testWindow = null;
/*
<html>
<body onload='document.body.mozRequestFullScreen();'>
</body>
</html>
*/
var requestFullScreenContents = "data:text/html;charset=utf-8,<html>%0D%0A <body onload%3D'document.body.mozRequestFullScreen()%3B'>%0D%0A <%2Fbody>%0D%0A<%2Fhtml>";
var prevTrusted = false;
var prevEnabled = false;
function run() {
document.addEventListener("mozfullscreenchange",
function(){ok(false, "Should never receive a mozfullscreenchange event in the main window.");},
false);
// Ensure the full-screen api is enabled, and will be disabled on test exit.
prevEnabled = SpecialPowers.getBoolPref("full-screen-api.enabled");
SpecialPowers.setBoolPref("full-screen-api.enabled", true);
prevTrusted = SpecialPowers.getBoolPref("full-screen-api.allow-trusted-requests-only");
// Request full-screen from a non trusted context (this script isn't a user
// generated event!). We should not receive a "mozfullscreenchange" event.
SpecialPowers.setBoolPref("full-screen-api.allow-trusted-requests-only", true);
document.body.mozRequestFullScreen();
// Disable the requirement for trusted contexts only, so the tests are easier
// to write.
SpecialPowers.setBoolPref("full-screen-api.allow-trusted-requests-only", false);
// Load an iframe whose contents requests full-screen. This request should
// fail, and we should never receive a "mozfullscreenchange" event, because the
// iframe doesn't have a mozallowfullscreen attribute.
var iframe = document.createElement("iframe");
iframe.src = requestFullScreenContents;
document.body.appendChild(iframe);
// Run the tests which go full-screen in a new window, as mochitests normally
// run in an iframe, which by default will not have the mozallowfullscreen
// attribute set, so full-screen won't work.
testWindow = window.open("file_fullscreen-api.html", "", "width=500,height=500");
}
function apiTestFinished() {
testWindow.close();
testWindow = window.open("file_fullscreen-api-keys.html", "", "width=500,height=500");
}
function keysTestFinished() {
testWindow.close();
SpecialPowers.setBoolPref("full-screen-api.enabled", prevEnabled);
SpecialPowers.setBoolPref("full-screen-api.allow-trusted-requests-only", prevTrusted);
SimpleTest.finish();
}
addLoadEvent(run);
SimpleTest.waitForExplicitFinish();
</script>
</pre>
</body>
</html>

View File

@ -262,6 +262,25 @@ MediaDocument::CreateSyntheticDocument()
return NS_ERROR_OUT_OF_MEMORY;
}
nsCOMPtr<nsINodeInfo> nodeInfoMeta;
nodeInfoMeta = mNodeInfoManager->GetNodeInfo(nsGkAtoms::meta, nsnull,
kNameSpaceID_XHTML,
nsIDOMNode::ELEMENT_NODE);
NS_ENSURE_TRUE(nodeInfoMeta, NS_ERROR_OUT_OF_MEMORY);
nsRefPtr<nsGenericHTMLElement> metaContent = NS_NewHTMLMetaElement(nodeInfoMeta.forget());
if (!metaContent) {
return NS_ERROR_OUT_OF_MEMORY;
}
metaContent->SetAttr(kNameSpaceID_None, nsGkAtoms::name,
NS_LITERAL_STRING("viewport"),
PR_TRUE);
metaContent->SetAttr(kNameSpaceID_None, nsGkAtoms::content,
NS_LITERAL_STRING("width=device-width; height=device-height;"),
PR_TRUE);
head->AppendChildTo(metaContent, PR_FALSE);
root->AppendChildTo(head, PR_FALSE);
nodeInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::body, nsnull,

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg">
<animate id="a" end="a.end+6s" />
</svg>

After

Width:  |  Height:  |  Size: 82 B

View File

@ -0,0 +1,11 @@
<svg xmlns="http://www.w3.org/2000/svg" class="reftest-wait">
<script>
window.addEventListener("load", function() {
setTimeout(function() {
document.documentElement.setCurrentTime(0);
document.documentElement.removeAttribute("class");
}, 0);
}, false);
</script>
<set id="c"/><set id="b" begin="c.begin; b.begin"/>
</svg>

After

Width:  |  Height:  |  Size: 346 B

View File

@ -37,6 +37,8 @@ load 615872-1.svg
load 650732-1.svg
load 665334-1.svg
load 669225-1.svg
load 670313-1.svg
load 669225-2.svg
load 670313-1.svg
load 678822-1.svg
load 678847-1.svg
load 678938-1.svg

View File

@ -478,6 +478,21 @@ nsSMILAnimationFunction::InterpolateResult(const nsSMILValueArray& aValues,
if (calcMode == CALC_DISCRETE || NS_FAILED(rv)) {
double scaledSimpleProgress =
ScaleSimpleProgress(simpleProgress, CALC_DISCRETE);
// Floating-point errors can mean that, for example, a sample time of 29s in
// a 100s duration animation gives us a simple progress of 0.28999999999
// instead of the 0.29 we'd expect. Normally this isn't a noticeable
// problem, but when we have sudden jumps in animation values (such as is
// the case here with discrete animation) we can get unexpected results.
//
// To counteract this, before we perform a floor() on the animation
// progress, we add a tiny fudge factor to push us into the correct interval
// in cases where floating-point errors might cause us to fall short.
static const double kFloatingPointFudgeFactor = 1.0e-16;
if (scaledSimpleProgress + kFloatingPointFudgeFactor <= 1.0) {
scaledSimpleProgress += kFloatingPointFudgeFactor;
}
if (IsToAnimation()) {
// We don't follow SMIL 3, 12.6.4, where discrete to animations
// are the same as <set> animations. Instead, we treat it as a

View File

@ -758,10 +758,10 @@ nsSMILTimedElement::Rewind()
mSeekState == SEEK_BACKWARD_FROM_ACTIVE,
"Rewind in the middle of a forwards seek?");
ClearIntervals();
// ClearIntervals puts us in to the POSTACTIVE state but we're doing a full
// rewind so go back to the startup state
// Putting us in the startup state will ensure we skip doing any interval
// updates
mElementState = STATE_STARTUP;
ClearIntervals();
UnsetBeginSpec(RemoveNonDynamic);
UnsetEndSpec(RemoveNonDynamic);
@ -784,6 +784,8 @@ nsSMILTimedElement::Rewind()
mPrevRegisteredMilestone = sMaxMilestone;
RegisterMilestone();
NS_ABORT_IF_FALSE(!mCurrentInterval,
"Current interval is set at end of rewind");
}
namespace
@ -1332,7 +1334,9 @@ nsSMILTimedElement::ClearSpecs(TimeValueSpecList& aSpecs,
void
nsSMILTimedElement::ClearIntervals()
{
mElementState = STATE_POSTACTIVE;
if (mElementState != STATE_STARTUP) {
mElementState = STATE_POSTACTIVE;
}
mCurrentRepeatIteration = 0;
ResetCurrentInterval();
@ -1684,14 +1688,15 @@ nsSMILTimedElement::GetNextInterval(const nsSMILInterval* aPrevInterval,
// a) We never had any end attribute to begin with (and hence we should
// just use the active duration after allowing for the possibility of
// an end instance provided by a DOM call), OR
// b) We have an end attribute but no end instances--this is a special
// case that is needed for syncbase timing so that animations of the
// following sort: <animate id="a" end="a.begin+1s" ... /> can be
// resolved (see SVGT 1.2 Test Suite animate-elem-221-t.svg) by first
// establishing an interval of unresolved duration, OR
// b) We have no resolved (not incl. indefinite) end instances
// (SMIL only says "if the instance list is empty"--but if we have
// indefinite/unresolved instance times then there must be a good
// reason we haven't used them (since they'll be >= tempBegin) such as
// avoiding creating a self-referential loop. In any case, the interval
// should be allowed to be open.), OR
// c) We have end events which leave the interval open-ended.
PRBool openEndedIntervalOk = mEndSpecs.IsEmpty() ||
mEndInstances.IsEmpty() ||
!HaveResolvedEndTimes() ||
EndHasEventConditions();
if (!tempEnd && !openEndedIntervalOk)
return PR_FALSE; // Bad interval
@ -2248,6 +2253,17 @@ nsSMILTimedElement::GetPreviousInterval() const
: mOldIntervals[mOldIntervals.Length()-1].get();
}
PRBool
nsSMILTimedElement::HaveResolvedEndTimes() const
{
if (mEndInstances.IsEmpty())
return PR_FALSE;
// mEndInstances is sorted so if the first time is not resolved then none of
// them are
return mEndInstances[0]->Time().IsResolved();
}
PRBool
nsSMILTimedElement::EndHasEventConditions() const
{

View File

@ -525,6 +525,7 @@ protected:
const nsSMILInstanceTime* GetEffectiveBeginInstance() const;
const nsSMILInterval* GetPreviousInterval() const;
PRBool HasPlayed() const { return !mOldIntervals.IsEmpty(); }
PRBool HaveResolvedEndTimes() const;
PRBool EndHasEventConditions() const;
// Reset the current interval by first passing ownership to a temporary

View File

@ -60,6 +60,7 @@ _TEST_FILES = \
test_animLengthUnits.xhtml \
test_bbox.xhtml \
test_bbox-with-invalid-viewBox.xhtml \
test_bounds.html \
bbox-helper.svg \
bounds-helper.svg \
test_dataTypes.html \

View File

@ -7,24 +7,23 @@ text { font: 20px monospace; }
<g id="g">
<text id="text1" x="25" y="25">abc</text>
<text id="text1a" x="85" y="25" stroke="black" stroke-width="4">abc</text>
<rect id="rect1" x="50" y="50" width="50" height="50" fill="green"/>
<rect id="rect1a" x="50" y="50" width="50" height="50" fill="none" stroke-width="2" stroke="yellow"/>
<rect id="rect1a" x="50" y="50" width="50" height="50" fill="none" stroke-width="4" stroke="yellow"/>
<text id="text2" x="125" y="25">abc</text>
<text id="text2a" x="185" y="25" stroke="black" stroke-width="10">abc</text>
<g transform="rotate(45 175 75)">
<rect id="rect2" x="150" y="50" width="50" height="50" fill="yellow"/>
<rect id="rect2a" x="150" y="50" width="50" height="50" fill="none" stroke-width="2" stroke="blue"/>
<rect id="rect2a" x="150" y="50" width="50" height="50" fill="none" stroke-width="4" stroke="blue"/>
<text id="text3" x="150" y="50" text-anchor="middle">abc</text>
</g>
<g transform="scale(2)">
<rect id="rect3" x="25" y="80" width="50" height="50" fill="green"/>
<rect id="rect3a" x="25" y="80" width="50" height="50" fill="none" stroke-width="2" stroke="blue"/>
<rect id="rect3a" x="25" y="80" width="50" height="50" fill="none" stroke-width="4" stroke="blue"/>
</g>
<g transform="scale(2) rotate(45 175 75)">
<rect id="rect4" x="150" y="50" width="50" height="50" fill="yellow"/>
<rect id="rect4a" x="150" y="50" width="50" height="50" fill="none" stroke-width="2" stroke="blue"/>
<text id="text4" x="125" y="125">abc</text>
<rect id="rect4a" x="150" y="50" width="50" height="50" fill="none" stroke-width="4" stroke="blue"/>
</g>
<text id="text1a" x="85" y="25" stroke="black" stroke-width="1">M</text>
<text id="text2a" x="185" y="25" stroke="black" stroke-width="10">M</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -19,101 +19,120 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=463934
<script class="testbody" type="application/javascript">
SimpleTest.waitForExplicitFinish();
function Rect(left, top, width, height)
{
this.left = left;
this.top = top;
this.width = width;
this.height = height;
}
Rect.prototype.roundOut = function()
{
this.width = Math.ceil(this.left + this.width) - Math.floor(this.left);
this.height = Math.ceil(this.top + this.height) - Math.floor(this.top);
this.left = Math.floor(this.left);
this.top = Math.floor(this.top);
}
var delta = 1;
function isApproximately(a, b, message)
{
ok(delta >= Math.abs(a - b), message + " - got " + a + ", expected " + b + " ± " + delta);
}
function runTest()
{
function isRounded(a, b, message) {
is (Math.round(a), Math.round(b), message);
}
var doc = $("svg").contentWindow.document;
var text1 = doc.getElementById("text1");
var len = text1.getComputedTextLength();
var text1Bounds = text1.getBoundingClientRect();
var text2Bounds = doc.getElementById("text2").getBoundingClientRect();
var text3Bounds = doc.getElementById("text3").getBoundingClientRect();
var text4Bounds = doc.getElementById("text4").getBoundingClientRect();
var sin45 = Math.sin(Math.PI / 4);
isRounded(text1Bounds.left, 25, "text1.getBoundingClientRect().left");
isRounded(text1Bounds.width, len, "text1.getBoundingClientRect().width");
isApproximately(text1Bounds.left, 24, "text1.getBoundingClientRect().left");
isRounded(text2Bounds.left, text1Bounds.left + 100, "text2.getBoundingClientRect().left");
isRounded(text2Bounds.top, text1Bounds.top, "text2.getBoundingClientRect().top");
isRounded(text2Bounds.width, text1Bounds.width, "text2.getBoundingClientRect().width");
isRounded(text2Bounds.height, text1Bounds.height, "text2.getBoundingClientRect().height");
is(text2Bounds.left, text1Bounds.left + 100, "text2.getBoundingClientRect().left");
is(text2Bounds.top, text1Bounds.top, "text2.getBoundingClientRect().top");
is(text2Bounds.width, text1Bounds.width, "text2.getBoundingClientRect().width");
is(text2Bounds.height, text1Bounds.height, "text2.getBoundingClientRect().height");
isRounded(text3Bounds.width, (text1Bounds.width + text1Bounds.height) * sin45 + .5, "text3.getBoundingClientRect().width");
isRounded(text3Bounds.height, (text1Bounds.height + text1Bounds.width) * sin45 + .5, "text3.getBoundingClientRect().height");
isRounded(text4Bounds.width, 2 * (text1Bounds.width + text1Bounds.height) * sin45, "text4.getBoundingClientRect().width");
isRounded(text4Bounds.height, 2 * ((text1Bounds.height + text1Bounds.width) * sin45 - .5), "text4.getBoundingClientRect().height");
var r = (text1Bounds.width + text1Bounds.height) * sin45;
isApproximately(text3Bounds.width, Math.ceil(r), "text3.getBoundingClientRect().width");
isApproximately(text3Bounds.height, Math.ceil(r), "text3.getBoundingClientRect().height");
var rect1Bounds = doc.getElementById("rect1").getBoundingClientRect();
var rect2Bounds = doc.getElementById("rect2").getBoundingClientRect();
var rect3Bounds = doc.getElementById("rect3").getBoundingClientRect();
var rect4Bounds = doc.getElementById("rect4").getBoundingClientRect();
isRounded(rect1Bounds.left, 50, "rect1.getBoundingClientRect().left");
isRounded(rect1Bounds.top, 50, "rect1.getBoundingClientRect().top");
isRounded(rect1Bounds.width, 50, "rect1.getBoundingClientRect().width");
isRounded(rect1Bounds.height, 50, "rect1.getBoundingClientRect().height");
isRounded(rect2Bounds.left, 175 - 50 * sin45 - .5, "rect2.getBoundingClientRect().left");
isRounded(rect2Bounds.top, 75 - 50 * sin45 - .5, "rect2.getBoundingClientRect().top");
isRounded(rect2Bounds.width, (50 * sin45 + .5) * 2, "rect2.getBoundingClientRect().width");
isRounded(rect2Bounds.height, (50 * sin45 + .5) * 2, "rect2.getBoundingClientRect().height");
is(rect1Bounds.left, 50, "rect1.getBoundingClientRect().left");
is(rect1Bounds.top, 50, "rect1.getBoundingClientRect().top");
is(rect1Bounds.width, 50, "rect1.getBoundingClientRect().width");
is(rect1Bounds.height, 50, "rect1.getBoundingClientRect().height");
isRounded(rect3Bounds.left, 50, "rect3.getBoundingClientRect().left");
isRounded(rect3Bounds.top, 160, "rect3.getBoundingClientRect().top");
isRounded(rect3Bounds.width, 100, "rect3.getBoundingClientRect().width");
isRounded(rect3Bounds.height, 100, "rect3.getBoundingClientRect().height");
rect = new Rect(175 - 50 * sin45, 75 - 50 * sin45, 50 * sin45 * 2, 50 * sin45 * 2);
rect.roundOut();
is(rect2Bounds.left, rect.left, "rect2.getBoundingClientRect().left");
is(rect2Bounds.top, rect.top, "rect2.getBoundingClientRect().top");
is(rect2Bounds.width, rect.width, "rect2.getBoundingClientRect().width");
is(rect2Bounds.height, rect.height, "rect2.getBoundingClientRect().height");
isRounded(rect4Bounds.left, 350 - 100 * sin45 - .5, "rect4.getBoundingClientRect().left");
isRounded(rect4Bounds.top, 150 - 100 * sin45 - .5, "rect4.getBoundingClientRect().top");
isRounded(rect4Bounds.width, (100 * sin45 + .5) * 2, "rect4.getBoundingClientRect().width");
isRounded(rect4Bounds.height, (100 * sin45 + .5) * 2, "rect4.getBoundingClientRect().height");
is(rect3Bounds.left, 50, "rect3.getBoundingClientRect().left");
is(rect3Bounds.top, 160, "rect3.getBoundingClientRect().top");
is(rect3Bounds.width, 100, "rect3.getBoundingClientRect().width");
is(rect3Bounds.height, 100, "rect3.getBoundingClientRect().height");
rect = new Rect(350 - 100 * sin45, 150 - 100 * sin45, 100 * sin45 * 2, 100 * sin45 * 2);
rect.roundOut();
is(rect4Bounds.left, rect.left, "rect4.getBoundingClientRect().left");
is(rect4Bounds.top, rect.top, "rect4.getBoundingClientRect().top");
is(rect4Bounds.width, rect.width, "rect4.getBoundingClientRect().width");
is(rect4Bounds.height, rect.height, "rect4.getBoundingClientRect().height");
var rect1aBounds = doc.getElementById("rect1a").getBoundingClientRect();
var rect2aBounds = doc.getElementById("rect2a").getBoundingClientRect();
var rect3aBounds = doc.getElementById("rect3a").getBoundingClientRect();
var rect4aBounds = doc.getElementById("rect4a").getBoundingClientRect();
isRounded(rect1aBounds.left, 49, "rect1a.getBoundingClientRect().left");
isRounded(rect1aBounds.top, 49, "rect1a.getBoundingClientRect().top");
isRounded(rect1aBounds.width, 52, "rect1a.getBoundingClientRect().width");
isRounded(rect1aBounds.height, 52, "rect1a.getBoundingClientRect().height");
isRounded(rect2aBounds.left, 175 - 52 * sin45 - .5, "rect2a.getBoundingClientRect().left");
isRounded(rect2aBounds.top, 75 - 52 * sin45 - .5, "rect2a.getBoundingClientRect().top");
isRounded(rect2aBounds.width, 52 * sin45 * 2, "rect2a.getBoundingClientRect().width");
isRounded(rect2aBounds.height, 52 * sin45 * 2, "rect2a.getBoundingClientRect().height");
is(rect1aBounds.left, 48, "rect1a.getBoundingClientRect().left");
is(rect1aBounds.top, 48, "rect1a.getBoundingClientRect().top");
is(rect1aBounds.width, 54, "rect1a.getBoundingClientRect().width");
is(rect1aBounds.height, 54, "rect1a.getBoundingClientRect().height");
isRounded(rect3aBounds.left, 48, "rect3a.getBoundingClientRect().left");
isRounded(rect3aBounds.top, 158, "rect3a.getBoundingClientRect().top");
isRounded(rect3aBounds.width, 104, "rect3a.getBoundingClientRect().width");
isRounded(rect3aBounds.height, 104, "rect3a.getBoundingClientRect().height");
rect = new Rect(175 - 54 * sin45, 75 - 54 * sin45, 54 * sin45 * 2, 54 * sin45 * 2);
rect.roundOut();
is(rect2aBounds.left, rect.left, "rect2a.getBoundingClientRect().left");
is(rect2aBounds.top, rect.top, "rect2a.getBoundingClientRect().top");
is(rect2aBounds.width, rect.width, "rect2a.getBoundingClientRect().width");
is(rect2aBounds.height, rect.height, "rect2a.getBoundingClientRect().height");
isRounded(rect4aBounds.left, 350 - 104 * sin45 - .5, "rect4a.getBoundingClientRect().left");
isRounded(rect4aBounds.top, 150 - 104 * sin45 - .5, "rect4a.getBoundingClientRect().top");
isRounded(rect4aBounds.width, (104 * sin45 + .5) * 2, "rect4a.getBoundingClientRect().width");
isRounded(rect4aBounds.height, (104 * sin45 + .5) * 2, "rect4a.getBoundingClientRect().height");
is(rect3aBounds.left, 46, "rect3a.getBoundingClientRect().left");
is(rect3aBounds.top, 156, "rect3a.getBoundingClientRect().top");
is(rect3aBounds.width, 108, "rect3a.getBoundingClientRect().width");
is(rect3aBounds.height, 108, "rect3a.getBoundingClientRect().height");
rect = new Rect(350 - 108 * sin45, 150 - 108 * sin45, 108 * sin45 * 2, 108 * sin45 * 2);
rect.roundOut();
is(rect4aBounds.left, rect.left, "rect4a.getBoundingClientRect().left");
is(rect4aBounds.top, rect.top, "rect4a.getBoundingClientRect().top");
is(rect4aBounds.width, rect.width, "rect4a.getBoundingClientRect().width");
is(rect4aBounds.height, rect.height, "rect4a.getBoundingClientRect().height");
var text1a = doc.getElementById("text1a");
var text1aBounds = text1a.getBoundingClientRect();
var text2aBounds = doc.getElementById("text2a").getBoundingClientRect();
var len = text1a.getComputedTextLength();
isApproximately(text1aBounds.left, 82, "text1a.getBoundingClientRect().left");
is(text1aBounds.width, text1Bounds.width + 4, "text1a.getBoundingClientRect().width");
isRounded(text1aBounds.left, 85 - 1, "text1a.getBoundingClientRect().left");
isRounded(text1aBounds.width, len + 1, "text1a.getBoundingClientRect().width");
isRounded(text2aBounds.left, text1aBounds.left + 100 - 4, "text2a.getBoundingClientRect().left");
isRounded(text2aBounds.width, text1aBounds.width + 9, "text2a.getBoundingClientRect().width");
is(text2aBounds.left, text1aBounds.left + 100 - 3, "text2a.getBoundingClientRect().left");
is(text2aBounds.width, text1aBounds.width + 6, "text2a.getBoundingClientRect().width");
SimpleTest.finish();
}

View File

@ -44,8 +44,4 @@ include $(DEPTH)/config/autoconf.mk
PARALLEL_DIRS = base xml xpath xslt
ifdef MOZ_XSLT_STANDALONE
PARALLEL_DIRS += main
endif
include $(topsrcdir)/config/rules.mk

View File

@ -46,20 +46,12 @@ MODULE = transformiix
LIBRARY_NAME = txbase_s
LIBXUL_LIBRARY = 1
CPPSRCS = txDouble.cpp \
txList.cpp \
txExpandedNameMap.cpp \
txNamespaceMap.cpp \
txURIUtils.cpp
ifdef MOZ_XSLT_STANDALONE
CPPSRCS += txSimpleErrorObserver.cpp \
txStringUtils.cpp \
txAtoms.cpp
endif
# we don't want the shared lib, but we want to force the creation of a
# static lib.
FORCE_STATIC_LIB = 1

View File

@ -39,75 +39,10 @@
#ifndef TRANSFRMX_ATOMS_H
#define TRANSFRMX_ATOMS_H
#ifndef TX_EXE
#include "nsGkAtoms.h"
typedef class nsGkAtoms txXPathAtoms;
typedef class nsGkAtoms txXMLAtoms;
typedef class nsGkAtoms txXSLTAtoms;
typedef class nsGkAtoms txHTMLAtoms;
#else
class nsIAtom;
/*
* Declare all atoms
*
* The atom names and values are stored in tx*AtomList.h and
* are brought to you by the magic of C preprocessing.
* Add new atoms to tx*AtomList.h and all support logic will
* be auto-generated.
*/
#define DOM_ATOMS \
TX_ATOM(comment, "#comment") \
TX_ATOM(document, "#document") \
TX_ATOM(text, "#text")
#define XML_ATOMS \
TX_ATOM(_empty, "") \
TX_ATOM(base, "base") \
TX_ATOM(_default, "default") \
TX_ATOM(lang, "lang") \
TX_ATOM(preserve, "preserve") \
TX_ATOM(space, "space") \
TX_ATOM(xml, "xml") \
TX_ATOM(xmlns, "xmlns") \
DOM_ATOMS
#define TX_ATOM(_name, _value) static nsIAtom* _name;
class txXMLAtoms
{
public:
static void init();
XML_ATOMS
};
class txXPathAtoms
{
public:
static void init();
#include "txXPathAtomList.h"
};
class txXSLTAtoms
{
public:
static void init();
#include "txXSLTAtomList.h"
};
class txHTMLAtoms
{
public:
static void init();
#include "txHTMLAtomList.h"
};
#undef TX_ATOM
#endif
#endif

View File

@ -40,9 +40,6 @@
#define MITRE_ERROROBSERVER_H
#include "txCore.h"
#ifdef TX_EXE
#include <iostream.h>
#endif
/**
* A simple interface for observing errors
@ -74,39 +71,4 @@ public:
}; //-- ErrorObserver
#ifdef TX_EXE
/**
* A simple ErrorObserver which allows printing error messages to a stream
**/
class SimpleErrorObserver : public ErrorObserver {
public:
/**
* Creates a new SimpleErrorObserver.
* All errors will be printed to the console (cout).
**/
SimpleErrorObserver();
/**
* Creates a new SimpleErrorObserver.
* All errors will be printed to the given ostream.
**/
SimpleErrorObserver(ostream& errStream);
/**
* Notifies this Error observer of a new error aRes
**/
void receiveError(const nsAString& errorMessage, nsresult aRes);
virtual void suppressWarnings(MBool suppress);
private:
ostream* errStream;
MBool hideWarnings;
}; //-- SimpleErrorObserver
#endif
#endif

View File

@ -1,80 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** 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 TransforMiiX XSLT processor code.
*
* The Initial Developer of the Original Code is
* The MITRE Corporation.
* Portions created by the Initial Developer are Copyright (C) 1999
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Keith Visco <kvisco@ziplink.net> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "txErrorObserver.h"
#include "nsString.h"
/**
* Creates a new SimpleErrorObserver.
* All errors will be printed to the console (cout).
**/
SimpleErrorObserver::SimpleErrorObserver() {
#ifdef TX_EXE
errStream = &cout;
#endif
hideWarnings = MB_FALSE;
} //-- SimpleErrorObserver
/**
* Creates a new SimpleErrorObserver.
* All errors will be printed to the given ostream.
**/
SimpleErrorObserver::SimpleErrorObserver(ostream& errStream) {
this->errStream = &errStream;
hideWarnings = MB_FALSE;
} //-- SimpleErrorObserver
/**
* Notifies this Error observer of a new error using the given error level
**/
void SimpleErrorObserver::receiveError(const nsAString& errorMessage,
nsresult aRes)
{
#ifdef TX_EXE
if (NS_FAILED(aRes)) {
*errStream << "error: ";
}
*errStream << NS_LossyConvertUTF16toASCII(errorMessage).get() << endl;
errStream->flush();
#endif
}
void SimpleErrorObserver::suppressWarnings(MBool suppress) {
this->hideWarnings = suppress;
} //-- suppressWarnings

View File

@ -1,152 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** 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 TransforMiiX XSLT processor code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <axel@pike.org>
* Peter Van der Beken <peterv@propagandism.org>
*
* 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 "txStringUtils.h"
#include "nsDependentString.h"
int
txCaseInsensitiveStringComparator::operator()(const char_type* lhs,
const char_type* rhs,
PRUint32 aLength ) const
{
PRUnichar thisChar, otherChar;
PRUint32 compLoop = 0;
while (compLoop < aLength) {
thisChar = lhs[compLoop];
if ((thisChar >= 'A') && (thisChar <= 'Z')) {
thisChar += 32;
}
otherChar = rhs[compLoop];
if ((otherChar >= 'A') && (otherChar <= 'Z')) {
otherChar += 32;
}
if (thisChar != otherChar) {
return thisChar - otherChar;
}
++compLoop;
}
return 0;
}
int
txCaseInsensitiveStringComparator::operator()(char_type lhs,
char_type rhs) const
{
if (lhs >= 'A' && lhs <= 'Z') {
lhs += 32;
}
if (rhs >= 'A' && rhs <= 'Z') {
rhs += 32;
}
return lhs - rhs;
}
/**
* A character sink for case conversion.
*/
class ConvertToLowerCase
{
public:
typedef PRUnichar value_type;
void write( const PRUnichar* aSource, PRUint32 aSourceLength)
{
PRUnichar* cp = const_cast<PRUnichar*>(aSource);
const PRUnichar* end = aSource + aSourceLength;
while (cp != end) {
PRUnichar ch = *cp;
if ((ch >= 'A') && (ch <= 'Z'))
*cp = ch + ('a' - 'A');
++cp;
}
}
};
void TX_ToLowerCase(nsAString& aString)
{
nsAString::iterator fromBegin, fromEnd;
ConvertToLowerCase converter;
copy_string(aString.BeginWriting(fromBegin), aString.EndWriting(fromEnd),
converter);
}
/**
* A character sink for copying with case conversion.
*/
class CopyToLowerCase
{
public:
typedef PRUnichar value_type;
CopyToLowerCase(nsAString::iterator& aDestIter) : mIter(aDestIter)
{
}
void write(const PRUnichar* aSource, PRUint32 aSourceLength)
{
PRUint32 len = NS_MIN(PRUint32(mIter.size_forward()), aSourceLength);
PRUnichar* cp = mIter.get();
const PRUnichar* end = aSource + len;
while (aSource != end) {
PRUnichar ch = *aSource;
if ((ch >= 'A') && (ch <= 'Z'))
*cp = ch + ('a' - 'A');
else
*cp = ch;
++aSource;
++cp;
}
mIter.advance(len);
}
protected:
nsAString::iterator& mIter;
};
void TX_ToLowerCase(const nsAString& aSource, nsAString& aDest)
{
nsAString::const_iterator fromBegin, fromEnd;
nsAString::iterator toBegin;
if (!EnsureStringLength(aDest, aSource.Length()))
return; // XXX no way to signal out-of-memory
CopyToLowerCase converter(aDest.BeginWriting(toBegin));
copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd),
converter);
}

View File

@ -42,6 +42,11 @@
#include "nsAString.h"
#include "nsIAtom.h"
#include "nsUnicharUtils.h"
#define TX_ToLowerCase ToLowerCase
typedef nsCaseInsensitiveStringComparator txCaseInsensitiveStringComparator;
/**
* Check equality between a string and an atom containing ASCII.
@ -52,30 +57,6 @@ TX_StringEqualsAtom(const nsASingleFragmentString& aString, nsIAtom* aAtom)
return aAtom->Equals(aString);
}
#ifndef TX_EXE
#include "nsUnicharUtils.h"
typedef nsCaseInsensitiveStringComparator txCaseInsensitiveStringComparator;
#define TX_ToLowerCase ToLowerCase
#else
// These only work for ASCII ranges!
class txCaseInsensitiveStringComparator
: public nsStringComparator
{
public:
virtual int operator()(const char_type*, const char_type*, PRUint32 aLength) const;
virtual int operator()(char_type, char_type) const;
};
void TX_ToLowerCase(nsAString& aString);
void TX_ToLowerCase(const nsAString& aSource, nsAString& aDest);
#endif
inline already_AddRefed<nsIAtom>
TX_ToLowerCaseAtom(nsIAtom* aAtom)
{

View File

@ -38,8 +38,6 @@
* ***** END LICENSE BLOCK ***** */
#include "txURIUtils.h"
#ifndef TX_EXE
#include "nsNetUtil.h"
#include "nsIAttribute.h"
#include "nsIScriptSecurityManager.h"
@ -48,119 +46,12 @@
#include "nsIContent.h"
#include "nsIPrincipal.h"
#include "nsINodeInfo.h"
#endif
/**
* URIUtils
* A set of utilities for handling URIs
**/
#ifdef TX_EXE
//- Constants -/
const char URIUtils::HREF_PATH_SEP = '/';
/**
* Implementation of utility functions for parsing URLs.
* Just file paths for now.
*/
void
txParsedURL::init(const nsAFlatString& aSpec)
{
mPath.Truncate();
mName.Truncate();
mRef.Truncate();
PRUint32 specLength = aSpec.Length();
if (!specLength) {
return;
}
const PRUnichar* start = aSpec.get();
const PRUnichar* end = start + specLength;
const PRUnichar* c = end - 1;
// check for #ref
for (; c >= start; --c) {
if (*c == '#') {
// we could eventually unescape this, too.
mRef = Substring(c + 1, end);
end = c;
--c;
if (c == start) {
// we're done,
return;
}
break;
}
}
for (c = end - 1; c >= start; --c) {
if (*c == '/') {
mName = Substring(c + 1, end);
mPath = Substring(start, c + 1);
return;
}
}
mName = Substring(start, end);
}
void
txParsedURL::resolve(const txParsedURL& aRef, txParsedURL& aDest)
{
/*
* No handling of absolute URLs now.
* These aren't really URLs yet, anyway, but paths with refs
*/
aDest.mPath = mPath + aRef.mPath;
if (aRef.mName.IsEmpty() && aRef.mPath.IsEmpty()) {
// the relative URL is just a fragment identifier
aDest.mName = mName;
if (aRef.mRef.IsEmpty()) {
// and not even that, keep the base ref
aDest.mRef = mRef;
return;
}
aDest.mRef = aRef.mRef;
return;
}
aDest.mName = aRef.mName;
aDest.mRef = aRef.mRef;
}
/**
* Returns an InputStream for the file represented by the href
* argument
* @param href the href of the file to get the input stream for.
* @return an InputStream to the desired resource
* @exception java.io.FileNotFoundException when the file could not be
* found
**/
istream* URIUtils::getInputStream(const nsAString& href, nsAString& errMsg)
{
return new ifstream(NS_LossyConvertUTF16toASCII(href).get(), ios::in);
} //-- getInputStream
/**
* Returns the document base of the href argument
* @return the document base of the given href
**/
void URIUtils::getDocumentBase(const nsAFlatString& href, nsAString& dest)
{
if (href.IsEmpty()) {
return;
}
nsAFlatString::const_char_iterator temp;
href.BeginReading(temp);
PRUint32 iter = href.Length();
while (iter > 0) {
if (temp[--iter] == HREF_PATH_SEP) {
dest.Append(StringHead(href, iter));
break;
}
}
}
#endif
/**
* Resolves the given href argument, using the given documentBase
* if necessary.
@ -176,8 +67,6 @@ void URIUtils::resolveHref(const nsAString& href, const nsAString& base,
dest.Append(base);
return;
}
#ifndef TX_EXE
nsCOMPtr<nsIURI> pURL;
nsAutoString resultHref;
nsresult result = NS_NewURI(getter_AddRefs(pURL), base);
@ -185,23 +74,8 @@ void URIUtils::resolveHref(const nsAString& href, const nsAString& base,
NS_MakeAbsoluteURI(resultHref, href, pURL);
dest.Append(resultHref);
}
#else
nsAutoString documentBase;
getDocumentBase(PromiseFlatString(base), documentBase);
//-- join document base + href
if (!documentBase.IsEmpty()) {
dest.Append(documentBase);
if (documentBase.CharAt(documentBase.Length()-1) != HREF_PATH_SEP)
dest.Append(PRUnichar(HREF_PATH_SEP));
}
dest.Append(href);
#endif
} //-- resolveHref
#ifndef TX_EXE
// static
void
URIUtils::ResetWithSource(nsIDocument *aNewDoc, nsIDOMNode *aSourceNode)
@ -245,5 +119,3 @@ URIUtils::ResetWithSource(nsIDocument *aNewDoc, nsIDOMNode *aSourceNode)
sourceDoc->GetDocumentCharacterSetSource());
aNewDoc->SetDocumentCharacterSet(sourceDoc->GetDocumentCharacterSet());
}
#endif /* TX_EXE */

View File

@ -39,62 +39,23 @@
#define TRANSFRMX_URIUTILS_H
#include "txCore.h"
#ifdef TX_EXE
#include <fstream.h>
#include <iostream.h>
#include "nsString.h"
#else
class nsIDocument;
class nsIDOMNode;
#endif
/**
* A utility class for URI handling
* Not yet finished, only handles file URI at this point
**/
#ifdef TX_EXE
class txParsedURL
{
public:
void init(const nsAFlatString& aSpec);
void resolve(const txParsedURL& aRef, txParsedURL& aDest);
void getFile(nsString& aResult) const
{
aResult = mPath + mName;
}
nsString mPath, mName, mRef;
};
#endif
class URIUtils {
public:
#ifdef TX_EXE
/**
* the path separator for an URI
**/
static const char HREF_PATH_SEP;
static istream* getInputStream
(const nsAString& href, nsAString& errMsg);
/**
* Returns the document base of the href argument
* The document base will be appended to the given dest String
**/
static void getDocumentBase(const nsAFlatString& href, nsAString& dest);
#else /* TX_EXE */
/**
* Reset the given document with the document of the source node
*/
static void ResetWithSource(nsIDocument *aNewDoc, nsIDOMNode *aSourceNode);
#endif /* TX_EXE */
/**
* Resolves the given href argument, using the given documentBase
* if necessary.

Some files were not shown because too many files have changed in this diff Show More