mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to s-c
This commit is contained in:
commit
0910ed33c2
@ -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).
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
1
aclocal.m4
vendored
@ -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()
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
@ -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;
|
||||
},
|
||||
|
||||
|
208
browser/base/content/tabview/storagePolicy.js
Normal file
208
browser/base/content/tabview/storagePolicy.js
Normal 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);
|
||||
}
|
||||
};
|
@ -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");
|
||||
}
|
||||
};
|
||||
});
|
||||
|
@ -71,6 +71,7 @@ let AllTabs = {
|
||||
|
||||
#include iq.js
|
||||
#include storage.js
|
||||
#include storagePolicy.js
|
||||
#include items.js
|
||||
#include groupitems.js
|
||||
#include tabitems.js
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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 \
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
});
|
||||
});
|
||||
}
|
@ -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();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
@ -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);
|
||||
});
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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];
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
25
build/autoconf/frameptr.m4
Normal file
25
build/autoconf/frameptr.m4
Normal 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
|
||||
])
|
@ -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)
|
||||
|
@ -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@
|
||||
|
@ -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)
|
||||
|
||||
|
43
configure.in
43
configure.in
@ -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)
|
||||
|
2
content/base/crashtests/679689-1.html
Normal file
2
content/base/crashtests/679689-1.html
Normal file
@ -0,0 +1,2 @@
|
||||
<!DOCTYPE html>
|
||||
<img crossorigin>
|
@ -93,3 +93,4 @@ load 642022-1.html
|
||||
load 646184.html
|
||||
load 658845-1.svg
|
||||
load 667336-1.html
|
||||
load 679689-1.html
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -69,6 +69,7 @@ _CHROME_FILES = \
|
||||
test_bug357450.xul \
|
||||
test_bug571390.xul \
|
||||
test_bug574596.html \
|
||||
test_bug683852.xul \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
67
content/base/test/chrome/test_bug683852.xul
Normal file
67
content/base/test/chrome/test_bug683852.xul
Normal 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>
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 &&
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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_
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -177,6 +177,7 @@ public:
|
||||
eDOMEvents_afterpaint,
|
||||
eDOMEvents_beforepaint,
|
||||
eDOMEvents_beforeresize,
|
||||
eDOMEvents_mozfullscreenchange,
|
||||
eDOMEvents_MozSwipeGesture,
|
||||
eDOMEvents_MozMagnifyGestureStart,
|
||||
eDOMEvents_MozMagnifyGestureUpdate,
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
/**
|
||||
|
@ -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))
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
250
content/html/content/test/file_fullscreen-api-keys.html
Normal file
250
content/html/content/test/file_fullscreen-api-keys.html
Normal 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>
|
161
content/html/content/test/file_fullscreen-api.html
Normal file
161
content/html/content/test/file_fullscreen-api.html
Normal 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>
|
@ -40,7 +40,6 @@ function test() {
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(test);
|
||||
addLoadEvent(SimpleTest.finish);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
|
@ -74,7 +74,7 @@ i.onchange = function(event) {
|
||||
|
||||
i.oninvalid = function(event) {
|
||||
eventHandler(event);
|
||||
i.oninvad = null;
|
||||
i.oninvalid = null;
|
||||
endTest();
|
||||
};
|
||||
|
||||
|
83
content/html/content/test/test_fullscreen-api.html
Normal file
83
content/html/content/test/test_fullscreen-api.html
Normal 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>
|
@ -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,
|
||||
|
3
content/smil/crashtests/678847-1.svg
Normal file
3
content/smil/crashtests/678847-1.svg
Normal 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 |
11
content/smil/crashtests/678938-1.svg
Normal file
11
content/smil/crashtests/678938-1.svg
Normal 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 |
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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 \
|
||||
|
@ -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 |
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
@ -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);
|
||||
}
|
@ -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)
|
||||
{
|
||||
|
@ -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 */
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user