зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to fx-team.
This commit is contained in:
Коммит
b053ff822a
2
CLOBBER
2
CLOBBER
|
@ -18,4 +18,4 @@
|
|||
# Modifying this file will now automatically clobber the buildbot machines \o/
|
||||
#
|
||||
|
||||
Bug 941844 - Because Android resource builds are flaky.
|
||||
Bug 921918 - need clobber for Windows.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"revision": "2a055e0d4214f04646c15c09a6a03bf96f347689",
|
||||
"revision": "aac07cb753d6c364c3cbd39ad8116d455d5adf01",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -268,7 +268,8 @@ EventSource::Init(nsISupports* aOwner,
|
|||
do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = convManager->GetUnicodeDecoder("UTF-8", getter_AddRefs(mUnicodeDecoder));
|
||||
rv = convManager->GetUnicodeDecoderRaw("UTF-8",
|
||||
getter_AddRefs(mUnicodeDecoder));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// the constructor should throw a SYNTAX_ERROR only if it fails resolving the
|
||||
|
|
|
@ -540,7 +540,8 @@ nsDOMFileReader::ConvertStream(const char *aFileData,
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIUnicodeDecoder> unicodeDecoder;
|
||||
rv = charsetConverter->GetUnicodeDecoder(aCharset, getter_AddRefs(unicodeDecoder));
|
||||
rv = charsetConverter->GetUnicodeDecoderRaw(aCharset,
|
||||
getter_AddRefs(unicodeDecoder));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
int32_t destLength;
|
||||
|
|
|
@ -2724,7 +2724,8 @@ nsDocument::InitCSP(nsIChannel* aChannel)
|
|||
if (csp) {
|
||||
// Copy into principal
|
||||
nsIPrincipal* principal = GetPrincipal();
|
||||
principal->SetCsp(csp);
|
||||
rv = principal->SetCsp(csp);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
#ifdef PR_LOGGING
|
||||
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
||||
("Inserted CSP into principal %p", principal));
|
||||
|
@ -3289,16 +3290,12 @@ nsDocument::GetBaseTarget(nsAString &aBaseTarget)
|
|||
void
|
||||
nsDocument::SetDocumentCharacterSet(const nsACString& aCharSetID)
|
||||
{
|
||||
// XXX it would be a good idea to assert the sanity of the argument,
|
||||
// but before we figure out what to do about non-Encoding Standard
|
||||
// encodings in the charset menu and in mailnews, assertions are futile.
|
||||
if (!mCharacterSet.Equals(aCharSetID)) {
|
||||
mCharacterSet = aCharSetID;
|
||||
|
||||
#ifdef DEBUG
|
||||
nsAutoCString canonicalName;
|
||||
nsCharsetAlias::GetPreferred(aCharSetID, canonicalName);
|
||||
NS_ASSERTION(canonicalName.Equals(aCharSetID),
|
||||
"charset name must be canonical");
|
||||
#endif
|
||||
|
||||
int32_t n = mCharSetObservers.Length();
|
||||
|
||||
for (int32_t i = 0; i < n; i++) {
|
||||
|
|
|
@ -771,6 +771,8 @@ GK_ATOM(onpopuphiding, "onpopuphiding")
|
|||
GK_ATOM(onpopupshowing, "onpopupshowing")
|
||||
GK_ATOM(onpopupshown, "onpopupshown")
|
||||
GK_ATOM(onradiostatechange, "onradiostatechange")
|
||||
GK_ATOM(onreaderror, "onreaderror")
|
||||
GK_ATOM(onreadsuccess, "onreadsuccess")
|
||||
GK_ATOM(onreadystatechange, "onreadystatechange")
|
||||
GK_ATOM(onreceived, "onreceived")
|
||||
GK_ATOM(onremoteheld, "onremoteheld")
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "nsSandboxFlags.h"
|
||||
#include "nsContentTypeParser.h"
|
||||
#include "nsINetworkSeer.h"
|
||||
#include "mozilla/dom/EncodingUtils.h"
|
||||
|
||||
#include "mozilla/CORSMode.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
@ -1197,15 +1198,15 @@ nsScriptLoader::ConvertToUTF16(nsIChannel* aChannel, const uint8_t* aData,
|
|||
if (!unicodeDecoder &&
|
||||
aChannel &&
|
||||
NS_SUCCEEDED(aChannel->GetContentCharset(charset)) &&
|
||||
!charset.IsEmpty()) {
|
||||
charsetConv->GetUnicodeDecoder(charset.get(),
|
||||
getter_AddRefs(unicodeDecoder));
|
||||
EncodingUtils::FindEncodingForLabel(charset, charset)) {
|
||||
charsetConv->GetUnicodeDecoderRaw(charset.get(),
|
||||
getter_AddRefs(unicodeDecoder));
|
||||
}
|
||||
|
||||
if (!unicodeDecoder && !aHintCharset.IsEmpty()) {
|
||||
CopyUTF16toUTF8(aHintCharset, charset);
|
||||
charsetConv->GetUnicodeDecoder(charset.get(),
|
||||
getter_AddRefs(unicodeDecoder));
|
||||
if (!unicodeDecoder &&
|
||||
EncodingUtils::FindEncodingForLabel(aHintCharset, charset)) {
|
||||
charsetConv->GetUnicodeDecoderRaw(charset.get(),
|
||||
getter_AddRefs(unicodeDecoder));
|
||||
}
|
||||
|
||||
if (!unicodeDecoder && aDocument) {
|
||||
|
|
|
@ -79,11 +79,13 @@ class MediaRecorder::Session: public nsIObserver
|
|||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
MediaRecorder *recorder = mSession->mRecorder;
|
||||
if (mSession->IsEncoderError()) {
|
||||
recorder->NotifyError(NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
nsresult rv = recorder->CreateAndDispatchBlobEvent(mSession);
|
||||
if (NS_FAILED(rv)) {
|
||||
recorder->NotifyError(rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -225,6 +227,13 @@ public:
|
|||
return mEncodedBufferCache->ExtractBlob(mimeType);
|
||||
}
|
||||
|
||||
bool IsEncoderError()
|
||||
{
|
||||
if (mEncoder && mEncoder->HasError()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private:
|
||||
|
||||
// Pull encoded meida data from MediaEncoder and put into EncodedBufferCache.
|
||||
|
|
|
@ -148,7 +148,7 @@ MediaEncoder::CreateEncoder(const nsAString& aMIMEType)
|
|||
* If this is the last packet of input stream
|
||||
* Set mState to ENCODE_DONE
|
||||
*
|
||||
* If mState is ENCODE_DONE
|
||||
* If mState is ENCODE_DONE or ENCODE_ERROR
|
||||
* Stop the loop
|
||||
*/
|
||||
void
|
||||
|
@ -164,17 +164,23 @@ MediaEncoder::GetEncodedData(nsTArray<nsTArray<uint8_t> >* aOutputBufs,
|
|||
switch (mState) {
|
||||
case ENCODE_METADDATA: {
|
||||
nsRefPtr<TrackMetadataBase> meta = mAudioEncoder->GetMetadata();
|
||||
MOZ_ASSERT(meta);
|
||||
if (meta == nullptr) {
|
||||
LOG("ERROR! AudioEncoder get null Metadata!");
|
||||
mState = ENCODE_ERROR;
|
||||
break;
|
||||
}
|
||||
nsresult rv = mWriter->SetMetadata(meta);
|
||||
if (NS_FAILED(rv)) {
|
||||
mState = ENCODE_DONE;
|
||||
LOG("ERROR! writer can't accept audio metadata!");
|
||||
mState = ENCODE_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
rv = mWriter->GetContainerData(aOutputBufs,
|
||||
ContainerWriter::GET_HEADER);
|
||||
if (NS_FAILED(rv)) {
|
||||
mState = ENCODE_DONE;
|
||||
LOG("ERROR! writer fail to generate header!");
|
||||
mState = ENCODE_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -188,7 +194,7 @@ MediaEncoder::GetEncodedData(nsTArray<nsTArray<uint8_t> >* aOutputBufs,
|
|||
if (NS_FAILED(rv)) {
|
||||
// Encoding might be canceled.
|
||||
LOG("ERROR! Fail to get encoded data from encoder.");
|
||||
mState = ENCODE_DONE;
|
||||
mState = ENCODE_ERROR;
|
||||
break;
|
||||
}
|
||||
rv = mWriter->WriteEncodedTrack(encodedData,
|
||||
|
@ -196,7 +202,7 @@ MediaEncoder::GetEncodedData(nsTArray<nsTArray<uint8_t> >* aOutputBufs,
|
|||
ContainerWriter::END_OF_STREAM : 0);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG("ERROR! Fail to write encoded track to the media container.");
|
||||
mState = ENCODE_DONE;
|
||||
mState = ENCODE_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -217,7 +223,11 @@ MediaEncoder::GetEncodedData(nsTArray<nsTArray<uint8_t> >* aOutputBufs,
|
|||
mShutdown = true;
|
||||
reloop = false;
|
||||
break;
|
||||
|
||||
case ENCODE_ERROR:
|
||||
LOG("ERROR! MediaEncoder got error!");
|
||||
mShutdown = true;
|
||||
reloop = false;
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Invalid encode state");
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ public :
|
|||
ENCODE_METADDATA,
|
||||
ENCODE_TRACK,
|
||||
ENCODE_DONE,
|
||||
ENCODE_ERROR,
|
||||
};
|
||||
|
||||
MediaEncoder(ContainerWriter* aWriter,
|
||||
|
@ -121,6 +122,11 @@ public :
|
|||
}
|
||||
}
|
||||
|
||||
bool HasError()
|
||||
{
|
||||
return mState == ENCODE_ERROR;
|
||||
}
|
||||
|
||||
private:
|
||||
nsAutoPtr<ContainerWriter> mWriter;
|
||||
nsAutoPtr<AudioTrackEncoder> mAudioEncoder;
|
||||
|
|
|
@ -136,18 +136,17 @@ OpusTrackEncoder::~OpusTrackEncoder()
|
|||
nsresult
|
||||
OpusTrackEncoder::Init(int aChannels, int aSamplingRate)
|
||||
{
|
||||
// The track must have 1 or 2 channels.
|
||||
if (aChannels <= 0 || aChannels > MAX_CHANNELS) {
|
||||
LOG("[Opus] Fail to create the AudioTrackEncoder! The input has"
|
||||
" %d channel(s), but expects no more than %d.", aChannels, MAX_CHANNELS);
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
// This monitor is used to wake up other methods that are waiting for encoder
|
||||
// to be completely initialized.
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
mChannels = aChannels;
|
||||
// This version of encoder API only support 1 or 2 channels,
|
||||
// So set the mChannels less or equal 2 and
|
||||
// let InterleaveTrackData downmix pcm data.
|
||||
mChannels = aChannels > 2 ? 2 : aChannels;
|
||||
|
||||
if (aChannels <= 0) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// The granule position is required to be incremented at a rate of 48KHz, and
|
||||
// it is simply calculated as |granulepos = samples * (48000/source_rate)|,
|
||||
// that is, the source sampling rate must divide 48000 evenly.
|
||||
|
@ -326,10 +325,6 @@ OpusTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
|
|||
// encoding.
|
||||
if (mSourceSegment->GetDuration() == 0 && mEndOfStream) {
|
||||
mDoneEncoding = true;
|
||||
if (mResampler) {
|
||||
speex_resampler_destroy(mResampler);
|
||||
mResampler = nullptr;
|
||||
}
|
||||
LOG("[Opus] Done encoding.");
|
||||
}
|
||||
|
||||
|
@ -358,6 +353,12 @@ OpusTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
|
|||
if (result < 0) {
|
||||
LOG("[Opus] Fail to encode data! Result: %s.", opus_strerror(result));
|
||||
}
|
||||
if (mDoneEncoding) {
|
||||
if (mResampler) {
|
||||
speex_resampler_destroy(mResampler);
|
||||
mResampler = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
audiodata->SetFrameData(&frameData);
|
||||
aData.AppendEncodedFrame(audiodata);
|
||||
|
|
|
@ -141,8 +141,10 @@ protected:
|
|||
uint32_t aOutputChannels, AudioDataValue* aOutput);
|
||||
|
||||
/**
|
||||
* The number of channels in the first valid audio chunk, and is being used
|
||||
* to initialize the audio encoder.
|
||||
* The number of channels are used for processing PCM data in the audio encoder.
|
||||
* This value comes from the first valid audio chunk. If encoder can't support
|
||||
* the channels in the chunk, downmix PCM stream can be performed.
|
||||
* This value also be used to initialize the audio encoder.
|
||||
*/
|
||||
int mChannels;
|
||||
int mSamplingRate;
|
||||
|
|
|
@ -169,6 +169,7 @@ OggWriter::GetContainerData(nsTArray<nsTArray<uint8_t> >* aOutputBufs,
|
|||
nsresult
|
||||
OggWriter::SetMetadata(TrackMetadataBase* aMetadata)
|
||||
{
|
||||
MOZ_ASSERT(aMetadata);
|
||||
if (aMetadata->GetKind() != TrackMetadataBase::METADATA_OPUS) {
|
||||
LOG("wrong meta data type!");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
|
|
@ -237,6 +237,7 @@ support-files =
|
|||
[test_mediarecorder_avoid_recursion.html]
|
||||
[test_mediarecorder_record_timeslice.html]
|
||||
[test_mediarecorder_record_audiocontext.html]
|
||||
[test_mediarecorder_record_4ch_audiocontext.html]
|
||||
[test_mediarecorder_record_stopms.html]
|
||||
[test_mediarecorder_record_nosrc.html]
|
||||
[test_mozHasAudio.html]
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test MediaRecorder Record AudioContext with four channels</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<script type="text/javascript" src="manifest.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
function startTest() {
|
||||
var context = new AudioContext();
|
||||
var buffer = context.createBuffer(4, 80920, context.sampleRate);
|
||||
for (var i = 0; i < 80920; ++i) {
|
||||
for(var j = 0; j < 4; ++j) {
|
||||
buffer.getChannelData(j)[i] = Math.sin(1000 * 2 * Math.PI * i / context.sampleRate);
|
||||
}
|
||||
}
|
||||
|
||||
var source = context.createBufferSource();
|
||||
source.buffer = buffer;
|
||||
var dest = context.createMediaStreamDestination();
|
||||
var stopTriggered = false;
|
||||
var onstopTriggered = false;
|
||||
dest.channelCount = 4;
|
||||
var expectedMimeType = 'audio/ogg';
|
||||
source.channelCountMode = 'explicit';
|
||||
source.connect(dest);
|
||||
var elem = document.createElement('audio');
|
||||
elem.mozSrcObject = dest.stream;
|
||||
mMediaStream = dest.stream;
|
||||
source.start(0);
|
||||
elem.play();
|
||||
mMediaRecorder = new MediaRecorder(dest.stream);
|
||||
mMediaRecorder.onwarning = function() {
|
||||
ok(false, 'onwarning unexpectedly fired');
|
||||
};
|
||||
|
||||
mMediaRecorder.onerror = function() {
|
||||
ok(false, 'onerror unexpectedly fired');
|
||||
};
|
||||
|
||||
mMediaRecorder.onstop = function() {
|
||||
ok(true, 'onstop fired successfully');
|
||||
is(mMediaRecorder.state, 'inactive', 'check recording status is inactive');
|
||||
onstopTriggered = true;
|
||||
SimpleTest.finish();
|
||||
};
|
||||
mMediaRecorder.ondataavailable = function (e) {
|
||||
ok(e.data.size > 0, 'check blob has data');
|
||||
is(mMediaRecorder.mimeType, expectedMimeType, 'blob should has mimetype, return ' + mMediaRecorder.mimeType);
|
||||
if (!stopTriggered) {
|
||||
mMediaRecorder.stop();
|
||||
stopTriggered = true;
|
||||
} else if (onstopTriggered) {
|
||||
ok(false, 'ondataavailable should come before onstop event');
|
||||
}
|
||||
};
|
||||
try {
|
||||
mMediaRecorder.start(1000);
|
||||
is('recording', mMediaRecorder.state, "check record state recording");
|
||||
} catch (e) {
|
||||
ok(false, 'Can t record audio context');
|
||||
}
|
||||
}
|
||||
|
||||
startTest();
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -30,6 +30,8 @@ support-files =
|
|||
file_bug503832.html
|
||||
file_bug655270.html
|
||||
file_bug670318.html
|
||||
file_bug941562-child.html
|
||||
file_bug941562.html
|
||||
print_postdata.sjs
|
||||
test-form_sjis.html
|
||||
|
||||
|
@ -58,6 +60,7 @@ support-files =
|
|||
[browser_bug670318.js]
|
||||
[browser_bug673467.js]
|
||||
[browser_bug92473.js]
|
||||
[browser_bug941562.js]
|
||||
[browser_loadDisallowInherit.js]
|
||||
[browser_loadURI.js]
|
||||
[browser_search_notification.js]
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
|
||||
gBrowser.selectedTab = gBrowser.addTab(rootDir + "file_bug941562.html");
|
||||
gBrowser.selectedBrowser.addEventListener("load", afterOpen, true);
|
||||
}
|
||||
|
||||
function afterOpen(event) {
|
||||
if (event.target != gBrowser.contentDocument) {
|
||||
return;
|
||||
}
|
||||
|
||||
gBrowser.selectedBrowser.removeEventListener("load", afterOpen, true);
|
||||
gBrowser.selectedBrowser.addEventListener("load", afterChangeCharset, true);
|
||||
|
||||
is(gBrowser.contentDocument.documentElement.textContent.indexOf('\u20AC'), 140, "Parent doc should be windows-1252 initially");
|
||||
|
||||
is(gBrowser.contentDocument.getElementsByTagName("iframe")[0].contentDocument.documentElement.textContent.indexOf('\u4E2D'), 77, "Child doc should be HZ-GB-2312 initially");
|
||||
|
||||
BrowserSetForcedCharacterSet("windows-1251");
|
||||
}
|
||||
|
||||
function afterChangeCharset(event) {
|
||||
if (event.target != gBrowser.contentDocument) {
|
||||
return;
|
||||
}
|
||||
|
||||
gBrowser.selectedBrowser.removeEventListener("load", afterChangeCharset, true);
|
||||
|
||||
is(gBrowser.contentDocument.documentElement.textContent.indexOf('\u0402'), 140, "Parent doc should decode as windows-1251 subsequently");
|
||||
is(gBrowser.contentDocument.getElementsByTagName("iframe")[0].contentDocument.documentElement.textContent.indexOf('\u4E2D'), 77, "Child doc should decode as HZ-GB-2312 subsequently");
|
||||
|
||||
is(gBrowser.contentDocument.characterSet, "windows-1251", "Parent doc should report windows-1251 subsequently");
|
||||
is(gBrowser.contentDocument.getElementsByTagName("iframe")[0].contentDocument.characterSet, "HZ-GB-2312", "Child doc should report HZ-GB-2312 subsequently");
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="hz-gb-2312">
|
||||
<meta content="width=device-width, initial-scale=1" name="viewport">
|
||||
<title>meta declaration in parent and meta HZ in child</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>China if decoded as HZ: ~{VP~}</p>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="windows-1252">
|
||||
<meta content="width=device-width, initial-scale=1" name="viewport">
|
||||
<title>meta declaration in parent and meta HZ in child</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>meta declaration in parent and meta HZ in child</h1>
|
||||
|
||||
<p>Euro sign if decoded as Windows-1252: €</p>
|
||||
<p>a with diaeresis if decoded as Windows-1252: ä</p>
|
||||
|
||||
<iframe src="file_bug941562-child.html"></iframe>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -38,6 +38,8 @@ EncodingUtils::IsAsciiCompatible(const nsACString& aPreferredName)
|
|||
return !(aPreferredName.LowerCaseEqualsLiteral("utf-16") ||
|
||||
aPreferredName.LowerCaseEqualsLiteral("utf-16be") ||
|
||||
aPreferredName.LowerCaseEqualsLiteral("utf-16le") ||
|
||||
aPreferredName.LowerCaseEqualsLiteral("replacement") ||
|
||||
aPreferredName.LowerCaseEqualsLiteral("hz-gb-2312") ||
|
||||
aPreferredName.LowerCaseEqualsLiteral("utf-7") ||
|
||||
aPreferredName.LowerCaseEqualsLiteral("x-imap4-modified-utf7"));
|
||||
}
|
||||
|
|
|
@ -21,8 +21,9 @@ TextDecoder::Init(const nsAString& aEncoding, const bool aFatal,
|
|||
EncodingUtils::TrimSpaceCharacters(label);
|
||||
|
||||
// Let encoding be the result of getting an encoding from label.
|
||||
// If encoding is failure, throw a TypeError.
|
||||
if (!EncodingUtils::FindEncodingForLabel(label, mEncoding)) {
|
||||
// If encoding is failure or replacement, throw a TypeError.
|
||||
if (!EncodingUtils::FindEncodingForLabel(label, mEncoding) ||
|
||||
mEncoding.EqualsLiteral("replacement")) {
|
||||
aRv.ThrowTypeError(MSG_ENCODING_NOT_SUPPORTED, &label);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -215,8 +215,10 @@ ks_c_5601-1989=EUC-KR
|
|||
ksc5601=EUC-KR
|
||||
ksc_5601=EUC-KR
|
||||
windows-949=EUC-KR
|
||||
csiso2022kr=ISO-2022-KR
|
||||
iso-2022-kr=ISO-2022-KR
|
||||
csiso2022kr=replacement
|
||||
iso-2022-kr=replacement
|
||||
iso-2022-cn=replacement
|
||||
iso-2022-cn-ext=replacement
|
||||
utf-16=UTF-16LE
|
||||
utf-16le=UTF-16LE
|
||||
utf-16be=UTF-16BE
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<meta charset=utf-8><EFBFBD>
|
|
@ -0,0 +1 @@
|
|||
<meta charset=iso-2022-cn>
|
|
@ -0,0 +1,3 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<iframe src="data:text/html;charset=utf-8,<2C><iframe src='data:text/html;charset=utf-8,PASS'></iframe>" width=400 height=200></iframe>
|
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<html class=reftest-wait>
|
||||
<meta charset=utf-8>
|
||||
<script>
|
||||
function runTest() {
|
||||
var r = document.documentElement;
|
||||
var d = window[0].document;
|
||||
var i = d.createElement("iframe");
|
||||
i.src = "data:text/html,PASS";
|
||||
i.onload = function() {
|
||||
r.removeAttribute("class");
|
||||
}
|
||||
d.body.appendChild(i);
|
||||
}
|
||||
</script>
|
||||
<body onload="runTest();">
|
||||
<iframe src="bug863728-1.html" width=400 height=200></iframe>
|
|
@ -0,0 +1,5 @@
|
|||
<link rel=stylesheet href="data:text/css;charset=iso-2022-kr,html { background-color: red }">
|
||||
<link rel=stylesheet href="data:text/css,html { background-color: red }" charset="iso-2022-cn-ext">
|
||||
<link rel=stylesheet href='data:text/css,@charset "csiso2022kr"; html { background-color: red }'>
|
||||
<script src="data:text/javascript;charset=iso-2022-kr,document.write('FAIL');"></script>
|
||||
<script src="data:text/javascript,document.write('FAIL');" charset="iso-2022-kr"></script>
|
|
@ -0,0 +1,3 @@
|
|||
== bug863728-1.html bug863728-1-ref.html
|
||||
== bug863728-2.html bug863728-2-ref.html
|
||||
== bug863728-3.html bug863728-3-ref.html
|
|
@ -349,11 +349,10 @@ function testDecoderGetEncoding()
|
|||
{encoding: "iso-2022-jp", labels: ["csiso2022jp", "iso-2022-jp"]},
|
||||
{encoding: "shift_jis", labels: ["csshiftjis", "ms_kanji", "shift-jis", "shift_jis", "sjis", "windows-31j", "x-sjis"]},
|
||||
{encoding: "euc-kr", labels: ["cseuckr", "csksc56011987", "euc-kr", "iso-ir-149", "korean", "ks_c_5601-1987", "ks_c_5601-1989", "ksc5601", "ksc_5601", "windows-949"]},
|
||||
{encoding: "iso-2022-kr", labels: ["csiso2022kr", "iso-2022-kr"]},
|
||||
{encoding: "utf-16le", labels: ["utf-16", "utf-16le"]},
|
||||
{encoding: "utf-16be", labels: ["utf-16be"]},
|
||||
{encoding: "x-user-defined", labels: ["x-user-defined"]},
|
||||
{error: "TypeError", labels: ["x-windows-949", "\u0130SO-8859-1"]},
|
||||
{error: "TypeError", labels: ["x-windows-949", "\u0130SO-8859-1", "csiso2022kr", "iso-2022-kr", "iso-2022-cn", "iso-2022-cn-ext", "replacement"]},
|
||||
];
|
||||
|
||||
for (var le of labelEncodings) {
|
||||
|
|
|
@ -24,7 +24,6 @@ setup({explicit_timeout: true});
|
|||
<script type="text/javascript" src="unit/test_iso-2022-jp.js"></script>
|
||||
<script type="text/javascript" src="unit/test_shift_jis.js"></script>
|
||||
<script type="text/javascript" src="unit/test_euc-kr.js"></script>
|
||||
<script type="text/javascript" src="unit/test_iso-2022-kr.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -6,6 +6,5 @@
|
|||
[test_gbk.js]
|
||||
[test_hz-gb-2312.js]
|
||||
[test_iso-2022-jp.js]
|
||||
[test_iso-2022-kr.js]
|
||||
[test_shift_jis.js]
|
||||
[test_singlebytes.js]
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -297,7 +297,7 @@ test(
|
|||
|
||||
test(
|
||||
function () {
|
||||
var encodings = ["utf-8", "ibm866", "iso-8859-2", "iso-8859-3", "iso-8859-4", "iso-8859-5", "iso-8859-6", "iso-8859-7", "iso-8859-8", "iso-8859-8-i", "iso-8859-10", "iso-8859-13", "iso-8859-14", "iso-8859-15", "iso-8859-16", "koi8-r", "koi8-u", "macintosh", "windows-874", "windows-1250", "windows-1251", "windows-1252", "windows-1253", "windows-1254", "windows-1255", "windows-1256", "windows-1257", "windows-1258", "x-mac-cyrillic", "gbk", "gb18030", "hz-gb-2312", "big5", "euc-jp", "iso-2022-jp", "shift_jis", "euc-kr", "iso-2022-kr", "x-user-defined"];
|
||||
var encodings = ["utf-8", "ibm866", "iso-8859-2", "iso-8859-3", "iso-8859-4", "iso-8859-5", "iso-8859-6", "iso-8859-7", "iso-8859-8", "iso-8859-8-i", "iso-8859-10", "iso-8859-13", "iso-8859-14", "iso-8859-15", "iso-8859-16", "koi8-r", "koi8-u", "macintosh", "windows-874", "windows-1250", "windows-1251", "windows-1252", "windows-1253", "windows-1254", "windows-1255", "windows-1256", "windows-1257", "windows-1258", "x-mac-cyrillic", "gbk", "gb18030", "hz-gb-2312", "big5", "euc-jp", "iso-2022-jp", "shift_jis", "euc-kr", "x-user-defined"];
|
||||
|
||||
encodings.forEach(function (encoding) {
|
||||
var string = '', bytes = [];
|
||||
|
@ -308,8 +308,6 @@ test(
|
|||
continue;
|
||||
if (encoding === "iso-2022-jp" && i === 0x1B)
|
||||
continue;
|
||||
if (encoding === "iso-2022-kr" && (i === 0x0E || i === 0x0F || i === 0x1B))
|
||||
continue;
|
||||
|
||||
string += String.fromCharCode(i);
|
||||
bytes.push(i);
|
||||
|
@ -344,7 +342,7 @@ test(
|
|||
|
||||
var utf_encodings = ["utf-8", "utf-16le", "utf-16be"];
|
||||
|
||||
var legacy_encodings = ["ibm866", "iso-8859-2", "iso-8859-3", "iso-8859-4", "iso-8859-5", "iso-8859-6", "iso-8859-7", "iso-8859-8", "iso-8859-8-i", "iso-8859-10", "iso-8859-13", "iso-8859-14", "iso-8859-15", "iso-8859-16", "koi8-r", "koi8-u", "macintosh", "windows-874", "windows-1250", "windows-1251", "windows-1252", "windows-1253", "windows-1254", "windows-1255", "windows-1256", "windows-1257", "windows-1258", "x-mac-cyrillic", "gbk", "gb18030", "hz-gb-2312", "big5", "euc-jp", "iso-2022-jp", "shift_jis", "euc-kr", "iso-2022-kr", "x-user-defined"];
|
||||
var legacy_encodings = ["ibm866", "iso-8859-2", "iso-8859-3", "iso-8859-4", "iso-8859-5", "iso-8859-6", "iso-8859-7", "iso-8859-8", "iso-8859-8-i", "iso-8859-10", "iso-8859-13", "iso-8859-14", "iso-8859-15", "iso-8859-16", "koi8-r", "koi8-u", "macintosh", "windows-874", "windows-1250", "windows-1251", "windows-1252", "windows-1253", "windows-1254", "windows-1255", "windows-1256", "windows-1257", "windows-1258", "x-mac-cyrillic", "gbk", "gb18030", "hz-gb-2312", "big5", "euc-jp", "iso-2022-jp", "shift_jis", "euc-kr", "x-user-defined"];
|
||||
|
||||
utf_encodings.forEach(function(encoding) {
|
||||
assert_equals(TextDecoder(encoding).encoding, encoding);
|
||||
|
|
|
@ -8,6 +8,5 @@ tail =
|
|||
[test_gbk.js]
|
||||
[test_hz-gb-2312.js]
|
||||
[test_iso-2022-jp.js]
|
||||
[test_iso-2022-kr.js]
|
||||
[test_shift_jis.js]
|
||||
[test_singlebytes.js]
|
||||
|
|
|
@ -15,17 +15,9 @@
|
|||
<script type="text/javascript;version=1.7">
|
||||
|
||||
function runTest() {
|
||||
if (!SpecialPowers.isMainProcess()) {
|
||||
window.runTest = function() {
|
||||
todo(false, "Figure out this test for child processes!");
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// doing this IDBRequest should not be able to retrieve the filename and
|
||||
// line number.
|
||||
//setTimeout(indexedDB.deleteDatabase.bind(indexedDB), 0, 'x');
|
||||
setTimeout(indexedDB.deleteDatabase.bind(indexedDB), 0, 'x');
|
||||
setTimeout(function() {
|
||||
ok(true, "Still alive");
|
||||
SimpleTest.finish();
|
||||
|
|
|
@ -74,6 +74,9 @@ this.SystemMessagePermissionsTable = {
|
|||
"sms-delivery-success": {
|
||||
"sms": []
|
||||
},
|
||||
"sms-read-success": {
|
||||
"sms": []
|
||||
},
|
||||
"sms-received": {
|
||||
"sms": []
|
||||
},
|
||||
|
|
|
@ -11,7 +11,7 @@ interface nsIDOMDOMCursor;
|
|||
interface nsIDOMDOMRequest;
|
||||
interface nsIDOMBlob;
|
||||
|
||||
[scriptable, builtinclass, uuid(cfcc7067-083f-4e09-91aa-75067a721b70)]
|
||||
[scriptable, builtinclass, uuid(a99c3538-a8d6-492f-9ece-f6e92f9c00c5)]
|
||||
interface nsIDOMMozMobileMessageManager : nsIDOMEventTarget
|
||||
{
|
||||
nsIDOMDOMRequest getSegmentInfoForText(in DOMString text);
|
||||
|
@ -75,4 +75,6 @@ interface nsIDOMMozMobileMessageManager : nsIDOMEventTarget
|
|||
[implicit_jscontext] attribute jsval onfailed;
|
||||
[implicit_jscontext] attribute jsval ondeliverysuccess;
|
||||
[implicit_jscontext] attribute jsval ondeliveryerror;
|
||||
[implicit_jscontext] attribute jsval onreadsuccess;
|
||||
[implicit_jscontext] attribute jsval onreaderror;
|
||||
};
|
||||
|
|
|
@ -21,6 +21,9 @@ dictionary MmsDeliveryInfo
|
|||
DOMString? deliveryStatus;
|
||||
jsval deliveryTimestamp; // Date object; null if not available (e.g.,
|
||||
// |delivery| = "received" or not yet delivered).
|
||||
DOMString? readStatus;
|
||||
jsval readTimestamp; // Date object. null if not available (e.g.,
|
||||
// |delivery| = "received" or not yet read).
|
||||
};
|
||||
|
||||
[scriptable, builtinclass, uuid(82ca2465-f967-4107-a4da-65b7a15d5dba)]
|
||||
|
|
|
@ -25,30 +25,27 @@ interface nsIRilMobileMessageDatabaseRecordCallback : nsISupports
|
|||
void notify(in nsresult aRv, in jsval aMessageRecord, in nsISupports aDomMessage);
|
||||
};
|
||||
|
||||
[scriptable, uuid(d5374151-7451-4590-a70e-40c49c1369ce)]
|
||||
[scriptable, uuid(a92eba51-e619-4f70-98c5-175a33590582)]
|
||||
interface nsIRilMobileMessageDatabaseService : nsIMobileMessageDatabaseService
|
||||
{
|
||||
/**
|
||||
* |aMessage| Object: should contain the following properties for internal use:
|
||||
* - |type| DOMString: "sms" or "mms"
|
||||
* - |sender| DOMString: the phone number of sender
|
||||
* - |timestamp| Number: the timestamp of received message
|
||||
* - |iccId| DOMString: the ICC ID of the SIM for receiving message
|
||||
* - |iccId| DOMString: [optional] the ICC ID of the SIM for receiving
|
||||
* message if available.
|
||||
*
|
||||
* - If |type| == "sms", we also need:
|
||||
* - |messageClass| DOMString: the message class of received message
|
||||
* - |receiver| DOMString: the phone number of receiver
|
||||
* - |pid| Number: the TP-PID field of the SMS TPDU, default 0.
|
||||
* - |sender| DOMString: the phone number of sender
|
||||
*
|
||||
* - If |type| == "mms", we also need:
|
||||
* - |delivery| DOMString: the delivery state of received message
|
||||
* - |deliveryStatus| DOMString Array: the delivery status of received message
|
||||
* - |deliveryStatus| DOMString: the delivery status of received message
|
||||
* - |receivers| DOMString Array: the phone numbers of receivers
|
||||
* - |phoneNumber| DOMString: [optional] my own phone number.
|
||||
* - |transactionId| DOMString: the transaction ID from MMS PDU header.
|
||||
*
|
||||
* Note: |deliveryStatus| should only contain single string to specify
|
||||
* the delivery status of MMS message for the phone owner self.
|
||||
*/
|
||||
void saveReceivedMessage(in jsval aMessage,
|
||||
[optional] in nsIRilMobileMessageDatabaseCallback aCallback);
|
||||
|
@ -88,15 +85,24 @@ interface nsIRilMobileMessageDatabaseService : nsIMobileMessageDatabaseService
|
|||
/**
|
||||
* |aEnvelopeId| DOMString: the "message-id" specified in the MMS PDU headers.
|
||||
* |aReceiver| DOMString: the phone number of receiver (for MMS; can be null).
|
||||
* |aDelivery| DOMString: the new delivery value to update (can be null).
|
||||
* |aDeliveryStatus| DOMString: the new delivery status to update (can be null).
|
||||
* |aDeliveryStatus| DOMString: the new delivery status to be updated (can be null).
|
||||
* |aCallback| nsIRilMobileMessageDatabaseCallback: an optional callback.
|
||||
*/
|
||||
void setMessageDeliveryByEnvelopeId(in DOMString aEnvelopeId,
|
||||
in DOMString aReceiver,
|
||||
in DOMString aDelivery,
|
||||
in DOMString aDeliveryStatus,
|
||||
[optional] in nsIRilMobileMessageDatabaseCallback aCallback);
|
||||
void setMessageDeliveryStatusByEnvelopeId(in DOMString aEnvelopeId,
|
||||
in DOMString aReceiver,
|
||||
in DOMString aDeliveryStatus,
|
||||
[optional] in nsIRilMobileMessageDatabaseCallback aCallback);
|
||||
|
||||
/**
|
||||
* |aEnvelopeId| DOMString: the "message-id" specified in the MMS PDU headers.
|
||||
* |aReceiver| DOMString: the phone number of receiver (for MMS; can be null).
|
||||
* |aReadStatus| DOMString: the new read status to be updated.
|
||||
* |aCallback| nsIRilMobileMessageDatabaseCallback: an optional callback.
|
||||
*/
|
||||
void setMessageReadStatusByEnvelopeId(in DOMString aEnvelopeId,
|
||||
in DOMString aReceiver,
|
||||
in DOMString aReadStatus,
|
||||
[optional] in nsIRilMobileMessageDatabaseCallback aCallback);
|
||||
|
||||
/**
|
||||
* |aMessageId| Number: the message's DB record ID.
|
||||
|
|
|
@ -15,6 +15,8 @@ const char* kSmsFailedObserverTopic = "sms-failed";
|
|||
const char* kSmsDeliverySuccessObserverTopic = "sms-delivery-success";
|
||||
const char* kSmsDeliveryErrorObserverTopic = "sms-delivery-error";
|
||||
const char* kSilentSmsReceivedObserverTopic = "silent-sms-received";
|
||||
const char* kSmsReadSuccessObserverTopic = "sms-read-success";
|
||||
const char* kSmsReadErrorObserverTopic = "sms-read-error";
|
||||
|
||||
} // namespace mobilemessage
|
||||
} // namespace dom
|
||||
|
|
|
@ -19,6 +19,8 @@ extern const char* kSmsFailedObserverTopic;
|
|||
extern const char* kSmsDeliverySuccessObserverTopic;
|
||||
extern const char* kSmsDeliveryErrorObserverTopic;
|
||||
extern const char* kSilentSmsReceivedObserverTopic;
|
||||
extern const char* kSmsReadSuccessObserverTopic;
|
||||
extern const char* kSmsReadErrorObserverTopic;
|
||||
|
||||
#define DELIVERY_RECEIVED NS_LITERAL_STRING("received")
|
||||
#define DELIVERY_SENDING NS_LITERAL_STRING("sending")
|
||||
|
@ -33,6 +35,11 @@ extern const char* kSilentSmsReceivedObserverTopic;
|
|||
#define DELIVERY_STATUS_REJECTED NS_LITERAL_STRING("rejected")
|
||||
#define DELIVERY_STATUS_MANUAL NS_LITERAL_STRING("manual")
|
||||
|
||||
#define READ_STATUS_NOT_APPLICABLE NS_LITERAL_STRING("not-applicable")
|
||||
#define READ_STATUS_SUCCESS NS_LITERAL_STRING("success")
|
||||
#define READ_STATUS_PENDING NS_LITERAL_STRING("pending")
|
||||
#define READ_STATUS_ERROR NS_LITERAL_STRING("error")
|
||||
|
||||
#define MESSAGE_CLASS_NORMAL NS_LITERAL_STRING("normal")
|
||||
#define MESSAGE_CLASS_CLASS_0 NS_LITERAL_STRING("class-0")
|
||||
#define MESSAGE_CLASS_CLASS_1 NS_LITERAL_STRING("class-1")
|
||||
|
|
|
@ -145,6 +145,40 @@ MmsMessage::MmsMessage(const mobilemessage::MmsMessageData& aData)
|
|||
}
|
||||
}
|
||||
|
||||
// Prepare |info.readStatus|.
|
||||
nsString statusReadString;
|
||||
switch(infoData.readStatus()) {
|
||||
case eReadStatus_NotApplicable:
|
||||
statusReadString = READ_STATUS_NOT_APPLICABLE;
|
||||
break;
|
||||
case eReadStatus_Success:
|
||||
statusReadString = READ_STATUS_SUCCESS;
|
||||
break;
|
||||
case eReadStatus_Pending:
|
||||
statusReadString = READ_STATUS_PENDING;
|
||||
break;
|
||||
case eReadStatus_Error:
|
||||
statusReadString = READ_STATUS_ERROR;
|
||||
break;
|
||||
case eReadStatus_EndGuard:
|
||||
default:
|
||||
MOZ_CRASH("We shouldn't get any other read status!");
|
||||
}
|
||||
info.readStatus = statusReadString;
|
||||
|
||||
// Prepare |info.readTimestamp|.
|
||||
info.readTimestamp = JSVAL_NULL;
|
||||
if (infoData.readTimestamp() != 0) {
|
||||
AutoJSContext cx;
|
||||
JS::Rooted<JSObject*>
|
||||
dateObj(cx, JS_NewDateObjectMsec(cx, infoData.readTimestamp()));
|
||||
if (!dateObj) {
|
||||
NS_WARNING("MmsMessage: Unable to create Data for readTimestamp.");
|
||||
} else {
|
||||
info.readTimestamp = OBJECT_TO_JSVAL(dateObj);
|
||||
}
|
||||
}
|
||||
|
||||
mDeliveryInfo.AppendElement(info);
|
||||
}
|
||||
}
|
||||
|
@ -376,6 +410,29 @@ MmsMessage::GetData(ContentParent* aParent,
|
|||
convertTimeToInt(cx, info.deliveryTimestamp, infoData.deliveryTimestamp());
|
||||
}
|
||||
|
||||
// Prepare |infoData.readStatus|.
|
||||
ReadStatus readStatus;
|
||||
if (info.readStatus.Equals(READ_STATUS_NOT_APPLICABLE)) {
|
||||
readStatus = eReadStatus_NotApplicable;
|
||||
} else if (info.readStatus.Equals(READ_STATUS_SUCCESS)) {
|
||||
readStatus = eReadStatus_Success;
|
||||
} else if (info.readStatus.Equals(READ_STATUS_PENDING)) {
|
||||
readStatus = eReadStatus_Pending;
|
||||
} else if (info.readStatus.Equals(READ_STATUS_ERROR)) {
|
||||
readStatus = eReadStatus_Error;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
infoData.readStatus() = readStatus;
|
||||
|
||||
// Prepare |infoData.readTimestamp|.
|
||||
if (info.readTimestamp == JSVAL_NULL) {
|
||||
infoData.readTimestamp() = 0;
|
||||
} else {
|
||||
AutoJSContext cx;
|
||||
convertTimeToInt(cx, info.readTimestamp, infoData.readTimestamp());
|
||||
}
|
||||
|
||||
aData.deliveryInfo().AppendElement(infoData);
|
||||
}
|
||||
|
||||
|
@ -521,6 +578,24 @@ MmsMessage::GetDeliveryInfo(JSContext* aCx, JS::Value* aDeliveryInfo)
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Get |info.readStatus|.
|
||||
tmpJsStr = JS_NewUCStringCopyN(aCx,
|
||||
info.readStatus.get(),
|
||||
info.readStatus.Length());
|
||||
NS_ENSURE_TRUE(tmpJsStr, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
tmpJsVal.setString(tmpJsStr);
|
||||
if (!JS_DefineProperty(aCx, infoJsObj, "readStatus", tmpJsVal,
|
||||
NULL, NULL, JSPROP_ENUMERATE)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Get |info.readTimestamp|.
|
||||
if (!JS_DefineProperty(aCx, infoJsObj, "readTimestamp", info.readTimestamp,
|
||||
NULL, NULL, JSPROP_ENUMERATE)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
tmpJsVal = OBJECT_TO_JSVAL(infoJsObj);
|
||||
if (!JS_SetElement(aCx, deliveryInfo, i, &tmpJsVal)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
|
|
|
@ -38,6 +38,8 @@
|
|||
#define FAILED_EVENT_NAME NS_LITERAL_STRING("failed")
|
||||
#define DELIVERY_SUCCESS_EVENT_NAME NS_LITERAL_STRING("deliverysuccess")
|
||||
#define DELIVERY_ERROR_EVENT_NAME NS_LITERAL_STRING("deliveryerror")
|
||||
#define READ_SUCCESS_EVENT_NAME NS_LITERAL_STRING("readsuccess")
|
||||
#define READ_ERROR_EVENT_NAME NS_LITERAL_STRING("readerror")
|
||||
|
||||
using namespace mozilla::dom::mobilemessage;
|
||||
|
||||
|
@ -62,6 +64,8 @@ NS_IMPL_EVENT_HANDLER(MobileMessageManager, sent)
|
|||
NS_IMPL_EVENT_HANDLER(MobileMessageManager, failed)
|
||||
NS_IMPL_EVENT_HANDLER(MobileMessageManager, deliverysuccess)
|
||||
NS_IMPL_EVENT_HANDLER(MobileMessageManager, deliveryerror)
|
||||
NS_IMPL_EVENT_HANDLER(MobileMessageManager, readsuccess)
|
||||
NS_IMPL_EVENT_HANDLER(MobileMessageManager, readerror)
|
||||
|
||||
void
|
||||
MobileMessageManager::Init(nsPIDOMWindow *aWindow)
|
||||
|
@ -81,6 +85,8 @@ MobileMessageManager::Init(nsPIDOMWindow *aWindow)
|
|||
obs->AddObserver(this, kSmsFailedObserverTopic, false);
|
||||
obs->AddObserver(this, kSmsDeliverySuccessObserverTopic, false);
|
||||
obs->AddObserver(this, kSmsDeliveryErrorObserverTopic, false);
|
||||
obs->AddObserver(this, kSmsReadSuccessObserverTopic, false);
|
||||
obs->AddObserver(this, kSmsReadErrorObserverTopic, false);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -99,6 +105,8 @@ MobileMessageManager::Shutdown()
|
|||
obs->RemoveObserver(this, kSmsFailedObserverTopic);
|
||||
obs->RemoveObserver(this, kSmsDeliverySuccessObserverTopic);
|
||||
obs->RemoveObserver(this, kSmsDeliveryErrorObserverTopic);
|
||||
obs->RemoveObserver(this, kSmsReadSuccessObserverTopic);
|
||||
obs->RemoveObserver(this, kSmsReadErrorObserverTopic);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -536,6 +544,14 @@ MobileMessageManager::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
return DispatchTrustedSmsEventToSelf(aTopic, DELIVERY_ERROR_EVENT_NAME, aSubject);
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, kSmsReadSuccessObserverTopic)) {
|
||||
return DispatchTrustedSmsEventToSelf(aTopic, READ_SUCCESS_EVENT_NAME, aSubject);
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, kSmsReadErrorObserverTopic)) {
|
||||
return DispatchTrustedSmsEventToSelf(aTopic, READ_ERROR_EVENT_NAME, aSubject);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,16 @@ enum DeliveryStatus {
|
|||
eDeliveryStatus_EndGuard
|
||||
};
|
||||
|
||||
// For MmsMessageData.readStatus.
|
||||
enum ReadStatus {
|
||||
eReadStatus_NotApplicable = 0,
|
||||
eReadStatus_Success,
|
||||
eReadStatus_Pending,
|
||||
eReadStatus_Error,
|
||||
// This state should stay at the end.
|
||||
eReadStatus_EndGuard
|
||||
};
|
||||
|
||||
// For {Mms,Sms}FilterData.read.
|
||||
enum ReadState {
|
||||
eReadState_Unknown = -1,
|
||||
|
@ -92,6 +102,16 @@ struct ParamTraits<mozilla::dom::mobilemessage::DeliveryStatus>
|
|||
mozilla::dom::mobilemessage::eDeliveryStatus_EndGuard>
|
||||
{};
|
||||
|
||||
/**
|
||||
* Read status serializer.
|
||||
*/
|
||||
template <>
|
||||
struct ParamTraits<mozilla::dom::mobilemessage::ReadStatus>
|
||||
: public EnumSerializer<mozilla::dom::mobilemessage::ReadStatus,
|
||||
mozilla::dom::mobilemessage::eReadStatus_NotApplicable,
|
||||
mozilla::dom::mobilemessage::eReadStatus_EndGuard>
|
||||
{};
|
||||
|
||||
/**
|
||||
* Read state serializer.
|
||||
*/
|
||||
|
|
|
@ -45,6 +45,48 @@ function defineLazyRegExp(obj, name, pattern) {
|
|||
});
|
||||
}
|
||||
|
||||
function RangedValue(name, min, max) {
|
||||
this.name = name;
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
RangedValue.prototype = {
|
||||
name: null,
|
||||
min: null,
|
||||
max: null,
|
||||
|
||||
/**
|
||||
* @param data
|
||||
* A wrapped object containing raw PDU data.
|
||||
*
|
||||
* @return A decoded integer.
|
||||
*
|
||||
* @throws CodeError if decoded value is not in the range [this.min, this.max].
|
||||
*/
|
||||
decode: function decode(data) {
|
||||
let value = WSP.Octet.decode(data);
|
||||
if ((value >= this.min) && (value <= this.max)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
throw new WSP.CodeError(this.name + ": invalid value " + value);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param data
|
||||
* A wrapped object to store encoded raw data.
|
||||
* @param value
|
||||
* An integer value within thr range [this.min, this.max].
|
||||
*/
|
||||
encode: function encode(data, value) {
|
||||
if ((value < this.min) || (value > this.max)) {
|
||||
throw new WSP.CodeError(this.name + ": invalid value " + value);
|
||||
}
|
||||
|
||||
WSP.Octet.encode(data, value);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Internal decoding function for boolean values.
|
||||
*
|
||||
|
@ -337,44 +379,21 @@ this.MmsHeader = {
|
|||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Cancel-status-value = Cancel Request Successfully received |
|
||||
* Cancel Request corrupted
|
||||
*
|
||||
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.7
|
||||
*/
|
||||
this.CancelStatusValue = new RangedValue("Cancel-status-value", 128, 129);
|
||||
|
||||
/**
|
||||
* Content-class-value = text | image-basic| image-rich | video-basic |
|
||||
* video-rich | megapixel | content-basic | content-rich
|
||||
*
|
||||
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.9
|
||||
*/
|
||||
this.ContentClassValue = {
|
||||
/**
|
||||
* @param data
|
||||
* A wrapped object containing raw PDU data.
|
||||
*
|
||||
* @return A integer value for each class.
|
||||
*
|
||||
* @throws CodeError if decoded value is not in range 128..135.
|
||||
*/
|
||||
decode: function decode(data) {
|
||||
let value = WSP.Octet.decode(data);
|
||||
if ((value >= 128) && (value <= 135)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
throw new WSP.CodeError("Content-class-value: invalid class " + value);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param data
|
||||
* A wrapped object to store encoded raw data.
|
||||
* @param value
|
||||
* A numeric content class value to be encoded.
|
||||
*/
|
||||
encode: function encode(data, value) {
|
||||
if ((value < 128) || (value > 135)) {
|
||||
throw new WSP.CodeError("Content-class-value: invalid class " + value);
|
||||
}
|
||||
|
||||
WSP.Octet.encode(data, value);
|
||||
},
|
||||
};
|
||||
this.ContentClassValue = new RangedValue("Content-class-value", 128, 135);
|
||||
|
||||
/**
|
||||
* When used in a PDU other than M-Mbox-Delete.conf and M-Delete.conf:
|
||||
|
@ -969,40 +988,7 @@ this.MessageClassValue = {
|
|||
*
|
||||
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.30
|
||||
*/
|
||||
this.MessageTypeValue = {
|
||||
/**
|
||||
* @param data
|
||||
* A wrapped object containing raw PDU data.
|
||||
*
|
||||
* @return A decoded integer.
|
||||
*
|
||||
* @throws CodeError if decoded value is not in the range 128..151.
|
||||
*/
|
||||
decode: function decode(data) {
|
||||
let type = WSP.Octet.decode(data);
|
||||
if ((type >= 128) && (type <= 151)) {
|
||||
return type;
|
||||
}
|
||||
|
||||
throw new WSP.CodeError("Message-type-value: invalid type " + type);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param data
|
||||
* A wrapped object to store encoded raw data.
|
||||
* @param type
|
||||
* A numeric message type value to be encoded.
|
||||
*
|
||||
* @throws CodeError if the value is not in the range 128..151.
|
||||
*/
|
||||
encode: function encode(data, type) {
|
||||
if ((type < 128) || (type > 151)) {
|
||||
throw new WSP.CodeError("Message-type-value: invalid type " + type);
|
||||
}
|
||||
|
||||
WSP.Octet.encode(data, type);
|
||||
},
|
||||
};
|
||||
this.MessageTypeValue = new RangedValue("Message-type-value", 128, 151);
|
||||
|
||||
/**
|
||||
* MM-flags-value = Value-length ( Add-token | Remove-token | Filter-token ) Encoded-string-value
|
||||
|
@ -1075,40 +1061,7 @@ this.MmFlagsValue = {
|
|||
*
|
||||
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.33
|
||||
*/
|
||||
this.MmStateValue = {
|
||||
/**
|
||||
* @param data
|
||||
* A wrapped object containing raw PDU data.
|
||||
*
|
||||
* @return A decoded integer.
|
||||
*
|
||||
* @throws CodeError if decoded value is not in the range 128..132.
|
||||
*/
|
||||
decode: function decode(data) {
|
||||
let state = WSP.Octet.decode(data);
|
||||
if ((state >= 128) && (state <= 132)) {
|
||||
return state;
|
||||
}
|
||||
|
||||
throw new WSP.CodeError("MM-state-value: invalid state " + state);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param data
|
||||
* A wrapped object to store encoded raw data.
|
||||
* @param state
|
||||
* A numeric state value to be encoded.
|
||||
*
|
||||
* @throws CodeError if state is not in the range 128..132.
|
||||
*/
|
||||
encode: function encode(data, state) {
|
||||
if ((state < 128) || (state > 132)) {
|
||||
throw new WSP.CodeError("MM-state-value: invalid state " + state);
|
||||
}
|
||||
|
||||
WSP.Octet.encode(data, state);
|
||||
},
|
||||
};
|
||||
this.MmStateValue = new RangedValue("MM-state-value", 128, 132);
|
||||
|
||||
/**
|
||||
* Priority-value = Low | Normal | High
|
||||
|
@ -1118,38 +1071,14 @@ this.MmStateValue = {
|
|||
*
|
||||
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.35
|
||||
*/
|
||||
this.PriorityValue = {
|
||||
/**
|
||||
* @param data
|
||||
* A wrapped object containing raw PDU data.
|
||||
*
|
||||
* @return A decoded integer.
|
||||
*
|
||||
* @throws CodeError if decoded value is not in the range 128..130.
|
||||
*/
|
||||
decode: function decode(data) {
|
||||
let priority = WSP.Octet.decode(data);
|
||||
if ((priority >= 128) && (priority <= 130)) {
|
||||
return priority;
|
||||
}
|
||||
this.PriorityValue = new RangedValue("Priority-value", 128, 130);
|
||||
|
||||
throw new WSP.CodeError("Priority-value: invalid priority " + priority);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param data
|
||||
* A wrapped object to store encoded raw data.
|
||||
* @param priority
|
||||
* A numeric priority value to be encoded.
|
||||
*/
|
||||
encode: function encode(data, priority) {
|
||||
if ((priority < 128) || (priority > 130)) {
|
||||
throw new WSP.CodeError("Priority-value: invalid priority " + priority);
|
||||
}
|
||||
|
||||
WSP.Octet.encode(data, priority);
|
||||
},
|
||||
};
|
||||
/**
|
||||
* Read-status-value = Read | Deleted without being read
|
||||
*
|
||||
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.38
|
||||
*/
|
||||
this.ReadStatusValue = new RangedValue("Read-status-value", 128, 129);
|
||||
|
||||
/**
|
||||
* Recommended-Retrieval-Mode-value = Manual
|
||||
|
@ -1179,38 +1108,7 @@ this.RecommendedRetrievalModeValue = {
|
|||
*
|
||||
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.43
|
||||
*/
|
||||
this.ReplyChargingValue = {
|
||||
/**
|
||||
* @param data
|
||||
* A wrapped object containing raw PDU data.
|
||||
*
|
||||
* @return A decoded integer.
|
||||
*
|
||||
* @throws CodeError if decoded value is not in the range 128..131.
|
||||
*/
|
||||
decode: function decode(data) {
|
||||
let value = WSP.Octet.decode(data);
|
||||
if ((value >= 128) && (value <= 131)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
throw new WSP.CodeError("Reply-charging-value: invalid value " + value);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param data
|
||||
* A wrapped object to store encoded raw data.
|
||||
* @param value
|
||||
* An integer value within thr range 128..131.
|
||||
*/
|
||||
encode: function encode(data, value) {
|
||||
if ((value < 128) || (value > 131)) {
|
||||
throw new WSP.CodeError("Reply-charging-value: invalid value " + value);
|
||||
}
|
||||
|
||||
WSP.Octet.encode(data, value);
|
||||
},
|
||||
};
|
||||
this.ReplyChargingValue = new RangedValue("Reply-charging-value", 128, 131);
|
||||
|
||||
/**
|
||||
* When used in a PDU other than M-Mbox-Delete.conf and M-Delete.conf:
|
||||
|
@ -1299,6 +1197,13 @@ this.RetrieveStatusValue = {
|
|||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Sender-visibility-value = Hide | Show
|
||||
*
|
||||
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.52
|
||||
*/
|
||||
this.SenderVisibilityValue = new RangedValue("Sender-visibility-value", 128, 129);
|
||||
|
||||
/**
|
||||
* Status-value = Expired | Retrieved | Rejected | Deferred | Unrecognised |
|
||||
* Indeterminate | Forwarded | Unreachable
|
||||
|
@ -1313,40 +1218,7 @@ this.RetrieveStatusValue = {
|
|||
*
|
||||
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.54
|
||||
*/
|
||||
this.StatusValue = {
|
||||
/**
|
||||
* @param data
|
||||
* A wrapped object containing raw PDU data.
|
||||
*
|
||||
* @return A decoded integer.
|
||||
*
|
||||
* @throws CodeError if decoded value is not in the range 128..135.
|
||||
*/
|
||||
decode: function decode(data) {
|
||||
let status = WSP.Octet.decode(data);
|
||||
if ((status >= 128) && (status <= 135)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
throw new WSP.CodeError("Status-value: invalid status " + status);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param data
|
||||
* A wrapped object to store encoded raw data.
|
||||
* @param value
|
||||
* A numeric status value to be encoded.
|
||||
*
|
||||
* @throws CodeError if the value is not in the range 128..135.
|
||||
*/
|
||||
encode: function encode(data, value) {
|
||||
if ((value < 128) || (value > 135)) {
|
||||
throw new WSP.CodeError("Status-value: invalid status " + value);
|
||||
}
|
||||
|
||||
WSP.Octet.encode(data, value);
|
||||
},
|
||||
};
|
||||
this.StatusValue = new RangedValue("Status-value", 128, 135);
|
||||
|
||||
this.PduHelper = {
|
||||
/**
|
||||
|
@ -1632,6 +1504,13 @@ const MMS_PDU_TYPES = (function () {
|
|||
"to",
|
||||
"from",
|
||||
"x-mms-read-status"]);
|
||||
add(MMS_PDU_TYPE_READ_ORIG_IND, false, ["x-mms-message-type",
|
||||
"x-mms-mms-version",
|
||||
"message-id",
|
||||
"to",
|
||||
"from",
|
||||
"date",
|
||||
"x-mms-read-status"]);
|
||||
|
||||
return pdus;
|
||||
})();
|
||||
|
@ -1671,14 +1550,14 @@ const MMS_HEADER_FIELDS = (function () {
|
|||
add("x-mms-report-allowed", 0x11, BooleanValue);
|
||||
add("x-mms-response-status", 0x12, RetrieveStatusValue);
|
||||
add("x-mms-response-text", 0x13, ResponseText);
|
||||
add("x-mms-sender-visibility", 0x14, BooleanValue);
|
||||
add("x-mms-sender-visibility", 0x14, SenderVisibilityValue);
|
||||
add("x-mms-status", 0x15, StatusValue);
|
||||
add("subject", 0x16, EncodedStringValue);
|
||||
add("to", 0x17, Address);
|
||||
add("x-mms-transaction-id", 0x18, WSP.TextString);
|
||||
add("x-mms-retrieve-status", 0x19, RetrieveStatusValue);
|
||||
add("x-mms-retrieve-text", 0x1A, EncodedStringValue);
|
||||
add("x-mms-read-status", 0x1B, BooleanValue);
|
||||
add("x-mms-read-status", 0x1B, ReadStatusValue);
|
||||
add("x-mms-reply-charging", 0x1C, ReplyChargingValue);
|
||||
add("x-mms-reply-charging-deadline", 0x1D, ExpiryValue);
|
||||
add("x-mms-reply-charging-id", 0x1E, WSP.TextString);
|
||||
|
@ -1714,7 +1593,7 @@ const MMS_HEADER_FIELDS = (function () {
|
|||
add("x-mms-adaptation-allowed", 0x3C, BooleanValue);
|
||||
add("x-mms-replace-id", 0x3D, WSP.TextString);
|
||||
add("x-mms-cancel-id", 0x3E, WSP.TextString);
|
||||
add("x-mms-cancel-status", 0x3F, BooleanValue);
|
||||
add("x-mms-cancel-status", 0x3F, CancelStatusValue);
|
||||
|
||||
return names;
|
||||
})();
|
||||
|
@ -1759,6 +1638,7 @@ this.EXPORTED_SYMBOLS = ALL_CONST_SYMBOLS.concat([
|
|||
"Address",
|
||||
"HeaderField",
|
||||
"MmsHeader",
|
||||
"CancelStatusValue",
|
||||
"ContentClassValue",
|
||||
"ContentLocationValue",
|
||||
"ElementDescriptorValue",
|
||||
|
@ -1773,10 +1653,12 @@ this.EXPORTED_SYMBOLS = ALL_CONST_SYMBOLS.concat([
|
|||
"MmFlagsValue",
|
||||
"MmStateValue",
|
||||
"PriorityValue",
|
||||
"ReadStatusValue",
|
||||
"RecommendedRetrievalModeValue",
|
||||
"ReplyChargingValue",
|
||||
"ResponseText",
|
||||
"RetrieveStatusValue",
|
||||
"SenderVisibilityValue",
|
||||
"StatusValue",
|
||||
|
||||
// Parser
|
||||
|
|
|
@ -18,6 +18,9 @@ const RIL_MMSSERVICE_CONTRACTID = "@mozilla.org/mms/rilmmsservice;1";
|
|||
const RIL_MMSSERVICE_CID = Components.ID("{217ddd76-75db-4210-955d-8806cd8d87f9}");
|
||||
|
||||
let DEBUG = false;
|
||||
function debug(s) {
|
||||
dump("-@- MmsService: " + s + "\n");
|
||||
};
|
||||
|
||||
// Read debug setting from pref.
|
||||
try {
|
||||
|
@ -32,6 +35,8 @@ const kSmsReceivedObserverTopic = "sms-received";
|
|||
const kSmsRetrievingObserverTopic = "sms-retrieving";
|
||||
const kSmsDeliverySuccessObserverTopic = "sms-delivery-success";
|
||||
const kSmsDeliveryErrorObserverTopic = "sms-delivery-error";
|
||||
const kSmsReadSuccessObserverTopic = "sms-read-success";
|
||||
const kSmsReadErrorObserverTopic = "sms-read-error";
|
||||
|
||||
const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown";
|
||||
const kNetworkInterfaceStateChangedTopic = "network-interface-state-changed";
|
||||
|
@ -1354,7 +1359,7 @@ function ReadRecTransaction(mmsConnection, messageID, toAddress) {
|
|||
type: type}
|
||||
headers["to"] = to;
|
||||
headers["from"] = null;
|
||||
headers["x-mms-read-status"] = true;
|
||||
headers["x-mms-read-status"] = MMS.MMS_PDU_READ_STATUS_READ;
|
||||
|
||||
this.istream = MMS.PduHelper.compose(null, {headers: headers});
|
||||
if (!this.istream) {
|
||||
|
@ -1431,38 +1436,33 @@ MmsService.prototype = {
|
|||
retrievalMode) {
|
||||
intermediate.type = "mms";
|
||||
intermediate.delivery = DELIVERY_NOT_DOWNLOADED;
|
||||
// As a receiver, we don't need to care about the delivery status of others.
|
||||
let deliveryInfo = intermediate.deliveryInfo = [{
|
||||
receiver: mmsConnection.getPhoneNumber(),
|
||||
deliveryStatus: DELIVERY_STATUS_NOT_APPLICABLE }];
|
||||
|
||||
let deliveryStatus;
|
||||
switch (retrievalMode) {
|
||||
case RETRIEVAL_MODE_MANUAL:
|
||||
deliveryInfo[0].deliveryStatus = DELIVERY_STATUS_MANUAL;
|
||||
deliveryStatus = DELIVERY_STATUS_MANUAL;
|
||||
break;
|
||||
case RETRIEVAL_MODE_NEVER:
|
||||
deliveryInfo[0].deliveryStatus = DELIVERY_STATUS_REJECTED;
|
||||
deliveryStatus = DELIVERY_STATUS_REJECTED;
|
||||
break;
|
||||
case RETRIEVAL_MODE_AUTOMATIC:
|
||||
deliveryInfo[0].deliveryStatus = DELIVERY_STATUS_PENDING;
|
||||
deliveryStatus = DELIVERY_STATUS_PENDING;
|
||||
break;
|
||||
case RETRIEVAL_MODE_AUTOMATIC_HOME:
|
||||
if (mmsConnection.isVoiceRoaming()) {
|
||||
deliveryInfo[0].deliveryStatus = DELIVERY_STATUS_MANUAL;
|
||||
deliveryStatus = DELIVERY_STATUS_MANUAL;
|
||||
} else {
|
||||
deliveryInfo[0].deliveryStatus = DELIVERY_STATUS_PENDING;
|
||||
deliveryStatus = DELIVERY_STATUS_PENDING;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
deliveryStatus = DELIVERY_STATUS_NOT_APPLICABLE;
|
||||
break;
|
||||
}
|
||||
// |intermediate.deliveryStatus| will be deleted after being stored in db.
|
||||
intermediate.deliveryStatus = deliveryStatus;
|
||||
|
||||
intermediate.timestamp = Date.now();
|
||||
intermediate.sender = null;
|
||||
intermediate.transactionId = intermediate.headers["x-mms-transaction-id"];
|
||||
if (intermediate.headers.from) {
|
||||
intermediate.sender = intermediate.headers.from.address;
|
||||
} else {
|
||||
intermediate.sender = "anonymous";
|
||||
}
|
||||
intermediate.receivers = [];
|
||||
intermediate.phoneNumber = mmsConnection.getPhoneNumber();
|
||||
intermediate.iccId = mmsConnection.getIccId();
|
||||
|
@ -1485,11 +1485,6 @@ MmsService.prototype = {
|
|||
intermediate,
|
||||
savable) {
|
||||
savable.timestamp = Date.now();
|
||||
if (intermediate.headers.from) {
|
||||
savable.sender = intermediate.headers.from.address;
|
||||
} else {
|
||||
savable.sender = "anonymous";
|
||||
}
|
||||
savable.receivers = [];
|
||||
// We don't have Bcc in recevied MMS message.
|
||||
for each (let type in ["cc", "to"]) {
|
||||
|
@ -1505,10 +1500,8 @@ MmsService.prototype = {
|
|||
}
|
||||
|
||||
savable.delivery = DELIVERY_RECEIVED;
|
||||
// As a receiver, we don't need to care about the delivery status of others.
|
||||
savable.deliveryInfo = [{
|
||||
receiver: mmsConnection.getPhoneNumber(),
|
||||
deliveryStatus: DELIVERY_STATUS_SUCCESS }];
|
||||
// |savable.deliveryStatus| will be deleted after being stored in db.
|
||||
savable.deliveryStatus = DELIVERY_STATUS_SUCCESS;
|
||||
for (let field in intermediate.headers) {
|
||||
savable.headers[field] = intermediate.headers[field];
|
||||
}
|
||||
|
@ -1615,6 +1608,8 @@ MmsService.prototype = {
|
|||
retrievedMessage) {
|
||||
if (DEBUG) debug("retrievedMessage = " + JSON.stringify(retrievedMessage));
|
||||
|
||||
let transactionId = savableMessage.headers["x-mms-transaction-id"];
|
||||
|
||||
// The absence of the field does not indicate any default
|
||||
// value. So we go check the same field in the retrieved
|
||||
// message instead.
|
||||
|
@ -1654,8 +1649,6 @@ MmsService.prototype = {
|
|||
savableMessage = this.mergeRetrievalConfirmation(mmsConnection,
|
||||
retrievedMessage,
|
||||
savableMessage);
|
||||
let transactionId = savableMessage.headers["x-mms-transaction-id"];
|
||||
|
||||
gMobileMessageDatabaseService.saveReceivedMessage(savableMessage,
|
||||
(function (rv, domMessage) {
|
||||
let success = Components.isSuccessCode(rv);
|
||||
|
@ -1805,11 +1798,6 @@ MmsService.prototype = {
|
|||
* The MMS message object.
|
||||
*/
|
||||
handleDeliveryIndication: function handleDeliveryIndication(aMsg) {
|
||||
if (DEBUG) {
|
||||
debug("handleDeliveryIndication: got delivery report" +
|
||||
JSON.stringify(aMsg));
|
||||
}
|
||||
|
||||
let headers = aMsg.headers;
|
||||
let envelopeId = headers["message-id"];
|
||||
let address = headers.to.address;
|
||||
|
@ -1847,11 +1835,8 @@ MmsService.prototype = {
|
|||
|
||||
if (DEBUG) debug("Updating the delivery status to: " + deliveryStatus);
|
||||
gMobileMessageDatabaseService
|
||||
.setMessageDeliveryByEnvelopeId(envelopeId,
|
||||
address,
|
||||
null,
|
||||
deliveryStatus,
|
||||
(function notifySetDeliveryResult(aRv, aDomMessage) {
|
||||
.setMessageDeliveryStatusByEnvelopeId(envelopeId, address, deliveryStatus,
|
||||
(function(aRv, aDomMessage) {
|
||||
if (DEBUG) debug("Marking the delivery status is done.");
|
||||
// TODO bug 832140 handle !Components.isSuccessCode(aRv)
|
||||
|
||||
|
@ -1873,6 +1858,57 @@ MmsService.prototype = {
|
|||
}).bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle incoming M-Read-Orig.ind PDU.
|
||||
*
|
||||
* @param aIndication
|
||||
* The MMS message object.
|
||||
*/
|
||||
handleReadOriginateIndication:
|
||||
function handleReadOriginateIndication(aIndication) {
|
||||
|
||||
let headers = aIndication.headers;
|
||||
let envelopeId = headers["message-id"];
|
||||
let address = headers.from.address;
|
||||
let mmsReadStatus = headers["x-mms-read-status"];
|
||||
if (DEBUG) {
|
||||
debug("Start updating the read status for envelopeId: " + envelopeId +
|
||||
", address: " + address + ", mmsReadStatus: " + mmsReadStatus);
|
||||
}
|
||||
|
||||
// From OMA-TS-MMS_ENC-V1_3-20110913-A subclause 9.4 "X-Mms-Read-Status",
|
||||
// in M-Read-Rec-Orig.ind the X-Mms-Read-Status could be
|
||||
// MMS.MMS_READ_STATUS_{ READ, DELETED_WITHOUT_BEING_READ }.
|
||||
let readStatus = mmsReadStatus == MMS.MMS_PDU_READ_STATUS_READ
|
||||
? MMS.DOM_READ_STATUS_SUCCESS
|
||||
: MMS.DOM_READ_STATUS_ERROR;
|
||||
if (DEBUG) debug("Updating the read status to: " + readStatus);
|
||||
|
||||
gMobileMessageDatabaseService
|
||||
.setMessageReadStatusByEnvelopeId(envelopeId, address, readStatus,
|
||||
(function(aRv, aDomMessage) {
|
||||
if (!Components.isSuccessCode(aRv)) {
|
||||
// Notifying observers the read status is error.
|
||||
Services.obs.notifyObservers(aDomMessage, kSmsReadSuccessObserverTopic, null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (DEBUG) debug("Marking the read status is done.");
|
||||
let topic;
|
||||
if (mmsReadStatus == MMS.MMS_PDU_READ_STATUS_READ) {
|
||||
topic = kSmsReadSuccessObserverTopic;
|
||||
|
||||
// Broadcasting a 'sms-read-success' system message to open apps.
|
||||
this.broadcastMmsSystemMessage(topic, aDomMessage);
|
||||
} else {
|
||||
topic = kSmsReadErrorObserverTopic;
|
||||
}
|
||||
|
||||
// Notifying observers the read status is updated.
|
||||
Services.obs.notifyObservers(aDomMessage, topic, null);
|
||||
}).bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* A utility function to convert the MmsParameters dictionary object
|
||||
* to a database-savable message.
|
||||
|
@ -2113,7 +2149,7 @@ MmsService.prototype = {
|
|||
|
||||
if (errorCode !== Ci.nsIMobileMessageCallback.SUCCESS_NO_ERROR) {
|
||||
if (DEBUG) debug("Error! The params for sending MMS are invalid.");
|
||||
sendTransactionCb(aDomMessage, errorCode);
|
||||
sendTransactionCb(aDomMessage, errorCode, null);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2126,7 +2162,7 @@ MmsService.prototype = {
|
|||
} catch (e) {
|
||||
if (DEBUG) debug("Exception: fail to create a SendTransaction instance.");
|
||||
sendTransactionCb(aDomMessage,
|
||||
Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
|
||||
Ci.nsIMobileMessageCallback.INTERNAL_ERROR, null);
|
||||
return;
|
||||
}
|
||||
sendTransaction.run(function callback(aMmsStatus, aMsg) {
|
||||
|
@ -2143,10 +2179,8 @@ MmsService.prototype = {
|
|||
} else {
|
||||
errorCode = Ci.nsIMobileMessageCallback.SUCCESS_NO_ERROR;
|
||||
}
|
||||
let envelopeId = null;
|
||||
if (aMsg) {
|
||||
envelopeId = aMsg.headers ? aMsg.headers["message-id"] : null;
|
||||
}
|
||||
let envelopeId =
|
||||
aMsg && aMsg.headers && aMsg.headers["message-id"] || null;
|
||||
sendTransactionCb(aDomMessage, errorCode, envelopeId);
|
||||
});
|
||||
});
|
||||
|
@ -2181,7 +2215,8 @@ MmsService.prototype = {
|
|||
aRequest.notifyGetMessageFailed(Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
|
||||
return;
|
||||
}
|
||||
if (DELIVERY_STATUS_PENDING == aMessageRecord.deliveryStatus) {
|
||||
let deliveryStatus = aMessageRecord.deliveryInfo[0].deliveryStatus;
|
||||
if (DELIVERY_STATUS_PENDING == deliveryStatus) {
|
||||
if (DEBUG) debug("Delivery status of message record is 'pending'.");
|
||||
aRequest.notifyGetMessageFailed(Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
|
||||
return;
|
||||
|
@ -2375,6 +2410,9 @@ MmsService.prototype = {
|
|||
case MMS.MMS_PDU_TYPE_DELIVERY_IND:
|
||||
this.handleDeliveryIndication(msg);
|
||||
break;
|
||||
case MMS.MMS_PDU_TYPE_READ_ORIG_IND:
|
||||
this.handleReadOriginateIndication(msg);
|
||||
break;
|
||||
default:
|
||||
if (DEBUG) debug("Unsupported X-MMS-Message-Type: " + msg.type);
|
||||
break;
|
||||
|
@ -2395,12 +2433,3 @@ MmsService.prototype = {
|
|||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([MmsService]);
|
||||
|
||||
let debug;
|
||||
if (DEBUG) {
|
||||
debug = function (s) {
|
||||
dump("-@- MmsService: " + s + "\n");
|
||||
};
|
||||
} else {
|
||||
debug = function (s) {};
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ const DISABLE_MMS_GROUPING_FOR_RECEIVING = true;
|
|||
|
||||
|
||||
const DB_NAME = "sms";
|
||||
const DB_VERSION = 19;
|
||||
const DB_VERSION = 20;
|
||||
const MESSAGE_STORE_NAME = "sms";
|
||||
const THREAD_STORE_NAME = "thread";
|
||||
const PARTICIPANT_STORE_NAME = "participant";
|
||||
|
@ -260,6 +260,10 @@ MobileMessageDatabaseService.prototype = {
|
|||
self.upgradeSchema18(event.target.transaction, next);
|
||||
break;
|
||||
case 19:
|
||||
if (DEBUG) debug("Upgrade to version 20. Add readStatus and readTimestamp.");
|
||||
self.upgradeSchema19(event.target.transaction, next);
|
||||
break;
|
||||
case 20:
|
||||
// This will need to be moved for each new version
|
||||
if (DEBUG) debug("Upgrade finished.");
|
||||
break;
|
||||
|
@ -1181,6 +1185,63 @@ MobileMessageDatabaseService.prototype = {
|
|||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Add readStatus and readTimestamp.
|
||||
*/
|
||||
upgradeSchema19: function upgradeSchema19(transaction, next) {
|
||||
let messageStore = transaction.objectStore(MESSAGE_STORE_NAME);
|
||||
messageStore.openCursor().onsuccess = function(event) {
|
||||
let cursor = event.target.result;
|
||||
if (!cursor) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
let messageRecord = cursor.value;
|
||||
if (messageRecord.type == "sms") {
|
||||
cursor.continue();
|
||||
return;
|
||||
}
|
||||
|
||||
// We can always retrieve transaction id from
|
||||
// |messageRecord.headers["x-mms-transaction-id"]|.
|
||||
if (messageRecord.hasOwnProperty("transactionId")) {
|
||||
delete messageRecord.transactionId;
|
||||
}
|
||||
|
||||
// xpconnect gives "undefined" for an unassigned argument of an interface
|
||||
// method.
|
||||
if (messageRecord.envelopeIdIndex === "undefined") {
|
||||
delete messageRecord.envelopeIdIndex;
|
||||
}
|
||||
|
||||
// Convert some header fields that were originally decoded as BooleanValue
|
||||
// to numeric enums.
|
||||
for (let field of ["x-mms-cancel-status",
|
||||
"x-mms-sender-visibility",
|
||||
"x-mms-read-status"]) {
|
||||
let value = messageRecord.headers[field];
|
||||
if (value !== undefined) {
|
||||
messageRecord.headers[field] = value ? 128 : 129;
|
||||
}
|
||||
}
|
||||
|
||||
// For all sent and received MMS messages, we have to add their
|
||||
// |readStatus| and |readTimestamp| attributes in |deliveryInfo| array.
|
||||
let readReportRequested =
|
||||
messageRecord.headers["x-mms-read-report"] || false;
|
||||
for (let element of messageRecord.deliveryInfo) {
|
||||
element.readStatus = readReportRequested
|
||||
? MMS.DOM_READ_STATUS_PENDING
|
||||
: MMS.DOM_READ_STATUS_NOT_APPLICABLE;
|
||||
element.readTimestamp = 0;
|
||||
}
|
||||
|
||||
cursor.update(messageRecord);
|
||||
cursor.continue();
|
||||
};
|
||||
},
|
||||
|
||||
matchParsedPhoneNumbers: function matchParsedPhoneNumbers(addr1, parsedAddr1,
|
||||
addr2, parsedAddr2) {
|
||||
if ((parsedAddr1.internationalNumber &&
|
||||
|
@ -1484,20 +1545,54 @@ MobileMessageDatabaseService.prototype = {
|
|||
});
|
||||
},
|
||||
|
||||
newTxnWithCallback: function newTxnWithCallback(aCallback, aFunc, aStoreNames) {
|
||||
let self = this;
|
||||
this.newTxn(READ_WRITE, function(aError, aTransaction, aStores) {
|
||||
let notifyResult = function(aRv, aMessageRecord) {
|
||||
if (!aCallback) {
|
||||
return;
|
||||
}
|
||||
let domMessage =
|
||||
aMessageRecord && self.createDomMessageFromRecord(aMessageRecord);
|
||||
aCallback.notify(aRv, domMessage);
|
||||
};
|
||||
|
||||
if (aError) {
|
||||
// TODO bug 832140 check event.target.errorCode
|
||||
notifyResult(Cr.NS_ERROR_FAILURE, null);
|
||||
return;
|
||||
}
|
||||
|
||||
let capture = {};
|
||||
aTransaction.oncomplete = function(event) {
|
||||
notifyResult(Cr.NS_OK, capture.messageRecord);
|
||||
};
|
||||
aTransaction.onabort = function(event) {
|
||||
// TODO bug 832140 check event.target.errorCode
|
||||
notifyResult(Cr.NS_ERROR_FAILURE, null);
|
||||
};
|
||||
|
||||
aFunc(capture, aStores);
|
||||
}, aStoreNames);
|
||||
},
|
||||
|
||||
saveRecord: function saveRecord(aMessageRecord, aAddresses, aCallback) {
|
||||
if (DEBUG) debug("Going to store " + JSON.stringify(aMessageRecord));
|
||||
|
||||
let self = this;
|
||||
this.newTxn(READ_WRITE, function(error, txn, stores) {
|
||||
let notifyResult = function(rv) {
|
||||
if (aCallback) {
|
||||
aCallback.notify(rv, self.createDomMessageFromRecord(aMessageRecord));
|
||||
let notifyResult = function(aRv, aMessageRecord) {
|
||||
if (!aCallback) {
|
||||
return;
|
||||
}
|
||||
let domMessage =
|
||||
aMessageRecord && self.createDomMessageFromRecord(aMessageRecord);
|
||||
aCallback.notify(aRv, domMessage);
|
||||
};
|
||||
|
||||
if (error) {
|
||||
// TODO bug 832140 check event.target.errorCode
|
||||
notifyResult(Cr.NS_ERROR_FAILURE);
|
||||
notifyResult(Cr.NS_ERROR_FAILURE, null);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1505,11 +1600,11 @@ MobileMessageDatabaseService.prototype = {
|
|||
if (aMessageRecord.id > self.lastMessageId) {
|
||||
self.lastMessageId = aMessageRecord.id;
|
||||
}
|
||||
notifyResult(Cr.NS_OK);
|
||||
notifyResult(Cr.NS_OK, aMessageRecord);
|
||||
};
|
||||
txn.onabort = function onabort(event) {
|
||||
// TODO bug 832140 check event.target.errorCode
|
||||
notifyResult(Cr.NS_ERROR_FAILURE);
|
||||
notifyResult(Cr.NS_ERROR_FAILURE, null);
|
||||
};
|
||||
|
||||
let messageStore = stores[0];
|
||||
|
@ -1734,41 +1829,19 @@ MobileMessageDatabaseService.prototype = {
|
|||
}
|
||||
|
||||
let self = this;
|
||||
let messageRecord;
|
||||
function notifyResult(rv) {
|
||||
if (!callback) {
|
||||
return;
|
||||
}
|
||||
let domMessage = self.createDomMessageFromRecord(messageRecord);
|
||||
callback.notify(rv, domMessage);
|
||||
}
|
||||
|
||||
this.newTxn(READ_WRITE, function (error, txn, messageStore) {
|
||||
if (error) {
|
||||
// TODO bug 832140 check event.target.errorCode
|
||||
notifyResult(Cr.NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
txn.oncomplete = function oncomplete(event) {
|
||||
notifyResult(Cr.NS_OK);
|
||||
};
|
||||
txn.onabort = function onabort(event) {
|
||||
// TODO bug 832140 check event.target.errorCode
|
||||
notifyResult(Cr.NS_ERROR_FAILURE);
|
||||
};
|
||||
|
||||
this.newTxnWithCallback(callback, function(aCapture, aMessageStore) {
|
||||
let getRequest;
|
||||
if (type === "messageId") {
|
||||
getRequest = messageStore.get(id);
|
||||
getRequest = aMessageStore.get(id);
|
||||
} else if (type === "envelopeId") {
|
||||
getRequest = messageStore.index("envelopeId").get(id);
|
||||
getRequest = aMessageStore.index("envelopeId").get(id);
|
||||
}
|
||||
|
||||
getRequest.onsuccess = function onsuccess(event) {
|
||||
messageRecord = event.target.result;
|
||||
let messageRecord = event.target.result;
|
||||
if (!messageRecord) {
|
||||
if (DEBUG) debug("type = " + id + " is not found");
|
||||
return;
|
||||
throw Cr.NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
let isRecordUpdated = false;
|
||||
|
@ -1823,6 +1896,7 @@ MobileMessageDatabaseService.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
aCapture.messageRecord = messageRecord;
|
||||
if (!isRecordUpdated) {
|
||||
if (DEBUG) {
|
||||
debug("The values of delivery, deliveryStatus and envelopeId " +
|
||||
|
@ -1834,7 +1908,7 @@ MobileMessageDatabaseService.prototype = {
|
|||
if (DEBUG) {
|
||||
debug("The delivery, deliveryStatus or envelopeId are updated.");
|
||||
}
|
||||
messageStore.put(messageRecord);
|
||||
aMessageStore.put(messageRecord);
|
||||
};
|
||||
});
|
||||
},
|
||||
|
@ -1940,21 +2014,30 @@ MobileMessageDatabaseService.prototype = {
|
|||
|
||||
saveReceivedMessage: function saveReceivedMessage(aMessage, aCallback) {
|
||||
if ((aMessage.type != "sms" && aMessage.type != "mms") ||
|
||||
(aMessage.type == "sms" && aMessage.messageClass == undefined) ||
|
||||
(aMessage.type == "sms" && (aMessage.messageClass == undefined ||
|
||||
aMessage.sender == undefined)) ||
|
||||
(aMessage.type == "mms" && (aMessage.delivery == undefined ||
|
||||
aMessage.transactionId == undefined ||
|
||||
!Array.isArray(aMessage.deliveryInfo) ||
|
||||
aMessage.deliveryStatus == undefined ||
|
||||
!Array.isArray(aMessage.receivers))) ||
|
||||
aMessage.sender == undefined ||
|
||||
aMessage.timestamp == undefined) {
|
||||
if (aCallback) {
|
||||
aCallback.notify(Cr.NS_ERROR_FAILURE, null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
let threadParticipants = [aMessage.sender];
|
||||
|
||||
let threadParticipants;
|
||||
if (aMessage.type == "mms") {
|
||||
if (aMessage.headers.from) {
|
||||
aMessage.sender = aMessage.headers.from.address;
|
||||
} else {
|
||||
aMessage.sender = "anonymous";
|
||||
}
|
||||
|
||||
threadParticipants = [aMessage.sender];
|
||||
this.fillReceivedMmsThreadParticipants(aMessage, threadParticipants);
|
||||
} else { // SMS
|
||||
threadParticipants = [aMessage.sender];
|
||||
}
|
||||
|
||||
let timestamp = aMessage.timestamp;
|
||||
|
@ -1965,30 +2048,31 @@ MobileMessageDatabaseService.prototype = {
|
|||
aMessage.read = FILTER_READ_UNREAD;
|
||||
|
||||
if (aMessage.type == "mms") {
|
||||
aMessage.transactionIdIndex = aMessage.transactionId;
|
||||
aMessage.transactionIdIndex = aMessage.headers["x-mms-transaction-id"];
|
||||
aMessage.isReadReportSent = false;
|
||||
|
||||
// If |deliveryTimestamp| is not specified, use 0 as default.
|
||||
let deliveryInfo = aMessage.deliveryInfo;
|
||||
for (let i = 0; i < deliveryInfo.length; i++) {
|
||||
if (deliveryInfo[i].deliveryTimestamp == undefined) {
|
||||
deliveryInfo[i].deliveryTimestamp = 0;
|
||||
}
|
||||
}
|
||||
// As a receiver, we don't need to care about the delivery status of
|
||||
// others, so we put a single element with self's phone number in the
|
||||
// |deliveryInfo| array.
|
||||
aMessage.deliveryInfo = [{
|
||||
receiver: aMessage.phoneNumber,
|
||||
deliveryStatus: aMessage.deliveryStatus,
|
||||
deliveryTimestamp: 0,
|
||||
readStatus: MMS.DOM_READ_STATUS_NOT_APPLICABLE,
|
||||
readTimestamp: 0,
|
||||
}];
|
||||
|
||||
delete aMessage.deliveryStatus;
|
||||
}
|
||||
|
||||
if (aMessage.type == "sms") {
|
||||
aMessage.delivery = DELIVERY_RECEIVED;
|
||||
aMessage.deliveryStatus = DELIVERY_STATUS_SUCCESS;
|
||||
aMessage.deliveryTimestamp = 0;
|
||||
|
||||
if (aMessage.pid == undefined) {
|
||||
aMessage.pid = RIL.PDU_PID_DEFAULT;
|
||||
}
|
||||
|
||||
// If |deliveryTimestamp| is not specified, use 0 as default.
|
||||
if (aMessage.deliveryTimestamp == undefined) {
|
||||
aMessage.deliveryTimestamp = 0;
|
||||
}
|
||||
}
|
||||
aMessage.deliveryIndex = [aMessage.delivery, timestamp];
|
||||
|
||||
|
@ -2029,12 +2113,18 @@ MobileMessageDatabaseService.prototype = {
|
|||
}
|
||||
return;
|
||||
}
|
||||
let readStatus = aMessage.headers["x-mms-read-report"]
|
||||
? MMS.DOM_READ_STATUS_PENDING
|
||||
: MMS.DOM_READ_STATUS_NOT_APPLICABLE;
|
||||
aMessage.deliveryInfo = [];
|
||||
for (let i = 0; i < receivers.length; i++) {
|
||||
aMessage.deliveryInfo.push({
|
||||
receiver: receivers[i],
|
||||
deliveryStatus: deliveryStatus,
|
||||
deliveryTimestamp: 0 });
|
||||
deliveryTimestamp: 0,
|
||||
readStatus: readStatus,
|
||||
readTimestamp: 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2065,12 +2155,62 @@ MobileMessageDatabaseService.prototype = {
|
|||
|
||||
},
|
||||
|
||||
setMessageDeliveryByEnvelopeId: function setMessageDeliveryByEnvelopeId(
|
||||
envelopeId, receiver, delivery, deliveryStatus, callback) {
|
||||
this.updateMessageDeliveryById(envelopeId, "envelopeId",
|
||||
receiver, delivery, deliveryStatus,
|
||||
null, callback);
|
||||
setMessageDeliveryStatusByEnvelopeId:
|
||||
function setMessageDeliveryStatusByEnvelopeId(aEnvelopeId, aReceiver,
|
||||
aDeliveryStatus, aCallback) {
|
||||
this.updateMessageDeliveryById(aEnvelopeId, "envelopeId", aReceiver, null,
|
||||
aDeliveryStatus, null, aCallback);
|
||||
},
|
||||
|
||||
setMessageReadStatusByEnvelopeId:
|
||||
function setMessageReadStatusByEnvelopeId(aEnvelopeId, aReceiver,
|
||||
aReadStatus, aCallback) {
|
||||
if (DEBUG) {
|
||||
debug("Setting message's read status by envelopeId = " + aEnvelopeId +
|
||||
", receiver: " + aReceiver + ", readStatus: " + aReadStatus);
|
||||
}
|
||||
|
||||
let self = this;
|
||||
this.newTxnWithCallback(aCallback, function(aCapture, aMessageStore) {
|
||||
let getRequest = aMessageStore.index("envelopeId").get(aEnvelopeId);
|
||||
getRequest.onsuccess = function onsuccess(event) {
|
||||
let messageRecord = event.target.result;
|
||||
if (!messageRecord) {
|
||||
if (DEBUG) debug("envelopeId '" + aEnvelopeId + "' not found");
|
||||
throw Cr.NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
aCapture.messageRecord = messageRecord;
|
||||
|
||||
let isRecordUpdated = false;
|
||||
self.forEachMatchedMmsDeliveryInfo(messageRecord.deliveryInfo,
|
||||
aReceiver, function(aEntry) {
|
||||
if (aEntry.readStatus == aReadStatus) {
|
||||
return;
|
||||
}
|
||||
|
||||
aEntry.readStatus = aReadStatus;
|
||||
if (aReadStatus == MMS.DOM_READ_STATUS_SUCCESS) {
|
||||
aEntry.readTimestamp = Date.now();
|
||||
} else {
|
||||
aEntry.readTimestamp = 0;
|
||||
}
|
||||
isRecordUpdated = true;
|
||||
});
|
||||
|
||||
if (!isRecordUpdated) {
|
||||
if (DEBUG) {
|
||||
debug("The values of readStatus don't need to be updated.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
debug("The readStatus is updated.");
|
||||
}
|
||||
aMessageStore.put(messageRecord);
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
getMessageRecordByTransactionId: function getMessageRecordByTransactionId(aTransactionId, aCallback) {
|
||||
|
|
|
@ -95,6 +95,21 @@ this.MMS_PDU_STATUS_INDETERMINATE = 133;
|
|||
this.MMS_PDU_STATUS_FORWARDED = 134;
|
||||
this.MMS_PDU_STATUS_UNREACHABLE = 135;
|
||||
|
||||
// X-Mms-Cancel-Status values
|
||||
// @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.7
|
||||
this.MMS_PDU_CANCEL_STATUS_RECEIVED = 128;
|
||||
this.MMS_PDU_CANCEL_STATUS_CORRUPTED = 129;
|
||||
|
||||
// X-Mms-Sender-Visibility
|
||||
// @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.52
|
||||
this.MMS_PDU_SENDER_VISIBILITY_HIDE = 128;
|
||||
this.MMS_PDU_SENDER_VISIBILITY_SHOW = 129;
|
||||
|
||||
// X-Mms-Read-Status
|
||||
// @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.38
|
||||
this.MMS_PDU_READ_STATUS_READ = 128;
|
||||
this.MMS_PDU_READ_STATUS_DELETED_UNREAD = 129;
|
||||
|
||||
// Maximum Values of MMS Parameters
|
||||
// @see OMA-TS-MMS_CONF-V1_3-20110511-C 10.2.5
|
||||
this.MMS_MAX_LENGTH_SUBJECT = 40;
|
||||
|
@ -103,6 +118,11 @@ this.MMS_MAX_TOTAL_RECIPIENTS = 20;
|
|||
this.MMS_MAX_LENGTH_NAME_CONTENT_TYPE = 40;
|
||||
this.MMS_MAX_LENGTH_MAILBOX_PORTION = 256;
|
||||
|
||||
this.DOM_READ_STATUS_NOT_APPLICABLE = "not-applicable";
|
||||
this.DOM_READ_STATUS_SUCCESS = "success";
|
||||
this.DOM_READ_STATUS_PENDING = "pending";
|
||||
this.DOM_READ_STATUS_ERROR = "error";
|
||||
|
||||
this.ALL_CONST_SYMBOLS = undefined; // We want ALL_CONST_SYMBOLS to be exported.
|
||||
this.ALL_CONST_SYMBOLS = Object.keys(this);
|
||||
|
||||
|
|
|
@ -118,6 +118,10 @@ child:
|
|||
|
||||
NotifyReceivedSilentMessage(MobileMessageData aMessageData);
|
||||
|
||||
NotifyReadSuccessMessage(MobileMessageData aMessageData);
|
||||
|
||||
NotifyReadErrorMessage(MobileMessageData aMessageData);
|
||||
|
||||
parent:
|
||||
/**
|
||||
* Sent when the child no longer needs to use sms.
|
||||
|
|
|
@ -118,6 +118,20 @@ SmsChild::RecvNotifyReceivedSilentMessage(const MobileMessageData& aData)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SmsChild::RecvNotifyReadSuccessMessage(const MobileMessageData& aData)
|
||||
{
|
||||
NotifyObserversWithMobileMessage(kSmsReadSuccessObserverTopic, aData);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SmsChild::RecvNotifyReadErrorMessage(const MobileMessageData& aData)
|
||||
{
|
||||
NotifyObserversWithMobileMessage(kSmsReadErrorObserverTopic, aData);
|
||||
return true;
|
||||
}
|
||||
|
||||
PSmsRequestChild*
|
||||
SmsChild::AllocPSmsRequestChild(const IPCSmsRequest& aRequest)
|
||||
{
|
||||
|
|
|
@ -58,6 +58,12 @@ protected:
|
|||
virtual bool
|
||||
RecvNotifyReceivedSilentMessage(const MobileMessageData& aMessage) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvNotifyReadSuccessMessage(const MobileMessageData& aMessage) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvNotifyReadErrorMessage(const MobileMessageData& aMessage) MOZ_OVERRIDE;
|
||||
|
||||
virtual PSmsRequestChild*
|
||||
AllocPSmsRequestChild(const IPCSmsRequest& aRequest) MOZ_OVERRIDE;
|
||||
|
||||
|
|
|
@ -153,6 +153,8 @@ SmsParent::SmsParent()
|
|||
obs->AddObserver(this, kSmsDeliverySuccessObserverTopic, false);
|
||||
obs->AddObserver(this, kSmsDeliveryErrorObserverTopic, false);
|
||||
obs->AddObserver(this, kSilentSmsReceivedObserverTopic, false);
|
||||
obs->AddObserver(this, kSmsReadSuccessObserverTopic, false);
|
||||
obs->AddObserver(this, kSmsReadErrorObserverTopic, false);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -171,6 +173,8 @@ SmsParent::ActorDestroy(ActorDestroyReason why)
|
|||
obs->RemoveObserver(this, kSmsDeliverySuccessObserverTopic);
|
||||
obs->RemoveObserver(this, kSmsDeliveryErrorObserverTopic);
|
||||
obs->RemoveObserver(this, kSilentSmsReceivedObserverTopic);
|
||||
obs->RemoveObserver(this, kSmsReadSuccessObserverTopic);
|
||||
obs->RemoveObserver(this, kSmsReadErrorObserverTopic);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -272,6 +276,30 @@ SmsParent::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
if (!strcmp(aTopic, kSmsReadSuccessObserverTopic)) {
|
||||
MobileMessageData msgData;
|
||||
if (!GetMobileMessageDataFromMessage(aSubject, msgData)) {
|
||||
NS_ERROR("Got a 'sms-read-success' topic without a valid message!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
unused << SendNotifyReadSuccessMessage(msgData);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, kSmsReadErrorObserverTopic)) {
|
||||
MobileMessageData msgData;
|
||||
if (!GetMobileMessageDataFromMessage(aSubject, msgData)) {
|
||||
NS_ERROR("Got a 'sms-read-error' topic without a valid message!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
unused << SendNotifyReadErrorMessage(msgData);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ include protocol PBlob;
|
|||
using DeliveryState from "mozilla/dom/mobilemessage/Types.h";
|
||||
using DeliveryStatus from "mozilla/dom/mobilemessage/Types.h";
|
||||
using MessageClass from "mozilla/dom/mobilemessage/Types.h";
|
||||
using ReadStatus from "mozilla/dom/mobilemessage/Types.h";
|
||||
using ReadState from "mozilla/dom/mobilemessage/Types.h";
|
||||
using MessageType from "mozilla/dom/mobilemessage/Types.h";
|
||||
|
||||
|
@ -51,6 +52,8 @@ struct MmsDeliveryInfoData
|
|||
nsString receiver;
|
||||
DeliveryStatus deliveryStatus;
|
||||
uint64_t deliveryTimestamp;
|
||||
ReadStatus readStatus;
|
||||
uint64_t readTimestamp;
|
||||
};
|
||||
|
||||
struct MmsMessageData
|
||||
|
|
|
@ -177,6 +177,38 @@ add_test(function test_MmsHeader_encode() {
|
|||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: CancelStatusValue
|
||||
//
|
||||
|
||||
//// CancelStatusValue.decode ////
|
||||
|
||||
add_test(function test_CancelStatusValue_decode() {
|
||||
for (let i = 0; i < 256; i++) {
|
||||
if ((i >= 128) && (i <= 129)) {
|
||||
wsp_decode_test(MMS.CancelStatusValue, [i], i);
|
||||
} else {
|
||||
wsp_decode_test(MMS.CancelStatusValue, [i], null, "CodeError");
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//// CancelStatusValue.encode ////
|
||||
|
||||
add_test(function test_CancelStatusValue_encode() {
|
||||
for (let i = 0; i < 256; i++) {
|
||||
if ((i >= 128) && (i <= 129)) {
|
||||
wsp_encode_test(MMS.CancelStatusValue, i, [i]);
|
||||
} else {
|
||||
wsp_encode_test(MMS.CancelStatusValue, i, null, "CodeError");
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: ContentClassValue
|
||||
//
|
||||
|
@ -657,6 +689,38 @@ add_test(function test_PriorityValue_encode() {
|
|||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: ReadStatusValue
|
||||
//
|
||||
|
||||
//// ReadStatusValue.decode ////
|
||||
|
||||
add_test(function test_ReadStatusValue_decode() {
|
||||
for (let i = 0; i < 256; i++) {
|
||||
if ((i >= 128) && (i <= 129)) {
|
||||
wsp_decode_test(MMS.ReadStatusValue, [i], i);
|
||||
} else {
|
||||
wsp_decode_test(MMS.ReadStatusValue, [i], null, "CodeError");
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//// ReadStatusValue.encode ////
|
||||
|
||||
add_test(function test_ReadStatusValue_encode() {
|
||||
for (let i = 0; i < 256; i++) {
|
||||
if ((i >= 128) && (i <= 129)) {
|
||||
wsp_encode_test(MMS.ReadStatusValue, i, [i]);
|
||||
} else {
|
||||
wsp_encode_test(MMS.ReadStatusValue, i, null, "CodeError");
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: RecommendedRetrievalModeValue
|
||||
//
|
||||
|
@ -765,6 +829,38 @@ add_test(function test_RetrieveStatusValue_decode() {
|
|||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: SenderVisibilityValue
|
||||
//
|
||||
|
||||
//// SenderVisibilityValue.decode ////
|
||||
|
||||
add_test(function test_SenderVisibilityValue_decode() {
|
||||
for (let i = 0; i < 256; i++) {
|
||||
if ((i >= 128) && (i <= 129)) {
|
||||
wsp_decode_test(MMS.SenderVisibilityValue, [i], i);
|
||||
} else {
|
||||
wsp_decode_test(MMS.SenderVisibilityValue, [i], null, "CodeError");
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//// SenderVisibilityValue.encode ////
|
||||
|
||||
add_test(function test_SenderVisibilityValue_encode() {
|
||||
for (let i = 0; i < 256; i++) {
|
||||
if ((i >= 128) && (i <= 129)) {
|
||||
wsp_encode_test(MMS.SenderVisibilityValue, i, [i]);
|
||||
} else {
|
||||
wsp_encode_test(MMS.SenderVisibilityValue, i, null, "CodeError");
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: StatusValue
|
||||
//
|
||||
|
|
|
@ -198,15 +198,15 @@ var WifiManager = (function() {
|
|||
// can trigger bugs in some drivers.
|
||||
// On properly written drivers, bringing the interface
|
||||
// down powers down the interface.
|
||||
callback(0);
|
||||
notify("supplicantlost", { success: true });
|
||||
callback(0);
|
||||
return;
|
||||
}
|
||||
|
||||
wifiCommand.unloadDriver(function(status) {
|
||||
driverLoaded = (status < 0);
|
||||
callback(status);
|
||||
notify("supplicantlost", { success: true });
|
||||
callback(status);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -419,12 +419,6 @@ var WifiManager = (function() {
|
|||
}
|
||||
|
||||
function notifyStateChange(fields) {
|
||||
// Don't handle any state change when and after disabling.
|
||||
if (manager.state === "DISABLING" ||
|
||||
manager.state === "UNINITIALIZED") {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we're already in the COMPLETED state, we might receive events from
|
||||
// the supplicant that tell us that we're re-authenticating or reminding
|
||||
// us that we're associated to a network. In those cases, we don't need to
|
||||
|
@ -446,12 +440,19 @@ var WifiManager = (function() {
|
|||
fields.state === "COMPLETED")) {
|
||||
setBackgroundScan("OFF", function() {});
|
||||
}
|
||||
fields.prevState = manager.state;
|
||||
manager.state = fields.state;
|
||||
|
||||
fields.prevState = manager.state;
|
||||
// Detect wpa_supplicant's loop iterations.
|
||||
manager.supplicantLoopDetection(fields.prevState, fields.state);
|
||||
notify("statechange", fields);
|
||||
|
||||
// Don't update state when and after disabling.
|
||||
if (manager.state === "DISABLING" ||
|
||||
manager.state === "UNINITIALIZED") {
|
||||
return false;
|
||||
}
|
||||
|
||||
manager.state = fields.state;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -185,5 +185,5 @@ const SequenceModel TIS620ThaiModel =
|
|||
ThaiLangModel,
|
||||
(float)0.926386,
|
||||
false,
|
||||
"TIS-620"
|
||||
"windows-874"
|
||||
};
|
||||
|
|
|
@ -22,7 +22,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=488426
|
|||
<script class="testbody" type="text/javascript">
|
||||
/** Test for Bug 488426 **/
|
||||
CharsetDetectionTests("bug488426_text.html",
|
||||
"TIS-620",
|
||||
"windows-874",
|
||||
new Array("universal_charset_detector"));
|
||||
</script>
|
||||
</pre>
|
||||
|
|
|
@ -606,19 +606,32 @@ DrawTargetSkia::Mask(const Pattern &aSource,
|
|||
raster->addLayer(maskPaint);
|
||||
SkSafeUnref(paint.mPaint.setRasterizer(raster));
|
||||
|
||||
// Skia only uses the mask rasterizer when we are drawing a path/rect.
|
||||
// Take our destination bounds and convert them into user space to use
|
||||
// as the path to draw.
|
||||
SkPath path;
|
||||
path.addRect(SkRect::MakeWH(SkScalar(mSize.width), SkScalar(mSize.height)));
|
||||
|
||||
Matrix temp = mTransform;
|
||||
temp.Invert();
|
||||
SkMatrix mat;
|
||||
GfxMatrixToSkiaMatrix(temp, mat);
|
||||
path.transform(mat);
|
||||
mCanvas->drawRect(SkRectCoveringWholeSurface(), paint.mPaint);
|
||||
}
|
||||
|
||||
mCanvas->drawPath(path, paint.mPaint);
|
||||
void
|
||||
DrawTargetSkia::MaskSurface(const Pattern &aSource,
|
||||
SourceSurface *aMask,
|
||||
Point aOffset,
|
||||
const DrawOptions &aOptions)
|
||||
{
|
||||
MarkChanged();
|
||||
AutoPaintSetup paint(mCanvas.get(), aOptions, aSource);
|
||||
|
||||
SkPaint maskPaint;
|
||||
SetPaintPattern(maskPaint, SurfacePattern(aMask, EXTEND_CLAMP));
|
||||
|
||||
SkMatrix transform = maskPaint.getShader()->getLocalMatrix();
|
||||
transform.postTranslate(SkFloatToScalar(aOffset.x), SkFloatToScalar(aOffset.y));
|
||||
maskPaint.getShader()->setLocalMatrix(transform);
|
||||
|
||||
SkLayerRasterizer *raster = new SkLayerRasterizer();
|
||||
raster->addLayer(maskPaint);
|
||||
SkSafeUnref(paint.mPaint.setRasterizer(raster));
|
||||
|
||||
IntSize size = aMask->GetSize();
|
||||
Rect rect = Rect(aOffset.x, aOffset.y, size.width, size.height);
|
||||
mCanvas->drawRect(RectToSkRect(rect), paint.mPaint);
|
||||
}
|
||||
|
||||
TemporaryRef<SourceSurface>
|
||||
|
@ -869,6 +882,14 @@ DrawTargetSkia::MarkChanged()
|
|||
}
|
||||
}
|
||||
|
||||
// Return a rect (in user space) that covers the entire surface by applying
|
||||
// the inverse of GetTransform() to (0, 0, mSize.width, mSize.height).
|
||||
SkRect
|
||||
DrawTargetSkia::SkRectCoveringWholeSurface() const
|
||||
{
|
||||
return RectToSkRect(mTransform.TransformBounds(Rect(0, 0, mSize.width, mSize.height)));
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetSkia::SnapshotDestroyed()
|
||||
{
|
||||
|
|
|
@ -78,7 +78,7 @@ public:
|
|||
virtual void MaskSurface(const Pattern &aSource,
|
||||
SourceSurface *aMask,
|
||||
Point aOffset,
|
||||
const DrawOptions &aOptions = DrawOptions()) { MOZ_ASSERT(0); };
|
||||
const DrawOptions &aOptions = DrawOptions());
|
||||
virtual void PushClip(const Path *aPath);
|
||||
virtual void PushClipRect(const Rect& aRect);
|
||||
virtual void PopClip();
|
||||
|
@ -125,6 +125,8 @@ private:
|
|||
|
||||
void MarkChanged();
|
||||
|
||||
SkRect SkRectCoveringWholeSurface() const;
|
||||
|
||||
#ifdef USE_SKIA_GPU
|
||||
/*
|
||||
* These members have inter-dependencies, but do not keep each other alive, so
|
||||
|
|
|
@ -87,6 +87,7 @@ x-mac-hebrew.notForBrowser = true
|
|||
x-imap4-modified-utf7.notForBrowser = true
|
||||
utf-7.notForBrowser = true
|
||||
ibm864.notForBrowser = true
|
||||
replacement.notForBrowser = true
|
||||
|
||||
x-mac-arabic.isInternal = true
|
||||
x-mac-farsi.isInternal = true
|
||||
|
@ -95,6 +96,7 @@ x-imap4-modified-utf7.isInternal = true
|
|||
utf-7.isInternal = true
|
||||
t.61-8bit.isInternal = true
|
||||
ibm864.isInternal = true
|
||||
replacement.isInternal = true
|
||||
|
||||
t.61-8bit.notForOutgoing = true
|
||||
utf-7.notForOutgoing = true
|
||||
|
@ -110,7 +112,7 @@ iso-8859-8-e.notForOutgoing = true
|
|||
iso-8859-8.notForOutgoing = true
|
||||
iso-2022-kr.notForOutgoing = true
|
||||
x-johab.notForOutgoing = true
|
||||
|
||||
replacement.notForOutgoing = true
|
||||
|
||||
// XXX : there are some entries only necessary for Gtk/Xlib builds
|
||||
// to map XLFD registry-encoding pairs to langGroups. they can be
|
||||
|
@ -119,6 +121,7 @@ x-johab.notForOutgoing = true
|
|||
// XXX : todo: move to something based on BCP 47 (RFC 5646);
|
||||
// these should primarily specify script (and sometimes region),
|
||||
// but NOT language.
|
||||
// See also https://bugzilla.mozilla.org/show_bug.cgi?id=756022
|
||||
// e.g. x-western -> *-Latn-155 (Western Europe)
|
||||
// x-central-euro -> *-Latn-151 (Eastern Europe)
|
||||
// x-baltic -> *-Latn-154 (Northern Europe)
|
||||
|
@ -194,6 +197,7 @@ utf-16be.LangGroup = x-unicode
|
|||
utf-16le.LangGroup = x-unicode
|
||||
utf-7.LangGroup = x-unicode
|
||||
x-imap4-modified-utf7.LangGroup = x-unicode
|
||||
replacement.LangGroup = x-unicode
|
||||
viscii.LangGroup = x-western
|
||||
x-viet-tcvn5712.LangGroup = x-western
|
||||
x-viet-vps.LangGroup = x-western
|
||||
|
@ -244,3 +248,4 @@ euc-kr.isMultibyte = true
|
|||
x-johab.isMultibyte = true
|
||||
utf-7.isMultibyte = true
|
||||
utf-8.isMultibyte = true
|
||||
replacement.isMultibyte = true
|
||||
|
|
|
@ -11,6 +11,7 @@ UNIFIED_SOURCES += [
|
|||
'nsCP1252ToUnicode.cpp',
|
||||
'nsISO88591ToUnicode.cpp',
|
||||
'nsMacRomanToUnicode.cpp',
|
||||
'nsReplacementToUnicode.cpp',
|
||||
'nsScriptableUConv.cpp',
|
||||
'nsTextToSubURI.cpp',
|
||||
'nsUConvModule.cpp',
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsReplacementToUnicode.h"
|
||||
|
||||
nsReplacementToUnicode::nsReplacementToUnicode()
|
||||
: mSeenByte(false)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsReplacementToUnicode::Convert(const char* aSrc,
|
||||
int32_t* aSrcLength,
|
||||
PRUnichar* aDest,
|
||||
int32_t* aDestLength)
|
||||
{
|
||||
if (mSeenByte || !(*aSrcLength)) {
|
||||
*aDestLength = 0;
|
||||
return NS_PARTIAL_MORE_INPUT;
|
||||
}
|
||||
if (mErrBehavior == kOnError_Signal) {
|
||||
mSeenByte = true;
|
||||
*aSrcLength = 0;
|
||||
*aDestLength = 0;
|
||||
return NS_ERROR_ILLEGAL_INPUT;
|
||||
}
|
||||
if (!(*aDestLength)) {
|
||||
*aSrcLength = -1;
|
||||
return NS_PARTIAL_MORE_OUTPUT;
|
||||
}
|
||||
mSeenByte = true;
|
||||
*aDest = 0xFFFD;
|
||||
*aDestLength = 1;
|
||||
return NS_PARTIAL_MORE_INPUT;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsReplacementToUnicode::GetMaxLength(const char* aSrc,
|
||||
int32_t aSrcLength,
|
||||
int32_t* aDestLength)
|
||||
{
|
||||
if (!mSeenByte && aSrcLength > 0) {
|
||||
*aDestLength = 1;
|
||||
} else {
|
||||
*aDestLength = 0;
|
||||
}
|
||||
return NS_EXACT_LENGTH;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsReplacementToUnicode::Reset()
|
||||
{
|
||||
mSeenByte = false;
|
||||
return NS_OK;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsReplacementToUnicode_h_
|
||||
#define nsReplacementToUnicode_h_
|
||||
|
||||
#include "nsUCSupport.h"
|
||||
|
||||
#define NS_REPLACEMENTTOUNICODE_CID \
|
||||
{ 0xd24b24da, 0xc607, 0x489a, \
|
||||
{ 0xb5, 0xf0, 0x67, 0x91, 0xf4, 0x45, 0x45, 0x6d } }
|
||||
|
||||
#define NS_REPLACEMENTTOUNICODE_CONTRACTID \
|
||||
"@mozilla.org/intl/unicode/decoder;1?charset=replacement"
|
||||
|
||||
class nsReplacementToUnicode : public nsBasicDecoderSupport
|
||||
{
|
||||
public:
|
||||
nsReplacementToUnicode();
|
||||
|
||||
NS_IMETHOD Convert(const char* aSrc,
|
||||
int32_t* aSrcLength,
|
||||
PRUnichar* aDest,
|
||||
int32_t* aDestLength);
|
||||
|
||||
NS_IMETHOD GetMaxLength(const char* aSrc,
|
||||
int32_t aSrcLength,
|
||||
int32_t* aDestLength);
|
||||
|
||||
NS_IMETHOD Reset();
|
||||
|
||||
private:
|
||||
bool mSeenByte;
|
||||
};
|
||||
|
||||
#endif // nsReplacementToUnicode_h_
|
|
@ -21,6 +21,7 @@
|
|||
#include "nsISO88591ToUnicode.h"
|
||||
#include "nsCP1252ToUnicode.h"
|
||||
#include "nsMacRomanToUnicode.h"
|
||||
#include "nsReplacementToUnicode.h"
|
||||
#include "nsUTF8ToUnicode.h"
|
||||
#include "nsUnicodeToISO88591.h"
|
||||
#include "nsUnicodeToCP1252.h"
|
||||
|
@ -219,6 +220,7 @@ NS_UCONV_REG_UNREG("ISO-8859-1", NS_ISO88591TOUNICODE_CID, NS_UNICODETOISO88591_
|
|||
NS_UCONV_REG_UNREG("windows-1252", NS_CP1252TOUNICODE_CID, NS_UNICODETOCP1252_CID)
|
||||
NS_UCONV_REG_UNREG("macintosh", NS_MACROMANTOUNICODE_CID, NS_UNICODETOMACROMAN_CID)
|
||||
NS_UCONV_REG_UNREG("UTF-8", NS_UTF8TOUNICODE_CID, NS_UNICODETOUTF8_CID)
|
||||
NS_UCONV_REG_UNREG("replacement", NS_REPLACEMENTTOUNICODE_CID, NS_UNICODETOUTF8_CID)
|
||||
|
||||
// ucvlatin
|
||||
NS_UCONV_REG_UNREG("us-ascii", NS_ASCIITOUNICODE_CID, NS_UNICODETOASCII_CID)
|
||||
|
@ -332,6 +334,7 @@ NS_CONVERTER_REGISTRY_END
|
|||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsUnicodeToUTF8)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsUTF8ToUnicode)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsReplacementToUnicode)
|
||||
|
||||
// ucvlatin
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsUTF7ToUnicode)
|
||||
|
@ -506,6 +509,7 @@ NS_DEFINE_NAMED_CID(NS_ISO88591TOUNICODE_CID);
|
|||
NS_DEFINE_NAMED_CID(NS_CP1252TOUNICODE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_MACROMANTOUNICODE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_UTF8TOUNICODE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_REPLACEMENTTOUNICODE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_UNICODETOISO88591_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_UNICODETOCP1252_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_UNICODETOMACROMAN_CID);
|
||||
|
@ -690,6 +694,7 @@ static const mozilla::Module::CIDEntry kUConvCIDs[] = {
|
|||
{ &kNS_ISO88591TOUNICODE_CID, false, nullptr, nsISO88591ToUnicodeConstructor },
|
||||
{ &kNS_CP1252TOUNICODE_CID, false, nullptr, nsCP1252ToUnicodeConstructor },
|
||||
{ &kNS_MACROMANTOUNICODE_CID, false, nullptr, nsMacRomanToUnicodeConstructor },
|
||||
{ &kNS_REPLACEMENTTOUNICODE_CID, false, nullptr, nsReplacementToUnicodeConstructor },
|
||||
{ &kNS_UTF8TOUNICODE_CID, false, nullptr, nsUTF8ToUnicodeConstructor },
|
||||
{ &kNS_UNICODETOISO88591_CID, false, nullptr, nsUnicodeToISO88591Constructor },
|
||||
{ &kNS_UNICODETOCP1252_CID, false, nullptr, nsUnicodeToCP1252Constructor },
|
||||
|
@ -877,6 +882,7 @@ static const mozilla::Module::ContractIDEntry kUConvContracts[] = {
|
|||
{ NS_ISO88591TOUNICODE_CONTRACTID, &kNS_ISO88591TOUNICODE_CID },
|
||||
{ NS_CP1252TOUNICODE_CONTRACTID, &kNS_CP1252TOUNICODE_CID },
|
||||
{ NS_MACROMANTOUNICODE_CONTRACTID, &kNS_MACROMANTOUNICODE_CID },
|
||||
{ NS_REPLACEMENTTOUNICODE_CONTRACTID, &kNS_REPLACEMENTTOUNICODE_CID },
|
||||
{ NS_UTF8TOUNICODE_CONTRACTID, &kNS_UTF8TOUNICODE_CID },
|
||||
{ NS_UNICODETOISO88591_CONTRACTID, &kNS_UNICODETOISO88591_CID },
|
||||
{ NS_UNICODETOCP1252_CONTRACTID, &kNS_UNICODETOCP1252_CID },
|
||||
|
|
|
@ -34,7 +34,10 @@ while (decoderList.hasMore()) {
|
|||
|
||||
// Skip UTF-16 variants. (Other non-ASCII compatible encodings will be
|
||||
// ignored anyway because of bug 601429
|
||||
if (decoder.substring(0, 6) == "UTF-16")
|
||||
if (decoder.substring(0, 6) == "UTF-16" ||
|
||||
decoder == "replacement" ||
|
||||
decoder == "ISO-2022-KR" ||
|
||||
decoder == "ISO-2022-CN")
|
||||
continue;
|
||||
|
||||
data = encodeURI(testContent);
|
||||
|
|
|
@ -99,6 +99,7 @@ var encoderList = [
|
|||
"gbk",
|
||||
"HZ-GB-2312",
|
||||
"gb18030",
|
||||
"replacement",
|
||||
];
|
||||
|
||||
var decoderList = [
|
||||
|
@ -183,6 +184,7 @@ var decoderList = [
|
|||
"gb18030",
|
||||
"ISO-2022-KR",
|
||||
"ISO-2022-CN",
|
||||
"replacement",
|
||||
];
|
||||
|
||||
function verifyList(aEnumerator, aList)
|
||||
|
|
|
@ -43,6 +43,11 @@ const JSFunctionSpec ParallelArrayObject::methods[] = {
|
|||
JS_FS_END
|
||||
};
|
||||
|
||||
const JSPropertySpec ParallelArrayObject::properties[] = {
|
||||
JS_SELF_HOSTED_GET("length", "ParallelArrayLength", JSPROP_PERMANENT),
|
||||
JS_PS_END
|
||||
};
|
||||
|
||||
const Class ParallelArrayObject::protoClass = {
|
||||
"ParallelArray",
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_ParallelArray),
|
||||
|
@ -220,37 +225,12 @@ ParallelArrayObject::initClass(JSContext *cx, HandleObject obj)
|
|||
cx->names().ParallelArray, 0));
|
||||
if (!ctor ||
|
||||
!LinkConstructorAndPrototype(cx, ctor, proto) ||
|
||||
!DefinePropertiesAndBrand(cx, proto, nullptr, methods) ||
|
||||
!DefinePropertiesAndBrand(cx, proto, properties, methods) ||
|
||||
!DefineConstructorAndPrototype(cx, global, key, ctor, proto))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Define the length getter.
|
||||
{
|
||||
const char lengthStr[] = "ParallelArrayLength";
|
||||
JSAtom *atom = Atomize(cx, lengthStr, strlen(lengthStr));
|
||||
if (!atom)
|
||||
return nullptr;
|
||||
Rooted<PropertyName *> lengthProp(cx, atom->asPropertyName());
|
||||
RootedValue lengthValue(cx);
|
||||
if (!cx->global()->getIntrinsicValue(cx, lengthProp, &lengthValue))
|
||||
return nullptr;
|
||||
RootedObject lengthGetter(cx, &lengthValue.toObject());
|
||||
if (!lengthGetter)
|
||||
return nullptr;
|
||||
|
||||
RootedId lengthId(cx, AtomToId(cx->names().length));
|
||||
unsigned flags = JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_GETTER;
|
||||
RootedValue value(cx, UndefinedValue());
|
||||
if (!DefineNativeProperty(cx, proto, lengthId, value,
|
||||
JS_DATA_TO_FUNC_PTR(PropertyOp, lengthGetter.get()), nullptr,
|
||||
flags, 0, 0))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return proto;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ class ParallelArrayObject : public JSObject
|
|||
{
|
||||
static const Class protoClass;
|
||||
static const JSFunctionSpec methods[];
|
||||
static const JSPropertySpec properties[];
|
||||
static const uint32_t NumFixedSlots = 4;
|
||||
static const uint32_t NumCtors = 4;
|
||||
static FixedHeapPtr<PropertyName> ctorNames[NumCtors];
|
||||
|
|
|
@ -872,7 +872,7 @@ ArrayType::create(JSContext *cx,
|
|||
JS_ASSERT(prototypeVal.isObject()); // immutable binding
|
||||
|
||||
RootedObject obj(
|
||||
cx, NewObjectWithClassProto(cx, &ArrayType::class_,
|
||||
cx, NewObjectWithGivenProto(cx, &ArrayType::class_,
|
||||
&prototypeVal.toObject(), cx->global()));
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
@ -1145,7 +1145,7 @@ StructType::create(JSContext *cx, HandleObject metaTypeObject,
|
|||
JS_ASSERT(prototypeVal.isObject()); // immutable binding
|
||||
|
||||
RootedObject obj(
|
||||
cx, NewObjectWithClassProto(cx, &StructType::class_,
|
||||
cx, NewObjectWithGivenProto(cx, &StructType::class_,
|
||||
&prototypeVal.toObject(), cx->global()));
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
@ -1249,15 +1249,15 @@ StructType::construct(JSContext *cx, unsigned int argc, Value *vp)
|
|||
template<typename T>
|
||||
static bool
|
||||
DefineSimpleTypeObject(JSContext *cx,
|
||||
HandleObject global,
|
||||
Handle<GlobalObject *> global,
|
||||
HandleObject module,
|
||||
typename T::TypeRepr::Type type,
|
||||
HandlePropertyName className)
|
||||
{
|
||||
RootedObject funcProto(cx, JS_GetFunctionPrototype(cx, global));
|
||||
RootedObject funcProto(cx, global->getOrCreateFunctionPrototype(cx));
|
||||
JS_ASSERT(funcProto);
|
||||
|
||||
RootedObject numFun(cx, NewObjectWithClassProto(cx, &T::class_, funcProto, global));
|
||||
RootedObject numFun(cx, NewObjectWithGivenProto(cx, &T::class_, funcProto, global));
|
||||
if (!numFun)
|
||||
return false;
|
||||
|
||||
|
@ -1521,7 +1521,7 @@ js_InitTypedObjectClass(JSContext *cx, HandleObject obj)
|
|||
if (!objProto)
|
||||
return nullptr;
|
||||
|
||||
RootedObject module(cx, NewObjectWithClassProto(cx, &JSObject::class_,
|
||||
RootedObject module(cx, NewObjectWithGivenProto(cx, &JSObject::class_,
|
||||
objProto, global));
|
||||
if (!module)
|
||||
return nullptr;
|
||||
|
|
|
@ -2916,13 +2916,24 @@ MOZ_ARG_WITH_STRING(nspr-libs,
|
|||
AC_SUBST(NSPR_CFLAGS)
|
||||
AC_SUBST(NSPR_LIBS)
|
||||
|
||||
JS_THREADSAFE=1
|
||||
MOZ_ARG_DISABLE_BOOL(threadsafe,
|
||||
[ --disable-threadsafe Disable support for multiple threads.],
|
||||
JS_THREADSAFE= ,
|
||||
JS_THREADSAFE=1 )
|
||||
if test -n "$JS_THREADSAFE"; then
|
||||
AC_DEFINE(JS_THREADSAFE)
|
||||
fi
|
||||
|
||||
if test "$_USE_SYSTEM_NSPR" || (test "$NSPR_CFLAGS" -o "$NSPR_LIBS"); then
|
||||
_HAS_NSPR=1
|
||||
fi
|
||||
|
||||
case "$target" in
|
||||
*linux*|*darwin*|*dragonfly*|*freebsd*|*netbsd*|*openbsd*)
|
||||
if test -z "$_HAS_NSPR"; then JS_POSIX_NSPR_DEFAULT=1; fi
|
||||
if test -z "$_HAS_NSPR" && test "$JS_THREADSAFE"; then
|
||||
JS_POSIX_NSPR_DEFAULT=1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
|
@ -2936,6 +2947,8 @@ if test -n "$JS_POSIX_NSPR"; then
|
|||
AC_DEFINE(JS_POSIX_NSPR)
|
||||
fi
|
||||
|
||||
AC_SUBST(JS_POSIX_NSPR)
|
||||
|
||||
dnl Pass either --with-system-nspr or (--with-nspr-cflags and
|
||||
dnl --with-nspr-libs), but not both.
|
||||
if test "$_USE_SYSTEM_NSPR" && (test "$NSPR_CFLAGS" -o "$NSPR_LIBS"); then
|
||||
|
@ -4108,15 +4121,6 @@ elif test "$OS_ARCH" != "WINNT" -a "$OS_ARCH" != "OS2"; then
|
|||
AC_DEFINE(XP_UNIX)
|
||||
fi
|
||||
|
||||
JS_THREADSAFE=1
|
||||
MOZ_ARG_DISABLE_BOOL(threadsafe,
|
||||
[ --disable-threadsafe Disable support for multiple threads.],
|
||||
JS_THREADSAFE= ,
|
||||
JS_THREADSAFE=1 )
|
||||
if test -n "$JS_THREADSAFE"; then
|
||||
AC_DEFINE(JS_THREADSAFE)
|
||||
fi
|
||||
|
||||
if test "$MOZ_DEBUG"; then
|
||||
AC_DEFINE(MOZ_REFLOW_PERF)
|
||||
AC_DEFINE(MOZ_REFLOW_PERF_DSP)
|
||||
|
|
|
@ -3242,6 +3242,15 @@ JS_DefineProperties(JSContext *cx, JSObject *objArg, const JSPropertySpec *ps)
|
|||
// If you have self-hosted getter/setter, you can't have a
|
||||
// native one.
|
||||
JS_ASSERT(!ps->getter.op && !ps->setter.op);
|
||||
/*
|
||||
* During creation of the self-hosting global, we ignore all
|
||||
* self-hosted properties, as that means we're currently setting up
|
||||
* the global object that the self-hosted code is then compiled
|
||||
* in. That means that Self-hosted properties can't be used in the
|
||||
* self-hosting global itself, right now.
|
||||
*/
|
||||
if (cx->runtime()->isSelfHostingGlobal(cx->global()))
|
||||
continue;
|
||||
|
||||
ok = DefineSelfHostedProperty(cx, obj, ps->name,
|
||||
ps->selfHostedGetter,
|
||||
|
@ -4146,6 +4155,8 @@ JS_DefineFunctions(JSContext *cx, JSObject *objArg, const JSFunctionSpec *fs)
|
|||
* call paths then call InitializeLazyFunctionScript if !hasScript.
|
||||
*/
|
||||
if (fs->selfHostedName) {
|
||||
JS_ASSERT(!fs->call.op);
|
||||
JS_ASSERT(!fs->call.info);
|
||||
/*
|
||||
* During creation of the self-hosting global, we ignore all
|
||||
* self-hosted functions, as that means we're currently setting up
|
||||
|
@ -4153,8 +4164,6 @@ JS_DefineFunctions(JSContext *cx, JSObject *objArg, const JSFunctionSpec *fs)
|
|||
* in. Self-hosted functions can access each other via their names,
|
||||
* but not via the builtin classes they get installed into.
|
||||
*/
|
||||
JS_ASSERT(!fs->call.op);
|
||||
JS_ASSERT(!fs->call.info);
|
||||
if (cx->runtime()->isSelfHostingGlobal(cx->global()))
|
||||
continue;
|
||||
|
||||
|
|
|
@ -1475,7 +1475,10 @@ static const JSFunctionSpec math_static_methods[] = {
|
|||
JSObject *
|
||||
js_InitMathClass(JSContext *cx, HandleObject obj)
|
||||
{
|
||||
RootedObject Math(cx, NewObjectWithClassProto(cx, &MathClass, nullptr, obj, SingletonObject));
|
||||
RootedObject proto(cx, obj->as<GlobalObject>().getOrCreateObjectPrototype(cx));
|
||||
if (!proto)
|
||||
return nullptr;
|
||||
RootedObject Math(cx, NewObjectWithGivenProto(cx, &MathClass, proto, obj, SingletonObject));
|
||||
if (!Math)
|
||||
return nullptr;
|
||||
|
||||
|
|
|
@ -873,8 +873,8 @@ js_InitJSONClass(JSContext *cx, HandleObject obj)
|
|||
if (!global->getOrCreateBooleanPrototype(cx))
|
||||
return nullptr;
|
||||
|
||||
RootedObject JSON(cx, NewObjectWithClassProto(cx, &JSONClass, nullptr,
|
||||
global, SingletonObject));
|
||||
RootedObject proto(cx, obj->as<GlobalObject>().getOrCreateObjectPrototype(cx));
|
||||
RootedObject JSON(cx, NewObjectWithClassProto(cx, &JSONClass, proto, global, SingletonObject));
|
||||
if (!JSON)
|
||||
return nullptr;
|
||||
|
||||
|
|
|
@ -3313,7 +3313,10 @@ JS_InitReflect(JSContext *cx, JSObject *objArg)
|
|||
};
|
||||
|
||||
RootedObject obj(cx, objArg);
|
||||
RootedObject Reflect(cx, NewObjectWithClassProto(cx, &JSObject::class_, nullptr,
|
||||
RootedObject proto(cx, obj->as<GlobalObject>().getOrCreateObjectPrototype(cx));
|
||||
if (!proto)
|
||||
return nullptr;
|
||||
RootedObject Reflect(cx, NewObjectWithGivenProto(cx, &JSObject::class_, proto,
|
||||
obj, SingletonObject));
|
||||
if (!Reflect)
|
||||
return nullptr;
|
||||
|
|
|
@ -170,7 +170,6 @@ UNIFIED_SOURCES += [
|
|||
'vm/Monitor.cpp',
|
||||
'vm/ObjectImpl.cpp',
|
||||
'vm/OldDebugAPI.cpp',
|
||||
'vm/PosixNSPR.cpp',
|
||||
'vm/Probes.cpp',
|
||||
'vm/PropertyKey.cpp',
|
||||
'vm/ProxyObject.cpp',
|
||||
|
@ -206,6 +205,11 @@ SOURCES += [
|
|||
'jsutil.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['JS_POSIX_NSPR']:
|
||||
UNIFIED_SOURCES += [
|
||||
'vm/PosixNSPR.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_INSTRUMENTS']:
|
||||
SOURCES += [
|
||||
'devtools/Instruments.cpp',
|
||||
|
|
|
@ -387,7 +387,11 @@ GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
|
|||
if (cx->runtime()->isSelfHostingGlobal(self)) {
|
||||
intrinsicsHolder = self;
|
||||
} else {
|
||||
intrinsicsHolder = NewObjectWithClassProto(cx, &JSObject::class_, nullptr, self, TenuredObject);
|
||||
RootedObject proto(cx, self->getOrCreateObjectPrototype(cx));
|
||||
if (!proto)
|
||||
return nullptr;
|
||||
intrinsicsHolder = NewObjectWithGivenProto(cx, &JSObject::class_, proto, self,
|
||||
TenuredObject);
|
||||
if (!intrinsicsHolder)
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -483,6 +487,9 @@ GlobalObject::initStandardClasses(JSContext *cx, Handle<GlobalObject*> global)
|
|||
GlobalObject::initSetIteratorProto(cx, global) &&
|
||||
#if EXPOSE_INTL_API
|
||||
js_InitIntlClass(cx, global) &&
|
||||
#endif
|
||||
#if ENABLE_PARALLEL_JS
|
||||
js_InitParallelArrayClass(cx, global) &&
|
||||
#endif
|
||||
true;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,10 @@
|
|||
|
||||
#ifdef JS_POSIX_NSPR
|
||||
|
||||
#ifndef JS_THREADSAFE
|
||||
#error "This file must not be included in non-threadsafe mode"
|
||||
#endif
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
|
|
@ -331,12 +331,12 @@ GetViewListRef(ArrayBufferObject *obj)
|
|||
return reinterpret_cast<OldObjectRepresentationHack*>(obj->getElementsHeader())->views;
|
||||
}
|
||||
|
||||
bool
|
||||
ArrayBufferObject::neuterViews(JSContext *cx)
|
||||
/* static */ bool
|
||||
ArrayBufferObject::neuterViews(JSContext *cx, Handle<ArrayBufferObject*> buffer)
|
||||
{
|
||||
ArrayBufferViewObject *view;
|
||||
size_t numViews = 0;
|
||||
for (view = GetViewList(this); view; view = view->nextView()) {
|
||||
for (view = GetViewList(buffer); view; view = view->nextView()) {
|
||||
numViews++;
|
||||
view->neuter();
|
||||
|
||||
|
@ -346,26 +346,26 @@ ArrayBufferObject::neuterViews(JSContext *cx)
|
|||
|
||||
// neuterAsmJSArrayBuffer adjusts state specific to the ArrayBuffer data
|
||||
// itself, but it only affects the behavior of views
|
||||
if (isAsmJSArrayBuffer()) {
|
||||
if (!ArrayBufferObject::neuterAsmJSArrayBuffer(cx, *this))
|
||||
if (buffer->isAsmJSArrayBuffer()) {
|
||||
if (!ArrayBufferObject::neuterAsmJSArrayBuffer(cx, *buffer))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove buffer from the list of buffers with > 1 view.
|
||||
if (numViews > 1 && GetViewList(this)->bufferLink() != UNSET_BUFFER_LINK) {
|
||||
ArrayBufferObject *prev = compartment()->gcLiveArrayBuffers;
|
||||
if (prev == this) {
|
||||
compartment()->gcLiveArrayBuffers = GetViewList(prev)->bufferLink();
|
||||
if (numViews > 1 && GetViewList(buffer)->bufferLink() != UNSET_BUFFER_LINK) {
|
||||
ArrayBufferObject *prev = buffer->compartment()->gcLiveArrayBuffers;
|
||||
if (prev == buffer) {
|
||||
buffer->compartment()->gcLiveArrayBuffers = GetViewList(prev)->bufferLink();
|
||||
} else {
|
||||
for (ArrayBufferObject *buf = GetViewList(prev)->bufferLink();
|
||||
buf;
|
||||
buf = GetViewList(buf)->bufferLink())
|
||||
for (ArrayBufferObject *b = GetViewList(prev)->bufferLink();
|
||||
b;
|
||||
b = GetViewList(b)->bufferLink())
|
||||
{
|
||||
if (buf == this) {
|
||||
GetViewList(prev)->setBufferLink(GetViewList(buf)->bufferLink());
|
||||
if (b == buffer) {
|
||||
GetViewList(prev)->setBufferLink(GetViewList(b)->bufferLink());
|
||||
break;
|
||||
}
|
||||
prev = buf;
|
||||
prev = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -705,7 +705,7 @@ ArrayBufferObject::stealContents(JSContext *cx, Handle<ArrayBufferObject*> buffe
|
|||
|
||||
// Neuter the views, which may also mprotect(PROT_NONE) the buffer. So do
|
||||
// it after copying out the data.
|
||||
if (!buffer->neuterViews(cx))
|
||||
if (!ArrayBufferObject::neuterViews(cx, buffer))
|
||||
return false;
|
||||
|
||||
if (!own) {
|
||||
|
@ -4062,7 +4062,7 @@ JS_NeuterArrayBuffer(JSContext *cx, HandleObject obj)
|
|||
}
|
||||
|
||||
Rooted<ArrayBufferObject*> buffer(cx, &obj->as<ArrayBufferObject>());
|
||||
if (!buffer->neuterViews(cx))
|
||||
if (!ArrayBufferObject::neuterViews(cx, buffer))
|
||||
return false;
|
||||
buffer->neuter(cx);
|
||||
return true;
|
||||
|
|
|
@ -198,7 +198,7 @@ class ArrayBufferObject : public JSObject
|
|||
/*
|
||||
* Neuter all views of an ArrayBuffer.
|
||||
*/
|
||||
bool neuterViews(JSContext *cx);
|
||||
static bool neuterViews(JSContext *cx, Handle<ArrayBufferObject*> buffer);
|
||||
|
||||
inline uint8_t * dataPointer() const {
|
||||
return (uint8_t *) elements;
|
||||
|
|
|
@ -32,6 +32,10 @@ while (decoderList.hasMore()) {
|
|||
data = encodeUTF16BE(testContent);
|
||||
else if (decoder == "UTF-16" || decoder == "UTF-16LE")
|
||||
data = encodeUTF16LE(testContent);
|
||||
else if (decoder == "replacement" ||
|
||||
decoder == "ISO-2022-KR" ||
|
||||
decoder == "ISO-2022-CN")
|
||||
continue;
|
||||
else
|
||||
data = encodeURI(testContent);
|
||||
var dataURI = "data:text/html;charset=" + decoder + "," + data;
|
||||
|
|
|
@ -786,6 +786,67 @@ nsBlockFrame::ComputeTightBounds(gfxContext* aContext) const
|
|||
return ComputeSimpleTightBounds(aContext);
|
||||
}
|
||||
|
||||
/* virtual */ nsresult
|
||||
nsBlockFrame::GetPrefWidthTightBounds(nsRenderingContext* aRenderingContext,
|
||||
nscoord* aX,
|
||||
nscoord* aXMost)
|
||||
{
|
||||
nsIFrame* firstInFlow = FirstContinuation();
|
||||
if (firstInFlow != this) {
|
||||
return firstInFlow->GetPrefWidthTightBounds(aRenderingContext, aX, aXMost);
|
||||
}
|
||||
|
||||
*aX = 0;
|
||||
*aXMost = 0;
|
||||
|
||||
nsresult rv;
|
||||
InlinePrefWidthData data;
|
||||
for (nsBlockFrame* curFrame = this; curFrame;
|
||||
curFrame = static_cast<nsBlockFrame*>(curFrame->GetNextContinuation())) {
|
||||
for (line_iterator line = curFrame->begin_lines(), line_end = curFrame->end_lines();
|
||||
line != line_end; ++line)
|
||||
{
|
||||
nscoord childX, childXMost;
|
||||
if (line->IsBlock()) {
|
||||
data.ForceBreak(aRenderingContext);
|
||||
rv = line->mFirstChild->GetPrefWidthTightBounds(aRenderingContext,
|
||||
&childX, &childXMost);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
*aX = std::min(*aX, childX);
|
||||
*aXMost = std::max(*aXMost, childXMost);
|
||||
} else {
|
||||
if (!curFrame->GetPrevContinuation() &&
|
||||
line == curFrame->begin_lines()) {
|
||||
// Only add text-indent if it has no percentages; using a
|
||||
// percentage basis of 0 unconditionally would give strange
|
||||
// behavior for calc(10%-3px).
|
||||
const nsStyleCoord &indent = StyleText()->mTextIndent;
|
||||
if (indent.ConvertsToLength()) {
|
||||
data.currentLine += nsRuleNode::ComputeCoordPercentCalc(indent, 0);
|
||||
}
|
||||
}
|
||||
// XXX Bug NNNNNN Should probably handle percentage text-indent.
|
||||
|
||||
data.line = &line;
|
||||
data.lineContainer = curFrame;
|
||||
nsIFrame *kid = line->mFirstChild;
|
||||
for (int32_t i = 0, i_end = line->GetChildCount(); i != i_end;
|
||||
++i, kid = kid->GetNextSibling()) {
|
||||
rv = kid->GetPrefWidthTightBounds(aRenderingContext, &childX,
|
||||
&childXMost);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
*aX = std::min(*aX, data.currentLine + childX);
|
||||
*aXMost = std::max(*aXMost, data.currentLine + childXMost);
|
||||
kid->AddInlinePrefWidth(aRenderingContext, &data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
data.ForceBreak(aRenderingContext);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static bool
|
||||
AvailableSpaceShrunk(const nsRect& aOldAvailableSpace,
|
||||
const nsRect& aNewAvailableSpace)
|
||||
|
|
|
@ -261,6 +261,10 @@ public:
|
|||
|
||||
virtual nsRect ComputeTightBounds(gfxContext* aContext) const MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult GetPrefWidthTightBounds(nsRenderingContext* aContext,
|
||||
nscoord* aX,
|
||||
nscoord* aXMost) MOZ_OVERRIDE;
|
||||
|
||||
/**
|
||||
* Compute the final height of this frame.
|
||||
*
|
||||
|
|
|
@ -1563,8 +1563,8 @@ MainAxisPositionTracker::
|
|||
}
|
||||
|
||||
mJustifyContent = aFlexContainerFrame->StylePosition()->mJustifyContent;
|
||||
// If packing space is negative, 'justify' behaves like 'start', and
|
||||
// 'distribute' behaves like 'center'. In those cases, it's simplest to
|
||||
// If packing space is negative, 'space-between' behaves like 'flex-start',
|
||||
// and 'space-around' behaves like 'center'. In those cases, it's simplest to
|
||||
// just pretend we have a different 'justify-content' value and share code.
|
||||
if (mPackingSpaceRemaining < 0) {
|
||||
if (mJustifyContent == NS_STYLE_JUSTIFY_CONTENT_SPACE_BETWEEN) {
|
||||
|
@ -1863,7 +1863,7 @@ SingleLineCrossAxisPositionTracker::
|
|||
case NS_STYLE_ALIGN_ITEMS_FLEX_START:
|
||||
case NS_STYLE_ALIGN_ITEMS_STRETCH:
|
||||
// No space to skip over -- we're done.
|
||||
// NOTE: 'stretch' behaves like 'start' once we've stretched any
|
||||
// NOTE: 'stretch' behaves like 'flex-start' once we've stretched any
|
||||
// auto-sized items (which we've already done).
|
||||
break;
|
||||
case NS_STYLE_ALIGN_ITEMS_FLEX_END:
|
||||
|
|
|
@ -4049,6 +4049,14 @@ nsFrame::ComputeSimpleTightBounds(gfxContext* aContext) const
|
|||
return r;
|
||||
}
|
||||
|
||||
/* virtual */ nsresult
|
||||
nsIFrame::GetPrefWidthTightBounds(nsRenderingContext* aContext,
|
||||
nscoord* aX,
|
||||
nscoord* aXMost)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* virtual */ nsSize
|
||||
nsFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext,
|
||||
nsSize aCBSize, nscoord aAvailableWidth,
|
||||
|
|
|
@ -1832,6 +1832,26 @@ public:
|
|||
*/
|
||||
virtual nsRect ComputeTightBounds(gfxContext* aContext) const;
|
||||
|
||||
/**
|
||||
* This function is similar to GetPrefWidth and ComputeTightBounds: it
|
||||
* computes the left and right coordinates of a preferred tight bounding
|
||||
* rectangle for the frame. This is a rectangle that would enclose the pixels
|
||||
* that are drawn if we lay out the element without taking any optional line
|
||||
* breaks. The rectangle is in appunits and relative to the origin of this
|
||||
* frame. Currently, this function is only implemented for nsBlockFrame and
|
||||
* nsTextFrame and is used to determine intrinsic widths of MathML token
|
||||
* elements.
|
||||
|
||||
* @param aContext a rendering context that can be used if we need
|
||||
* to do measurement
|
||||
* @param aX computed left coordinate of the tight bounding rectangle
|
||||
* @param aXMost computed intrinsic width of the tight bounding rectangle
|
||||
*
|
||||
*/
|
||||
virtual nsresult GetPrefWidthTightBounds(nsRenderingContext* aContext,
|
||||
nscoord* aX,
|
||||
nscoord* aXMost);
|
||||
|
||||
/**
|
||||
* Pre-reflow hook. Before a frame is reflowed this method will be called.
|
||||
* This call will always be invoked at least once before a subsequent Reflow
|
||||
|
|
|
@ -2609,17 +2609,20 @@ GetEndOfTrimmedText(const nsTextFragment* aFrag, const nsStyleText* aStyleText,
|
|||
|
||||
nsTextFrame::TrimmedOffsets
|
||||
nsTextFrame::GetTrimmedOffsets(const nsTextFragment* aFrag,
|
||||
bool aTrimAfter)
|
||||
bool aTrimAfter, bool aPostReflow)
|
||||
{
|
||||
NS_ASSERTION(mTextRun, "Need textrun here");
|
||||
// This should not be used during reflow. We need our TEXT_REFLOW_FLAGS
|
||||
// to be set correctly. If our parent wasn't reflowed due to the frame
|
||||
// tree being too deep then the return value doesn't matter.
|
||||
NS_ASSERTION(!(GetStateBits() & NS_FRAME_FIRST_REFLOW) ||
|
||||
(GetParent()->GetStateBits() & NS_FRAME_TOO_DEEP_IN_FRAME_TREE),
|
||||
"Can only call this on frames that have been reflowed");
|
||||
NS_ASSERTION(!(GetStateBits() & NS_FRAME_IN_REFLOW),
|
||||
"Can only call this on frames that are not being reflowed");
|
||||
if (aPostReflow) {
|
||||
// This should not be used during reflow. We need our TEXT_REFLOW_FLAGS
|
||||
// to be set correctly. If our parent wasn't reflowed due to the frame
|
||||
// tree being too deep then the return value doesn't matter.
|
||||
NS_ASSERTION(!(GetStateBits() & NS_FRAME_FIRST_REFLOW) ||
|
||||
(GetParent()->GetStateBits() &
|
||||
NS_FRAME_TOO_DEEP_IN_FRAME_TREE),
|
||||
"Can only call this on frames that have been reflowed");
|
||||
NS_ASSERTION(!(GetStateBits() & NS_FRAME_IN_REFLOW),
|
||||
"Can only call this on frames that are not being reflowed");
|
||||
}
|
||||
|
||||
TrimmedOffsets offsets = { GetContentOffset(), GetContentLength() };
|
||||
const nsStyleText* textStyle = StyleText();
|
||||
|
@ -2628,7 +2631,7 @@ nsTextFrame::GetTrimmedOffsets(const nsTextFragment* aFrag,
|
|||
if (textStyle->WhiteSpaceIsSignificant())
|
||||
return offsets;
|
||||
|
||||
if (GetStateBits() & TEXT_START_OF_LINE) {
|
||||
if (!aPostReflow || (GetStateBits() & TEXT_START_OF_LINE)) {
|
||||
int32_t whitespaceCount =
|
||||
GetTrimmableWhitespaceCount(aFrag,
|
||||
offsets.mStart, offsets.mLength, 1);
|
||||
|
@ -2636,7 +2639,7 @@ nsTextFrame::GetTrimmedOffsets(const nsTextFragment* aFrag,
|
|||
offsets.mLength -= whitespaceCount;
|
||||
}
|
||||
|
||||
if (aTrimAfter && (GetStateBits() & TEXT_END_OF_LINE)) {
|
||||
if (aTrimAfter && (!aPostReflow || (GetStateBits() & TEXT_END_OF_LINE))) {
|
||||
// This treats a trailing 'pre-line' newline as trimmable. That's fine,
|
||||
// it's actually what we want since we want whitespace before it to
|
||||
// be trimmed.
|
||||
|
@ -2809,6 +2812,8 @@ public:
|
|||
// Call this after construction if you're not going to reflow the text
|
||||
void InitializeForDisplay(bool aTrimAfter);
|
||||
|
||||
void InitializeForMeasure();
|
||||
|
||||
virtual void GetSpacing(uint32_t aStart, uint32_t aLength, Spacing* aSpacing);
|
||||
virtual gfxFloat GetHyphenWidth();
|
||||
virtual void GetHyphenationBreaks(uint32_t aStart, uint32_t aLength,
|
||||
|
@ -3249,6 +3254,17 @@ PropertyProvider::InitializeForDisplay(bool aTrimAfter)
|
|||
SetupJustificationSpacing();
|
||||
}
|
||||
|
||||
void
|
||||
PropertyProvider::InitializeForMeasure()
|
||||
{
|
||||
nsTextFrame::TrimmedOffsets trimmed =
|
||||
mFrame->GetTrimmedOffsets(mFrag, true, false);
|
||||
mStart.SetOriginalOffset(trimmed.mStart);
|
||||
mLength = trimmed.mLength;
|
||||
SetupJustificationSpacing();
|
||||
}
|
||||
|
||||
|
||||
static uint32_t GetSkippedDistance(const gfxSkipCharsIterator& aStart,
|
||||
const gfxSkipCharsIterator& aEnd)
|
||||
{
|
||||
|
@ -7287,6 +7303,31 @@ nsTextFrame::ComputeTightBounds(gfxContext* aContext) const
|
|||
return RoundOut(metrics.mBoundingBox) + nsPoint(0, mAscent);
|
||||
}
|
||||
|
||||
/* virtual */ nsresult
|
||||
nsTextFrame::GetPrefWidthTightBounds(nsRenderingContext* aContext,
|
||||
nscoord* aX,
|
||||
nscoord* aXMost)
|
||||
{
|
||||
gfxSkipCharsIterator iter =
|
||||
const_cast<nsTextFrame*>(this)->EnsureTextRun(nsTextFrame::eInflated);
|
||||
if (!mTextRun)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PropertyProvider provider(const_cast<nsTextFrame*>(this), iter,
|
||||
nsTextFrame::eInflated);
|
||||
provider.InitializeForMeasure();
|
||||
|
||||
gfxTextRun::Metrics metrics =
|
||||
mTextRun->MeasureText(provider.GetStart().GetSkippedOffset(),
|
||||
ComputeTransformedLength(provider),
|
||||
gfxFont::TIGHT_HINTED_OUTLINE_EXTENTS,
|
||||
aContext->ThebesContext(), &provider);
|
||||
*aX = metrics.mBoundingBox.x;
|
||||
*aXMost = metrics.mBoundingBox.XMost();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static bool
|
||||
HasSoftHyphenBefore(const nsTextFragment* aFrag, gfxTextRun* aTextRun,
|
||||
int32_t aStartOffset, const gfxSkipCharsIterator& aIter)
|
||||
|
|
|
@ -221,6 +221,9 @@ public:
|
|||
nsSize aMargin, nsSize aBorder, nsSize aPadding,
|
||||
uint32_t aFlags) MOZ_OVERRIDE;
|
||||
virtual nsRect ComputeTightBounds(gfxContext* aContext) const MOZ_OVERRIDE;
|
||||
virtual nsresult GetPrefWidthTightBounds(nsRenderingContext* aContext,
|
||||
nscoord* aX,
|
||||
nscoord* aXMost) MOZ_OVERRIDE;
|
||||
NS_IMETHOD Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aMetrics,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
|
@ -511,7 +514,7 @@ public:
|
|||
int32_t GetEnd() const { return mStart + mLength; }
|
||||
};
|
||||
TrimmedOffsets GetTrimmedOffsets(const nsTextFragment* aFrag,
|
||||
bool aTrimAfter);
|
||||
bool aTrimAfter, bool aPostReflow = true);
|
||||
|
||||
// Similar to Reflow(), but for use from nsLineLayout
|
||||
void ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
|
||||
|
|
|
@ -29,6 +29,7 @@ NS_IMPL_FRAMEARENA_HELPERS(nsMathMLContainerFrame)
|
|||
|
||||
NS_QUERYFRAME_HEAD(nsMathMLContainerFrame)
|
||||
NS_QUERYFRAME_ENTRY(nsIMathMLFrame)
|
||||
NS_QUERYFRAME_ENTRY(nsMathMLContainerFrame)
|
||||
NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
|
||||
|
||||
// =============================================================================
|
||||
|
@ -985,7 +986,11 @@ nsMathMLContainerFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
|
|||
{
|
||||
nscoord result;
|
||||
DISPLAY_MIN_WIDTH(this, result);
|
||||
result = GetIntrinsicWidth(aRenderingContext);
|
||||
nsHTMLReflowMetrics desiredSize;
|
||||
GetIntrinsicWidthMetrics(aRenderingContext, desiredSize);
|
||||
nsBoundingMetrics bm = desiredSize.mBoundingMetrics;
|
||||
// We include the overflow to compensate for FixInterFrameSpacing.
|
||||
result = std::max(bm.width, bm.rightBearing) - std::min(0, bm.leftBearing);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -994,29 +999,46 @@ nsMathMLContainerFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
|
|||
{
|
||||
nscoord result;
|
||||
DISPLAY_MIN_WIDTH(this, result);
|
||||
result = GetIntrinsicWidth(aRenderingContext);
|
||||
nsHTMLReflowMetrics desiredSize;
|
||||
GetIntrinsicWidthMetrics(aRenderingContext, desiredSize);
|
||||
nsBoundingMetrics bm = desiredSize.mBoundingMetrics;
|
||||
// We include the overflow to compensate for FixInterFrameSpacing.
|
||||
result = std::max(bm.width, bm.rightBearing) - std::min(0, bm.leftBearing);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
nsMathMLContainerFrame::GetIntrinsicWidth(nsRenderingContext* aRenderingContext)
|
||||
/* virtual */ void
|
||||
nsMathMLContainerFrame::GetIntrinsicWidthMetrics(nsRenderingContext* aRenderingContext, nsHTMLReflowMetrics& aDesiredSize)
|
||||
{
|
||||
// Get child widths
|
||||
nsIFrame* childFrame = mFrames.FirstChild();
|
||||
while (childFrame) {
|
||||
// XXX This includes margin while Reflow currently doesn't consider
|
||||
// margin, so we may end up with too much space, but, with stretchy
|
||||
// characters, this is an approximation anyway.
|
||||
nscoord width =
|
||||
nsLayoutUtils::IntrinsicForContainer(aRenderingContext, childFrame,
|
||||
nsLayoutUtils::PREF_WIDTH);
|
||||
|
||||
nsHTMLReflowMetrics childDesiredSize;
|
||||
childDesiredSize.width = width;
|
||||
childDesiredSize.mBoundingMetrics.width = width;
|
||||
// TODO: we need nsIFrame::GetIntrinsicHBounds() for better values here.
|
||||
childDesiredSize.mBoundingMetrics.leftBearing = 0;
|
||||
childDesiredSize.mBoundingMetrics.rightBearing = width;
|
||||
|
||||
nsMathMLContainerFrame* containerFrame = do_QueryFrame(childFrame);
|
||||
if (containerFrame) {
|
||||
containerFrame->GetIntrinsicWidthMetrics(aRenderingContext,
|
||||
childDesiredSize);
|
||||
} else {
|
||||
// XXX This includes margin while Reflow currently doesn't consider
|
||||
// margin, so we may end up with too much space, but, with stretchy
|
||||
// characters, this is an approximation anyway.
|
||||
nscoord width =
|
||||
nsLayoutUtils::IntrinsicForContainer(aRenderingContext, childFrame,
|
||||
nsLayoutUtils::PREF_WIDTH);
|
||||
|
||||
childDesiredSize.width = width;
|
||||
childDesiredSize.mBoundingMetrics.width = width;
|
||||
childDesiredSize.mBoundingMetrics.leftBearing = 0;
|
||||
childDesiredSize.mBoundingMetrics.rightBearing = width;
|
||||
|
||||
nscoord x, xMost;
|
||||
if (NS_SUCCEEDED(childFrame->GetPrefWidthTightBounds(aRenderingContext,
|
||||
&x, &xMost))) {
|
||||
childDesiredSize.mBoundingMetrics.leftBearing = x;
|
||||
childDesiredSize.mBoundingMetrics.rightBearing = xMost;
|
||||
}
|
||||
}
|
||||
|
||||
SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
|
||||
childDesiredSize.mBoundingMetrics);
|
||||
|
@ -1025,15 +1047,12 @@ nsMathMLContainerFrame::GetIntrinsicWidth(nsRenderingContext* aRenderingContext)
|
|||
}
|
||||
|
||||
// Measure
|
||||
nsHTMLReflowMetrics desiredSize;
|
||||
nsresult rv = MeasureForWidth(*aRenderingContext, desiredSize);
|
||||
nsresult rv = MeasureForWidth(*aRenderingContext, aDesiredSize);
|
||||
if (NS_FAILED(rv)) {
|
||||
ReflowError(*aRenderingContext, desiredSize);
|
||||
ReflowError(*aRenderingContext, aDesiredSize);
|
||||
}
|
||||
|
||||
ClearSavedChildMetrics();
|
||||
|
||||
return desiredSize.width;
|
||||
}
|
||||
|
||||
/* virtual */ nsresult
|
||||
|
|
|
@ -33,6 +33,7 @@ class nsMathMLContainerFrame : public nsContainerFrame,
|
|||
public:
|
||||
nsMathMLContainerFrame(nsStyleContext* aContext) : nsContainerFrame(aContext) {}
|
||||
|
||||
NS_DECL_QUERYFRAME_TARGET(nsMathMLContainerFrame)
|
||||
NS_DECL_QUERYFRAME
|
||||
NS_DECL_FRAMEARENA_HELPERS
|
||||
|
||||
|
@ -92,16 +93,18 @@ public:
|
|||
nsIFrame* aOldFrame) MOZ_OVERRIDE;
|
||||
|
||||
/**
|
||||
* Both GetMinWidth and GetPrefWidth return whatever
|
||||
* GetIntrinsicWidth returns.
|
||||
* Both GetMinWidth and GetPrefWidth use the intrinsic width metrics
|
||||
* returned by GetIntrinsicMetrics, including ink overflow.
|
||||
*/
|
||||
virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE;
|
||||
virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE;
|
||||
|
||||
/**
|
||||
* Return the intrinsic width of the frame's content area.
|
||||
* Return the intrinsic horizontal metrics of the frame's content area.
|
||||
*/
|
||||
virtual nscoord GetIntrinsicWidth(nsRenderingContext *aRenderingContext);
|
||||
virtual void
|
||||
GetIntrinsicWidthMetrics(nsRenderingContext* aRenderingContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize);
|
||||
|
||||
NS_IMETHOD
|
||||
Reflow(nsPresContext* aPresContext,
|
||||
|
|
|
@ -564,8 +564,8 @@ GetMaxCharWidth(nsPresContext* aPresContext,
|
|||
return width;
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
nsMathMLmfencedFrame::GetIntrinsicWidth(nsRenderingContext* aRenderingContext)
|
||||
/* virtual */ void
|
||||
nsMathMLmfencedFrame::GetIntrinsicWidthMetrics(nsRenderingContext* aRenderingContext, nsHTMLReflowMetrics& aDesiredSize)
|
||||
{
|
||||
nscoord width = 0;
|
||||
|
||||
|
@ -607,7 +607,10 @@ nsMathMLmfencedFrame::GetIntrinsicWidth(nsRenderingContext* aRenderingContext)
|
|||
NS_MATHML_OPERATOR_FORM_POSTFIX, font->mScriptLevel, em);
|
||||
}
|
||||
|
||||
return width;
|
||||
aDesiredSize.width = width;
|
||||
aDesiredSize.mBoundingMetrics.width = width;
|
||||
aDesiredSize.mBoundingMetrics.leftBearing = 0;
|
||||
aDesiredSize.mBoundingMetrics.rightBearing = width;
|
||||
}
|
||||
|
||||
nscoord
|
||||
|
|
|
@ -42,8 +42,9 @@ public:
|
|||
const nsRect& aDirtyRect,
|
||||
const nsDisplayListSet& aLists) MOZ_OVERRIDE;
|
||||
|
||||
virtual nscoord
|
||||
GetIntrinsicWidth(nsRenderingContext* aRenderingContext) MOZ_OVERRIDE;
|
||||
virtual void
|
||||
GetIntrinsicWidthMetrics(nsRenderingContext* aRenderingContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize) MOZ_OVERRIDE;
|
||||
|
||||
NS_IMETHOD
|
||||
AttributeChanged(int32_t aNameSpaceID,
|
||||
|
|
|
@ -986,28 +986,36 @@ nsMathMLmoFrame::MarkIntrinsicWidthsDirty()
|
|||
nsMathMLContainerFrame::MarkIntrinsicWidthsDirty();
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
nsMathMLmoFrame::GetIntrinsicWidth(nsRenderingContext *aRenderingContext)
|
||||
/* virtual */ void
|
||||
nsMathMLmoFrame::GetIntrinsicWidthMetrics(nsRenderingContext *aRenderingContext, nsHTMLReflowMetrics& aDesiredSize)
|
||||
{
|
||||
ProcessOperatorData();
|
||||
nscoord width;
|
||||
if (UseMathMLChar()) {
|
||||
uint32_t stretchHint = GetStretchHint(mFlags, mPresentationData, true);
|
||||
width = mMathMLChar.
|
||||
aDesiredSize.width = mMathMLChar.
|
||||
GetMaxWidth(PresContext(), *aRenderingContext,
|
||||
stretchHint, mMaxSize,
|
||||
NS_MATHML_OPERATOR_MAXSIZE_IS_ABSOLUTE(mFlags));
|
||||
}
|
||||
else {
|
||||
width = nsMathMLTokenFrame::GetIntrinsicWidth(aRenderingContext);
|
||||
nsMathMLTokenFrame::GetIntrinsicWidthMetrics(aRenderingContext,
|
||||
aDesiredSize);
|
||||
}
|
||||
|
||||
// leadingSpace and trailingSpace are actually applied to the outermost
|
||||
// embellished container but for determining total intrinsic width it should
|
||||
// be safe to include it for the core here instead.
|
||||
width += mEmbellishData.leadingSpace + mEmbellishData.trailingSpace;
|
||||
|
||||
return width;
|
||||
bool isRTL = StyleVisibility()->mDirection;
|
||||
aDesiredSize.width +=
|
||||
mEmbellishData.leadingSpace + mEmbellishData.trailingSpace;
|
||||
aDesiredSize.mBoundingMetrics.width = aDesiredSize.width;
|
||||
if (isRTL) {
|
||||
aDesiredSize.mBoundingMetrics.leftBearing += mEmbellishData.trailingSpace;
|
||||
aDesiredSize.mBoundingMetrics.rightBearing += mEmbellishData.trailingSpace;
|
||||
} else {
|
||||
aDesiredSize.mBoundingMetrics.leftBearing += mEmbellishData.leadingSpace;
|
||||
aDesiredSize.mBoundingMetrics.rightBearing += mEmbellishData.leadingSpace;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -46,8 +46,9 @@ public:
|
|||
|
||||
virtual void MarkIntrinsicWidthsDirty() MOZ_OVERRIDE;
|
||||
|
||||
virtual nscoord
|
||||
GetIntrinsicWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE;
|
||||
virtual void
|
||||
GetIntrinsicWidthMetrics(nsRenderingContext* aRenderingContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize) MOZ_OVERRIDE;
|
||||
|
||||
NS_IMETHOD
|
||||
AttributeChanged(int32_t aNameSpaceID,
|
||||
|
|
|
@ -350,17 +350,16 @@ nsMathMLmrootFrame::Reflow(nsPresContext* aPresContext,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
nsMathMLmrootFrame::GetIntrinsicWidth(nsRenderingContext* aRenderingContext)
|
||||
/* virtual */ void
|
||||
nsMathMLmrootFrame::GetIntrinsicWidthMetrics(nsRenderingContext* aRenderingContext, nsHTMLReflowMetrics& aDesiredSize)
|
||||
{
|
||||
nsIFrame* baseFrame = mFrames.FirstChild();
|
||||
nsIFrame* indexFrame = nullptr;
|
||||
if (baseFrame)
|
||||
indexFrame = baseFrame->GetNextSibling();
|
||||
if (!indexFrame || indexFrame->GetNextSibling()) {
|
||||
nsHTMLReflowMetrics desiredSize;
|
||||
ReflowError(*aRenderingContext, desiredSize);
|
||||
return desiredSize.width;
|
||||
ReflowError(*aRenderingContext, aDesiredSize);
|
||||
return;
|
||||
}
|
||||
|
||||
nscoord baseWidth =
|
||||
|
@ -375,7 +374,12 @@ nsMathMLmrootFrame::GetIntrinsicWidth(nsRenderingContext* aRenderingContext)
|
|||
GetRadicalXOffsets(indexWidth, sqrWidth, aRenderingContext->FontMetrics(),
|
||||
nullptr, &dxSqr);
|
||||
|
||||
return dxSqr + sqrWidth + baseWidth;
|
||||
nscoord width = dxSqr + sqrWidth + baseWidth;
|
||||
|
||||
aDesiredSize.width = width;
|
||||
aDesiredSize.mBoundingMetrics.width = width;
|
||||
aDesiredSize.mBoundingMetrics.leftBearing = 0;
|
||||
aDesiredSize.mBoundingMetrics.rightBearing = width;
|
||||
}
|
||||
|
||||
// ----------------------
|
||||
|
|
|
@ -40,8 +40,9 @@ public:
|
|||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus) MOZ_OVERRIDE;
|
||||
|
||||
virtual nscoord
|
||||
GetIntrinsicWidth(nsRenderingContext* aRenderingContext) MOZ_OVERRIDE;
|
||||
virtual void
|
||||
GetIntrinsicWidthMetrics(nsRenderingContext* aRenderingContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize) MOZ_OVERRIDE;
|
||||
|
||||
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
const nsRect& aDirtyRect,
|
||||
|
|
|
@ -39,6 +39,7 @@ skip-if(B2G) == quotes-1.xhtml quotes-1-ref.xhtml
|
|||
!= stretchy-underbar-1.xhtml stretchy-underbar-1-ref.xhtml
|
||||
== table-width-1.xhtml table-width-1-ref.xhtml
|
||||
== table-width-2.html table-width-2-ref.html
|
||||
fails-if(OSX||/^Windows\x20NT\x206\.[12]/.test(http.oscpu)||Android) == table-width-3.html table-width-3-ref.html
|
||||
== underbar-width-1.xhtml underbar-width-1-ref.xhtml
|
||||
== mathml-type-supported.xhtml mathml-type-supported-ref.xml
|
||||
== mtable-align-negative-rownumber.html mtable-align-negative-rownumber-ref.html
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
<!doctype>
|
||||
<html>
|
||||
<head>
|
||||
<title>table-width-3</title>
|
||||
<meta charset="utf-8"/>
|
||||
<style type="text/css">
|
||||
html { background-color: grey; }
|
||||
td { border: 1px solid white;
|
||||
padding: 0;
|
||||
background-color: black;
|
||||
color: red; }
|
||||
mi, mtext { font-size: 3em; }
|
||||
span { font-style: italic; display: inline-block; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<math>
|
||||
<mphantom>
|
||||
<mi>f</mi>
|
||||
</mphantom>
|
||||
</math>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<math>
|
||||
<mphantom>
|
||||
<mi>f</mi>
|
||||
</mphantom>
|
||||
</math>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<math>
|
||||
<mphantom>
|
||||
<mi>f</mi>
|
||||
<mi>f</mi>
|
||||
<mi>f</mi>
|
||||
</mphantom>
|
||||
</math>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<math>
|
||||
<mphantom>
|
||||
<mi style="font-style: italic;">fff</mi>
|
||||
</mphantom>
|
||||
</math>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<math>
|
||||
<mphantom>
|
||||
<mtext><span>fff</span></mtext>
|
||||
</mphantom>
|
||||
</math>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<math>
|
||||
<mphantom>
|
||||
<mtext><span>f</span></mtext>
|
||||
<mtext><span>f</span></mtext>
|
||||
<mtext><span>f</span></mtext>
|
||||
</mphantom>
|
||||
</math>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<math>
|
||||
<mphantom>
|
||||
<mtext><span>f</span><span>f</span><span>f</span></mtext>
|
||||
</mphantom>
|
||||
</math>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,87 @@
|
|||
<!doctype>
|
||||
<html>
|
||||
<head>
|
||||
<title>table-width-3</title>
|
||||
<meta charset="utf-8"/>
|
||||
<style type="text/css">
|
||||
html { background-color: grey; }
|
||||
td { border: 1px solid white;
|
||||
padding: 0;
|
||||
background-color: black;
|
||||
color: black; }
|
||||
mi, mtext { font-size: 3em; }
|
||||
span { font-style: italic; display: inline-block; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<math>
|
||||
<mi>f</mi>
|
||||
</math>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<math>
|
||||
<mi> f </mi>
|
||||
</math>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<math>
|
||||
<mi>f</mi>
|
||||
<mi>f</mi>
|
||||
<mi>f</mi>
|
||||
</math>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<math>
|
||||
<mi style="font-style: italic;">fff</mi>
|
||||
</math>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<math>
|
||||
<mtext><span>fff</span></mtext>
|
||||
</math>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<math>
|
||||
<mtext><span>f</span></mtext>
|
||||
<mtext><span>f</span></mtext>
|
||||
<mtext><span>f</span></mtext>
|
||||
</math>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<math>
|
||||
<mtext><span>f</span><span>f</span><span>f</span></mtext>
|
||||
</math>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -343,3 +343,6 @@ skip-if(B2G) include box-sizing/reftest.list
|
|||
|
||||
# invalidation - only run on B2G
|
||||
skip-if(!B2G) include invalidation/reftest.list
|
||||
|
||||
# encodings
|
||||
include ../../dom/encoding/test/reftest/reftest.list
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче