Merge last PGO-green changeset of mozilla-inbound to mozilla-central

This commit is contained in:
Ed Morley 2012-11-07 12:52:55 +00:00
Родитель edaf3f8964 72e9c813de
Коммит b1b1282206
113 изменённых файлов: 2457 добавлений и 665 удалений

Просмотреть файл

@ -64,6 +64,33 @@ SettingsListener.observe('audio.volume.master', 0.5, function(value) {
audioManager.masterVolume = Math.max(0.0, Math.min(value, 1.0));
});
const nsIAudioManager = Ci.nsIAudioManager;
let audioSettings = [
// settings name, default value, stream type
['audio.volume.voice_call', 10, nsIAudioManager.STREAM_TYPE_VOICE_CALL],
['audio.volume.system', 10, nsIAudioManager.STREAM_TYPE_SYSTEM],
['audio.volume.ring', 7, nsIAudioManager.STREAM_TYPE_RING],
['audio.volume.music', 15, nsIAudioManager.STREAM_TYPE_MUSIC],
['audio.volume.alarm', 7, nsIAudioManager.STREAM_TYPE_ALARM],
['audio.volume.notification', 7, nsIAudioManager.STREAM_TYPE_NOTIFICATION],
['audio.volume.bt_sco', 15, nsIAudioManager.STREAM_TYPE_BLUETOOTH_SCO],
['audio.volume.enforced_audible', 7, nsIAudioManager.STREAM_TYPE_ENFORCED_AUDIBLE],
['audio.volume.dtmf', 15, nsIAudioManager.STREAM_TYPE_DTMF],
['audio.volume.tts', 15, nsIAudioManager.STREAM_TYPE_TTS],
['audio.volume.fm', 10, nsIAudioManager.STREAM_TYPE_FM],
];
for each (let [setting, defaultValue, streamType] in audioSettings) {
(function AudioStreamSettings(s, d, t) {
SettingsListener.observe(s, d, function(value) {
let audioManager = Services.audioManager;
if (!audioManager)
return;
audioManager.setStreamVolumeIndex(t, Math.min(value, d));
});
})(setting, defaultValue, streamType);
}
// =================== Languages ====================
SettingsListener.observe('language.current', 'en-US', function(value) {

Просмотреть файл

@ -271,6 +271,7 @@ _BROWSER_FILES = \
browser_tabDrop.js \
browser_lastAccessedTab.js \
browser_bug734076.js \
browser_social.js \
browser_social_toolbar.js \
browser_social_shareButton.js \
browser_social_sidebar.js \

Просмотреть файл

@ -0,0 +1,92 @@
/* 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/. */
// a place for miscellaneous social tests
const pb = Cc["@mozilla.org/privatebrowsing;1"].
getService(Ci.nsIPrivateBrowsingService);
function test() {
waitForExplicitFinish();
let manifest = { // normal provider
name: "provider 1",
origin: "https://example.com",
sidebarURL: "https://example.com/browser/browser/base/content/test/social_sidebar.html",
workerURL: "https://example.com/browser/browser/base/content/test/social_worker.js",
iconURL: "https://example.com/browser/browser/base/content/test/moz.png"
};
runSocialTestWithProvider(manifest, function (finishcb) {
runSocialTests(tests, undefined, undefined, finishcb);
});
}
var tests = {
testPrivateBrowsing: function(next) {
let port = Social.provider.getWorkerPort();
ok(port, "provider has a port");
port.postMessage({topic: "test-init"});
port.onmessage = function (e) {
let topic = e.data.topic;
switch (topic) {
case "got-sidebar-message":
ok(true, "got sidebar message");
port.close();
togglePrivateBrowsing(function () {
ok(!Social.enabled, "Social shuts down during private browsing");
togglePrivateBrowsing(function () {
ok(Social.enabled, "Social enabled after private browsing");
next();
});
});
break;
}
};
},
testPrivateBrowsingSocialDisabled: function(next) {
// test PB from the perspective of entering PB without social enabled
// we expect social to be enabled at the start of the test, we need
// to disable it before testing PB transitions.
let port = Social.provider.getWorkerPort();
ok(port, "provider has a port");
port.postMessage({topic: "test-init"});
port.onmessage = function (e) {
let topic = e.data.topic;
switch (topic) {
case "got-sidebar-message":
ok(true, "got sidebar message");
port.close();
Social.enabled = false;
break;
}
}
// wait for disable, then do some pb toggling. We expect social to remain
// disabled through these tests
Services.obs.addObserver(function observer(aSubject, aTopic) {
Services.obs.removeObserver(observer, aTopic);
ok(!Social.enabled, "Social is not enabled");
togglePrivateBrowsing(function () {
ok(!Social.enabled, "Social not available during private browsing");
togglePrivateBrowsing(function () {
ok(!Social.enabled, "Social is not enabled after private browsing");
// social will be reenabled on start of next social test
next();
});
});
}, "social:pref-changed", false);
}
}
function togglePrivateBrowsing(aCallback) {
Services.obs.addObserver(function observe(subject, topic, data) {
Services.obs.removeObserver(observe, topic);
executeSoon(aCallback);
}, "private-browsing-transition-complete", false);
pb.privateBrowsingEnabled = !pb.privateBrowsingEnabled;
}

Просмотреть файл

@ -28,6 +28,11 @@ this.Social = {
return;
}
if (!this._addedPrivateBrowsingObserver) {
Services.obs.addObserver(this, "private-browsing", false);
this._addedPrivateBrowsingObserver = true;
}
// Eventually this might want to retrieve a specific provider, but for now
// just use the first available.
SocialService.getProviderList(function (providers) {
@ -37,6 +42,17 @@ this.Social = {
}.bind(this));
},
observe: function(aSubject, aTopic, aData) {
if (aTopic == "private-browsing") {
if (aData == "enter") {
this._enabledBeforePrivateBrowsing = this.enabled;
this.enabled = false;
} else if (aData == "exit") {
this.enabled = this._enabledBeforePrivateBrowsing;
}
}
},
get uiVisible() {
return this.provider && this.provider.enabled;
},

Просмотреть файл

@ -3648,6 +3648,41 @@ CanvasRenderingContext2D::IsPointInPath(float x, float y, bool *retVal)
return NS_OK;
}
bool
CanvasRenderingContext2D::MozIsPointInStroke(double x, double y)
{
if (!FloatValidate(x,y)) {
return false;
}
EnsureUserSpacePath(false);
if (!mPath) {
return false;
}
const ContextState &state = CurrentState();
StrokeOptions strokeOptions(state.lineWidth,
state.lineJoin,
state.lineCap,
state.miterLimit,
state.dash.Length(),
state.dash.Elements(),
state.dashOffset);
if (mPathTransformWillUpdate) {
return mPath->StrokeContainsPoint(strokeOptions, Point(x, y), mPathToDS);
}
return mPath->StrokeContainsPoint(strokeOptions, Point(x, y), mTarget->GetTransform());
}
NS_IMETHODIMP
CanvasRenderingContext2D::MozIsPointInStroke(float x, float y, bool *retVal)
{
*retVal = MozIsPointInStroke(x, y);
return NS_OK;
}
//
// image
//

Просмотреть файл

@ -246,6 +246,7 @@ public:
void Stroke();
void Clip();
bool IsPointInPath(double x, double y);
bool MozIsPointInStroke(double x, double y);
void FillText(const nsAString& text, double x, double y,
const mozilla::dom::Optional<double>& maxWidth,
mozilla::ErrorResult& error);

Просмотреть файл

@ -55,6 +55,7 @@ MOCHITEST_FILES = \
test_toDataURL_lowercase_ascii.html \
test_toDataURL_parameters.html \
test_mozGetAsFile.html \
test_mozIsPointInStroke.html \
test_canvas_strokeStyle_getter.html \
test_bug613794.html \
test_bug753758.html \

Просмотреть файл

@ -0,0 +1,244 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Canvas test: mozIsPointInStroke</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
<script type="application/javascript">
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
ctx.lineWidth = 5;
ok(ctx.mozIsPointInStroke(50, 25) === false, 'ctx.mozIsPointInStroke(50, 25) === false');
ctx.beginPath();
ctx.rect(0, 0, 20, 20);
ok(ctx.mozIsPointInStroke(-4, -4) === false, 'ctx.mozIsPointInStroke(-4, -4) === false');
ok(ctx.mozIsPointInStroke(4, 4) === false, 'ctx.mozIsPointInStroke(4, 4) === false');
ok(ctx.mozIsPointInStroke(16, 16) === false, 'ctx.mozIsPointInStroke(16, 16) === false');
ok(ctx.mozIsPointInStroke(24, 24) === false, 'ctx.mozIsPointInStroke(24, 24) === false');
ok(ctx.mozIsPointInStroke(-2, -2) === true, 'ctx.mozIsPointInStroke(-2, -2) === true');
ok(ctx.mozIsPointInStroke(2, 2) === true, 'ctx.mozIsPointInStroke(2, 2) === true');
ok(ctx.mozIsPointInStroke(18, 18) === true, 'ctx.mozIsPointInStroke(18, 18) === true');
ok(ctx.mozIsPointInStroke(22, 22) === true, 'ctx.mozIsPointInStroke(22, 22) === true');
ctx.beginPath();
ctx.rect(25, 25, 20, 20);
ok(ctx.mozIsPointInStroke(21, 21) === false, 'ctx.mozIsPointInStroke(21, 21) === false');
ok(ctx.mozIsPointInStroke(29, 29) === false, 'ctx.mozIsPointInStroke(29, 29) === false');
ok(ctx.mozIsPointInStroke(42, 42) === false, 'ctx.mozIsPointInStroke(42, 42) === false');
ok(ctx.mozIsPointInStroke(50, 50) === false, 'ctx.mozIsPointInStroke(50, 50) === false');
ok(ctx.mozIsPointInStroke(23, 23) === true, 'ctx.mozIsPointInStroke(23, 23) === true');
ok(ctx.mozIsPointInStroke(27, 27) === true, 'ctx.mozIsPointInStroke(27, 27) === true');
ok(ctx.mozIsPointInStroke(43, 43) === true, 'ctx.mozIsPointInStroke(43, 43) === true');
ok(ctx.mozIsPointInStroke(47, 47) === true, 'ctx.mozIsPointInStroke(47, 47) === true');
ctx.beginPath();
ctx.moveTo(25, 25);
ctx.bezierCurveTo(50, -50, 50, 100, 75, 25);
ok(ctx.mozIsPointInStroke(23, 26) === false, 'ctx.mozIsPointInStroke(23, 26) === false');
ok(ctx.mozIsPointInStroke(75, 23) === false, 'ctx.mozIsPointInStroke(75, 23) === false');
ok(ctx.mozIsPointInStroke(37, 8) === false, 'ctx.mozIsPointInStroke(37, 8) === false');
ok(ctx.mozIsPointInStroke(61, 42) === false, 'ctx.mozIsPointInStroke(61, 42) === false');
ok(ctx.mozIsPointInStroke(24, 24) === true, 'ctx.mozIsPointInStroke(24, 24) === true');
ok(ctx.mozIsPointInStroke(74, 25) === true, 'ctx.mozIsPointInStroke(74, 25) === true');
ok(ctx.mozIsPointInStroke(37, 2) === true, 'ctx.mozIsPointInStroke(37, 2) === true');
ok(ctx.mozIsPointInStroke(61, 47) === true, 'ctx.mozIsPointInStroke(61, 47) === true');
ctx.beginPath();
ctx.arc(50, 25, 10, 0, Math.PI, false);
ok(ctx.mozIsPointInStroke(39, 23) === false, 'ctx.mozIsPointInStroke(39, 23) === false');
ok(ctx.mozIsPointInStroke(50, 15) === false, 'ctx.mozIsPointInStroke(50, 15) === false');
ok(ctx.mozIsPointInStroke(60, 23) === false, 'ctx.mozIsPointInStroke(60, 23) === false');
ok(ctx.mozIsPointInStroke(50, 25) === false, 'ctx.mozIsPointInStroke(50, 25) === false');
ok(ctx.mozIsPointInStroke(39, 26) === true, 'ctx.mozIsPointInStroke(39, 26) === true');
ok(ctx.mozIsPointInStroke(45, 33) === true, 'ctx.mozIsPointInStroke(45, 33) === true');
ok(ctx.mozIsPointInStroke(53, 33) === true, 'ctx.mozIsPointInStroke(53, 33) === true');
ok(ctx.mozIsPointInStroke(59, 26) === true, 'ctx.mozIsPointInStroke(59, 26) === true');
ctx.beginPath();
ctx.arc(50, 25, 10, 0, 2 * Math.PI, false);
ok(ctx.mozIsPointInStroke(34, 25) === false, 'ctx.mozIsPointInStroke(34, 25) === false');
ok(ctx.mozIsPointInStroke(44, 25) === false, 'ctx.mozIsPointInStroke(44, 25) === false');
ok(ctx.mozIsPointInStroke(49, 30) === false, 'ctx.mozIsPointInStroke(49, 30) === false');
ok(ctx.mozIsPointInStroke(49, 40) === false, 'ctx.mozIsPointInStroke(49, 40) === false');
ok(ctx.mozIsPointInStroke(39, 23) === true, 'ctx.mozIsPointInStroke(39, 23) === true');
ok(ctx.mozIsPointInStroke(50, 15) === true, 'ctx.mozIsPointInStroke(50, 15) === true');
ok(ctx.mozIsPointInStroke(60, 23) === true, 'ctx.mozIsPointInStroke(60, 23) === true');
ok(ctx.mozIsPointInStroke(49, 34) === true, 'ctx.mozIsPointInStroke(49, 34) === true');
ctx.beginPath();
ctx.save();
ctx.translate(20, 20);
ctx.rect(0, 0, 20, 20);
ok(ctx.mozIsPointInStroke(16, 16) === false, 'ctx.mozIsPointInStroke(16, 16) === false');
ok(ctx.mozIsPointInStroke(24, 24) === false, 'ctx.mozIsPointInStroke(24, 24) === false');
ok(ctx.mozIsPointInStroke(36, 36) === false, 'ctx.mozIsPointInStroke(36, 36) === false');
ok(ctx.mozIsPointInStroke(44, 44) === false, 'ctx.mozIsPointInStroke(44, 44) === false');
ok(ctx.mozIsPointInStroke(18, 18) === true, 'ctx.mozIsPointInStroke(18, 18) === true');
ok(ctx.mozIsPointInStroke(22, 22) === true, 'ctx.mozIsPointInStroke(22, 22) === true');
ok(ctx.mozIsPointInStroke(38, 38) === true, 'ctx.mozIsPointInStroke(38, 38) === true');
ok(ctx.mozIsPointInStroke(42, 42) === true, 'ctx.mozIsPointInStroke(42, 42) === true');
ctx.restore();
ctx.beginPath();
ctx.save();
ctx.scale(-1, 1);
ctx.rect(-30, 20, 20, 20);
ok(ctx.mozIsPointInStroke(16, 16) === false, 'ctx.mozIsPointInStroke(16, 16) === false');
ok(ctx.mozIsPointInStroke(14, 24) === false, 'ctx.mozIsPointInStroke(14, 24) === false');
ok(ctx.mozIsPointInStroke(26, 36) === false, 'ctx.mozIsPointInStroke(26, 36) === false');
ok(ctx.mozIsPointInStroke(34, 44) === false, 'ctx.mozIsPointInStroke(34, 44) === false');
ok(ctx.mozIsPointInStroke(8, 18) === true, 'ctx.mozIsPointInStroke(8, 18) === true');
ok(ctx.mozIsPointInStroke(12, 22) === true, 'ctx.mozIsPointInStroke(12, 22) === true');
ok(ctx.mozIsPointInStroke(28, 38) === true, 'ctx.mozIsPointInStroke(28, 38) === true');
ok(ctx.mozIsPointInStroke(32, 42) === true, 'ctx.mozIsPointInStroke(32, 42) === true');
ctx.restore();
ctx.beginPath();
ctx.save();
ctx.lineWidth = 2;
ctx.translate(50, 25);
ctx.rotate(180 * Math.PI / 180);
ctx.scale(5, 5);
ctx.arc(0, 0, 2, 0, Math.PI, false);
ok(ctx.mozIsPointInStroke(39, 26) === false, 'ctx.mozIsPointInStroke(39, 26) === false');
ok(ctx.mozIsPointInStroke(45, 33) === false, 'ctx.mozIsPointInStroke(45, 33) === false');
ok(ctx.mozIsPointInStroke(53, 33) === false, 'ctx.mozIsPointInStroke(53, 33) === false');
ok(ctx.mozIsPointInStroke(59, 26) === false, 'ctx.mozIsPointInStroke(59, 26) === false');
ok(ctx.mozIsPointInStroke(39, 23) === true, 'ctx.mozIsPointInStroke(39, 23) === true');
ok(ctx.mozIsPointInStroke(45, 15) === true, 'ctx.mozIsPointInStroke(50, 15) === true');
ok(ctx.mozIsPointInStroke(55, 15) === true, 'ctx.mozIsPointInStroke(50, 25) === true');
ok(ctx.mozIsPointInStroke(60, 23) === true, 'ctx.mozIsPointInStroke(60, 23) === true');
ctx.restore();
ctx.beginPath();
ctx.moveTo(10, 10);
ctx.lineTo(30, 10);
ctx.save();
ctx.lineWidth = 2;
ctx.scale(5, 5);
ctx.lineTo(6, 6);
ctx.lineTo(2, 6);
ctx.restore();
ctx.closePath();
ok(ctx.mozIsPointInStroke(6, 6) === false, 'ctx.mozIsPointInStroke(6, 6) === false');
ok(ctx.mozIsPointInStroke(14, 14) === false, 'ctx.mozIsPointInStroke(14, 14) === false');
ok(ctx.mozIsPointInStroke(26, 26) === false, 'ctx.mozIsPointInStroke(26, 26) === false');
ok(ctx.mozIsPointInStroke(34, 34) === false, 'ctx.mozIsPointInStroke(34, 34) === false');
ok(ctx.mozIsPointInStroke(8, 8) === true, 'ctx.mozIsPointInStroke(8, 8) === true');
ok(ctx.mozIsPointInStroke(12, 12) === true, 'ctx.mozIsPointInStroke(12, 12) === true');
ok(ctx.mozIsPointInStroke(28, 28) === true, 'ctx.mozIsPointInStroke(28, 28) === true');
ok(ctx.mozIsPointInStroke(32, 32) === true, 'ctx.mozIsPointInStroke(32, 32) === true');
ctx.beginPath();
ctx.rect(-30, -30, 20, 20);
ok(ctx.mozIsPointInStroke(-34, -34) === false, 'ctx.mozIsPointInStroke(-34, -34) === false');
ok(ctx.mozIsPointInStroke(-26, -26) === false, 'ctx.mozIsPointInStroke(-26, -26) === false');
ok(ctx.mozIsPointInStroke(-14, -14) === false, 'ctx.mozIsPointInStroke(-14, -14) === false');
ok(ctx.mozIsPointInStroke(-6, -6) === false, 'ctx.mozIsPointInStroke(-6, -6) === false');
ok(ctx.mozIsPointInStroke(-32, -32) === true, 'ctx.mozIsPointInStroke(-32, -32) === true');
ok(ctx.mozIsPointInStroke(-28, -28) === true, 'ctx.mozIsPointInStroke(-28, -28) === true');
ok(ctx.mozIsPointInStroke(-12, -12) === true, 'ctx.mozIsPointInStroke(-12, -12) === true');
ok(ctx.mozIsPointInStroke(-8, -8) === true, 'ctx.mozIsPointInStroke(-8, -8) === true');
ctx.beginPath();
ctx.moveTo(20, 25);
ctx.lineTo(80, 25);
ok(ctx.mozIsPointInStroke(19, 25) === false, 'ctx.mozIsPointInStroke(19, 25) === false');
ok(ctx.mozIsPointInStroke(50, 21) === false, 'ctx.mozIsPointInStroke(50, 21) === false');
ok(ctx.mozIsPointInStroke(81, 25) === false, 'ctx.mozIsPointInStroke(81, 25) === false');
ok(ctx.mozIsPointInStroke(50, 29) === false, 'ctx.mozIsPointInStroke(50, 29) === false');
ok(ctx.mozIsPointInStroke(21, 25) === true, 'ctx.mozIsPointInStroke(21, 25) === true');
ok(ctx.mozIsPointInStroke(50, 23) === true, 'ctx.mozIsPointInStroke(50, 23) === true');
ok(ctx.mozIsPointInStroke(79, 25) === true, 'ctx.mozIsPointInStroke(79, 25) === true');
ok(ctx.mozIsPointInStroke(50, 27) === true, 'ctx.mozIsPointInStroke(50, 27) === true');
ctx.lineWidth = 15;
ctx.lineCap = 'round';
ctx.beginPath();
ctx.moveTo(20, 25);
ctx.lineTo(80, 25);
ok(ctx.mozIsPointInStroke(13, 18) === false, 'ctx.mozIsPointInStroke(13, 18) === false');
ok(ctx.mozIsPointInStroke(13, 31) === false, 'ctx.mozIsPointInStroke(13, 31) === false');
ok(ctx.mozIsPointInStroke(86, 18) === false, 'ctx.mozIsPointInStroke(86, 18) === false');
ok(ctx.mozIsPointInStroke(86, 31) === false, 'ctx.mozIsPointInStroke(86, 31) === false');
ok(ctx.mozIsPointInStroke(13, 25) === true, 'ctx.mozIsPointInStroke(13, 25) === true');
ok(ctx.mozIsPointInStroke(50, 18) === true, 'ctx.mozIsPointInStroke(50, 18) === true');
ok(ctx.mozIsPointInStroke(86, 25) === true, 'ctx.mozIsPointInStroke(86, 25) === true');
ok(ctx.mozIsPointInStroke(50, 31) === true, 'ctx.mozIsPointInStroke(50, 31) === true');
ctx.lineJoin = 'round';
ctx.beginPath();
ctx.moveTo(20, 15);
ctx.lineTo(80, 15);
ctx.lineTo(80, 35);
ok(ctx.mozIsPointInStroke(86, 8) === false, 'ctx.mozIsPointInStroke(86, 8) === false');
ok(ctx.mozIsPointInStroke(70, 24) === false, 'ctx.mozIsPointInStroke(70, 24) === false');
ok(ctx.mozIsPointInStroke(73, 41) === false, 'ctx.mozIsPointInStroke(73, 41) === false');
ok(ctx.mozIsPointInStroke(86, 41) === false, 'ctx.mozIsPointInStroke(86, 41) === false');
ok(ctx.mozIsPointInStroke(14, 15) === true, 'ctx.mozIsPointInStroke(14, 15) === true');
ok(ctx.mozIsPointInStroke(81, 15) === true, 'ctx.mozIsPointInStroke(81, 15) === true');
ok(ctx.mozIsPointInStroke(79, 41) === true, 'ctx.mozIsPointInStroke(79, 41) === true');
ok(ctx.mozIsPointInStroke(73, 21) === true, 'ctx.mozIsPointInStroke(73, 21) === true');
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -1755,8 +1755,6 @@ nsFocusManager::Focus(nsPIDOMWindow* aWindow,
// if switching to a new document, first fire the focus event on the
// document and then the window.
if (aIsNewDocument) {
nsIMEStateManager::OnChangeFocus(presShell->GetPresContext(), nullptr,
GetFocusMoveActionCause(aFlags));
nsIDocument* doc = aWindow->GetExtantDoc();
if (doc)
SendFocusOrBlurEvent(NS_FOCUS_CONTENT, presShell, doc,

Просмотреть файл

@ -4,6 +4,7 @@
* 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 <algorithm>
#include <stdarg.h>
#include "BindingUtils.h"
@ -44,6 +45,58 @@ ThrowErrorMessage(JSContext* aCx, const ErrNum aErrorNumber, ...)
return false;
}
} // namespace dom
struct ErrorResult::Message {
nsTArray<nsString> mArgs;
dom::ErrNum mErrorNumber;
};
void
ErrorResult::ThrowTypeError(const dom::ErrNum errorNumber, ...)
{
va_list ap;
va_start(ap, errorNumber);
if (IsTypeError()) {
delete mMessage;
}
mResult = NS_ERROR_TYPE_ERR;
Message* message = new Message();
message->mErrorNumber = errorNumber;
uint16_t argCount =
dom::GetErrorMessage(nullptr, nullptr, errorNumber)->argCount;
MOZ_ASSERT(argCount <= 10);
argCount = std::min<uint16_t>(argCount, 10);
while (argCount--) {
message->mArgs.AppendElement(*va_arg(ap, nsString*));
}
mMessage = message;
va_end(ap);
}
void
ErrorResult::ReportTypeError(JSContext* aCx)
{
MOZ_ASSERT(mMessage, "ReportTypeError() can be called only once");
Message* message = mMessage;
const uint32_t argCount = message->mArgs.Length();
const jschar* args[11];
for (uint32_t i = 0; i < argCount; ++i) {
args[i] = message->mArgs.ElementAt(i).get();
}
args[argCount] = nullptr;
JS_ReportErrorNumberUCArray(aCx, dom::GetErrorMessage, nullptr,
static_cast<const unsigned>(message->mErrorNumber),
argCount > 0 ? args : nullptr);
delete message;
mMessage = nullptr;
}
namespace dom {
bool
DefineConstants(JSContext* cx, JSObject* obj, ConstantSpec* cs)
{

Просмотреть файл

@ -31,14 +31,6 @@ class nsGlobalWindow;
namespace mozilla {
namespace dom {
enum ErrNum {
#define MSG_DEF(_name, _argc, _str) \
_name,
#include "mozilla/dom/Errors.msg"
#undef MSG_DEF
Err_Limit
};
bool
ThrowErrorMessage(JSContext* aCx, const ErrNum aErrorNumber, ...);
@ -61,10 +53,14 @@ Throw(JSContext* cx, nsresult rv)
template<bool mainThread>
inline bool
ThrowMethodFailedWithDetails(JSContext* cx, const ErrorResult& rv,
ThrowMethodFailedWithDetails(JSContext* cx, ErrorResult& rv,
const char* /* ifaceName */,
const char* /* memberName */)
{
if (rv.IsTypeError()) {
rv.ReportTypeError(cx);
return false;
}
return Throw<mainThread>(cx, rv.ErrorCode());
}

Просмотреть файл

@ -353,14 +353,9 @@ DOMInterfaces = {
},
'TextEncoder': {
'headerFile': 'mozilla/dom/TextEncoder.h',
'implicitJSContext': [ 'encode' ],
},
'TextDecoder': {
'headerFile': 'mozilla/dom/TextDecoder.h',
},
'WebGLActiveInfo': {
'nativeType': 'mozilla::WebGLActiveInfo',
'headerFile': 'WebGLContext.h',

Просмотреть файл

@ -11,22 +11,48 @@
#ifndef mozilla_ErrorResult_h
#define mozilla_ErrorResult_h
#include <stdarg.h>
#include "jsapi.h"
#include "nscore.h"
#include "mozilla/Assertions.h"
namespace mozilla {
namespace dom {
enum ErrNum {
#define MSG_DEF(_name, _argc, _str) \
_name,
#include "mozilla/dom/Errors.msg"
#undef MSG_DEF
Err_Limit
};
} // namespace dom
class ErrorResult {
public:
ErrorResult() {
mResult = NS_OK;
}
#ifdef DEBUG
~ErrorResult() {
MOZ_ASSERT_IF(IsTypeError(), !mMessage);
}
#endif
void Throw(nsresult rv) {
MOZ_ASSERT(NS_FAILED(rv), "Please don't try throwing success");
MOZ_ASSERT(rv != NS_ERROR_TYPE_ERR, "Use ThrowTypeError()");
MOZ_ASSERT(!IsTypeError(), "Don't overwite TypeError");
mResult = rv;
}
void ThrowTypeError(const dom::ErrNum errorNumber, ...);
void ReportTypeError(JSContext* cx);
bool IsTypeError() const { return ErrorCode() == NS_ERROR_TYPE_ERR; }
// In the future, we can add overloads of Throw that take more
// interesting things, like strings or DOM exception types or
// something if desired.
@ -35,6 +61,8 @@ public:
// Throw() here because people can easily pass success codes to
// this.
void operator=(nsresult rv) {
MOZ_ASSERT(rv != NS_ERROR_TYPE_ERR, "Use ThrowTypeError()");
MOZ_ASSERT(!IsTypeError(), "Don't overwite TypeError");
mResult = rv;
}
@ -48,6 +76,9 @@ public:
private:
nsresult mResult;
struct Message;
// Do not use nsAutoPtr to avoid extra initalizatoin and check.
Message* mMessage;
// Not to be implemented, to make sure people always pass this by
// reference, not by value.

Просмотреть файл

@ -32,3 +32,5 @@ MSG_DEF(MSG_ENFORCE_RANGE_OUT_OF_RANGE, 1, "Value is out of range for {0}.")
MSG_DEF(MSG_NOT_SEQUENCE, 0, "object can not be converted to a sequence")
MSG_DEF(MSG_INVALID_ARG, 2, "argument {0} is not valid for any of the {1}-argument overloads")
MSG_DEF(MSG_GLOBAL_NOT_NATIVE, 0, "global is not a native object")
MSG_DEF(MSG_ENCODING_NOT_SUPPORTED, 1, "The given encoding '{0}' is not supported.")
MSG_DEF(MSG_DOM_ENCODING_NOT_UTF, 0, "The encoding must be utf-8, utf-16, or utf-16be.")

Просмотреть файл

@ -191,7 +191,6 @@ nsGonkCameraControl::nsGonkCameraControl(uint32_t aCameraId, nsIThread* aCameraT
, mDiscardedFrameCount(0)
, mMediaProfiles(nullptr)
, mRecorder(nullptr)
, mVideoRotation(0)
, mVideoFile()
, mProfileManager(nullptr)
, mRecorderProfile(nullptr)
@ -1172,7 +1171,7 @@ nsGonkCameraControl::HandleRecorderEvent(int msg, int ext1, int ext2)
}
nsresult
nsGonkCameraControl::SetupRecording(int aFd, int64_t aMaxFileSizeBytes, int64_t aMaxVideoLengthMs)
nsGonkCameraControl::SetupRecording(int aFd, int aRotation, int64_t aMaxFileSizeBytes, int64_t aMaxVideoLengthMs)
{
// choosing a size big enough to hold the params
const size_t SIZE = 256;
@ -1200,7 +1199,15 @@ nsGonkCameraControl::SetupRecording(int aFd, int64_t aMaxFileSizeBytes, int64_t
snprintf(buffer, SIZE, "max-filesize=%lld", aMaxFileSizeBytes);
CHECK_SETARG(mRecorder->setParameters(String8(buffer)));
snprintf(buffer, SIZE, "video-param-rotation-angle-degrees=%d", mVideoRotation);
// adjust rotation by camera sensor offset
int r = aRotation;
r += GonkCameraHardware::GetSensorOrientation(mHwHandle, GonkCameraHardware::RAW_SENSOR_ORIENTATION);
r %= 360;
r += 45;
r /= 90;
r *= 90;
DOM_CAMERA_LOGI("setting video rotation to %d degrees (mapped from %d)\n", r, aRotation);
snprintf(buffer, SIZE, "video-param-rotation-angle-degrees=%d", r);
CHECK_SETARG(mRecorder->setParameters(String8(buffer)));
CHECK_SETARG(mRecorder->setListener(new GonkRecorderListener(this)));
@ -1218,7 +1225,6 @@ nsGonkCameraControl::GetPreviewStreamVideoModeImpl(GetPreviewStreamVideoModeTask
StopPreviewInternal(true /* forced */);
// setup the video mode
mVideoRotation = aGetPreviewStreamVideoMode->mOptions.rotation;
nsresult rv = SetupVideoMode(aGetPreviewStreamVideoMode->mOptions.profile);
NS_ENSURE_SUCCESS(rv, rv);
@ -1226,7 +1232,7 @@ nsGonkCameraControl::GetPreviewStreamVideoModeImpl(GetPreviewStreamVideoModeTask
int width = video->GetWidth();
int height = video->GetHeight();
int fps = video->GetFramerate();
DOM_CAMERA_LOGI("recording preview format: %d x %d (rotated %d degrees)\n", width, height, fps);
DOM_CAMERA_LOGI("recording preview format: %d x %d (%d fps)\n", width, height, fps);
// create and return new preview stream object
nsCOMPtr<GetPreviewStreamResult> getPreviewStreamResult = new GetPreviewStreamResult(this, width, height, fps, aGetPreviewStreamVideoMode->mOnSuccessCb, mWindowId);

Просмотреть файл

@ -56,7 +56,7 @@ public:
nsresult GetVideoSizes(nsTArray<CameraSize>& aVideoSizes);
nsresult PushParameters();
nsresult SetupRecording(int aFd, int64_t aMaxFileSizeBytes = -1, int64_t aMaxVideoLengthMs = -1);
nsresult SetupRecording(int aFd, int aRotation = 0, int64_t aMaxFileSizeBytes = -1, int64_t aMaxVideoLengthMs = -1);
nsresult SetupVideoMode(const nsAString& aProfile);
void AutoFocusComplete(bool aSuccess);
@ -107,7 +107,6 @@ protected:
android::MediaProfiles* mMediaProfiles;
android::GonkRecorder* mRecorder;
uint32_t mVideoRotation;
nsString mVideoFile;
// camcorder profile settings for the desired quality level

Просмотреть файл

@ -193,18 +193,21 @@ GonkCameraHardware::Init()
if (rv != 0) {
return;
}
mSensorOrientation = info.orientation;
mRawSensorOrientation = info.orientation;
mSensorOrientation = mRawSensorOrientation;
// Some kernels report the wrong sensor orientation through
// get_camera_info()...
char propname[PROP_NAME_MAX];
char prop[PROP_VALUE_MAX];
int offset = 0;
snprintf(propname, sizeof(propname), "ro.moz.cam.%d.sensor_offset", mCamera);
if (__system_property_get(propname, prop) > 0) {
int offset = clamped(atoi(prop), 0, 270);
offset = clamped(atoi(prop), 0, 270);
mSensorOrientation += offset;
mSensorOrientation %= 360;
}
DOM_CAMERA_LOGI("Sensor orientation: base=%d, offset=%d, final=%d\n", info.orientation, offset, mSensorOrientation);
if (sHwHandle == 0) {
sHwHandle = 1; // don't use 0
@ -271,14 +274,24 @@ GonkCameraHardware::GetHandle(GonkCamera* aTarget, uint32_t aCamera)
}
int
GonkCameraHardware::GetSensorOrientation(uint32_t aHwHandle)
GonkCameraHardware::GetSensorOrientation(uint32_t aHwHandle, uint32_t aType)
{
DOM_CAMERA_LOGI("%s: aHwHandle = %d\n", __func__, aHwHandle);
GonkCameraHardware* hw = GetHardware(aHwHandle);
if (!hw) {
return 0;
}
return hw->mSensorOrientation;
switch (aType) {
case OFFSET_SENSOR_ORIENTATION:
return hw->mSensorOrientation;
case RAW_SENSOR_ORIENTATION:
return hw->mRawSensorOrientation;
default:
DOM_CAMERA_LOGE("%s:%d : unknown aType=%d\n", __func__, __LINE__, aType);
return 0;
}
}
int

Просмотреть файл

@ -65,8 +65,16 @@ public:
* right edge of the screen in natural orientation, the value should be
* 90. If the top side of a front-facing camera sensor is aligned with the
* right of the screen, the value should be 270.
*
* RAW_SENSOR_ORIENTATION is the uncorrected orientation returned directly
* by get_camera_info(); OFFSET_SENSOR_ORIENTATION is the offset adjusted
* orientation.
*/
static int GetSensorOrientation(uint32_t aHwHandle);
enum {
RAW_SENSOR_ORIENTATION,
OFFSET_SENSOR_ORIENTATION
};
static int GetSensorOrientation(uint32_t aHwHandle, uint32_t aType = OFFSET_SENSOR_ORIENTATION);
static int AutoFocus(uint32_t aHwHandle);
static void CancelAutoFocus(uint32_t aHwHandle);
@ -116,6 +124,7 @@ protected:
#endif
sp<GonkCameraListener> mListener;
bool mInitialized;
int mRawSensorOrientation;
int mSensorOrientation;
bool IsInitialized()

Просмотреть файл

@ -21,21 +21,10 @@ TextDecoder::Init(const nsAString& aEncoding,
nsAutoString label(aEncoding);
EncodingUtils::TrimSpaceCharacters(label);
// If label is a case-insensitive match for "utf-16"
// then set the internal useBOM flag.
if (label.LowerCaseEqualsLiteral("utf-16")) {
mUseBOM = true;
mIsUTF16Family = true;
mEncoding = "utf-16le";
// If BOM is used, we can't determine the converter yet.
return;
}
// Run the steps to get an encoding from Encoding.
// Let encoding be the result of getting an encoding from label.
// If encoding is failure, throw a TypeError.
if (!EncodingUtils::FindEncodingForLabel(label, mEncoding)) {
// If the steps result in failure,
// throw a "EncodingError" exception and terminate these steps.
aRv.Throw(NS_ERROR_DOM_ENCODING_NOT_SUPPORTED_ERR);
aRv.ThrowTypeError(MSG_ENCODING_NOT_SUPPORTED, &label);
return;
}
@ -47,12 +36,6 @@ TextDecoder::Init(const nsAString& aEncoding,
// set the internal fatal flag of the decoder object.
mFatal = aFatal.fatal;
CreateDecoder(aRv);
}
void
TextDecoder::CreateDecoder(ErrorResult& aRv)
{
// Create a decoder object for mEncoding.
nsCOMPtr<nsICharsetConverterManager> ccm =
do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID);
@ -73,12 +56,10 @@ TextDecoder::CreateDecoder(ErrorResult& aRv)
}
void
TextDecoder::ResetDecoder(bool aResetOffset)
TextDecoder::ResetDecoder()
{
mDecoder->Reset();
if (aResetOffset) {
mOffset = 0;
}
mOffset = 0;
}
void
@ -192,22 +173,7 @@ TextDecoder::HandleBOM(const char*& aData, uint32_t& aLength,
strcmp(encoding, mEncoding)) {
// If the stream doesn't start with BOM or the BOM doesn't match the
// encoding, feed a BOM to workaround decoder's bug (bug 634541).
if (!mUseBOM) {
FeedBytes(!strcmp(mEncoding, "utf-16le") ? "\xFF\xFE" : "\xFE\xFF");
}
}
if (mUseBOM) {
// Select a decoder corresponding to the BOM.
if (!*encoding) {
encoding = "utf-16le";
}
// If the endian has not been changed, reuse the decoder.
if (mDecoder && !strcmp(encoding, mEncoding)) {
ResetDecoder(false);
} else {
mEncoding = encoding;
CreateDecoder(aRv);
}
FeedBytes(!strcmp(mEncoding, "utf-16le") ? "\xFF\xFE" : "\xFE\xFF");
}
FeedBytes(mInitialBytes, &aOutString);
}
@ -235,7 +201,7 @@ TextDecoder::GetEncoding(nsAString& aEncoding)
// "utf-16".
// This workaround should not be exposed to the public API and so "utf-16"
// is returned by GetEncoding() if the internal encoding name is "utf-16le".
if (mUseBOM || !strcmp(mEncoding, "utf-16le")) {
if (!strcmp(mEncoding, "utf-16le")) {
aEncoding.AssignLiteral("utf-16");
return;
}

Просмотреть файл

@ -41,8 +41,7 @@ public:
}
TextDecoder(nsISupports* aGlobal)
: mGlobal(aGlobal)
, mFatal(false), mUseBOM(false), mOffset(0), mIsUTF16Family(false)
: mGlobal(aGlobal), mFatal(false), mOffset(0), mIsUTF16Family(false)
{
MOZ_ASSERT(aGlobal);
SetIsDOMBinding();
@ -97,7 +96,6 @@ private:
nsCOMPtr<nsIUnicodeDecoder> mDecoder;
nsCOMPtr<nsISupports> mGlobal;
bool mFatal;
bool mUseBOM;
uint8_t mOffset;
char mInitialBytes[3];
bool mIsUTF16Family;
@ -117,8 +115,7 @@ private:
ErrorResult& aRv);
// Internal helper functions.
void CreateDecoder(ErrorResult& aRv);
void ResetDecoder(bool aResetOffset = true);
void ResetDecoder();
void HandleBOM(const char*& aData, uint32_t& aLength,
const TextDecodeOptions& aOptions,
nsAString& aOutString, ErrorResult& aRv);

Просмотреть файл

@ -18,21 +18,18 @@ TextEncoder::Init(const nsAString& aEncoding,
nsAutoString label(aEncoding);
EncodingUtils::TrimSpaceCharacters(label);
// Run the steps to get an encoding from Encoding.
// Let encoding be the result of getting an encoding from label.
// If encoding is failure, or is none of utf-8, utf-16, and utf-16be,
// throw a TypeError.
if (!EncodingUtils::FindEncodingForLabel(label, mEncoding)) {
// If the steps result in failure,
// throw an "EncodingError" exception and terminate these steps.
aRv.Throw(NS_ERROR_DOM_ENCODING_NOT_SUPPORTED_ERR);
aRv.ThrowTypeError(MSG_ENCODING_NOT_SUPPORTED, &label);
return;
}
// Otherwise, if the Name of the returned encoding is not one of
// "utf-8", "utf-16", or "utf-16be" throw an "EncodingError" exception
// and terminate these steps.
if (PL_strcasecmp(mEncoding, "utf-8") &&
PL_strcasecmp(mEncoding, "utf-16le") &&
PL_strcasecmp(mEncoding, "utf-16be")) {
aRv.Throw(NS_ERROR_DOM_ENCODING_NOT_UTF_ERR);
aRv.ThrowTypeError(MSG_DOM_ENCODING_NOT_UTF);
return;
}

Просмотреть файл

@ -46,7 +46,7 @@ function testBOMEncodingUTF8() {
// test empty encoding provided with invalid byte OM also provided.
data = [0xFF, 0xFE, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27];
testBOMCharset({encoding: "", data: data, error: "EncodingError",
testBOMCharset({encoding: "", data: data, error: "TypeError",
msg: "empty encoding provided with invalid utf-8 BOM test."});
}
@ -65,18 +65,17 @@ function testMoreBOMEncoding() {
// Testing user provided encoding is UTF-16LE & bom encoding is utf-16be
var dataUTF16 = [0xFE, 0xFF, 0x22, 0x00, 0x12, 0x04, 0x41, 0x04, 0x35, 0x04, 0x20, 0x00, 0x41, 0x04, 0x47, 0x04, 0x30, 0x04, 0x41, 0x04, 0x42, 0x04, 0x3B, 0x04, 0x38, 0x04, 0x32, 0x04, 0x4B, 0x04, 0x35, 0x04, 0x20, 0x00, 0x41, 0x04, 0x35, 0x04, 0x3C, 0x04, 0x4C, 0x04, 0x38, 0x04, 0x20, 0x00, 0x3F, 0x04, 0x3E, 0x04, 0x45, 0x04, 0x3E, 0x04, 0x36, 0x04, 0x38, 0x04, 0x20, 0x00, 0x34, 0x04, 0x40, 0x04, 0x43, 0x04, 0x33, 0x04, 0x20, 0x00, 0x3D, 0x04, 0x30, 0x04, 0x20, 0x00, 0x34, 0x04, 0x40, 0x04, 0x43, 0x04, 0x33, 0x04, 0x30, 0x04, 0x2C, 0x00, 0x20, 0x00, 0x3A, 0x04, 0x30, 0x04, 0x36, 0x04, 0x34, 0x04, 0x30, 0x04, 0x4F, 0x04, 0x20, 0x00, 0x3D, 0x04, 0x35, 0x04, 0x41, 0x04, 0x47, 0x04, 0x30, 0x04, 0x41, 0x04, 0x42, 0x04, 0x3B, 0x04, 0x38, 0x04, 0x32, 0x04, 0x30, 0x04, 0x4F, 0x04, 0x20, 0x00, 0x41, 0x04, 0x35, 0x04, 0x3C, 0x04, 0x4C, 0x04, 0x4F, 0x04, 0x20, 0x00, 0x3D, 0x04, 0x35, 0x04, 0x41, 0x04, 0x47, 0x04, 0x30, 0x04, 0x41, 0x04, 0x42, 0x04, 0x3B, 0x04, 0x38, 0x04, 0x32, 0x04, 0x30, 0x04, 0x20, 0x00, 0x3F, 0x04, 0x3E, 0x04, 0x2D, 0x00, 0x41, 0x04, 0x32, 0x04, 0x3E, 0x04, 0x35, 0x04, 0x3C, 0x04, 0x43, 0x04, 0x2E, 0x00, 0x22, 0x00];
testBOMCharset({encoding: "utf-16le", fatal: true, data: dataUTF16, expected: "\ufffe" + expectedString,
msg: "test decoder invalid BOM encoding for utf-16 fatal."});
msg: "test decoder invalid BOM encoding for utf-16le fatal."});
testBOMCharset({encoding: "utf-16le", data: dataUTF16, expected: "\ufffe" + expectedString,
msg: "test decoder invalid BOM encoding for utf-16."});
msg: "test decoder invalid BOM encoding for utf-16le."});
// Testing user provided encoding is UTF-16 & bom encoding is utf-16be
data = [0xFE, 0xFF, 0x00, 0x22, 0x04, 0x12, 0x04, 0x41, 0x04, 0x35, 0x00, 0x20, 0x04, 0x41, 0x04, 0x47, 0x04, 0x30, 0x04, 0x41, 0x04, 0x42, 0x04, 0x3B, 0x04, 0x38, 0x04, 0x32, 0x04, 0x4B, 0x04, 0x35, 0x00, 0x20, 0x04, 0x41, 0x04, 0x35, 0x04, 0x3C, 0x04, 0x4C, 0x04, 0x38, 0x00, 0x20, 0x04, 0x3F, 0x04, 0x3E, 0x04, 0x45, 0x04, 0x3E, 0x04, 0x36, 0x04, 0x38, 0x00, 0x20, 0x04, 0x34, 0x04, 0x40, 0x04, 0x43, 0x04, 0x33, 0x00, 0x20, 0x04, 0x3D, 0x04, 0x30, 0x00, 0x20, 0x04, 0x34, 0x04, 0x40, 0x04, 0x43, 0x04, 0x33, 0x04, 0x30, 0x00, 0x2C, 0x00, 0x20, 0x04, 0x3A, 0x04, 0x30, 0x04, 0x36, 0x04, 0x34, 0x04, 0x30, 0x04, 0x4F, 0x00, 0x20, 0x04, 0x3D, 0x04, 0x35, 0x04, 0x41, 0x04, 0x47, 0x04, 0x30, 0x04, 0x41, 0x04, 0x42, 0x04, 0x3B, 0x04, 0x38, 0x04, 0x32, 0x04, 0x30, 0x04, 0x4F, 0x00, 0x20, 0x04, 0x41, 0x04, 0x35, 0x04, 0x3C, 0x04, 0x4C, 0x04, 0x4F, 0x00, 0x20, 0x04, 0x3D, 0x04, 0x35, 0x04, 0x41, 0x04, 0x47, 0x04, 0x30, 0x04, 0x41, 0x04, 0x42, 0x04, 0x3B, 0x04, 0x38, 0x04, 0x32, 0x04, 0x30, 0x00, 0x20, 0x04, 0x3F, 0x04, 0x3E, 0x00, 0x2D, 0x04, 0x41, 0x04, 0x32, 0x04, 0x3E, 0x04, 0x35, 0x04, 0x3C, 0x04, 0x43, 0x00, 0x2E, 0x00, 0x22];
testBOMCharset({encoding: "utf-16", fatal: true, data: data, expected: expectedString,
msg: "test decoder BOM encoding for utf-16 fatal."});
testBOMCharset({encoding: "utf-16", fatal: true, data: dataUTF16, expected: "\ufffe" + expectedString,
msg: "test decoder invalid BOM encoding for utf-16 fatal."});
testBOMCharset({encoding: "utf-16", data: data, expected: expectedString,
msg: "test decoder BOM encoding for utf-16."});
testBOMCharset({encoding: "utf-16", data: dataUTF16, expected: "\ufffe" + expectedString,
msg: "test decoder invalid BOM encoding for utf-16."});
// Testing user provided encoding is UTF-16 & bom encoding is utf-16le
dataUTF16 = [0xFF, 0xFE, 0x22, 0x00, 0x12, 0x04, 0x41, 0x04, 0x35, 0x04, 0x20, 0x00, 0x41, 0x04, 0x47, 0x04, 0x30, 0x04, 0x41, 0x04, 0x42, 0x04, 0x3B, 0x04, 0x38, 0x04, 0x32, 0x04, 0x4B, 0x04, 0x35, 0x04, 0x20, 0x00, 0x41, 0x04, 0x35, 0x04, 0x3C, 0x04, 0x4C, 0x04, 0x38, 0x04, 0x20, 0x00, 0x3F, 0x04, 0x3E, 0x04, 0x45, 0x04, 0x3E, 0x04, 0x36, 0x04, 0x38, 0x04, 0x20, 0x00, 0x34, 0x04, 0x40, 0x04, 0x43, 0x04, 0x33, 0x04, 0x20, 0x00, 0x3D, 0x04, 0x30, 0x04, 0x20, 0x00, 0x34, 0x04, 0x40, 0x04, 0x43, 0x04, 0x33, 0x04, 0x30, 0x04, 0x2C, 0x00, 0x20, 0x00, 0x3A, 0x04, 0x30, 0x04, 0x36, 0x04, 0x34, 0x04, 0x30, 0x04, 0x4F, 0x04, 0x20, 0x00, 0x3D, 0x04, 0x35, 0x04, 0x41, 0x04, 0x47, 0x04, 0x30, 0x04, 0x41, 0x04, 0x42, 0x04, 0x3B, 0x04, 0x38, 0x04, 0x32, 0x04, 0x30, 0x04, 0x4F, 0x04, 0x20, 0x00, 0x41, 0x04, 0x35, 0x04, 0x3C, 0x04, 0x4C, 0x04, 0x4F, 0x04, 0x20, 0x00, 0x3D, 0x04, 0x35, 0x04, 0x41, 0x04, 0x47, 0x04, 0x30, 0x04, 0x41, 0x04, 0x42, 0x04, 0x3B, 0x04, 0x38, 0x04, 0x32, 0x04, 0x30, 0x04, 0x20, 0x00, 0x3F, 0x04, 0x3E, 0x04, 0x2D, 0x00, 0x41, 0x04, 0x32, 0x04, 0x3E, 0x04, 0x35, 0x04, 0x3C, 0x04, 0x43, 0x04, 0x2E, 0x00, 0x22, 0x00];

Просмотреть файл

@ -72,19 +72,19 @@ function testConstructorEncodingOption(aData, aExpectedString)
msg: "decoder testing constructor valid encoding."});
// invalid encoding passed
testCharset({encoding: "asdfasdf", input: aData, error: "EncodingError",
testCharset({encoding: "asdfasdf", input: aData, error: "TypeError",
msg: "constructor encoding, invalid encoding test."});
// passing spaces for encoding
testCharset({encoding: " ", input: aData, error: "EncodingError",
testCharset({encoding: " ", input: aData, error: "TypeError",
msg: "constructor encoding, spaces encoding test."});
// passing null for encoding
testCharset({encoding: null, input: aData, error: "EncodingError",
testCharset({encoding: null, input: aData, error: "TypeError",
msg: "constructor encoding, \"null\" encoding test."});
// empty encoding passed
testCharset({encoding: "", input: aData, error: "EncodingError",
testCharset({encoding: "", input: aData, error: "TypeError",
msg: "constuctor encoding, empty encoding test."});
// replacement character test
@ -184,10 +184,10 @@ function testDecodeStreamCompositions() {
{encoding: "utf-16", input: [0xFF,0xFE,0x01,0x00], expected: ["","","","\x01"]},
{encoding: "utf-16", input: [0xFF,0xFE,0xFF,0xFE], expected: ["","","","\uFEFF"]},
{encoding: "utf-16", input: [0xFF,0xFE,0xFE,0xFF], expected: ["","","","\uFFFE"]},
{encoding: "utf-16", input: [0xFE,0xFF], expected: ["",""]},
{encoding: "utf-16", input: [0xFE,0xFF,0x01,0x00], expected: ["","","","\u0100"]},
{encoding: "utf-16", input: [0xFE,0xFF,0xFF,0xFE], expected: ["","","","\uFFFE"]},
{encoding: "utf-16", input: [0xFE,0xFF,0xFE,0xFF], expected: ["","","","\uFEFF"]},
{encoding: "utf-16", input: [0xFE,0xFF], expected: ["","\uFFFE"]},
{encoding: "utf-16", input: [0xFE,0xFF,0x01,0x00], expected: ["","\uFFFE","","\x01"]},
{encoding: "utf-16", input: [0xFE,0xFF,0xFF,0xFE], expected: ["","\uFFFE","","\uFEFF"]},
{encoding: "utf-16", input: [0xFE,0xFF,0xFE,0xFF], expected: ["","\uFFFE","","\uFFFE"]},
{encoding: "utf-16le", input: [0x01,0x00], expected: ["","\x01"]},
{encoding: "utf-16le", input: [0x01,0x00,0x03,0x02], expected: ["","\x01","","\u0203"]},
{encoding: "utf-16le", input: [0xFF,0xFE,0x01,0x00], expected: ["","","","\x01"]},
@ -337,7 +337,7 @@ function testDecoderGetEncoding()
{encoding: "utf-16", labels: ["utf-16", "utf-16le"]},
{encoding: "utf-16be", labels: ["utf-16be"]},
{encoding: "x-user-defined", labels: ["x-user-defined"]},
{error: "EncodingError", labels: ["x-windows-949", "\u0130SO-8859-1"]},
{error: "TypeError", labels: ["x-windows-949", "\u0130SO-8859-1"]},
];
for (var le of labelEncodings) {

Просмотреть файл

@ -95,26 +95,26 @@ function testConstructorEncodingOption(aData, aExpectedString)
msg: "testing encoding with valid utf-8 encoding."});
// passing spaces for encoding
testSingleString({encoding: " ", input: aData, error: "EncodingError",
testSingleString({encoding: " ", input: aData, error: "TypeError",
msg: "constructor encoding, spaces encoding test."});
// invalid encoding passed
testSingleString({encoding: "asdfasdf", input: aData, error: "EncodingError",
testSingleString({encoding: "asdfasdf", input: aData, error: "TypeError",
msg: "constructor encoding, invalid encoding test."});
// null encoding passed
testSingleString({encoding: null, input: aData, error: "EncodingError",
testSingleString({encoding: null, input: aData, error: "TypeError",
msg: "constructor encoding, \"null\" encoding test."});
// null encoding passed
testSingleString({encoding: "", input: aData, error: "EncodingError",
testSingleString({encoding: "", input: aData, error: "TypeError",
msg: "constructor encoding, empty encoding test."});
}
function testEncodingValues(aData, aExpectedString)
{
var encoding = "ISO-8859-11";
testSingleString({encoding: aData, input: encoding, error: "EncodingError",
testSingleString({encoding: aData, input: encoding, error: "TypeError",
msg: "encoder encoding values test."});
}

Просмотреть файл

@ -1,30 +1,30 @@
<!DOCTYPE html>
<!DOCTYPE HTML>
<html>
<head>
<meta charset=utf-8>
<title>Encoding API Tests</title>
<link rel="stylesheet" href="/resources/testharness.css">
</head>
<body>
<h1>Encoding API Tests</h1>
<div id="log"></div>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
var _test = test;
test = function(msg, no, func) { _test(func || no, msg); };
equal = assert_equals;
ok = assert_true;
raises = function(func) { assert_throws(null, func); };
expect = function() {};
setup({explicit_timeout: true});
</script>
<div id="log"></div>
<script type="text/javascript" src="unit/test_singlebytes.js"></script>
<!-- TODO: test for all single-byte encoding indexes -->
<script type="text/javascript" src="unit/test_gbk.js"></script>
<!-- TODO: gb18030 -->
<script type="text/javascript" src="unit/test_hz-gb-2312.js"></script>
<script type="text/javascript" src="unit/test_big5.js"></script>
<script type="text/javascript" src="unit/test_euc-jp.js"></script>
<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>

Просмотреть файл

@ -5,34 +5,48 @@
const { 'classes': Cc, 'interfaces': Ci } = Components;
function equal(a, b, msg) {
dump("equal(" + a + ", " + b + ", \"" + msg + "\")");
// Instantiate nsIDOMScriptObjectFactory so that DOMException is usable in xpcshell
Components.classesByID["{9eb760f0-4380-11d2-b328-00805f8a3859}"].getService(Ci.nsISupports);
function assert_equals(a, b, msg) {
dump("assert_equals(" + a + ", " + b + ", \"" + msg + "\")");
do_check_eq(a, b, Components.stack.caller);
}
function ok(cond, msg) {
dump("ok(" + cond + ", \"" + msg + "\")");
function assert_not_equals(a, b, msg) {
dump("assert_not_equals(" + a + ", " + b + ", \"" + msg + "\")");
do_check_neq(a, b, Components.stack.caller);
}
function assert_array_equals(a, b, msg) {
dump("assert_array_equals(\"" + msg + "\")");
do_check_eq(a.length, b.length, Components.stack.caller);
for (var i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) {
do_check_eq(a[i], b[i], Components.stack.caller);
}
}
}
function assert_true(cond, msg) {
dump("assert_true(" + cond + ", \"" + msg + "\")");
do_check_true(!!cond, Components.stack.caller);
}
function raises(func) {
dump("raises(" + func + ")");
function assert_throws(ex, func) {
dump("assert_throws(\"" + ex + "\", " + func + ")");
try {
func();
do_check_true(false, Components.stack.caller);
} catch (e) {
do_check_true(true, Components.stack.caller);
do_check_eq(e.name, ex.name, Components.stack.caller);
}
}
var tests = [];
function test(msg, no, func) {
tests.push({msg: msg, func: func || no});
}
function expect(count) {
dump("expect(", count, ")");
function test(func, msg) {
tests.push({msg: msg, func: func});
}
function run_test() {

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -1,15 +1,5 @@
// NOTE: relies on http://docs.jquery.com/QUnit
function arrayEqual(a, b, msg) {
// deepEqual() is too picky
equal(a.length, b.length, msg + " - array length");
for (var i = 0; i < a.length; i += 1) {
// equal() is too slow to call each time
if (a[i] !== b[i]) { equal(a[i], b[i], msg + " - first array index: " + String(i) ); return; }
}
ok(true, msg);
}
// NOTE: Requires testharness.js
// http://www.w3.org/2008/webapps/wiki/Harness
function testEncodeDecode(encoding, min, max) {
function cpname(n) {
@ -19,7 +9,6 @@ function testEncodeDecode(encoding, min, max) {
}
test(
encoding + " - Encode/Decode Range " + cpname(min) + " - " + cpname(max),
function() {
var string, i, j, BATCH_SIZE = 0x1000;
for (i = min; i < max; i += BATCH_SIZE) {
@ -31,25 +20,24 @@ function testEncodeDecode(encoding, min, max) {
} else if (j > 0xffff) {
// outside BMP - encode as surrogate pair
string += String.fromCharCode(
0xd800 + ((j >> 10) & 0x3ff),
0xdc00 + (j & 0x3ff));
0xd800 + ((j >> 10) & 0x3ff),
0xdc00 + (j & 0x3ff));
} else {
string += String.fromCharCode(i);
}
}
var encoded = TextEncoder(encoding).encode(string);
var decoded = TextDecoder(encoding).decode(encoded);
equal(string, decoded, 'Round trip ' + cpname(i) + " - " + cpname(j));
assert_equals(string, decoded, 'Round trip ' + cpname(i) + " - " + cpname(j));
}
});
},
encoding + " - Encode/Decode Range " + cpname(min) + " - " + cpname(max)
);
}
testEncodeDecode('UTF-8', 0, 0x10FFFF);
testEncodeDecode('UTF-16LE', 0, 0x10FFFF);
testEncodeDecode('UTF-16BE', 0, 0x10FFFF);
// TextEncoder no longer supports non-UTF encodings
//testEncodeDecode('windows-1252', 0, 0xFF);
// Inspired by:
// http://ecmanaut.blogspot.com/2006/07/encoding-decoding-utf8-in-javascript.html
@ -68,10 +56,7 @@ function decode_utf8(octets) {
}
test(
"UTF-8 encoding (compare against unescape/encodeURIComponent)",
function() {
expect(544);
var actual, expected, str, i, j, BATCH_SIZE = 0x1000;
for (i = 0; i < 0x10FFFF; i += BATCH_SIZE) {
@ -83,8 +68,8 @@ test(
} else if (j > 0xffff) {
// outside BMP - encode as surrogate pair
str += String.fromCharCode(
0xd800 + ((j >> 10) & 0x3ff),
0xdc00 + (j & 0x3ff));
0xd800 + ((j >> 10) & 0x3ff),
0xdc00 + (j & 0x3ff));
} else {
str += String.fromCharCode(i);
}
@ -92,15 +77,14 @@ test(
expected = encode_utf8(str);
actual = TextEncoder('UTF-8').encode(str);
arrayEqual(actual, expected, 'expected equal encodings');
assert_array_equals(actual, expected, 'expected equal encodings');
}
});
},
"UTF-8 encoding (compare against unescape/encodeURIComponent)"
);
test(
"UTF-8 decoding (compare against decodeURIComponent/escape)",
function() {
expect(272);
var encoded, actual, expected, str, i, j, BATCH_SIZE = 0x1000;
for (i = 0; i < 0x10FFFF; i += BATCH_SIZE) {
@ -112,8 +96,8 @@ test(
} else if (j > 0xffff) {
// outside BMP - encode as surrogate pair
str += String.fromCharCode(
0xd800 + ((j >> 10) & 0x3ff),
0xdc00 + (j & 0x3ff));
0xd800 + ((j >> 10) & 0x3ff),
0xdc00 + (j & 0x3ff));
} else {
str += String.fromCharCode(i);
}
@ -124,32 +108,25 @@ test(
expected = decode_utf8(encoded);
actual = TextDecoder('UTF-8').decode(new Uint8Array(encoded));
equal(actual, expected, 'expected equal decodings');
assert_equals(actual, expected, 'expected equal decodings');
}
});
},
"UTF-8 decoding (compare against decodeURIComponent/escape)"
);
function testEncodeDecodeSample(encoding, string, expected) {
test(
encoding + " - Encode/Decode - reference sample",
function() {
expect(/^utf-/i.test(encoding) ? 3 : 1);
if (/^utf-/i.test(encoding)) {
var encoded = TextEncoder(encoding).encode(string);
arrayEqual(encoded, expected, 'expected equal encodings ' + encoding);
}
var encoded = TextEncoder(encoding).encode(string);
assert_array_equals(encoded, expected, 'expected equal encodings ' + encoding);
var decoded = TextDecoder(encoding).decode(new Uint8Array(expected));
equal(decoded, string, 'expected equal decodings ' + encoding);
});
assert_equals(decoded, string, 'expected equal decodings ' + encoding);
},
encoding + " - Encode/Decode - reference sample"
);
}
testEncodeDecodeSample(
"windows-1252",
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u20ac\x81\u201a\u0192\u201e\u2026\u2020\u2021\u02c6\u2030\u0160\u2039\u0152\x8d\u017d\x8f\x90\u2018\u2019\u201c\u201d\u2022\u2013\u2014\u02dc\u2122\u0161\u203a\u0153\x9d\u017e\u0178\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
(function() { var i = 0, a = []; while (i < 256) { a.push(i++); } return a; }())
);
testEncodeDecodeSample(
"utf-8",
"z\xA2\u6C34\uD834\uDD1E\uDBFF\uDFFD", // z, cent, CJK water, G-Clef, Private-use character
@ -172,10 +149,7 @@ testEncodeDecodeSample(
);
test(
"bad data",
function() {
expect(5);
var badStrings = [
{ input: '\ud800', expected: '\ufffd' }, // Surrogate half
{ input: '\udc00', expected: '\ufffd' }, // Surrogate half
@ -188,15 +162,14 @@ test(
function(t) {
var encoded = TextEncoder('utf-8').encode(t.input);
var decoded = TextDecoder('utf-8').decode(encoded);
equal(decoded, t.expected);
assert_equals(t.expected, decoded);
});
});
},
"bad data"
);
test(
"fatal flag",
function() {
expect(14);
var bad = [
{ encoding: 'utf-8', input: [0xC0] }, // ends early
{ encoding: 'utf-8', input: [0xC0, 0x00] }, // invalid trail
@ -208,98 +181,90 @@ test(
{ encoding: 'utf-8', input: [0xE0, 0x80, 0xC0] }, // invalid trail
{ encoding: 'utf-8', input: [0xFC, 0x80, 0x80, 0x80, 0x80, 0x80] }, // > 0x10FFFF
{ encoding: 'utf-16', input: [0x00] }, // truncated code unit
{ encoding: 'utf-16', input: [0x00, 0xd8] }, // surrogate half
{ encoding: 'utf-16', input: [0x00, 0xd8, 0x00, 0x00] }, // surrogate half
{ encoding: 'utf-16', input: [0x00, 0xdc, 0x00, 0x00] }, // trail surrogate
{ encoding: 'utf-16', input: [0x00, 0xdc, 0x00, 0xd8] } // swapped surrogates
//TODO: Gecko doesn't throw for unpaired surrogates
//{ encoding: 'utf-16', input: [0x00, 0xd8] }, // surrogate half
//{ encoding: 'utf-16', input: [0x00, 0xd8, 0x00, 0x00] }, // surrogate half
//{ encoding: 'utf-16', input: [0x00, 0xdc, 0x00, 0x00] }, // trail surrogate
//{ encoding: 'utf-16', input: [0x00, 0xdc, 0x00, 0xd8] } // swapped surrogates
// TODO: Single byte encoding cases
];
bad.forEach(
function(t) {
raises(function () { TextDecoder('utf-8').encode(t.input, {fatal: true}); });
assert_throws({name: 'EncodingError'}, function () {
TextDecoder(t.encoding, {fatal: true}).decode(new Uint8Array(t.input));
});
});
});
},
"fatal flag"
);
test(
"Encoding names are case insensitive", function() {
var utfencodings = [
{ encoding: 'UTF-8', string: 'z\xA2\u6C34\uD834\uDD1E\uDBFF\uDFFD' },
{ encoding: 'UTF-16', string: 'z\xA2\u6C34\uD834\uDD1E\uDBFF\uDFFD' },
{ encoding: 'UTF-16LE', string: 'z\xA2\u6C34\uD834\uDD1E\uDBFF\uDFFD' },
{ encoding: 'UTF-16BE', string: 'z\xA2\u6C34\uD834\uDD1E\uDBFF\uDFFD' },
];
utfencodings.forEach(
function(test) {
var lower = test.encoding.toLowerCase();
var upper = test.encoding.toUpperCase();
equal(
TextDecoder(lower).decode(TextEncoder(lower).encode(test.string)),
TextDecoder(upper).decode(TextEncoder(upper).encode(test.string))
);
});
function() {
var encodings = [
{ encoding: 'ASCII', input: [0x41, 0x42, 0x43, 0x61, 0x62, 0x63, 0x31, 0x32, 0x33, 0x21, 0x40, 0x23] },
{ encoding: 'ISO-8859-1', input: [0x41, 0x42, 0x43, 0x61, 0x62, 0x63, 0x31, 0x32, 0x33, 0x21, 0x40, 0x23, 0xA2] }
{ label: 'utf-8', encoding: 'utf-8' },
{ label: 'utf-16', encoding: 'utf-16' },
{ label: 'utf-16le', encoding: 'utf-16' },
{ label: 'utf-16be', encoding: 'utf-16be' },
{ label: 'ascii', encoding: 'windows-1252' },
{ label: 'iso-8859-1', encoding: 'windows-1252' }
];
encodings.forEach(
function(test) {
var lower = test.encoding.toLowerCase();
var upper = test.encoding.toUpperCase();
equal(
TextDecoder(lower).decode(new Uint8Array(test.input)),
TextDecoder(upper).decode(new Uint8Array(test.input))
);
assert_equals(TextDecoder(test.label.toLowerCase()).encoding, test.encoding);
assert_equals(TextDecoder(test.label.toUpperCase()).encoding, test.encoding);
});
});
},
"Encoding names are case insensitive"
);
test(
"Byte-order marks",
function() {
//expect(11);
expect(5);
var utf8_bom = [0xEF, 0xBB, 0xBF];
var utf8 = [0x7A, 0xC2, 0xA2, 0xE6, 0xB0, 0xB4, 0xF0, 0x9D, 0x84, 0x9E, 0xF4, 0x8F, 0xBF, 0xBD];
var utf8 = [0xEF, 0xBB, 0xBF, 0x7A, 0xC2, 0xA2, 0xE6, 0xB0, 0xB4, 0xF0, 0x9D, 0x84, 0x9E, 0xF4, 0x8F, 0xBF, 0xBD];
var utf16le = [0xff, 0xfe, 0x7A, 0x00, 0xA2, 0x00, 0x34, 0x6C, 0x34, 0xD8, 0x1E, 0xDD, 0xFF, 0xDB, 0xFD, 0xDF];
var utf16be = [0xfe, 0xff, 0x00, 0x7A, 0x00, 0xA2, 0x6C, 0x34, 0xD8, 0x34, 0xDD, 0x1E, 0xDB, 0xFF, 0xDF, 0xFD];
var utf16le_bom = [0xff, 0xfe];
var utf16le = [0x7A, 0x00, 0xA2, 0x00, 0x34, 0x6C, 0x34, 0xD8, 0x1E, 0xDD, 0xFF, 0xDB, 0xFD, 0xDF];
var utf16be_bom = [0xfe, 0xff];
var utf16be = [0x00, 0x7A, 0x00, 0xA2, 0x6C, 0x34, 0xD8, 0x34, 0xDD, 0x1E, 0xDB, 0xFF, 0xDF, 0xFD];
var string = "z\xA2\u6C34\uD834\uDD1E\uDBFF\uDFFD"; // z, cent, CJK water, G-Clef, Private-use character
// Basic cases
equal(TextDecoder('utf-8').decode(new Uint8Array(utf8)), string);
equal(TextDecoder('utf-16le').decode(new Uint8Array(utf16le)), string);
equal(TextDecoder('utf-16be').decode(new Uint8Array(utf16be)), string);
equal(TextDecoder('utf-16').decode(new Uint8Array(utf16le)), string);
equal(TextDecoder('utf-16').decode(new Uint8Array(utf16be)), string);
// missing BOMs
assert_equals(TextDecoder('utf-8').decode(new Uint8Array(utf8)), string);
assert_equals(TextDecoder('utf-16le').decode(new Uint8Array(utf16le)), string);
assert_equals(TextDecoder('utf-16be').decode(new Uint8Array(utf16be)), string);
/*
// TODO: New API?
// Verify that BOM wins
equal(stringEncoding.decode(new Uint8Array(utf8), 'utf-16le'), string);
equal(stringEncoding.decode(new Uint8Array(utf8), 'utf-16be'), string);
equal(stringEncoding.decode(new Uint8Array(utf16le), 'utf-8'), string);
equal(stringEncoding.decode(new Uint8Array(utf16le), 'utf-16be'), string);
equal(stringEncoding.decode(new Uint8Array(utf16be), 'utf-8'), string);
equal(stringEncoding.decode(new Uint8Array(utf16be), 'utf-16le'), string);
*/
});
// matching BOMs
assert_equals(TextDecoder('utf-8').decode(new Uint8Array(utf8_bom.concat(utf8))), string);
assert_equals(TextDecoder('utf-16le').decode(new Uint8Array(utf16le_bom.concat(utf16le))), string);
assert_equals(TextDecoder('utf-16be').decode(new Uint8Array(utf16be_bom.concat(utf16be))), string);
// mismatching BOMs
assert_not_equals(TextDecoder('utf-8').decode(new Uint8Array(utf16le_bom.concat(utf8))), string);
assert_not_equals(TextDecoder('utf-8').decode(new Uint8Array(utf16be_bom.concat(utf8))), string);
assert_not_equals(TextDecoder('utf-16le').decode(new Uint8Array(utf8_bom.concat(utf16le))), string);
assert_not_equals(TextDecoder('utf-16le').decode(new Uint8Array(utf16be_bom.concat(utf16le))), string);
assert_not_equals(TextDecoder('utf-16be').decode(new Uint8Array(utf8_bom.concat(utf16be))), string);
assert_not_equals(TextDecoder('utf-16be').decode(new Uint8Array(utf16le_bom.concat(utf16be))), string);
},
"Byte-order marks"
);
test(
"Encoding names",
function () {
equal(TextEncoder("utf-8").encoding, "utf-8"); // canonical case
equal(TextEncoder("UTF-16").encoding, "utf-16"); // canonical case and name
equal(TextEncoder("UTF-16BE").encoding, "utf-16be"); // canonical case and name
equal(TextDecoder("iso8859-1").encoding, "windows-1252"); // canonical case and name
equal(TextDecoder("iso-8859-1").encoding, "windows-1252"); // canonical case and name
});
assert_equals(TextDecoder("utf-8").encoding, "utf-8"); // canonical case
assert_equals(TextDecoder("UTF-16").encoding, "utf-16"); // canonical case and name
assert_equals(TextDecoder("UTF-16BE").encoding, "utf-16be"); // canonical case and name
assert_equals(TextDecoder("iso8859-1").encoding, "windows-1252"); // canonical case and name
assert_equals(TextDecoder("iso-8859-1").encoding, "windows-1252"); // canonical case and name
},
"Encoding names"
);
test(
"Streaming Decode",
function () {
["utf-8", "utf-16le", "utf-16be"].forEach(function (encoding) {
var string = "\x00123ABCabc\x80\xFF\u0100\u1000\uFFFD\uD800\uDC00\uDBFF\uDFFF";
@ -315,24 +280,25 @@ test(
out += decoder.decode(new Uint8Array(sub), {stream: true});
}
out += decoder.decode();
equal(out, string, "streaming decode " + encoding);
assert_equals(out, string, "streaming decode " + encoding);
}
});
});
},
"Streaming Decode"
);
test(
"Shift_JIS Decode",
function () {
var jis = [0x82, 0xC9, 0x82, 0xD9, 0x82, 0xF1];
var expected = "\u306B\u307B\u3093"; // Nihon
equal(TextDecoder("shift_jis").decode(new Uint8Array(jis)), expected);
});
assert_equals(TextDecoder("shift_jis").decode(new Uint8Array(jis)), expected);
},
"Shift_JIS Decode"
);
test(
"Supersets of ASCII decode ASCII correctly",
38,
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-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"];
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"];
encodings.forEach(function (encoding) {
var string = '', bytes = [];
@ -350,9 +316,46 @@ test(
bytes.push(i);
}
var ascii_encoded = TextEncoder('utf-8').encode(string);
equal(TextDecoder(encoding).decode(ascii_encoded), string, encoding);
if (encoding === "utf-8") {
arrayEqual(TextEncoder(encoding).encode(string), bytes, encoding);
}
assert_equals(TextDecoder(encoding).decode(ascii_encoded), string, encoding);
//assert_array_equals(TextEncoder(encoding).encode(string), bytes, encoding);
});
});
},
"Supersets of ASCII decode ASCII correctly"
);
test(
function () {
assert_throws({name: 'EncodingError'}, function() { TextDecoder("utf-8", {fatal: true}).decode(new Uint8Array([0xff])); });
// This should not hang:
TextDecoder("utf-8").decode(new Uint8Array([0xff]));
assert_throws({name: 'EncodingError'}, function() { TextDecoder("utf-16", {fatal: true}).decode(new Uint8Array([0x00])); });
// This should not hang:
TextDecoder("utf-16").decode(new Uint8Array([0x00]));
assert_throws({name: 'EncodingError'}, function() { TextDecoder("utf-16be", {fatal: true}).decode(new Uint8Array([0x00])); });
// This should not hang:
TextDecoder("utf-16be").decode(new Uint8Array([0x00]));
},
"Non-fatal errors at EOF"
);
test(
function () {
var utf_encodings = ["utf-8", "utf-16", "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"];
utf_encodings.forEach(function(encoding) {
assert_equals(TextDecoder(encoding).encoding, encoding);
assert_equals(TextEncoder(encoding).encoding, encoding);
});
legacy_encodings.forEach(function(encoding) {
assert_equals(TextDecoder(encoding).encoding, encoding);
assert_throws({name: 'TypeError'}, function() { TextEncoder(encoding); });
});
},
"Non-UTF encodings supported only for decode, not encode"
);

Просмотреть файл

@ -28,7 +28,11 @@ ArchiveItem::~ArchiveItem()
nsCString
ArchiveItem::GetType()
{
return mType.IsEmpty() ? nsCString("binary/octet-stream") : mType;
if (mType.IsEmpty()) {
return NS_LITERAL_CSTRING("binary/octet-stream");
}
return mType;
}
void
@ -109,20 +113,29 @@ ArchiveReaderEvent::ShareMainThread()
for (uint32_t index = 0; index < mFileList.Length(); ++index) {
nsRefPtr<ArchiveItem> item = mFileList[index];
int32_t offset = item->GetFilename().RFindChar('.');
nsString tmp;
nsresult rv = item->GetFilename(tmp);
nsCString filename = NS_ConvertUTF16toUTF8(tmp);
if (NS_FAILED(rv)) {
continue;
}
int32_t offset = filename.RFindChar('.');
if (offset != kNotFound) {
nsCString ext(item->GetFilename());
ext.Cut(0, offset + 1);
filename.Cut(0, offset + 1);
// Just to be sure, if something goes wrong, the mimetype is an empty string:
nsCString type;
if (NS_SUCCEEDED(GetType(ext, type)))
if (NS_SUCCEEDED(GetType(filename, type))) {
item->SetType(type);
}
}
// This is a nsDOMFile:
nsRefPtr<nsIDOMFile> file = item->File(mArchiveReader);
fileList.AppendElement(file);
if (file) {
fileList.AppendElement(file);
}
}
}

Просмотреть файл

@ -17,8 +17,10 @@
BEGIN_FILE_NAMESPACE
// This class contains all the info needed for a single item
// It must contain the implementation of the File() method.
/**
* This class contains all the info needed for a single item
* It must contain the implementation of the File() method.
*/
class ArchiveItem : public nsISupports
{
public:
@ -28,11 +30,11 @@ public:
virtual ~ArchiveItem();
// Getter/Setter for the type
virtual nsCString GetType();
virtual void SetType(const nsCString& aType);
nsCString GetType();
void SetType(const nsCString& aType);
// Getter for the filename
virtual nsCString GetFilename() = 0;
virtual nsresult GetFilename(nsString& aFilename) = 0;
// Generate a DOMFile
virtual nsIDOMFile* File(ArchiveReader* aArchiveReader) = 0;
@ -41,9 +43,11 @@ protected:
nsCString mType;
};
// This class must be extended by any archive format supported by ArchiveReader API
// This class runs in a different thread and it calls the 'exec()' method.
// The exec() must populate mFileList and mStatus then it must call RunShare();
/**
* This class must be extended by any archive format supported by ArchiveReader API
* This class runs in a different thread and it calls the 'exec()' method.
* The exec() must populate mFileList and mStatus then it must call RunShare();
*/
class ArchiveReaderEvent : public nsRunnable
{
public:

Просмотреть файл

@ -40,11 +40,11 @@ ArchiveReader::Initialize(nsISupports* aOwner,
uint32_t aArgc,
JS::Value* aArgv)
{
NS_ENSURE_TRUE(aArgc > 0, NS_ERROR_UNEXPECTED);
NS_ENSURE_TRUE(aArgc == 1 || aArgc == 2, NS_ERROR_INVALID_ARG);
// We expect to get a Blob object
if (!aArgv[0].isObject()) {
return NS_ERROR_UNEXPECTED; // We're not interested
return NS_ERROR_INVALID_ARG; // We're not interested
}
JSObject* obj = &aArgv[0].toObject();
@ -52,16 +52,22 @@ ArchiveReader::Initialize(nsISupports* aOwner,
nsCOMPtr<nsIDOMBlob> blob;
blob = do_QueryInterface(nsContentUtils::XPConnect()->GetNativeOfWrapper(aCx, obj));
if (!blob) {
return NS_ERROR_UNEXPECTED;
return NS_ERROR_INVALID_ARG;
}
mBlob = blob;
// Extra param is an object
if (aArgc > 1) {
nsresult rv = mOptions.Init(aCx, &aArgv[1]);
NS_ENSURE_SUCCESS(rv, rv);
}
mWindow = do_QueryInterface(aOwner);
if (!mWindow) {
return NS_ERROR_UNEXPECTED;
}
mBlob = blob;
return NS_OK;
}
@ -122,7 +128,7 @@ ArchiveReader::OpenArchive()
nsRefPtr<ArchiveReaderEvent> event;
/* FIXME: If we want to support more than 1 format we should check the content type here: */
event = new ArchiveReaderZipEvent(this);
event = new ArchiveReaderZipEvent(this, mOptions);
rv = target->Dispatch(event, NS_DISPATCH_NORMAL);
NS_ENSURE_SUCCESS(rv, rv);
@ -186,6 +192,17 @@ ArchiveReader::GetFile(const nsAString& filename,
return NS_OK;
}
/* nsIDOMArchiveRequest getFiles (); */
NS_IMETHODIMP
ArchiveReader::GetFiles(nsIDOMArchiveRequest** _retval)
{
nsRefPtr<ArchiveRequest> request = GenerateArchiveRequest();
request->OpGetFiles();
request.forget(_retval);
return NS_OK;
}
already_AddRefed<ArchiveRequest>
ArchiveReader::GenerateArchiveRequest()
{

Просмотреть файл

@ -16,11 +16,15 @@
#include "nsIChannel.h"
#include "nsIDOMFile.h"
#include "mozilla/Attributes.h"
#include "DictionaryHelpers.h"
BEGIN_FILE_NAMESPACE
class ArchiveRequest;
/**
* This is the ArchiveReader object
*/
class ArchiveReader MOZ_FINAL : public nsIDOMArchiveReader,
public nsIJSNativeInitializer
{
@ -39,7 +43,7 @@ public:
JSContext* aCx,
JSObject* aObj,
uint32_t aArgc,
jsval* aArgv);
JS::Value* aArgv);
nsresult GetInputStream(nsIInputStream** aInputStream);
nsresult GetSize(uint64_t* aSize);
@ -90,6 +94,8 @@ protected:
nsTArray<nsCOMPtr<nsIDOMFile> > fileList;
nsresult status;
} mData;
ArchiveReaderOptions mOptions;
};
END_FILE_NAMESPACE

Просмотреть файл

@ -44,7 +44,7 @@ ArchiveRequestEvent::Run()
return NS_OK;
}
/* ArchiveRequest */
// ArchiveRequest
ArchiveRequest::ArchiveRequest(nsIDOMWindow* aWindow,
ArchiveReader* aReader)
@ -90,8 +90,9 @@ ArchiveRequest::Run()
// Register this request to the reader.
// When the reader is ready to return data, a 'Ready()' will be called
nsresult rv = mArchiveReader->RegisterRequest(this);
if (NS_FAILED(rv))
if (NS_FAILED(rv)) {
FireError(rv);
}
}
void
@ -107,6 +108,12 @@ ArchiveRequest::OpGetFile(const nsAString& aFilename)
mFilename = aFilename;
}
void
ArchiveRequest::OpGetFiles()
{
mOperation = GetFiles;
}
nsresult
ArchiveRequest::ReaderReady(nsTArray<nsCOMPtr<nsIDOMFile> >& aFileList,
nsresult aStatus)
@ -116,7 +123,7 @@ ArchiveRequest::ReaderReady(nsTArray<nsCOMPtr<nsIDOMFile> >& aFileList,
return NS_OK;
}
jsval result;
JS::Value result;
nsresult rv;
nsIScriptContext* sc = GetContextForEventHandlers(&rv);
@ -139,6 +146,10 @@ ArchiveRequest::ReaderReady(nsTArray<nsCOMPtr<nsIDOMFile> >& aFileList,
case GetFile:
rv = GetFileResult(cx, &result, aFileList);
break;
case GetFiles:
rv = GetFilesResult(cx, &result, aFileList);
break;
}
if (NS_FAILED(rv)) {
@ -157,7 +168,7 @@ ArchiveRequest::ReaderReady(nsTArray<nsCOMPtr<nsIDOMFile> >& aFileList,
nsresult
ArchiveRequest::GetFilenamesResult(JSContext* aCx,
jsval* aValue,
JS::Value* aValue,
nsTArray<nsCOMPtr<nsIDOMFile> >& aFileList)
{
JSObject* array = JS_NewArrayObject(aCx, aFileList.Length(), nullptr);
@ -177,7 +188,7 @@ ArchiveRequest::GetFilenamesResult(JSContext* aCx,
JSString* str = JS_NewUCStringCopyZ(aCx, filename.get());
NS_ENSURE_TRUE(str, NS_ERROR_OUT_OF_MEMORY);
jsval item = STRING_TO_JSVAL(str);
JS::Value item = STRING_TO_JSVAL(str);
if (NS_FAILED(rv) || !JS_SetElement(aCx, array, i, &item)) {
return NS_ERROR_FAILURE;
@ -187,14 +198,14 @@ ArchiveRequest::GetFilenamesResult(JSContext* aCx,
if (!JS_FreezeObject(aCx, array)) {
return NS_ERROR_FAILURE;
}
*aValue = OBJECT_TO_JSVAL(array);
return NS_OK;
}
nsresult
ArchiveRequest::GetFileResult(JSContext* aCx,
jsval* aValue,
JS::Value* aValue,
nsTArray<nsCOMPtr<nsIDOMFile> >& aFileList)
{
for (uint32_t i = 0; i < aFileList.Length(); ++i) {
@ -205,8 +216,9 @@ ArchiveRequest::GetFileResult(JSContext* aCx,
NS_ENSURE_SUCCESS(rv, rv);
if (filename == mFilename) {
JSObject* scope = JS_GetGlobalForScopeChain(aCx);
nsresult rv = nsContentUtils::WrapNative(aCx, scope, file, aValue, nullptr, true);
nsresult rv = nsContentUtils::WrapNative(
aCx, JS_GetGlobalForScopeChain(aCx),
file, &NS_GET_IID(nsIDOMFile), aValue);
return rv;
}
}
@ -214,6 +226,31 @@ ArchiveRequest::GetFileResult(JSContext* aCx,
return NS_ERROR_FAILURE;
}
nsresult
ArchiveRequest::GetFilesResult(JSContext* aCx,
JS::Value* aValue,
nsTArray<nsCOMPtr<nsIDOMFile> >& aFileList)
{
JSObject* array = JS_NewArrayObject(aCx, aFileList.Length(), nullptr);
if (!array) {
return NS_ERROR_OUT_OF_MEMORY;
}
for (PRUint32 i = 0; i < aFileList.Length(); ++i) {
nsCOMPtr<nsIDOMFile> file = aFileList[i];
JS::Value value;
nsresult rv = nsContentUtils::WrapNative(aCx, JS_GetGlobalForScopeChain(aCx),
file, &NS_GET_IID(nsIDOMFile), &value);
if (NS_FAILED(rv) || !JS_SetElement(aCx, array, i, &value)) {
return NS_ERROR_FAILURE;
}
}
aValue->setObject(*array);
return NS_OK;
}
// static
already_AddRefed<ArchiveRequest>
ArchiveRequest::Create(nsIDOMWindow* aOwner,

Просмотреть файл

@ -16,11 +16,15 @@
BEGIN_FILE_NAMESPACE
/**
* This is the ArchiveRequest that handles any operation
* related to ArchiveReader
*/
class ArchiveRequest : public mozilla::dom::DOMRequest,
public nsIDOMArchiveRequest
{
public:
NS_DECL_ISUPPORTS
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIDOMARCHIVEREQUEST
NS_FORWARD_NSIDOMDOMREQUEST(DOMRequest::)
@ -40,6 +44,7 @@ public:
// Set the types for this request
void OpGetFilenames();
void OpGetFile(const nsAString& aFilename);
void OpGetFiles();
nsresult ReaderReady(nsTArray<nsCOMPtr<nsIDOMFile> >& aFileList,
nsresult aStatus);
@ -52,11 +57,14 @@ private:
~ArchiveRequest();
nsresult GetFilenamesResult(JSContext* aCx,
jsval* aValue,
JS::Value* aValue,
nsTArray<nsCOMPtr<nsIDOMFile> >& aFileList);
nsresult GetFileResult(JSContext* aCx,
jsval* aValue,
JS::Value* aValue,
nsTArray<nsCOMPtr<nsIDOMFile> >& aFileList);
nsresult GetFilesResult(JSContext* aCx,
JS::Value* aValue,
nsTArray<nsCOMPtr<nsIDOMFile> >& aFileList);
protected:
// The reader:
@ -65,7 +73,8 @@ protected:
// The operation:
enum {
GetFilenames,
GetFile
GetFile,
GetFiles
} mOperation;
// The filename (needed by GetFile):

Просмотреть файл

@ -8,19 +8,24 @@
#include "ArchiveZipFile.h"
#include "nsContentUtils.h"
#include "nsIPlatformCharset.h"
#include "nsNativeCharsetUtils.h"
#include "nsCExternalHandlerService.h"
using namespace mozilla::dom;
USING_FILE_NAMESPACE
#ifndef PATH_MAX
# define PATH_MAX 65536 // The filename length is stored in 2 bytes
#endif
// ArchiveZipItem
ArchiveZipItem::ArchiveZipItem(const char* aFilename,
ZipCentral& aCentralStruct)
const ZipCentral& aCentralStruct,
const ArchiveReaderOptions& aOptions)
: mFilename(aFilename),
mCentralStruct(aCentralStruct)
mCentralStruct(aCentralStruct),
mOptions(aOptions)
{
MOZ_COUNT_CTOR(ArchiveZipItem);
}
@ -30,25 +35,58 @@ ArchiveZipItem::~ArchiveZipItem()
MOZ_COUNT_DTOR(ArchiveZipItem);
}
// Getter/Setter for the filename
nsCString
ArchiveZipItem::GetFilename()
nsresult
ArchiveZipItem::ConvertFilename()
{
return mFilename;
if (mOptions.encoding.IsEmpty()) {
return NS_ERROR_FAILURE;
}
nsString filenameU;
nsresult rv = nsContentUtils::ConvertStringFromCharset(
NS_ConvertUTF16toUTF8(mOptions.encoding),
mFilename, filenameU);
NS_ENSURE_SUCCESS(rv, rv);
if (filenameU.IsEmpty()) {
return NS_ERROR_FAILURE;
}
mFilenameU = filenameU;
return NS_OK;
}
void
ArchiveZipItem::SetFilename(const nsCString& aFilename)
nsresult
ArchiveZipItem::GetFilename(nsString& aFilename)
{
mFilename = aFilename;
}
if (mFilenameU.IsEmpty()) {
// Maybe this string is UTF-8:
if (IsUTF8(mFilename, false)) {
mFilenameU = NS_ConvertUTF8toUTF16(mFilename);
}
// Let's use the enconding value for the dictionary
else {
nsresult rv = ConvertFilename();
NS_ENSURE_SUCCESS(rv, rv);
}
}
aFilename = mFilenameU;
return NS_OK;
}
// From zipItem to DOMFile:
nsIDOMFile*
ArchiveZipItem::File(ArchiveReader* aArchiveReader)
{
return new ArchiveZipFile(NS_ConvertUTF8toUTF16(mFilename),
nsString filename;
if (NS_FAILED(GetFilename(filename))) {
return nullptr;
}
return new ArchiveZipFile(filename,
NS_ConvertUTF8toUTF16(GetType()),
StrToInt32(mCentralStruct.orglen),
mCentralStruct,
@ -72,8 +110,10 @@ ArchiveZipItem::StrToInt16(const uint8_t* aStr)
// ArchiveReaderZipEvent
ArchiveReaderZipEvent::ArchiveReaderZipEvent(ArchiveReader* aArchiveReader)
: ArchiveReaderEvent(aArchiveReader)
ArchiveReaderZipEvent::ArchiveReaderZipEvent(ArchiveReader* aArchiveReader,
const ArchiveReaderOptions& aOptions)
: ArchiveReaderEvent(aArchiveReader),
mOptions(aOptions)
{
}
@ -104,8 +144,7 @@ ArchiveReaderZipEvent::Exec()
}
// Reading backward.. looking for the ZipEnd signature
for (uint64_t curr = size - ZIPEND_SIZE; curr > 4; --curr)
{
for (uint64_t curr = size - ZIPEND_SIZE; curr > 4; --curr) {
seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, curr);
uint8_t buffer[ZIPEND_SIZE];
@ -162,7 +201,7 @@ ArchiveReaderZipEvent::Exec()
// We ignore the directories:
if (filename[filenameLen - 1] != '/') {
mFileList.AppendElement(new ArchiveZipItem(filename, centralStruct));
mFileList.AppendElement(new ArchiveZipItem(filename, centralStruct, mOptions));
}
PR_Free(filename);

Просмотреть файл

@ -12,17 +12,22 @@
#include "FileCommon.h"
#include "zipstruct.h"
#include "DictionaryHelpers.h"
BEGIN_FILE_NAMESPACE
/**
* ArchiveZipItem - ArchiveItem for ArchiveReaderZipEvent
*/
class ArchiveZipItem : public ArchiveItem
{
public:
ArchiveZipItem(const char* aFilename,
ZipCentral& aCentralStruct);
const ZipCentral& aCentralStruct,
const ArchiveReaderOptions& aOptions);
virtual ~ArchiveZipItem();
void SetFilename(const nsCString& aFilename);
nsCString GetFilename();
nsresult GetFilename(nsString& aFilename);
// From zipItem to DOMFile:
virtual nsIDOMFile* File(ArchiveReader* aArchiveReader);
@ -31,17 +36,31 @@ public: // for the event
static uint32_t StrToInt32(const uint8_t* aStr);
static uint16_t StrToInt16(const uint8_t* aStr);
private:
nsresult ConvertFilename();
private: // data
nsCString mFilename;
nsString mFilenameU;
ZipCentral mCentralStruct;
ArchiveReaderOptions mOptions;
};
/**
* ArchiveReaderEvent implements the ArchiveReaderEvent for the ZIP format
*/
class ArchiveReaderZipEvent : public ArchiveReaderEvent
{
public:
ArchiveReaderZipEvent(ArchiveReader* aArchiveReader);
ArchiveReaderZipEvent(ArchiveReader* aArchiveReader,
const ArchiveReaderOptions& aOptions);
nsresult Exec();
private:
ArchiveReaderOptions mOptions;
};
END_FILE_NAMESPACE

Просмотреть файл

@ -15,8 +15,9 @@ USING_FILE_NAMESPACE
#define ZIP_CHUNK 16384
// a internat input stream object
/**
* Input stream object for zip files
*/
class ArchiveInputStream MOZ_FINAL : public nsIInputStream,
public nsISeekableStream
{
@ -92,22 +93,25 @@ ArchiveInputStream::Init()
memset(&mZs, 0, sizeof(z_stream));
int zerr = inflateInit2(&mZs, -MAX_WBITS);
if (zerr != Z_OK)
if (zerr != Z_OK) {
return NS_ERROR_OUT_OF_MEMORY;
}
mData.sizeToBeRead = ArchiveZipItem::StrToInt32(mCentral.size);
uint32_t offset = ArchiveZipItem::StrToInt32(mCentral.localhdr_offset);
// The file is corrupt
if (offset + ZIPLOCAL_SIZE > mData.parentSize)
if (offset + ZIPLOCAL_SIZE > mData.parentSize) {
return NS_ERROR_UNEXPECTED;
}
// From the input stream to a seekable stream
nsCOMPtr<nsISeekableStream> seekableStream;
seekableStream = do_QueryInterface(mData.inputStream);
if (!seekableStream)
if (!seekableStream) {
return NS_ERROR_UNEXPECTED;
}
// Seek + read the ZipLocal struct
seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, offset);
@ -115,12 +119,14 @@ ArchiveInputStream::Init()
uint32_t ret;
rv = mData.inputStream->Read((char*)buffer, ZIPLOCAL_SIZE, &ret);
if (NS_FAILED(rv) || ret != ZIPLOCAL_SIZE)
if (NS_FAILED(rv) || ret != ZIPLOCAL_SIZE) {
return NS_ERROR_UNEXPECTED;
}
// Signature check:
if (ArchiveZipItem::StrToInt32(buffer) != LOCALSIG)
if (ArchiveZipItem::StrToInt32(buffer) != LOCALSIG) {
return NS_ERROR_UNEXPECTED;
}
ZipLocal local;
memcpy(&local, buffer, ZIPLOCAL_SIZE);
@ -131,8 +137,9 @@ ArchiveInputStream::Init()
ArchiveZipItem::StrToInt16(local.extrafield_len);
// The file is corrupt if there is not enough data
if (offset + mData.sizeToBeRead > mData.parentSize)
if (offset + mData.sizeToBeRead > mData.parentSize) {
return NS_ERROR_UNEXPECTED;
}
// Data starts here:
seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, offset);
@ -182,8 +189,9 @@ ArchiveInputStream::Read(char* aBuffer,
mStatus = Started;
rv = Init();
if (NS_FAILED(rv))
if (NS_FAILED(rv)) {
return rv;
}
// Let's set avail_out to -1 so we read something from the stream.
mZs.avail_out = (uInt)-1;
@ -196,8 +204,7 @@ ArchiveInputStream::Read(char* aBuffer,
}
// Stored file:
if (!mData.compressed)
{
if (!mData.compressed) {
rv = mData.inputStream->Read(aBuffer,
(mData.sizeToBeRead > aCount ?
aCount : mData.sizeToBeRead),
@ -206,23 +213,24 @@ ArchiveInputStream::Read(char* aBuffer,
mData.sizeToBeRead -= *_retval;
mData.cursor += *_retval;
if (mData.sizeToBeRead == 0)
if (mData.sizeToBeRead == 0) {
mStatus = Done;
}
}
return rv;
}
// We have nothing ready to be processed:
if (mZs.avail_out != 0 && mData.sizeToBeRead != 0)
{
if (mZs.avail_out != 0 && mData.sizeToBeRead != 0) {
uint32_t ret;
rv = mData.inputStream->Read((char*)mData.input,
(mData.sizeToBeRead > sizeof(mData.input) ?
sizeof(mData.input) : mData.sizeToBeRead),
&ret);
if (NS_FAILED(rv))
if (NS_FAILED(rv)) {
return rv;
}
// Terminator:
if (ret == 0) {
@ -239,11 +247,13 @@ ArchiveInputStream::Read(char* aBuffer,
mZs.next_out = (unsigned char*)aBuffer;
int ret = inflate(&mZs, mData.sizeToBeRead ? Z_NO_FLUSH : Z_FINISH);
if (ret != Z_BUF_ERROR && ret != Z_OK && ret != Z_STREAM_END)
if (ret != Z_BUF_ERROR && ret != Z_OK && ret != Z_STREAM_END) {
return NS_ERROR_UNEXPECTED;
}
if (ret == Z_STREAM_END)
if (ret == Z_STREAM_END) {
mStatus = Done;
}
*_retval = aCount - mZs.avail_out;
mData.cursor += *_retval;
@ -291,11 +301,13 @@ ArchiveInputStream::Seek(int32_t aWhence, int64_t aOffset)
return NS_ERROR_UNEXPECTED;
}
if (pos == int64_t(mData.cursor))
if (pos == int64_t(mData.cursor)) {
return NS_OK;
}
if (pos < 0 || pos >= mLength)
if (pos < 0 || pos >= mLength) {
return NS_ERROR_FAILURE;
}
// We have to terminate the previous operation:
nsresult rv;
@ -312,11 +324,13 @@ ArchiveInputStream::Seek(int32_t aWhence, int64_t aOffset)
char buffer[1024];
while (pos > 0) {
rv = Read(buffer, pos > int64_t(sizeof(buffer)) ? sizeof(buffer) : pos, &ret);
if (NS_FAILED(rv))
if (NS_FAILED(rv)) {
return rv;
}
if (ret == 0)
if (ret == 0) {
return NS_ERROR_UNEXPECTED;
}
pos -= ret;
}
@ -342,8 +356,9 @@ ArchiveInputStream::SetEOF()
NS_IMETHODIMP
ArchiveZipFile::GetInternalStream(nsIInputStream** aStream)
{
if (mLength > INT32_MAX)
if (mLength > INT32_MAX) {
return NS_ERROR_FAILURE;
}
uint64_t size;
nsresult rv = mArchiveReader->GetSize(&size);
@ -351,8 +366,9 @@ ArchiveZipFile::GetInternalStream(nsIInputStream** aStream)
nsCOMPtr<nsIInputStream> inputStream;
rv = mArchiveReader->GetInputStream(getter_AddRefs(inputStream));
if (NS_FAILED(rv) || !inputStream)
if (NS_FAILED(rv) || !inputStream) {
return NS_ERROR_UNEXPECTED;
}
nsRefPtr<ArchiveInputStream> stream = new ArchiveInputStream(size,
inputStream,

Просмотреть файл

@ -16,6 +16,9 @@
BEGIN_FILE_NAMESPACE
/**
* ZipFile to DOMFileCC
*/
class ArchiveZipFile : public nsDOMFileCC
{
public:

Просмотреть файл

@ -12,6 +12,15 @@ interface nsIDOMArchiveReader : nsISupports
{
nsIDOMArchiveRequest getFilenames();
nsIDOMArchiveRequest getFile(in DOMString filename);
nsIDOMArchiveRequest getFiles();
};
/* This dictionary is the optional argument for the
* ArchiveReader constructor:
* var a = new ArchiveReader(blob, { encoding: "iso-8859-1" }); */
dictionary ArchiveReaderOptions
{
DOMString encoding = "windows-1252"; // Default fallback encoding
};
%{ C++

Просмотреть файл

@ -31,6 +31,7 @@ MOCHITEST_FILES = \
test_workers.html \
test_archivereader.html \
test_archivereader_zip_in_zip.html \
test_archivereader_nonUnicode.html \
test_bug_793311.html \
$(NULL)

Просмотреть файл

@ -62,7 +62,7 @@
}
}
function isFinished() {
return handleFinished == 5;
return handleFinished == 6;
}
function testSteps()
@ -232,6 +232,25 @@
ok(false, "ArchiveReader.getFile('test/a.txt') should not return an 'error'");
markTestDone();
}
var handle5 = r.getFiles();
isnot(handle5, null, "ArchiveReader.getFiles() cannot be null");
handle5.onsuccess = function() {
ok(true, "ArchiveReader.getFiles() should return a 'success'");
ok(this.reader, r, "ArchiveRequest.reader should be == ArchiveReader");
is(this.result.length, 2, "ArchiveReader.getFilenames(): the array contains 2 items");
is(this.result[0].name, "test/a.txt", "ArchiveReader.getFilenames(): first file is 'test/a.txt'");
is(this.result[1].name, "test/b.txt", "ArchiveReader.getFilenames(): second file is 'test/b.txt'");
is(this.result[0].type, "text/plain", "ArchiveReader.getFile('test/a.txt') the type MUST be 'text/plain'");
is(this.result[1].type, "text/plain", "ArchiveReader.getFile('test/a.txt') the type MUST be 'text/plain'");
markTestDone();
}
handle5.onerror = function() {
ok(false, "ArchiveReader.getFiles() should not return an 'error'");
markTestDone();
}
}
SimpleTest.waitForExplicitFinish();

Просмотреть файл

@ -0,0 +1,104 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>Archive Reader Non-Unicode Test</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;version=1.7">
function createNonUnicodeData() {
const Cc = SpecialPowers.wrap(Components).classes;
const Ci = SpecialPowers.wrap(Components).interfaces;
var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
var testFile = dirSvc.get("ProfD", Ci.nsIFile);
testFile.append("fileArchiveReader_nonUnicode.zip");
var outStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
0666, 0);
var binaryData = "";
for (var i = 0, len = binaryString.length / 2; i < len; ++i) {
var hex = binaryString[i * 2] + binaryString[i * 2 + 1];
binaryData += String.fromCharCode(parseInt(hex,16));
}
outStream.write(binaryData, binaryData.length);
outStream.close();
var fileList = document.getElementById('fileList');
SpecialPowers.wrap(fileList).value = testFile.path;
return fileList.files[0];
}
function test1()
{
var binaryFile = createNonUnicodeData();
var r = new ArchiveReader(binaryFile, { encoding: "ISO-8859-1" });
isnot(r, null, "ArchiveReader cannot be null");
// GetFilename
var handle = r.getFilenames();
isnot(handle, null, "ArchiveReader.getFilenames() cannot be null");
handle.onsuccess = function() {
ok(true, "ArchiveReader.getFilenames() should return a 'success'");
is(this.result instanceof Array, true, "ArchiveReader.getFilenames() should return an array");
is(this.result.length, 1, "ArchiveReader.getFilenames(): the array contains 1 item");
ok(this.reader, r, "ArchiveRequest.reader should be == ArchiveReader");
dump('Content: ' + this.result[0] + '\n');
test2();
}
}
function test2()
{
var binaryFile = createNonUnicodeData();
var r = new ArchiveReader(binaryFile, { encoding: "random stuff" });
isnot(r, null, "ArchiveReader cannot be null");
// GetFilename
var handle = r.getFilenames();
isnot(handle, null, "ArchiveReader.getFilenames() cannot be null");
handle.onsuccess = function() {
ok(true, "ArchiveReader.getFilenames() should return a 'success'");
is(this.result instanceof Array, true, "ArchiveReader.getFilenames() should return an array");
is(this.result.length, 0, "ArchiveReader.getFilenames(): the array contains 0 item");
ok(this.reader, r, "ArchiveRequest.reader should be == ArchiveReader");
finishTest();
}
}
function testSteps()
{
test1();
yield;
}
</script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>
<body onload="runTest();">
<p id="display">
<input id="fileList" type="file"></input>
</p>
<script type="text/javascript;version=1.7">
var binaryString = '' +
'504B0304140000000000255D094100000000000000000000000002000000912F504B03040A0000000000285D09416BB50A5A' +
'010000000100000007000000912F9B2E747874D8504B01023F00140000000000255D09410000000000000000000000000200' +
'24000000000000001000000000000000912F0A002000000000000100180062505F1A1376CD0162505F1A1376CD01FE3F8D59' +
'1176CD01504B01023F000A0000000000285D09416BB50A5A0100000001000000070024000000000000002000000020000000' +
'912F9B2E7478740A0020000000000001001800565EF41D1376CD0107BD73631176CD0107BD73631176CD01504B0506000000' +
'0002000200AD000000460000000000';
</script>
</body>
</html>

Просмотреть файл

@ -30,7 +30,7 @@ interface nsIDOMTextMetrics : nsISupports
readonly attribute float width;
};
[scriptable, uuid(c835c768-2dcc-461c-82f5-3653710d2942)]
[scriptable, uuid(438fe14d-6501-40ab-b6c2-130fa38bd2c9)]
interface nsIDOMCanvasRenderingContext2D : nsISupports
{
// back-reference to the canvas element for which
@ -166,6 +166,7 @@ enum CanvasMultiGetterType {
// point-membership test
boolean isPointInPath(in float x, in float y);
boolean mozIsPointInStroke(in float x, in float y);
// pixel manipulation
// ImageData getImageData (in float x, in float y, in float width, in float height);

Просмотреть файл

@ -4,12 +4,6 @@
<title>Test for Power API</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Power API **/
@ -17,18 +11,42 @@
ok('mozPower' in navigator, "navigator.mozPower should exist");
/** Test permission **/
// In b2g, addPermission 'power' is only working after a document reload
// See bug 802312
SpecialPowers.removePermission("power", document);
SimpleTest.waitForExplicitFinish();
power = navigator.mozPower;
ok(!power, "Shouldn't be able to access power manager without permission.");
function startTest() {
window.frames[0].frameElement.setAttribute('onload', 'doTest2()');
power = window.frames[0].navigator.mozPower;
ok(!power, "Shouldn't be able to access power manager without permission.");
SpecialPowers.addPermission("power", true, document);
SpecialPowers.addPermission("power", true, window.frames[0].document);
window.frames[0].location.reload();
}
power = navigator.mozPower;
ok(power, "Shouldn be able to access power manager with permission.");
function doTest2() {
window.frames[0].frameElement.setAttribute('onload', 'doTest3()');
power = window.frames[0].navigator.mozPower;
ok(power, "Should be able to access power manager with permission.");
SpecialPowers.removePermission("power", window.frames[0].document);
window.frames[0].location.reload();
}
function doTest3() {
power = window.frames[0].navigator.mozPower;
ok(!power, "Shouldn't be able to access power manager without permission.");
SimpleTest.finish();
}
</script>
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<iframe onload="startTest()"></iframe>
<pre id="test">
</pre>
</body>
</html>

Просмотреть файл

@ -13,7 +13,7 @@
* limitations under the License.
*/
#include <android/log.h>
#include <android/log.h>
#include "mozilla/Hal.h"
#include "AudioManager.h"
@ -26,7 +26,7 @@ using namespace android;
using namespace mozilla::hal;
using namespace mozilla;
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "AudioManager" , ## args)
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "AudioManager" , ## args)
#define HEADPHONES_STATUS_CHANGED "headphones-status-changed"
#define HEADPHONES_STATUS_ON NS_LITERAL_STRING("on").get()
@ -34,6 +34,21 @@ using namespace mozilla;
#define HEADPHONES_STATUS_UNKNOWN NS_LITERAL_STRING("unknown").get()
#define BLUETOOTH_SCO_STATUS_CHANGED "bluetooth-sco-status-changed"
// Refer AudioService.java from Android
static int sMaxStreamVolumeTbl[AUDIO_STREAM_CNT] = {
10, // voice call
10, // system
7, // ring
15, // music
7, // alarm
7, // notification
15, // BT SCO
7, // enforced audible
15, // DTMF
15, // TTS
10, // FM
};
// A bitwise variable for recording what kind of headset is attached.
static int sHeadsetState;
static int kBtSampleRate = 8000;
@ -44,7 +59,7 @@ IsFmRadioAudioOn()
if (static_cast<
audio_policy_dev_state_t (*) (audio_devices_t, const char *)
>(AudioSystem::getDeviceConnectionState)) {
return AudioSystem::getDeviceConnectionState(AUDIO_DEVICE_OUT_FM, "") ==
return AudioSystem::getDeviceConnectionState(AUDIO_DEVICE_OUT_FM, "") ==
AUDIO_POLICY_DEVICE_STATE_AVAILABLE ? true : false;
} else {
return false;
@ -187,6 +202,11 @@ AudioManager::AudioManager() : mPhoneState(PHONE_STATE_CURRENT),
if (NS_FAILED(obs->AddObserver(this, BLUETOOTH_SCO_STATUS_CHANGED, false))) {
NS_WARNING("Failed to add bluetooth-sco-status-changed oberver!");
}
for (int loop = 0; loop < AUDIO_STREAM_CNT; loop++) {
AudioSystem::initStreamVolume(static_cast<audio_stream_type_t>(loop), 0,
sMaxStreamVolumeTbl[loop]);
}
}
AudioManager::~AudioManager() {
@ -338,7 +358,7 @@ AudioManager::SetFmRadioAudioEnabled(bool aFmRadioAudioEnabled)
status_t (*) (AudioSystem::audio_devices, AudioSystem::device_connection_state, const char *)
>(AudioSystem::setDeviceConnectionState)) {
AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_FM,
aFmRadioAudioEnabled ? AUDIO_POLICY_DEVICE_STATE_AVAILABLE :
aFmRadioAudioEnabled ? AUDIO_POLICY_DEVICE_STATE_AVAILABLE :
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, "");
InternalSetAudioRoutes(GetCurrentSwitchState(SWITCH_HEADPHONES));
return NS_OK;
@ -346,3 +366,24 @@ AudioManager::SetFmRadioAudioEnabled(bool aFmRadioAudioEnabled)
return NS_ERROR_NOT_IMPLEMENTED;
}
}
NS_IMETHODIMP
AudioManager::SetStreamVolumeIndex(int32_t aStream, int32_t aIndex) {
status_t status =
AudioSystem::setStreamVolumeIndex(static_cast<audio_stream_type_t>(aStream), aIndex);
return status ? NS_ERROR_FAILURE : NS_OK;
}
NS_IMETHODIMP
AudioManager::GetStreamVolumeIndex(int32_t aStream, int32_t* aIndex) {
status_t status =
AudioSystem::getStreamVolumeIndex(static_cast<audio_stream_type_t>(aStream), aIndex);
return status ? NS_ERROR_FAILURE : NS_OK;
}
NS_IMETHODIMP
AudioManager::GetMaxStreamVolumeIndex(int32_t aStream, int32_t* aMaxIndex) {
*aMaxIndex = sMaxStreamVolumeTbl[aStream];
return NS_OK;
}

Просмотреть файл

@ -4,7 +4,7 @@
#include "nsISupports.idl"
[scriptable, builtinclass, uuid(d2124467-7209-4b2e-a91a-cf3f90681e3c)]
[scriptable, builtinclass, uuid(b76a3de4-79f4-4cbb-a0e2-871095eacb2c)]
interface nsIAudioManager : nsISupports
{
/**
@ -59,4 +59,23 @@ interface nsIAudioManager : nsISupports
void setForceForUse(in long usage, in long force);
long getForceForUse(in long usage);
/**
* Control the volume of various audio streams
*/
const long STREAM_TYPE_VOICE_CALL = 0;
const long STREAM_TYPE_SYSTEM = 1;
const long STREAM_TYPE_RING = 2;
const long STREAM_TYPE_MUSIC = 3;
const long STREAM_TYPE_ALARM = 4;
const long STREAM_TYPE_NOTIFICATION = 5;
const long STREAM_TYPE_BLUETOOTH_SCO = 6;
const long STREAM_TYPE_ENFORCED_AUDIBLE = 7;
const long STREAM_TYPE_DTMF = 8;
const long STREAM_TYPE_TTS = 9;
const long STREAM_TYPE_FM = 10;
void setStreamVolumeIndex(in long stream, in long index);
long getStreamVolumeIndex(in long stream);
long getMaxStreamVolumeIndex(in long stream);
};

Просмотреть файл

@ -144,6 +144,8 @@ interface CanvasRenderingContext2D {
// if scaled.
attribute boolean mozImageSmoothingEnabled;
boolean mozIsPointInStroke(double x, double y);
// Show the caret if appropriate when drawing
[ChromeOnly]
const unsigned long DRAWWINDOW_DRAW_CARET = 0x01;

Просмотреть файл

@ -398,6 +398,15 @@ public:
*/
virtual bool ContainsPoint(const Point &aPoint, const Matrix &aTransform) const = 0;
/* This function checks if a point lies within the stroke of a path using the
* specified strokeoptions. It allows passing a transform that will transform
* the path to the coordinate space in which aPoint is given.
*/
virtual bool StrokeContainsPoint(const StrokeOptions &aStrokeOptions,
const Point &aPoint,
const Matrix &aTransform) const = 0;
/* This functions gets the bounds of this path. These bounds are not
* guaranteed to be tight. A transform may be specified that gives the bounds
* after application of the transform.

Просмотреть файл

@ -198,6 +198,34 @@ ScratchContext()
return cg;
}
bool
PathCG::StrokeContainsPoint(const StrokeOptions &aStrokeOptions,
const Point &aPoint,
const Matrix &aTransform) const
{
Matrix inverse = aTransform;
inverse.Invert();
Point transformedPoint = inverse*aPoint;
// We could probably drop the input transform and just transform the point at the caller?
CGPoint point = {transformedPoint.x, transformedPoint.y};
CGContextRef cg = ScratchContext();
CGContextSaveGState(cg);
CGContextBeginPath(cg);
CGContextAddPath(cg, mPath);
SetStrokeOptions(cg, aStrokeOptions);
CGContextReplacePathWithStrokedPath(cg);
CGContextRestoreGState(cg);
CGPathRef sPath = CGContextCopyPath(cg);
return CGPathContainsPoint(sPath, nullptr, point, false);
}
//XXX: what should these functions return for an empty path?
// currently they return CGRectNull {inf,inf, 0, 0}
Rect

Просмотреть файл

@ -77,6 +77,9 @@ public:
FillRule aFillRule = FILL_WINDING) const;
virtual bool ContainsPoint(const Point &aPoint, const Matrix &aTransform) const;
virtual bool StrokeContainsPoint(const StrokeOptions &aStrokeOptions,
const Point &aPoint,
const Matrix &aTransform) const;
virtual Rect GetBounds(const Matrix &aTransform = Matrix()) const;
virtual Rect GetStrokedBounds(const StrokeOptions &aStrokeOptions,
const Matrix &aTransform = Matrix()) const;

Просмотреть файл

@ -263,6 +263,21 @@ PathCairo::ContainsPoint(const Point &aPoint, const Matrix &aTransform) const
return cairo_in_fill(*mPathContext, transformed.x, transformed.y);
}
bool
PathCairo::StrokeContainsPoint(const StrokeOptions &aStrokeOptions,
const Point &aPoint,
const Matrix &aTransform) const
{
CairoTempMatrix(*mPathContext, mTransform);
Matrix inverse = aTransform;
inverse.Invert();
Point transformed = inverse * aPoint;
SetCairoStrokeOptions(*mPathContext, aStrokeOptions);
return cairo_in_stroke(*mPathContext, transformed.x, transformed.y);
}
Rect
PathCairo::GetBounds(const Matrix &aTransform) const
{

Просмотреть файл

@ -125,6 +125,10 @@ public:
virtual bool ContainsPoint(const Point &aPoint, const Matrix &aTransform) const;
virtual bool StrokeContainsPoint(const StrokeOptions &aStrokeOptions,
const Point &aPoint,
const Matrix &aTransform) const;
virtual Rect GetBounds(const Matrix &aTransform = Matrix()) const;
virtual Rect GetStrokedBounds(const StrokeOptions &aStrokeOptions,

Просмотреть файл

@ -307,6 +307,29 @@ PathD2D::ContainsPoint(const Point &aPoint, const Matrix &aTransform) const
return !!result;
}
bool
PathD2D::StrokeContainsPoint(const StrokeOptions &aStrokeOptions,
const Point &aPoint,
const Matrix &aTransform) const
{
BOOL result;
RefPtr<ID2D1StrokeStyle> strokeStyle =
DrawTargetD2D::CreateStrokeStyleForOptions(aStrokeOptions);
HRESULT hr = mGeometry->StrokeContainsPoint(D2DPoint(aPoint),
aStrokeOptions.mLineWidth,
strokeStyle,
D2DMatrix(aTransform),
&result);
if (FAILED(hr)) {
// Log
return false;
}
return !!result;
}
Rect
PathD2D::GetBounds(const Matrix &aTransform) const
{

Просмотреть файл

@ -75,6 +75,10 @@ public:
virtual bool ContainsPoint(const Point &aPoint, const Matrix &aTransform) const;
virtual bool StrokeContainsPoint(const StrokeOptions &aStrokeOptions,
const Point &aPoint,
const Matrix &aTransform) const;
virtual Rect GetBounds(const Matrix &aTransform = Matrix()) const;
virtual Rect GetStrokedBounds(const StrokeOptions &aStrokeOptions,

Просмотреть файл

@ -96,6 +96,10 @@ public:
FillRule aFillRule = FILL_WINDING) const;
virtual bool ContainsPoint(const Point &aPoint, const Matrix &aTransform) const
{ return mPath->ContainsPoint(aPoint, aTransform); }
virtual bool StrokeContainsPoint(const StrokeOptions &aStrokeOptions,
const Point &aPoint,
const Matrix &aTransform) const
{ return mPath->StrokeContainsPoint(aStrokeOptions, aPoint, aTransform); }
virtual Rect GetBounds(const Matrix &aTransform = Matrix()) const
{ return mPath->GetBounds(aTransform); }

Просмотреть файл

@ -148,6 +148,32 @@ static Rect SkRectToRect(const SkRect& aBounds)
SkScalarToFloat(aBounds.fBottom - aBounds.fTop));
}
bool
PathSkia::StrokeContainsPoint(const StrokeOptions &aStrokeOptions,
const Point &aPoint,
const Matrix &aTransform) const
{
Matrix inverse = aTransform;
inverse.Invert();
Point transformed = inverse * aPoint;
SkPaint paint;
StrokeOptionsToPaint(paint, aStrokeOptions);
SkPath strokePath;
paint.getFillPath(mPath, &strokePath);
Rect bounds = aTransform.TransformBounds(SkRectToRect(strokePath.getBounds()));
if (aPoint.x < bounds.x || aPoint.y < bounds.y ||
aPoint.x > bounds.XMost() || aPoint.y > bounds.YMost()) {
return false;
}
return strokePath.contains(SkFloatToScalar(transformed.x),
SkFloatToScalar(transformed.y));
}
Rect
PathSkia::GetBounds(const Matrix &aTransform) const
{

Просмотреть файл

@ -57,6 +57,10 @@ public:
virtual bool ContainsPoint(const Point &aPoint, const Matrix &aTransform) const;
virtual bool StrokeContainsPoint(const StrokeOptions &aStrokeOptions,
const Point &aPoint,
const Matrix &aTransform) const;
virtual Rect GetBounds(const Matrix &aTransform = Matrix()) const;
virtual Rect GetStrokedBounds(const StrokeOptions &aStrokeOptions,

Просмотреть файл

@ -625,21 +625,34 @@ GLContext::CanUploadSubTextures()
return true;
}
bool GLContext::sPowerOfTwoForced = false;
bool GLContext::sPowerOfTwoPrefCached = false;
void
GLContext::PlatformStartup()
{
CacheCanUploadNPOT();
}
void
GLContext::CacheCanUploadNPOT()
{
MOZ_ASSERT(NS_IsMainThread(), "Can't cache prefs off the main thread.");
MOZ_ASSERT(!sPowerOfTwoPrefCached, "Must only call this function once!");
sPowerOfTwoPrefCached = true;
mozilla::Preferences::AddBoolVarCache(&sPowerOfTwoForced,
"gfx.textures.poweroftwo.force-enabled");
}
bool
GLContext::CanUploadNonPowerOfTwo()
{
MOZ_ASSERT(sPowerOfTwoPrefCached);
if (!mWorkAroundDriverBugs)
return true;
static bool sPowerOfTwoForced;
static bool sPowerOfTwoPrefCached = false;
if (!sPowerOfTwoPrefCached) {
sPowerOfTwoPrefCached = true;
mozilla::Preferences::AddBoolVarCache(&sPowerOfTwoForced,
"gfx.textures.poweroftwo.force-enabled");
}
// Some GPUs driver crash when uploading non power of two 565 textures.
return sPowerOfTwoForced ? false : (Renderer() != RendererAdreno200 &&
Renderer() != RendererAdreno205);

Просмотреть файл

@ -744,7 +744,17 @@ public:
}
bool CanUploadSubTextures();
static void PlatformStartup();
protected:
static bool sPowerOfTwoForced;
static bool sPowerOfTwoPrefCached;
static void CacheCanUploadNPOT();
public:
bool CanUploadNonPowerOfTwo();
bool WantsSmallTiles();
virtual bool HasLockSurface() { return false; }

Просмотреть файл

@ -537,9 +537,13 @@ BasicLayerManager::EndTransactionInternal(DrawThebesLayerCallback aCallback,
mTransactionIncomplete = false;
if (aFlags & END_NO_COMPOSITE) {
// TODO: We should really just set mTarget to null and make sure we can handle that further down the call chain
nsRefPtr<gfxASurface> surf = gfxPlatform::GetPlatform()->CreateOffscreenSurface(gfxIntSize(1, 1), gfxASurface::CONTENT_COLOR);
mTarget = new gfxContext(surf);
if (!mDummyTarget) {
// TODO: We should really just set mTarget to null and make sure we can handle that further down the call chain
// Creating this temporary surface can be expensive on some platforms (d2d in particular), so cache it between paints.
nsRefPtr<gfxASurface> surf = gfxPlatform::GetPlatform()->CreateOffscreenSurface(gfxIntSize(1, 1), gfxASurface::CONTENT_COLOR);
mDummyTarget = new gfxContext(surf);
}
mTarget = mDummyTarget;
}
if (mTarget && mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) {

Просмотреть файл

@ -1614,8 +1614,9 @@ gfxContext::PointInStroke(const gfxPoint& pt)
if (mCairo) {
return cairo_in_stroke(mCairo, pt.x, pt.y);
} else {
// XXX - Used by SVG, needs fixing.
return false;
return mPath->StrokeContainsPoint(CurrentState().strokeOptions,
ToPoint(pt),
mTransform);
}
}

Просмотреть файл

@ -258,16 +258,16 @@ gfxPlatform::Init()
bool useOffMainThreadCompositing = false;
#ifdef MOZ_X11
// On X11 platforms only use OMTC if firefox was initalized with thread-safe
// On X11 platforms only use OMTC if firefox was initalized with thread-safe
// X11 (else it would crash).
useOffMainThreadCompositing = (PR_GetEnv("MOZ_USE_OMTC") != NULL);
#else
useOffMainThreadCompositing = Preferences::GetBool(
"layers.offmainthreadcomposition.enabled",
"layers.offmainthreadcomposition.enabled",
false);
#endif
if (useOffMainThreadCompositing && (XRE_GetProcessType() ==
if (useOffMainThreadCompositing && (XRE_GetProcessType() ==
GeckoProcessType_Default)) {
CompositorParent::StartUp();
if (Preferences::GetBool("layers.async-video.enabled",false)) {
@ -340,6 +340,8 @@ gfxPlatform::Init()
gPlatform->mWorkAroundDriverBugs = Preferences::GetBool("gfx.work-around-driver-bugs", true);
mozilla::gl::GLContext::PlatformStartup();
#ifdef MOZ_WIDGET_ANDROID
// Texture pool init
mozilla::gl::TexturePoolOGL::Init();
@ -440,7 +442,7 @@ gfxPlatform::~gfxPlatform()
already_AddRefed<gfxASurface>
gfxPlatform::CreateOffscreenImageSurface(const gfxIntSize& aSize,
gfxASurface::gfxContentType aContentType)
{
{
nsRefPtr<gfxASurface> newSurface;
newSurface = new gfxImageSurface(aSize, OptimalFormatForContent(aContentType));
@ -454,7 +456,7 @@ gfxPlatform::OptimizeImage(gfxImageSurface *aSurface,
const gfxIntSize& surfaceSize = aSurface->GetSize();
#ifdef XP_WIN
if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() ==
if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() ==
gfxWindowsPlatform::RENDER_DIRECT2D) {
return nullptr;
}
@ -871,7 +873,7 @@ AppendGenericFontFromPref(nsString& aFonts, nsIAtom *aLangGroup, const char *aGe
genericDotLang.AppendLiteral(".");
genericDotLang.Append(langGroupString);
// fetch font.name.xxx value
// fetch font.name.xxx value
prefName.AssignLiteral("font.name.");
prefName.Append(genericDotLang);
nsAdoptingString nameValue = Preferences::GetString(prefName.get());
@ -881,7 +883,7 @@ AppendGenericFontFromPref(nsString& aFonts, nsIAtom *aLangGroup, const char *aGe
aFonts += nameValue;
}
// fetch font.name-list.xxx value
// fetch font.name-list.xxx value
prefName.AssignLiteral("font.name-list.");
prefName.Append(genericDotLang);
nsAdoptingString nameListValue = Preferences::GetString(prefName.get());
@ -911,17 +913,17 @@ bool gfxPlatform::ForEachPrefFont(eFontPrefLang aLangArray[], uint32_t aLangArra
for (i = 0; i < aLangArrayLen; i++) {
eFontPrefLang prefLang = aLangArray[i];
const char *langGroup = GetPrefLangName(prefLang);
nsAutoCString prefName;
prefName.AssignLiteral("font.default.");
prefName.Append(langGroup);
nsAdoptingCString genericDotLang = Preferences::GetCString(prefName.get());
genericDotLang.AppendLiteral(".");
genericDotLang.Append(langGroup);
// fetch font.name.xxx value
// fetch font.name.xxx value
prefName.AssignLiteral("font.name.");
prefName.Append(genericDotLang);
nsAdoptingCString nameValue = Preferences::GetCString(prefName.get());
@ -929,8 +931,8 @@ bool gfxPlatform::ForEachPrefFont(eFontPrefLang aLangArray[], uint32_t aLangArra
if (!aCallback(prefLang, NS_ConvertUTF8toUTF16(nameValue), aClosure))
return false;
}
// fetch font.name-list.xxx value
// fetch font.name-list.xxx value
prefName.AssignLiteral("font.name-list.");
prefName.Append(genericDotLang);
nsAdoptingCString nameListValue = Preferences::GetCString(prefName.get());
@ -1029,7 +1031,7 @@ gfxPlatform::GetFontPrefLangFor(uint8_t aUnicodeRange)
}
}
bool
bool
gfxPlatform::IsLangCJK(eFontPrefLang aLang)
{
switch (aLang) {
@ -1045,7 +1047,7 @@ gfxPlatform::IsLangCJK(eFontPrefLang aLang)
}
}
void
void
gfxPlatform::GetLangPrefs(eFontPrefLang aPrefLangs[], uint32_t &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang)
{
if (IsLangCJK(aCharLang)) {
@ -1064,14 +1066,14 @@ gfxPlatform::AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], uint32_t &aLen, eFon
if (IsLangCJK(aPageLang)) {
AppendPrefLang(aPrefLangs, aLen, aPageLang);
}
// if not set up, set up the default CJK order, based on accept lang settings and locale
if (mCJKPrefLangs.Length() == 0) {
// temp array
eFontPrefLang tempPrefLangs[kMaxLenPrefLangList];
uint32_t tempLen = 0;
// Add the CJK pref fonts from accept languages, the order should be same order
nsAdoptingCString list = Preferences::GetLocalizedCString("intl.accept_languages");
if (!list.IsEmpty()) {
@ -1148,34 +1150,34 @@ gfxPlatform::AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], uint32_t &aLen, eFon
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
// copy into the cached array
uint32_t j;
for (j = 0; j < tempLen; j++) {
mCJKPrefLangs.AppendElement(tempPrefLangs[j]);
}
}
// append in cached CJK langs
uint32_t i, numCJKlangs = mCJKPrefLangs.Length();
for (i = 0; i < numCJKlangs; i++) {
AppendPrefLang(aPrefLangs, aLen, (eFontPrefLang) (mCJKPrefLangs[i]));
}
}
void
void
gfxPlatform::AppendPrefLang(eFontPrefLang aPrefLangs[], uint32_t& aLen, eFontPrefLang aAddLang)
{
if (aLen >= kMaxLenPrefLangList) return;
// make sure
uint32_t i = 0;
while (i < aLen && aPrefLangs[i] != aAddLang) {
i++;
}
if (i == aLen) {
aPrefLangs[aLen] = aAddLang;
aLen++;
@ -1306,7 +1308,7 @@ gfxPlatform::GetRenderingIntent()
return gCMSIntent;
}
void
void
gfxPlatform::TransformPixel(const gfxRGBA& in, gfxRGBA& out, qcms_transform *transform)
{
@ -1381,7 +1383,7 @@ gfxPlatform::GetCMSOutputProfile()
if (!gCMSOutputProfile) {
gCMSOutputProfile = GetCMSsRGBProfile();
}
/* Precache the LUT16 Interpolations for the output profile. See
/* Precache the LUT16 Interpolations for the output profile. See
bug 444661 for details. */
qcms_profile_precache_output_transform(gCMSOutputProfile);
}

Просмотреть файл

@ -18,6 +18,7 @@
#include "nsThreadUtils.h"
#include "mozilla/FileUtils.h"
#include <cutils/properties.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/videodev2.h>
@ -70,12 +71,29 @@ static void
initTavaruaRadio(hal::FMRadioSettings &aInfo)
{
mozilla::ScopedClose fd(sRadioFD);
char command[64];
snprintf(command, sizeof(command), "/system/bin/fm_qsoc_patches %d 0", sTavaruaVersion);
int rc = system(command);
if (rc) {
HAL_LOG(("Unable to initialize radio"));
return;
char version[64];
int rc;
snprintf(version, sizeof(version), "%d", sTavaruaVersion);
property_set("hw.fm.version", version);
/* Set the mode for soc downloader */
property_set("hw.fm.mode", "normal");
/* start fm_dl service */
property_set("ctl.start", "fm_dl");
/*
* Fix bug 800263. Wait until the FM radio chips initialization is done
* then set other properties, or the system will hang and reboot. This
* work around is from codeaurora
* (git://codeaurora.org/platform/frameworks/base.git).
*/
for (int i = 0; i < 4; ++i) {
sleep(1);
char value[PROPERTY_VALUE_MAX];
property_get("hw.fm.init", value, "0");
if (!strcmp(value, "1")) {
break;
}
}
rc = setControl(V4L2_CID_PRIVATE_TAVARUA_STATE, FM_RECV);

Просмотреть файл

@ -519,27 +519,23 @@ class Rooted : public RootedBase<T>
{
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
ContextFriendFields *cx = ContextFriendFields::get(cxArg);
ThingRootKind kind = RootMethods<T>::kind();
this->stack = reinterpret_cast<Rooted<T>**>(&cx->thingGCRooters[kind]);
this->prev = *stack;
*stack = this;
JS_ASSERT(!RootMethods<T>::poisoned(ptr));
commonInit(cx->thingGCRooters);
#endif
}
void init(JSRuntime *rtArg)
{
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
RuntimeFriendFields *rt = const_cast<RuntimeFriendFields *>(RuntimeFriendFields::get(rtArg));
PerThreadDataFriendFields *pt = PerThreadDataFriendFields::getMainThread(rtArg);
commonInit(pt->thingGCRooters);
#endif
}
ThingRootKind kind = RootMethods<T>::kind();
this->stack = reinterpret_cast<Rooted<T>**>(&rt->thingGCRooters[kind]);
this->prev = *stack;
*stack = this;
JS_ASSERT(!RootMethods<T>::poisoned(ptr));
void init(js::PerThreadData *ptArg)
{
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
PerThreadDataFriendFields *pt = PerThreadDataFriendFields::get(ptArg);
commonInit(pt->thingGCRooters);
#endif
}
@ -576,6 +572,22 @@ class Rooted : public RootedBase<T>
init(cx);
}
Rooted(js::PerThreadData *pt
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: ptr(RootMethods<T>::initial())
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
init(pt);
}
Rooted(js::PerThreadData *pt, T initial
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: ptr(initial)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
init(pt);
}
template <typename S>
Rooted(JSContext *cx, const Return<S> &initial
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
@ -585,6 +597,15 @@ class Rooted : public RootedBase<T>
init(cx);
}
template <typename S>
Rooted(js::PerThreadData *pt, const Return<S> &initial
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: ptr(initial.ptr_)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
init(pt);
}
~Rooted()
{
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
@ -625,6 +646,17 @@ class Rooted : public RootedBase<T>
}
private:
void commonInit(Rooted<void*> **thingGCRooters) {
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
ThingRootKind kind = RootMethods<T>::kind();
this->stack = reinterpret_cast<Rooted<T>**>(&thingGCRooters[kind]);
this->prev = *stack;
*stack = this;
JS_ASSERT(!RootMethods<T>::poisoned(ptr));
#endif
}
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
Rooted<T> **stack, *prev;
#endif

Просмотреть файл

@ -676,33 +676,36 @@ static JSBool js_NewRuntimeWasCalled = JS_FALSE;
/*
* Thread Local Storage slot for storing the runtime for a thread.
*/
namespace js {
mozilla::ThreadLocal<PerThreadData *> TlsPerThreadData;
}
namespace JS {
mozilla::ThreadLocal<JSRuntime *> TlsRuntime;
#ifdef DEBUG
JS_FRIEND_API(void)
EnterAssertNoGCScope()
{
++TlsRuntime.get()->gcAssertNoGCDepth;
++TlsPerThreadData.get()->gcAssertNoGCDepth;
}
JS_FRIEND_API(void)
LeaveAssertNoGCScope()
{
--TlsRuntime.get()->gcAssertNoGCDepth;
JS_ASSERT(TlsRuntime.get()->gcAssertNoGCDepth >= 0);
--TlsPerThreadData.get()->gcAssertNoGCDepth;
JS_ASSERT(TlsPerThreadData.get()->gcAssertNoGCDepth >= 0);
}
JS_FRIEND_API(bool)
InNoGCScope()
{
return TlsRuntime.get()->gcAssertNoGCDepth > 0;
return TlsPerThreadData.get()->gcAssertNoGCDepth > 0;
}
JS_FRIEND_API(bool)
NeedRelaxedRootChecks()
{
return TlsRuntime.get()->gcRelaxRootChecks;
return TlsPerThreadData.get()->gcRelaxRootChecks;
}
#else
JS_FRIEND_API(void) EnterAssertNoGCScope() {}
@ -715,8 +718,17 @@ JS_FRIEND_API(bool) NeedRelaxedRootChecks() { return false; }
static const JSSecurityCallbacks NullSecurityCallbacks = { };
js::PerThreadData::PerThreadData(JSRuntime *runtime)
: runtime_(runtime)
#ifdef DEBUG
, gcRelaxRootChecks(false)
, gcAssertNoGCDepth(0)
#endif
{}
JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
: atomsCompartment(NULL),
: mainThread(this),
atomsCompartment(NULL),
#ifdef JS_THREADSAFE
ownerThread_(NULL),
#endif
@ -788,10 +800,6 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
gcSliceBudget(SliceBudget::Unlimited),
gcIncrementalEnabled(true),
gcExactScanningEnabled(true),
#ifdef DEBUG
gcRelaxRootChecks(false),
gcAssertNoGCDepth(0),
#endif
gcPoke(false),
heapState(Idle),
#ifdef JS_GC_ZEAL
@ -885,16 +893,12 @@ JSRuntime::init(uint32_t maxbytes)
ownerThread_ = PR_GetCurrentThread();
#endif
JS::TlsRuntime.set(this);
js::TlsPerThreadData.set(&mainThread);
#ifdef JS_METHODJIT_SPEW
JMCheckLogging();
#endif
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
PodArrayZero(thingGCRooters);
#endif
if (!js_InitGC(this, maxbytes))
return false;
@ -1018,9 +1022,9 @@ JSRuntime::setOwnerThread()
JS_ASSERT(ownerThread_ == (void *)0xc1ea12); /* "clear" */
JS_ASSERT(requestDepth == 0);
JS_ASSERT(js_NewRuntimeWasCalled);
JS_ASSERT(JS::TlsRuntime.get() == NULL);
JS_ASSERT(js::TlsPerThreadData.get() == NULL);
ownerThread_ = PR_GetCurrentThread();
JS::TlsRuntime.set(this);
js::TlsPerThreadData.set(&mainThread);
nativeStackBase = GetNativeStackBase();
if (nativeStackQuota)
JS_SetNativeStackQuota(this, nativeStackQuota);
@ -1033,7 +1037,7 @@ JSRuntime::clearOwnerThread()
JS_ASSERT(requestDepth == 0);
JS_ASSERT(js_NewRuntimeWasCalled);
ownerThread_ = (void *)0xc1ea12; /* "clear" */
JS::TlsRuntime.set(NULL);
js::TlsPerThreadData.set(NULL);
nativeStackBase = 0;
#if JS_STACK_GROWTH_DIRECTION > 0
nativeStackLimit = UINTPTR_MAX;
@ -1047,7 +1051,7 @@ JSRuntime::abortIfWrongThread() const
{
if (ownerThread_ != PR_GetCurrentThread())
MOZ_CRASH();
if (this != JS::TlsRuntime.get())
if (!js::TlsPerThreadData.get()->associatedWith(this))
MOZ_CRASH();
}
@ -1055,7 +1059,7 @@ JS_FRIEND_API(void)
JSRuntime::assertValidThread() const
{
JS_ASSERT(ownerThread_ == PR_GetCurrentThread());
JS_ASSERT(this == JS::TlsRuntime.get());
JS_ASSERT(js::TlsPerThreadData.get()->associatedWith(this));
}
#endif /* JS_THREADSAFE */
@ -1092,7 +1096,7 @@ JS_NewRuntime(uint32_t maxbytes, JSUseHelperThreads useHelperThreads)
InitMemorySubsystem();
if (!JS::TlsRuntime.init())
if (!js::TlsPerThreadData.init())
return NULL;
js_NewRuntimeWasCalled = JS_TRUE;
@ -6553,7 +6557,7 @@ JS_ReportErrorNumberVA(JSContext *cx, JSErrorCallback errorCallback,
JS_PUBLIC_API(void)
JS_ReportErrorNumberUC(JSContext *cx, JSErrorCallback errorCallback,
void *userRef, const unsigned errorNumber, ...)
void *userRef, const unsigned errorNumber, ...)
{
va_list ap;
@ -6564,6 +6568,16 @@ JS_ReportErrorNumberUC(JSContext *cx, JSErrorCallback errorCallback,
va_end(ap);
}
JS_PUBLIC_API(void)
JS_ReportErrorNumberUCArray(JSContext *cx, JSErrorCallback errorCallback,
void *userRef, const unsigned errorNumber,
const jschar **args)
{
AssertHeapIsIdle(cx);
js_ReportErrorNumberUCArray(cx, JSREPORT_ERROR, errorCallback, userRef,
errorNumber, args);
}
JS_PUBLIC_API(JSBool)
JS_ReportWarning(JSContext *cx, const char *format, ...)
{

Просмотреть файл

@ -2889,8 +2889,6 @@ JS_IsInRequest(JSRuntime *rt);
namespace JS {
extern mozilla::ThreadLocal<JSRuntime *> TlsRuntime;
inline bool
IsPoisonedId(jsid iden)
{
@ -5693,6 +5691,11 @@ extern JS_PUBLIC_API(void)
JS_ReportErrorNumberUC(JSContext *cx, JSErrorCallback errorCallback,
void *userRef, const unsigned errorNumber, ...);
extern JS_PUBLIC_API(void)
JS_ReportErrorNumberUCArray(JSContext *cx, JSErrorCallback errorCallback,
void *userRef, const unsigned errorNumber,
const jschar **args);
/*
* As above, but report a warning instead (JSREPORT_IS_WARNING(report.flags)).
* Return true if there was no error trying to issue the warning, and if the

Просмотреть файл

@ -875,6 +875,7 @@ js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
const JSErrorFormatString *efs;
int i;
int argCount;
bool messageArgsPassed = !!reportp->messageArgs;
*messagep = NULL;
@ -897,12 +898,19 @@ js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
* null it out to act as the caboose when we free the
* pointers later.
*/
reportp->messageArgs = cx->pod_malloc<const jschar*>(argCount + 1);
if (!reportp->messageArgs)
return JS_FALSE;
reportp->messageArgs[argCount] = NULL;
if (messageArgsPassed) {
JS_ASSERT(!reportp->messageArgs[argCount]);
} else {
reportp->messageArgs = cx->pod_malloc<const jschar*>(argCount + 1);
if (!reportp->messageArgs)
return JS_FALSE;
/* NULL-terminate for easy copying. */
reportp->messageArgs[argCount] = NULL;
}
for (i = 0; i < argCount; i++) {
if (charArgs) {
if (messageArgsPassed) {
/* Do nothing. */
} else if (charArgs) {
char *charArg = va_arg(ap, char *);
size_t charArgLength = strlen(charArg);
reportp->messageArgs[i] = InflateString(cx, charArg, &charArgLength);
@ -914,8 +922,6 @@ js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
argLengths[i] = js_strlen(reportp->messageArgs[i]);
totalArgsLength += argLengths[i];
}
/* NULL-terminate for easy copying. */
reportp->messageArgs[i] = NULL;
}
/*
* Parse the error format, substituting the argument X
@ -968,6 +974,8 @@ js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
goto error;
}
} else {
/* Non-null messageArgs should have at least one non-null arg. */
JS_ASSERT(!reportp->messageArgs);
/*
* Zero arguments: the format string (if it exists) is the
* entire message.
@ -997,7 +1005,7 @@ js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
return JS_TRUE;
error:
if (reportp->messageArgs) {
if (!messageArgsPassed && reportp->messageArgs) {
/* free the arguments only if we allocated them */
if (charArgs) {
i = 0;
@ -1063,6 +1071,39 @@ js_ReportErrorNumberVA(JSContext *cx, unsigned flags, JSErrorCallback callback,
return warning;
}
bool
js_ReportErrorNumberUCArray(JSContext *cx, unsigned flags, JSErrorCallback callback,
void *userRef, const unsigned errorNumber,
const jschar **args)
{
if (checkReportFlags(cx, &flags))
return true;
bool warning = JSREPORT_IS_WARNING(flags);
JSErrorReport report;
PodZero(&report);
report.flags = flags;
report.errorNumber = errorNumber;
PopulateReportBlame(cx, &report);
report.messageArgs = args;
char *message;
va_list dummy;
if (!js_ExpandErrorArguments(cx, callback, userRef, errorNumber,
&message, &report, JS_FALSE, dummy)) {
return false;
}
ReportError(cx, message, &report, callback, userRef);
if (message)
js_free(message);
if (report.ucmessage)
js_free((void *)report.ucmessage);
return warning;
}
JS_FRIEND_API(void)
js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *reportp)
{

Просмотреть файл

@ -389,8 +389,70 @@ struct JSAtomState
#define NAME_OFFSET(name) offsetof(JSAtomState, name)
#define OFFSET_TO_NAME(rt,off) (*(js::FixedHeapPtr<js::PropertyName>*)((char*)&(rt)->atomState + (off)))
namespace js {
/*
* Encapsulates portions of the runtime/context that are tied to a
* single active thread. Normally, as most JS is single-threaded,
* there is only one instance of this struct, embedded in the
* JSRuntime as the field |mainThread|. During Parallel JS sections,
* however, there will be one instance per worker thread.
*
* The eventual plan is to designate thread-safe portions of the
* interpreter and runtime by having them take |PerThreadData*|
* arguments instead of |JSContext*| or |JSRuntime*|.
*/
class PerThreadData : public js::PerThreadDataFriendFields
{
/*
* Backpointer to the full shared JSRuntime* with which this
* thread is associaed. This is private because accessing the
* fields of this runtime can provoke race conditions, so the
* intention is that access will be mediated through safe
* functions like |associatedWith()| below.
*/
JSRuntime *runtime_;
public:
/*
* We save all conservative scanned roots in this vector so that
* conservative scanning can be "replayed" deterministically. In DEBUG mode,
* this allows us to run a non-incremental GC after every incremental GC to
* ensure that no objects were missed.
*/
#ifdef DEBUG
struct SavedGCRoot {
void *thing;
JSGCTraceKind kind;
SavedGCRoot(void *thing, JSGCTraceKind kind) : thing(thing), kind(kind) {}
};
js::Vector<SavedGCRoot, 0, js::SystemAllocPolicy> gcSavedRoots;
bool gcRelaxRootChecks;
int gcAssertNoGCDepth;
#endif
PerThreadData(JSRuntime *runtime);
bool associatedWith(const JSRuntime *rt) { return runtime_ == rt; }
};
} // namespace js
struct JSRuntime : js::RuntimeFriendFields
{
/* Per-thread data for the main thread that is associated with
* this JSRuntime, as opposed to any worker threads used in
* parallel sections. See definition of |PerThreadData| struct
* above for more details.
*
* NB: This field is statically asserted to be at offset
* sizeof(RuntimeFriendFields). See
* PerThreadDataFriendFields::getMainThread.
*/
js::PerThreadData mainThread;
/* Default compartment. */
JSCompartment *atomsCompartment;
@ -654,25 +716,6 @@ struct JSRuntime : js::RuntimeFriendFields
*/
bool gcExactScanningEnabled;
/*
* We save all conservative scanned roots in this vector so that
* conservative scanning can be "replayed" deterministically. In DEBUG mode,
* this allows us to run a non-incremental GC after every incremental GC to
* ensure that no objects were missed.
*/
#ifdef DEBUG
struct SavedGCRoot {
void *thing;
JSGCTraceKind kind;
SavedGCRoot(void *thing, JSGCTraceKind kind) : thing(thing), kind(kind) {}
};
js::Vector<SavedGCRoot, 0, js::SystemAllocPolicy> gcSavedRoots;
bool gcRelaxRootChecks;
int gcAssertNoGCDepth;
#endif
bool gcPoke;
enum HeapState {
@ -1874,6 +1917,11 @@ js_ReportErrorNumberVA(JSContext *cx, unsigned flags, JSErrorCallback callback,
void *userRef, const unsigned errorNumber,
JSBool charArgs, va_list ap);
extern bool
js_ReportErrorNumberUCArray(JSContext *cx, unsigned flags, JSErrorCallback callback,
void *userRef, const unsigned errorNumber,
const jschar **args);
extern JSBool
js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
void *userRef, const unsigned errorNumber,

Просмотреть файл

@ -967,7 +967,8 @@ js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp,
return false;
tv[1] = OBJECT_TO_JSVAL(errObject);
RootedString messageStr(cx, JS_NewStringCopyZ(cx, message));
RootedString messageStr(cx, reportp->ucmessage ? JS_NewUCStringCopyZ(cx, reportp->ucmessage)
: JS_NewStringCopyZ(cx, message));
if (!messageStr)
return false;
tv[2] = STRING_TO_JSVAL(messageStr);

Просмотреть файл

@ -22,6 +22,16 @@
using namespace js;
using namespace JS;
// Required by PerThreadDataFriendFields::getMainThread()
JS_STATIC_ASSERT(offsetof(JSRuntime, mainThread) == sizeof(RuntimeFriendFields));
PerThreadDataFriendFields::PerThreadDataFriendFields()
{
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
PodArrayZero(thingGCRooters);
#endif
}
JS_FRIEND_API(void)
JS_SetSourceHook(JSRuntime *rt, JS_SourceHook hook)
{

Просмотреть файл

@ -183,6 +183,8 @@ JS_SetSourceHook(JSRuntime *rt, JS_SourceHook hook);
namespace js {
extern mozilla::ThreadLocal<PerThreadData *> TlsPerThreadData;
inline JSRuntime *
GetRuntime(const JSContext *cx)
{

Просмотреть файл

@ -992,7 +992,7 @@ MarkExactStackRoots(JSTracer *trc)
for (ContextIter cx(trc->runtime); !cx.done(); cx.next()) {
MarkExactStackRooters(trc, cx->thingGCRooters[i], ThingRootKind(i));
}
MarkExactStackRooters(trc, rt->thingGCRooters[i], ThingRootKind(i));
MarkExactStackRooters(trc, rt->mainThread.thingGCRooters[i], ThingRootKind(i));
}
}
#endif /* JSGC_USE_EXACT_ROOTING */
@ -1125,7 +1125,8 @@ MarkIfGCThingWord(JSTracer *trc, uintptr_t w)
#ifdef DEBUG
if (trc->runtime->gcIncrementalState == MARK_ROOTS)
trc->runtime->gcSavedRoots.append(JSRuntime::SavedGCRoot(thing, traceKind));
trc->runtime->mainThread.gcSavedRoots.append(
PerThreadData::SavedGCRoot(thing, traceKind));
#endif
return CGCT_VALID;
@ -1186,8 +1187,8 @@ MarkConservativeStackRoots(JSTracer *trc, bool useSavedRoots)
#ifdef DEBUG
if (useSavedRoots) {
for (JSRuntime::SavedGCRoot *root = rt->gcSavedRoots.begin();
root != rt->gcSavedRoots.end();
for (PerThreadData::SavedGCRoot *root = rt->mainThread.gcSavedRoots.begin();
root != rt->mainThread.gcSavedRoots.end();
root++)
{
JS_SET_TRACING_NAME(trc, "cstack");
@ -1197,7 +1198,7 @@ MarkConservativeStackRoots(JSTracer *trc, bool useSavedRoots)
}
if (rt->gcIncrementalState == MARK_ROOTS)
rt->gcSavedRoots.clearAndFree();
rt->mainThread.gcSavedRoots.clearAndFree();
#endif
ConservativeGCData *cgcd = &rt->conservativeGC;
@ -4912,7 +4913,8 @@ CheckStackRoot(JSTracer *trc, uintptr_t *w)
bool matched = false;
JSRuntime *rt = trc->runtime;
for (unsigned i = 0; i < THING_ROOT_LIMIT; i++) {
CheckStackRootThings(w, rt->thingGCRooters[i], ThingRootKind(i), &matched);
CheckStackRootThings(w, rt->mainThread.thingGCRooters[i],
ThingRootKind(i), &matched);
for (ContextIter cx(rt); !cx.done(); cx.next()) {
CheckStackRootThings(w, cx->thingGCRooters[i], ThingRootKind(i), &matched);
SkipRoot *skip = cx->skipGCRooters;

Просмотреть файл

@ -307,14 +307,6 @@ struct RuntimeFriendFields {
/* Limit pointer for checking native stack consumption. */
uintptr_t nativeStackLimit;
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
/*
* Stack allocated GC roots for stack GC heap pointers, which may be
* overwritten if moved during a GC.
*/
Rooted<void*> *thingGCRooters[THING_ROOT_LIMIT];
#endif
RuntimeFriendFields()
: interrupt(0),
nativeStackLimit(0) { }
@ -324,6 +316,32 @@ struct RuntimeFriendFields {
}
};
class PerThreadData;
struct PerThreadDataFriendFields
{
PerThreadDataFriendFields();
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
/*
* Stack allocated GC roots for stack GC heap pointers, which may be
* overwritten if moved during a GC.
*/
Rooted<void*> *thingGCRooters[THING_ROOT_LIMIT];
#endif
static PerThreadDataFriendFields *get(js::PerThreadData *pt) {
return reinterpret_cast<PerThreadDataFriendFields *>(pt);
}
static PerThreadDataFriendFields *getMainThread(JSRuntime *rt) {
// mainThread must always appear directly after |RuntimeFriendFields|.
// Tested by a JS_STATIC_ASSERT in |jsfriendapi.cpp|
return reinterpret_cast<PerThreadDataFriendFields *>(
reinterpret_cast<char*>(rt) + sizeof(RuntimeFriendFields));
}
};
} /* namespace js */
#endif /* __cplusplus */

Просмотреть файл

@ -3417,7 +3417,7 @@ RelaxRootChecks(JSContext *cx, unsigned argc, jsval *vp)
}
#ifdef DEBUG
cx->runtime->gcRelaxRootChecks = true;
cx->runtime->mainThread.gcRelaxRootChecks = true;
#endif
return true;

Просмотреть файл

@ -1402,7 +1402,8 @@ StackIter::settleOnNewState()
}
StackIter::StackIter(JSContext *cx, SavedOption savedOption)
: maybecx_(cx),
: perThread_(&cx->runtime->mainThread),
maybecx_(cx),
savedOption_(savedOption),
script_(cx, NULL)
#ifdef JS_ION
@ -1426,7 +1427,9 @@ StackIter::StackIter(JSContext *cx, SavedOption savedOption)
}
StackIter::StackIter(JSRuntime *rt, StackSegment &seg)
: maybecx_(NULL), savedOption_(STOP_AT_SAVED),
: perThread_(&rt->mainThread),
maybecx_(NULL),
savedOption_(STOP_AT_SAVED),
script_(rt, NULL)
#ifdef JS_ION
, ionActivations_(rt),
@ -1444,14 +1447,15 @@ StackIter::StackIter(JSRuntime *rt, StackSegment &seg)
}
StackIter::StackIter(const StackIter &other)
: maybecx_(other.maybecx_),
: perThread_(other.perThread_),
maybecx_(other.maybecx_),
savedOption_(other.savedOption_),
state_(other.state_),
fp_(other.fp_),
calls_(other.calls_),
seg_(other.seg_),
pc_(other.pc_),
script_(other.maybecx_ ? other.maybecx_->runtime : TlsRuntime.get(), other.script_),
script_(perThread_, other.script_),
args_(other.args_)
#ifdef JS_ION
, ionActivations_(other.ionActivations_),

Просмотреть файл

@ -1712,6 +1712,7 @@ class GeneratorFrameGuard : public FrameGuard
class StackIter
{
friend class ContextStack;
PerThreadData *perThread_;
JSContext *maybecx_;
public:
enum SavedOption { STOP_AT_SAVED, GO_THROUGH_SAVED };

Просмотреть файл

@ -31,7 +31,7 @@
#include "TypeTraits.h"
#include <limits>
#include <stdint.h>
#include "mozilla/StandardInteger.h"
#ifdef _MSC_VER
# undef min

Просмотреть файл

@ -30,7 +30,7 @@
namespace JSC { namespace Yarr {
#include <stddef.h>
#include <stdint.h>
#include "mozilla/StandardInteger.h"
uint16_t ucs2CharacterSet0[] = { 0x01c4u, 0x01c5u, 0x01c6u, 0 };
uint16_t ucs2CharacterSet1[] = { 0x01c7u, 0x01c8u, 0x01c9u, 0 };

Просмотреть файл

@ -26,7 +26,7 @@
#ifndef YarrCanonicalizeUCS2_H
#define YarrCanonicalizeUCS2_H
#include <stdint.h>
#include "mozilla/StandardInteger.h"
#include "wtfbridge.h"
#include "assembler/wtf/Assertions.h"

Просмотреть файл

@ -180,7 +180,7 @@ print('#include "assembler/wtf/Assertions.h"');
print();
print("namespace JSC { namespace Yarr {");
print();
print("#include <stdint.h>");
print('#include "mozilla/StandardInteger.h"');
print();
for (i in characterSetInfo) {

Просмотреть файл

@ -1469,7 +1469,7 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCCallContext& ccx,
nsRefPtr<XPCWrappedNative> wrapper;
AutoWrapperChanger wrapperChanger;
JSObject *flat;
JSObject *flat = nullptr;
nsWrapperCache* cache = nullptr;
CallQueryInterface(aCOMObj, &cache);
if (cache) {
@ -1490,7 +1490,8 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCCallContext& ccx,
if (NS_FAILED(rv))
return rv;
flat = wrapper->GetFlatJSObject();
if (wrapper)
flat = wrapper->GetFlatJSObject();
}
if (!flat) {

Просмотреть файл

@ -20,7 +20,8 @@ dictionaries = [
[ 'CameraPosition', 'nsIDOMCameraManager.idl' ],
[ 'CameraSelector', 'nsIDOMCameraManager.idl' ],
[ 'CameraPictureOptions', 'nsIDOMCameraManager.idl' ],
[ 'CameraRecordingOptions', 'nsIDOMCameraManager.idl' ]
[ 'CameraRecordingOptions', 'nsIDOMCameraManager.idl' ],
[ 'ArchiveReaderOptions', 'nsIDOMArchiveReader.idl' ]
]
# include file names

Просмотреть файл

@ -144,7 +144,14 @@ nsPopupBoxObject::SizeTo(int32_t aWidth, int32_t aHeight)
height.AppendInt(aHeight);
nsCOMPtr<nsIContent> content = mContent;
content->SetAttr(kNameSpaceID_None, nsGkAtoms::width, width, false);
// We only want to pass aNotify=true to SetAttr once, but must make sure
// we pass it when a value is being changed. Thus, we check if the height
// is the same and if so, pass true when setting the width and skip setting
// the height.
bool heightSame = content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::height, height, eCaseMatters);
content->SetAttr(kNameSpaceID_None, nsGkAtoms::width, width, heightSame);
content->SetAttr(kNameSpaceID_None, nsGkAtoms::height, height, true);
return NS_OK;

Просмотреть файл

@ -19,6 +19,7 @@ MOCHITEST_FILES = test_bug511075.html \
MOCHITEST_CHROME_FILES = test_bug381167.xhtml \
test_bug393970.xul \
test_bug477754.xul \
test_popupSizeTo.xul \
test_stack.xul \
test_resizer.xul \
window_resizer.xul \

Просмотреть файл

@ -0,0 +1,55 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<!--
XUL Panel sizeTo tests
-->
<window title="XUL Panel sizeTo tests"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml">
</body>
<!-- test code goes here -->
<script type="application/javascript"><![CDATA[
SimpleTest.waitForExplicitFinish();
function openPopup()
{
document.getElementById("panel").
openPopupAtScreen(Math.round(window.mozInnerScreenX) + window.innerWidth - 130,
Math.round(window.mozInnerScreenY) + window.innerHeight - 130);
}
function sizeAndCheck(width, height) {
var panel = document.getElementById("panel");
panel.sizeTo(width, height);
is(panel.getBoundingClientRect().width, width, "width is correct");
is(panel.getBoundingClientRect().height, height, "height is correct");
}
function popupShown(event)
{
var panel = document.getElementById("panel");
var bcr = panel.getBoundingClientRect();
// resize to 10px bigger in both dimensions.
sizeAndCheck(bcr.width+10, bcr.height+10);
// Same width, different height (based on *new* size from last sizeAndCheck)
sizeAndCheck(bcr.width+10, bcr.height);
// Same height, different width (also based on *new* size from last sizeAndCheck)
sizeAndCheck(bcr.width, bcr.height);
event.target.hidePopup();
}
SimpleTest.waitForFocus(openPopup);
]]></script>
<panel id="panel" onpopupshown="popupShown(event)" onpopuphidden="SimpleTest.finish()">
<resizer id="resizer" dir="bottomend" width="16" height="16"/>
<hbox width="50" height="50" flex="1"/>
</panel>
</window>

Просмотреть файл

@ -75,6 +75,7 @@ typedef enum {
AUDIO_STREAM_ENFORCED_AUDIBLE = 7, /* Sounds that cannot be muted by user and must be routed to speaker */
AUDIO_STREAM_DTMF = 8,
AUDIO_STREAM_TTS = 9,
AUDIO_STREAM_FM = 10,
AUDIO_STREAM_CNT,
AUDIO_STREAM_MAX = AUDIO_STREAM_CNT - 1,
@ -335,6 +336,7 @@ public:
ENFORCED_AUDIBLE = 7, // Sounds that cannot be muted by user and must be routed to speaker
DTMF = 8,
TTS = 9,
FM = 10,
NUM_STREAM_TYPES
};
@ -699,8 +701,13 @@ public:
static status_t initStreamVolume(stream_type stream,
int indexMin,
int indexMax);
static status_t initStreamVolume(audio_stream_type_t stream,
int indexMin,
int indexMax);
static status_t setStreamVolumeIndex(stream_type stream, int index);
static status_t setStreamVolumeIndex(audio_stream_type_t stream, int index);
static status_t getStreamVolumeIndex(stream_type stream, int *index);
static status_t getStreamVolumeIndex(audio_stream_type_t stream, int *index);
static uint32_t getStrategyForStream(stream_type stream);

175
mfbt/EnumSet.h Normal file
Просмотреть файл

@ -0,0 +1,175 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
/* A set abstraction for enumeration values. */
#ifndef mozilla_EnumSet_h
#define mozilla_EnumSet_h
#include "mozilla/Assertions.h"
#include "mozilla/StandardInteger.h"
namespace mozilla {
/**
* EnumSet<T> is a set of values defined by an enumeration. It is implemented
* using a 32 bit mask for each value so it will only work for enums with an int
* representation less than 32. It works both for enum and enum class types.
*/
template<typename T>
class EnumSet
{
public:
EnumSet()
: mBitField(0)
{ }
EnumSet(T aEnum)
: mBitField(aEnum)
{ }
EnumSet(T aEnum1, T aEnum2)
: mBitField(bitFor(aEnum1) |
bitFor(aEnum2))
{ }
EnumSet(T aEnum1, T aEnum2, T aEnum3)
: mBitField(bitFor(aEnum1) |
bitFor(aEnum2) |
bitFor(aEnum3))
{ }
EnumSet(T aEnum1, T aEnum2, T aEnum3, T aEnum4)
: mBitField(bitFor(aEnum1) |
bitFor(aEnum2) |
bitFor(aEnum3) |
bitFor(aEnum4))
{ }
EnumSet(const EnumSet& aEnumSet)
: mBitField(aEnumSet.mBitField)
{ }
/**
* Add an element
*/
void operator+=(T aEnum) {
mBitField |= bitFor(aEnum);
}
/**
* Add an element
*/
EnumSet<T> operator+(T aEnum) const {
EnumSet<T> result(*this);
result += aEnum;
return result;
}
/**
* Union
*/
void operator+=(const EnumSet<T> aEnumSet) {
mBitField |= aEnumSet.mBitField;
}
/**
* Union
*/
EnumSet<T> operator+(const EnumSet<T> aEnumSet) const {
EnumSet<T> result(*this);
result += aEnumSet;
return result;
}
/**
* Remove an element
*/
void operator-=(T aEnum) {
mBitField &= ~(bitFor(aEnum));
}
/**
* Remove an element
*/
EnumSet<T> operator-(T aEnum) const {
EnumSet<T> result(*this);
result -= aEnum;
return result;
}
/**
* Remove a set of elements
*/
void operator-=(const EnumSet<T> aEnumSet) {
mBitField &= ~(aEnumSet.mBitField);
}
/**
* Remove a set of elements
*/
EnumSet<T> operator-(const EnumSet<T> aEnumSet) const {
EnumSet<T> result(*this);
result -= aEnumSet;
return result;
}
/**
* Intersection
*/
void operator&=(const EnumSet<T> aEnumSet) {
mBitField &= aEnumSet.mBitField;
}
/**
* Intersection
*/
EnumSet<T> operator&(const EnumSet<T> aEnumSet) const {
EnumSet<T> result(*this);
result &= aEnumSet;
return result;
}
/**
* Equality
*/
bool operator==(const EnumSet<T> aEnumSet) const {
return mBitField == aEnumSet.mBitField;
}
/**
* Test is an element is contained in the set
*/
bool contains(T aEnum) const {
return mBitField & bitFor(aEnum);
}
/**
* Return the number of elements in the set
*/
uint8_t size() {
uint8_t count = 0;
for (uint32_t bitField = mBitField; bitField; bitField >>= 1) {
if (bitField & 1)
count++;
}
return count;
}
private:
static uint32_t bitFor(T aEnum) {
uint32_t bitNumber(aEnum);
MOZ_ASSERT(bitNumber < 32);
return 1U << bitNumber;
}
uint32_t mBitField;
};
} // namespace mozilla
#endif // mozilla_EnumSet_h_

Просмотреть файл

@ -14,6 +14,7 @@ EXPORTS_mozilla += \
BloomFilter.h \
CheckedInt.h \
Constants.h \
EnumSet.h \
FloatingPoint.h \
GuardObjects.h \
HashFunctions.h \

Просмотреть файл

@ -14,6 +14,7 @@ STL_FLAGS =
CPP_UNIT_TESTS = \
TestBloomFilter.cpp \
TestCheckedInt.cpp \
TestEnumSet.cpp \
TestSHA1.cpp \
TestTypeTraits.cpp \
TestWeakPtr.cpp \

232
mfbt/tests/TestEnumSet.cpp Normal file
Просмотреть файл

@ -0,0 +1,232 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "mozilla/EnumSet.h"
using namespace mozilla;
enum SeaBird {
PENGUIN,
ALBATROSS,
FULMAR,
PRION,
SHEARWATER,
GADFLY_PETREL,
TRUE_PETREL,
DIVING_PETREL,
STORM_PETREL,
PELICAN,
GANNET,
BOOBY,
CORMORANT,
FRIGATEBIRD,
TROPICBIRD,
SKUA,
GULL,
TERN,
SKIMMER,
AUK
};
class EnumSetSuite {
public:
EnumSetSuite()
: mAlcidae(),
mDiomedeidae(ALBATROSS),
mPetrelProcellariidae(GADFLY_PETREL, TRUE_PETREL),
mNonPetrelProcellariidae(FULMAR, PRION, SHEARWATER),
mPetrels(GADFLY_PETREL, TRUE_PETREL, DIVING_PETREL, STORM_PETREL)
{ }
void runTests() {
testSize();
testContains();
testAddTo();
testAdd();
testAddAll();
testUnion();
testRemoveFrom();
testRemove();
testRemoveAllFrom();
testRemoveAll();
testIntersect();
testInsersection();
testEquality();
testDuplicates();
}
private:
void testSize() {
MOZ_ASSERT(mAlcidae.size() == 0);
MOZ_ASSERT(mDiomedeidae.size() == 1);
MOZ_ASSERT(mPetrelProcellariidae.size() == 2);
MOZ_ASSERT(mNonPetrelProcellariidae.size() == 3);
MOZ_ASSERT(mPetrels.size() == 4);
}
void testContains() {
MOZ_ASSERT(!mPetrels.contains(PENGUIN));
MOZ_ASSERT(!mPetrels.contains(ALBATROSS));
MOZ_ASSERT(!mPetrels.contains(FULMAR));
MOZ_ASSERT(!mPetrels.contains(PRION));
MOZ_ASSERT(!mPetrels.contains(SHEARWATER));
MOZ_ASSERT(mPetrels.contains(GADFLY_PETREL));
MOZ_ASSERT(mPetrels.contains(TRUE_PETREL));
MOZ_ASSERT(mPetrels.contains(DIVING_PETREL));
MOZ_ASSERT(mPetrels.contains(STORM_PETREL));
MOZ_ASSERT(!mPetrels.contains(PELICAN));
MOZ_ASSERT(!mPetrels.contains(GANNET));
MOZ_ASSERT(!mPetrels.contains(BOOBY));
MOZ_ASSERT(!mPetrels.contains(CORMORANT));
MOZ_ASSERT(!mPetrels.contains(FRIGATEBIRD));
MOZ_ASSERT(!mPetrels.contains(TROPICBIRD));
MOZ_ASSERT(!mPetrels.contains(SKUA));
MOZ_ASSERT(!mPetrels.contains(GULL));
MOZ_ASSERT(!mPetrels.contains(TERN));
MOZ_ASSERT(!mPetrels.contains(SKIMMER));
MOZ_ASSERT(!mPetrels.contains(AUK));
}
void testCopy() {
EnumSet<SeaBird> likes = mPetrels;
likes -= TRUE_PETREL;
MOZ_ASSERT(mPetrels.size() == 4);
MOZ_ASSERT(mPetrels.contains(TRUE_PETREL));
MOZ_ASSERT(likes.size() == 3);
MOZ_ASSERT(likes.contains(GADFLY_PETREL));
MOZ_ASSERT(likes.contains(DIVING_PETREL));
MOZ_ASSERT(likes.contains(STORM_PETREL));
}
void testAddTo() {
EnumSet<SeaBird> seen = mPetrels;
seen += CORMORANT;
seen += TRUE_PETREL;
MOZ_ASSERT(mPetrels.size() == 4);
MOZ_ASSERT(!mPetrels.contains(CORMORANT));
MOZ_ASSERT(seen.size() == 5);
MOZ_ASSERT(seen.contains(GADFLY_PETREL));
MOZ_ASSERT(seen.contains(TRUE_PETREL));
MOZ_ASSERT(seen.contains(DIVING_PETREL));
MOZ_ASSERT(seen.contains(STORM_PETREL));
MOZ_ASSERT(seen.contains(CORMORANT));
}
void testAdd() {
EnumSet<SeaBird> seen = mPetrels + CORMORANT +
STORM_PETREL;
MOZ_ASSERT(mPetrels.size() == 4);
MOZ_ASSERT(!mPetrels.contains(CORMORANT));
MOZ_ASSERT(seen.size() == 5);
MOZ_ASSERT(seen.contains(GADFLY_PETREL));
MOZ_ASSERT(seen.contains(TRUE_PETREL));
MOZ_ASSERT(seen.contains(DIVING_PETREL));
MOZ_ASSERT(seen.contains(STORM_PETREL));
MOZ_ASSERT(seen.contains(CORMORANT));
}
void testAddAll() {
EnumSet<SeaBird> procellariidae;
procellariidae += mPetrelProcellariidae;
procellariidae += mNonPetrelProcellariidae;
MOZ_ASSERT(procellariidae.size() == 5);
// Both procellariidae and mPetrels include GADFLY_PERTEL and TRUE_PETREL
EnumSet<SeaBird> procellariiformes;
procellariiformes += mDiomedeidae;
procellariiformes += procellariidae;
procellariiformes += mPetrels;
MOZ_ASSERT(procellariiformes.size() == 8);
}
void testUnion() {
EnumSet<SeaBird> procellariidae = mPetrelProcellariidae +
mNonPetrelProcellariidae;
MOZ_ASSERT(procellariidae.size() == 5);
// Both procellariidae and mPetrels include GADFLY_PETREL and TRUE_PETREL
EnumSet<SeaBird> procellariiformes = mDiomedeidae + procellariidae +
mPetrels;
MOZ_ASSERT(procellariiformes.size() == 8);
}
void testRemoveFrom() {
EnumSet<SeaBird> likes = mPetrels;
likes -= TRUE_PETREL;
likes -= DIVING_PETREL;
MOZ_ASSERT(likes.size() == 2);
MOZ_ASSERT(likes.contains(GADFLY_PETREL));
MOZ_ASSERT(likes.contains(STORM_PETREL));
}
void testRemove() {
EnumSet<SeaBird> likes = mPetrels - TRUE_PETREL -
DIVING_PETREL;
MOZ_ASSERT(likes.size() == 2);
MOZ_ASSERT(likes.contains(GADFLY_PETREL));
MOZ_ASSERT(likes.contains(STORM_PETREL));
}
void testRemoveAllFrom() {
EnumSet<SeaBird> likes = mPetrels;
likes -= mPetrelProcellariidae;
MOZ_ASSERT(likes.size() == 2);
MOZ_ASSERT(likes.contains(DIVING_PETREL));
MOZ_ASSERT(likes.contains(STORM_PETREL));
}
void testRemoveAll() {
EnumSet<SeaBird> likes = mPetrels - mPetrelProcellariidae;
MOZ_ASSERT(likes.size() == 2);
MOZ_ASSERT(likes.contains(DIVING_PETREL));
MOZ_ASSERT(likes.contains(STORM_PETREL));
}
void testIntersect() {
EnumSet<SeaBird> likes = mPetrels;
likes &= mPetrelProcellariidae;
MOZ_ASSERT(likes.size() == 2);
MOZ_ASSERT(likes.contains(GADFLY_PETREL));
MOZ_ASSERT(likes.contains(TRUE_PETREL));
}
void testInsersection() {
EnumSet<SeaBird> likes = mPetrels & mPetrelProcellariidae;
MOZ_ASSERT(likes.size() == 2);
MOZ_ASSERT(likes.contains(GADFLY_PETREL));
MOZ_ASSERT(likes.contains(TRUE_PETREL));
}
void testEquality() {
EnumSet<SeaBird> likes = mPetrels & mPetrelProcellariidae;
MOZ_ASSERT(likes == EnumSet<SeaBird>(GADFLY_PETREL,
TRUE_PETREL));
}
void testDuplicates() {
EnumSet<SeaBird> likes = mPetrels;
likes += GADFLY_PETREL;
likes += TRUE_PETREL;
likes += DIVING_PETREL;
likes += STORM_PETREL;
MOZ_ASSERT(likes.size() == 4);
MOZ_ASSERT(likes == mPetrels);
}
EnumSet<SeaBird> mAlcidae;
EnumSet<SeaBird> mDiomedeidae;
EnumSet<SeaBird> mPetrelProcellariidae;
EnumSet<SeaBird> mNonPetrelProcellariidae;
EnumSet<SeaBird> mPetrels;
};
int main()
{
EnumSetSuite suite;
suite.runTests();
return 0;
}

Просмотреть файл

@ -97,6 +97,7 @@ public class BrowserToolbar implements ViewSwitcher.ViewFactory,
private TranslateAnimation mTitleSlideRight;
private int mCount;
private int mFaviconSize;
private static final int TABS_CONTRACTED = 1;
private static final int TABS_EXPANDED = 2;
@ -226,6 +227,7 @@ public class BrowserToolbar implements ViewSwitcher.ViewFactory,
mFavicon.setOnClickListener(faviconListener);
if (Build.VERSION.SDK_INT >= 16)
mFavicon.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
mFaviconSize = Math.round(mActivity.getResources().getDimension(R.dimen.browser_toolbar_favicon_size));
mSiteSecurity = (ImageButton) mLayout.findViewById(R.id.site_security);
mSiteSecurity.setOnClickListener(faviconListener);
@ -683,10 +685,12 @@ public class BrowserToolbar implements ViewSwitcher.ViewFactory,
if (Tabs.getInstance().getSelectedTab().getState() == Tab.STATE_LOADING)
return;
if (image != null)
if (image != null) {
image = Bitmap.createScaledBitmap(image, mFaviconSize, mFaviconSize, false);
mFavicon.setImageBitmap(image);
else
} else {
mFavicon.setImageResource(R.drawable.favicon);
}
}
public void setSecurityMode(String mode) {

Просмотреть файл

@ -810,7 +810,8 @@ public class AllPagesTab extends AwesomeBarTab implements GeckoEventListener {
private void displayFavicon(AwesomeEntryViewHolder viewHolder) {
final String url = viewHolder.urlView.getText().toString();
Favicons favicons = GeckoApp.mAppContext.getFavicons();
viewHolder.faviconView.setImageBitmap(favicons.getFaviconFromMemCache(url));
Bitmap bitmap = favicons.getFaviconFromMemCache(url);
updateFavicon(viewHolder.faviconView, bitmap);
}
private void updateFavicons() {

Просмотреть файл

@ -41,9 +41,13 @@ abstract public class AwesomeBarTab {
// FIXME: This value should probably come from a prefs key
public static final int MAX_RESULTS = 100;
protected Context mContext = null;
private static int sFaviconSize = -1;
public AwesomeBarTab(Context context) {
mContext = context;
if (sFaviconSize < 0) {
sFaviconSize = Math.round(mContext.getResources().getDimension(R.dimen.awesomebar_row_favicon_size));
}
}
public void setListTouchListener(View.OnTouchListener listener) {
@ -94,6 +98,15 @@ abstract public class AwesomeBarTab {
faviconView.setImageDrawable(null);
} else {
Bitmap bitmap = BitmapFactory.decodeByteArray(b, 0, b.length);
updateFavicon(faviconView, bitmap);
}
}
protected void updateFavicon(ImageView faviconView, Bitmap bitmap) {
if (bitmap == null) {
faviconView.setImageDrawable(null);
} else {
bitmap = Bitmap.createScaledBitmap(bitmap, sFaviconSize, sFaviconSize, false);
faviconView.setImageBitmap(bitmap);
}
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше