mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-01 13:57:32 +00:00
merge m-c to fx-team
This commit is contained in:
commit
ccc89189bc
@ -223,11 +223,15 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
// Function: getStorageData
|
||||
// Get data to be used for persistent storage of this object.
|
||||
getStorageData: function TabItem_getStorageData() {
|
||||
return {
|
||||
let data = {
|
||||
url: this.tab.linkedBrowser.currentURI.spec,
|
||||
groupID: (this.parent ? this.parent.id : 0),
|
||||
title: this.tab.label
|
||||
};
|
||||
if (this.parent.getActiveTab() == this)
|
||||
data.active = true;
|
||||
|
||||
return data;
|
||||
},
|
||||
|
||||
// ----------
|
||||
@ -339,14 +343,13 @@ 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 self = this;
|
||||
let tabData = Storage.getTabData(this.tab);
|
||||
|
||||
if (tabData && TabItems.storageSanity(tabData)) {
|
||||
this.loadThumbnail(tabData);
|
||||
|
||||
if (self.parent)
|
||||
self.parent.remove(self, {immediately: true});
|
||||
if (this.parent)
|
||||
this.parent.remove(this, {immediately: true});
|
||||
|
||||
let groupItem;
|
||||
|
||||
@ -357,22 +360,26 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
}
|
||||
|
||||
if (groupItem) {
|
||||
groupItem.add(self, {immediately: true});
|
||||
groupItem.add(this, {immediately: true});
|
||||
|
||||
// restore the active tab for each group between browser sessions
|
||||
if (tabData.active)
|
||||
groupItem.setActiveTab(this);
|
||||
|
||||
// if it matches the selected tab or no active tab and the browser
|
||||
// tab is hidden, the active group item would be set.
|
||||
if (self.tab == gBrowser.selectedTab ||
|
||||
(!GroupItems.getActiveGroupItem() && !self.tab.hidden))
|
||||
UI.setActive(self.parent);
|
||||
if (this.tab == gBrowser.selectedTab ||
|
||||
(!GroupItems.getActiveGroupItem() && !this.tab.hidden))
|
||||
UI.setActive(this.parent);
|
||||
}
|
||||
} else {
|
||||
// create tab group by double click is handled in UI_init().
|
||||
GroupItems.newTab(self, {immediately: true});
|
||||
GroupItems.newTab(this, {immediately: true});
|
||||
}
|
||||
|
||||
self._reconnected = true;
|
||||
self.save();
|
||||
self._sendToSubscribers("reconnected");
|
||||
this._reconnected = true;
|
||||
this.save();
|
||||
this._sendToSubscribers("reconnected");
|
||||
},
|
||||
|
||||
// ----------
|
||||
|
@ -58,6 +58,7 @@ _BROWSER_FILES = \
|
||||
browser_tabview_bug589324.js \
|
||||
browser_tabview_bug590606.js \
|
||||
browser_tabview_bug591706.js \
|
||||
browser_tabview_bug593283.js \
|
||||
browser_tabview_bug594958.js \
|
||||
browser_tabview_bug595020.js \
|
||||
browser_tabview_bug595191.js \
|
||||
|
@ -0,0 +1,75 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const DUMMY_PAGE_URL = "http://example.com/";
|
||||
|
||||
let state = {
|
||||
windows: [{
|
||||
tabs: [{
|
||||
entries: [{ url: DUMMY_PAGE_URL }],
|
||||
hidden: false,
|
||||
attributes: {},
|
||||
extData: {
|
||||
"tabview-tab": '{"url":"' + DUMMY_PAGE_URL + '","groupID":1,"title":null,"active":true}'
|
||||
}
|
||||
},{
|
||||
entries: [{ url: DUMMY_PAGE_URL }],
|
||||
hidden: false,
|
||||
attributes: {},
|
||||
extData: {
|
||||
"tabview-tab": '{"url":"' + DUMMY_PAGE_URL + '","groupID":1,"title":null}'
|
||||
}
|
||||
},{
|
||||
entries: [{ url: DUMMY_PAGE_URL }],
|
||||
hidden: true,
|
||||
attributes: {},
|
||||
extData: {
|
||||
"tabview-tab": '{"url":"' + DUMMY_PAGE_URL + '","groupID":2,"title":null}'
|
||||
},
|
||||
},{
|
||||
entries: [{ url: DUMMY_PAGE_URL }],
|
||||
hidden: true,
|
||||
attributes: {},
|
||||
extData: {
|
||||
"tabview-tab": '{"url":"' + DUMMY_PAGE_URL + '","groupID":2,"title":null,"active":true}'
|
||||
},
|
||||
}],
|
||||
selected:1,
|
||||
_closedTabs: [],
|
||||
extData: {
|
||||
"tabview-groups": '{"nextID":3,"activeGroupId":2,"totalNumber":2}',
|
||||
"tabview-group":
|
||||
'{"1":{"bounds":{"left":15,"top":28,"width":546,"height":218},' +
|
||||
'"userSize":{"x":546,"y":218},"title":"","id":1},' +
|
||||
'"2":{"bounds":{"left":15,"top":261,"width":546,"height":199},' +
|
||||
'"userSize":{"x":546,"y":199},"title":"","id":2}}',
|
||||
"tabview-ui": '{"pageBounds":{"left":0,"top":0,"width":976,"height":663}}'
|
||||
}, sizemode:"normal"
|
||||
}]
|
||||
};
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
newWindowWithState(state, function (win) {
|
||||
registerCleanupFunction(function () win.close());
|
||||
|
||||
showTabView(function() {
|
||||
let cw = win.TabView.getContentWindow();
|
||||
let groupItems = cw.GroupItems.groupItems;
|
||||
let groupOne = groupItems[0];
|
||||
let groupTwo = groupItems[1];
|
||||
|
||||
// check the active tab of each group
|
||||
is(groupOne.getActiveTab(), groupOne.getChild(0), "The active tab item of group one is the first one");
|
||||
is(groupTwo.getActiveTab(), groupTwo.getChild(1), "The active tab item of group two is the second one");
|
||||
|
||||
is(cw.UI.getActiveTab(), groupOne.getChild(0), "The hightlighted tab item is the first one in group one");
|
||||
// select a group and the second tab should be hightlighted
|
||||
cw.UI.setActive(groupTwo);
|
||||
is(cw.UI.getActiveTab(), groupTwo.getChild(1), "The hightlighted tab item is the second one in group two");
|
||||
|
||||
finish();
|
||||
}, win);
|
||||
});
|
||||
}
|
@ -27,6 +27,10 @@ function openContextMenuFor(element, shiftkey) {
|
||||
// Context menu should be closed before we open it again.
|
||||
is(contextMenu.state, "closed", "checking if popup is closed");
|
||||
|
||||
if (lastElement)
|
||||
lastElement.blur();
|
||||
element.focus();
|
||||
lastElement = element;
|
||||
var eventDetails = { type : "contextmenu", button : 2, shiftKey : shiftkey };
|
||||
synthesizeMouse(element, 2, 2, eventDetails, element.ownerDocument.defaultView);
|
||||
}
|
||||
@ -555,7 +559,7 @@ function runTest(testNum) {
|
||||
|
||||
|
||||
var testNum = 1;
|
||||
var subwindow, chromeWin, contextMenu;
|
||||
var subwindow, chromeWin, contextMenu, lastElement;
|
||||
var text, link, mailto, input, img, canvas, video_ok, video_bad, video_bad2,
|
||||
iframe, textarea, contenteditable, inputspell, pagemenu;
|
||||
|
||||
@ -577,6 +581,8 @@ function startTest() {
|
||||
return;
|
||||
}
|
||||
|
||||
lastElement = null;
|
||||
|
||||
text = subwindow.document.getElementById("test-text");
|
||||
link = subwindow.document.getElementById("test-link");
|
||||
mailto = subwindow.document.getElementById("test-mailto");
|
||||
|
@ -1801,6 +1801,26 @@ public:
|
||||
*/
|
||||
static void InitializeTouchEventTable();
|
||||
|
||||
/**
|
||||
* Test whether the given URI always inherits a security context
|
||||
* from the document it comes from.
|
||||
*/
|
||||
static nsresult URIInheritsSecurityContext(nsIURI *aURI, PRBool *aResult);
|
||||
|
||||
/**
|
||||
* Set the given principal as the owner of the given channel, if
|
||||
* needed. aURI must be the URI of aChannel. aPrincipal may be
|
||||
* null. If aSetUpForAboutBlank is true, then about:blank will get
|
||||
* the principal set up on it.
|
||||
*
|
||||
* The return value is whether the principal was set up as the owner
|
||||
* of the channel.
|
||||
*/
|
||||
static bool SetUpChannelOwner(nsIPrincipal* aLoadingPrincipal,
|
||||
nsIChannel* aChannel,
|
||||
nsIURI* aURI,
|
||||
PRBool aSetUpForAboutBlank);
|
||||
|
||||
static nsresult Btoa(const nsAString& aBinaryData,
|
||||
nsAString& aAsciiBase64String);
|
||||
|
||||
|
@ -4674,6 +4674,7 @@ nsContentUtils::URIIsLocalFile(nsIURI *aURI)
|
||||
PRBool isFile;
|
||||
nsCOMPtr<nsINetUtil> util = do_QueryInterface(sIOService);
|
||||
|
||||
// Important: we do NOT test the entire URI chain here!
|
||||
return util && NS_SUCCEEDED(util->ProtocolHasFlags(aURI,
|
||||
nsIProtocolHandler::URI_IS_LOCAL_FILE,
|
||||
&isFile)) &&
|
||||
@ -5721,6 +5722,71 @@ nsContentUtils::IsPatternMatching(nsAString& aValue, nsAString& aPattern,
|
||||
return res == JS_FALSE || rval != JSVAL_NULL;
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
nsContentUtils::URIInheritsSecurityContext(nsIURI *aURI, PRBool *aResult)
|
||||
{
|
||||
// Note: about:blank URIs do NOT inherit the security context from the
|
||||
// current document, which is what this function tests for...
|
||||
return NS_URIChainHasFlags(aURI,
|
||||
nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
|
||||
aResult);
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
nsContentUtils::SetUpChannelOwner(nsIPrincipal* aLoadingPrincipal,
|
||||
nsIChannel* aChannel,
|
||||
nsIURI* aURI,
|
||||
PRBool aSetUpForAboutBlank)
|
||||
{
|
||||
//
|
||||
// Set the owner of the channel, but only for channels that can't
|
||||
// provide their own security context.
|
||||
//
|
||||
// XXX: It seems wrong that the owner is ignored - even if one is
|
||||
// supplied) unless the URI is javascript or data or about:blank.
|
||||
// XXX: If this is ever changed, check all callers for what owners
|
||||
// they're passing in. In particular, see the code and
|
||||
// comments in nsDocShell::LoadURI where we fall back on
|
||||
// inheriting the owner if called from chrome. That would be
|
||||
// very wrong if this code changed anything but channels that
|
||||
// can't provide their own security context!
|
||||
//
|
||||
// (Currently chrome URIs set the owner when they are created!
|
||||
// So setting a NULL owner would be bad!)
|
||||
//
|
||||
PRBool inherit;
|
||||
// We expect URIInheritsSecurityContext to return success for an
|
||||
// about:blank URI, so don't call NS_IsAboutBlank() if this call fails.
|
||||
// This condition needs to match the one in nsDocShell::InternalLoad where
|
||||
// we're checking for things that will use the owner.
|
||||
if (NS_SUCCEEDED(URIInheritsSecurityContext(aURI, &inherit)) &&
|
||||
(inherit || (aSetUpForAboutBlank && NS_IsAboutBlank(aURI)))) {
|
||||
aChannel->SetOwner(aLoadingPrincipal);
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// file: uri special-casing
|
||||
//
|
||||
// If this is a file: load opened from another file: then it may need
|
||||
// to inherit the owner from the referrer so they can script each other.
|
||||
// If we don't set the owner explicitly then each file: gets an owner
|
||||
// based on its own codebase later.
|
||||
//
|
||||
if (URIIsLocalFile(aURI) && aLoadingPrincipal &&
|
||||
NS_SUCCEEDED(aLoadingPrincipal->CheckMayLoad(aURI, PR_FALSE)) &&
|
||||
// One more check here. CheckMayLoad will always return true for the
|
||||
// system principal, but we do NOT want to inherit in that case.
|
||||
!IsSystemPrincipal(aLoadingPrincipal)) {
|
||||
aChannel->SetOwner(aLoadingPrincipal);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsContentUtils::IsFullScreenApiEnabled()
|
||||
{
|
||||
|
@ -1130,23 +1130,6 @@ nsObjectLoadingContent::LoadObject(const nsAString& aURI,
|
||||
return LoadObject(uri, aNotify, aTypeHint, aForceLoad);
|
||||
}
|
||||
|
||||
static PRBool
|
||||
IsAboutBlank(nsIURI* aURI)
|
||||
{
|
||||
// XXXbz this duplicates an nsDocShell function, sadly
|
||||
NS_PRECONDITION(aURI, "Must have URI");
|
||||
|
||||
// GetSpec can be expensive for some URIs, so check the scheme first.
|
||||
PRBool isAbout = PR_FALSE;
|
||||
if (NS_FAILED(aURI->SchemeIs("about", &isAbout)) || !isAbout) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsCAutoString str;
|
||||
aURI->GetSpec(str);
|
||||
return str.EqualsLiteral("about:blank");
|
||||
}
|
||||
|
||||
void
|
||||
nsObjectLoadingContent::UpdateFallbackState(nsIContent* aContent,
|
||||
AutoFallback& fallback,
|
||||
@ -1460,17 +1443,8 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI,
|
||||
}
|
||||
|
||||
// Set up the channel's principal and such, like nsDocShell::DoURILoad does
|
||||
PRBool inheritPrincipal;
|
||||
rv = NS_URIChainHasFlags(aURI,
|
||||
nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
|
||||
&inheritPrincipal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (inheritPrincipal || IsAboutBlank(aURI) ||
|
||||
(nsContentUtils::URIIsLocalFile(aURI) &&
|
||||
NS_SUCCEEDED(thisContent->NodePrincipal()->CheckMayLoad(aURI,
|
||||
PR_FALSE)))) {
|
||||
chan->SetOwner(thisContent->NodePrincipal());
|
||||
}
|
||||
nsContentUtils::SetUpChannelOwner(thisContent->NodePrincipal(),
|
||||
chan, aURI, PR_TRUE);
|
||||
|
||||
nsCOMPtr<nsIScriptChannel> scriptChannel = do_QueryInterface(chan);
|
||||
if (scriptChannel) {
|
||||
|
@ -105,5 +105,13 @@ def web_socket_transfer_data(request):
|
||||
test37reason = request.ws_close_reason
|
||||
elif request.ws_protocol == "test-37c":
|
||||
request.ws_stream.close_connection(test37code, test37reason)
|
||||
elif request.ws_protocol == "test-42":
|
||||
# Echo back 3 messages
|
||||
msgutil.send_message(request,
|
||||
msgutil.receive_message(request))
|
||||
msgutil.send_message(request,
|
||||
msgutil.receive_message(request))
|
||||
msgutil.send_message(request,
|
||||
msgutil.receive_message(request))
|
||||
while not request.client_terminated:
|
||||
msgutil.receive_message(request)
|
||||
|
@ -62,10 +62,12 @@
|
||||
* 38. ensure extensions attribute is defined
|
||||
* 39. a basic wss:// connectivity test
|
||||
* 40. negative test for wss:// with no cert
|
||||
* 41. HSTS
|
||||
* 42. non-char utf-8 sequences
|
||||
*/
|
||||
|
||||
var first_test = 1;
|
||||
var last_test = 40;
|
||||
var last_test = 42;
|
||||
|
||||
var current_test = first_test;
|
||||
|
||||
@ -1067,7 +1069,7 @@ function test38()
|
||||
{
|
||||
ok(true, "test 38 open");
|
||||
ok(ws.extensions != undefined, "extensions attribute defined");
|
||||
ok(ws.extensions == "deflate-stream", "extensions attribute deflate-stream");
|
||||
// ok(ws.extensions == "deflate-stream", "extensions attribute deflate-stream");
|
||||
ws.close();
|
||||
};
|
||||
|
||||
@ -1123,6 +1125,44 @@ function test40()
|
||||
};
|
||||
}
|
||||
|
||||
function test41()
|
||||
{
|
||||
// reserve test41 for HSTS - bug 664284
|
||||
doTest(42);
|
||||
}
|
||||
|
||||
function test42()
|
||||
{
|
||||
// test some utf-8 non-characters. They should be allowed in the
|
||||
// websockets context. Test via round trip echo.
|
||||
var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-42");
|
||||
var data = ["U+FFFE ",
|
||||
"U+FFFF ",
|
||||
"U+10FFFF "];
|
||||
var index = 0;
|
||||
|
||||
ws.onopen = function()
|
||||
{
|
||||
ws.send(data[0]);
|
||||
ws.send(data[1]);
|
||||
ws.send(data[2]);
|
||||
}
|
||||
|
||||
ws.onmessage = function(e)
|
||||
{
|
||||
ok(e.data == data[index], "bad received message in test-42! index="+index);
|
||||
index++;
|
||||
if (index == 3)
|
||||
ws.close();
|
||||
}
|
||||
|
||||
ws.onclose = function(e)
|
||||
{
|
||||
doTest(43);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var ranAllTests = false;
|
||||
|
||||
function maybeFinished()
|
||||
|
@ -68,6 +68,8 @@ DoDrawImageSecurityCheck(nsHTMLCanvasElement *aCanvasElement,
|
||||
PRBool forceWriteOnly,
|
||||
PRBool CORSUsed)
|
||||
{
|
||||
NS_PRECONDITION(aPrincipal, "Must have a principal here");
|
||||
|
||||
// Callers should ensure that mCanvasElement is non-null before calling this
|
||||
if (!aCanvasElement) {
|
||||
NS_WARNING("DoDrawImageSecurityCheck called without canvas element!");
|
||||
@ -83,9 +85,6 @@ DoDrawImageSecurityCheck(nsHTMLCanvasElement *aCanvasElement,
|
||||
return;
|
||||
}
|
||||
|
||||
if (aPrincipal == nsnull)
|
||||
return;
|
||||
|
||||
// No need to do a security check if the image used CORS for the load
|
||||
if (CORSUsed)
|
||||
return;
|
||||
|
@ -68,6 +68,7 @@
|
||||
#include "prenv.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gl;
|
||||
@ -206,6 +207,7 @@ nsresult NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** aResult
|
||||
nsresult
|
||||
NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** aResult)
|
||||
{
|
||||
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1);
|
||||
nsIDOMWebGLRenderingContext* ctx = new WebGLContext();
|
||||
if (!ctx)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
@ -3604,9 +3604,7 @@ WebGLContext::DOMElementToImageSurface(nsIDOMElement *imageOrCanvas,
|
||||
|
||||
// part 1: check that the DOM element is same-origin, or has otherwise been
|
||||
// validated for cross-domain use.
|
||||
// if res.mPrincipal == null, no need for the origin check. See DoDrawImageSecurityCheck.
|
||||
// this case happens in the mochitest for images served from mochi.test:8888
|
||||
if (res.mPrincipal && !res.mCORSUsed) {
|
||||
if (!res.mCORSUsed) {
|
||||
PRBool subsumes;
|
||||
nsresult rv = HTMLCanvasElement()->NodePrincipal()->Subsumes(res.mPrincipal, &subsumes);
|
||||
if (NS_FAILED(rv) || !subsumes) {
|
||||
|
@ -1789,37 +1789,6 @@ nsGenericHTMLElement::MapCommonAttributesInto(const nsMappedAttributes* aAttribu
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsGenericHTMLFormElement::UpdateEditableFormControlState(PRBool aNotify)
|
||||
{
|
||||
// nsCSSFrameConstructor::MaybeConstructLazily is based on the logic of this
|
||||
// function, so should be kept in sync with that.
|
||||
|
||||
ContentEditableTristate value = GetContentEditableValue();
|
||||
if (value != eInherit) {
|
||||
DoSetEditableFlag(!!value, aNotify);
|
||||
return;
|
||||
}
|
||||
|
||||
nsIContent *parent = GetParent();
|
||||
|
||||
if (parent && parent->HasFlag(NODE_IS_EDITABLE)) {
|
||||
DoSetEditableFlag(PR_TRUE, aNotify);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsTextControl(PR_FALSE)) {
|
||||
DoSetEditableFlag(PR_FALSE, aNotify);
|
||||
return;
|
||||
}
|
||||
|
||||
// If not contentEditable we still need to check the readonly attribute.
|
||||
PRBool roState;
|
||||
GetBoolAttr(nsGkAtoms::readonly, &roState);
|
||||
|
||||
DoSetEditableFlag(!roState, aNotify);
|
||||
}
|
||||
|
||||
|
||||
/* static */ const nsGenericHTMLElement::MappedAttributeEntry
|
||||
nsGenericHTMLElement::sCommonAttributeMap[] = {
|
||||
@ -2912,6 +2881,18 @@ nsGenericHTMLFormElement::IntrinsicState() const
|
||||
state |= NS_EVENT_STATE_DEFAULT;
|
||||
}
|
||||
|
||||
// Make the text controls read-write
|
||||
if (!state.HasState(NS_EVENT_STATE_MOZ_READWRITE) &&
|
||||
IsTextControl(PR_FALSE)) {
|
||||
PRBool roState;
|
||||
GetBoolAttr(nsGkAtoms::readonly, &roState);
|
||||
|
||||
if (!roState) {
|
||||
state |= NS_EVENT_STATE_MOZ_READWRITE;
|
||||
state &= ~NS_EVENT_STATE_MOZ_READONLY;
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
|
@ -928,8 +928,6 @@ protected:
|
||||
virtual nsresult AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
const nsAString* aValue, PRBool aNotify);
|
||||
|
||||
void UpdateEditableFormControlState(PRBool aNotify);
|
||||
|
||||
/**
|
||||
* This method will update the form owner, using @form or looking to a parent.
|
||||
*
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsMathUtils.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
||||
#include "nsFrameManager.h"
|
||||
#include "nsDisplayList.h"
|
||||
@ -779,6 +780,7 @@ nsresult NS_NewCanvasRenderingContext2DAzure(nsIDOMCanvasRenderingContext2D** aR
|
||||
nsresult
|
||||
NS_NewCanvasRenderingContext2D(nsIDOMCanvasRenderingContext2D** aResult)
|
||||
{
|
||||
Telemetry::Accumulate(Telemetry::CANVAS_2D_USED, 1);
|
||||
if (Preferences::GetBool("gfx.canvas.azure.enabled", PR_FALSE)) {
|
||||
nsresult rv = NS_NewCanvasRenderingContext2DAzure(aResult);
|
||||
// If Azure fails, fall back to a classic canvas.
|
||||
|
@ -848,7 +848,6 @@ nsHTMLInputElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
UpdateTypeMismatchValidityState();
|
||||
}
|
||||
|
||||
UpdateEditableState(aNotify);
|
||||
UpdateState(aNotify);
|
||||
}
|
||||
|
||||
|
@ -235,11 +235,6 @@ public:
|
||||
|
||||
NS_IMETHOD FireAsyncClickHandler();
|
||||
|
||||
virtual void UpdateEditableState(PRBool aNotify)
|
||||
{
|
||||
return UpdateEditableFormControlState(aNotify);
|
||||
}
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHTMLInputElement,
|
||||
nsGenericHTMLFormElement)
|
||||
|
||||
|
@ -200,11 +200,6 @@ public:
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
|
||||
|
||||
virtual void UpdateEditableState(PRBool aNotify)
|
||||
{
|
||||
return UpdateEditableFormControlState(aNotify);
|
||||
}
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHTMLTextAreaElement,
|
||||
nsGenericHTMLFormElement)
|
||||
|
||||
@ -1267,9 +1262,6 @@ nsHTMLTextAreaElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
UpdateTooLongValidityState();
|
||||
}
|
||||
|
||||
if (aName == nsGkAtoms::readonly) {
|
||||
UpdateEditableState(aNotify);
|
||||
}
|
||||
UpdateState(aNotify);
|
||||
}
|
||||
|
||||
|
@ -1559,6 +1559,9 @@ nsTextEditorState::CreateRootNode()
|
||||
nsresult
|
||||
nsTextEditorState::InitializeRootNode()
|
||||
{
|
||||
// Make our root node editable
|
||||
mRootNode->SetFlags(NODE_IS_EDITABLE);
|
||||
|
||||
// Set the necessary classes on the text control. We use class values
|
||||
// instead of a 'style' attribute so that the style comes from a user-agent
|
||||
// style sheet and is still applied even if author styles are disabled.
|
||||
|
@ -8171,7 +8171,8 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
||||
// One more twist: Don't inherit the owner for external loads.
|
||||
if (aLoadType != LOAD_NORMAL_EXTERNAL && !owner &&
|
||||
(aFlags & INTERNAL_LOAD_FLAGS_INHERIT_OWNER) &&
|
||||
NS_SUCCEEDED(URIInheritsSecurityContext(aURI, &inherits)) &&
|
||||
NS_SUCCEEDED(nsContentUtils::URIInheritsSecurityContext(aURI,
|
||||
&inherits)) &&
|
||||
inherits) {
|
||||
|
||||
owner = GetInheritedPrincipal(PR_TRUE);
|
||||
@ -8182,11 +8183,13 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
||||
// if this document came from an unsafe channel.
|
||||
{
|
||||
PRBool willInherit;
|
||||
// This condition needs to match the one in DoChannelLoad.
|
||||
// This condition needs to match the one in
|
||||
// nsContentUtils::SetUpChannelOwner.
|
||||
// Except we reverse the rv check to be safe in case
|
||||
// URIInheritsSecurityContext fails here and succeeds there.
|
||||
rv = URIInheritsSecurityContext(aURI, &willInherit);
|
||||
if (NS_FAILED(rv) || willInherit || IsAboutBlank(aURI)) {
|
||||
// nsContentUtils::URIInheritsSecurityContext fails here and
|
||||
// succeeds there.
|
||||
rv = nsContentUtils::URIInheritsSecurityContext(aURI, &willInherit);
|
||||
if (NS_FAILED(rv) || willInherit || NS_IsAboutBlank(aURI)) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> treeItem = this;
|
||||
do {
|
||||
nsCOMPtr<nsIDocShell> itemDocShell =
|
||||
@ -9001,56 +9004,9 @@ nsDocShell::DoURILoad(nsIURI * aURI,
|
||||
httpChannel->SetReferrer(aReferrerURI);
|
||||
}
|
||||
}
|
||||
//
|
||||
// Set the owner of the channel, but only for channels that can't
|
||||
// provide their own security context.
|
||||
//
|
||||
// XXX: Is seems wrong that the owner is ignored - even if one is
|
||||
// supplied) unless the URI is javascript or data or about:blank.
|
||||
// XXX: If this is ever changed, check all callers for what owners they're
|
||||
// passing in. In particular, see the code and comments in LoadURI
|
||||
// where we fall back on inheriting the owner if called
|
||||
// from chrome. That would be very wrong if this code changed
|
||||
// anything but channels that can't provide their own security context!
|
||||
//
|
||||
// (Currently chrome URIs set the owner when they are created!
|
||||
// So setting a NULL owner would be bad!)
|
||||
//
|
||||
// If this code ever changes, change nsObjectLoadingContent::LoadObject
|
||||
// accordingly.
|
||||
PRBool inherit;
|
||||
// We expect URIInheritsSecurityContext to return success for an
|
||||
// about:blank URI, so don't call IsAboutBlank() if this call fails.
|
||||
// This condition needs to match the one in InternalLoad where
|
||||
// we're checking for things that will use the owner.
|
||||
rv = URIInheritsSecurityContext(aURI, &inherit);
|
||||
if (NS_SUCCEEDED(rv) && (inherit || IsAboutBlank(aURI))) {
|
||||
channel->SetOwner(aOwner);
|
||||
}
|
||||
|
||||
//
|
||||
// file: uri special-casing
|
||||
//
|
||||
// If this is a file: load opened from another file: then it may need
|
||||
// to inherit the owner from the referrer so they can script each other.
|
||||
// If we don't set the owner explicitly then each file: gets an owner
|
||||
// based on its own codebase later.
|
||||
//
|
||||
nsCOMPtr<nsIPrincipal> ownerPrincipal(do_QueryInterface(aOwner));
|
||||
if (URIIsLocalFile(aURI) && ownerPrincipal &&
|
||||
NS_SUCCEEDED(ownerPrincipal->CheckMayLoad(aURI, PR_FALSE))) {
|
||||
// One more check here. CheckMayLoad will always return true for the
|
||||
// system principal, but we do NOT want to inherit in that case.
|
||||
PRBool isSystem;
|
||||
nsCOMPtr<nsIScriptSecurityManager> secMan =
|
||||
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
|
||||
if (secMan &&
|
||||
NS_SUCCEEDED(secMan->IsSystemPrincipal(ownerPrincipal,
|
||||
&isSystem)) &&
|
||||
!isSystem) {
|
||||
channel->SetOwner(aOwner);
|
||||
}
|
||||
}
|
||||
nsContentUtils::SetUpChannelOwner(ownerPrincipal, channel, aURI, PR_TRUE);
|
||||
|
||||
nsCOMPtr<nsIScriptChannel> scriptChannel = do_QueryInterface(channel);
|
||||
if (scriptChannel) {
|
||||
@ -9452,7 +9408,7 @@ nsDocShell::OnNewURI(nsIURI * aURI, nsIChannel * aChannel, nsISupports* aOwner,
|
||||
shAvailable, updateHistory, equalUri));
|
||||
|
||||
if (shAvailable && mCurrentURI && !mOSHE && aLoadType != LOAD_ERROR_PAGE) {
|
||||
NS_ASSERTION(IsAboutBlank(mCurrentURI), "no SHEntry for a non-transient viewer?");
|
||||
NS_ASSERTION(NS_IsAboutBlank(mCurrentURI), "no SHEntry for a non-transient viewer?");
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -9743,7 +9699,7 @@ nsDocShell::AddState(nsIVariant *aData, const nsAString& aTitle,
|
||||
}
|
||||
|
||||
// 2c: Same-origin check.
|
||||
if (!URIIsLocalFile(newURI)) {
|
||||
if (!nsContentUtils::URIIsLocalFile(newURI)) {
|
||||
// In addition to checking that the security manager says that
|
||||
// the new URI has the same origin as our current URI, we also
|
||||
// check that the two URIs have the same userpass. (The
|
||||
@ -11251,47 +11207,6 @@ nsDocShell::GetIsContent(PRBool *aIsContent)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult
|
||||
nsDocShell::URIInheritsSecurityContext(nsIURI* aURI, PRBool* aResult)
|
||||
{
|
||||
// Note: about:blank URIs do NOT inherit the security context from the
|
||||
// current document, which is what this function tests for...
|
||||
return NS_URIChainHasFlags(aURI,
|
||||
nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
|
||||
aResult);
|
||||
}
|
||||
|
||||
/* static */
|
||||
PRBool
|
||||
nsDocShell::URIIsLocalFile(nsIURI *aURI)
|
||||
{
|
||||
PRBool isFile;
|
||||
nsCOMPtr<nsINetUtil> util = do_GetNetUtil();
|
||||
|
||||
return util && NS_SUCCEEDED(util->ProtocolHasFlags(aURI,
|
||||
nsIProtocolHandler::URI_IS_LOCAL_FILE,
|
||||
&isFile)) &&
|
||||
isFile;
|
||||
}
|
||||
|
||||
/* static */
|
||||
PRBool
|
||||
nsDocShell::IsAboutBlank(nsIURI* aURI)
|
||||
{
|
||||
NS_PRECONDITION(aURI, "Must have URI");
|
||||
|
||||
// GetSpec can be expensive for some URIs, so check the scheme first.
|
||||
PRBool isAbout = PR_FALSE;
|
||||
if (NS_FAILED(aURI->SchemeIs("about", &isAbout)) || !isAbout) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsCAutoString str;
|
||||
aURI->GetSpec(str);
|
||||
return str.EqualsLiteral("about:blank");
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDocShell::IsOKToLoadURI(nsIURI* aURI)
|
||||
{
|
||||
|
@ -650,15 +650,6 @@ protected:
|
||||
void DoGetPositionAndSize(PRInt32 * x, PRInt32 * y, PRInt32 * cx,
|
||||
PRInt32 * cy);
|
||||
|
||||
// Check whether aURI should inherit our security context
|
||||
static nsresult URIInheritsSecurityContext(nsIURI* aURI, PRBool* aResult);
|
||||
|
||||
// Check whether aURI is a URI_IS_LOCAL_FILE or not
|
||||
static PRBool URIIsLocalFile(nsIURI *aURI);
|
||||
|
||||
// Check whether aURI is about:blank
|
||||
static PRBool IsAboutBlank(nsIURI* aURI);
|
||||
|
||||
// Call this when a URI load is handed to us (via OnLinkClick or
|
||||
// InternalLoad). This makes sure that we're not inside unload, or that if
|
||||
// we are it's still OK to load this URI.
|
||||
|
@ -433,22 +433,6 @@ static const char kPkcs11ContractID[] = NS_PKCS11_CONTRACTID;
|
||||
#endif
|
||||
static const char sPopStatePrefStr[] = "browser.history.allowPopState";
|
||||
|
||||
static PRBool
|
||||
IsAboutBlank(nsIURI* aURI)
|
||||
{
|
||||
NS_PRECONDITION(aURI, "Must have URI");
|
||||
|
||||
// GetSpec can be expensive for some URIs, so check the scheme first.
|
||||
PRBool isAbout = PR_FALSE;
|
||||
if (NS_FAILED(aURI->SchemeIs("about", &isAbout)) || !isAbout) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsCAutoString str;
|
||||
aURI->GetSpec(str);
|
||||
return str.EqualsLiteral("about:blank");
|
||||
}
|
||||
|
||||
class nsDummyJavaPluginOwner : public nsIPluginInstanceOwner
|
||||
{
|
||||
public:
|
||||
@ -1615,7 +1599,7 @@ nsGlobalWindow::WouldReuseInnerWindow(nsIDocument *aNewDocument)
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
NS_ASSERTION(IsAboutBlank(mDoc->GetDocumentURI()),
|
||||
NS_ASSERTION(NS_IsAboutBlank(mDoc->GetDocumentURI()),
|
||||
"How'd this happen?");
|
||||
|
||||
// Great, we're the original document, check for one of the other
|
||||
@ -1664,8 +1648,8 @@ nsGlobalWindow::SetOpenerScriptPrincipal(nsIPrincipal* aPrincipal)
|
||||
// something is really weird.
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
mDoc->NodePrincipal()->GetURI(getter_AddRefs(uri));
|
||||
NS_ASSERTION(uri && IsAboutBlank(uri) &&
|
||||
IsAboutBlank(mDoc->GetDocumentURI()),
|
||||
NS_ASSERTION(uri && NS_IsAboutBlank(uri) &&
|
||||
NS_IsAboutBlank(mDoc->GetDocumentURI()),
|
||||
"Unexpected original document");
|
||||
#endif
|
||||
|
||||
@ -5013,7 +4997,7 @@ nsGlobalWindow::Focus()
|
||||
NS_ASSERTION(doc, "Bogus doc?");
|
||||
nsIURI* ourURI = doc->GetDocumentURI();
|
||||
if (ourURI) {
|
||||
lookForPresShell = !IsAboutBlank(ourURI);
|
||||
lookForPresShell = !NS_IsAboutBlank(ourURI);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2207,7 +2207,7 @@ class ThreadLocalJSRuntime
|
||||
JSObject* mGlobal;
|
||||
|
||||
static JSClass sGlobalClass;
|
||||
static const unsigned sRuntimeHeapSize = 64 * 1024; // should be enough for anyone
|
||||
static const unsigned sRuntimeHeapSize = 256 * 1024; // should be enough for anyone
|
||||
|
||||
ThreadLocalJSRuntime()
|
||||
: mRuntime(NULL), mContext(NULL), mGlobal(NULL)
|
||||
|
@ -382,7 +382,7 @@ struct ParamTraits<mozilla::plugins::NPRemoteWindow>
|
||||
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||
{
|
||||
uint64_t window;
|
||||
uint64 window;
|
||||
int32_t x, y;
|
||||
uint32_t width, height;
|
||||
NPRect clipRect;
|
||||
|
@ -36,7 +36,9 @@ function init3()
|
||||
rng.setEnd(textNode, 1);
|
||||
targetWindow.getSelection().addRange(rng);
|
||||
|
||||
targetDocument.execCommand("inserthtml", false, "<p>");
|
||||
try {
|
||||
targetDocument.execCommand("inserthtml", false, "<p>");
|
||||
} catch(e) {}
|
||||
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
|
@ -548,7 +548,7 @@ public:
|
||||
virtual PRBool IsContainer(nsIDOMNode *aNode);
|
||||
|
||||
/** returns PR_TRUE if aNode is an editable node */
|
||||
PRBool IsEditable(nsIDOMNode *aNode);
|
||||
virtual PRBool IsEditable(nsIDOMNode *aNode);
|
||||
|
||||
virtual PRBool IsTextInDirtyFrameVisible(nsIDOMNode *aNode);
|
||||
|
||||
|
@ -661,13 +661,8 @@ nsSelectAllCommand::IsCommandEnabled(const char * aCommandName,
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(outCmdEnabled);
|
||||
|
||||
// you can select all if there is an editor (and potentially no contents)
|
||||
// some day we may want to change this
|
||||
nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
|
||||
if (editor)
|
||||
return editor->GetIsSelectionEditable(outCmdEnabled);
|
||||
|
||||
*outCmdEnabled = PR_FALSE;
|
||||
// You can always select all!
|
||||
*outCmdEnabled = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -311,7 +311,9 @@ nsHTMLEditor::DoInsertHTMLWithContext(const nsAString & aInputString,
|
||||
// if caller didn't provide the destination/target node,
|
||||
// fetch the paste insertion point from our selection
|
||||
res = GetStartNodeAndOffset(selection, getter_AddRefs(targetNode), &targetOffset);
|
||||
if (!targetNode) res = NS_ERROR_FAILURE;
|
||||
if (!targetNode || !IsEditable(targetNode)) {
|
||||
res = NS_ERROR_FAILURE;
|
||||
}
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
}
|
||||
else
|
||||
|
@ -431,6 +431,12 @@ nsHTMLEditor::FindSelectionRoot(nsINode *aNode)
|
||||
}
|
||||
|
||||
if (!content->HasFlag(NODE_IS_EDITABLE)) {
|
||||
// If the content is in read-write state but is not editable itself,
|
||||
// return it as the selection root.
|
||||
if (content->IsElement() &&
|
||||
content->AsElement()->State().HasState(NS_EVENT_STATE_MOZ_READWRITE)) {
|
||||
return content.forget();
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
@ -6028,3 +6034,22 @@ nsHTMLEditor::GetPreferredIMEState(PRUint32 *aState)
|
||||
*aState = nsIContent::IME_STATUS_ENABLE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsHTMLEditor::IsEditable(nsIDOMNode* aNode) {
|
||||
if (!nsPlaintextEditor::IsEditable(aNode)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
|
||||
if (!node) {
|
||||
// If what we're dealing with is not a node, then it's not editable!
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (node->IsElement()) {
|
||||
// If we're dealing with an element, then ask it whether it's editable.
|
||||
return node->IsEditable();
|
||||
}
|
||||
// We might be dealing with a text node for example, which we always consider
|
||||
// to be editable.
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
@ -154,6 +154,7 @@ public:
|
||||
virtual already_AddRefed<nsIDOMEventTarget> GetDOMEventTarget();
|
||||
virtual already_AddRefed<nsIContent> FindSelectionRoot(nsINode *aNode);
|
||||
virtual PRBool IsAcceptableInputEvent(nsIDOMEvent* aEvent);
|
||||
virtual PRBool IsEditable(nsIDOMNode *aNode);
|
||||
|
||||
/* ------------ nsStubMutationObserver overrides --------- */
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
|
||||
|
@ -73,12 +73,14 @@ _TEST_FILES = \
|
||||
file_bug549262.html \
|
||||
test_bug550434.html \
|
||||
test_bug551704.html \
|
||||
test_bug552782.html \
|
||||
test_bug570144.html \
|
||||
test_bug592592.html \
|
||||
test_bug597784.html \
|
||||
test_bug599322.html \
|
||||
test_bug607584.html \
|
||||
test_bug611182.html \
|
||||
test_bug612128.html \
|
||||
test_bug612447.html \
|
||||
test_bug620906.html \
|
||||
test_bug622371.html \
|
||||
|
47
editor/libeditor/html/tests/test_bug552782.html
Normal file
47
editor/libeditor/html/tests/test_bug552782.html
Normal file
@ -0,0 +1,47 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=552782
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 552782</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.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=290026">Mozilla Bug 552782</a>
|
||||
<p id="display"></p>
|
||||
<div id="editor" contenteditable></div>
|
||||
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 552782 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var original = '<ol><li>Item 1</li><ol><li>Item 2</li><li>Item 3</li><li>Item 4</li></ol></ol>';
|
||||
var editor = document.getElementById("editor");
|
||||
editor.innerHTML = original;
|
||||
editor.focus();
|
||||
|
||||
addLoadEvent(function() {
|
||||
|
||||
var sel = window.getSelection();
|
||||
sel.removeAllRanges();
|
||||
var lis = document.getElementsByTagName("li");
|
||||
sel.selectAllChildren(lis[2]);
|
||||
document.execCommand("outdent", false, false);
|
||||
var expected = '<ol><li>Item 1</li><ol><li>Item 2</li></ol><li>Item 3</li><ol><li>Item 4</li></ol></ol>';
|
||||
is(editor.innerHTML, expected, "outdenting third item in a partially indented numbered list");
|
||||
document.execCommand("indent", false, false);
|
||||
todo_is(editor.innerHTML, original, "re-indenting third item in a partially indented numbered list");
|
||||
|
||||
// done
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
42
editor/libeditor/html/tests/test_bug612128.html
Normal file
42
editor/libeditor/html/tests/test_bug612128.html
Normal file
@ -0,0 +1,42 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=612128
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 612128</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.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=612128">Mozilla Bug 612128</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<input>
|
||||
<div contenteditable></div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 612128 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(function() {
|
||||
document.querySelector("input").focus();
|
||||
var threw = false;
|
||||
try {
|
||||
document.execCommand("inserthtml", null, "<span>f" + "oo</span>");
|
||||
} catch (e) {
|
||||
threw = true;
|
||||
}
|
||||
ok(threw, "The inserthtml command should fail");
|
||||
is(document.querySelectorAll("span").length, 0, "No span element should be injected inside the page");
|
||||
is(document.body.innerHTML.indexOf("f" + "oo"), -1, "No text should be injected inside the page");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -35,10 +35,17 @@ var gBlock1, gBlock2;
|
||||
function IsCommandEnabled(command) {
|
||||
var enabled;
|
||||
|
||||
var resultInNonEditableRegion = false;
|
||||
if (command == "selectAll") {
|
||||
// The select all command is sort of exceptional, as it needs to be enabled
|
||||
// everywhere.
|
||||
resultInNonEditableRegion = true;
|
||||
}
|
||||
|
||||
// non-editable div: should return false
|
||||
window.getSelection().selectAllChildren(gBlock1);
|
||||
enabled = document.queryCommandEnabled(command);
|
||||
is(enabled, false, "'" + command + "' should not be enabled on a non-editable block.");
|
||||
is(enabled, resultInNonEditableRegion, "'" + command + "' should not be enabled on a non-editable block.");
|
||||
|
||||
// editable div: should return true
|
||||
window.getSelection().selectAllChildren(gBlock2);
|
||||
|
@ -85,6 +85,12 @@ SurfaceDescriptorX11::SurfaceDescriptorX11(gfxXlibSurface* aSurf)
|
||||
, mFormat(aSurf->XRenderFormat()->id)
|
||||
{ }
|
||||
|
||||
SurfaceDescriptorX11::SurfaceDescriptorX11(const int aXid, const int aXrenderPictID, const gfxIntSize& aSize)
|
||||
: mId(aXid)
|
||||
, mSize(aSize)
|
||||
, mFormat(aXrenderPictID)
|
||||
{ }
|
||||
|
||||
already_AddRefed<gfxXlibSurface>
|
||||
SurfaceDescriptorX11::OpenForeign() const
|
||||
{
|
||||
|
@ -60,6 +60,8 @@ struct SurfaceDescriptorX11 {
|
||||
|
||||
SurfaceDescriptorX11(gfxXlibSurface* aSurf);
|
||||
|
||||
SurfaceDescriptorX11(const int aXid, const int aXrenderPictID, const gfxIntSize& aSize);
|
||||
|
||||
// Default copy ctor and operator= are OK
|
||||
|
||||
bool operator==(const SurfaceDescriptorX11& aOther) const {
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include <sys/int_types.h>
|
||||
#elif defined (_AIX)
|
||||
#include <sys/types.h>
|
||||
#elif !defined(ANDROID)
|
||||
#elif !defined(ANDROID) && !defined(__OpenBSD__)
|
||||
typedef PRInt8 int8_t;
|
||||
typedef PRUint8 uint8_t;
|
||||
typedef PRInt16 int16_t;
|
||||
|
@ -604,7 +604,7 @@ gfxXlibNativeRenderer::Draw(gfxContext* ctx, nsIntSize size,
|
||||
CopyXlibSurfaceToImage(tempXlibSurface, gfxASurface::ImageFormatRGB24);
|
||||
|
||||
if (blackImage->CairoStatus() == CAIRO_STATUS_SUCCESS &&
|
||||
blackImage->CairoStatus() == CAIRO_STATUS_SUCCESS) {
|
||||
whiteImage->CairoStatus() == CAIRO_STATUS_SUCCESS) {
|
||||
gfxAlphaRecovery::Analysis analysis;
|
||||
if (!gfxAlphaRecovery::RecoverAlpha(blackImage, whiteImage,
|
||||
result ? &analysis : nsnull))
|
||||
|
@ -15,6 +15,7 @@
|
||||
#elif defined(ANDROID)
|
||||
#include <sys/stat.h>
|
||||
#elif defined(OS_POSIX)
|
||||
#include <sys/types.h>
|
||||
#include <fts.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
@ -30,6 +30,11 @@
|
||||
#include "base/string_util.h"
|
||||
#include "base/time.h"
|
||||
|
||||
// FreeBSD/OpenBSD lacks stat64, but its stat handles files >2GB just fine
|
||||
#if defined(OS_FREEBSD) || defined(OS_OPENBSD)
|
||||
#define stat64 stat
|
||||
#endif
|
||||
|
||||
namespace file_util {
|
||||
|
||||
#if defined(GOOGLE_CHROME_BUILD)
|
||||
|
@ -33,6 +33,9 @@ PlatformThreadId PlatformThread::CurrentId() {
|
||||
// into the kernel.
|
||||
#if defined(OS_MACOSX)
|
||||
return mach_thread_self();
|
||||
#elif defined (__OpenBSD__)
|
||||
// TODO(BSD): find a better thread ID
|
||||
return (intptr_t)(pthread_self());
|
||||
#elif defined(OS_LINUX)
|
||||
return syscall(__NR_gettid);
|
||||
#endif
|
||||
|
@ -36,6 +36,8 @@
|
||||
#include "base/third_party/nspr/prcpucfg_mac.h"
|
||||
#elif defined(__linux__) || defined(ANDROID)
|
||||
#include "base/third_party/nspr/prcpucfg_linux.h"
|
||||
#elif defined(__OpenBSD__)
|
||||
#include "base/third_party/nspr/prcpucfg_openbsd.h"
|
||||
#else
|
||||
#error Provide a prcpucfg.h appropriate for your platform
|
||||
#endif
|
||||
|
437
ipc/chromium/src/base/third_party/nspr/prcpucfg_openbsd.h
vendored
Normal file
437
ipc/chromium/src/base/third_party/nspr/prcpucfg_openbsd.h
vendored
Normal file
@ -0,0 +1,437 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nspr_cpucfg___
|
||||
#define nspr_cpucfg___
|
||||
|
||||
#ifndef XP_UNIX
|
||||
#define XP_UNIX
|
||||
#endif
|
||||
|
||||
#ifndef OPENBSD
|
||||
#define OPENBSD
|
||||
#endif
|
||||
|
||||
#define PR_AF_INET6 24 /* same as AF_INET6 */
|
||||
|
||||
#ifndef HAVE_LONG_LONG
|
||||
#define HAVE_LONG_LONG
|
||||
#endif
|
||||
|
||||
#if defined(__i386__) || defined(__arm__)
|
||||
|
||||
#define IS_LITTLE_ENDIAN 1
|
||||
#undef IS_BIG_ENDIAN
|
||||
#undef HAVE_ALIGNED_DOUBLES
|
||||
#undef HAVE_ALIGNED_LONGLONGS
|
||||
|
||||
#define PR_BYTES_PER_BYTE 1
|
||||
#define PR_BYTES_PER_SHORT 2
|
||||
#define PR_BYTES_PER_INT 4
|
||||
#define PR_BYTES_PER_INT64 8
|
||||
#define PR_BYTES_PER_LONG 4
|
||||
#define PR_BYTES_PER_FLOAT 4
|
||||
#define PR_BYTES_PER_DOUBLE 8
|
||||
#define PR_BYTES_PER_WORD 4
|
||||
#define PR_BYTES_PER_DWORD 8
|
||||
#define PR_BYTES_PER_WORD_LOG2 2
|
||||
#define PR_BYTES_PER_DWORD_LOG2 3
|
||||
|
||||
#define PR_BITS_PER_BYTE 8
|
||||
#define PR_BITS_PER_SHORT 16
|
||||
#define PR_BITS_PER_INT 32
|
||||
#define PR_BITS_PER_INT64 64
|
||||
#define PR_BITS_PER_LONG 32
|
||||
#define PR_BITS_PER_FLOAT 32
|
||||
#define PR_BITS_PER_DOUBLE 64
|
||||
#define PR_BITS_PER_WORD 32
|
||||
|
||||
#define PR_BITS_PER_BYTE_LOG2 3
|
||||
#define PR_BITS_PER_SHORT_LOG2 4
|
||||
#define PR_BITS_PER_INT_LOG2 5
|
||||
#define PR_BITS_PER_INT64_LOG2 6
|
||||
#define PR_BITS_PER_LONG_LOG2 5
|
||||
#define PR_BITS_PER_FLOAT_LOG2 5
|
||||
#define PR_BITS_PER_DOUBLE_LOG2 6
|
||||
#define PR_BITS_PER_WORD_LOG2 5
|
||||
|
||||
#define PR_ALIGN_OF_SHORT 2
|
||||
#define PR_ALIGN_OF_INT 4
|
||||
#define PR_ALIGN_OF_LONG 4
|
||||
#define PR_ALIGN_OF_INT64 4
|
||||
#define PR_ALIGN_OF_FLOAT 4
|
||||
#define PR_ALIGN_OF_DOUBLE 4
|
||||
#define PR_ALIGN_OF_POINTER 4
|
||||
|
||||
#elif defined(__amd64__)
|
||||
|
||||
#define IS_LITTLE_ENDIAN 1
|
||||
#undef IS_BIG_ENDIAN
|
||||
#define IS_64
|
||||
|
||||
#define PR_BYTES_PER_BYTE 1
|
||||
#define PR_BYTES_PER_SHORT 2
|
||||
#define PR_BYTES_PER_INT 4
|
||||
#define PR_BYTES_PER_INT64 8
|
||||
#define PR_BYTES_PER_LONG 8
|
||||
#define PR_BYTES_PER_FLOAT 4
|
||||
#define PR_BYTES_PER_DOUBLE 8
|
||||
#define PR_BYTES_PER_WORD 8
|
||||
#define PR_BYTES_PER_DWORD 8
|
||||
|
||||
#define PR_BITS_PER_BYTE 8
|
||||
#define PR_BITS_PER_SHORT 16
|
||||
#define PR_BITS_PER_INT 32
|
||||
#define PR_BITS_PER_INT64 64
|
||||
#define PR_BITS_PER_LONG 64
|
||||
#define PR_BITS_PER_FLOAT 32
|
||||
#define PR_BITS_PER_DOUBLE 64
|
||||
#define PR_BITS_PER_WORD 64
|
||||
|
||||
#define PR_BITS_PER_BYTE_LOG2 3
|
||||
#define PR_BITS_PER_SHORT_LOG2 4
|
||||
#define PR_BITS_PER_INT_LOG2 5
|
||||
#define PR_BITS_PER_INT64_LOG2 6
|
||||
#define PR_BITS_PER_LONG_LOG2 6
|
||||
#define PR_BITS_PER_FLOAT_LOG2 5
|
||||
#define PR_BITS_PER_DOUBLE_LOG2 6
|
||||
#define PR_BITS_PER_WORD_LOG2 6
|
||||
|
||||
#define PR_ALIGN_OF_SHORT 2
|
||||
#define PR_ALIGN_OF_INT 4
|
||||
#define PR_ALIGN_OF_LONG 8
|
||||
#define PR_ALIGN_OF_INT64 8
|
||||
#define PR_ALIGN_OF_FLOAT 4
|
||||
#define PR_ALIGN_OF_DOUBLE 8
|
||||
#define PR_ALIGN_OF_POINTER 8
|
||||
#define PR_ALIGN_OF_WORD 8
|
||||
|
||||
#define PR_BYTES_PER_WORD_LOG2 3
|
||||
#define PR_BYTES_PER_DWORD_LOG2 3
|
||||
|
||||
#define HAVE_ALIGNED_DOUBLES
|
||||
#define HAVE_ALIGNED_LONGLONGS
|
||||
|
||||
#elif defined(__sparc_v9__)
|
||||
|
||||
#undef IS_LITTLE_ENDIAN
|
||||
#define IS_BIG_ENDIAN 1
|
||||
#define HAVE_ALIGNED_DOUBLES
|
||||
#define HAVE_ALIGNED_LONGLONGS
|
||||
#define IS_64
|
||||
|
||||
#define PR_BYTES_PER_BYTE 1
|
||||
#define PR_BYTES_PER_SHORT 2
|
||||
#define PR_BYTES_PER_INT 4
|
||||
#define PR_BYTES_PER_INT64 8
|
||||
#define PR_BYTES_PER_LONG 8
|
||||
#define PR_BYTES_PER_FLOAT 4
|
||||
#define PR_BYTES_PER_DOUBLE 8
|
||||
#define PR_BYTES_PER_WORD 8
|
||||
#define PR_BYTES_PER_DWORD 8
|
||||
|
||||
#define PR_BITS_PER_BYTE 8
|
||||
#define PR_BITS_PER_SHORT 16
|
||||
#define PR_BITS_PER_INT 32
|
||||
#define PR_BITS_PER_INT64 64
|
||||
#define PR_BITS_PER_LONG 64
|
||||
#define PR_BITS_PER_FLOAT 32
|
||||
#define PR_BITS_PER_DOUBLE 64
|
||||
#define PR_BITS_PER_WORD 64
|
||||
|
||||
#define PR_BITS_PER_BYTE_LOG2 3
|
||||
#define PR_BITS_PER_SHORT_LOG2 4
|
||||
#define PR_BITS_PER_INT_LOG2 5
|
||||
#define PR_BITS_PER_INT64_LOG2 6
|
||||
#define PR_BITS_PER_LONG_LOG2 6
|
||||
#define PR_BITS_PER_FLOAT_LOG2 5
|
||||
#define PR_BITS_PER_DOUBLE_LOG2 6
|
||||
#define PR_BITS_PER_WORD_LOG2 6
|
||||
|
||||
#define PR_ALIGN_OF_SHORT 2
|
||||
#define PR_ALIGN_OF_INT 4
|
||||
#define PR_ALIGN_OF_LONG 8
|
||||
#define PR_ALIGN_OF_INT64 8
|
||||
#define PR_ALIGN_OF_FLOAT 4
|
||||
#define PR_ALIGN_OF_DOUBLE 8
|
||||
#define PR_ALIGN_OF_POINTER 8
|
||||
|
||||
#define PR_BYTES_PER_WORD_LOG2 3
|
||||
#define PR_BYTES_PER_DWORD_LOG2 3
|
||||
|
||||
#elif defined(__sparc__) || defined(__hppa__)
|
||||
|
||||
#undef IS_LITTLE_ENDIAN
|
||||
#define IS_BIG_ENDIAN 1
|
||||
#define HAVE_ALIGNED_DOUBLES
|
||||
#define HAVE_ALIGNED_LONGLONGS
|
||||
|
||||
#define PR_BYTES_PER_BYTE 1
|
||||
#define PR_BYTES_PER_SHORT 2
|
||||
#define PR_BYTES_PER_INT 4
|
||||
#define PR_BYTES_PER_INT64 8
|
||||
#define PR_BYTES_PER_LONG 4
|
||||
#define PR_BYTES_PER_FLOAT 4
|
||||
#define PR_BYTES_PER_DOUBLE 8
|
||||
#define PR_BYTES_PER_WORD 4
|
||||
#define PR_BYTES_PER_DWORD 8
|
||||
#define PR_BYTES_PER_WORD_LOG2 2
|
||||
#define PR_BYTES_PER_DWORD_LOG2 3
|
||||
|
||||
#define PR_BITS_PER_BYTE 8
|
||||
#define PR_BITS_PER_SHORT 16
|
||||
#define PR_BITS_PER_INT 32
|
||||
#define PR_BITS_PER_INT64 64
|
||||
#define PR_BITS_PER_LONG 32
|
||||
#define PR_BITS_PER_FLOAT 32
|
||||
#define PR_BITS_PER_DOUBLE 64
|
||||
#define PR_BITS_PER_WORD 32
|
||||
|
||||
#define PR_BITS_PER_BYTE_LOG2 3
|
||||
#define PR_BITS_PER_SHORT_LOG2 4
|
||||
#define PR_BITS_PER_INT_LOG2 5
|
||||
#define PR_BITS_PER_INT64_LOG2 6
|
||||
#define PR_BITS_PER_LONG_LOG2 5
|
||||
#define PR_BITS_PER_FLOAT_LOG2 5
|
||||
#define PR_BITS_PER_DOUBLE_LOG2 6
|
||||
#define PR_BITS_PER_WORD_LOG2 5
|
||||
|
||||
#define PR_ALIGN_OF_SHORT 2
|
||||
#define PR_ALIGN_OF_INT 4
|
||||
#define PR_ALIGN_OF_LONG 4
|
||||
#define PR_ALIGN_OF_INT64 8
|
||||
#define PR_ALIGN_OF_FLOAT 4
|
||||
#define PR_ALIGN_OF_DOUBLE 8
|
||||
#define PR_ALIGN_OF_POINTER 4
|
||||
|
||||
#elif defined(__alpha__)
|
||||
#define IS_LITTLE_ENDIAN 1
|
||||
#undef IS_BIG_ENDIAN
|
||||
#define HAVE_ALIGNED_DOUBLES
|
||||
#define HAVE_ALIGNED_LONGLONGS
|
||||
#define IS_64
|
||||
|
||||
#define PR_BYTES_PER_BYTE 1
|
||||
#define PR_BYTES_PER_SHORT 2
|
||||
#define PR_BYTES_PER_INT 4
|
||||
#define PR_BYTES_PER_INT64 8
|
||||
#define PR_BYTES_PER_LONG 8
|
||||
#define PR_BYTES_PER_FLOAT 4
|
||||
#define PR_BYTES_PER_DOUBLE 8
|
||||
#define PR_BYTES_PER_WORD 8
|
||||
#define PR_BYTES_PER_DWORD 8
|
||||
|
||||
#define PR_BITS_PER_BYTE 8
|
||||
#define PR_BITS_PER_SHORT 16
|
||||
#define PR_BITS_PER_INT 32
|
||||
#define PR_BITS_PER_INT64 64
|
||||
#define PR_BITS_PER_LONG 64
|
||||
#define PR_BITS_PER_FLOAT 32
|
||||
#define PR_BITS_PER_DOUBLE 64
|
||||
#define PR_BITS_PER_WORD 64
|
||||
|
||||
#define PR_BITS_PER_BYTE_LOG2 3
|
||||
#define PR_BITS_PER_SHORT_LOG2 4
|
||||
#define PR_BITS_PER_INT_LOG2 5
|
||||
#define PR_BITS_PER_INT64_LOG2 6
|
||||
#define PR_BITS_PER_LONG_LOG2 6
|
||||
#define PR_BITS_PER_FLOAT_LOG2 5
|
||||
#define PR_BITS_PER_DOUBLE_LOG2 6
|
||||
#define PR_BITS_PER_WORD_LOG2 6
|
||||
|
||||
#define PR_ALIGN_OF_SHORT 2
|
||||
#define PR_ALIGN_OF_INT 4
|
||||
#define PR_ALIGN_OF_LONG 8
|
||||
#define PR_ALIGN_OF_INT64 8
|
||||
#define PR_ALIGN_OF_FLOAT 4
|
||||
#define PR_ALIGN_OF_DOUBLE 8
|
||||
#define PR_ALIGN_OF_POINTER 8
|
||||
|
||||
#define PR_BYTES_PER_WORD_LOG2 3
|
||||
#define PR_BYTES_PER_DWORD_LOG2 3
|
||||
|
||||
#elif defined(__powerpc__) || defined(__m68k__)
|
||||
|
||||
#undef IS_LITTLE_ENDIAN
|
||||
#define IS_BIG_ENDIAN 1
|
||||
#undef HAVE_ALIGNED_DOUBLES
|
||||
#undef HAVE_ALIGNED_LONGLONGS
|
||||
|
||||
#define PR_BYTES_PER_BYTE 1
|
||||
#define PR_BYTES_PER_SHORT 2
|
||||
#define PR_BYTES_PER_INT 4
|
||||
#define PR_BYTES_PER_INT64 8
|
||||
#define PR_BYTES_PER_LONG 4
|
||||
#define PR_BYTES_PER_FLOAT 4
|
||||
#define PR_BYTES_PER_DOUBLE 8
|
||||
#define PR_BYTES_PER_WORD 4
|
||||
#define PR_BYTES_PER_DWORD 8
|
||||
|
||||
#define PR_BITS_PER_BYTE 8
|
||||
#define PR_BITS_PER_SHORT 16
|
||||
#define PR_BITS_PER_INT 32
|
||||
#define PR_BITS_PER_INT64 64
|
||||
#define PR_BITS_PER_LONG 32
|
||||
#define PR_BITS_PER_FLOAT 32
|
||||
#define PR_BITS_PER_DOUBLE 64
|
||||
#define PR_BITS_PER_WORD 32
|
||||
|
||||
#define PR_BITS_PER_BYTE_LOG2 3
|
||||
#define PR_BITS_PER_SHORT_LOG2 4
|
||||
#define PR_BITS_PER_INT_LOG2 5
|
||||
#define PR_BITS_PER_INT64_LOG2 6
|
||||
#define PR_BITS_PER_LONG_LOG2 5
|
||||
#define PR_BITS_PER_FLOAT_LOG2 5
|
||||
#define PR_BITS_PER_DOUBLE_LOG2 6
|
||||
#define PR_BITS_PER_WORD_LOG2 5
|
||||
|
||||
#define PR_ALIGN_OF_SHORT 2
|
||||
#define PR_ALIGN_OF_INT 4
|
||||
#define PR_ALIGN_OF_LONG 4
|
||||
#define PR_ALIGN_OF_INT64 4
|
||||
#define PR_ALIGN_OF_FLOAT 4
|
||||
#define PR_ALIGN_OF_DOUBLE 4
|
||||
#define PR_ALIGN_OF_POINTER 4
|
||||
|
||||
#define PR_BYTES_PER_WORD_LOG2 2
|
||||
#define PR_BYTES_PER_DWORD_LOG2 3
|
||||
|
||||
#elif defined(__mips__)
|
||||
|
||||
#ifdef __MIPSEB__
|
||||
#define IS_BIG_ENDIAN 1
|
||||
#undef IS_LITTLE_ENDIAN
|
||||
#elif defined(__MIPSEL__)
|
||||
#define IS_LITTLE_ENDIAN 1
|
||||
#undef IS_BIG_ENDIAN
|
||||
#else
|
||||
#error "Unknown MIPS endianness."
|
||||
#endif
|
||||
|
||||
#define PR_BYTES_PER_BYTE 1
|
||||
#define PR_BYTES_PER_SHORT 2
|
||||
#define PR_BYTES_PER_INT 4
|
||||
#define PR_BYTES_PER_INT64 8
|
||||
#define PR_BYTES_PER_LONG 8
|
||||
#define PR_BYTES_PER_FLOAT 4
|
||||
#define PR_BYTES_PER_DOUBLE 8
|
||||
#define PR_BYTES_PER_WORD 4
|
||||
#define PR_BYTES_PER_DWORD 8
|
||||
|
||||
#define PR_BITS_PER_BYTE 8
|
||||
#define PR_BITS_PER_SHORT 16
|
||||
#define PR_BITS_PER_INT 32
|
||||
#define PR_BITS_PER_INT64 64
|
||||
#define PR_BITS_PER_LONG 64
|
||||
#define PR_BITS_PER_FLOAT 32
|
||||
#define PR_BITS_PER_DOUBLE 64
|
||||
#define PR_BITS_PER_WORD 64
|
||||
|
||||
#define PR_BITS_PER_BYTE_LOG2 3
|
||||
#define PR_BITS_PER_SHORT_LOG2 4
|
||||
#define PR_BITS_PER_INT_LOG2 5
|
||||
#define PR_BITS_PER_INT64_LOG2 6
|
||||
#define PR_BITS_PER_LONG_LOG2 5
|
||||
#define PR_BITS_PER_FLOAT_LOG2 5
|
||||
#define PR_BITS_PER_DOUBLE_LOG2 6
|
||||
#define PR_BITS_PER_WORD_LOG2 5
|
||||
|
||||
#define PR_ALIGN_OF_SHORT 2
|
||||
#define PR_ALIGN_OF_INT 4
|
||||
#define PR_ALIGN_OF_LONG 4
|
||||
#define PR_ALIGN_OF_INT64 8
|
||||
#define PR_ALIGN_OF_FLOAT 4
|
||||
#define PR_ALIGN_OF_DOUBLE 8
|
||||
#define PR_ALIGN_OF_POINTER 4
|
||||
#define PR_ALIGN_OF_WORD 4
|
||||
|
||||
#define PR_BYTES_PER_WORD_LOG2 2
|
||||
#define PR_BYTES_PER_DWORD_LOG2 3
|
||||
|
||||
#else
|
||||
|
||||
#error Must define constants for type sizes here.
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef NO_NSPR_10_SUPPORT
|
||||
|
||||
#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
|
||||
#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
|
||||
#define BYTES_PER_INT PR_BYTES_PER_INT
|
||||
#define BYTES_PER_INT64 PR_BYTES_PER_INT64
|
||||
#define BYTES_PER_LONG PR_BYTES_PER_LONG
|
||||
#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
|
||||
#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
|
||||
#define BYTES_PER_WORD PR_BYTES_PER_WORD
|
||||
#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
|
||||
|
||||
#define BITS_PER_BYTE PR_BITS_PER_BYTE
|
||||
#define BITS_PER_SHORT PR_BITS_PER_SHORT
|
||||
#define BITS_PER_INT PR_BITS_PER_INT
|
||||
#define BITS_PER_INT64 PR_BITS_PER_INT64
|
||||
#define BITS_PER_LONG PR_BITS_PER_LONG
|
||||
#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
|
||||
#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
|
||||
#define BITS_PER_WORD PR_BITS_PER_WORD
|
||||
|
||||
#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
|
||||
#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
|
||||
#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
|
||||
#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
|
||||
#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
|
||||
#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
|
||||
#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
|
||||
#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
|
||||
|
||||
#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
|
||||
#define ALIGN_OF_INT PR_ALIGN_OF_INT
|
||||
#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
|
||||
#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
|
||||
#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
|
||||
#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
|
||||
#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
|
||||
#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
|
||||
|
||||
#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
|
||||
#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
|
||||
#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
|
||||
|
||||
#endif /* NO_NSPR_10_SUPPORT */
|
||||
|
||||
#endif /* nspr_cpucfg___ */
|
@ -164,7 +164,7 @@ TimeTicks TimeTicks::Now() {
|
||||
// With numer and denom = 1 (the expected case), the 64-bit absolute time
|
||||
// reported in nanoseconds is enough to last nearly 585 years.
|
||||
|
||||
#elif defined(OS_POSIX) && \
|
||||
#elif defined(__OpenBSD__) || defined(OS_POSIX) && \
|
||||
defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0
|
||||
|
||||
struct timespec ts;
|
||||
|
@ -19,6 +19,8 @@
|
||||
#define OS_MACOSX 1
|
||||
#elif defined(__linux__) || defined(ANDROID)
|
||||
#define OS_LINUX 1
|
||||
#elif defined(__OpenBSD__)
|
||||
#define OS_OPENBSD 1
|
||||
#elif defined(_WIN32)
|
||||
#define OS_WIN 1
|
||||
#else
|
||||
@ -27,7 +29,7 @@
|
||||
|
||||
// For access to standard POSIX features, use OS_POSIX instead of a more
|
||||
// specific macro.
|
||||
#if defined(OS_MACOSX) || defined(OS_LINUX)
|
||||
#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_OPENBSD)
|
||||
#define OS_POSIX 1
|
||||
#endif
|
||||
|
||||
@ -60,6 +62,9 @@
|
||||
#elif defined(__ppc__) || defined(__powerpc__)
|
||||
#define ARCH_CPU_PPC 1
|
||||
#define ARCH_CPU_32_BITS 1
|
||||
#elif defined(__sparc64__)
|
||||
#define ARCH_CPU_SPARC 1
|
||||
#define ARCH_CPU_64_BITS 1
|
||||
#else
|
||||
#error Please add support for your architecture in build/build_config.h
|
||||
#endif
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
70001
js/src/jit-test/tests/basic/bug674776.js
Normal file
70001
js/src/jit-test/tests/basic/bug674776.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -58,7 +58,7 @@ BEGIN_TEST(testGCOutOfMemory)
|
||||
}
|
||||
|
||||
virtual JSRuntime * createRuntime() {
|
||||
return JS_NewRuntime(256 * 1024);
|
||||
return JS_NewRuntime(512 * 1024);
|
||||
}
|
||||
|
||||
virtual void destroyRuntime() {
|
||||
|
@ -56,7 +56,7 @@ BEGIN_TEST(testIndexToString)
|
||||
JSString *str = js::IndexToString(cx, u);
|
||||
CHECK(str);
|
||||
|
||||
if (!JSAtom::hasUintStatic(u))
|
||||
if (!js::StaticStrings::hasUint(u))
|
||||
CHECK(cx->compartment->dtoaCache.lookup(10, u) == str);
|
||||
|
||||
JSBool match = JS_FALSE;
|
||||
|
@ -11,28 +11,28 @@ BEGIN_TEST(testIntString_bug515273)
|
||||
|
||||
EVAL("'1';", v.addr());
|
||||
JSString *str = JSVAL_TO_STRING(v.value());
|
||||
CHECK(str->isStaticAtom());
|
||||
CHECK(JS_StringHasBeenInterned(cx, str));
|
||||
CHECK(JS_FlatStringEqualsAscii(JS_ASSERT_STRING_IS_FLAT(str), "1"));
|
||||
|
||||
EVAL("'42';", v.addr());
|
||||
str = JSVAL_TO_STRING(v.value());
|
||||
CHECK(str->isStaticAtom());
|
||||
CHECK(JS_StringHasBeenInterned(cx, str));
|
||||
CHECK(JS_FlatStringEqualsAscii(JS_ASSERT_STRING_IS_FLAT(str), "42"));
|
||||
|
||||
EVAL("'111';", v.addr());
|
||||
str = JSVAL_TO_STRING(v.value());
|
||||
CHECK(str->isStaticAtom());
|
||||
CHECK(JS_StringHasBeenInterned(cx, str));
|
||||
CHECK(JS_FlatStringEqualsAscii(JS_ASSERT_STRING_IS_FLAT(str), "111"));
|
||||
|
||||
/* Test other types of static strings. */
|
||||
EVAL("'a';", v.addr());
|
||||
str = JSVAL_TO_STRING(v.value());
|
||||
CHECK(str->isStaticAtom());
|
||||
CHECK(JS_StringHasBeenInterned(cx, str));
|
||||
CHECK(JS_FlatStringEqualsAscii(JS_ASSERT_STRING_IS_FLAT(str), "a"));
|
||||
|
||||
EVAL("'bc';", v.addr());
|
||||
str = JSVAL_TO_STRING(v.value());
|
||||
CHECK(str->isStaticAtom());
|
||||
CHECK(JS_StringHasBeenInterned(cx, str));
|
||||
CHECK(JS_FlatStringEqualsAscii(JS_ASSERT_STRING_IS_FLAT(str), "bc"));
|
||||
|
||||
return true;
|
||||
|
@ -423,7 +423,7 @@ js_SweepAtomState(JSContext *cx)
|
||||
JS_ASSERT(!IsAboutToBeFinalized(cx, entry.asPtr()));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (IsAboutToBeFinalized(cx, entry.asPtr()))
|
||||
e.removeFront();
|
||||
}
|
||||
@ -432,7 +432,8 @@ js_SweepAtomState(JSContext *cx)
|
||||
bool
|
||||
AtomIsInterned(JSContext *cx, JSAtom *atom)
|
||||
{
|
||||
if (atom->isStaticAtom())
|
||||
/* We treat static strings as interned because they're never collected. */
|
||||
if (StaticStrings::isStatic(atom))
|
||||
return true;
|
||||
|
||||
AutoLockAtomsCompartment lock(cx);
|
||||
@ -461,7 +462,7 @@ AtomizeInline(JSContext *cx, const jschar **pchars, size_t length,
|
||||
{
|
||||
const jschar *chars = *pchars;
|
||||
|
||||
if (JSAtom *s = JSAtom::lookupStatic(chars, length))
|
||||
if (JSAtom *s = cx->runtime->staticStrings.lookup(chars, length))
|
||||
return s;
|
||||
|
||||
AutoLockAtomsCompartment lock(cx);
|
||||
@ -521,7 +522,7 @@ js_AtomizeString(JSContext *cx, JSString *str, InternBehavior ib)
|
||||
if (str->isAtom()) {
|
||||
JSAtom &atom = str->asAtom();
|
||||
/* N.B. static atoms are effectively always interned. */
|
||||
if (ib != InternAtom || atom.isStaticAtom())
|
||||
if (ib != InternAtom || js::StaticStrings::isStatic(&atom))
|
||||
return &atom;
|
||||
|
||||
/* Here we have to check whether the atom is already interned. */
|
||||
@ -604,7 +605,7 @@ js_AtomizeChars(JSContext *cx, const jschar *chars, size_t length, InternBehavio
|
||||
JSAtom *
|
||||
js_GetExistingStringAtom(JSContext *cx, const jschar *chars, size_t length)
|
||||
{
|
||||
if (JSAtom *atom = JSAtom::lookupStatic(chars, length))
|
||||
if (JSAtom *atom = cx->runtime->staticStrings.lookup(chars, length))
|
||||
return atom;
|
||||
AutoLockAtomsCompartment lock(cx);
|
||||
AtomSet::Ptr p = cx->runtime->atomState.atoms.lookup(AtomHasher::Lookup(chars, length));
|
||||
|
@ -406,7 +406,9 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize)
|
||||
#ifdef JS_THREADSAFE
|
||||
JS_BeginRequest(cx);
|
||||
#endif
|
||||
JSBool ok = js_InitCommonAtoms(cx);
|
||||
bool ok = rt->staticStrings.init(cx);
|
||||
if (ok)
|
||||
ok = js_InitCommonAtoms(cx);
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
JS_EndRequest(cx);
|
||||
|
@ -65,6 +65,7 @@
|
||||
#include "prmjtime.h"
|
||||
|
||||
#include "vm/Stack.h"
|
||||
#include "vm/String.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
@ -655,6 +656,9 @@ struct JSRuntime {
|
||||
/* Literal table maintained by jsatom.c functions. */
|
||||
JSAtomState atomState;
|
||||
|
||||
/* Tables of strings that are pre-allocated in the atomsCompartment. */
|
||||
js::StaticStrings staticStrings;
|
||||
|
||||
JSWrapObjectCallback wrapObjectCallback;
|
||||
JSPreWrapCallback preWrapObjectCallback;
|
||||
|
||||
|
@ -207,10 +207,6 @@ JSCompartment::wrap(JSContext *cx, Value *vp)
|
||||
if (vp->isString()) {
|
||||
JSString *str = vp->toString();
|
||||
|
||||
/* Static atoms do not have to be wrapped. */
|
||||
if (str->isStaticAtom())
|
||||
return true;
|
||||
|
||||
/* If the string is already in this compartment, we are done. */
|
||||
if (str->compartment() == this)
|
||||
return true;
|
||||
|
@ -450,9 +450,8 @@ Chunk::removeFromAvailableList()
|
||||
}
|
||||
|
||||
ArenaHeader *
|
||||
Chunk::allocateArena(JSContext *cx, AllocKind thingKind)
|
||||
Chunk::allocateArena(JSCompartment *comp, AllocKind thingKind)
|
||||
{
|
||||
JSCompartment *comp = cx->compartment;
|
||||
JS_ASSERT(hasAvailableArenas());
|
||||
ArenaHeader *aheader = info.emptyArenaListHead;
|
||||
info.emptyArenaListHead = aheader->next;
|
||||
@ -547,9 +546,8 @@ ReleaseGCChunk(JSRuntime *rt, Chunk *p)
|
||||
|
||||
/* The caller must hold the GC lock. */
|
||||
static Chunk *
|
||||
PickChunk(JSContext *cx)
|
||||
PickChunk(JSCompartment *comp)
|
||||
{
|
||||
JSCompartment *comp = cx->compartment;
|
||||
JSRuntime *rt = comp->rt;
|
||||
Chunk **listHeadp = GetAvailableChunkList(comp);
|
||||
Chunk *chunk = *listHeadp;
|
||||
@ -621,8 +619,6 @@ ExpireGCChunks(JSRuntime *rt, JSGCInvocationKind gckind)
|
||||
JS_FRIEND_API(bool)
|
||||
IsAboutToBeFinalized(JSContext *cx, const void *thing)
|
||||
{
|
||||
if (JSAtom::isStatic(thing))
|
||||
return false;
|
||||
JS_ASSERT(cx);
|
||||
|
||||
JSCompartment *thingCompartment = reinterpret_cast<const Cell *>(thing)->compartment();
|
||||
@ -639,7 +635,6 @@ js_GCThingIsMarked(void *thing, uintN color = BLACK)
|
||||
{
|
||||
JS_ASSERT(thing);
|
||||
AssertValidColor(thing, color);
|
||||
JS_ASSERT(!JSAtom::isStatic(thing));
|
||||
return reinterpret_cast<Cell *>(thing)->isMarked(color);
|
||||
}
|
||||
|
||||
@ -1148,7 +1143,7 @@ namespace js {
|
||||
namespace gc {
|
||||
|
||||
inline void *
|
||||
ArenaLists::allocateFromArena(JSContext *cx, AllocKind thingKind)
|
||||
ArenaLists::allocateFromArena(JSCompartment *comp, AllocKind thingKind)
|
||||
{
|
||||
Chunk *chunk = NULL;
|
||||
|
||||
@ -1163,7 +1158,7 @@ ArenaLists::allocateFromArena(JSContext *cx, AllocKind thingKind)
|
||||
* background finalization runs and can modify head or cursor at any
|
||||
* moment. So we always allocate a new arena in that case.
|
||||
*/
|
||||
maybeLock.lock(cx->runtime);
|
||||
maybeLock.lock(comp->rt);
|
||||
for (;;) {
|
||||
if (*bfs == BFS_DONE)
|
||||
break;
|
||||
@ -1179,7 +1174,7 @@ ArenaLists::allocateFromArena(JSContext *cx, AllocKind thingKind)
|
||||
}
|
||||
|
||||
JS_ASSERT(!*al->cursor);
|
||||
chunk = PickChunk(cx);
|
||||
chunk = PickChunk(comp);
|
||||
if (chunk)
|
||||
break;
|
||||
|
||||
@ -1189,7 +1184,7 @@ ArenaLists::allocateFromArena(JSContext *cx, AllocKind thingKind)
|
||||
* added new empty arenas.
|
||||
*/
|
||||
JS_ASSERT(*bfs == BFS_RUN);
|
||||
cx->runtime->gcHelperThread.waitBackgroundSweepEnd(cx->runtime, false);
|
||||
comp->rt->gcHelperThread.waitBackgroundSweepEnd(comp->rt, false);
|
||||
JS_ASSERT(*bfs == BFS_JUST_FINISHED || *bfs == BFS_DONE);
|
||||
}
|
||||
}
|
||||
@ -1217,8 +1212,8 @@ ArenaLists::allocateFromArena(JSContext *cx, AllocKind thingKind)
|
||||
|
||||
/* Make sure we hold the GC lock before we call PickChunk. */
|
||||
if (!maybeLock.locked())
|
||||
maybeLock.lock(cx->runtime);
|
||||
chunk = PickChunk(cx);
|
||||
maybeLock.lock(comp->rt);
|
||||
chunk = PickChunk(comp);
|
||||
if (!chunk)
|
||||
return NULL;
|
||||
}
|
||||
@ -1233,7 +1228,7 @@ ArenaLists::allocateFromArena(JSContext *cx, AllocKind thingKind)
|
||||
* for allocations improving cache locality.
|
||||
*/
|
||||
JS_ASSERT(!*al->cursor);
|
||||
ArenaHeader *aheader = chunk->allocateArena(cx, thingKind);
|
||||
ArenaHeader *aheader = chunk->allocateArena(comp, thingKind);
|
||||
aheader->next = al->head;
|
||||
if (!al->head) {
|
||||
JS_ASSERT(al->cursor == &al->head);
|
||||
@ -1436,14 +1431,9 @@ ArenaLists::refillFreeList(JSContext *cx, AllocKind thingKind)
|
||||
{
|
||||
JS_ASSERT(cx->compartment->arenas.freeLists[thingKind].isEmpty());
|
||||
|
||||
/*
|
||||
* For compatibility with older code we tolerate calling the allocator
|
||||
* during the GC in optimized builds.
|
||||
*/
|
||||
JSRuntime *rt = cx->runtime;
|
||||
JSCompartment *comp = cx->compartment;
|
||||
JSRuntime *rt = comp->rt;
|
||||
JS_ASSERT(!rt->gcRunning);
|
||||
if (rt->gcRunning)
|
||||
return NULL;
|
||||
|
||||
bool runGC = !!rt->gcIsNeeded;
|
||||
for (;;) {
|
||||
@ -1460,10 +1450,10 @@ ArenaLists::refillFreeList(JSContext *cx, AllocKind thingKind)
|
||||
* return that list head.
|
||||
*/
|
||||
size_t thingSize = Arena::thingSize(thingKind);
|
||||
if (void *thing = cx->compartment->arenas.allocateFromFreeList(thingKind, thingSize))
|
||||
if (void *thing = comp->arenas.allocateFromFreeList(thingKind, thingSize))
|
||||
return thing;
|
||||
}
|
||||
void *thing = cx->compartment->arenas.allocateFromArena(cx, thingKind);
|
||||
void *thing = comp->arenas.allocateFromArena(comp, thingKind);
|
||||
if (JS_LIKELY(!!thing))
|
||||
return thing;
|
||||
|
||||
@ -1640,24 +1630,22 @@ gc_root_traversal(JSTracer *trc, const RootEntry &entry)
|
||||
}
|
||||
|
||||
if (ptr && !trc->context->runtime->gcCurrentCompartment) {
|
||||
if (!JSAtom::isStatic(ptr)) {
|
||||
/*
|
||||
* Use conservative machinery to find if ptr is a valid GC thing.
|
||||
* We only do this during global GCs, to preserve the invariant
|
||||
* that mark callbacks are not in place during compartment GCs.
|
||||
*/
|
||||
JSTracer checker;
|
||||
JS_TRACER_INIT(&checker, trc->context, EmptyMarkCallback);
|
||||
ConservativeGCTest test = MarkIfGCThingWord(&checker, reinterpret_cast<jsuword>(ptr));
|
||||
if (test != CGCT_VALID && entry.value.name) {
|
||||
fprintf(stderr,
|
||||
/*
|
||||
* Use conservative machinery to find if ptr is a valid GC thing.
|
||||
* We only do this during global GCs, to preserve the invariant
|
||||
* that mark callbacks are not in place during compartment GCs.
|
||||
*/
|
||||
JSTracer checker;
|
||||
JS_TRACER_INIT(&checker, trc->context, EmptyMarkCallback);
|
||||
ConservativeGCTest test = MarkIfGCThingWord(&checker, reinterpret_cast<jsuword>(ptr));
|
||||
if (test != CGCT_VALID && entry.value.name) {
|
||||
fprintf(stderr,
|
||||
"JS API usage error: the address passed to JS_AddNamedRoot currently holds an\n"
|
||||
"invalid gcthing. This is usually caused by a missing call to JS_RemoveRoot.\n"
|
||||
"The root's name is \"%s\".\n",
|
||||
entry.value.name);
|
||||
}
|
||||
JS_ASSERT(test == CGCT_VALID);
|
||||
entry.value.name);
|
||||
}
|
||||
JS_ASSERT(test == CGCT_VALID);
|
||||
}
|
||||
#endif
|
||||
JS_SET_TRACING_NAME(trc, entry.value.name ? entry.value.name : "root");
|
||||
@ -1856,6 +1844,7 @@ MarkRuntime(JSTracer *trc)
|
||||
gc_lock_traversal(r.front(), trc);
|
||||
|
||||
js_TraceAtomState(trc);
|
||||
rt->staticStrings.trace(trc);
|
||||
|
||||
JSContext *iter = NULL;
|
||||
while (JSContext *acx = js_ContextIterator(rt, JS_TRUE, &iter))
|
||||
|
@ -654,7 +654,7 @@ struct Chunk {
|
||||
inline void addToAvailableList(JSCompartment *compartment);
|
||||
inline void removeFromAvailableList();
|
||||
|
||||
ArenaHeader *allocateArena(JSContext *cx, AllocKind kind);
|
||||
ArenaHeader *allocateArena(JSCompartment *comp, AllocKind kind);
|
||||
|
||||
void releaseArena(ArenaHeader *aheader);
|
||||
};
|
||||
@ -1102,7 +1102,7 @@ struct ArenaLists {
|
||||
inline void finalizeNow(JSContext *cx, AllocKind thingKind);
|
||||
inline void finalizeLater(JSContext *cx, AllocKind thingKind);
|
||||
|
||||
inline void *allocateFromArena(JSContext *cx, AllocKind thingKind);
|
||||
inline void *allocateFromArena(JSCompartment *comp, AllocKind thingKind);
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -49,63 +49,6 @@
|
||||
#include "jslock.h"
|
||||
#include "jstl.h"
|
||||
|
||||
inline bool
|
||||
JSAtom::isUnitString(const void *ptr)
|
||||
{
|
||||
#ifdef JS_HAS_STATIC_STRINGS
|
||||
jsuword delta = reinterpret_cast<jsuword>(ptr) -
|
||||
reinterpret_cast<jsuword>(unitStaticTable);
|
||||
if (delta >= UNIT_STATIC_LIMIT * sizeof(JSString))
|
||||
return false;
|
||||
|
||||
/* If ptr points inside the static array, it must be well-aligned. */
|
||||
JS_ASSERT(delta % sizeof(JSString) == 0);
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSAtom::isLength2String(const void *ptr)
|
||||
{
|
||||
#ifdef JS_HAS_STATIC_STRINGS
|
||||
jsuword delta = reinterpret_cast<jsuword>(ptr) -
|
||||
reinterpret_cast<jsuword>(length2StaticTable);
|
||||
if (delta >= NUM_SMALL_CHARS * NUM_SMALL_CHARS * sizeof(JSString))
|
||||
return false;
|
||||
|
||||
/* If ptr points inside the static array, it must be well-aligned. */
|
||||
JS_ASSERT(delta % sizeof(JSString) == 0);
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSAtom::isHundredString(const void *ptr)
|
||||
{
|
||||
#ifdef JS_HAS_STATIC_STRINGS
|
||||
jsuword delta = reinterpret_cast<jsuword>(ptr) -
|
||||
reinterpret_cast<jsuword>(hundredStaticTable);
|
||||
if (delta >= NUM_HUNDRED_STATICS * sizeof(JSString))
|
||||
return false;
|
||||
|
||||
/* If ptr points inside the static array, it must be well-aligned. */
|
||||
JS_ASSERT(delta % sizeof(JSString) == 0);
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSAtom::isStatic(const void *ptr)
|
||||
{
|
||||
return isUnitString(ptr) || isLength2String(ptr) || isHundredString(ptr);
|
||||
}
|
||||
|
||||
namespace js {
|
||||
|
||||
struct Shape;
|
||||
@ -116,8 +59,6 @@ inline JSGCTraceKind
|
||||
GetGCThingTraceKind(const void *thing)
|
||||
{
|
||||
JS_ASSERT(thing);
|
||||
if (JSAtom::isStatic(thing))
|
||||
return JSTRACE_STRING;
|
||||
const Cell *cell = reinterpret_cast<const Cell *>(thing);
|
||||
return MapAllocToTraceKind(cell->getAllocKind());
|
||||
}
|
||||
|
@ -115,7 +115,6 @@ CheckMarkedThing(JSTracer *trc, T *thing)
|
||||
JS_ASSERT(trc->debugPrinter || trc->debugPrintArg);
|
||||
JS_ASSERT_IF(trc->context->runtime->gcCurrentCompartment, IS_GC_MARKING_TRACER(trc));
|
||||
|
||||
JS_ASSERT(!JSAtom::isStatic(thing));
|
||||
JS_ASSERT(thing->isAligned());
|
||||
|
||||
JS_ASSERT(thing->compartment());
|
||||
@ -155,8 +154,6 @@ void
|
||||
MarkString(JSTracer *trc, JSString *str)
|
||||
{
|
||||
JS_ASSERT(str);
|
||||
if (str->isStaticAtom())
|
||||
return;
|
||||
Mark(trc, str);
|
||||
}
|
||||
|
||||
@ -334,8 +331,7 @@ MarkAtomRange(JSTracer *trc, size_t len, JSAtom **vec, const char *name)
|
||||
for (uint32 i = 0; i < len; i++) {
|
||||
if (JSAtom *atom = vec[i]) {
|
||||
JS_SET_TRACING_INDEX(trc, name, i);
|
||||
if (!atom->isStaticAtom())
|
||||
Mark(trc, atom);
|
||||
Mark(trc, atom);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -365,13 +361,10 @@ MarkXMLRange(JSTracer *trc, size_t len, JSXML **vec, const char *name)
|
||||
void
|
||||
MarkId(JSTracer *trc, jsid id)
|
||||
{
|
||||
if (JSID_IS_STRING(id)) {
|
||||
JSString *str = JSID_TO_STRING(id);
|
||||
if (!str->isStaticAtom())
|
||||
Mark(trc, str);
|
||||
} else if (JS_UNLIKELY(JSID_IS_OBJECT(id))) {
|
||||
if (JSID_IS_STRING(id))
|
||||
Mark(trc, JSID_TO_STRING(id));
|
||||
else if (JS_UNLIKELY(JSID_IS_OBJECT(id)))
|
||||
Mark(trc, JSID_TO_OBJECT(id));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -447,9 +440,6 @@ MarkCrossCompartmentValue(JSTracer *trc, const js::Value &v, const char *name)
|
||||
{
|
||||
if (v.isMarkable()) {
|
||||
js::gc::Cell *cell = (js::gc::Cell *)v.toGCThing();
|
||||
unsigned kind = v.gcKind();
|
||||
if (kind == JSTRACE_STRING && ((JSString *)cell)->isStaticAtom())
|
||||
return;
|
||||
JSRuntime *rt = trc->context->runtime;
|
||||
if (rt->gcCurrentCompartment && cell->compartment() != rt->gcCurrentCompartment)
|
||||
return;
|
||||
@ -604,12 +594,10 @@ ScanValue(GCMarker *gcmarker, const Value &v)
|
||||
if (v.isMarkable()) {
|
||||
JSGCTraceKind kind = v.gcKind();
|
||||
if (kind == JSTRACE_STRING) {
|
||||
JSString *str = (JSString *)v.toGCThing();
|
||||
if (!str->isStaticAtom())
|
||||
PushMarkStack(gcmarker, str);
|
||||
PushMarkStack(gcmarker, v.toString());
|
||||
} else {
|
||||
JS_ASSERT(kind == JSTRACE_OBJECT);
|
||||
PushMarkStack(gcmarker, (JSObject *)v.toGCThing());
|
||||
PushMarkStack(gcmarker, &v.toObject());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -622,13 +610,10 @@ restart:
|
||||
if (rt->gcRegenShapes)
|
||||
shape->shapeid = js_RegenerateShapeForGC(rt);
|
||||
|
||||
if (JSID_IS_STRING(shape->propid)) {
|
||||
JSString *str = JSID_TO_STRING(shape->propid);
|
||||
if (!str->isStaticAtom())
|
||||
PushMarkStack(gcmarker, str);
|
||||
} else if (JS_UNLIKELY(JSID_IS_OBJECT(shape->propid))) {
|
||||
if (JSID_IS_STRING(shape->propid))
|
||||
PushMarkStack(gcmarker, JSID_TO_STRING(shape->propid));
|
||||
else if (JS_UNLIKELY(JSID_IS_OBJECT(shape->propid)))
|
||||
PushMarkStack(gcmarker, JSID_TO_OBJECT(shape->propid));
|
||||
}
|
||||
|
||||
if (shape->hasGetterValue() && shape->getter())
|
||||
PushMarkStack(gcmarker, shape->getterObject());
|
||||
@ -894,11 +879,8 @@ ScanTypeObject(GCMarker *gcmarker, types::TypeObject *type)
|
||||
unsigned count = type->getPropertyCount();
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
types::Property *prop = type->getProperty(i);
|
||||
if (prop && JSID_IS_STRING(prop->id)) {
|
||||
JSString *str = JSID_TO_STRING(prop->id);
|
||||
if (!str->isStaticAtom())
|
||||
PushMarkStack(gcmarker, str);
|
||||
}
|
||||
if (prop && JSID_IS_STRING(prop->id))
|
||||
PushMarkStack(gcmarker, JSID_TO_STRING(prop->id));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5937,7 +5937,7 @@ TypeCompartment::sweep(JSContext *cx)
|
||||
for (unsigned i = 0; !remove && i < key.nslots; i++) {
|
||||
if (JSID_IS_STRING(key.ids[i])) {
|
||||
JSString *str = JSID_TO_STRING(key.ids[i]);
|
||||
if (!str->isStaticAtom() && !str->isMarked())
|
||||
if (!str->isMarked())
|
||||
remove = true;
|
||||
}
|
||||
JS_ASSERT(!entry.types[i].isSingleObject());
|
||||
@ -6031,7 +6031,6 @@ TypeScript::Sweep(JSContext *cx, JSScript *script)
|
||||
*/
|
||||
#ifdef JS_METHODJIT
|
||||
mjit::ReleaseScriptCode(cx, script);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Use counts for scripts are reset on GC. After discarding code we need to
|
||||
@ -6039,6 +6038,7 @@ TypeScript::Sweep(JSContext *cx, JSScript *script)
|
||||
* array holes or accessing getter properties.
|
||||
*/
|
||||
script->resetUseCount();
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -3837,7 +3837,7 @@ BEGIN_CASE(JSOP_GETELEM)
|
||||
JSString *str = lref.toString();
|
||||
int32_t i = rref.toInt32();
|
||||
if (size_t(i) < str->length()) {
|
||||
str = JSAtom::getUnitStringForElement(cx, str, size_t(i));
|
||||
str = cx->runtime->staticStrings.getUnitStringForElement(cx, str, size_t(i));
|
||||
if (!str)
|
||||
goto error;
|
||||
regs.sp--;
|
||||
@ -4966,7 +4966,7 @@ BEGIN_CASE(JSOP_GETTER)
|
||||
BEGIN_CASE(JSOP_SETTER)
|
||||
{
|
||||
do_getter_setter:
|
||||
JSOp op2 = (JSOp) *++regs.pc;
|
||||
JSOp op2 = js_GetOpcode(cx, script, ++regs.pc);
|
||||
jsid id;
|
||||
Value rval;
|
||||
jsint i;
|
||||
|
@ -1025,8 +1025,8 @@ js_IteratorNext(JSContext *cx, JSObject *iterobj, Value *rval)
|
||||
|
||||
JSString *str;
|
||||
jsint i;
|
||||
if (rval->isInt32() && JSAtom::hasIntStatic(i = rval->toInt32())) {
|
||||
str = &JSAtom::intStatic(i);
|
||||
if (rval->isInt32() && StaticStrings::hasInt(i = rval->toInt32())) {
|
||||
str = cx->runtime->staticStrings.getInt(i);
|
||||
} else {
|
||||
str = js_ValueToString(cx, *rval);
|
||||
if (!str)
|
||||
|
@ -637,8 +637,8 @@ js_IntToString(JSContext *cx, int32 si)
|
||||
{
|
||||
uint32 ui;
|
||||
if (si >= 0) {
|
||||
if (JSAtom::hasIntStatic(si))
|
||||
return &JSAtom::intStatic(si);
|
||||
if (StaticStrings::hasInt(si))
|
||||
return cx->runtime->staticStrings.getInt(si);
|
||||
ui = si;
|
||||
} else {
|
||||
ui = uint32(-si);
|
||||
@ -1204,17 +1204,15 @@ js_NumberToStringWithBase(JSContext *cx, jsdouble d, jsint base)
|
||||
|
||||
int32_t i;
|
||||
if (JSDOUBLE_IS_INT32(d, &i)) {
|
||||
if (base == 10 && JSAtom::hasIntStatic(i))
|
||||
return &JSAtom::intStatic(i);
|
||||
#ifdef JS_HAS_STATIC_STRINGS
|
||||
if (base == 10 && StaticStrings::hasInt(i))
|
||||
return cx->runtime->staticStrings.getInt(i);
|
||||
if (jsuint(i) < jsuint(base)) {
|
||||
if (i < 10)
|
||||
return &JSAtom::intStatic(i);
|
||||
return cx->runtime->staticStrings.getInt(i);
|
||||
jschar c = 'a' + i - 10;
|
||||
JS_ASSERT(JSAtom::hasUnitStatic(c));
|
||||
return &JSAtom::unitStatic(c);
|
||||
JS_ASSERT(StaticStrings::hasUnit(c));
|
||||
return cx->runtime->staticStrings.getUnit(c);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (JSFlatString *str = c->dtoaCache.lookup(base, d))
|
||||
return str;
|
||||
@ -1260,8 +1258,8 @@ NumberToString(JSContext *cx, jsdouble d)
|
||||
JSFixedString *
|
||||
IndexToString(JSContext *cx, uint32 index)
|
||||
{
|
||||
if (JSAtom::hasUintStatic(index))
|
||||
return &JSAtom::uintStatic(index);
|
||||
if (StaticStrings::hasUint(index))
|
||||
return cx->runtime->staticStrings.getUint(index);
|
||||
|
||||
JSCompartment *c = cx->compartment;
|
||||
if (JSFixedString *str = c->dtoaCache.lookup(10, index))
|
||||
|
@ -148,24 +148,24 @@ uintN
|
||||
js_GetIndexFromBytecode(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
ptrdiff_t pcoff)
|
||||
{
|
||||
JSOp op;
|
||||
uintN span, base;
|
||||
|
||||
op = js_GetOpcode(cx, script, pc);
|
||||
JSOp op = js_GetOpcode(cx, script, pc);
|
||||
JS_ASSERT(js_CodeSpec[op].length >= 1 + pcoff + UINT16_LEN);
|
||||
|
||||
/*
|
||||
* We need to detect index base prefix. It presents when resetbase
|
||||
* follows the bytecode.
|
||||
*/
|
||||
span = js_CodeSpec[op].length;
|
||||
base = 0;
|
||||
uintN span = js_CodeSpec[op].length;
|
||||
uintN base = 0;
|
||||
if (pc - script->code + span < script->length) {
|
||||
if (pc[span] == JSOP_RESETBASE) {
|
||||
JSOp next = js_GetOpcode(cx, script, pc + span);
|
||||
if (next == JSOP_RESETBASE) {
|
||||
JS_ASSERT(js_GetOpcode(cx, script, pc - JSOP_INDEXBASE_LENGTH) == JSOP_INDEXBASE);
|
||||
base = GET_INDEXBASE(pc - JSOP_INDEXBASE_LENGTH);
|
||||
} else if (pc[span] == JSOP_RESETBASE0) {
|
||||
JS_ASSERT(JSOP_INDEXBASE1 <= pc[-1] || pc[-1] <= JSOP_INDEXBASE3);
|
||||
base = (pc[-1] - JSOP_INDEXBASE1 + 1) << 16;
|
||||
} else if (next == JSOP_RESETBASE0) {
|
||||
JSOp prev = js_GetOpcode(cx, script, pc - 1);
|
||||
JS_ASSERT(JSOP_INDEXBASE1 <= prev && prev <= JSOP_INDEXBASE3);
|
||||
base = (prev - JSOP_INDEXBASE1 + 1) << 16;
|
||||
}
|
||||
}
|
||||
return base + GET_UINT16(pc + pcoff);
|
||||
|
@ -224,7 +224,8 @@ typedef enum JSOp {
|
||||
#define GET_INDEX(pc) GET_UINT16(pc)
|
||||
#define SET_INDEX(pc,i) ((pc)[1] = INDEX_HI(i), (pc)[2] = INDEX_LO(i))
|
||||
|
||||
#define GET_INDEXBASE(pc) (JS_ASSERT(*(pc) == JSOP_INDEXBASE), \
|
||||
#define GET_INDEXBASE(pc) (JS_ASSERT(*(pc) == JSOP_INDEXBASE \
|
||||
|| *(pc) == JSOP_TRAP), \
|
||||
((uintN)((pc)[1])) << 16)
|
||||
#define INDEXBASE_LEN 1
|
||||
|
||||
|
216
js/src/jsstr.cpp
216
js/src/jsstr.cpp
@ -372,7 +372,7 @@ str_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags,
|
||||
|
||||
jsint slot = JSID_TO_INT(id);
|
||||
if ((size_t)slot < str->length()) {
|
||||
JSString *str1 = JSAtom::getUnitStringForElement(cx, str, size_t(slot));
|
||||
JSString *str1 = cx->runtime->staticStrings.getUnitStringForElement(cx, str, size_t(slot));
|
||||
if (!str1)
|
||||
return JS_FALSE;
|
||||
if (!obj->defineElement(cx, uint32(slot), StringValue(str1), NULL, NULL,
|
||||
@ -730,7 +730,7 @@ js_str_charAt(JSContext *cx, uintN argc, Value *vp)
|
||||
i = (jsint) d;
|
||||
}
|
||||
|
||||
str = JSAtom::getUnitStringForElement(cx, str, size_t(i));
|
||||
str = cx->runtime->staticStrings.getUnitStringForElement(cx, str, size_t(i));
|
||||
if (!str)
|
||||
return false;
|
||||
vp->setString(str);
|
||||
@ -2611,7 +2611,7 @@ str_slice(JSContext *cx, uintN argc, Value *vp)
|
||||
str = cx->runtime->emptyString;
|
||||
} else {
|
||||
str = (length == 1)
|
||||
? JSAtom::getUnitStringForElement(cx, str, begin)
|
||||
? cx->runtime->staticStrings.getUnitStringForElement(cx, str, begin)
|
||||
: js_NewDependentString(cx, str, begin, length);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
@ -2829,7 +2829,7 @@ js_String_getelem(JSContext* cx, JSString* str, int32 i)
|
||||
{
|
||||
if ((size_t)i >= str->length())
|
||||
return NULL;
|
||||
return JSAtom::getUnitStringForElement(cx, str, size_t(i));
|
||||
return cx->runtime->staticStrings.getUnitStringForElement(cx, str, size_t(i));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -2893,204 +2893,6 @@ static JSFunctionSpec string_methods[] = {
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
#ifdef JS_HAS_STATIC_STRINGS
|
||||
|
||||
/*
|
||||
* Set up some tools to make it easier to generate large tables. After constant
|
||||
* folding, for each n, Rn(0) is the comma-separated list R(0), R(1), ..., R(2^n-1).
|
||||
* Similary, Rn(k) (for any k and n) generates the list R(k), R(k+1), ..., R(k+2^n-1).
|
||||
* To use this, define R appropriately, then use Rn(0) (for some value of n), then
|
||||
* undefine R.
|
||||
*/
|
||||
#define R2(n) R(n), R((n) + (1 << 0)), R((n) + (2 << 0)), R((n) + (3 << 0))
|
||||
#define R4(n) R2(n), R2((n) + (1 << 2)), R2((n) + (2 << 2)), R2((n) + (3 << 2))
|
||||
#define R6(n) R4(n), R4((n) + (1 << 4)), R4((n) + (2 << 4)), R4((n) + (3 << 4))
|
||||
#define R8(n) R6(n), R6((n) + (1 << 6)), R6((n) + (2 << 6)), R6((n) + (3 << 6))
|
||||
#define R10(n) R8(n), R8((n) + (1 << 8)), R8((n) + (2 << 8)), R8((n) + (3 << 8))
|
||||
#define R12(n) R10(n), R10((n) + (1 << 10)), R10((n) + (2 << 10)), R10((n) + (3 << 10))
|
||||
|
||||
#define R3(n) R2(n), R2((n) + (1 << 2))
|
||||
#define R7(n) R6(n), R6((n) + (1 << 6))
|
||||
|
||||
#define BUILD_LENGTH_AND_FLAGS(length, flags) \
|
||||
(((length) << JSString::LENGTH_SHIFT) | (flags))
|
||||
|
||||
/*
|
||||
* Declare unit strings. Pack the string data itself into the mInlineChars
|
||||
* place in the header.
|
||||
*/
|
||||
#define R(c) { \
|
||||
BUILD_LENGTH_AND_FLAGS(1, JSString::STATIC_ATOM_FLAGS), \
|
||||
{ (jschar *)(uintptr_t(unitStaticTable + (c)) + \
|
||||
offsetof(JSString::Data, inlineStorage)) }, \
|
||||
{ {(c), 0x00} } }
|
||||
|
||||
/*
|
||||
* For all the pragma pack usage in this file, the following logic applies:
|
||||
* To apply: To reset:
|
||||
* Sun CC: pack(#) / pack(0)
|
||||
* IBM xlC: pack(#) / pack(pop)
|
||||
* HP aCC: pack # / pack
|
||||
* Others: pack(push, #) / pack(pop)
|
||||
* The -Dlint case is explicitly excluded because GCC will error out when
|
||||
* pack pragmas are used on unsupported platforms. If GCC is being used
|
||||
* simply for error checking, these errors will be avoided.
|
||||
*/
|
||||
|
||||
#if defined(__SUNPRO_CC) || defined(__xlC__)
|
||||
#pragma pack(8)
|
||||
#elif defined(__HP_aCC)
|
||||
#pragma pack 8
|
||||
#elif !defined(lint)
|
||||
#pragma pack(push, 8)
|
||||
#endif
|
||||
|
||||
const JSString::Data JSAtom::unitStaticTable[]
|
||||
#if defined(__GNUC__) || defined(__xlC__)
|
||||
__attribute__ ((aligned (8)))
|
||||
#endif
|
||||
= { R8(0) };
|
||||
|
||||
#if defined(__SUNPRO_CC)
|
||||
#pragma pack(0)
|
||||
#elif defined(__HP_aCC)
|
||||
#pragma pack
|
||||
#elif !defined(lint)
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
#undef R
|
||||
|
||||
/*
|
||||
* Declare length-2 strings. We only store strings where both characters are
|
||||
* alphanumeric. The lower 10 short chars are the numerals, the next 26 are
|
||||
* the lowercase letters, and the next 26 are the uppercase letters.
|
||||
*/
|
||||
#define TO_SMALL_CHAR(c) ((c) >= '0' && (c) <= '9' ? (c) - '0' : \
|
||||
(c) >= 'a' && (c) <= 'z' ? (c) - 'a' + 10 : \
|
||||
(c) >= 'A' && (c) <= 'Z' ? (c) - 'A' + 36 : \
|
||||
JSAtom::INVALID_SMALL_CHAR)
|
||||
|
||||
#define R TO_SMALL_CHAR
|
||||
|
||||
const JSAtom::SmallChar JSAtom::toSmallChar[] = { R7(0) };
|
||||
|
||||
#undef R
|
||||
|
||||
/*
|
||||
* This is used when we generate our table of short strings, so the compiler is
|
||||
* happier if we use |c| as few times as possible.
|
||||
*/
|
||||
#define FROM_SMALL_CHAR(c) ((c) + ((c) < 10 ? '0' : \
|
||||
(c) < 36 ? 'a' - 10 : \
|
||||
'A' - 36))
|
||||
#define R FROM_SMALL_CHAR
|
||||
|
||||
const jschar JSAtom::fromSmallChar[] = { R6(0) };
|
||||
|
||||
#undef R
|
||||
|
||||
/*
|
||||
* For code-generation ease, length-2 strings are encoded as 12-bit int values,
|
||||
* where the upper 6 bits is the first character and the lower 6 bits is the
|
||||
* second character.
|
||||
*/
|
||||
#define R(c) { \
|
||||
BUILD_LENGTH_AND_FLAGS(2, JSString::STATIC_ATOM_FLAGS), \
|
||||
{ (jschar *)(uintptr_t(length2StaticTable + (c)) + \
|
||||
offsetof(JSString::Data, inlineStorage)) }, \
|
||||
{ {FROM_SMALL_CHAR((c) >> 6), FROM_SMALL_CHAR((c) & 0x3F), 0x00} } }
|
||||
|
||||
#if defined(__SUNPRO_CC) || defined(__xlC__)
|
||||
#pragma pack(8)
|
||||
#elif defined(__HP_aCC)
|
||||
#pragma pack 8
|
||||
#elif !defined(lint)
|
||||
#pragma pack(push, 8)
|
||||
#endif
|
||||
|
||||
const JSString::Data JSAtom::length2StaticTable[]
|
||||
#if defined(__GNUC__) || defined(__xlC__)
|
||||
__attribute__ ((aligned (8)))
|
||||
#endif
|
||||
= { R12(0) };
|
||||
|
||||
#if defined(__SUNPRO_CC)
|
||||
#pragma pack(0)
|
||||
#elif defined(__HP_aCC)
|
||||
#pragma pack
|
||||
#elif !defined(lint)
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
#undef R
|
||||
|
||||
/*
|
||||
* Declare int strings. Only int strings from 100 to 255 actually have to be
|
||||
* generated, since the rest are either unit strings or length-2 strings. To
|
||||
* avoid the runtime cost of figuring out where to look for the string for a
|
||||
* particular integer, we precompute a table of JSString*s which refer to the
|
||||
* correct location of the int string.
|
||||
*/
|
||||
#define R(c) { \
|
||||
BUILD_LENGTH_AND_FLAGS(3, JSString::STATIC_ATOM_FLAGS), \
|
||||
{ (jschar *)(uintptr_t(hundredStaticTable + ((c) - 100)) + \
|
||||
offsetof(JSString::Data, inlineStorage)) }, \
|
||||
{ {((c) / 100) + '0', ((c) / 10 % 10) + '0', ((c) % 10) + '0', 0x00} } }
|
||||
|
||||
|
||||
JS_STATIC_ASSERT(100 + (1 << 7) + (1 << 4) + (1 << 3) + (1 << 2) == 256);
|
||||
|
||||
#if defined(__SUNPRO_CC) || defined(__xlC__)
|
||||
#pragma pack(8)
|
||||
#elif defined(__HP_aCC)
|
||||
#pragma pack 8
|
||||
#elif !defined(lint)
|
||||
#pragma pack(push, 8)
|
||||
#endif
|
||||
|
||||
const JSString::Data JSAtom::hundredStaticTable[]
|
||||
#if defined(__GNUC__) || defined(__xlC__)
|
||||
__attribute__ ((aligned (8)))
|
||||
#endif
|
||||
= { R7(100), /* 100 through 227 */
|
||||
R4(100 + (1 << 7)), /* 228 through 243 */
|
||||
R3(100 + (1 << 7) + (1 << 4)), /* 244 through 251 */
|
||||
R2(100 + (1 << 7) + (1 << 4) + (1 << 3)) /* 252 through 255 */
|
||||
};
|
||||
|
||||
#undef R
|
||||
|
||||
#define R(c) ((c) < 10 ? JSAtom::unitStaticTable + ((c) + '0') : \
|
||||
(c) < 100 ? JSAtom::length2StaticTable + \
|
||||
((size_t)TO_SMALL_CHAR(((c) / 10) + '0') << 6) + \
|
||||
TO_SMALL_CHAR(((c) % 10) + '0') : \
|
||||
JSAtom::hundredStaticTable + ((c) - 100))
|
||||
|
||||
const JSString::Data *const JSAtom::intStaticTable[] = { R8(0) };
|
||||
|
||||
#undef R
|
||||
|
||||
#if defined(__SUNPRO_CC)
|
||||
#pragma pack(0)
|
||||
#elif defined(__HP_aCC)
|
||||
#pragma pack
|
||||
#elif !defined(lint)
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
#undef R2
|
||||
#undef R4
|
||||
#undef R6
|
||||
#undef R8
|
||||
#undef R10
|
||||
#undef R12
|
||||
|
||||
#undef R3
|
||||
#undef R7
|
||||
|
||||
#endif /* defined(JS_HAS_STATIC_STRINGS) */
|
||||
|
||||
JSBool
|
||||
js_String(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
@ -3125,8 +2927,8 @@ str_fromCharCode(JSContext *cx, uintN argc, Value *vp)
|
||||
uint16_t code;
|
||||
if (!ValueToUint16(cx, argv[0], &code))
|
||||
return JS_FALSE;
|
||||
if (JSAtom::hasUnitStatic(code)) {
|
||||
vp->setString(&JSAtom::unitStatic(code));
|
||||
if (StaticStrings::hasUnit(code)) {
|
||||
vp->setString(cx->runtime->staticStrings.getUnit(code));
|
||||
return JS_TRUE;
|
||||
}
|
||||
argv[0].setInt32(code);
|
||||
@ -3158,8 +2960,8 @@ String_fromCharCode(JSContext* cx, int32 i)
|
||||
{
|
||||
JS_ASSERT(JS_ON_TRACE(cx));
|
||||
jschar c = (jschar)i;
|
||||
if (JSAtom::hasUnitStatic(c))
|
||||
return &JSAtom::unitStatic(c);
|
||||
if (StaticStrings::hasUnit(c))
|
||||
return cx->runtime->staticStrings.getUnit(c);
|
||||
return js_NewStringCopyN(cx, &c, 1);
|
||||
}
|
||||
#endif
|
||||
@ -3375,7 +3177,7 @@ js_NewDependentString(JSContext *cx, JSString *baseArg, size_t start, size_t len
|
||||
|
||||
const jschar *chars = base->chars() + start;
|
||||
|
||||
if (JSLinearString *staticStr = JSAtom::lookupStatic(chars, length))
|
||||
if (JSLinearString *staticStr = cx->runtime->staticStrings.lookup(chars, length))
|
||||
return staticStr;
|
||||
|
||||
JSLinearString *s = JSDependentString::new_(cx, base, chars, length);
|
||||
|
@ -11516,22 +11516,6 @@ TraceRecorder::callNative(uintN argc, JSOp mode)
|
||||
}
|
||||
if (vp[1].isString()) {
|
||||
JSString *str = vp[1].toString();
|
||||
#ifdef JS_HAS_STATIC_STRINGS
|
||||
if (native == js_str_charAt) {
|
||||
jsdouble i = vp[2].toNumber();
|
||||
if (JSDOUBLE_IS_NaN(i))
|
||||
i = 0;
|
||||
if (i < 0 || i >= str->length())
|
||||
RETURN_STOP("charAt out of bounds");
|
||||
LIns* str_ins = get(&vp[1]);
|
||||
LIns* idx_ins = get(&vp[2]);
|
||||
LIns* char_ins;
|
||||
CHECK_STATUS(getCharAt(str, str_ins, idx_ins, mode, &char_ins));
|
||||
set(&vp[0], char_ins);
|
||||
pendingSpecializedNative = IGNORE_NATIVE_CALL_COMPLETE_CALLBACK;
|
||||
return RECORD_CONTINUE;
|
||||
} else
|
||||
#endif
|
||||
if (native == js_str_charCodeAt) {
|
||||
jsdouble i = vp[2].toNumber();
|
||||
if (JSDOUBLE_IS_NaN(i))
|
||||
@ -12879,53 +12863,6 @@ TraceRecorder::getCharCodeAt(JSString *str, LIns* str_ins, LIns* idx_ins, LIns**
|
||||
JS_STATIC_ASSERT(sizeof(JSString) == 16 || sizeof(JSString) == 32);
|
||||
|
||||
|
||||
#ifdef JS_HAS_STATIC_STRINGS
|
||||
JS_REQUIRES_STACK LIns*
|
||||
TraceRecorder::getUnitString(LIns* str_ins, LIns* idx_ins)
|
||||
{
|
||||
LIns *ch_ins = w.getStringChar(str_ins, idx_ins);
|
||||
guard(true, w.ltuiN(ch_ins, JSAtom::UNIT_STATIC_LIMIT), MISMATCH_EXIT);
|
||||
JS_STATIC_ASSERT(sizeof(JSString) == 16 || sizeof(JSString) == 32);
|
||||
return w.addp(w.nameImmpNonGC(JSAtom::unitStaticTable),
|
||||
w.lshpN(w.ui2p(ch_ins), (sizeof(JSString) == 16) ? 4 : 5));
|
||||
}
|
||||
|
||||
JS_REQUIRES_STACK RecordingStatus
|
||||
TraceRecorder::getCharAt(JSString *str, LIns* str_ins, LIns* idx_ins, JSOp mode, LIns** out)
|
||||
{
|
||||
CHECK_STATUS(makeNumberInt32(idx_ins, &idx_ins));
|
||||
idx_ins = w.ui2p(idx_ins);
|
||||
LIns *lengthAndFlags_ins = w.ldpStringLengthAndFlags(str_ins);
|
||||
if (MaybeBranch mbr = w.jt(w.eqp0(w.andp(lengthAndFlags_ins,
|
||||
w.nameImmw(JSString::ROPE_BIT)))))
|
||||
{
|
||||
LIns *args[] = { str_ins, cx_ins };
|
||||
LIns *ok_ins = w.call(&js_FlattenOnTrace_ci, args);
|
||||
guard(false, w.eqi0(ok_ins), OOM_EXIT);
|
||||
w.label(mbr);
|
||||
}
|
||||
|
||||
LIns* inRange = w.ltup(idx_ins, w.rshupN(lengthAndFlags_ins, JSString::LENGTH_SHIFT));
|
||||
|
||||
if (mode == JSOP_GETELEM) {
|
||||
guard(true, inRange, MISMATCH_EXIT);
|
||||
|
||||
*out = getUnitString(str_ins, idx_ins);
|
||||
} else {
|
||||
LIns *phi_ins = w.allocp(sizeof(JSString *));
|
||||
w.stAlloc(w.nameImmpNonGC(cx->runtime->emptyString), phi_ins);
|
||||
|
||||
if (MaybeBranch mbr = w.jf(inRange)) {
|
||||
LIns *unitstr_ins = getUnitString(str_ins, idx_ins);
|
||||
w.stAlloc(unitstr_ins, phi_ins);
|
||||
w.label(mbr);
|
||||
}
|
||||
*out = w.ldpAlloc(phi_ins);
|
||||
}
|
||||
return RECORD_CONTINUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Typed array tracing depends on EXPANDED_LOADSTORE and F2I
|
||||
#if NJ_EXPANDED_LOADSTORE_SUPPORTED && NJ_F2I_SUPPORTED
|
||||
static bool OkToTraceTypedArrays = true;
|
||||
@ -12959,21 +12896,6 @@ TraceRecorder::record_JSOP_GETELEM()
|
||||
LIns* obj_ins = get(&lval);
|
||||
LIns* idx_ins = get(&idx);
|
||||
|
||||
#ifdef JS_HAS_STATIC_STRINGS
|
||||
// Special case for array-like access of strings.
|
||||
if (lval.isString() && hasInt32Repr(idx)) {
|
||||
if (call)
|
||||
RETURN_STOP_A("JSOP_CALLELEM on a string");
|
||||
int i = asInt32(idx);
|
||||
if (size_t(i) >= lval.toString()->length())
|
||||
RETURN_STOP_A("Invalid string index in JSOP_GETELEM");
|
||||
LIns* char_ins;
|
||||
CHECK_STATUS_A(getCharAt(lval.toString(), obj_ins, idx_ins, JSOP_GETELEM, &char_ins));
|
||||
set(&lval, char_ins);
|
||||
return ARECORD_CONTINUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (lval.isPrimitive())
|
||||
RETURN_STOP_A("JSOP_GETLEM on a primitive");
|
||||
RETURN_IF_XML_A(lval);
|
||||
|
@ -1398,12 +1398,6 @@ class TraceRecorder
|
||||
JS_REQUIRES_STACK RecordingStatus getCharCodeAt(JSString *str,
|
||||
nanojit::LIns* str_ins, nanojit::LIns* idx_ins,
|
||||
nanojit::LIns** out_ins);
|
||||
#ifdef JS_HAS_STATIC_STRINGS
|
||||
JS_REQUIRES_STACK nanojit::LIns* getUnitString(nanojit::LIns* str_ins, nanojit::LIns* idx_ins);
|
||||
JS_REQUIRES_STACK RecordingStatus getCharAt(JSString *str,
|
||||
nanojit::LIns* str_ins, nanojit::LIns* idx_ins,
|
||||
JSOp mode, nanojit::LIns** out_ins);
|
||||
#endif
|
||||
|
||||
JS_REQUIRES_STACK RecordingStatus initOrSetPropertyByName(nanojit::LIns* obj_ins,
|
||||
Value* idvalp, Value* rvalp,
|
||||
|
@ -1148,7 +1148,7 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::SparcRegist
|
||||
/*
|
||||
* Generate code testing whether an in memory value at address has a type
|
||||
* in the specified set. Updates mismatches with any failure jumps. Assumes
|
||||
* no data registers are live.
|
||||
* that no temporary (caller save) registers are live.
|
||||
*/
|
||||
bool generateTypeCheck(JSContext *cx, Address address,
|
||||
types::TypeSet *types, Vector<Jump> *mismatches)
|
||||
@ -1198,8 +1198,7 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::SparcRegist
|
||||
if (count != 0) {
|
||||
if (!mismatches->append(testObject(Assembler::NotEqual, address)))
|
||||
return false;
|
||||
Registers tempRegs(Registers::AvailRegs);
|
||||
RegisterID reg = tempRegs.takeAnyReg().reg();
|
||||
RegisterID reg = Registers::ArgReg1;
|
||||
|
||||
loadPayload(address, reg);
|
||||
|
||||
|
@ -279,12 +279,13 @@ mjit::Compiler::compileGetChar(FrameEntry *thisValue, FrameEntry *arg, GetCharMo
|
||||
if (mode == GetChar) {
|
||||
/* Slow path if there's no unit string for this character. */
|
||||
Jump notUnitString = masm.branch32(Assembler::AboveOrEqual, reg2,
|
||||
Imm32(JSAtom::UNIT_STATIC_LIMIT));
|
||||
Imm32(StaticStrings::UNIT_STATIC_LIMIT));
|
||||
stubcc.linkExit(notUnitString, Uses(3));
|
||||
|
||||
/* Load unit string in reg2. */
|
||||
masm.lshiftPtr(Imm32(sizeof(JSString) == 16 ? 4 : 5), reg2);
|
||||
masm.addPtr(ImmPtr(JSAtom::unitStaticTable), reg2);
|
||||
masm.lshiftPtr(Imm32(sizeof(JSAtom *) == 4 ? 2 : 3), reg2);
|
||||
masm.addPtr(ImmPtr(&cx->runtime->staticStrings.unitStaticTable), reg2);
|
||||
masm.loadPtr(Address(reg2), reg2);
|
||||
}
|
||||
|
||||
if (thisValue->isConstant())
|
||||
|
@ -1234,7 +1234,8 @@ class GetPropCompiler : public PICStubCompiler
|
||||
if (!linker.init(f.cx))
|
||||
THROW();
|
||||
|
||||
if (!linker.verifyRange(f.jit())) {
|
||||
if (!linker.verifyRange(pic.lastCodeBlock(f.jit())) ||
|
||||
!linker.verifyRange(f.jit())) {
|
||||
disable("code memory is out of range");
|
||||
return;
|
||||
}
|
||||
|
@ -436,7 +436,7 @@ stubs::GetElem(VMFrame &f)
|
||||
JSString *str = lref.toString();
|
||||
int32_t i = rref.toInt32();
|
||||
if ((size_t)i < str->length()) {
|
||||
str = JSAtom::getUnitStringForElement(cx, str, (size_t)i);
|
||||
str = f.cx->runtime->staticStrings.getUnitStringForElement(cx, str, (size_t)i);
|
||||
if (!str)
|
||||
THROW();
|
||||
f.regs.sp[-2].setString(str);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=4 sw=4 et tw=79 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
@ -193,54 +193,53 @@ JSExternalString::new_(JSContext *cx, const jschar *chars, size_t length, intN t
|
||||
return str;
|
||||
}
|
||||
|
||||
#ifdef JS_HAS_STATIC_STRINGS
|
||||
inline bool
|
||||
JSAtom::fitsInSmallChar(jschar c)
|
||||
js::StaticStrings::fitsInSmallChar(jschar c)
|
||||
{
|
||||
return c < SMALL_CHAR_LIMIT && toSmallChar[c] != INVALID_SMALL_CHAR;
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSAtom::hasUnitStatic(jschar c)
|
||||
js::StaticStrings::hasUnit(jschar c)
|
||||
{
|
||||
return c < UNIT_STATIC_LIMIT;
|
||||
}
|
||||
|
||||
inline JSStaticAtom &
|
||||
JSAtom::unitStatic(jschar c)
|
||||
inline JSAtom *
|
||||
js::StaticStrings::getUnit(jschar c)
|
||||
{
|
||||
JS_ASSERT(hasUnitStatic(c));
|
||||
return (JSStaticAtom &)unitStaticTable[c];
|
||||
JS_ASSERT(hasUnit(c));
|
||||
return unitStaticTable[c];
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSAtom::hasUintStatic(uint32 u)
|
||||
js::StaticStrings::hasUint(uint32 u)
|
||||
{
|
||||
return u < INT_STATIC_LIMIT;
|
||||
}
|
||||
|
||||
inline JSStaticAtom &
|
||||
JSAtom::uintStatic(uint32 u)
|
||||
inline JSAtom *
|
||||
js::StaticStrings::getUint(uint32 u)
|
||||
{
|
||||
JS_ASSERT(hasUintStatic(u));
|
||||
return *reinterpret_cast<JSStaticAtom *>(const_cast<JSString::Data *>(intStaticTable[u]));
|
||||
JS_ASSERT(hasUint(u));
|
||||
return intStaticTable[u];
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSAtom::hasIntStatic(int32 i)
|
||||
js::StaticStrings::hasInt(int32 i)
|
||||
{
|
||||
return uint32(i) < INT_STATIC_LIMIT;
|
||||
}
|
||||
|
||||
inline JSStaticAtom &
|
||||
JSAtom::intStatic(jsint i)
|
||||
inline JSAtom *
|
||||
js::StaticStrings::getInt(jsint i)
|
||||
{
|
||||
JS_ASSERT(hasIntStatic(i));
|
||||
return uintStatic(uint32(i));
|
||||
JS_ASSERT(hasInt(i));
|
||||
return getUint(uint32(i));
|
||||
}
|
||||
|
||||
inline JSLinearString *
|
||||
JSAtom::getUnitStringForElement(JSContext *cx, JSString *str, size_t index)
|
||||
js::StaticStrings::getUnitStringForElement(JSContext *cx, JSString *str, size_t index)
|
||||
{
|
||||
JS_ASSERT(index < str->length());
|
||||
const jschar *chars = str->getChars(cx);
|
||||
@ -248,38 +247,38 @@ JSAtom::getUnitStringForElement(JSContext *cx, JSString *str, size_t index)
|
||||
return NULL;
|
||||
jschar c = chars[index];
|
||||
if (c < UNIT_STATIC_LIMIT)
|
||||
return &unitStatic(c);
|
||||
return getUnit(c);
|
||||
return js_NewDependentString(cx, str, index, 1);
|
||||
}
|
||||
|
||||
inline JSStaticAtom &
|
||||
JSAtom::length2Static(jschar c1, jschar c2)
|
||||
inline JSAtom *
|
||||
js::StaticStrings::getLength2(jschar c1, jschar c2)
|
||||
{
|
||||
JS_ASSERT(fitsInSmallChar(c1));
|
||||
JS_ASSERT(fitsInSmallChar(c2));
|
||||
size_t index = (((size_t)toSmallChar[c1]) << 6) + toSmallChar[c2];
|
||||
return (JSStaticAtom &)length2StaticTable[index];
|
||||
return length2StaticTable[index];
|
||||
}
|
||||
|
||||
inline JSStaticAtom &
|
||||
JSAtom::length2Static(uint32 i)
|
||||
inline JSAtom *
|
||||
js::StaticStrings::getLength2(uint32 i)
|
||||
{
|
||||
JS_ASSERT(i < 100);
|
||||
return length2Static('0' + i / 10, '0' + i % 10);
|
||||
return getLength2('0' + i / 10, '0' + i % 10);
|
||||
}
|
||||
|
||||
/* Get a static atomized string for chars if possible. */
|
||||
inline JSStaticAtom *
|
||||
JSAtom::lookupStatic(const jschar *chars, size_t length)
|
||||
inline JSAtom *
|
||||
js::StaticStrings::lookup(const jschar *chars, size_t length)
|
||||
{
|
||||
switch (length) {
|
||||
case 1:
|
||||
if (chars[0] < UNIT_STATIC_LIMIT)
|
||||
return &unitStatic(chars[0]);
|
||||
return getUnit(chars[0]);
|
||||
return NULL;
|
||||
case 2:
|
||||
if (fitsInSmallChar(chars[0]) && fitsInSmallChar(chars[1]))
|
||||
return &length2Static(chars[0], chars[1]);
|
||||
return getLength2(chars[0], chars[1]);
|
||||
return NULL;
|
||||
case 3:
|
||||
/*
|
||||
@ -297,7 +296,7 @@ JSAtom::lookupStatic(const jschar *chars, size_t length)
|
||||
(chars[2] - '0');
|
||||
|
||||
if (jsuint(i) < INT_STATIC_LIMIT)
|
||||
return &intStatic(i);
|
||||
return getInt(i);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -305,87 +304,11 @@ JSAtom::lookupStatic(const jschar *chars, size_t length)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else /* defined(JS_HAS_STATIC_STRINGS) */
|
||||
|
||||
inline bool
|
||||
JSAtom::fitsInSmallChar(jschar c)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSAtom::hasUnitStatic(jschar c)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
inline JSStaticAtom &
|
||||
JSAtom::unitStatic(jschar c)
|
||||
{
|
||||
JS_NOT_REACHED("no static strings");
|
||||
return *(JSStaticAtom *)NULL;
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSAtom::hasUintStatic(uint32 u)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
inline JSStaticAtom &
|
||||
JSAtom::uintStatic(uint32 u)
|
||||
{
|
||||
JS_NOT_REACHED("no static strings");
|
||||
return *(JSStaticAtom *)NULL;
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSAtom::hasIntStatic(int32 i)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
inline JSStaticAtom &
|
||||
JSAtom::intStatic(jsint i)
|
||||
{
|
||||
JS_NOT_REACHED("no static strings");
|
||||
return *(JSStaticAtom *)NULL;
|
||||
}
|
||||
|
||||
inline JSLinearString *
|
||||
JSAtom::getUnitStringForElement(JSContext *cx, JSString *str, size_t index)
|
||||
{
|
||||
JS_ASSERT(index < str->length());
|
||||
return js_NewDependentString(cx, str, index, 1);
|
||||
}
|
||||
|
||||
inline JSStaticAtom &
|
||||
JSAtom::length2Static(jschar c1, jschar c2)
|
||||
{
|
||||
JS_NOT_REACHED("no static strings");
|
||||
return *(JSStaticAtom *)NULL;
|
||||
}
|
||||
|
||||
inline JSStaticAtom &
|
||||
JSAtom::length2Static(uint32 i)
|
||||
{
|
||||
JS_NOT_REACHED("no static strings");
|
||||
return *(JSStaticAtom *)NULL;
|
||||
}
|
||||
|
||||
/* Get a static atomized string for chars if possible. */
|
||||
inline JSStaticAtom *
|
||||
JSAtom::lookupStatic(const jschar *chars, size_t length)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif /* defined(JS_HAS_STATIC_STRINGS) */
|
||||
|
||||
JS_ALWAYS_INLINE void
|
||||
JSString::finalize(JSContext *cx)
|
||||
{
|
||||
/* Statics are not GC-things and shorts are in a different arena. */
|
||||
JS_ASSERT(!isStaticAtom() && !isShort());
|
||||
/* Shorts are in a different arena. */
|
||||
JS_ASSERT(!isShort());
|
||||
|
||||
if (isFlat())
|
||||
asFlat().finalize(cx->runtime);
|
||||
|
@ -40,6 +40,8 @@
|
||||
|
||||
#include "mozilla/RangedPtr.h"
|
||||
|
||||
#include "jsgcmark.h"
|
||||
|
||||
#include "String.h"
|
||||
#include "String-inl.h"
|
||||
|
||||
@ -78,7 +80,7 @@ void
|
||||
JSLinearString::mark(JSTracer *)
|
||||
{
|
||||
JSLinearString *str = this;
|
||||
while (!str->isStaticAtom() && str->markIfUnmarked() && str->isDependent())
|
||||
while (str->markIfUnmarked() && str->isDependent())
|
||||
str = str->asDependent().base();
|
||||
}
|
||||
|
||||
@ -114,10 +116,6 @@ JSString::charsHeapSize(JSUsableSizeFun usf)
|
||||
if (isInline())
|
||||
return 0;
|
||||
|
||||
/* JSStaticAtom: the chars are static and so not part of the heap. */
|
||||
if (isStaticAtom())
|
||||
return 0;
|
||||
|
||||
/* JSAtom, JSFixedString: count the chars. */
|
||||
JSFixedString &fixed = asFixed();
|
||||
size_t usable = usf((void *)fixed.chars());
|
||||
@ -374,3 +372,120 @@ JSFlatString::isElement(uint32 *indexp) const
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up some tools to make it easier to generate large tables. After constant
|
||||
* folding, for each n, Rn(0) is the comma-separated list R(0), R(1), ..., R(2^n-1).
|
||||
* Similary, Rn(k) (for any k and n) generates the list R(k), R(k+1), ..., R(k+2^n-1).
|
||||
* To use this, define R appropriately, then use Rn(0) (for some value of n), then
|
||||
* undefine R.
|
||||
*/
|
||||
#define R2(n) R(n), R((n) + (1 << 0)), R((n) + (2 << 0)), R((n) + (3 << 0))
|
||||
#define R4(n) R2(n), R2((n) + (1 << 2)), R2((n) + (2 << 2)), R2((n) + (3 << 2))
|
||||
#define R6(n) R4(n), R4((n) + (1 << 4)), R4((n) + (2 << 4)), R4((n) + (3 << 4))
|
||||
#define R7(n) R6(n), R6((n) + (1 << 6))
|
||||
|
||||
/*
|
||||
* This is used when we generate our table of short strings, so the compiler is
|
||||
* happier if we use |c| as few times as possible.
|
||||
*/
|
||||
#define FROM_SMALL_CHAR(c) ((c) + ((c) < 10 ? '0' : \
|
||||
(c) < 36 ? 'a' - 10 : \
|
||||
'A' - 36))
|
||||
|
||||
/*
|
||||
* Declare length-2 strings. We only store strings where both characters are
|
||||
* alphanumeric. The lower 10 short chars are the numerals, the next 26 are
|
||||
* the lowercase letters, and the next 26 are the uppercase letters.
|
||||
*/
|
||||
#define TO_SMALL_CHAR(c) ((c) >= '0' && (c) <= '9' ? (c) - '0' : \
|
||||
(c) >= 'a' && (c) <= 'z' ? (c) - 'a' + 10 : \
|
||||
(c) >= 'A' && (c) <= 'Z' ? (c) - 'A' + 36 : \
|
||||
StaticStrings::INVALID_SMALL_CHAR)
|
||||
|
||||
#define R TO_SMALL_CHAR
|
||||
const StaticStrings::SmallChar StaticStrings::toSmallChar[] = { R7(0) };
|
||||
#undef R
|
||||
|
||||
bool
|
||||
StaticStrings::init(JSContext *cx)
|
||||
{
|
||||
SwitchToCompartment sc(cx, cx->runtime->atomsCompartment);
|
||||
|
||||
for (uint32 i = 0; i < UNIT_STATIC_LIMIT; i++) {
|
||||
jschar buffer[] = { i, 0x00 };
|
||||
JSFixedString *s = js_NewStringCopyN(cx, buffer, 1);
|
||||
if (!s)
|
||||
return false;
|
||||
unitStaticTable[i] = s->morphAtomizedStringIntoAtom();
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < NUM_SMALL_CHARS * NUM_SMALL_CHARS; i++) {
|
||||
jschar buffer[] = { FROM_SMALL_CHAR(i >> 6), FROM_SMALL_CHAR(i & 0x3F), 0x00 };
|
||||
JSFixedString *s = js_NewStringCopyN(cx, buffer, 2);
|
||||
if (!s)
|
||||
return false;
|
||||
length2StaticTable[i] = s->morphAtomizedStringIntoAtom();
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < INT_STATIC_LIMIT; i++) {
|
||||
if (i < 10) {
|
||||
intStaticTable[i] = unitStaticTable[i + '0'];
|
||||
} else if (i < 100) {
|
||||
size_t index = ((size_t)TO_SMALL_CHAR((i / 10) + '0') << 6) +
|
||||
TO_SMALL_CHAR((i % 10) + '0');
|
||||
intStaticTable[i] = length2StaticTable[index];
|
||||
} else {
|
||||
jschar buffer[] = { (i / 100) + '0', ((i / 10) % 10) + '0', (i % 10) + '0', 0x00 };
|
||||
JSFixedString *s = js_NewStringCopyN(cx, buffer, 3);
|
||||
if (!s)
|
||||
return false;
|
||||
intStaticTable[i] = s->morphAtomizedStringIntoAtom();
|
||||
}
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
StaticStrings::trace(JSTracer *trc)
|
||||
{
|
||||
if (!initialized)
|
||||
return;
|
||||
|
||||
for (uint32 i = 0; i < UNIT_STATIC_LIMIT; i++)
|
||||
MarkString(trc, unitStaticTable[i], "unit-static-string");
|
||||
|
||||
for (uint32 i = 0; i < NUM_SMALL_CHARS * NUM_SMALL_CHARS; i++)
|
||||
MarkString(trc, length2StaticTable[i], "length2-static-string");
|
||||
|
||||
/* This may mark some strings more than once, but so be it. */
|
||||
for (uint32 i = 0; i < INT_STATIC_LIMIT; i++)
|
||||
MarkString(trc, intStaticTable[i], "int-static-string");
|
||||
}
|
||||
|
||||
bool
|
||||
StaticStrings::isStatic(JSAtom *atom)
|
||||
{
|
||||
const jschar *chars = atom->chars();
|
||||
switch (atom->length()) {
|
||||
case 1:
|
||||
return (chars[0] < UNIT_STATIC_LIMIT);
|
||||
case 2:
|
||||
return (fitsInSmallChar(chars[0]) && fitsInSmallChar(chars[1]));
|
||||
case 3:
|
||||
if ('1' <= chars[0] && chars[0] <= '9' &&
|
||||
'0' <= chars[1] && chars[1] <= '9' &&
|
||||
'0' <= chars[2] && chars[2] <= '9') {
|
||||
jsint i = (chars[0] - '0') * 100 +
|
||||
(chars[1] - '0') * 10 +
|
||||
(chars[2] - '0');
|
||||
|
||||
return (jsuint(i) < INT_STATIC_LIMIT);
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=4 sw=4 et tw=79 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
@ -49,12 +49,12 @@ class JSExtensibleString;
|
||||
class JSExternalString;
|
||||
class JSLinearString;
|
||||
class JSFixedString;
|
||||
class JSStaticAtom;
|
||||
class JSRope;
|
||||
class JSAtom;
|
||||
|
||||
namespace js {
|
||||
|
||||
class StaticStrings;
|
||||
class PropertyName;
|
||||
|
||||
/* The buffer length required to contain any unsigned 32-bit integer. */
|
||||
@ -114,11 +114,6 @@ js_AtomizeString(JSContext *cx, JSString *str, js::InternBehavior ib = js::DoNot
|
||||
* canonicalized to "atoms" (JSAtom) such that there is a single atom with a
|
||||
* given (length,chars).
|
||||
*
|
||||
* - To avoid dynamic creation of common short strings (e.g., single-letter
|
||||
* alphanumeric strings, numeric strings up to 999) headers and char arrays
|
||||
* for such strings are allocated in static memory (JSStaticAtom) and used
|
||||
* as atoms.
|
||||
*
|
||||
* - To avoid copying all strings created through the JSAPI, an "external"
|
||||
* string (JSExternalString) can be created whose chars are managed by the
|
||||
* JSAPI client.
|
||||
@ -150,12 +145,10 @@ js_AtomizeString(JSContext *cx, JSString *str, js::InternBehavior ib = js::DoNot
|
||||
* | | JSShortString - / header is fat
|
||||
* | | |
|
||||
* JSAtom | | - / string equality === pointer equality
|
||||
* | \ | |
|
||||
* | JSInlineAtom | - / atomized JSInlineString
|
||||
* | \ |
|
||||
* | JSShortAtom - / atomized JSShortString
|
||||
* |
|
||||
* JSStaticAtom - / header and chars statically allocated
|
||||
* \ | |
|
||||
* JSInlineAtom | - / atomized JSInlineString
|
||||
* \ |
|
||||
* JSShortAtom - / atomized JSShortString
|
||||
*
|
||||
* Classes marked with (abstract) above are not literally C++ Abstract Base
|
||||
* Classes (since there are no virtual functions, pure or not, in this
|
||||
@ -258,9 +251,6 @@ class JSString : public js::gc::Cell
|
||||
static const size_t ATOM_MASK = JS_BITMASK(3);
|
||||
static const size_t ATOM_FLAGS = 0x0;
|
||||
|
||||
static const size_t STATIC_ATOM_MASK = JS_BITMASK(4);
|
||||
static const size_t STATIC_ATOM_FLAGS = 0x0;
|
||||
|
||||
static const size_t EXTENSIBLE_FLAGS = JS_BIT(2) | JS_BIT(3);
|
||||
static const size_t NON_STATIC_ATOM = JS_BIT(3);
|
||||
|
||||
@ -400,11 +390,6 @@ class JSString : public js::gc::Cell
|
||||
return *(JSAtom *)this;
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
bool isStaticAtom() const {
|
||||
return (d.lengthAndFlags & FLAGS_MASK) == STATIC_ATOM_FLAGS;
|
||||
}
|
||||
|
||||
/* Only called by the GC for strings with the FINALIZE_STRING kind. */
|
||||
|
||||
inline void finalize(JSContext *cx);
|
||||
@ -655,79 +640,9 @@ class JSExternalString : public JSFixedString
|
||||
|
||||
JS_STATIC_ASSERT(sizeof(JSExternalString) == sizeof(JSString));
|
||||
|
||||
#if !defined(__ia64__)
|
||||
/*
|
||||
* Don't use static strings on ia64 since the compiler may put the static
|
||||
* memory out of the acceptable 47-bit jsval pointer range.
|
||||
*/
|
||||
# define JS_HAS_STATIC_STRINGS
|
||||
#endif
|
||||
|
||||
class JSAtom : public JSFixedString
|
||||
{
|
||||
public:
|
||||
/* Exposed only for jits. */
|
||||
|
||||
#ifdef JS_HAS_STATIC_STRINGS
|
||||
static const size_t UNIT_STATIC_LIMIT = 256U;
|
||||
static const size_t SMALL_CHAR_LIMIT = 128U; /* Bigger chars cannot be in a length-2 string. */
|
||||
static const size_t NUM_SMALL_CHARS = 64U;
|
||||
static const size_t INT_STATIC_LIMIT = 256U;
|
||||
static const size_t NUM_HUNDRED_STATICS = 156U;
|
||||
|
||||
# ifdef __SUNPRO_CC
|
||||
# pragma align 8 (__1cGJSAtomPunitStaticTable_, __1cGJSAtomSlength2StaticTable_, __1cGJSAtomShundredStaticTable_)
|
||||
# endif
|
||||
|
||||
static const JSString::Data unitStaticTable[];
|
||||
static const JSString::Data length2StaticTable[];
|
||||
static const JSString::Data hundredStaticTable[];
|
||||
static const JSString::Data *const intStaticTable[];
|
||||
#endif
|
||||
|
||||
private:
|
||||
/* Defined in jsgcinlines.h */
|
||||
static inline bool isUnitString(const void *ptr);
|
||||
static inline bool isLength2String(const void *ptr);
|
||||
static inline bool isHundredString(const void *ptr);
|
||||
|
||||
typedef uint8 SmallChar;
|
||||
static const SmallChar INVALID_SMALL_CHAR = -1;
|
||||
|
||||
static inline bool fitsInSmallChar(jschar c);
|
||||
|
||||
static const jschar fromSmallChar[];
|
||||
static const SmallChar toSmallChar[];
|
||||
|
||||
static void staticAsserts() {
|
||||
JS_STATIC_ASSERT(sizeof(JSString::Data) == sizeof(JSString));
|
||||
}
|
||||
|
||||
static JSStaticAtom &length2Static(jschar c1, jschar c2);
|
||||
static JSStaticAtom &length2Static(uint32 i);
|
||||
|
||||
public:
|
||||
/*
|
||||
* While this query can be used for any pointer to GC thing, given a
|
||||
* JSString 'str', it is more efficient to use 'str->isStaticAtom()'.
|
||||
*/
|
||||
static inline bool isStatic(const void *ptr);
|
||||
|
||||
static inline bool hasUintStatic(uint32 u);
|
||||
static inline JSStaticAtom &uintStatic(uint32 u);
|
||||
|
||||
static inline bool hasIntStatic(int32 i);
|
||||
static inline JSStaticAtom &intStatic(jsint i);
|
||||
|
||||
static inline bool hasUnitStatic(jschar c);
|
||||
static JSStaticAtom &unitStatic(jschar c);
|
||||
|
||||
/* May not return atom, returns null on (reported) failure. */
|
||||
static inline JSLinearString *getUnitStringForElement(JSContext *cx, JSString *str, size_t index);
|
||||
|
||||
/* Return null if no static atom exists for the given (chars, length). */
|
||||
static inline JSStaticAtom *lookupStatic(const jschar *chars, size_t length);
|
||||
|
||||
/* Returns the PropertyName for this. isElement() must be false. */
|
||||
inline js::PropertyName *asPropertyName();
|
||||
|
||||
@ -756,13 +671,61 @@ class JSShortAtom : public JSShortString /*, JSInlineAtom */
|
||||
|
||||
JS_STATIC_ASSERT(sizeof(JSShortAtom) == sizeof(JSShortString));
|
||||
|
||||
class JSStaticAtom : public JSAtom
|
||||
{};
|
||||
|
||||
JS_STATIC_ASSERT(sizeof(JSStaticAtom) == sizeof(JSString));
|
||||
|
||||
namespace js {
|
||||
|
||||
class StaticStrings
|
||||
{
|
||||
private:
|
||||
bool initialized;
|
||||
|
||||
/* Bigger chars cannot be in a length-2 string. */
|
||||
static const size_t SMALL_CHAR_LIMIT = 128U;
|
||||
static const size_t NUM_SMALL_CHARS = 64U;
|
||||
|
||||
static const size_t INT_STATIC_LIMIT = 256U;
|
||||
|
||||
JSAtom *length2StaticTable[NUM_SMALL_CHARS * NUM_SMALL_CHARS];
|
||||
JSAtom *intStaticTable[INT_STATIC_LIMIT];
|
||||
|
||||
public:
|
||||
/* We keep these public for the methodjit. */
|
||||
static const size_t UNIT_STATIC_LIMIT = 256U;
|
||||
JSAtom *unitStaticTable[UNIT_STATIC_LIMIT];
|
||||
|
||||
StaticStrings() : initialized(false) {}
|
||||
|
||||
bool init(JSContext *cx);
|
||||
void trace(JSTracer *trc);
|
||||
|
||||
static inline bool hasUint(uint32 u);
|
||||
inline JSAtom *getUint(uint32 u);
|
||||
|
||||
static inline bool hasInt(int32 i);
|
||||
inline JSAtom *getInt(jsint i);
|
||||
|
||||
static inline bool hasUnit(jschar c);
|
||||
JSAtom *getUnit(jschar c);
|
||||
|
||||
/* May not return atom, returns null on (reported) failure. */
|
||||
inline JSLinearString *getUnitStringForElement(JSContext *cx, JSString *str, size_t index);
|
||||
|
||||
static bool isStatic(JSAtom *atom);
|
||||
|
||||
/* Return null if no static atom exists for the given (chars, length). */
|
||||
inline JSAtom *lookup(const jschar *chars, size_t length);
|
||||
|
||||
private:
|
||||
typedef uint8 SmallChar;
|
||||
static const SmallChar INVALID_SMALL_CHAR = -1;
|
||||
|
||||
static inline bool fitsInSmallChar(jschar c);
|
||||
|
||||
static const SmallChar toSmallChar[];
|
||||
|
||||
JSAtom *getLength2(jschar c1, jschar c2);
|
||||
JSAtom *getLength2(uint32 i);
|
||||
};
|
||||
|
||||
/*
|
||||
* Represents an atomized string which does not contain an unsigned 32-bit
|
||||
* value. That is, it is never the case that for a PropertyName propname,
|
||||
|
@ -3883,6 +3883,31 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsFrameConstructorState& aState,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
SetFlagsOnSubtree(nsIContent *aNode, PtrBits aFlagsToSet)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// Make sure that the node passed to us doesn't have any XBL children
|
||||
{
|
||||
nsIDocument *doc = aNode->GetOwnerDoc();
|
||||
NS_ASSERTION(doc, "The node must be in a document");
|
||||
NS_ASSERTION(!doc->BindingManager()->GetXBLChildNodesFor(aNode),
|
||||
"The node should not have any XBL children");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set the flag on the node itself
|
||||
aNode->SetFlags(aFlagsToSet);
|
||||
|
||||
// Set the flag on all of its children recursively
|
||||
PRUint32 count;
|
||||
nsIContent * const *children = aNode->GetChildArray(&count);
|
||||
|
||||
for (PRUint32 index = 0; index < count; ++index) {
|
||||
SetFlagsOnSubtree(children[index], aFlagsToSet);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCSSFrameConstructor::GetAnonymousContent(nsIContent* aParent,
|
||||
nsIFrame* aParentFrame,
|
||||
@ -3910,7 +3935,17 @@ nsCSSFrameConstructor::GetAnonymousContent(nsIContent* aParent,
|
||||
content->SetNativeAnonymous();
|
||||
}
|
||||
|
||||
PRBool anonContentIsEditable = content->HasFlag(NODE_IS_EDITABLE);
|
||||
rv = content->BindToTree(mDocument, aParent, aParent, PR_TRUE);
|
||||
// If the anonymous content creator requested that the content should be
|
||||
// editable, honor its request.
|
||||
// We need to set the flag on the whole subtree, because existing
|
||||
// children's flags have already been set as part of the BindToTree operation.
|
||||
if (anonContentIsEditable) {
|
||||
NS_ASSERTION(aParentFrame->GetType() == nsGkAtoms::textInputFrame,
|
||||
"We only expect this for anonymous content under a text control frame");
|
||||
SetFlagsOnSubtree(content, NODE_IS_EDITABLE);
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
content->UnbindFromTree();
|
||||
return rv;
|
||||
@ -6137,25 +6172,6 @@ nsCSSFrameConstructor::ReframeTextIfNeeded(nsIContent* aParentContent,
|
||||
ContentInserted(aParentContent, aContent, nsnull, PR_FALSE);
|
||||
}
|
||||
|
||||
// We want to disable lazy frame construction for nodes that are under an
|
||||
// editor. We use nsINode::IsEditable, but that includes inputs with type text
|
||||
// and password and textareas, which are common and aren't really editable (the
|
||||
// native anonymous content under them is what is actually editable) so we want
|
||||
// to construct frames for those lazily.
|
||||
// The logic for this check is based on
|
||||
// nsGenericHTMLFormElement::UpdateEditableFormControlState and so must be kept
|
||||
// in sync with that. MayHaveContentEditableAttr() being true only indicates
|
||||
// a contenteditable attribute, it doesn't indicate whether it is true or false,
|
||||
// so we force eager construction in some cases when the node is not editable,
|
||||
// but that should be rare.
|
||||
static inline PRBool
|
||||
IsActuallyEditable(nsIContent* aContainer, nsIContent* aChild)
|
||||
{
|
||||
return (aChild->IsEditable() &&
|
||||
(aContainer->IsEditable() ||
|
||||
aChild->MayHaveContentEditableAttr()));
|
||||
}
|
||||
|
||||
// For inserts aChild should be valid, for appends it should be null.
|
||||
// Returns true if this operation can be lazy, false if not.
|
||||
PRBool
|
||||
@ -6170,7 +6186,7 @@ nsCSSFrameConstructor::MaybeConstructLazily(Operation aOperation,
|
||||
|
||||
if (aOperation == CONTENTINSERT) {
|
||||
if (aChild->IsRootOfAnonymousSubtree() ||
|
||||
aChild->IsXUL() || IsActuallyEditable(aContainer, aChild)) {
|
||||
aChild->IsEditable() || aChild->IsXUL()) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
} else { // CONTENTAPPEND
|
||||
@ -6179,7 +6195,7 @@ nsCSSFrameConstructor::MaybeConstructLazily(Operation aOperation,
|
||||
for (nsIContent* child = aChild; child; child = child->GetNextSibling()) {
|
||||
NS_ASSERTION(!child->IsRootOfAnonymousSubtree(),
|
||||
"Should be coming through the CONTENTAPPEND case");
|
||||
if (child->IsXUL() || IsActuallyEditable(aContainer, child)) {
|
||||
if (child->IsXUL() || child->IsEditable()) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
@ -7961,6 +7977,12 @@ nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
|
||||
}
|
||||
|
||||
if (hint & nsChangeHint_ReconstructFrame) {
|
||||
// If we ever start passing PR_TRUE here, be careful of restyles
|
||||
// that involve a reframe and animations. In particular, if the
|
||||
// restyle we're processing here is an animation restyle, but
|
||||
// the style resolution we will do for the frame construction
|
||||
// happens async when we're not in an animation restyle already,
|
||||
// problems could arise.
|
||||
RecreateFramesForContent(content, PR_FALSE);
|
||||
} else {
|
||||
NS_ASSERTION(frame, "This shouldn't happen");
|
||||
|
@ -4050,27 +4050,10 @@ nsLayoutUtils::SurfaceFromElement(nsIDOMElement *aElement,
|
||||
return result;
|
||||
}
|
||||
|
||||
// In case of data: URIs, we want to ignore principals;
|
||||
// they should have the originating content's principal,
|
||||
// but that's broken at the moment in imgLib.
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = imgRequest->GetURI(getter_AddRefs(uri));
|
||||
if (NS_FAILED(rv))
|
||||
return result;
|
||||
|
||||
PRBool isDataURI = PR_FALSE;
|
||||
rv = uri->SchemeIs("data", &isDataURI);
|
||||
if (NS_FAILED(rv))
|
||||
return result;
|
||||
|
||||
// Data URIs are always OK; set the principal
|
||||
// to null to indicate that.
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
if (!isDataURI) {
|
||||
rv = imgRequest->GetImagePrincipal(getter_AddRefs(principal));
|
||||
if (NS_FAILED(rv) || !principal)
|
||||
return result;
|
||||
}
|
||||
rv = imgRequest->GetImagePrincipal(getter_AddRefs(principal));
|
||||
if (NS_FAILED(rv) || !principal)
|
||||
return result;
|
||||
|
||||
nsCOMPtr<imgIContainer> imgContainer;
|
||||
rv = imgRequest->GetImage(getter_AddRefs(imgContainer));
|
||||
|
@ -1357,7 +1357,8 @@ public:
|
||||
nsRefPtr<gfxASurface> mSurface;
|
||||
/* The size of the surface */
|
||||
gfxIntSize mSize;
|
||||
/* The principal associated with the element whose surface was returned */
|
||||
/* The principal associated with the element whose surface was returned.
|
||||
If there is a surface, this will never be null. */
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
/* The image request, if the element is an nsIImageLoadingContent */
|
||||
nsCOMPtr<imgIRequest> mImageRequest;
|
||||
|
@ -79,6 +79,10 @@ public:
|
||||
* Creates "native" anonymous content and adds the created content to
|
||||
* the aElements array. None of the returned elements can be nsnull.
|
||||
*
|
||||
* If the anonymous content creator sets the editable flag on some
|
||||
* of the elements that it creates, the flag will be applied to the node
|
||||
* upon being bound to the document.
|
||||
*
|
||||
* @note The returned elements are owned by this object. This object is
|
||||
* responsible for calling UnbindFromTree on the elements it returned
|
||||
* from CreateAnonymousContent when appropriate (i.e. before releasing
|
||||
|
13
layout/reftests/editor/readonly-editable-ref.html
Normal file
13
layout/reftests/editor/readonly-editable-ref.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<input>
|
||||
<input readonly>
|
||||
<input type=password>
|
||||
<input type=password readonly>
|
||||
<input type=email>
|
||||
<input type=email readonly>
|
||||
<textarea></textarea>
|
||||
<textarea readonly></textarea>
|
||||
</body>
|
||||
</html>
|
24
layout/reftests/editor/readonly-editable.html
Normal file
24
layout/reftests/editor/readonly-editable.html
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
:-moz-read-write + span {
|
||||
display: none;
|
||||
}
|
||||
span {
|
||||
color: transparent; /* workaround for bug 617524 */
|
||||
outline: 1px solid green;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body contenteditable>
|
||||
<input><span>hide me</span>
|
||||
<input readonly><span>hide me</span>
|
||||
<input type=password><span>hide me</span>
|
||||
<input type=password readonly><span>hide me</span>
|
||||
<input type=email><span>hide me</span>
|
||||
<input type=email readonly><span>hide me</span>
|
||||
<textarea></textarea><span>hide me</span>
|
||||
<textarea readonly></textarea><span>hide me</span>
|
||||
</body>
|
||||
</html>
|
21
layout/reftests/editor/readonly-non-editable-ref.html
Normal file
21
layout/reftests/editor/readonly-non-editable-ref.html
Normal file
@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
span {
|
||||
color: transparent; /* workaround for bug 617524 */
|
||||
outline: 1px solid green;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<input><span>hide me</span>
|
||||
<input readonly>
|
||||
<input type=password><span>hide me</span>
|
||||
<input type=password readonly>
|
||||
<input type=email><span>hide me</span>
|
||||
<input type=email readonly>
|
||||
<textarea></textarea><span>hide me</span>
|
||||
<textarea readonly></textarea>
|
||||
</body>
|
||||
</html>
|
24
layout/reftests/editor/readonly-non-editable.html
Normal file
24
layout/reftests/editor/readonly-non-editable.html
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
:-moz-read-only + span {
|
||||
display: none;
|
||||
}
|
||||
span {
|
||||
color: transparent; /* workaround for bug 617524 */
|
||||
outline: 1px solid green;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<input><span>hide me</span>
|
||||
<input readonly><span>hide me</span>
|
||||
<input type=password><span>hide me</span>
|
||||
<input type=password readonly><span>hide me</span>
|
||||
<input type=email><span>hide me</span>
|
||||
<input type=email readonly><span>hide me</span>
|
||||
<textarea></textarea><span>hide me</span>
|
||||
<textarea readonly></textarea><span>hide me</span>
|
||||
</body>
|
||||
</html>
|
13
layout/reftests/editor/readwrite-editable-ref.html
Normal file
13
layout/reftests/editor/readwrite-editable-ref.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<input>
|
||||
<input readonly>
|
||||
<input type=password>
|
||||
<input type=password readonly>
|
||||
<input type=email>
|
||||
<input type=email readonly>
|
||||
<textarea></textarea>
|
||||
<textarea readonly></textarea>
|
||||
</body>
|
||||
</html>
|
24
layout/reftests/editor/readwrite-editable.html
Normal file
24
layout/reftests/editor/readwrite-editable.html
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
:-moz-read-write + span {
|
||||
display: none;
|
||||
}
|
||||
span {
|
||||
color: transparent; /* workaround for bug 617524 */
|
||||
outline: 1px solid green;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body contenteditable>
|
||||
<input><span>hide me</span>
|
||||
<input readonly><span>hide me</span>
|
||||
<input type=password><span>hide me</span>
|
||||
<input type=password readonly><span>hide me</span>
|
||||
<input type=email><span>hide me</span>
|
||||
<input type=email readonly><span>hide me</span>
|
||||
<textarea></textarea><span>hide me</span>
|
||||
<textarea readonly></textarea><span>hide me</span>
|
||||
</body>
|
||||
</html>
|
21
layout/reftests/editor/readwrite-non-editable-ref.html
Normal file
21
layout/reftests/editor/readwrite-non-editable-ref.html
Normal file
@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
span {
|
||||
color: transparent; /* workaround for bug 617524 */
|
||||
outline: 1px solid green;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<input>
|
||||
<input readonly><span>hide me</span>
|
||||
<input type=password>
|
||||
<input type=password readonly><span>hide me</span>
|
||||
<input type=email>
|
||||
<input type=email readonly><span>hide me</span>
|
||||
<textarea></textarea>
|
||||
<textarea readonly></textarea><span>hide me</span>
|
||||
</body>
|
||||
</html>
|
24
layout/reftests/editor/readwrite-non-editable.html
Normal file
24
layout/reftests/editor/readwrite-non-editable.html
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
:-moz-read-write + span {
|
||||
display: none;
|
||||
}
|
||||
span {
|
||||
color: transparent; /* workaround for bug 617524 */
|
||||
outline: 1px solid green;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<input><span>hide me</span>
|
||||
<input readonly><span>hide me</span>
|
||||
<input type=password><span>hide me</span>
|
||||
<input type=password readonly><span>hide me</span>
|
||||
<input type=email><span>hide me</span>
|
||||
<input type=email readonly><span>hide me</span>
|
||||
<textarea></textarea><span>hide me</span>
|
||||
<textarea readonly></textarea><span>hide me</span>
|
||||
</body>
|
||||
</html>
|
@ -69,4 +69,8 @@ skip-if(Android) == 674212-spellcheck.html 674212-spellcheck-ref.html
|
||||
skip-if(Android) == 338427-2.html 338427-2-ref.html
|
||||
skip-if(Android) == 338427-3.html 338427-3-ref.html
|
||||
skip-if(Android) == 462758-grabbers-resizers.html 462758-grabbers-resizers-ref.html
|
||||
== readwrite-non-editable.html readwrite-non-editable-ref.html
|
||||
== readwrite-editable.html readwrite-editable-ref.html
|
||||
== readonly-non-editable.html readonly-non-editable-ref.html
|
||||
== readonly-editable.html readonly-editable-ref.html
|
||||
== dynamic-overflow-change.html dynamic-overflow-change-ref.html
|
||||
|
@ -1362,17 +1362,19 @@ nsStyleSet::GCRuleTrees()
|
||||
}
|
||||
|
||||
static inline nsRuleNode*
|
||||
SkipTransitionRules(nsRuleNode* aRuleNode, Element* aElement, PRBool isPseudo)
|
||||
SkipAnimationRules(nsRuleNode* aRuleNode, Element* aElement, PRBool isPseudo)
|
||||
{
|
||||
nsRuleNode* ruleNode = aRuleNode;
|
||||
while (!ruleNode->IsRoot() &&
|
||||
ruleNode->GetLevel() == nsStyleSet::eTransitionSheet) {
|
||||
(ruleNode->GetLevel() == nsStyleSet::eTransitionSheet ||
|
||||
ruleNode->GetLevel() == nsStyleSet::eAnimationSheet)) {
|
||||
ruleNode = ruleNode->GetParent();
|
||||
}
|
||||
if (ruleNode != aRuleNode) {
|
||||
NS_ASSERTION(aElement, "How can we have transition rules but no element?");
|
||||
// Need to do an animation restyle, just like
|
||||
// nsTransitionManager::WalkTransitionRule would.
|
||||
// nsTransitionManager::WalkTransitionRule and
|
||||
// nsAnimationManager::GetAnimationRule would.
|
||||
nsRestyleHint hint = isPseudo ? eRestyle_Subtree : eRestyle_Self;
|
||||
aRuleNode->GetPresContext()->PresShell()->RestyleForAnimation(aElement,
|
||||
hint);
|
||||
@ -1403,16 +1405,16 @@ nsStyleSet::ReparentStyleContext(nsStyleContext* aStyleContext,
|
||||
|
||||
// Skip transition rules as needed just like
|
||||
// nsTransitionManager::WalkTransitionRule would.
|
||||
PRBool skipTransitionRules = PresContext()->IsProcessingRestyles() &&
|
||||
PRBool skipAnimationRules = PresContext()->IsProcessingRestyles() &&
|
||||
!PresContext()->IsProcessingAnimationStyleChange();
|
||||
if (skipTransitionRules) {
|
||||
// FIXME do something here for animations?
|
||||
// Make sure that we're not using transition rules for our new style
|
||||
// context. If we need them, an animation restyle will provide.
|
||||
if (skipAnimationRules) {
|
||||
// Make sure that we're not using transition rules or animation rules for
|
||||
// our new style context. If we need them, an animation restyle will
|
||||
// provide.
|
||||
ruleNode =
|
||||
SkipTransitionRules(ruleNode, aElement,
|
||||
pseudoType !=
|
||||
nsCSSPseudoElements::ePseudo_NotPseudoElement);
|
||||
SkipAnimationRules(ruleNode, aElement,
|
||||
pseudoType !=
|
||||
nsCSSPseudoElements::ePseudo_NotPseudoElement);
|
||||
}
|
||||
|
||||
nsRuleNode* visitedRuleNode = nsnull;
|
||||
@ -1424,12 +1426,12 @@ nsStyleSet::ReparentStyleContext(nsStyleContext* aStyleContext,
|
||||
if (visitedContext) {
|
||||
visitedRuleNode = visitedContext->GetRuleNode();
|
||||
// Again, skip transition rules as needed
|
||||
if (skipTransitionRules) {
|
||||
if (skipAnimationRules) {
|
||||
// FIXME do something here for animations?
|
||||
visitedRuleNode =
|
||||
SkipTransitionRules(visitedRuleNode, aElement,
|
||||
pseudoType !=
|
||||
nsCSSPseudoElements::ePseudo_NotPseudoElement);
|
||||
SkipAnimationRules(visitedRuleNode, aElement,
|
||||
pseudoType !=
|
||||
nsCSSPseudoElements::ePseudo_NotPseudoElement);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1219,6 +1219,39 @@ is(cs.marginTop, "40px",
|
||||
"rest of animation should still work when UA !important present at 200ms");
|
||||
done_div();
|
||||
|
||||
// Test interaction of animations and restyling (Bug 686656).
|
||||
// This test depends on kf3 getting its 0% and 100% values from the
|
||||
// rules below it in the cascade; we're checking that the animation
|
||||
// isn't rebuilt when the restyles happen.
|
||||
new_div("-moz-animation: kf3 1s linear forwards");
|
||||
is(cs.marginTop, "0px", "bug 686656 test 1 at 0ms");
|
||||
advance_clock(250);
|
||||
display.style.color = "blue";
|
||||
is(cs.marginTop, "100px", "bug 686656 test 1 at 250ms");
|
||||
advance_clock(375);
|
||||
is(cs.marginTop, "50px", "bug 686656 test 1 at 625ms");
|
||||
advance_clock(375);
|
||||
is(cs.marginTop, "0px", "bug 686656 test 1 at 1000ms");
|
||||
done_div();
|
||||
display.style.color = "";
|
||||
|
||||
// Test interaction of animations and restyling (Bug 686656),
|
||||
// with reframing.
|
||||
// This test depends on kf3 getting its 0% and 100% values from the
|
||||
// rules below it in the cascade; we're checking that the animation
|
||||
// isn't rebuilt when the restyles happen.
|
||||
new_div("-moz-animation: kf3 1s linear forwards");
|
||||
is(cs.marginTop, "0px", "bug 686656 test 2 at 0ms");
|
||||
advance_clock(250);
|
||||
display.style.overflow = "scroll";
|
||||
is(cs.marginTop, "100px", "bug 686656 test 2 at 250ms");
|
||||
advance_clock(375);
|
||||
is(cs.marginTop, "50px", "bug 686656 test 2 at 625ms");
|
||||
advance_clock(375);
|
||||
is(cs.marginTop, "0px", "bug 686656 test 2 at 1000ms");
|
||||
done_div();
|
||||
display.style.overflow = "";
|
||||
|
||||
SpecialPowers.DOMWindowUtils.restoreNormalRefresh();
|
||||
|
||||
</script>
|
||||
|
122
mobile/chrome/content/CharsetMenu.js
Normal file
122
mobile/chrome/content/CharsetMenu.js
Normal file
@ -0,0 +1,122 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Mobile Browser.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Wes Johnston <wjohnston@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 ***** */
|
||||
|
||||
var CharsetMenu = {
|
||||
_strings: null,
|
||||
_charsets: null,
|
||||
|
||||
get strings() {
|
||||
if (!this._strings)
|
||||
this._strings = Services.strings.createBundle("chrome://global/locale/charsetTitles.properties");
|
||||
return this._strings;
|
||||
},
|
||||
|
||||
init: function() {
|
||||
PageActions.register("pageaction-charset", this.updatePageAction, this);
|
||||
},
|
||||
|
||||
updatePageAction: function(aNode) {
|
||||
let pref = Services.prefs.getComplexValue("browser.menu.showCharacterEncoding", Ci.nsIPrefLocalizedString).data;
|
||||
if (pref == "true") {
|
||||
let charset = getBrowser().documentCharsetInfo.forcedCharset;
|
||||
if (charset) {
|
||||
charset = charset.toString();
|
||||
charset = charset.trim().toLowerCase();
|
||||
aNode.setAttribute("description", this.strings.GetStringFromName(charset + ".title"));
|
||||
} else if (aNode.hasAttribute("description")) {
|
||||
aNode.removeAttribute("description");
|
||||
}
|
||||
}
|
||||
return ("true" == pref)
|
||||
},
|
||||
|
||||
_toMenuItems: function(aCharsets, aCurrent) {
|
||||
let ret = [];
|
||||
aCharsets.forEach(function (aSet) {
|
||||
try {
|
||||
let string = aSet.trim().toLowerCase();
|
||||
ret.push({
|
||||
label: this.strings.GetStringFromName(string + ".title"),
|
||||
value: string,
|
||||
selected: (string == aCurrent)
|
||||
});
|
||||
} catch(ex) { }
|
||||
}, this);
|
||||
return ret;
|
||||
},
|
||||
|
||||
menu : {
|
||||
dispatchEvent: function(aEvent) {
|
||||
if (aEvent.type == "command")
|
||||
CharsetMenu.setCharset(this.menupopup.children[this.selectedIndex].value);
|
||||
},
|
||||
menupopup: {
|
||||
hasAttribute: function(aAttr) { return false; },
|
||||
},
|
||||
selectedIndex: -1
|
||||
},
|
||||
|
||||
get charsets() {
|
||||
if (!this._charsets) {
|
||||
this._charsets = Services.prefs.getComplexValue("intl.charsetmenu.browser.static", Ci.nsIPrefLocalizedString).data.split(",");
|
||||
}
|
||||
let charsets = this._charsets;
|
||||
let currentCharset = getBrowser().documentCharsetInfo.forcedCharset;
|
||||
|
||||
if (currentCharset) {
|
||||
currentCharset = currentCharset.toString();
|
||||
currentCharset = currentCharset.trim().toLowerCase();
|
||||
if (charsets.indexOf(currentCharset) == -1)
|
||||
charsets.splice(0, 0, currentCharset);
|
||||
}
|
||||
return this._toMenuItems(charsets, currentCharset);
|
||||
},
|
||||
|
||||
show: function showCharsetMenu() {
|
||||
this.menu.menupopup.children = this.charsets;
|
||||
MenuListHelperUI.show(this.menu);
|
||||
},
|
||||
|
||||
setCharset: function setCharset(aCharset) {
|
||||
let browser = getBrowser();
|
||||
browser.messageManager.sendAsyncMessage("Browser:SetCharset", {
|
||||
charset: aCharset
|
||||
});
|
||||
let history = Cc["@mozilla.org/browser/nav-history-service;1"].getService(Ci.nsINavHistoryService);
|
||||
history.setCharsetForURI(browser.documentURI, aCharset);
|
||||
}
|
||||
};
|
273
mobile/chrome/content/PageActions.js
Normal file
273
mobile/chrome/content/PageActions.js
Normal file
@ -0,0 +1,273 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Mobile Browser.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Matt Brubeck <mbrubeck@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 ***** */
|
||||
|
||||
var PageActions = {
|
||||
_handlers: null,
|
||||
|
||||
init: function init() {
|
||||
if (this._handlers)
|
||||
return;
|
||||
|
||||
this._handlers = [];
|
||||
document.getElementById("pageactions-container").addEventListener("click", this, true);
|
||||
|
||||
this.register("pageaction-reset", this.updatePagePermissions, this);
|
||||
this.register("pageaction-password", this.updateForgetPassword, this);
|
||||
#ifdef NS_PRINTING
|
||||
this.register("pageaction-saveas", this.updatePageSaveAs, this);
|
||||
#endif
|
||||
this.register("pageaction-share", this.updateShare, this);
|
||||
this.register("pageaction-search", BrowserSearch.updatePageSearchEngines, BrowserSearch);
|
||||
this.register("pageaction-webapps-install", WebappsUI.updateWebappsInstall, WebappsUI);
|
||||
|
||||
CharsetMenu.init();
|
||||
},
|
||||
|
||||
handleEvent: function handleEvent(aEvent) {
|
||||
switch (aEvent.type) {
|
||||
case "click":
|
||||
getIdentityHandler().hide();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @param aId id of a pageaction element
|
||||
* @param aCallback function that takes an element and returns true if it should be visible
|
||||
* @param aThisObj (optional) scope object for aCallback
|
||||
*/
|
||||
register: function register(aId, aCallback, aThisObj) {
|
||||
this._handlers.push({id: aId, callback: aCallback, obj: aThisObj});
|
||||
},
|
||||
|
||||
updateSiteMenu: function updateSiteMenu() {
|
||||
this.init();
|
||||
this._handlers.forEach(function(action) {
|
||||
let node = document.getElementById(action.id);
|
||||
if (node)
|
||||
node.hidden = !action.callback.call(action.obj, node);
|
||||
});
|
||||
this._updateAttributes();
|
||||
},
|
||||
|
||||
get _loginManager() {
|
||||
delete this._loginManager;
|
||||
return this._loginManager = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
|
||||
},
|
||||
|
||||
// Permissions we track in Page Actions
|
||||
_permissions: ["popup", "offline-app", "geolocation", "desktop-notification"],
|
||||
|
||||
_forEachPermissions: function _forEachPermissions(aHost, aCallback) {
|
||||
let pm = Services.perms;
|
||||
for (let i = 0; i < this._permissions.length; i++) {
|
||||
let type = this._permissions[i];
|
||||
if (!pm.testPermission(aHost, type))
|
||||
continue;
|
||||
|
||||
let perms = pm.enumerator;
|
||||
while (perms.hasMoreElements()) {
|
||||
let permission = perms.getNext().QueryInterface(Ci.nsIPermission);
|
||||
if (permission.host == aHost.asciiHost && permission.type == type)
|
||||
aCallback(type);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
updatePagePermissions: function updatePagePermissions(aNode) {
|
||||
let host = Browser.selectedBrowser.currentURI;
|
||||
let permissions = [];
|
||||
|
||||
this._forEachPermissions(host, function(aType) {
|
||||
permissions.push("pageactions." + aType);
|
||||
});
|
||||
|
||||
if (!this._loginManager.getLoginSavingEnabled(host.prePath)) {
|
||||
// If rememberSignons is false, then getLoginSavingEnabled returns false
|
||||
// for all pages, so we should just ignore it (Bug 601163).
|
||||
if (Services.prefs.getBoolPref("signon.rememberSignons"))
|
||||
permissions.push("pageactions.password");
|
||||
}
|
||||
|
||||
let descriptions = permissions.map(function(s) Strings.browser.GetStringFromName(s));
|
||||
aNode.setAttribute("description", descriptions.join(", "));
|
||||
|
||||
return (permissions.length > 0);
|
||||
},
|
||||
|
||||
updateForgetPassword: function updateForgetPassword(aNode) {
|
||||
let host = Browser.selectedBrowser.currentURI;
|
||||
let logins = this._loginManager.findLogins({}, host.prePath, "", "");
|
||||
|
||||
return logins.some(function(login) login.hostname == host.prePath);
|
||||
},
|
||||
|
||||
forgetPassword: function forgetPassword(aEvent) {
|
||||
let host = Browser.selectedBrowser.currentURI;
|
||||
let lm = this._loginManager;
|
||||
|
||||
lm.findLogins({}, host.prePath, "", "").forEach(function(login) {
|
||||
if (login.hostname == host.prePath)
|
||||
lm.removeLogin(login);
|
||||
});
|
||||
|
||||
this.hideItem(aEvent.target);
|
||||
aEvent.stopPropagation(); // Don't hide the site menu.
|
||||
},
|
||||
|
||||
clearPagePermissions: function clearPagePermissions(aEvent) {
|
||||
let pm = Services.perms;
|
||||
let host = Browser.selectedBrowser.currentURI;
|
||||
this._forEachPermissions(host, function(aType) {
|
||||
pm.remove(host.asciiHost, aType);
|
||||
|
||||
// reset the 'remember' counter for permissions that support it
|
||||
if (["geolocation", "desktop-notification"].indexOf(aType) != -1)
|
||||
Services.contentPrefs.setPref(host.asciiHost, aType + ".request.remember", 0);
|
||||
});
|
||||
|
||||
let lm = this._loginManager;
|
||||
if (!lm.getLoginSavingEnabled(host.prePath))
|
||||
lm.setLoginSavingEnabled(host.prePath, true);
|
||||
|
||||
this.hideItem(aEvent.target);
|
||||
aEvent.stopPropagation(); // Don't hide the site menu.
|
||||
},
|
||||
|
||||
savePageAsPDF: function saveAsPDF() {
|
||||
let browser = Browser.selectedBrowser;
|
||||
let fileName = ContentAreaUtils.getDefaultFileName(browser.contentTitle, browser.documentURI, null, null);
|
||||
fileName = fileName.trim() + ".pdf";
|
||||
|
||||
let dm = Cc["@mozilla.org/download-manager;1"].getService(Ci.nsIDownloadManager);
|
||||
let downloadsDir = dm.defaultDownloadsDirectory;
|
||||
|
||||
#ifdef ANDROID
|
||||
// Create the final destination file location
|
||||
let file = downloadsDir.clone();
|
||||
file.append(fileName);
|
||||
file.createUnique(file.NORMAL_FILE_TYPE, 0666);
|
||||
#else
|
||||
let picker = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
|
||||
picker.init(window, Strings.browser.GetStringFromName("pageactions.saveas.pdf"), Ci.nsIFilePicker.modeSave);
|
||||
picker.appendFilter("PDF", "*.pdf");
|
||||
picker.defaultExtension = "pdf";
|
||||
|
||||
picker.defaultString = fileName;
|
||||
|
||||
picker.displayDirectory = downloadsDir;
|
||||
let rv = picker.show();
|
||||
if (rv == Ci.nsIFilePicker.returnCancel)
|
||||
return;
|
||||
|
||||
let file = picker.file;
|
||||
#endif
|
||||
fileName = file.leafName;
|
||||
|
||||
// We must manually add this to the download system
|
||||
let db = dm.DBConnection;
|
||||
|
||||
let stmt = db.createStatement(
|
||||
"INSERT INTO moz_downloads (name, source, target, startTime, endTime, state, referrer) " +
|
||||
"VALUES (:name, :source, :target, :startTime, :endTime, :state, :referrer)"
|
||||
);
|
||||
|
||||
let current = browser.currentURI.spec;
|
||||
stmt.params.name = fileName;
|
||||
stmt.params.source = current;
|
||||
stmt.params.target = Services.io.newFileURI(file).spec;
|
||||
stmt.params.startTime = Date.now() * 1000;
|
||||
stmt.params.endTime = Date.now() * 1000;
|
||||
stmt.params.state = Ci.nsIDownloadManager.DOWNLOAD_NOTSTARTED;
|
||||
stmt.params.referrer = current;
|
||||
stmt.execute();
|
||||
stmt.finalize();
|
||||
|
||||
let newItemId = db.lastInsertRowID;
|
||||
let download = dm.getDownload(newItemId);
|
||||
try {
|
||||
DownloadsView.downloadStarted(download);
|
||||
}
|
||||
catch(e) {}
|
||||
Services.obs.notifyObservers(download, "dl-start", null);
|
||||
|
||||
#ifdef ANDROID
|
||||
let tmpDir = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties).get("TmpD", Ci.nsIFile);
|
||||
|
||||
file = tmpDir.clone();
|
||||
file.append(fileName);
|
||||
|
||||
#endif
|
||||
|
||||
let data = {
|
||||
type: Ci.nsIPrintSettings.kOutputFormatPDF,
|
||||
id: newItemId,
|
||||
referrer: current,
|
||||
filePath: file.path
|
||||
};
|
||||
|
||||
Browser.selectedBrowser.messageManager.sendAsyncMessage("Browser:SaveAs", data);
|
||||
},
|
||||
|
||||
updatePageSaveAs: function updatePageSaveAs(aNode) {
|
||||
// Check for local XUL content
|
||||
let contentWindow = Browser.selectedBrowser.contentWindow;
|
||||
return !(contentWindow && contentWindow.document instanceof XULDocument);
|
||||
},
|
||||
|
||||
updateShare: function updateShare(aNode) {
|
||||
return Util.isShareableScheme(Browser.selectedBrowser.currentURI.scheme);
|
||||
},
|
||||
|
||||
hideItem: function hideItem(aNode) {
|
||||
aNode.hidden = true;
|
||||
this._updateAttributes();
|
||||
},
|
||||
|
||||
_updateAttributes: function _updateAttributes() {
|
||||
let container = document.getElementById("pageactions-container");
|
||||
let visibleNodes = container.querySelectorAll("pageaction:not([hidden=true])");
|
||||
let visibleCount = visibleNodes.length;
|
||||
|
||||
for (let i = 0; i < visibleCount; i++)
|
||||
visibleNodes[i].classList.remove("odd-last-child");
|
||||
|
||||
visibleNodes[visibleCount - 1].classList.add("last-child");
|
||||
if (visibleCount % 2)
|
||||
visibleNodes[visibleCount - 1].classList.add("odd");
|
||||
}
|
||||
};
|
202
mobile/chrome/content/SelectionHelper.js
Normal file
202
mobile/chrome/content/SelectionHelper.js
Normal file
@ -0,0 +1,202 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Mobile Browser.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mark Finkle <mfinkle@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 ***** */
|
||||
|
||||
var SelectionHelper = {
|
||||
enabled: true,
|
||||
popupState: null,
|
||||
target: null,
|
||||
deltaX: -1,
|
||||
deltaY: -1,
|
||||
|
||||
get _start() {
|
||||
delete this._start;
|
||||
return this._start = document.getElementById("selectionhandle-start");
|
||||
},
|
||||
|
||||
get _end() {
|
||||
delete this._end;
|
||||
return this._end = document.getElementById("selectionhandle-end");
|
||||
},
|
||||
|
||||
showPopup: function sh_showPopup(aMessage) {
|
||||
if (!this.enabled || aMessage.json.types.indexOf("content-text") == -1)
|
||||
return false;
|
||||
|
||||
this.popupState = aMessage.json;
|
||||
this.popupState.target = aMessage.target;
|
||||
|
||||
this._start.customDragger = {
|
||||
isDraggable: function isDraggable(target, content) { return { x: true, y: false }; },
|
||||
dragStart: function dragStart(cx, cy, target, scroller) {},
|
||||
dragStop: function dragStop(dx, dy, scroller) { return false; },
|
||||
dragMove: function dragMove(dx, dy, scroller) { return false; }
|
||||
};
|
||||
|
||||
this._end.customDragger = {
|
||||
isDraggable: function isDraggable(target, content) { return { x: true, y: false }; },
|
||||
dragStart: function dragStart(cx, cy, target, scroller) {},
|
||||
dragStop: function dragStop(dx, dy, scroller) { return false; },
|
||||
dragMove: function dragMove(dx, dy, scroller) { return false; }
|
||||
};
|
||||
|
||||
this._start.addEventListener("TapUp", this, true);
|
||||
this._end.addEventListener("TapUp", this, true);
|
||||
|
||||
messageManager.addMessageListener("Browser:SelectionRange", this);
|
||||
messageManager.addMessageListener("Browser:SelectionCopied", this);
|
||||
|
||||
this.popupState.target.messageManager.sendAsyncMessage("Browser:SelectionStart", { x: this.popupState.x, y: this.popupState.y });
|
||||
|
||||
// Hide the selection handles
|
||||
window.addEventListener("TapDown", this, true);
|
||||
window.addEventListener("resize", this, true);
|
||||
window.addEventListener("keypress", this, true);
|
||||
Elements.browsers.addEventListener("URLChanged", this, true);
|
||||
Elements.browsers.addEventListener("SizeChanged", this, true);
|
||||
Elements.browsers.addEventListener("ZoomChanged", this, true);
|
||||
|
||||
let event = document.createEvent("Events");
|
||||
event.initEvent("CancelTouchSequence", true, false);
|
||||
this.popupState.target.dispatchEvent(event);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
hide: function sh_hide(aEvent) {
|
||||
if (this._start.hidden)
|
||||
return;
|
||||
|
||||
let pos = this.popupState.target.transformClientToBrowser(aEvent.clientX || 0, aEvent.clientY || 0);
|
||||
let json = {
|
||||
x: pos.x,
|
||||
y: pos.y
|
||||
};
|
||||
|
||||
try {
|
||||
this.popupState.target.messageManager.sendAsyncMessage("Browser:SelectionEnd", json);
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
|
||||
this.popupState = null;
|
||||
|
||||
this._start.hidden = true;
|
||||
this._end.hidden = true;
|
||||
|
||||
this._start.removeEventListener("TapUp", this, true);
|
||||
this._end.removeEventListener("TapUp", this, true);
|
||||
|
||||
messageManager.removeMessageListener("Browser:SelectionRange", this);
|
||||
|
||||
window.removeEventListener("TapDown", this, true);
|
||||
window.removeEventListener("resize", this, true);
|
||||
window.removeEventListener("keypress", this, true);
|
||||
Elements.browsers.removeEventListener("URLChanged", this, true);
|
||||
Elements.browsers.removeEventListener("SizeChanged", this, true);
|
||||
Elements.browsers.removeEventListener("ZoomChanged", this, true);
|
||||
},
|
||||
|
||||
handleEvent: function handleEvent(aEvent) {
|
||||
switch (aEvent.type) {
|
||||
case "TapDown":
|
||||
if (aEvent.target == this._start || aEvent.target == this._end) {
|
||||
this.target = aEvent.target;
|
||||
this.deltaX = (aEvent.clientX - this.target.left);
|
||||
this.deltaY = (aEvent.clientY - this.target.top);
|
||||
window.addEventListener("TapMove", this, true);
|
||||
} else {
|
||||
this.hide(aEvent);
|
||||
}
|
||||
break;
|
||||
case "TapUp":
|
||||
window.removeEventListener("TapMove", this, true);
|
||||
this.target = null;
|
||||
this.deltaX = -1;
|
||||
this.deltaY = -1;
|
||||
break;
|
||||
case "TapMove":
|
||||
if (this.target) {
|
||||
this.target.left = aEvent.clientX - this.deltaX;
|
||||
this.target.top = aEvent.clientY - this.deltaY;
|
||||
let rect = this.target.getBoundingClientRect();
|
||||
let data = this.target == this._start ? { x: rect.right, y: rect.top, type: "start" } : { x: rect.left, y: rect.top, type: "end" };
|
||||
let pos = this.popupState.target.transformClientToBrowser(data.x || 0, data.y || 0);
|
||||
let json = {
|
||||
type: data.type,
|
||||
x: pos.x,
|
||||
y: pos.y
|
||||
};
|
||||
this.popupState.target.messageManager.sendAsyncMessage("Browser:SelectionMove", json);
|
||||
}
|
||||
break;
|
||||
case "resize":
|
||||
case "SizeChanged":
|
||||
case "ZoomChanged":
|
||||
case "URLChanged":
|
||||
case "keypress":
|
||||
this.hide(aEvent);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
receiveMessage: function sh_receiveMessage(aMessage) {
|
||||
let json = aMessage.json;
|
||||
switch (aMessage.name) {
|
||||
case "Browser:SelectionRange": {
|
||||
let pos = this.popupState.target.transformBrowserToClient(json.start.x || 0, json.start.y || 0);
|
||||
this._start.left = pos.x - 32;
|
||||
this._start.top = pos.y + this.deltaY;
|
||||
this._start.hidden = false;
|
||||
|
||||
pos = this.popupState.target.transformBrowserToClient(json.end.x || 0, json.end.y || 0);
|
||||
this._end.left = pos.x;
|
||||
this._end.top = pos.y;
|
||||
this._end.hidden = false;
|
||||
break;
|
||||
}
|
||||
|
||||
case "Browser:SelectionCopied": {
|
||||
messageManager.removeMessageListener("Browser:SelectionCopied", this);
|
||||
if (json.succeeded) {
|
||||
let toaster = Cc["@mozilla.org/toaster-alerts-service;1"].getService(Ci.nsIAlertsService);
|
||||
toaster.showAlertNotification(null, Strings.browser.GetStringFromName("selectionHelper.textCopied"), "", false, "", null);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
173
mobile/chrome/content/WebappsUI.js
Normal file
173
mobile/chrome/content/WebappsUI.js
Normal file
@ -0,0 +1,173 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Mobile Browser.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Fabrice Desré <fabrice@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 ***** */
|
||||
|
||||
var WebappsUI = {
|
||||
_dialog: null,
|
||||
_manifest: null,
|
||||
_perms: [],
|
||||
|
||||
checkBox: function(aEvent) {
|
||||
let elem = aEvent.originalTarget;
|
||||
let perm = elem.getAttribute("perm");
|
||||
if (this._manifest.capabilities && this._manifest.capabilities.indexOf(perm) != -1) {
|
||||
if (elem.checked) {
|
||||
elem.classList.remove("webapps-noperm");
|
||||
elem.classList.add("webapps-perm");
|
||||
} else {
|
||||
elem.classList.remove("webapps-perm");
|
||||
elem.classList.add("webapps-noperm");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
show: function show(aManifest) {
|
||||
if (!aManifest) {
|
||||
// Try every way to get an icon
|
||||
let browser = Browser.selectedBrowser;
|
||||
let icon = browser.appIcon.href;
|
||||
if (!icon)
|
||||
icon = browser.mIconURL;
|
||||
if (!icon)
|
||||
icon = gFaviconService.getFaviconImageForPage(browser.currentURI).spec;
|
||||
|
||||
// Create a simple manifest
|
||||
aManifest = {
|
||||
uri: browser.currentURI.spec,
|
||||
name: browser.contentTitle,
|
||||
icon: icon,
|
||||
capabilities: [],
|
||||
};
|
||||
}
|
||||
|
||||
this._manifest = aManifest;
|
||||
this._dialog = importDialog(window, "chrome://browser/content/webapps.xul", null);
|
||||
|
||||
if (aManifest.name)
|
||||
document.getElementById("webapps-title").value = aManifest.name;
|
||||
if (aManifest.icon)
|
||||
document.getElementById("webapps-icon").src = aManifest.icon;
|
||||
|
||||
let uri = Services.io.newURI(aManifest.uri, null, null);
|
||||
|
||||
let perms = [["offline", "offline-app"], ["geoloc", "geo"], ["notifications", "desktop-notification"]];
|
||||
let self = this;
|
||||
perms.forEach(function(tuple) {
|
||||
let elem = document.getElementById("webapps-" + tuple[0] + "-checkbox");
|
||||
let currentPerm = Services.perms.testExactPermission(uri, tuple[1]);
|
||||
self._perms[tuple[1]] = (currentPerm == Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
if ((aManifest.capabilities && (aManifest.capabilities.indexOf(tuple[1]) != -1)) || (currentPerm == Ci.nsIPermissionManager.ALLOW_ACTION))
|
||||
elem.checked = true;
|
||||
else
|
||||
elem.checked = (currentPerm == Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
elem.classList.remove("webapps-noperm");
|
||||
elem.classList.add("webapps-perm");
|
||||
});
|
||||
|
||||
BrowserUI.pushPopup(this, this._dialog);
|
||||
|
||||
// Force a modal dialog
|
||||
this._dialog.waitForClose();
|
||||
},
|
||||
|
||||
hide: function hide() {
|
||||
this._dialog.close();
|
||||
this._dialog = null;
|
||||
BrowserUI.popPopup(this);
|
||||
},
|
||||
|
||||
_updatePermission: function updatePermission(aId, aPerm) {
|
||||
try {
|
||||
let uri = Services.io.newURI(this._manifest.uri, null, null);
|
||||
let currentState = document.getElementById(aId).checked;
|
||||
if (currentState != this._perms[aPerm])
|
||||
Services.perms.add(uri, aPerm, currentState ? Ci.nsIPermissionManager.ALLOW_ACTION : Ci.nsIPermissionManager.DENY_ACTION);
|
||||
} catch(e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
},
|
||||
|
||||
launch: function launch() {
|
||||
let title = document.getElementById("webapps-title").value;
|
||||
if (!title)
|
||||
return;
|
||||
|
||||
this._updatePermission("webapps-offline-checkbox", "offline-app");
|
||||
this._updatePermission("webapps-geoloc-checkbox", "geo");
|
||||
this._updatePermission("webapps-notifications-checkbox", "desktop-notification");
|
||||
|
||||
this.hide();
|
||||
this.install(this._manifest.uri, title, this._manifest.icon);
|
||||
},
|
||||
|
||||
updateWebappsInstall: function updateWebappsInstall(aNode) {
|
||||
if (document.getElementById("main-window").hasAttribute("webapp"))
|
||||
return false;
|
||||
|
||||
let browser = Browser.selectedBrowser;
|
||||
|
||||
let webapp = Cc["@mozilla.org/webapps/support;1"].getService(Ci.nsIWebappsSupport);
|
||||
return !(webapp && webapp.isApplicationInstalled(browser.currentURI.spec));
|
||||
},
|
||||
|
||||
install: function(aURI, aTitle, aIcon) {
|
||||
const kIconSize = 64;
|
||||
|
||||
let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
||||
canvas.setAttribute("style", "display: none");
|
||||
|
||||
let self = this;
|
||||
let image = new Image();
|
||||
image.onload = function() {
|
||||
canvas.width = canvas.height = kIconSize; // clears the canvas
|
||||
let ctx = canvas.getContext("2d");
|
||||
ctx.drawImage(image, 0, 0, kIconSize, kIconSize);
|
||||
let data = canvas.toDataURL("image/png", "");
|
||||
canvas = null;
|
||||
try {
|
||||
let webapp = Cc["@mozilla.org/webapps/support;1"].getService(Ci.nsIWebappsSupport);
|
||||
webapp.installApplication(aTitle, aURI, aIcon, data);
|
||||
} catch(e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
}
|
||||
image.onerror = function() {
|
||||
// can't load the icon (bad URI) : fallback to the default one from chrome
|
||||
self.install(aURI, aTitle, "chrome://browser/skin/images/favicon-default-30.png");
|
||||
}
|
||||
image.src = aIcon;
|
||||
}
|
||||
};
|
@ -69,16 +69,12 @@ XPCOMUtils.defineLazyGetter(this, "CommonUI", function() {
|
||||
|
||||
[
|
||||
["FullScreenVideo"],
|
||||
["WebappsUI"],
|
||||
["BadgeHandlers"],
|
||||
["ContextHelper"],
|
||||
["SelectionHelper"],
|
||||
["FormHelperUI"],
|
||||
["FindHelperUI"],
|
||||
["NewTabPopup"],
|
||||
["PageActions"],
|
||||
["BrowserSearch"],
|
||||
["CharsetMenu"]
|
||||
].forEach(function (aObject) {
|
||||
XPCOMUtils.defineLazyGetter(window, aObject, function() {
|
||||
return CommonUI[aObject];
|
||||
@ -96,6 +92,7 @@ XPCOMUtils.defineLazyGetter(this, "CommonUI", function() {
|
||||
["AwesomeScreen", "chrome://browser/content/AwesomePanel.js"],
|
||||
["BookmarkHelper", "chrome://browser/content/BookmarkHelper.js"],
|
||||
["BookmarkPopup", "chrome://browser/content/BookmarkPopup.js"],
|
||||
["CharsetMenu", "chrome://browser/content/CharsetMenu.js"],
|
||||
["CommandUpdater", "chrome://browser/content/commandUtil.js"],
|
||||
["ContextCommands", "chrome://browser/content/ContextCommands.js"],
|
||||
["ConsoleView", "chrome://browser/content/console.js"],
|
||||
@ -104,9 +101,11 @@ XPCOMUtils.defineLazyGetter(this, "CommonUI", function() {
|
||||
["MenuListHelperUI", "chrome://browser/content/MenuListHelperUI.js"],
|
||||
["OfflineApps", "chrome://browser/content/OfflineApps.js"],
|
||||
["IndexedDB", "chrome://browser/content/IndexedDB.js"],
|
||||
["PageActions", "chrome://browser/content/PageActions.js"],
|
||||
["PreferencesView", "chrome://browser/content/preferences.js"],
|
||||
["Sanitizer", "chrome://browser/content/sanitize.js"],
|
||||
["SelectHelperUI", "chrome://browser/content/SelectHelperUI.js"],
|
||||
["SelectionHelper", "chrome://browser/content/SelectionHelper.js"],
|
||||
["ContentPopupHelper", "chrome://browser/content/ContentPopupHelper.js"],
|
||||
["SharingUI", "chrome://browser/content/SharingUI.js"],
|
||||
["TabsPopup", "chrome://browser/content/TabsPopup.js"],
|
||||
@ -114,6 +113,7 @@ XPCOMUtils.defineLazyGetter(this, "CommonUI", function() {
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
["WeaveGlue", "chrome://browser/content/sync.js"],
|
||||
#endif
|
||||
["WebappsUI", "chrome://browser/content/WebappsUI.js"],
|
||||
["SSLExceptions", "chrome://browser/content/exceptions.js"]
|
||||
].forEach(function (aScript) {
|
||||
let [name, script] = aScript;
|
||||
|
@ -494,10 +494,8 @@ var BrowserUI = {
|
||||
BadgeHandlers.register(BrowserUI._edit.popup);
|
||||
FormHelperUI.init();
|
||||
FindHelperUI.init();
|
||||
PageActions.init();
|
||||
FullScreenVideo.init();
|
||||
NewTabPopup.init();
|
||||
CharsetMenu.init();
|
||||
|
||||
// If some add-ons were disabled during during an application update, alert user
|
||||
let addonIDs = AddonManager.getStartupChanges("disabled");
|
||||
|
@ -586,7 +586,7 @@
|
||||
<separator flex="1"/>
|
||||
</scrollbox>
|
||||
<hbox class="prompt-buttons" pack="center">
|
||||
<button oncommand="WeaveGlue.close();">&sync.setup.cancel;</button>
|
||||
<button class="prompt-button" oncommand="WeaveGlue.close();">&sync.setup.cancel;</button>
|
||||
</hbox>
|
||||
</vbox>
|
||||
<vbox id="syncsetup-fallback" class="syncsetup-page" flex="1" hidden="true">
|
||||
@ -605,9 +605,9 @@
|
||||
<separator flex="1"/>
|
||||
</scrollbox>
|
||||
<hbox class="prompt-buttons" pack="center">
|
||||
<button oncommand="WeaveGlue.close();">&sync.setup.cancel;</button>
|
||||
<button class="prompt-button" oncommand="WeaveGlue.close();">&sync.setup.cancel;</button>
|
||||
<separator/>
|
||||
<button id="syncsetup-button-connect" oncommand="WeaveGlue.close(); WeaveGlue.connect();">&sync.setup.connect;</button>
|
||||
<button id="syncsetup-button-connect" class="prompt-button" oncommand="WeaveGlue.close(); WeaveGlue.connect();">&sync.setup.connect;</button>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</dialog>
|
||||
|
@ -169,236 +169,6 @@ var BrowserSearch = {
|
||||
}
|
||||
};
|
||||
|
||||
var PageActions = {
|
||||
init: function init() {
|
||||
document.getElementById("pageactions-container").addEventListener("click", this, true);
|
||||
|
||||
this.register("pageaction-reset", this.updatePagePermissions, this);
|
||||
this.register("pageaction-password", this.updateForgetPassword, this);
|
||||
#ifdef NS_PRINTING
|
||||
this.register("pageaction-saveas", this.updatePageSaveAs, this);
|
||||
#endif
|
||||
this.register("pageaction-share", this.updateShare, this);
|
||||
this.register("pageaction-search", BrowserSearch.updatePageSearchEngines, BrowserSearch);
|
||||
this.register("pageaction-webapps-install", WebappsUI.updateWebappsInstall, WebappsUI);
|
||||
},
|
||||
|
||||
handleEvent: function handleEvent(aEvent) {
|
||||
switch (aEvent.type) {
|
||||
case "click":
|
||||
getIdentityHandler().hide();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @param aId id of a pageaction element
|
||||
* @param aCallback function that takes an element and returns true if it should be visible
|
||||
* @param aThisObj (optional) scope object for aCallback
|
||||
*/
|
||||
register: function register(aId, aCallback, aThisObj) {
|
||||
this._handlers.push({id: aId, callback: aCallback, obj: aThisObj});
|
||||
},
|
||||
|
||||
_handlers: [],
|
||||
|
||||
updateSiteMenu: function updateSiteMenu() {
|
||||
this._handlers.forEach(function(action) {
|
||||
let node = document.getElementById(action.id);
|
||||
if (node)
|
||||
node.hidden = !action.callback.call(action.obj, node);
|
||||
});
|
||||
this._updateAttributes();
|
||||
},
|
||||
|
||||
get _loginManager() {
|
||||
delete this._loginManager;
|
||||
return this._loginManager = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
|
||||
},
|
||||
|
||||
// Permissions we track in Page Actions
|
||||
_permissions: ["popup", "offline-app", "geolocation", "desktop-notification"],
|
||||
|
||||
_forEachPermissions: function _forEachPermissions(aHost, aCallback) {
|
||||
let pm = Services.perms;
|
||||
for (let i = 0; i < this._permissions.length; i++) {
|
||||
let type = this._permissions[i];
|
||||
if (!pm.testPermission(aHost, type))
|
||||
continue;
|
||||
|
||||
let perms = pm.enumerator;
|
||||
while (perms.hasMoreElements()) {
|
||||
let permission = perms.getNext().QueryInterface(Ci.nsIPermission);
|
||||
if (permission.host == aHost.asciiHost && permission.type == type)
|
||||
aCallback(type);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
updatePagePermissions: function updatePagePermissions(aNode) {
|
||||
let host = Browser.selectedBrowser.currentURI;
|
||||
let permissions = [];
|
||||
|
||||
this._forEachPermissions(host, function(aType) {
|
||||
permissions.push("pageactions." + aType);
|
||||
});
|
||||
|
||||
if (!this._loginManager.getLoginSavingEnabled(host.prePath)) {
|
||||
// If rememberSignons is false, then getLoginSavingEnabled returns false
|
||||
// for all pages, so we should just ignore it (Bug 601163).
|
||||
if (Services.prefs.getBoolPref("signon.rememberSignons"))
|
||||
permissions.push("pageactions.password");
|
||||
}
|
||||
|
||||
let descriptions = permissions.map(function(s) Strings.browser.GetStringFromName(s));
|
||||
aNode.setAttribute("description", descriptions.join(", "));
|
||||
|
||||
return (permissions.length > 0);
|
||||
},
|
||||
|
||||
updateForgetPassword: function updateForgetPassword(aNode) {
|
||||
let host = Browser.selectedBrowser.currentURI;
|
||||
let logins = this._loginManager.findLogins({}, host.prePath, "", "");
|
||||
|
||||
return logins.some(function(login) login.hostname == host.prePath);
|
||||
},
|
||||
|
||||
forgetPassword: function forgetPassword(aEvent) {
|
||||
let host = Browser.selectedBrowser.currentURI;
|
||||
let lm = this._loginManager;
|
||||
|
||||
lm.findLogins({}, host.prePath, "", "").forEach(function(login) {
|
||||
if (login.hostname == host.prePath)
|
||||
lm.removeLogin(login);
|
||||
});
|
||||
|
||||
this.hideItem(aEvent.target);
|
||||
aEvent.stopPropagation(); // Don't hide the site menu.
|
||||
},
|
||||
|
||||
clearPagePermissions: function clearPagePermissions(aEvent) {
|
||||
let pm = Services.perms;
|
||||
let host = Browser.selectedBrowser.currentURI;
|
||||
this._forEachPermissions(host, function(aType) {
|
||||
pm.remove(host.asciiHost, aType);
|
||||
|
||||
// reset the 'remember' counter for permissions that support it
|
||||
if (["geolocation", "desktop-notification"].indexOf(aType) != -1)
|
||||
Services.contentPrefs.setPref(host.asciiHost, aType + ".request.remember", 0);
|
||||
});
|
||||
|
||||
let lm = this._loginManager;
|
||||
if (!lm.getLoginSavingEnabled(host.prePath))
|
||||
lm.setLoginSavingEnabled(host.prePath, true);
|
||||
|
||||
this.hideItem(aEvent.target);
|
||||
aEvent.stopPropagation(); // Don't hide the site menu.
|
||||
},
|
||||
|
||||
savePageAsPDF: function saveAsPDF() {
|
||||
let browser = Browser.selectedBrowser;
|
||||
let fileName = ContentAreaUtils.getDefaultFileName(browser.contentTitle, browser.documentURI, null, null);
|
||||
fileName = fileName.trim() + ".pdf";
|
||||
|
||||
let dm = Cc["@mozilla.org/download-manager;1"].getService(Ci.nsIDownloadManager);
|
||||
let downloadsDir = dm.defaultDownloadsDirectory;
|
||||
|
||||
#ifdef ANDROID
|
||||
// Create the final destination file location
|
||||
let file = downloadsDir.clone();
|
||||
file.append(fileName);
|
||||
file.createUnique(file.NORMAL_FILE_TYPE, 0666);
|
||||
#else
|
||||
let picker = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
|
||||
picker.init(window, Strings.browser.GetStringFromName("pageactions.saveas.pdf"), Ci.nsIFilePicker.modeSave);
|
||||
picker.appendFilter("PDF", "*.pdf");
|
||||
picker.defaultExtension = "pdf";
|
||||
|
||||
picker.defaultString = fileName;
|
||||
|
||||
picker.displayDirectory = downloadsDir;
|
||||
let rv = picker.show();
|
||||
if (rv == Ci.nsIFilePicker.returnCancel)
|
||||
return;
|
||||
|
||||
let file = picker.file;
|
||||
#endif
|
||||
fileName = file.leafName;
|
||||
|
||||
// We must manually add this to the download system
|
||||
let db = dm.DBConnection;
|
||||
|
||||
let stmt = db.createStatement(
|
||||
"INSERT INTO moz_downloads (name, source, target, startTime, endTime, state, referrer) " +
|
||||
"VALUES (:name, :source, :target, :startTime, :endTime, :state, :referrer)"
|
||||
);
|
||||
|
||||
let current = browser.currentURI.spec;
|
||||
stmt.params.name = fileName;
|
||||
stmt.params.source = current;
|
||||
stmt.params.target = Services.io.newFileURI(file).spec;
|
||||
stmt.params.startTime = Date.now() * 1000;
|
||||
stmt.params.endTime = Date.now() * 1000;
|
||||
stmt.params.state = Ci.nsIDownloadManager.DOWNLOAD_NOTSTARTED;
|
||||
stmt.params.referrer = current;
|
||||
stmt.execute();
|
||||
stmt.finalize();
|
||||
|
||||
let newItemId = db.lastInsertRowID;
|
||||
let download = dm.getDownload(newItemId);
|
||||
try {
|
||||
DownloadsView.downloadStarted(download);
|
||||
}
|
||||
catch(e) {}
|
||||
Services.obs.notifyObservers(download, "dl-start", null);
|
||||
|
||||
#ifdef ANDROID
|
||||
let tmpDir = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties).get("TmpD", Ci.nsIFile);
|
||||
|
||||
file = tmpDir.clone();
|
||||
file.append(fileName);
|
||||
|
||||
#endif
|
||||
|
||||
let data = {
|
||||
type: Ci.nsIPrintSettings.kOutputFormatPDF,
|
||||
id: newItemId,
|
||||
referrer: current,
|
||||
filePath: file.path
|
||||
};
|
||||
|
||||
Browser.selectedBrowser.messageManager.sendAsyncMessage("Browser:SaveAs", data);
|
||||
},
|
||||
|
||||
updatePageSaveAs: function updatePageSaveAs(aNode) {
|
||||
// Check for local XUL content
|
||||
let contentWindow = Browser.selectedBrowser.contentWindow;
|
||||
return !(contentWindow && contentWindow.document instanceof XULDocument);
|
||||
},
|
||||
|
||||
updateShare: function updateShare(aNode) {
|
||||
return Util.isShareableScheme(Browser.selectedBrowser.currentURI.scheme);
|
||||
},
|
||||
|
||||
hideItem: function hideItem(aNode) {
|
||||
aNode.hidden = true;
|
||||
this._updateAttributes();
|
||||
},
|
||||
|
||||
_updateAttributes: function _updateAttributes() {
|
||||
let container = document.getElementById("pageactions-container");
|
||||
let visibleNodes = container.querySelectorAll("pageaction:not([hidden=true])");
|
||||
let visibleCount = visibleNodes.length;
|
||||
|
||||
for (let i = 0; i < visibleCount; i++)
|
||||
visibleNodes[i].classList.remove("odd-last-child");
|
||||
|
||||
visibleNodes[visibleCount - 1].classList.add("last-child");
|
||||
if (visibleCount % 2)
|
||||
visibleNodes[visibleCount - 1].classList.add("odd");
|
||||
}
|
||||
};
|
||||
|
||||
var NewTabPopup = {
|
||||
_timeout: 0,
|
||||
_tabs: [],
|
||||
@ -1306,172 +1076,6 @@ var ContextHelper = {
|
||||
}
|
||||
};
|
||||
|
||||
var SelectionHelper = {
|
||||
enabled: true,
|
||||
popupState: null,
|
||||
target: null,
|
||||
deltaX: -1,
|
||||
deltaY: -1,
|
||||
|
||||
get _start() {
|
||||
delete this._start;
|
||||
return this._start = document.getElementById("selectionhandle-start");
|
||||
},
|
||||
|
||||
get _end() {
|
||||
delete this._end;
|
||||
return this._end = document.getElementById("selectionhandle-end");
|
||||
},
|
||||
|
||||
showPopup: function sh_showPopup(aMessage) {
|
||||
if (!this.enabled || aMessage.json.types.indexOf("content-text") == -1)
|
||||
return false;
|
||||
|
||||
this.popupState = aMessage.json;
|
||||
this.popupState.target = aMessage.target;
|
||||
|
||||
this._start.customDragger = {
|
||||
isDraggable: function isDraggable(target, content) { return { x: true, y: false }; },
|
||||
dragStart: function dragStart(cx, cy, target, scroller) {},
|
||||
dragStop: function dragStop(dx, dy, scroller) { return false; },
|
||||
dragMove: function dragMove(dx, dy, scroller) { return false; }
|
||||
};
|
||||
|
||||
this._end.customDragger = {
|
||||
isDraggable: function isDraggable(target, content) { return { x: true, y: false }; },
|
||||
dragStart: function dragStart(cx, cy, target, scroller) {},
|
||||
dragStop: function dragStop(dx, dy, scroller) { return false; },
|
||||
dragMove: function dragMove(dx, dy, scroller) { return false; }
|
||||
};
|
||||
|
||||
this._start.addEventListener("TapUp", this, true);
|
||||
this._end.addEventListener("TapUp", this, true);
|
||||
|
||||
messageManager.addMessageListener("Browser:SelectionRange", this);
|
||||
messageManager.addMessageListener("Browser:SelectionCopied", this);
|
||||
|
||||
this.popupState.target.messageManager.sendAsyncMessage("Browser:SelectionStart", { x: this.popupState.x, y: this.popupState.y });
|
||||
|
||||
// Hide the selection handles
|
||||
window.addEventListener("TapDown", this, true);
|
||||
window.addEventListener("resize", this, true);
|
||||
window.addEventListener("keypress", this, true);
|
||||
Elements.browsers.addEventListener("URLChanged", this, true);
|
||||
Elements.browsers.addEventListener("SizeChanged", this, true);
|
||||
Elements.browsers.addEventListener("ZoomChanged", this, true);
|
||||
|
||||
let event = document.createEvent("Events");
|
||||
event.initEvent("CancelTouchSequence", true, false);
|
||||
this.popupState.target.dispatchEvent(event);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
hide: function sh_hide(aEvent) {
|
||||
if (this._start.hidden)
|
||||
return;
|
||||
|
||||
let pos = this.popupState.target.transformClientToBrowser(aEvent.clientX || 0, aEvent.clientY || 0);
|
||||
let json = {
|
||||
x: pos.x,
|
||||
y: pos.y
|
||||
};
|
||||
|
||||
try {
|
||||
this.popupState.target.messageManager.sendAsyncMessage("Browser:SelectionEnd", json);
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
|
||||
this.popupState = null;
|
||||
|
||||
this._start.hidden = true;
|
||||
this._end.hidden = true;
|
||||
|
||||
this._start.removeEventListener("TapUp", this, true);
|
||||
this._end.removeEventListener("TapUp", this, true);
|
||||
|
||||
messageManager.removeMessageListener("Browser:SelectionRange", this);
|
||||
|
||||
window.removeEventListener("TapDown", this, true);
|
||||
window.removeEventListener("resize", this, true);
|
||||
window.removeEventListener("keypress", this, true);
|
||||
Elements.browsers.removeEventListener("URLChanged", this, true);
|
||||
Elements.browsers.removeEventListener("SizeChanged", this, true);
|
||||
Elements.browsers.removeEventListener("ZoomChanged", this, true);
|
||||
},
|
||||
|
||||
handleEvent: function handleEvent(aEvent) {
|
||||
switch (aEvent.type) {
|
||||
case "TapDown":
|
||||
if (aEvent.target == this._start || aEvent.target == this._end) {
|
||||
this.target = aEvent.target;
|
||||
this.deltaX = (aEvent.clientX - this.target.left);
|
||||
this.deltaY = (aEvent.clientY - this.target.top);
|
||||
window.addEventListener("TapMove", this, true);
|
||||
} else {
|
||||
this.hide(aEvent);
|
||||
}
|
||||
break;
|
||||
case "TapUp":
|
||||
window.removeEventListener("TapMove", this, true);
|
||||
this.target = null;
|
||||
this.deltaX = -1;
|
||||
this.deltaY = -1;
|
||||
break;
|
||||
case "TapMove":
|
||||
if (this.target) {
|
||||
this.target.left = aEvent.clientX - this.deltaX;
|
||||
this.target.top = aEvent.clientY - this.deltaY;
|
||||
let rect = this.target.getBoundingClientRect();
|
||||
let data = this.target == this._start ? { x: rect.right, y: rect.top, type: "start" } : { x: rect.left, y: rect.top, type: "end" };
|
||||
let pos = this.popupState.target.transformClientToBrowser(data.x || 0, data.y || 0);
|
||||
let json = {
|
||||
type: data.type,
|
||||
x: pos.x,
|
||||
y: pos.y
|
||||
};
|
||||
this.popupState.target.messageManager.sendAsyncMessage("Browser:SelectionMove", json);
|
||||
}
|
||||
break;
|
||||
case "resize":
|
||||
case "SizeChanged":
|
||||
case "ZoomChanged":
|
||||
case "URLChanged":
|
||||
case "keypress":
|
||||
this.hide(aEvent);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
receiveMessage: function sh_receiveMessage(aMessage) {
|
||||
let json = aMessage.json;
|
||||
switch (aMessage.name) {
|
||||
case "Browser:SelectionRange": {
|
||||
let pos = this.popupState.target.transformBrowserToClient(json.start.x || 0, json.start.y || 0);
|
||||
this._start.left = pos.x - 32;
|
||||
this._start.top = pos.y + this.deltaY;
|
||||
this._start.hidden = false;
|
||||
|
||||
pos = this.popupState.target.transformBrowserToClient(json.end.x || 0, json.end.y || 0);
|
||||
this._end.left = pos.x;
|
||||
this._end.top = pos.y;
|
||||
this._end.hidden = false;
|
||||
break;
|
||||
}
|
||||
|
||||
case "Browser:SelectionCopied": {
|
||||
messageManager.removeMessageListener("Browser:SelectionCopied", this);
|
||||
if (json.succeeded) {
|
||||
let toaster = Cc["@mozilla.org/toaster-alerts-service;1"].getService(Ci.nsIAlertsService);
|
||||
toaster.showAlertNotification(null, Strings.browser.GetStringFromName("selectionHelper.textCopied"), "", false, "", null);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var BadgeHandlers = {
|
||||
_handlers: [
|
||||
{
|
||||
@ -1655,227 +1259,3 @@ var FullScreenVideo = {
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var CharsetMenu = {
|
||||
_strings: null,
|
||||
_charsets: null,
|
||||
|
||||
get strings() {
|
||||
if (!this._strings)
|
||||
this._strings = Services.strings.createBundle("chrome://global/locale/charsetTitles.properties");
|
||||
return this._strings;
|
||||
},
|
||||
|
||||
init: function() {
|
||||
PageActions.register("pageaction-charset", this.updatePageAction, this);
|
||||
},
|
||||
|
||||
updatePageAction: function(aNode) {
|
||||
let pref = Services.prefs.getComplexValue("browser.menu.showCharacterEncoding", Ci.nsIPrefLocalizedString).data;
|
||||
if (pref == "true") {
|
||||
let charset = getBrowser().documentCharsetInfo.forcedCharset;
|
||||
if (charset) {
|
||||
charset = charset.toString();
|
||||
charset = charset.trim().toLowerCase();
|
||||
aNode.setAttribute("description", this.strings.GetStringFromName(charset + ".title"));
|
||||
} else if (aNode.hasAttribute("description")) {
|
||||
aNode.removeAttribute("description");
|
||||
}
|
||||
}
|
||||
return ("true" == pref)
|
||||
},
|
||||
|
||||
_toMenuItems: function(aCharsets, aCurrent) {
|
||||
let ret = [];
|
||||
aCharsets.forEach(function (aSet) {
|
||||
try {
|
||||
let string = aSet.trim().toLowerCase();
|
||||
ret.push({
|
||||
label: this.strings.GetStringFromName(string + ".title"),
|
||||
value: string,
|
||||
selected: (string == aCurrent)
|
||||
});
|
||||
} catch(ex) { }
|
||||
}, this);
|
||||
return ret;
|
||||
},
|
||||
|
||||
menu : {
|
||||
dispatchEvent: function(aEvent) {
|
||||
if (aEvent.type == "command")
|
||||
CharsetMenu.setCharset(this.menupopup.children[this.selectedIndex].value);
|
||||
},
|
||||
menupopup: {
|
||||
hasAttribute: function(aAttr) { return false; },
|
||||
},
|
||||
selectedIndex: -1
|
||||
},
|
||||
|
||||
get charsets() {
|
||||
if (!this._charsets) {
|
||||
this._charsets = Services.prefs.getComplexValue("intl.charsetmenu.browser.static", Ci.nsIPrefLocalizedString).data.split(",");
|
||||
}
|
||||
let charsets = this._charsets;
|
||||
let currentCharset = getBrowser().documentCharsetInfo.forcedCharset;
|
||||
|
||||
if (currentCharset) {
|
||||
currentCharset = currentCharset.toString();
|
||||
currentCharset = currentCharset.trim().toLowerCase();
|
||||
if (charsets.indexOf(currentCharset) == -1)
|
||||
charsets.splice(0, 0, currentCharset);
|
||||
}
|
||||
return this._toMenuItems(charsets, currentCharset);
|
||||
},
|
||||
|
||||
show: function showCharsetMenu() {
|
||||
this.menu.menupopup.children = this.charsets;
|
||||
MenuListHelperUI.show(this.menu);
|
||||
},
|
||||
|
||||
setCharset: function setCharset(aCharset) {
|
||||
let browser = getBrowser();
|
||||
browser.messageManager.sendAsyncMessage("Browser:SetCharset", {
|
||||
charset: aCharset
|
||||
});
|
||||
let history = Cc["@mozilla.org/browser/nav-history-service;1"].getService(Ci.nsINavHistoryService);
|
||||
history.setCharsetForURI(browser.documentURI, aCharset);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
var WebappsUI = {
|
||||
_dialog: null,
|
||||
_manifest: null,
|
||||
_perms: [],
|
||||
|
||||
checkBox: function(aEvent) {
|
||||
let elem = aEvent.originalTarget;
|
||||
let perm = elem.getAttribute("perm");
|
||||
if (this._manifest.capabilities && this._manifest.capabilities.indexOf(perm) != -1) {
|
||||
if (elem.checked) {
|
||||
elem.classList.remove("webapps-noperm");
|
||||
elem.classList.add("webapps-perm");
|
||||
} else {
|
||||
elem.classList.remove("webapps-perm");
|
||||
elem.classList.add("webapps-noperm");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
show: function show(aManifest) {
|
||||
if (!aManifest) {
|
||||
// Try every way to get an icon
|
||||
let browser = Browser.selectedBrowser;
|
||||
let icon = browser.appIcon.href;
|
||||
if (!icon)
|
||||
icon = browser.mIconURL;
|
||||
if (!icon)
|
||||
icon = gFaviconService.getFaviconImageForPage(browser.currentURI).spec;
|
||||
|
||||
// Create a simple manifest
|
||||
aManifest = {
|
||||
uri: browser.currentURI.spec,
|
||||
name: browser.contentTitle,
|
||||
icon: icon,
|
||||
capabilities: [],
|
||||
};
|
||||
}
|
||||
|
||||
this._manifest = aManifest;
|
||||
this._dialog = importDialog(window, "chrome://browser/content/webapps.xul", null);
|
||||
|
||||
if (aManifest.name)
|
||||
document.getElementById("webapps-title").value = aManifest.name;
|
||||
if (aManifest.icon)
|
||||
document.getElementById("webapps-icon").src = aManifest.icon;
|
||||
|
||||
let uri = Services.io.newURI(aManifest.uri, null, null);
|
||||
|
||||
let perms = [["offline", "offline-app"], ["geoloc", "geo"], ["notifications", "desktop-notification"]];
|
||||
let self = this;
|
||||
perms.forEach(function(tuple) {
|
||||
let elem = document.getElementById("webapps-" + tuple[0] + "-checkbox");
|
||||
let currentPerm = Services.perms.testExactPermission(uri, tuple[1]);
|
||||
self._perms[tuple[1]] = (currentPerm == Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
if ((aManifest.capabilities && (aManifest.capabilities.indexOf(tuple[1]) != -1)) || (currentPerm == Ci.nsIPermissionManager.ALLOW_ACTION))
|
||||
elem.checked = true;
|
||||
else
|
||||
elem.checked = (currentPerm == Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
elem.classList.remove("webapps-noperm");
|
||||
elem.classList.add("webapps-perm");
|
||||
});
|
||||
|
||||
BrowserUI.pushPopup(this, this._dialog);
|
||||
|
||||
// Force a modal dialog
|
||||
this._dialog.waitForClose();
|
||||
},
|
||||
|
||||
hide: function hide() {
|
||||
this._dialog.close();
|
||||
this._dialog = null;
|
||||
BrowserUI.popPopup(this);
|
||||
},
|
||||
|
||||
_updatePermission: function updatePermission(aId, aPerm) {
|
||||
try {
|
||||
let uri = Services.io.newURI(this._manifest.uri, null, null);
|
||||
let currentState = document.getElementById(aId).checked;
|
||||
if (currentState != this._perms[aPerm])
|
||||
Services.perms.add(uri, aPerm, currentState ? Ci.nsIPermissionManager.ALLOW_ACTION : Ci.nsIPermissionManager.DENY_ACTION);
|
||||
} catch(e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
},
|
||||
|
||||
launch: function launch() {
|
||||
let title = document.getElementById("webapps-title").value;
|
||||
if (!title)
|
||||
return;
|
||||
|
||||
this._updatePermission("webapps-offline-checkbox", "offline-app");
|
||||
this._updatePermission("webapps-geoloc-checkbox", "geo");
|
||||
this._updatePermission("webapps-notifications-checkbox", "desktop-notification");
|
||||
|
||||
this.hide();
|
||||
this.install(this._manifest.uri, title, this._manifest.icon);
|
||||
},
|
||||
|
||||
updateWebappsInstall: function updateWebappsInstall(aNode) {
|
||||
if (document.getElementById("main-window").hasAttribute("webapp"))
|
||||
return false;
|
||||
|
||||
let browser = Browser.selectedBrowser;
|
||||
|
||||
let webapp = Cc["@mozilla.org/webapps/support;1"].getService(Ci.nsIWebappsSupport);
|
||||
return !(webapp && webapp.isApplicationInstalled(browser.currentURI.spec));
|
||||
},
|
||||
|
||||
install: function(aURI, aTitle, aIcon) {
|
||||
const kIconSize = 64;
|
||||
|
||||
let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
||||
canvas.setAttribute("style", "display: none");
|
||||
|
||||
let self = this;
|
||||
let image = new Image();
|
||||
image.onload = function() {
|
||||
canvas.width = canvas.height = kIconSize; // clears the canvas
|
||||
let ctx = canvas.getContext("2d");
|
||||
ctx.drawImage(image, 0, 0, kIconSize, kIconSize);
|
||||
let data = canvas.toDataURL("image/png", "");
|
||||
canvas = null;
|
||||
try {
|
||||
let webapp = Cc["@mozilla.org/webapps/support;1"].getService(Ci.nsIWebappsSupport);
|
||||
webapp.installApplication(aTitle, aURI, aIcon, data);
|
||||
} catch(e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
}
|
||||
image.onerror = function() {
|
||||
// can't load the icon (bad URI) : fallback to the default one from chrome
|
||||
self.install(aURI, aTitle, "chrome://browser/skin/images/favicon-default-30.png");
|
||||
}
|
||||
image.src = aIcon;
|
||||
}
|
||||
};
|
||||
|
@ -85,10 +85,10 @@
|
||||
<method name="_onUndo">
|
||||
<body>
|
||||
<![CDATA[
|
||||
let closeFn = new Function("event", this._container.getAttribute("onreloadtab"));
|
||||
let container = this._container;
|
||||
let closeFn = new Function("event", container.getAttribute("onreloadtab"));
|
||||
closeFn.call(this);
|
||||
|
||||
this._container.removeTab(this);
|
||||
container.removeClosedTab(this);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
@ -23,12 +23,15 @@ chrome.jar:
|
||||
* content/AwesomePanel.js (content/AwesomePanel.js)
|
||||
content/BookmarkHelper.js (content/BookmarkHelper.js)
|
||||
content/BookmarkPopup.js (content/BookmarkPopup.js)
|
||||
content/CharsetMenu.js (content/CharsetMenu.js)
|
||||
content/ContentPopupHelper.js (content/ContentPopupHelper.js)
|
||||
* content/ContextCommands.js (content/ContextCommands.js)
|
||||
content/IndexedDB.js (content/IndexedDB.js)
|
||||
content/MenuListHelperUI.js (content/MenuListHelperUI.js)
|
||||
content/OfflineApps.js (content/OfflineApps.js)
|
||||
* content/PageActions.js (content/PageActions.js)
|
||||
content/SelectHelperUI.js (content/SelectHelperUI.js)
|
||||
content/SelectionHelper.js (content/SelectionHelper.js)
|
||||
content/SharingUI.js (content/SharingUI.js)
|
||||
content/TabsPopup.js (content/TabsPopup.js)
|
||||
content/MasterPasswordUI.js (content/MasterPasswordUI.js)
|
||||
@ -66,6 +69,7 @@ chrome.jar:
|
||||
content/prompt/prompt.js (content/prompt/prompt.js)
|
||||
content/share.xul (content/share.xul)
|
||||
content/webapps.xul (content/webapps.xul)
|
||||
content/WebappsUI.js (content/WebappsUI.js)
|
||||
content/masterPassword.xul (content/masterPassword.xul)
|
||||
content/removeMasterPassword.xul (content/removeMasterPassword.xul)
|
||||
content/AnimatedZoom.js (content/AnimatedZoom.js)
|
||||
|
@ -383,7 +383,7 @@ Prompt.prototype = {
|
||||
|
||||
let dialog = this.openDialog("chrome://browser/content/prompt/confirm.xul", params);
|
||||
let doc = this._doc;
|
||||
this._setupPrompt(doc, "prompt", aTitle, aText, {value: aCheckState.value, msg: aCheckMsg});
|
||||
this._setupPrompt(doc, "confirm", aTitle, aText, {value: aCheckState.value, msg: aCheckMsg});
|
||||
|
||||
dialog.waitForClose();
|
||||
return params.result;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user