зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to tracemonkey.
This commit is contained in:
Коммит
86b530a417
|
@ -4490,21 +4490,16 @@ var CombinedStopReload = {
|
|||
};
|
||||
|
||||
var TabsProgressListener = {
|
||||
onProgressChange: function (aBrowser, aWebProgress, aRequest,
|
||||
aCurSelfProgress, aMaxSelfProgress,
|
||||
aCurTotalProgress, aMaxTotalProgress) {
|
||||
},
|
||||
|
||||
onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
|
||||
if (aRequest instanceof Ci.nsIChannel &&
|
||||
aStateFlags & Ci.nsIWebProgressListener.STATE_START &&
|
||||
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT &&
|
||||
gCrashReporter.enabled) {
|
||||
gCrashReporter.annotateCrashReport("URL", aRequest.URI.spec);
|
||||
}
|
||||
#endif
|
||||
},
|
||||
#endif
|
||||
|
||||
onLocationChange: function (aBrowser, aWebProgress, aRequest, aLocationURI) {
|
||||
// Filter out any sub-frame loads
|
||||
|
@ -4512,9 +4507,6 @@ var TabsProgressListener = {
|
|||
FullZoom.onLocationChange(aLocationURI, false, aBrowser);
|
||||
},
|
||||
|
||||
onStatusChange: function (aBrowser, aWebProgress, aRequest, aStatus, aMessage) {
|
||||
},
|
||||
|
||||
onRefreshAttempted: function (aBrowser, aWebProgress, aURI, aDelay, aSameURI) {
|
||||
if (gPrefService.getBoolPref("accessibility.blockautorefresh")) {
|
||||
let brandBundle = document.getElementById("bundle_brand");
|
||||
|
@ -4561,9 +4553,6 @@ var TabsProgressListener = {
|
|||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
onSecurityChange: function (aBrowser, aWebProgress, aRequest, aState) {
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,11 +38,6 @@ var gFrontProgressListener = {
|
|||
}
|
||||
|
||||
var gAllProgressListener = {
|
||||
onProgressChange: function (aBrowser, aWebProgress, aRequest,
|
||||
aCurSelfProgress, aMaxSelfProgress,
|
||||
aCurTotalProgress, aMaxTotalProgress) {
|
||||
},
|
||||
|
||||
onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
|
||||
var state = "onStateChange";
|
||||
info("AllProgress: " + state + " 0x" + aStateFlags.toString(16));
|
||||
|
|
|
@ -57,12 +57,7 @@ var gProgressListener = {
|
|||
ok(gBrowser.tabs.length == kURIs.length, "Correctly opened all expected tabs");
|
||||
finishTest();
|
||||
}
|
||||
},
|
||||
|
||||
onProgressChange: function () {},
|
||||
onLocationChange: function () {},
|
||||
onStatusChange: function () {},
|
||||
onSecurityChange: function () {}
|
||||
}
|
||||
}
|
||||
|
||||
function test() {
|
||||
|
|
|
@ -35,13 +35,10 @@ var progressListener = {
|
|||
if (aBrowser == tab.linkedBrowser)
|
||||
record(arguments.callee.name);
|
||||
},
|
||||
onProgressChange: function () {},
|
||||
onSecurityChange: function () {},
|
||||
onStateChange: function onStateChange(aBrowser) {
|
||||
if (aBrowser == tab.linkedBrowser)
|
||||
record(arguments.callee.name);
|
||||
},
|
||||
onStatusChange: function () {},
|
||||
onLinkIconAvailable: function onLinkIconAvailable(aBrowser) {
|
||||
if (aBrowser == tab.linkedBrowser)
|
||||
record(arguments.callee.name);
|
||||
|
|
|
@ -95,21 +95,6 @@ var gTabsListener = {
|
|||
// Test finished. This will move to the next one.
|
||||
waitForFocus(gCurrentTest.finish, gBrowser.ownerDocument.defaultView);
|
||||
}
|
||||
},
|
||||
|
||||
onProgressChange: function(aBrowser, aWebProgress, aRequest,
|
||||
aCurSelfProgress, aMaxSelfProgress,
|
||||
aCurTotalProgress, aMaxTotalProgress) {
|
||||
},
|
||||
onStateChange: function(aBrowser, aWebProgress, aRequest,
|
||||
aStateFlags, aStatus) {
|
||||
},
|
||||
onStatusChange: function(aBrowser, aWebProgress, aRequest,
|
||||
aStatus, aMessage) {
|
||||
},
|
||||
onSecurityChange: function(aBrowser, aWebProgress, aRequest, aState) {
|
||||
},
|
||||
noLinkIconAvailable: function(aBrowser) {
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -92,11 +92,6 @@ function test() {
|
|||
Services.ww.registerNotification(observer);
|
||||
|
||||
gBrowser.addTabsProgressListener({
|
||||
onLocationChange: function() {},
|
||||
onProgressChange: function() {},
|
||||
onSecurityChange: function() {},
|
||||
onStatusChange: function() {},
|
||||
onRefreshAttempted: function() {},
|
||||
onStateChange: function(aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
|
||||
if (aStateFlags & (Ci.nsIWebProgressListener.STATE_STOP |
|
||||
Ci.nsIWebProgressListener.STATE_IS_WINDOW)) {
|
||||
|
|
|
@ -62,11 +62,7 @@ function test() {
|
|||
gBrowser.removeTabsProgressListener(this);
|
||||
executeSoon(aSetStateCallback);
|
||||
}
|
||||
},
|
||||
onProgressChange: function () {},
|
||||
onSecurityChange: function () {},
|
||||
onStateChange: function () {},
|
||||
onStatusChange: function () {}
|
||||
}
|
||||
});
|
||||
ss.setBrowserState(JSON.stringify(aState));
|
||||
}
|
||||
|
@ -211,11 +207,7 @@ function test() {
|
|||
gBrowser.removeTabsProgressListener(this);
|
||||
firstLocationChange();
|
||||
}
|
||||
},
|
||||
onProgressChange: function () {},
|
||||
onSecurityChange: function () {},
|
||||
onStateChange: function () {},
|
||||
onStatusChange: function () {}
|
||||
}
|
||||
});
|
||||
|
||||
function firstLocationChange() {
|
||||
|
|
|
@ -530,16 +530,6 @@ TabWindow.prototype = {
|
|||
},
|
||||
|
||||
//// Browser progress listener
|
||||
onLocationChange: function () {
|
||||
},
|
||||
onProgressChange: function () {
|
||||
},
|
||||
onSecurityChange: function () {
|
||||
},
|
||||
onStateChange: function () {
|
||||
},
|
||||
onStatusChange: function () {
|
||||
},
|
||||
onLinkIconAvailable: function (aBrowser, aIconURL) {
|
||||
let self = this;
|
||||
getFaviconAsImage(aIconURL, function (img) {
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
repo: f5ab154deef2ffa97f1b2139589ae4a1962090a4
|
||||
node: 3476582628db128ad061c30cab1a74a0c5d14b9b
|
||||
node: 7ae0b4af32617677698f9de3ab76bcb154bbf085
|
||||
|
|
|
@ -1402,7 +1402,7 @@ class Makefile(object):
|
|||
Inform the makefile of a target which is a candidate for being the default target,
|
||||
if there isn't already a default target.
|
||||
"""
|
||||
if self.defaulttarget is None:
|
||||
if self.defaulttarget is None and t != '.PHONY':
|
||||
self.defaulttarget = t
|
||||
|
||||
def getpatternvariables(self, pattern):
|
||||
|
|
|
@ -284,7 +284,7 @@ def ifeq(d, offset):
|
|||
if token == '(':
|
||||
arg1, t, offset = parsemakesyntax(d, offset, (',',), itermakefilechars)
|
||||
if t is None:
|
||||
raise SyntaxError("Expected two arguments in conditional", d.getloc(offset))
|
||||
raise SyntaxError("Expected two arguments in conditional", d.getloc(d.lend))
|
||||
|
||||
arg1.rstrip()
|
||||
|
||||
|
@ -604,6 +604,9 @@ class ParseStackFrame(object):
|
|||
self.function = function
|
||||
self.loc = loc
|
||||
|
||||
def __str__(self):
|
||||
return "<state=%i expansion=%s tokenlist=%s openbrace=%s closebrace=%s>" % (self.parsestate, self.expansion, self.tokenlist, self.openbrace, self.closebrace)
|
||||
|
||||
_matchingbrace = {
|
||||
'(': ')',
|
||||
'{': '}',
|
||||
|
@ -689,7 +692,7 @@ def parsemakesyntax(d, offset, stopon, iterfunc):
|
|||
stacktop.expansion.appendstr(token)
|
||||
stacktop = ParseStackFrame(_PARSESTATE_PARENMATCH, stacktop,
|
||||
stacktop.expansion,
|
||||
(token, stacktop.closebrace),
|
||||
(token, stacktop.closebrace, '$'),
|
||||
openbrace=token, closebrace=stacktop.closebrace, loc=d.getloc(tokenoffset))
|
||||
elif parsestate == _PARSESTATE_PARENMATCH:
|
||||
assert token == stacktop.closebrace
|
||||
|
|
|
@ -3,6 +3,8 @@ test: VAR = value
|
|||
%.do:
|
||||
@echo TEST-FAIL: ran target "$@", should have run "all"
|
||||
|
||||
.PHONY: test
|
||||
|
||||
all:
|
||||
@echo TEST-PASS: the default target is all
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
#T returncode: 2
|
||||
|
||||
ifeq ($(FOO,VAR))
|
||||
all:
|
||||
@echo TEST_FAIL
|
||||
endif
|
|
@ -1,5 +1,5 @@
|
|||
$(shell \
|
||||
if test ! -f include-dynamic.inc; then \
|
||||
if ! test -f include-dynamic.inc; then \
|
||||
echo "TESTVAR = oldval" > include-dynamic.inc; \
|
||||
sleep 2; \
|
||||
echo "TESTVAR = newval" > include-dynamic.inc.in; \
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -1006,7 +1006,10 @@ nsHTMLParanoidFragmentSink::AddAttributes(const nsIParserNode& aNode,
|
|||
nsContentUtils::TrimCharsInSet(kWhitespace, aNode.GetValueAt(i));
|
||||
|
||||
// check the attributes we allow that contain URIs
|
||||
if (IsAttrURI(keyAtom)) {
|
||||
// special case src attributes for img tags, because they can't
|
||||
// run any dangerous code.
|
||||
if (IsAttrURI(keyAtom) &&
|
||||
!(nodeType == eHTMLTag_img && keyAtom == nsGkAtoms::src)) {
|
||||
if (!baseURI) {
|
||||
baseURI = aContent->GetBaseURI();
|
||||
}
|
||||
|
|
|
@ -7,10 +7,6 @@ function test() {
|
|||
let numLocationChanges = 0;
|
||||
|
||||
let listener = {
|
||||
onStateChange: function() {},
|
||||
onProgressChange: function() {},
|
||||
onStatusChange: function() {},
|
||||
onSecurityChange: function() {},
|
||||
onLocationChange: function() {
|
||||
numLocationChanges++;
|
||||
}
|
||||
|
|
|
@ -281,7 +281,9 @@ nsRangeUpdater::SelAdjDeleteNode(nsIDOMNode *aNode)
|
|||
if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc...
|
||||
NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
|
||||
PRUint32 i, count = mArray.Length();
|
||||
NS_ENSURE_TRUE(count, NS_OK);
|
||||
if (!count) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
PRInt32 offset = 0;
|
||||
|
@ -339,7 +341,9 @@ nsRangeUpdater::SelAdjSplitNode(nsIDOMNode *aOldRightNode, PRInt32 aOffset, nsID
|
|||
if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc...
|
||||
NS_ENSURE_TRUE(aOldRightNode && aNewLeftNode, NS_ERROR_NULL_POINTER);
|
||||
PRUint32 i, count = mArray.Length();
|
||||
NS_ENSURE_TRUE(count, NS_OK);
|
||||
if (!count) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
PRInt32 offset;
|
||||
|
@ -395,7 +399,9 @@ nsRangeUpdater::SelAdjJoinNodes(nsIDOMNode *aLeftNode,
|
|||
if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc...
|
||||
NS_ENSURE_TRUE(aLeftNode && aRightNode && aParent, NS_ERROR_NULL_POINTER);
|
||||
PRUint32 i, count = mArray.Length();
|
||||
NS_ENSURE_TRUE(count, NS_OK);
|
||||
if (!count) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRangeStore *item;
|
||||
|
||||
|
@ -465,7 +471,9 @@ nsRangeUpdater::SelAdjInsertText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset
|
|||
if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc...
|
||||
|
||||
PRUint32 count = mArray.Length();
|
||||
NS_ENSURE_TRUE(count, NS_OK);
|
||||
if (!count) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(aTextNode));
|
||||
NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
|
||||
|
||||
|
@ -491,7 +499,9 @@ nsRangeUpdater::SelAdjDeleteText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset
|
|||
if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc...
|
||||
|
||||
PRUint32 i, count = mArray.Length();
|
||||
NS_ENSURE_TRUE(count, NS_OK);
|
||||
if (!count) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsRangeStore *item;
|
||||
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(aTextNode));
|
||||
NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
|
||||
|
@ -533,7 +543,9 @@ nsRangeUpdater::DidReplaceContainer(nsIDOMNode *aOriginalNode, nsIDOMNode *aNewN
|
|||
|
||||
NS_ENSURE_TRUE(aOriginalNode && aNewNode, NS_ERROR_NULL_POINTER);
|
||||
PRUint32 i, count = mArray.Length();
|
||||
NS_ENSURE_TRUE(count, NS_OK);
|
||||
if (!count) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRangeStore *item;
|
||||
|
||||
|
@ -568,7 +580,9 @@ nsRangeUpdater::DidRemoveContainer(nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt
|
|||
|
||||
NS_ENSURE_TRUE(aNode && aParent, NS_ERROR_NULL_POINTER);
|
||||
PRUint32 i, count = mArray.Length();
|
||||
NS_ENSURE_TRUE(count, NS_OK);
|
||||
if (!count) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRangeStore *item;
|
||||
|
||||
|
@ -632,7 +646,9 @@ nsRangeUpdater::DidMoveNode(nsIDOMNode *aOldParent, PRInt32 aOldOffset, nsIDOMNo
|
|||
|
||||
NS_ENSURE_TRUE(aOldParent && aNewParent, NS_ERROR_NULL_POINTER);
|
||||
PRUint32 i, count = mArray.Length();
|
||||
NS_ENSURE_TRUE(count, NS_OK);
|
||||
if (!count) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRangeStore *item;
|
||||
|
||||
|
|
|
@ -125,6 +125,9 @@
|
|||
#include "nsIPrefService.h"
|
||||
#include "nsIContentFilter.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "plbase64.h"
|
||||
#include "prmem.h"
|
||||
#include "nsStreamUtils.h"
|
||||
|
||||
const PRUnichar nbsp = 160;
|
||||
|
||||
|
@ -1402,60 +1405,25 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromTransferable(nsITransferable *transferable
|
|||
nsCOMPtr<nsIInputStream> imageStream(do_QueryInterface(genericDataObj));
|
||||
NS_ENSURE_TRUE(imageStream, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIFile> fileToUse;
|
||||
NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(fileToUse));
|
||||
|
||||
if (0 == nsCRT::strcmp(bestFlavor, kJPEGImageMime))
|
||||
fileToUse->Append(NS_LITERAL_STRING("moz-screenshot.jpg"));
|
||||
else if (0 == nsCRT::strcmp(bestFlavor, kPNGImageMime))
|
||||
fileToUse->Append(NS_LITERAL_STRING("moz-screenshot.png"));
|
||||
else if (0 == nsCRT::strcmp(bestFlavor, kGIFImageMime))
|
||||
fileToUse->Append(NS_LITERAL_STRING("moz-screenshot.gif"));
|
||||
|
||||
nsCOMPtr<nsILocalFile> path = do_QueryInterface(fileToUse);
|
||||
path->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
|
||||
|
||||
nsCOMPtr<nsIOutputStream> outputStream;
|
||||
rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), fileToUse);
|
||||
nsCString imageData;
|
||||
rv = NS_ConsumeStream(imageStream, PR_UINT32_MAX, imageData);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint32 length;
|
||||
imageStream->Available(&length);
|
||||
char * base64 = PL_Base64Encode(imageData.get(), imageData.Length(), nsnull);
|
||||
NS_ENSURE_TRUE(base64, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsCOMPtr<nsIOutputStream> bufferedOutputStream;
|
||||
rv = NS_NewBufferedOutputStream(getter_AddRefs(bufferedOutputStream), outputStream, length);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint32 numWritten;
|
||||
rv = bufferedOutputStream->WriteFrom(imageStream, length, &numWritten);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// force the stream close before we try to insert the image
|
||||
// into the document.
|
||||
rv = bufferedOutputStream->Close();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = NS_NewFileURI(getter_AddRefs(uri), fileToUse);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIURL> fileURL(do_QueryInterface(uri));
|
||||
if (fileURL)
|
||||
{
|
||||
nsCAutoString urltext;
|
||||
rv = fileURL->GetSpec(urltext);
|
||||
if (NS_SUCCEEDED(rv) && !urltext.IsEmpty())
|
||||
{
|
||||
stuffToPaste.AssignLiteral("<IMG src=\"");
|
||||
AppendUTF8toUTF16(urltext, stuffToPaste);
|
||||
stuffToPaste.AppendLiteral("\" alt=\"\" >");
|
||||
nsAutoEditBatch beginBatching(this);
|
||||
rv = InsertHTMLWithContext(stuffToPaste, EmptyString(), EmptyString(),
|
||||
NS_LITERAL_STRING(kFileMime),
|
||||
aSourceDoc,
|
||||
aDestinationNode, aDestOffset,
|
||||
aDoDeleteSelection);
|
||||
}
|
||||
}
|
||||
stuffToPaste.AssignLiteral("<IMG src=\"data:");
|
||||
AppendUTF8toUTF16(bestFlavor, stuffToPaste);
|
||||
stuffToPaste.AppendLiteral(";base64,");
|
||||
AppendUTF8toUTF16(base64, stuffToPaste);
|
||||
stuffToPaste.AppendLiteral("\" alt=\"\" >");
|
||||
nsAutoEditBatch beginBatching(this);
|
||||
rv = InsertHTMLWithContext(stuffToPaste, EmptyString(), EmptyString(),
|
||||
NS_LITERAL_STRING(kFileMime),
|
||||
aSourceDoc,
|
||||
aDestinationNode, aDestOffset,
|
||||
aDoDeleteSelection);
|
||||
PR_Free(base64);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -74,6 +74,11 @@ _DATA_FILES = \
|
|||
data/cfhtml-ooo.txt \
|
||||
$(NULL)
|
||||
|
||||
_CHROME_TEST_FILES = \
|
||||
test_bug490879.xul \
|
||||
green.png \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
|
||||
(cd $(srcdir) && tar $(TAR_CREATE_FLAGS) - browserscope 2> /dev/null) | (cd $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir) && tar -xf -)
|
||||
|
@ -81,3 +86,6 @@ libs:: $(_TEST_FILES)
|
|||
libs:: $(_DATA_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)/data
|
||||
|
||||
libs:: $(_CHROME_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)
|
||||
|
||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 334 B |
|
@ -0,0 +1,73 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin"
|
||||
type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||||
type="text/css"?>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=490879
|
||||
-->
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="Mozilla Bug 490879" onload="runTest();">
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/MochiKit/packed.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=490879"
|
||||
target="_blank">Mozilla Bug 490879</a>
|
||||
<p/>
|
||||
<iframe id="i1" width="200" height="100" src="about:blank" /><br />
|
||||
<img id="i" src="green.png" />
|
||||
<p/>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
<script class="testbody" type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
function runTest() {
|
||||
function verifyContent() {
|
||||
const kExpectedImgSpec = "data:image/png;base64,";
|
||||
var e = document.getElementById('i1');
|
||||
var doc = e.contentDocument;
|
||||
is(doc.getElementsByTagName("img")[0].src.substring(0, kExpectedImgSpec.length),
|
||||
kExpectedImgSpec, "The pasted image is a base64-encoded data: URI");
|
||||
}
|
||||
|
||||
function pasteInto() {
|
||||
var e = document.getElementById('i1');
|
||||
var doc = e.contentDocument;
|
||||
doc.designMode = "on";
|
||||
doc.defaultView.focus();
|
||||
var selection = doc.defaultView.getSelection();
|
||||
selection.removeAllRanges();
|
||||
selection.selectAllChildren(doc.body);
|
||||
selection.collapseToEnd();
|
||||
doc.execCommand("paste", false, null);
|
||||
}
|
||||
|
||||
function copyToClipBoard() {
|
||||
var tmpNode = document.popupNode;
|
||||
document.popupNode = document.getElementById("i");
|
||||
|
||||
const kCmd = "cmd_copyImageContents";
|
||||
var controller = top.document.commandDispatcher
|
||||
.getControllerForCommand(kCmd);
|
||||
ok((controller && controller.isCommandEnabled(kCmd)), "have copy command");
|
||||
controller.doCommand(kCmd);
|
||||
|
||||
document.popupNode = tmpNode;
|
||||
}
|
||||
|
||||
copyToClipBoard();
|
||||
pasteInto();
|
||||
verifyContent();
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
]]>
|
||||
</script>
|
||||
</window>
|
|
@ -46,6 +46,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=520182
|
|||
<div id="dd" contenteditable="true"></div>
|
||||
<iframe id="ee" src="about:blank"></iframe>
|
||||
<div id="ff" contenteditable="true"></div>
|
||||
<iframe id="gg" src="about:blank"></iframe>
|
||||
<div id="hh" contenteditable="true"></div>
|
||||
<iframe id="ii" src="about:blank"></iframe>
|
||||
<div id="jj" contenteditable="true"></div>
|
||||
<iframe id="kk" src="about:blank"></iframe>
|
||||
<div id="ll" contenteditable="true"></div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
@ -68,6 +74,9 @@ const invalidStyle4Payload = "foo<span style=\"@import 'xxx.css';\">bar</span>ba
|
|||
const invalidStyle5Payload = "foo<span style=\"@font-face{font-family:xxx;src:'xxx.ttf';}\">bar</span>baz";
|
||||
const invalidStyle6Payload = "foo<span style=\"@namespace xxx url(http://example.com/);\">bar</span>baz";
|
||||
const nestedStylePayload = "foo<style>#bar1{-moz-binding:url('data:text/xml,<?xml version="1.0"><binding xmlns="http://www.mozilla.org/xbl" id="binding-1"/>');<style></style>#bar2{-moz-binding:url('data:text/xml,<?xml version="1.0"><binding xmlns="http://www.mozilla.org/xbl" id="binding-2"/>');</style>baz";
|
||||
const validImgSrc1Payload = "foo<img src=\"data:image/png,bar\">baz";
|
||||
const validImgSrc2Payload = "foo<img src=\"javascript:void('bar');\">baz";
|
||||
const validImgSrc3Payload = "foo<img src=\"file:///bar.png\">baz";
|
||||
|
||||
var tests = [
|
||||
{
|
||||
|
@ -285,6 +294,45 @@ var tests = [
|
|||
payload: invalidStyle6Payload,
|
||||
rootElement: function() document.getElementById("ff"),
|
||||
checkResult: function(html) is(html.indexOf("xxx"), -1, "Should not have retained the namespace style")
|
||||
},
|
||||
{
|
||||
id: "gg",
|
||||
isIFrame: true,
|
||||
payload: invalidStyle6Payload,
|
||||
rootElement: function() document.getElementById("gg").contentDocument.documentElement,
|
||||
checkResult: function(html) isnot(html.indexOf("bar"), -1, "Should have retained the src attribute for the image")
|
||||
},
|
||||
{
|
||||
id: "hh",
|
||||
payload: invalidStyle6Payload,
|
||||
rootElement: function() document.getElementById("hh"),
|
||||
checkResult: function(html) isnot(html.indexOf("bar"), -1, "Should have retained the src attribute for the image")
|
||||
},
|
||||
{
|
||||
id: "ii",
|
||||
isIFrame: true,
|
||||
payload: invalidStyle6Payload,
|
||||
rootElement: function() document.getElementById("ii").contentDocument.documentElement,
|
||||
checkResult: function(html) isnot(html.indexOf("bar"), -1, "Should have retained the src attribute for the image")
|
||||
},
|
||||
{
|
||||
id: "jj",
|
||||
payload: invalidStyle6Payload,
|
||||
rootElement: function() document.getElementById("jj"),
|
||||
checkResult: function(html) isnot(html.indexOf("bar"), -1, "Should have retained the src attribute for the image")
|
||||
},
|
||||
{
|
||||
id: "kk",
|
||||
isIFrame: true,
|
||||
payload: invalidStyle6Payload,
|
||||
rootElement: function() document.getElementById("kk").contentDocument.documentElement,
|
||||
checkResult: function(html) isnot(html.indexOf("bar"), -1, "Should have retained the src attribute for the image")
|
||||
},
|
||||
{
|
||||
id: "ll",
|
||||
payload: invalidStyle6Payload,
|
||||
rootElement: function() document.getElementById("ll"),
|
||||
checkResult: function(html) isnot(html.indexOf("bar"), -1, "Should have retained the src attribute for the image")
|
||||
}
|
||||
];
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ public:
|
|||
nsIOSurface *surf,
|
||||
CGColorSpaceRef aColorSpace,
|
||||
int aX, int aY,
|
||||
uint32_t aWidth, uint32_t aHeight);
|
||||
int aWidth, int aHeight);
|
||||
private:
|
||||
void Destroy();
|
||||
|
||||
|
|
|
@ -676,7 +676,7 @@ nsresult nsCARenderer::DrawSurfaceToCGContext(CGContextRef aContext,
|
|||
nsIOSurface *surf,
|
||||
CGColorSpaceRef aColorSpace,
|
||||
int aX, int aY,
|
||||
uint32_t aWidth, uint32_t aHeight) {
|
||||
int aWidth, int aHeight) {
|
||||
surf->Lock();
|
||||
size_t bytesPerRow = surf->GetBytesPerRow();
|
||||
size_t ioWidth = surf->GetWidth();
|
||||
|
|
|
@ -68,6 +68,8 @@
|
|||
|
||||
#include "nsCRT.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
gfxFontCache *gfxFontCache::gGlobalCache = nsnull;
|
||||
|
||||
static PRLogModuleInfo *gFontSelection = PR_NewLogModule("fontSelectionLog");
|
||||
|
@ -1399,6 +1401,152 @@ gfxFont::SetupGlyphExtents(gfxContext *aContext, PRUint32 aGlyphID, PRBool aNeed
|
|||
aExtents->SetTightGlyphExtents(aGlyphID, bounds);
|
||||
}
|
||||
|
||||
// Try to initialize font metrics by reading sfnt tables directly;
|
||||
// set mIsValid=TRUE and return TRUE on success.
|
||||
// Return FALSE if the gfxFontEntry subclass does not
|
||||
// implement GetFontTable(), or for non-sfnt fonts where tables are
|
||||
// not available.
|
||||
PRBool
|
||||
gfxFont::InitMetricsFromSfntTables(Metrics& aMetrics)
|
||||
{
|
||||
mIsValid = PR_FALSE; // font is NOT valid in case of early return
|
||||
|
||||
const PRUint32 kHeadTableTag = TRUETYPE_TAG('h','e','a','d');
|
||||
const PRUint32 kHheaTableTag = TRUETYPE_TAG('h','h','e','a');
|
||||
const PRUint32 kPostTableTag = TRUETYPE_TAG('p','o','s','t');
|
||||
const PRUint32 kOS_2TableTag = TRUETYPE_TAG('O','S','/','2');
|
||||
|
||||
if (mFUnitsConvFactor == 0.0) {
|
||||
// If the conversion factor from FUnits is not yet set,
|
||||
// 'head' table is required; otherwise we cannot read any metrics
|
||||
// because we don't know unitsPerEm
|
||||
nsAutoTArray<PRUint8,sizeof(HeadTable)> headData;
|
||||
if (NS_FAILED(mFontEntry->GetFontTable(kHeadTableTag, headData)) ||
|
||||
headData.Length() < sizeof(HeadTable)) {
|
||||
return PR_FALSE; // no 'head' table -> not an sfnt
|
||||
}
|
||||
HeadTable *head = reinterpret_cast<HeadTable*>(headData.Elements());
|
||||
PRUint32 unitsPerEm = head->unitsPerEm;
|
||||
if (!unitsPerEm) {
|
||||
return PR_TRUE; // is an sfnt, but not valid
|
||||
}
|
||||
mFUnitsConvFactor = mAdjustedSize / unitsPerEm;
|
||||
}
|
||||
|
||||
// 'hhea' table is required to get vertical extents
|
||||
nsAutoTArray<PRUint8,sizeof(HheaTable)> hheaData;
|
||||
if (NS_FAILED(mFontEntry->GetFontTable(kHheaTableTag, hheaData)) ||
|
||||
hheaData.Length() < sizeof(HheaTable)) {
|
||||
return PR_FALSE; // no 'hhea' table -> not an sfnt
|
||||
}
|
||||
HheaTable *hhea = reinterpret_cast<HheaTable*>(hheaData.Elements());
|
||||
|
||||
#define SET_UNSIGNED(field,src) aMetrics.field = PRUint16(src) * mFUnitsConvFactor
|
||||
#define SET_SIGNED(field,src) aMetrics.field = PRInt16(src) * mFUnitsConvFactor
|
||||
|
||||
SET_UNSIGNED(maxAdvance, hhea->advanceWidthMax);
|
||||
SET_SIGNED(maxAscent, hhea->ascender);
|
||||
SET_SIGNED(maxDescent, -PRInt16(hhea->descender));
|
||||
SET_SIGNED(externalLeading, hhea->lineGap);
|
||||
|
||||
// 'post' table is required for underline metrics
|
||||
nsAutoTArray<PRUint8,sizeof(PostTable)> postData;
|
||||
if (NS_FAILED(mFontEntry->GetFontTable(kPostTableTag, postData))) {
|
||||
return PR_TRUE; // no 'post' table -> sfnt is not valid
|
||||
}
|
||||
if (postData.Length() <
|
||||
offsetof(PostTable, underlineThickness) + sizeof(PRUint16)) {
|
||||
return PR_TRUE; // bad post table -> sfnt is not valid
|
||||
}
|
||||
PostTable *post = reinterpret_cast<PostTable*>(postData.Elements());
|
||||
|
||||
SET_SIGNED(underlineOffset, post->underlinePosition);
|
||||
SET_UNSIGNED(underlineSize, post->underlineThickness);
|
||||
|
||||
// 'OS/2' table is optional, if not found we'll estimate xHeight
|
||||
// and aveCharWidth by measuring glyphs
|
||||
nsAutoTArray<PRUint8,sizeof(OS2Table)> os2data;
|
||||
if (NS_SUCCEEDED(mFontEntry->GetFontTable(kOS_2TableTag, os2data))) {
|
||||
OS2Table *os2 = reinterpret_cast<OS2Table*>(os2data.Elements());
|
||||
|
||||
if (os2data.Length() >= offsetof(OS2Table, sxHeight) +
|
||||
sizeof(PRInt16) &&
|
||||
PRUint16(os2->version) >= 2) {
|
||||
// version 2 and later includes the x-height field
|
||||
SET_SIGNED(xHeight, os2->sxHeight);
|
||||
// PR_ABS because of negative xHeight seen in Kokonor (Tibetan) font
|
||||
aMetrics.xHeight = PR_ABS(aMetrics.xHeight);
|
||||
}
|
||||
// this should always be present
|
||||
if (os2data.Length() >= offsetof(OS2Table, yStrikeoutPosition) +
|
||||
sizeof(PRInt16)) {
|
||||
SET_SIGNED(aveCharWidth, os2->xAvgCharWidth);
|
||||
SET_SIGNED(subscriptOffset, os2->ySubscriptYOffset);
|
||||
SET_SIGNED(superscriptOffset, os2->ySuperscriptYOffset);
|
||||
SET_SIGNED(strikeoutSize, os2->yStrikeoutSize);
|
||||
SET_SIGNED(strikeoutOffset, os2->yStrikeoutPosition);
|
||||
}
|
||||
}
|
||||
|
||||
mIsValid = PR_TRUE;
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static double
|
||||
RoundToNearestMultiple(double aValue, double aFraction)
|
||||
{
|
||||
return floor(aValue/aFraction + 0.5) * aFraction;
|
||||
}
|
||||
|
||||
void gfxFont::CalculateDerivedMetrics(Metrics& aMetrics)
|
||||
{
|
||||
aMetrics.maxAscent =
|
||||
NS_ceil(RoundToNearestMultiple(aMetrics.maxAscent, 1/1024.0));
|
||||
aMetrics.maxDescent =
|
||||
NS_ceil(RoundToNearestMultiple(aMetrics.maxDescent, 1/1024.0));
|
||||
|
||||
if (aMetrics.xHeight <= 0) {
|
||||
// only happens if we couldn't find either font metrics
|
||||
// or a char to measure;
|
||||
// pick an arbitrary value that's better than zero
|
||||
aMetrics.xHeight = aMetrics.maxAscent * DEFAULT_XHEIGHT_FACTOR;
|
||||
}
|
||||
|
||||
aMetrics.maxHeight = aMetrics.maxAscent + aMetrics.maxDescent;
|
||||
|
||||
if (aMetrics.maxHeight - aMetrics.emHeight > 0.0) {
|
||||
aMetrics.internalLeading = aMetrics.maxHeight - aMetrics.emHeight;
|
||||
} else {
|
||||
aMetrics.internalLeading = 0.0;
|
||||
}
|
||||
|
||||
aMetrics.emAscent = aMetrics.maxAscent * aMetrics.emHeight
|
||||
/ aMetrics.maxHeight;
|
||||
aMetrics.emDescent = aMetrics.emHeight - aMetrics.emAscent;
|
||||
|
||||
if (GetFontEntry()->IsFixedPitch()) {
|
||||
// Some Quartz fonts are fixed pitch, but there's some glyph with a bigger
|
||||
// advance than the average character width... this forces
|
||||
// those fonts to be recognized like fixed pitch fonts by layout.
|
||||
aMetrics.maxAdvance = aMetrics.aveCharWidth;
|
||||
}
|
||||
|
||||
if (!aMetrics.subscriptOffset) {
|
||||
aMetrics.subscriptOffset = aMetrics.xHeight;
|
||||
}
|
||||
if (!aMetrics.superscriptOffset) {
|
||||
aMetrics.superscriptOffset = aMetrics.xHeight;
|
||||
}
|
||||
|
||||
if (!aMetrics.strikeoutOffset) {
|
||||
aMetrics.strikeoutOffset = aMetrics.xHeight * 0.5;
|
||||
}
|
||||
if (!aMetrics.strikeoutSize) {
|
||||
aMetrics.strikeoutSize = aMetrics.underlineSize;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxFont::SanitizeMetrics(gfxFont::Metrics *aMetrics, PRBool aIsBadUnderlineFont)
|
||||
{
|
||||
|
|
|
@ -223,6 +223,10 @@ public:
|
|||
return PR_TRUE;
|
||||
}
|
||||
|
||||
virtual nsresult GetFontTable(PRUint32 aTableTag, nsTArray<PRUint8>& aBuffer) {
|
||||
return NS_ERROR_FAILURE; // all platform subclasses should reimplement this!
|
||||
}
|
||||
|
||||
void SetFamily(gfxFontFamily* aFamily) {
|
||||
mFamily = aFamily;
|
||||
}
|
||||
|
@ -284,10 +288,6 @@ protected:
|
|||
mFamily(nsnull)
|
||||
{ }
|
||||
|
||||
virtual nsresult GetFontTable(PRUint32 aTableTag, nsTArray<PRUint8>& aBuffer) {
|
||||
return NS_ERROR_FAILURE; // all platform subclasses should reimplement this!
|
||||
}
|
||||
|
||||
virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle, PRBool aNeedsBold) {
|
||||
NS_NOTREACHED("oops, somebody didn't override CreateFontInstance");
|
||||
return nsnull;
|
||||
|
@ -1109,11 +1109,28 @@ protected:
|
|||
// been updated.)
|
||||
virtual void CreatePlatformShaper() { }
|
||||
|
||||
// Helper for subclasses that want to initialize standard metrics from the
|
||||
// tables of sfnt (TrueType/OpenType) fonts.
|
||||
// This will use mFUnitsConvFactor if it is already set, else compute it
|
||||
// from mAdjustedSize and the unitsPerEm in the font's 'head' table.
|
||||
// Returns TRUE and sets mIsValid=TRUE if successful;
|
||||
// Returns TRUE but leaves mIsValid=FALSE if the font seems to be broken.
|
||||
// Returns FALSE if the font does not appear to be an sfnt at all,
|
||||
// and should be handled (if possible) using other APIs.
|
||||
PRBool InitMetricsFromSfntTables(Metrics& aMetrics);
|
||||
|
||||
// Helper to calculate various derived metrics from the results of
|
||||
// InitMetricsFromSfntTables or equivalent platform code
|
||||
void CalculateDerivedMetrics(Metrics& aMetrics);
|
||||
|
||||
// some fonts have bad metrics, this method sanitize them.
|
||||
// if this font has bad underline offset, aIsBadUnderlineFont should be true.
|
||||
void SanitizeMetrics(gfxFont::Metrics *aMetrics, PRBool aIsBadUnderlineFont);
|
||||
};
|
||||
|
||||
// proportion of ascent used for x-height, if unable to read value from font
|
||||
#define DEFAULT_XHEIGHT_FACTOR 0.56f
|
||||
|
||||
class THEBES_API gfxTextRunFactory {
|
||||
NS_INLINE_DECL_REFCOUNTING(gfxTextRunFactory)
|
||||
|
||||
|
|
|
@ -927,31 +927,6 @@ struct TableDirEntry {
|
|||
AutoSwap_PRUint32 length; // Length of this table.
|
||||
};
|
||||
|
||||
struct HeadTable {
|
||||
enum {
|
||||
HEAD_MAGIC_NUMBER = 0x5F0F3CF5,
|
||||
HEAD_CHECKSUM_CALC_CONST = 0xB1B0AFBA
|
||||
};
|
||||
|
||||
AutoSwap_PRUint32 tableVersionNumber; // Fixed, 0x00010000 for version 1.0.
|
||||
AutoSwap_PRUint32 fontRevision; // Set by font manufacturer.
|
||||
AutoSwap_PRUint32 checkSumAdjustment; // To compute: set it to 0, sum the entire font as ULONG, then store 0xB1B0AFBA - sum.
|
||||
AutoSwap_PRUint32 magicNumber; // Set to 0x5F0F3CF5.
|
||||
AutoSwap_PRUint16 flags;
|
||||
AutoSwap_PRUint16 unitsPerEm; // Valid range is from 16 to 16384. This value should be a power of 2 for fonts that have TrueType outlines.
|
||||
AutoSwap_PRUint64 created; // Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer
|
||||
AutoSwap_PRUint64 modified; // Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer
|
||||
AutoSwap_PRInt16 xMin; // For all glyph bounding boxes.
|
||||
AutoSwap_PRInt16 yMin; // For all glyph bounding boxes.
|
||||
AutoSwap_PRInt16 xMax; // For all glyph bounding boxes.
|
||||
AutoSwap_PRInt16 yMax; // For all glyph bounding boxes.
|
||||
AutoSwap_PRUint16 macStyle; // Bit 0: Bold (if set to 1);
|
||||
AutoSwap_PRUint16 lowestRecPPEM; // Smallest readable size in pixels.
|
||||
AutoSwap_PRInt16 fontDirectionHint;
|
||||
AutoSwap_PRInt16 indexToLocFormat;
|
||||
AutoSwap_PRInt16 glyphDataFormat;
|
||||
};
|
||||
|
||||
// name table stores set of name record structures, followed by
|
||||
// large block containing all the strings. name record offset and length
|
||||
// indicates the offset and length within that block.
|
||||
|
@ -961,46 +936,6 @@ struct NameRecordData {
|
|||
PRUint32 length;
|
||||
};
|
||||
|
||||
struct OS2Table {
|
||||
AutoSwap_PRUint16 version; // 0004 = OpenType 1.5
|
||||
AutoSwap_PRInt16 xAvgCharWidth;
|
||||
AutoSwap_PRUint16 usWeightClass;
|
||||
AutoSwap_PRUint16 usWidthClass;
|
||||
AutoSwap_PRUint16 fsType;
|
||||
AutoSwap_PRInt16 ySubscriptXSize;
|
||||
AutoSwap_PRInt16 ySubscriptYSize;
|
||||
AutoSwap_PRInt16 ySubscriptXOffset;
|
||||
AutoSwap_PRInt16 ySubscriptYOffset;
|
||||
AutoSwap_PRInt16 ySuperscriptXSize;
|
||||
AutoSwap_PRInt16 ySuperscriptYSize;
|
||||
AutoSwap_PRInt16 ySuperscriptXOffset;
|
||||
AutoSwap_PRInt16 ySuperscriptYOffset;
|
||||
AutoSwap_PRInt16 yStrikeoutSize;
|
||||
AutoSwap_PRInt16 yStrikeoutPosition;
|
||||
AutoSwap_PRInt16 sFamilyClass;
|
||||
PRUint8 panose[10];
|
||||
AutoSwap_PRUint32 unicodeRange1;
|
||||
AutoSwap_PRUint32 unicodeRange2;
|
||||
AutoSwap_PRUint32 unicodeRange3;
|
||||
AutoSwap_PRUint32 unicodeRange4;
|
||||
PRUint8 achVendID[4];
|
||||
AutoSwap_PRUint16 fsSelection;
|
||||
AutoSwap_PRUint16 usFirstCharIndex;
|
||||
AutoSwap_PRUint16 usLastCharIndex;
|
||||
AutoSwap_PRInt16 sTypoAscender;
|
||||
AutoSwap_PRInt16 sTypoDescender;
|
||||
AutoSwap_PRInt16 sTypoLineGap;
|
||||
AutoSwap_PRUint16 usWinAscent;
|
||||
AutoSwap_PRUint16 usWinDescent;
|
||||
AutoSwap_PRUint32 codePageRange1;
|
||||
AutoSwap_PRUint32 codePageRange2;
|
||||
AutoSwap_PRInt16 sxHeight;
|
||||
AutoSwap_PRInt16 sCapHeight;
|
||||
AutoSwap_PRUint16 usDefaultChar;
|
||||
AutoSwap_PRUint16 usBreakChar;
|
||||
AutoSwap_PRUint16 usMaxContext;
|
||||
};
|
||||
|
||||
// old 'kern' table, supported on Windows
|
||||
// see http://www.microsoft.com/typography/otspec/kern.htm
|
||||
struct KernTableVersion0 {
|
||||
|
|
|
@ -339,6 +339,17 @@ struct AutoSwap_PRUint32 {
|
|||
PRUint32 value;
|
||||
};
|
||||
|
||||
struct AutoSwap_PRInt32 {
|
||||
#ifdef __SUNPRO_CC
|
||||
AutoSwap_PRInt32& operator = (const PRInt32 aValue)
|
||||
{ this->value = NS_SWAP32(aValue); return *this; }
|
||||
#else
|
||||
AutoSwap_PRInt32(PRInt32 aValue) { value = NS_SWAP32(aValue); }
|
||||
#endif
|
||||
operator PRInt32() const { return NS_SWAP32(value); }
|
||||
PRInt32 value;
|
||||
};
|
||||
|
||||
struct AutoSwap_PRUint64 {
|
||||
#ifdef __SUNPRO_CC
|
||||
AutoSwap_PRUint64& operator = (const PRUint64 aValue)
|
||||
|
@ -357,6 +368,103 @@ private:
|
|||
PRUint8 value[3];
|
||||
};
|
||||
|
||||
struct HeadTable {
|
||||
enum {
|
||||
HEAD_MAGIC_NUMBER = 0x5F0F3CF5,
|
||||
HEAD_CHECKSUM_CALC_CONST = 0xB1B0AFBA
|
||||
};
|
||||
|
||||
AutoSwap_PRUint32 tableVersionNumber; // Fixed, 0x00010000 for version 1.0.
|
||||
AutoSwap_PRUint32 fontRevision; // Set by font manufacturer.
|
||||
AutoSwap_PRUint32 checkSumAdjustment; // To compute: set it to 0, sum the entire font as ULONG, then store 0xB1B0AFBA - sum.
|
||||
AutoSwap_PRUint32 magicNumber; // Set to 0x5F0F3CF5.
|
||||
AutoSwap_PRUint16 flags;
|
||||
AutoSwap_PRUint16 unitsPerEm; // Valid range is from 16 to 16384. This value should be a power of 2 for fonts that have TrueType outlines.
|
||||
AutoSwap_PRUint64 created; // Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer
|
||||
AutoSwap_PRUint64 modified; // Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer
|
||||
AutoSwap_PRInt16 xMin; // For all glyph bounding boxes.
|
||||
AutoSwap_PRInt16 yMin; // For all glyph bounding boxes.
|
||||
AutoSwap_PRInt16 xMax; // For all glyph bounding boxes.
|
||||
AutoSwap_PRInt16 yMax; // For all glyph bounding boxes.
|
||||
AutoSwap_PRUint16 macStyle; // Bit 0: Bold (if set to 1);
|
||||
AutoSwap_PRUint16 lowestRecPPEM; // Smallest readable size in pixels.
|
||||
AutoSwap_PRInt16 fontDirectionHint;
|
||||
AutoSwap_PRInt16 indexToLocFormat;
|
||||
AutoSwap_PRInt16 glyphDataFormat;
|
||||
};
|
||||
|
||||
struct OS2Table {
|
||||
AutoSwap_PRUint16 version; // 0004 = OpenType 1.5
|
||||
AutoSwap_PRInt16 xAvgCharWidth;
|
||||
AutoSwap_PRUint16 usWeightClass;
|
||||
AutoSwap_PRUint16 usWidthClass;
|
||||
AutoSwap_PRUint16 fsType;
|
||||
AutoSwap_PRInt16 ySubscriptXSize;
|
||||
AutoSwap_PRInt16 ySubscriptYSize;
|
||||
AutoSwap_PRInt16 ySubscriptXOffset;
|
||||
AutoSwap_PRInt16 ySubscriptYOffset;
|
||||
AutoSwap_PRInt16 ySuperscriptXSize;
|
||||
AutoSwap_PRInt16 ySuperscriptYSize;
|
||||
AutoSwap_PRInt16 ySuperscriptXOffset;
|
||||
AutoSwap_PRInt16 ySuperscriptYOffset;
|
||||
AutoSwap_PRInt16 yStrikeoutSize;
|
||||
AutoSwap_PRInt16 yStrikeoutPosition;
|
||||
AutoSwap_PRInt16 sFamilyClass;
|
||||
PRUint8 panose[10];
|
||||
AutoSwap_PRUint32 unicodeRange1;
|
||||
AutoSwap_PRUint32 unicodeRange2;
|
||||
AutoSwap_PRUint32 unicodeRange3;
|
||||
AutoSwap_PRUint32 unicodeRange4;
|
||||
PRUint8 achVendID[4];
|
||||
AutoSwap_PRUint16 fsSelection;
|
||||
AutoSwap_PRUint16 usFirstCharIndex;
|
||||
AutoSwap_PRUint16 usLastCharIndex;
|
||||
AutoSwap_PRInt16 sTypoAscender;
|
||||
AutoSwap_PRInt16 sTypoDescender;
|
||||
AutoSwap_PRInt16 sTypoLineGap;
|
||||
AutoSwap_PRUint16 usWinAscent;
|
||||
AutoSwap_PRUint16 usWinDescent;
|
||||
AutoSwap_PRUint32 codePageRange1;
|
||||
AutoSwap_PRUint32 codePageRange2;
|
||||
AutoSwap_PRInt16 sxHeight;
|
||||
AutoSwap_PRInt16 sCapHeight;
|
||||
AutoSwap_PRUint16 usDefaultChar;
|
||||
AutoSwap_PRUint16 usBreakChar;
|
||||
AutoSwap_PRUint16 usMaxContext;
|
||||
};
|
||||
|
||||
struct PostTable {
|
||||
AutoSwap_PRUint32 version;
|
||||
AutoSwap_PRInt32 italicAngle;
|
||||
AutoSwap_PRInt16 underlinePosition;
|
||||
AutoSwap_PRUint16 underlineThickness;
|
||||
AutoSwap_PRUint32 isFixedPitch;
|
||||
AutoSwap_PRUint32 minMemType42;
|
||||
AutoSwap_PRUint32 maxMemType42;
|
||||
AutoSwap_PRUint32 minMemType1;
|
||||
AutoSwap_PRUint32 maxMemType1;
|
||||
};
|
||||
|
||||
struct HheaTable {
|
||||
AutoSwap_PRUint32 version;
|
||||
AutoSwap_PRInt16 ascender;
|
||||
AutoSwap_PRInt16 descender;
|
||||
AutoSwap_PRInt16 lineGap;
|
||||
AutoSwap_PRUint16 advanceWidthMax;
|
||||
AutoSwap_PRInt16 minLeftSideBearing;
|
||||
AutoSwap_PRInt16 minRightSideBearing;
|
||||
AutoSwap_PRInt16 xMaxExtent;
|
||||
AutoSwap_PRInt16 caretSlopeRise;
|
||||
AutoSwap_PRInt16 caretSlopeRun;
|
||||
AutoSwap_PRInt16 caretOffset;
|
||||
AutoSwap_PRInt16 reserved1;
|
||||
AutoSwap_PRInt16 reserved2;
|
||||
AutoSwap_PRInt16 reserved3;
|
||||
AutoSwap_PRInt16 reserved4;
|
||||
AutoSwap_PRInt16 metricDataFormat;
|
||||
AutoSwap_PRUint16 numOfLongHorMetrics;
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
// Return just the highest bit of the given value, i.e., the highest
|
||||
|
|
|
@ -324,7 +324,8 @@ gfxGDIFont::Initialize()
|
|||
DWORD len = GetGlyphOutlineW(dc.GetDC(), PRUnichar('x'), GGO_METRICS, &gm, 0, nsnull, &kIdentityMatrix);
|
||||
if (len == GDI_ERROR || gm.gmptGlyphOrigin.y <= 0) {
|
||||
// 56% of ascent, best guess for true type
|
||||
mMetrics->xHeight = ROUND((double)metrics.tmAscent * 0.56);
|
||||
mMetrics->xHeight =
|
||||
ROUND((double)metrics.tmAscent * DEFAULT_XHEIGHT_FACTOR);
|
||||
} else {
|
||||
mMetrics->xHeight = gm.gmptGlyphOrigin.y;
|
||||
}
|
||||
|
@ -349,7 +350,8 @@ gfxGDIFont::Initialize()
|
|||
return;
|
||||
}
|
||||
|
||||
mMetrics->xHeight = ROUND((float)metrics.tmAscent * 0.56f); // 56% of ascent, best guess for non-true type
|
||||
mMetrics->xHeight =
|
||||
ROUND((float)metrics.tmAscent * DEFAULT_XHEIGHT_FACTOR);
|
||||
mMetrics->superscriptOffset = mMetrics->xHeight;
|
||||
mMetrics->subscriptOffset = mMetrics->xHeight;
|
||||
mMetrics->strikeoutSize = 1;
|
||||
|
|
|
@ -204,7 +204,7 @@ public:
|
|||
// All other fonts will be grouped correctly using family...
|
||||
switch (mWindowsFamily) {
|
||||
case FF_DONTCARE:
|
||||
return PR_TRUE;
|
||||
return PR_FALSE;
|
||||
case FF_ROMAN:
|
||||
return aGeneric.EqualsLiteral("serif");
|
||||
case FF_SWISS:
|
||||
|
@ -221,7 +221,7 @@ public:
|
|||
}
|
||||
|
||||
virtual PRBool SupportsLangGroup(nsIAtom* aLangGroup) const {
|
||||
if (!aLangGroup) {
|
||||
if (!aLangGroup || aLangGroup == gfxAtoms::x_unicode) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -91,7 +91,8 @@ gfxMacFont::gfxMacFont(MacOSFontEntry *aFontEntry, const gfxFontStyle *aFontStyl
|
|||
// synthetic oblique by skewing via the font matrix
|
||||
PRBool needsOblique =
|
||||
(mFontEntry != NULL) &&
|
||||
(!mFontEntry->IsItalic() && (mStyle.style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)));
|
||||
(!mFontEntry->IsItalic() &&
|
||||
(mStyle.style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)));
|
||||
|
||||
if (needsOblique) {
|
||||
double skewfactor = (needsOblique ? Fix2X(kATSItalicQDSkew) : 0);
|
||||
|
@ -110,11 +111,13 @@ gfxMacFont::gfxMacFont(MacOSFontEntry *aFontEntry, const gfxFontStyle *aFontStyl
|
|||
cairo_font_options_t *fontOptions = cairo_font_options_create();
|
||||
|
||||
// turn off font anti-aliasing based on user pref setting
|
||||
if (mAdjustedSize <= (float) gfxPlatformMac::GetPlatform()->GetAntiAliasingThreshold()) {
|
||||
if (mAdjustedSize <=
|
||||
(gfxFloat)gfxPlatformMac::GetPlatform()->GetAntiAliasingThreshold()) {
|
||||
cairo_font_options_set_antialias(fontOptions, CAIRO_ANTIALIAS_NONE);
|
||||
}
|
||||
|
||||
mScaledFont = cairo_scaled_font_create(mFontFace, &sizeMatrix, &ctm, fontOptions);
|
||||
mScaledFont = cairo_scaled_font_create(mFontFace, &sizeMatrix, &ctm,
|
||||
fontOptions);
|
||||
cairo_font_options_destroy(fontOptions);
|
||||
|
||||
cairoerr = cairo_scaled_font_status(mScaledFont);
|
||||
|
@ -164,20 +167,14 @@ gfxMacFont::SetupCairoFont(gfxContext *aContext)
|
|||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static double
|
||||
RoundToNearestMultiple(double aValue, double aFraction)
|
||||
{
|
||||
return floor(aValue/aFraction + 0.5) * aFraction;
|
||||
}
|
||||
|
||||
void
|
||||
gfxMacFont::InitMetrics()
|
||||
{
|
||||
gfxFloat size =
|
||||
PR_MAX(((mAdjustedSize != 0.0f) ? mAdjustedSize : mStyle.size), 1.0f);
|
||||
mIsValid = PR_FALSE;
|
||||
::memset(&mMetrics, 0, sizeof(mMetrics));
|
||||
|
||||
PRUint32 upem = ::CGFontGetUnitsPerEm(mCGFont);
|
||||
if (!upem) {
|
||||
mIsValid = PR_FALSE;
|
||||
#ifdef DEBUG
|
||||
char warnBuf[1024];
|
||||
sprintf(warnBuf, "Bad font metrics for: %s (no unitsPerEm value)",
|
||||
|
@ -187,103 +184,87 @@ gfxMacFont::InitMetrics()
|
|||
return;
|
||||
}
|
||||
|
||||
ATSFontMetrics atsMetrics;
|
||||
OSStatus err;
|
||||
mAdjustedSize = PR_MAX(mStyle.size, 1.0f);
|
||||
mFUnitsConvFactor = mAdjustedSize / upem;
|
||||
|
||||
err = ::ATSFontGetHorizontalMetrics(mATSFont, kATSOptionFlagsDefault,
|
||||
&atsMetrics);
|
||||
if (err != noErr) {
|
||||
mIsValid = PR_FALSE;
|
||||
|
||||
#ifdef DEBUG
|
||||
char warnBuf[1024];
|
||||
sprintf(warnBuf, "Bad font metrics for: %s err: %8.8x",
|
||||
NS_ConvertUTF16toUTF8(mFontEntry->Name()).get(), PRUint32(err));
|
||||
NS_WARNING(warnBuf);
|
||||
#endif
|
||||
// Try to read 'sfnt' metrics; for local, non-sfnt fonts ONLY, fall back to
|
||||
// platform APIs. The InitMetrics...() functions will set mIsValid on success.
|
||||
if (!InitMetricsFromSfntTables(mMetrics) &&
|
||||
(!mFontEntry->IsUserFont() || mFontEntry->IsLocalUserFont())) {
|
||||
InitMetricsFromATSMetrics();
|
||||
}
|
||||
if (!mIsValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (atsMetrics.xHeight > 0)
|
||||
mMetrics.xHeight = atsMetrics.xHeight * size;
|
||||
else
|
||||
mMetrics.xHeight = ::CGFontGetXHeight(mCGFont) * size / upem;
|
||||
|
||||
if (mAdjustedSize == 0.0f) {
|
||||
if (mMetrics.xHeight != 0.0f && mStyle.sizeAdjust != 0.0f) {
|
||||
gfxFloat aspect = mMetrics.xHeight / size;
|
||||
mAdjustedSize = mStyle.GetAdjustedSize(aspect);
|
||||
|
||||
// the recursive call to InitMetrics will see the adjusted size,
|
||||
// and set up the rest of the metrics fields accordingly
|
||||
InitMetrics();
|
||||
return;
|
||||
}
|
||||
mAdjustedSize = size;
|
||||
if (mMetrics.xHeight == 0.0) {
|
||||
mMetrics.xHeight = ::CGFontGetXHeight(mCGFont) * mFUnitsConvFactor;
|
||||
}
|
||||
|
||||
mMetrics.superscriptOffset = mMetrics.xHeight;
|
||||
mMetrics.subscriptOffset = mMetrics.xHeight;
|
||||
mMetrics.underlineOffset = atsMetrics.underlinePosition * size;
|
||||
mMetrics.underlineSize = atsMetrics.underlineThickness * size;
|
||||
mMetrics.strikeoutSize = mMetrics.underlineSize;
|
||||
mMetrics.strikeoutOffset = mMetrics.xHeight / 2;
|
||||
if (mStyle.sizeAdjust != 0.0 && mStyle.size > 0.0 &&
|
||||
mMetrics.xHeight > 0.0) {
|
||||
// apply font-size-adjust, and recalculate metrics
|
||||
gfxFloat aspect = mMetrics.xHeight / mStyle.size;
|
||||
mAdjustedSize = mStyle.GetAdjustedSize(aspect);
|
||||
mFUnitsConvFactor = mAdjustedSize / upem;
|
||||
mMetrics.xHeight = 0.0;
|
||||
if (!InitMetricsFromSfntTables(mMetrics) &&
|
||||
(!mFontEntry->IsUserFont() || mFontEntry->IsLocalUserFont())) {
|
||||
InitMetricsFromATSMetrics();
|
||||
}
|
||||
if (!mIsValid) {
|
||||
// this shouldn't happen, as we succeeded earlier before applying
|
||||
// the size-adjust factor! But check anyway, for paranoia's sake.
|
||||
return;
|
||||
}
|
||||
if (mMetrics.xHeight == 0.0) {
|
||||
mMetrics.xHeight = ::CGFontGetXHeight(mCGFont) * mFUnitsConvFactor;
|
||||
}
|
||||
}
|
||||
|
||||
mMetrics.externalLeading = atsMetrics.leading * size;
|
||||
mMetrics.emHeight = size;
|
||||
mMetrics.maxAscent =
|
||||
NS_ceil(RoundToNearestMultiple(atsMetrics.ascent * size, 1/1024.0));
|
||||
mMetrics.maxDescent =
|
||||
NS_ceil(-RoundToNearestMultiple(atsMetrics.descent * size, 1/1024.0));
|
||||
// Once we reach here, we've got basic metrics and set mIsValid = TRUE;
|
||||
// there should be no further points of actual failure in InitMetrics().
|
||||
// (If one is introduced, be sure to reset mIsValid to FALSE!)
|
||||
|
||||
mMetrics.maxHeight = mMetrics.maxAscent + mMetrics.maxDescent;
|
||||
if (mMetrics.maxHeight - mMetrics.emHeight > 0.0)
|
||||
mMetrics.internalLeading = mMetrics.maxHeight - mMetrics.emHeight;
|
||||
else
|
||||
mMetrics.internalLeading = 0.0;
|
||||
mMetrics.emHeight = mAdjustedSize;
|
||||
|
||||
mMetrics.maxAdvance = atsMetrics.maxAdvanceWidth * size + mSyntheticBoldOffset;
|
||||
|
||||
mMetrics.emAscent = mMetrics.maxAscent * mMetrics.emHeight / mMetrics.maxHeight;
|
||||
mMetrics.emDescent = mMetrics.emHeight - mMetrics.emAscent;
|
||||
// Measure/calculate additional metrics, independent of whether we used
|
||||
// the tables directly or ATS metrics APIs
|
||||
|
||||
CFDataRef cmap =
|
||||
::CGFontCopyTableForTag(mCGFont, TRUETYPE_TAG('c','m','a','p'));
|
||||
|
||||
PRUint32 glyphID;
|
||||
gfxFloat xWidth = GetCharWidth(cmap, upem, size, 'x', &glyphID);
|
||||
if (atsMetrics.avgAdvanceWidth != 0.0)
|
||||
mMetrics.aveCharWidth = PR_MIN(atsMetrics.avgAdvanceWidth * size, xWidth);
|
||||
else if (glyphID != 0)
|
||||
mMetrics.aveCharWidth = xWidth;
|
||||
else
|
||||
mMetrics.aveCharWidth = mMetrics.maxAdvance;
|
||||
mMetrics.aveCharWidth += mSyntheticBoldOffset;
|
||||
|
||||
if (mFontEntry->IsFixedPitch()) {
|
||||
// Some Quartz fonts are fixed pitch, but there's some glyph with a bigger
|
||||
// advance than the average character width... this forces
|
||||
// those fonts to be recognized like fixed pitch fonts by layout.
|
||||
mMetrics.maxAdvance = mMetrics.aveCharWidth;
|
||||
if (mMetrics.aveCharWidth <= 0) {
|
||||
mMetrics.aveCharWidth = GetCharWidth(cmap, 'x', &glyphID);
|
||||
if (glyphID == 0) {
|
||||
// we didn't find 'x', so use maxAdvance rather than zero
|
||||
mMetrics.aveCharWidth = mMetrics.maxAdvance;
|
||||
}
|
||||
}
|
||||
mMetrics.aveCharWidth += mSyntheticBoldOffset;
|
||||
mMetrics.maxAdvance += mSyntheticBoldOffset;
|
||||
|
||||
mMetrics.spaceWidth = GetCharWidth(cmap, upem, size, ' ', &glyphID);
|
||||
mMetrics.spaceWidth = GetCharWidth(cmap, ' ', &glyphID);
|
||||
if (glyphID == 0) {
|
||||
// no space glyph?!
|
||||
mMetrics.spaceWidth = mMetrics.aveCharWidth;
|
||||
}
|
||||
mSpaceGlyph = glyphID;
|
||||
|
||||
mMetrics.zeroOrAveCharWidth = GetCharWidth(cmap, upem, size, '0', &glyphID);
|
||||
if (glyphID == 0)
|
||||
mMetrics.zeroOrAveCharWidth = GetCharWidth(cmap, '0', &glyphID);
|
||||
if (glyphID == 0) {
|
||||
mMetrics.zeroOrAveCharWidth = mMetrics.aveCharWidth;
|
||||
}
|
||||
|
||||
if (cmap) {
|
||||
::CFRelease(cmap);
|
||||
}
|
||||
|
||||
mFUnitsConvFactor = mAdjustedSize / upem;
|
||||
CalculateDerivedMetrics(mMetrics);
|
||||
|
||||
SanitizeMetrics(&mMetrics, mFontEntry->mIsBadUnderlineFont);
|
||||
|
||||
mIsValid = PR_TRUE;
|
||||
|
||||
#if 0
|
||||
fprintf (stderr, "Font: %p (%s) size: %f\n", this,
|
||||
NS_ConvertUTF16toUTF8(GetName()).get(), mStyle.size);
|
||||
|
@ -297,8 +278,8 @@ gfxMacFont::InitMetrics()
|
|||
}
|
||||
|
||||
gfxFloat
|
||||
gfxMacFont::GetCharWidth(CFDataRef aCmap, PRUint32 aUpem, gfxFloat aSize,
|
||||
PRUnichar aUniChar, PRUint32 *aGlyphID)
|
||||
gfxMacFont::GetCharWidth(CFDataRef aCmap, PRUnichar aUniChar,
|
||||
PRUint32 *aGlyphID)
|
||||
{
|
||||
CGGlyph glyph = 0;
|
||||
|
||||
|
@ -315,7 +296,7 @@ gfxMacFont::GetCharWidth(CFDataRef aCmap, PRUint32 aUpem, gfxFloat aSize,
|
|||
if (glyph) {
|
||||
int advance;
|
||||
if (::CGFontGetGlyphAdvances(mCGFont, &glyph, 1, &advance)) {
|
||||
return advance * aSize / aUpem;
|
||||
return advance * mFUnitsConvFactor;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -341,3 +322,42 @@ gfxMacFont::GetFontTable(PRUint32 aTag)
|
|||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
// Try to initialize font metrics via ATS font metrics APIs,
|
||||
// and set mIsValid = TRUE on success.
|
||||
// We ONLY call this for local (platform) fonts that are not sfnt format;
|
||||
// for sfnts, including ALL downloadable fonts, use InitMetricsFromSfntTables
|
||||
// because ATSFontGetHorizontalMetrics() has been known to crash when
|
||||
// presented with bad fonts.
|
||||
void
|
||||
gfxMacFont::InitMetricsFromATSMetrics()
|
||||
{
|
||||
ATSFontMetrics atsMetrics;
|
||||
OSStatus err;
|
||||
|
||||
err = ::ATSFontGetHorizontalMetrics(mATSFont, kATSOptionFlagsDefault,
|
||||
&atsMetrics);
|
||||
if (err != noErr) {
|
||||
#ifdef DEBUG
|
||||
char warnBuf[1024];
|
||||
sprintf(warnBuf, "Bad font metrics for: %s err: %8.8x",
|
||||
NS_ConvertUTF16toUTF8(mFontEntry->Name()).get(), PRUint32(err));
|
||||
NS_WARNING(warnBuf);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
mMetrics.underlineOffset = atsMetrics.underlinePosition * mAdjustedSize;
|
||||
mMetrics.underlineSize = atsMetrics.underlineThickness * mAdjustedSize;
|
||||
|
||||
mMetrics.externalLeading = atsMetrics.leading * mAdjustedSize;
|
||||
|
||||
mMetrics.maxAscent = atsMetrics.ascent * mAdjustedSize;
|
||||
mMetrics.maxDescent = -atsMetrics.descent * mAdjustedSize;
|
||||
|
||||
mMetrics.maxAdvance = atsMetrics.maxAdvanceWidth * mAdjustedSize;
|
||||
mMetrics.aveCharWidth = atsMetrics.avgAdvanceWidth * mAdjustedSize;
|
||||
mMetrics.xHeight = atsMetrics.xHeight * mAdjustedSize;
|
||||
|
||||
mIsValid = PR_TRUE;
|
||||
}
|
||||
|
|
|
@ -76,9 +76,12 @@ protected:
|
|||
virtual void CreatePlatformShaper();
|
||||
|
||||
void InitMetrics();
|
||||
void InitMetricsFromATSMetrics();
|
||||
|
||||
gfxFloat GetCharWidth(CFDataRef aCmap, PRUint32 aUpem, gfxFloat aSize,
|
||||
PRUnichar aUniChar, PRUint32 *aGlyphID);
|
||||
// Get width and glyph ID for a character; requires that
|
||||
// mFUnitsConvFactor has been set before this is called
|
||||
gfxFloat GetCharWidth(CFDataRef aCmap, PRUnichar aUniChar,
|
||||
PRUint32 *aGlyphID);
|
||||
|
||||
static void DestroyBlobFunc(void* aUserData);
|
||||
|
||||
|
|
|
@ -66,14 +66,14 @@ public:
|
|||
ATSFontRef GetFontRef();
|
||||
nsresult ReadCMAP();
|
||||
|
||||
virtual nsresult GetFontTable(PRUint32 aTableTag, nsTArray<PRUint8>& aBuffer);
|
||||
|
||||
protected:
|
||||
// for use with data fonts
|
||||
MacOSFontEntry(const nsAString& aPostscriptName, ATSFontRef aFontRef,
|
||||
PRUint16 aWeight, PRUint16 aStretch, PRUint32 aItalicStyle,
|
||||
gfxUserFontData *aUserFontData);
|
||||
|
||||
virtual nsresult GetFontTable(PRUint32 aTableTag, nsTArray<PRUint8>& aBuffer);
|
||||
|
||||
virtual gfxFont* CreateFontInstance(const gfxFontStyle *aFontStyle, PRBool aNeedsBold);
|
||||
|
||||
ATSFontRef mATSFontRef;
|
||||
|
|
|
@ -71,7 +71,7 @@ public:
|
|||
> MapType;
|
||||
|
||||
OpaqueSeenType() {
|
||||
NS_ASSERTION(map.init(1), "Failed to initialize map");
|
||||
(void) map.init(1);
|
||||
}
|
||||
|
||||
bool ok() { return map.initialized(); }
|
||||
|
@ -452,24 +452,18 @@ JetpackActorCommon::RecvMessage(JSContext* cx,
|
|||
JSObject* implGlobal = JS_GetGlobalObject(cx);
|
||||
js::AutoValueRooter rval(cx);
|
||||
|
||||
const uint32 savedOptions =
|
||||
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_DONT_REPORT_UNCAUGHT);
|
||||
|
||||
for (PRUint32 i = 0; i < snapshot.Length(); ++i) {
|
||||
Variant* vp = results ? results->AppendElement() : NULL;
|
||||
rval.set(JSVAL_VOID);
|
||||
if (!JS_CallFunctionValue(cx, implGlobal, snapshot[i], argc, argv,
|
||||
rval.addr())) {
|
||||
// If a receiver throws, we drop the exception on the floor.
|
||||
JS_ClearPendingException(cx);
|
||||
(void) JS_ReportPendingException(cx);
|
||||
if (vp)
|
||||
*vp = void_t();
|
||||
} else if (vp && !jsval_to_Variant(cx, rval.value(), vp))
|
||||
*vp = void_t();
|
||||
}
|
||||
|
||||
JS_SetOptions(cx, savedOptions);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,12 +37,15 @@
|
|||
|
||||
#include "base/basictypes.h"
|
||||
#include "jscntxt.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
#include "mozilla/jetpack/JetpackChild.h"
|
||||
#include "mozilla/jetpack/Handle.h"
|
||||
|
||||
#include "jsarray.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace mozilla {
|
||||
namespace jetpack {
|
||||
|
||||
|
@ -54,18 +57,6 @@ JetpackChild::~JetpackChild()
|
|||
{
|
||||
}
|
||||
|
||||
#define IMPL_PROP_FLAGS (JSPROP_SHARED | \
|
||||
JSPROP_ENUMERATE | \
|
||||
JSPROP_READONLY | \
|
||||
JSPROP_PERMANENT)
|
||||
const JSPropertySpec
|
||||
JetpackChild::sImplProperties[] = {
|
||||
{ "jetpack", 0, IMPL_PROP_FLAGS, UserJetpackGetter, NULL },
|
||||
{ 0, 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
#undef IMPL_PROP_FLAGS
|
||||
|
||||
#define IMPL_METHOD_FLAGS (JSFUN_FAST_NATIVE | \
|
||||
JSPROP_ENUMERATE | \
|
||||
JSPROP_READONLY | \
|
||||
|
@ -79,6 +70,8 @@ JetpackChild::sImplMethods[] = {
|
|||
JS_FN("unregisterReceivers", UnregisterReceivers, 1, IMPL_METHOD_FLAGS),
|
||||
JS_FN("wrap", Wrap, 1, IMPL_METHOD_FLAGS),
|
||||
JS_FN("createHandle", CreateHandle, 0, IMPL_METHOD_FLAGS),
|
||||
JS_FN("createSandbox", CreateSandbox, 0, IMPL_METHOD_FLAGS),
|
||||
JS_FN("evalInSandbox", EvalInSandbox, 2, IMPL_METHOD_FLAGS),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
|
@ -91,7 +84,21 @@ JetpackChild::sGlobalClass = {
|
|||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
|
||||
JSCLASS_NO_OPTIONAL_MEMBERS
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
ReportJetpackErrors(JSContext* cx, const char* message, JSErrorReport* report)
|
||||
{
|
||||
const char* filename = "<unknown>";
|
||||
if (report && report->filename)
|
||||
filename = report->filename;
|
||||
int lineno = -1;
|
||||
if (report)
|
||||
lineno = report->lineno;
|
||||
|
||||
fprintf(stderr, "Jetpack JavaScript Error: %s:%i, %s\n",
|
||||
filename, lineno, message);
|
||||
}
|
||||
|
||||
bool
|
||||
JetpackChild::Init(base::ProcessHandle aParentProcessHandle,
|
||||
MessageLoop* aIOLoop,
|
||||
|
@ -101,31 +108,20 @@ JetpackChild::Init(base::ProcessHandle aParentProcessHandle,
|
|||
return false;
|
||||
|
||||
if (!(mRuntime = JS_NewRuntime(32L * 1024L * 1024L)) ||
|
||||
!(mImplCx = JS_NewContext(mRuntime, 8192)) ||
|
||||
!(mUserCx = JS_NewContext(mRuntime, 8192)))
|
||||
!(mCx = JS_NewContext(mRuntime, 8192)))
|
||||
return false;
|
||||
|
||||
{
|
||||
JSAutoRequest request(mImplCx);
|
||||
JS_SetContextPrivate(mImplCx, this);
|
||||
JSObject* implGlobal =
|
||||
JS_NewGlobalObject(mImplCx, const_cast<JSClass*>(&sGlobalClass));
|
||||
if (!implGlobal ||
|
||||
!JS_InitStandardClasses(mImplCx, implGlobal) ||
|
||||
!JS_DefineProperties(mImplCx, implGlobal,
|
||||
const_cast<JSPropertySpec*>(sImplProperties)) ||
|
||||
!JS_DefineFunctions(mImplCx, implGlobal,
|
||||
const_cast<JSFunctionSpec*>(sImplMethods)))
|
||||
return false;
|
||||
}
|
||||
JS_SetErrorReporter(mCx, ReportJetpackErrors);
|
||||
|
||||
{
|
||||
JSAutoRequest request(mUserCx);
|
||||
JS_SetContextPrivate(mUserCx, this);
|
||||
JSObject* userGlobal =
|
||||
JS_NewGlobalObject(mUserCx, const_cast<JSClass*>(&sGlobalClass));
|
||||
if (!userGlobal ||
|
||||
!JS_InitStandardClasses(mUserCx, userGlobal))
|
||||
JSAutoRequest request(mCx);
|
||||
JS_SetContextPrivate(mCx, this);
|
||||
JSObject* implGlobal =
|
||||
JS_NewGlobalObject(mCx, const_cast<JSClass*>(&sGlobalClass));
|
||||
if (!implGlobal ||
|
||||
!JS_InitStandardClasses(mCx, implGlobal) ||
|
||||
!JS_DefineFunctions(mCx, implGlobal,
|
||||
const_cast<JSFunctionSpec*>(sImplMethods)))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -135,42 +131,37 @@ JetpackChild::Init(base::ProcessHandle aParentProcessHandle,
|
|||
void
|
||||
JetpackChild::CleanUp()
|
||||
{
|
||||
JS_DestroyContext(mUserCx);
|
||||
JS_DestroyContext(mImplCx);
|
||||
ClearReceivers();
|
||||
JS_DestroyContext(mCx);
|
||||
JS_DestroyRuntime(mRuntime);
|
||||
JS_ShutDown();
|
||||
}
|
||||
|
||||
void
|
||||
JetpackChild::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
XRE_ShutdownChildProcess();
|
||||
}
|
||||
|
||||
bool
|
||||
JetpackChild::RecvSendMessage(const nsString& messageName,
|
||||
const nsTArray<Variant>& data)
|
||||
{
|
||||
JSAutoRequest request(mImplCx);
|
||||
return JetpackActorCommon::RecvMessage(mImplCx, messageName, data, NULL);
|
||||
JSAutoRequest request(mCx);
|
||||
return JetpackActorCommon::RecvMessage(mCx, messageName, data, NULL);
|
||||
}
|
||||
|
||||
static bool
|
||||
Evaluate(JSContext* cx, const nsCString& code)
|
||||
bool
|
||||
JetpackChild::RecvEvalScript(const nsString& code)
|
||||
{
|
||||
JSAutoRequest request(cx);
|
||||
js::AutoValueRooter ignored(cx);
|
||||
JS_EvaluateScript(cx, JS_GetGlobalObject(cx), code.get(),
|
||||
code.Length(), "", 1, ignored.addr());
|
||||
JSAutoRequest request(mCx);
|
||||
|
||||
js::AutoValueRooter ignored(mCx);
|
||||
(void) JS_EvaluateUCScript(mCx, JS_GetGlobalObject(mCx), code.get(),
|
||||
code.Length(), "", 1, ignored.addr());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
JetpackChild::RecvLoadImplementation(const nsCString& code)
|
||||
{
|
||||
return Evaluate(mImplCx, code);
|
||||
}
|
||||
|
||||
bool
|
||||
JetpackChild::RecvLoadUserScript(const nsCString& code)
|
||||
{
|
||||
return Evaluate(mUserCx, code);
|
||||
}
|
||||
|
||||
PHandleChild*
|
||||
JetpackChild::AllocPHandle()
|
||||
{
|
||||
|
@ -189,20 +180,10 @@ JetpackChild::GetThis(JSContext* cx)
|
|||
{
|
||||
JetpackChild* self =
|
||||
static_cast<JetpackChild*>(JS_GetContextPrivate(cx));
|
||||
JS_ASSERT(cx == self->mImplCx ||
|
||||
cx == self->mUserCx);
|
||||
JS_ASSERT(cx == self->mCx);
|
||||
return self;
|
||||
}
|
||||
|
||||
JSBool
|
||||
JetpackChild::UserJetpackGetter(JSContext* cx, JSObject* obj, jsval id,
|
||||
jsval* vp)
|
||||
{
|
||||
JSObject* userGlobal = JS_GetGlobalObject(GetThis(cx)->mUserCx);
|
||||
JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(userGlobal));
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
struct MessageResult {
|
||||
nsString msgName;
|
||||
nsTArray<Variant> data;
|
||||
|
@ -420,5 +401,49 @@ JetpackChild::CreateHandle(JSContext* cx, uintN argc, jsval* vp)
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
JetpackChild::CreateSandbox(JSContext* cx, uintN argc, jsval* vp)
|
||||
{
|
||||
if (argc > 0) {
|
||||
JS_ReportError(cx, "createSandbox takes zero arguments");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSObject* obj = JS_NewGlobalObject(cx, const_cast<JSClass*>(&sGlobalClass));
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
|
||||
JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj));
|
||||
return JS_InitStandardClasses(cx, obj);
|
||||
}
|
||||
|
||||
JSBool
|
||||
JetpackChild::EvalInSandbox(JSContext* cx, uintN argc, jsval* vp)
|
||||
{
|
||||
if (argc != 2) {
|
||||
JS_ReportError(cx, "evalInSandbox takes two arguments");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
jsval* argv = JS_ARGV(cx, vp);
|
||||
|
||||
JSObject* obj;
|
||||
if (!JSVAL_IS_OBJECT(argv[0]) ||
|
||||
!(obj = JSVAL_TO_OBJECT(argv[0])) ||
|
||||
&sGlobalClass != JS_GetClass(cx, obj) ||
|
||||
obj == JS_GetGlobalObject(cx)) {
|
||||
JS_ReportError(cx, "The first argument to evalInSandbox must be a global object created using createSandbox.");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSString* str = JS_ValueToString(cx, argv[1]);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
|
||||
js::AutoValueRooter ignored(cx);
|
||||
return JS_EvaluateUCScript(cx, obj, JS_GetStringChars(str), JS_GetStringLength(str), "", 1,
|
||||
ignored.addr());
|
||||
}
|
||||
|
||||
} // namespace jetpack
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -65,24 +65,21 @@ public:
|
|||
void CleanUp();
|
||||
|
||||
protected:
|
||||
NS_OVERRIDE virtual void ActorDestroy(ActorDestroyReason why);
|
||||
|
||||
NS_OVERRIDE virtual bool RecvSendMessage(const nsString& messageName,
|
||||
const nsTArray<Variant>& data);
|
||||
NS_OVERRIDE virtual bool RecvLoadImplementation(const nsCString& code);
|
||||
NS_OVERRIDE virtual bool RecvLoadUserScript(const nsCString& code);
|
||||
NS_OVERRIDE virtual bool RecvEvalScript(const nsString& script);
|
||||
|
||||
NS_OVERRIDE virtual PHandleChild* AllocPHandle();
|
||||
NS_OVERRIDE virtual bool DeallocPHandle(PHandleChild* actor);
|
||||
|
||||
private:
|
||||
JSRuntime* mRuntime;
|
||||
JSContext *mImplCx, *mUserCx;
|
||||
JSContext *mCx;
|
||||
|
||||
static JetpackChild* GetThis(JSContext* cx);
|
||||
|
||||
static const JSPropertySpec sImplProperties[];
|
||||
static JSBool UserJetpackGetter(JSContext* cx, JSObject* obj, jsval idval,
|
||||
jsval* vp);
|
||||
|
||||
static const JSFunctionSpec sImplMethods[];
|
||||
static JSBool SendMessage(JSContext* cx, uintN argc, jsval *vp);
|
||||
static JSBool CallMessage(JSContext* cx, uintN argc, jsval *vp);
|
||||
|
@ -91,6 +88,8 @@ private:
|
|||
static JSBool UnregisterReceivers(JSContext* cx, uintN argc, jsval *vp);
|
||||
static JSBool Wrap(JSContext* cx, uintN argc, jsval *vp);
|
||||
static JSBool CreateHandle(JSContext* cx, uintN argc, jsval *vp);
|
||||
static JSBool CreateSandbox(JSContext* cx, uintN argc, jsval *vp);
|
||||
static JSBool EvalInSandbox(JSContext* cx, uintN argc, jsval *vp);
|
||||
|
||||
static const JSClass sGlobalClass;
|
||||
|
||||
|
|
|
@ -57,44 +57,12 @@ JetpackParent::JetpackParent(JSContext* cx)
|
|||
|
||||
JetpackParent::~JetpackParent()
|
||||
{
|
||||
XRE_GetIOMessageLoop()
|
||||
->PostTask(FROM_HERE, new DeleteTask<JetpackProcessParent>(mSubprocess));
|
||||
if (mSubprocess)
|
||||
Destroy();
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(JetpackParent, nsIJetpack)
|
||||
|
||||
static nsresult
|
||||
ReadFromURI(const nsAString& aURI,
|
||||
nsCString* content)
|
||||
{
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(uri),
|
||||
NS_ConvertUTF16toUTF8(aURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
NS_NewChannel(getter_AddRefs(channel), uri);
|
||||
NS_ENSURE_TRUE(channel, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIInputStream> input;
|
||||
rv = channel->Open(getter_AddRefs(input));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ASSERTION(input, "Channel opened successfully but stream was null?");
|
||||
|
||||
char buffer[256];
|
||||
PRUint32 avail = 0;
|
||||
input->Available(&avail);
|
||||
if (avail) {
|
||||
PRUint32 read = 0;
|
||||
while (NS_SUCCEEDED(input->Read(buffer, sizeof(buffer), &read)) && read) {
|
||||
content->Append(buffer, read);
|
||||
read = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
JetpackParent::SendMessage(const nsAString& aMessageName)
|
||||
{
|
||||
|
@ -159,31 +127,12 @@ JetpackParent::UnregisterReceivers(const nsAString& aMessageName)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
JetpackParent::LoadImplementation(const nsAString& aURI)
|
||||
JetpackParent::EvalScript(const nsAString& aScript)
|
||||
{
|
||||
nsCString code;
|
||||
nsresult rv = ReadFromURI(aURI, &code);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!SendEvalScript(nsString(aScript)))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!code.IsEmpty() &&
|
||||
!SendLoadImplementation(code))
|
||||
rv = NS_ERROR_FAILURE;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
JetpackParent::LoadUserScript(const nsAString& aURI)
|
||||
{
|
||||
nsCString code;
|
||||
nsresult rv = ReadFromURI(aURI, &code);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!code.IsEmpty() &&
|
||||
!SendLoadUserScript(code))
|
||||
rv = NS_ERROR_FAILURE;
|
||||
|
||||
return rv;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -223,6 +172,20 @@ JetpackParent::CreateHandle(nsIVariant** aResult)
|
|||
return xpc->JSToVariant(mContext, OBJECT_TO_JSVAL(hobj), aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
JetpackParent::Destroy()
|
||||
{
|
||||
if (!mSubprocess)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
Close();
|
||||
XRE_GetIOMessageLoop()
|
||||
->PostTask(FROM_HERE, new DeleteTask<JetpackProcessParent>(mSubprocess));
|
||||
mSubprocess = NULL;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PHandleParent*
|
||||
JetpackParent::AllocPHandle()
|
||||
{
|
||||
|
|
|
@ -78,8 +78,7 @@ both:
|
|||
async PHandle();
|
||||
|
||||
child:
|
||||
async LoadImplementation(nsCString code);
|
||||
async LoadUserScript(nsCString code);
|
||||
async EvalScript(nsString code);
|
||||
|
||||
parent:
|
||||
sync CallMessage(nsString messageName,
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
interface nsIVariant;
|
||||
|
||||
[scriptable, uuid(563afdf8-5d2f-4bb2-9ac0-fb82461d2922)]
|
||||
[scriptable, uuid(61A5BE65-FAF2-4FD1-96DF-B13A7AD7D88D)]
|
||||
interface nsIJetpack : nsISupports
|
||||
{
|
||||
void sendMessage(in AString aMessageName
|
||||
|
@ -53,8 +53,9 @@ interface nsIJetpack : nsISupports
|
|||
in jsval aReceiver);
|
||||
void unregisterReceivers(in AString aMessageName);
|
||||
|
||||
void loadImplementation(in AString aURI);
|
||||
void loadUserScript(in AString aURI);
|
||||
void evalScript(in AString aScript);
|
||||
|
||||
nsIVariant createHandle();
|
||||
|
||||
void destroy();
|
||||
};
|
||||
|
|
|
@ -41,3 +41,43 @@ registerReceiver("drop methods", echo);
|
|||
registerReceiver("exception coping", echo);
|
||||
|
||||
registerReceiver("duplicate receivers", echo);
|
||||
|
||||
function ok(c, msg)
|
||||
{
|
||||
sendMessage("test result", c, msg);
|
||||
}
|
||||
|
||||
registerReceiver("test sandbox", function() {
|
||||
var addon = createSandbox();
|
||||
ok(typeof(addon) == "object", "typeof(addon)");
|
||||
ok("Date" in addon, "addon.Date exists");
|
||||
ok(addon.Date !== Date, "Date objects are different");
|
||||
|
||||
var fn = "var x; var c = 3; function doit() { x = 12; return 4; }";
|
||||
evalInSandbox(addon, fn);
|
||||
|
||||
ok(addon.x === undefined, "x is undefined");
|
||||
ok(addon.c == 3, "c is 3");
|
||||
ok(addon.doit() == 4, "doit called successfully");
|
||||
ok(addon.x == 12, "x is now 12");
|
||||
|
||||
var fn2 = "let function barbar{}";
|
||||
try {
|
||||
evalInSandbox(addon, fn2);
|
||||
ok(false, "bad syntax should throw");
|
||||
}
|
||||
catch(e) {
|
||||
ok(true, "bad syntax should throw");
|
||||
}
|
||||
|
||||
var fn3 = "throw new Error('just kidding')";
|
||||
try {
|
||||
evalInSandbox(addon, fn3);
|
||||
ok(false, "thrown error should be caught");
|
||||
}
|
||||
catch(e) {
|
||||
ok(true, "thrown error should be caught");
|
||||
}
|
||||
|
||||
sendMessage("sandbox done");
|
||||
});
|
||||
|
|
|
@ -1,20 +1,41 @@
|
|||
/*
|
||||
var jps = jps || Components.classes["@mozilla.org/jetpack/service;1"]
|
||||
.getService(Components.interfaces.nsIJetpackService),
|
||||
jetpack = null;
|
||||
*/
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
var jps = Components.classes["@mozilla.org/jetpack/service;1"]
|
||||
.getService(Components.interfaces.nsIJetpackService);
|
||||
var jetpack = null;
|
||||
|
||||
load("handle_tests.js");
|
||||
function createHandle() {
|
||||
return jetpack.createHandle();
|
||||
}
|
||||
|
||||
const PR_RDONLY = 0x1;
|
||||
|
||||
function read_file(f)
|
||||
{
|
||||
var fis = Cc["@mozilla.org/network/file-input-stream;1"]
|
||||
.createInstance(Ci.nsIFileInputStream);
|
||||
fis.init(f, PR_RDONLY, 0444, Ci.nsIFileInputStream.CLOSE_ON_EOF);
|
||||
|
||||
var lis = Cc["@mozilla.org/intl/converter-input-stream;1"]
|
||||
.createInstance(Ci.nsIConverterInputStream);
|
||||
lis.init(fis, "UTF-8", 1024, 0);
|
||||
|
||||
var data = "";
|
||||
|
||||
var r = {};
|
||||
while (lis.readString(0x0FFFFFFF, r))
|
||||
data += r.value;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
//jetpack = jps.createJetpack();
|
||||
return;
|
||||
jetpack = jps.createJetpack();
|
||||
run_handle_tests();
|
||||
|
||||
jetpack.loadImplementation("file://" + do_get_file("impl.js").path);
|
||||
jetpack.evalScript(read_file(do_get_file("impl.js")));
|
||||
|
||||
var circ1 = {},
|
||||
circ2 = {},
|
||||
|
@ -165,6 +186,13 @@ function run_test() {
|
|||
jetpack.registerReceiver("duplicate receivers",
|
||||
function() { do_test_finished() });
|
||||
|
||||
jetpack.registerReceiver("test result", function(name, c, msg) {
|
||||
dump("TEST-INFO | test_jetpack.js | remote check '" + msg + "' result: " + c + "\n");
|
||||
do_check_true(c);
|
||||
});
|
||||
jetpack.registerReceiver("sandbox done", do_test_finished);
|
||||
|
||||
do_test_pending();
|
||||
do_test_pending();
|
||||
do_test_pending();
|
||||
do_test_pending();
|
||||
|
@ -186,5 +214,12 @@ function run_test() {
|
|||
undefined, null, true, false, 1, 2, 999, 1/4, "oyez");
|
||||
jetpack.sendMessage("drop methods", drop);
|
||||
jetpack.sendMessage("exception coping");
|
||||
|
||||
jetpack.sendMessage("duplicate receivers");
|
||||
|
||||
jetpack.sendMessage("test sandbox");
|
||||
|
||||
do_register_cleanup(function() {
|
||||
jetpack.destroy();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -204,29 +204,12 @@ nsNPAPIPluginStreamListener::nsNPAPIPluginStreamListener(nsNPAPIPluginInstance*
|
|||
mResponseHeaderBuf(nsnull)
|
||||
{
|
||||
memset(&mNPStream, 0, sizeof(mNPStream));
|
||||
|
||||
NS_IF_ADDREF(mInst);
|
||||
}
|
||||
|
||||
nsNPAPIPluginStreamListener::~nsNPAPIPluginStreamListener(void)
|
||||
nsNPAPIPluginStreamListener::~nsNPAPIPluginStreamListener()
|
||||
{
|
||||
// remove itself from the instance stream list
|
||||
nsNPAPIPluginInstance *inst = mInst;
|
||||
if (inst) {
|
||||
nsInstanceStream * prev = nsnull;
|
||||
for (nsInstanceStream *is = inst->mStreams; is != nsnull; is = is->mNext) {
|
||||
if (is->mPluginStreamListener == this) {
|
||||
if (!prev)
|
||||
inst->mStreams = is->mNext;
|
||||
else
|
||||
prev->mNext = is->mNext;
|
||||
|
||||
delete is;
|
||||
break;
|
||||
}
|
||||
prev = is;
|
||||
}
|
||||
}
|
||||
// remove this from the plugin instance's stream list
|
||||
mInst->mStreamListeners.RemoveElement(this);
|
||||
|
||||
// For those cases when NewStream is never called, we still may need
|
||||
// to fire a notification callback. Return network error as fallback
|
||||
|
@ -240,8 +223,6 @@ nsNPAPIPluginStreamListener::~nsNPAPIPluginStreamListener(void)
|
|||
mStreamBuffer=nsnull;
|
||||
}
|
||||
|
||||
NS_IF_RELEASE(inst);
|
||||
|
||||
if (mNotifyURL)
|
||||
PL_strfree(mNotifyURL);
|
||||
|
||||
|
@ -319,7 +300,6 @@ void nsNPAPIPluginStreamListener::CallURLNotify(NPReason reason)
|
|||
return;
|
||||
|
||||
if (callbacks->urlnotify) {
|
||||
|
||||
NPP npp;
|
||||
mInst->GetNPP(&npp);
|
||||
|
||||
|
@ -473,8 +453,11 @@ nsNPAPIPluginStreamListener::StopDataPump()
|
|||
PRBool
|
||||
nsNPAPIPluginStreamListener::PluginInitJSLoadInProgress()
|
||||
{
|
||||
for (nsInstanceStream *is = mInst->mStreams; is; is = is->mNext) {
|
||||
if (is->mPluginStreamListener->mIsPluginInitJSStream) {
|
||||
if (!mInst)
|
||||
return PR_FALSE;
|
||||
|
||||
for (unsigned int i = 0; i < mInst->mStreamListeners.Length(); i++) {
|
||||
if (mInst->mStreamListeners[i]->mIsPluginInitJSStream) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -873,16 +856,6 @@ nsNPAPIPluginStreamListener::NewResponseHeader(const char* headerName,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsInstanceStream::nsInstanceStream()
|
||||
{
|
||||
mNext = nsnull;
|
||||
mPluginStreamListener = nsnull;
|
||||
}
|
||||
|
||||
nsInstanceStream::~nsInstanceStream()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsNPAPIPluginInstance, nsIPluginInstance)
|
||||
|
||||
nsNPAPIPluginInstance::nsNPAPIPluginInstance(NPPluginFuncs* callbacks,
|
||||
|
@ -903,7 +876,7 @@ nsNPAPIPluginInstance::nsNPAPIPluginInstance(NPPluginFuncs* callbacks,
|
|||
mWantsAllNetworkStreams(PR_FALSE),
|
||||
mInPluginInitCall(PR_FALSE),
|
||||
mLibrary(aLibrary),
|
||||
mStreams(nsnull),
|
||||
mStreamListeners(nsnull),
|
||||
mMIMEType(nsnull),
|
||||
mOwner(nsnull),
|
||||
mCurrentPluginEvent(nsnull)
|
||||
|
@ -918,17 +891,10 @@ nsNPAPIPluginInstance::nsNPAPIPluginInstance(NPPluginFuncs* callbacks,
|
|||
PLUGIN_LOG(PLUGIN_LOG_BASIC, ("nsNPAPIPluginInstance ctor: this=%p\n",this));
|
||||
}
|
||||
|
||||
nsNPAPIPluginInstance::~nsNPAPIPluginInstance(void)
|
||||
nsNPAPIPluginInstance::~nsNPAPIPluginInstance()
|
||||
{
|
||||
PLUGIN_LOG(PLUGIN_LOG_BASIC, ("nsNPAPIPluginInstance dtor: this=%p\n",this));
|
||||
|
||||
// clean the stream list if any
|
||||
for (nsInstanceStream *is = mStreams; is != nsnull;) {
|
||||
nsInstanceStream * next = is->mNext;
|
||||
delete is;
|
||||
is = next;
|
||||
}
|
||||
|
||||
if (mMIMEType) {
|
||||
PR_Free((void *)mMIMEType);
|
||||
mMIMEType = nsnull;
|
||||
|
@ -1004,19 +970,10 @@ NS_IMETHODIMP nsNPAPIPluginInstance::Stop()
|
|||
OnPluginDestroy(&mNPP);
|
||||
|
||||
// clean up open streams
|
||||
for (nsInstanceStream *is = mStreams; is != nsnull;) {
|
||||
nsRefPtr<nsNPAPIPluginStreamListener> listener = is->mPluginStreamListener;
|
||||
|
||||
nsInstanceStream *next = is->mNext;
|
||||
delete is;
|
||||
is = next;
|
||||
mStreams = is;
|
||||
|
||||
// Clean up our stream after removing it from the list because
|
||||
// it may be released and destroyed at this point.
|
||||
if (listener)
|
||||
listener->CleanUpStream(NPRES_USER_BREAK);
|
||||
for (unsigned int i = 0; i < mStreamListeners.Length(); i++) {
|
||||
mStreamListeners[i]->CleanUpStream(NPRES_USER_BREAK);
|
||||
}
|
||||
mStreamListeners.Clear();
|
||||
|
||||
NPError error = NPERR_GENERIC_ERROR;
|
||||
if (mCallbacks->destroy) {
|
||||
|
@ -1296,23 +1253,10 @@ nsresult nsNPAPIPluginInstance::NewNotifyStream(nsIPluginStreamListener** listen
|
|||
nsNPAPIPluginStreamListener* stream = new nsNPAPIPluginStreamListener(this, notifyData, aURL);
|
||||
NS_ENSURE_TRUE(stream, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// add it to the list
|
||||
nsInstanceStream * is = new nsInstanceStream();
|
||||
NS_ENSURE_TRUE(is, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
is->mNext = mStreams;
|
||||
is->mPluginStreamListener = stream;
|
||||
mStreams = is;
|
||||
mStreamListeners.AppendElement(stream);
|
||||
stream->SetCallNotify(aCallNotify); // set flag in stream to call URLNotify
|
||||
|
||||
NS_ADDREF(stream); // Stabilize
|
||||
|
||||
nsresult res = stream->QueryInterface(kIPluginStreamListenerIID, (void**)listener);
|
||||
|
||||
// Destabilize and avoid leaks. Avoid calling delete <interface pointer>
|
||||
NS_RELEASE(stream);
|
||||
|
||||
return res;
|
||||
return stream->QueryInterface(kIPluginStreamListenerIID, (void**)listener);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsNPAPIPluginInstance::Print(NPPrint* platformPrint)
|
||||
|
|
|
@ -56,15 +56,6 @@
|
|||
class nsNPAPIPluginStreamListener;
|
||||
class nsPIDOMWindow;
|
||||
|
||||
struct nsInstanceStream
|
||||
{
|
||||
nsInstanceStream *mNext;
|
||||
nsNPAPIPluginStreamListener *mPluginStreamListener;
|
||||
|
||||
nsInstanceStream();
|
||||
~nsInstanceStream();
|
||||
};
|
||||
|
||||
class nsNPAPITimer
|
||||
{
|
||||
public:
|
||||
|
@ -180,7 +171,7 @@ public:
|
|||
// True while creating the plugin, or calling NPP_SetWindow() on it.
|
||||
PRPackedBool mInPluginInitCall;
|
||||
PluginLibrary* mLibrary;
|
||||
nsInstanceStream *mStreams;
|
||||
nsTArray<nsNPAPIPluginStreamListener*> mStreamListeners;
|
||||
|
||||
private:
|
||||
nsTArray<PopupControlState> mPopupStates;
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "nsIHTTPHeaderListener.h"
|
||||
#include "nsIRequest.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#define MAX_PLUGIN_NECKO_BUFFER 16384
|
||||
|
@ -85,7 +86,7 @@ protected:
|
|||
void* mNotifyData;
|
||||
char* mStreamBuffer;
|
||||
char* mNotifyURL;
|
||||
nsNPAPIPluginInstance* mInst;
|
||||
nsRefPtr<nsNPAPIPluginInstance> mInst;
|
||||
NPStream mNPStream;
|
||||
PRUint32 mStreamBufferSize;
|
||||
PRInt32 mStreamBufferByteCount;
|
||||
|
|
|
@ -69,6 +69,10 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
|
|||
CPPSRCS += nptest_gtk2.cpp
|
||||
endif
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),android)
|
||||
CPPSRCS += nptest_droid.cpp
|
||||
endif
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
|
||||
CPPSRCS += nptest_os2.cpp
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
*
|
||||
* Copyright (c) 2010, Mozilla Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Mozilla Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brad Lassey <blassey@mozilla.com>
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#include "nptest_platform.h"
|
||||
#include "npapi.h"
|
||||
|
||||
struct _PlatformData {
|
||||
};
|
||||
using namespace std;
|
||||
|
||||
bool
|
||||
pluginSupportsWindowMode()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
pluginSupportsWindowlessMode()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
NPError
|
||||
pluginInstanceInit(InstanceData* instanceData)
|
||||
{
|
||||
printf("NPERR_INCOMPATIBLE_VERSION_ERROR\n");
|
||||
return NPERR_INCOMPATIBLE_VERSION_ERROR;
|
||||
}
|
||||
|
||||
void
|
||||
pluginInstanceShutdown(InstanceData* instanceData)
|
||||
{
|
||||
NPN_MemFree(instanceData->platformData);
|
||||
instanceData->platformData = 0;
|
||||
}
|
||||
|
||||
void
|
||||
pluginDoSetWindow(InstanceData* instanceData, NPWindow* newWindow)
|
||||
{
|
||||
instanceData->window = *newWindow;
|
||||
}
|
||||
|
||||
void
|
||||
pluginWidgetInit(InstanceData* instanceData, void* oldWindow)
|
||||
{
|
||||
// XXX nothing here yet since we don't support windowed plugins
|
||||
}
|
||||
|
||||
static void
|
||||
pluginDrawWindow(InstanceData* instanceData, void* event)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t
|
||||
pluginHandleEvent(InstanceData* instanceData, void* event)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t pluginGetEdge(InstanceData* instanceData, RectEdge edge)
|
||||
{
|
||||
// XXX nothing here yet since we don't support windowed plugins
|
||||
return NPTEST_INT32_ERROR;
|
||||
}
|
||||
|
||||
int32_t pluginGetClipRegionRectCount(InstanceData* instanceData)
|
||||
{
|
||||
// XXX nothing here yet since we don't support windowed plugins
|
||||
return NPTEST_INT32_ERROR;
|
||||
}
|
||||
|
||||
int32_t pluginGetClipRegionRectEdge(InstanceData* instanceData,
|
||||
int32_t rectIndex, RectEdge edge)
|
||||
{
|
||||
// XXX nothing here yet since we don't support windowed plugins
|
||||
return NPTEST_INT32_ERROR;
|
||||
}
|
||||
|
||||
void pluginDoInternalConsistencyCheck(InstanceData* instanceData, string& error)
|
||||
{
|
||||
}
|
|
@ -175,7 +175,7 @@ class XPCShellTests(object):
|
|||
'-e', 'print("To start the test, type |_execute_test();|.");',
|
||||
'-i']
|
||||
else:
|
||||
self.xpcsRunArgs = ['-e', '_execute_test();']
|
||||
self.xpcsRunArgs = ['-e', '_execute_test(); quit(0);']
|
||||
|
||||
def getPipes(self):
|
||||
"""
|
||||
|
|
Загрузка…
Ссылка в новой задаче