Bug 1215072 - throw in case dictionary initialization fails in canvas.getContext, r=baku

--HG--
extra : rebase_source : 006bfed7cfec46e6150ee15135de08941283dbb7
This commit is contained in:
Olli Pettay 2015-10-16 22:52:11 +03:00
Родитель b9fcc36e5e
Коммит 2b21892477
11 изменённых файлов: 84 добавлений и 17 удалений

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

@ -1606,7 +1606,9 @@ CanvasRenderingContext2D::SetIsIPC(bool isIPC)
} }
NS_IMETHODIMP NS_IMETHODIMP
CanvasRenderingContext2D::SetContextOptions(JSContext* aCx, JS::Handle<JS::Value> aOptions) CanvasRenderingContext2D::SetContextOptions(JSContext* aCx,
JS::Handle<JS::Value> aOptions,
ErrorResult& aRvForDictionaryInit)
{ {
if (aOptions.isNullOrUndefined()) { if (aOptions.isNullOrUndefined()) {
return NS_OK; return NS_OK;
@ -1616,7 +1618,10 @@ CanvasRenderingContext2D::SetContextOptions(JSContext* aCx, JS::Handle<JS::Value
MOZ_ASSERT(!mTarget); MOZ_ASSERT(!mTarget);
ContextAttributes2D attributes; ContextAttributes2D attributes;
NS_ENSURE_TRUE(attributes.Init(aCx, aOptions), NS_ERROR_UNEXPECTED); if (!attributes.Init(aCx, aOptions)) {
aRvForDictionaryInit.Throw(NS_ERROR_UNEXPECTED);
return NS_ERROR_UNEXPECTED;
}
if (Preferences::GetBool("gfx.canvas.willReadFrequently.enable", false)) { if (Preferences::GetBool("gfx.canvas.willReadFrequently.enable", false)) {
// Use software when there is going to be a lot of readback // Use software when there is going to be a lot of readback

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

@ -465,7 +465,9 @@ public:
// this rect is in canvas device space // this rect is in canvas device space
void Redraw(const mozilla::gfx::Rect &r); void Redraw(const mozilla::gfx::Rect &r);
NS_IMETHOD Redraw(const gfxRect &r) override { Redraw(ToRect(r)); return NS_OK; } NS_IMETHOD Redraw(const gfxRect &r) override { Redraw(ToRect(r)); return NS_OK; }
NS_IMETHOD SetContextOptions(JSContext* aCx, JS::Handle<JS::Value> aOptions) override; NS_IMETHOD SetContextOptions(JSContext* aCx,
JS::Handle<JS::Value> aOptions,
ErrorResult& aRvForDictionaryInit) override;
/** /**
* An abstract base class to be implemented by callers wanting to be notified * An abstract base class to be implemented by callers wanting to be notified

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

@ -173,9 +173,11 @@ CanvasRenderingContextHelper::GetContext(JSContext* aCx,
mCurrentContext = context.forget(); mCurrentContext = context.forget();
mCurrentContextType = contextType; mCurrentContextType = contextType;
aRv = UpdateContext(aCx, aContextOptions); nsresult rv = UpdateContext(aCx, aContextOptions, aRv);
if (aRv.Failed()) { if (NS_FAILED(rv)) {
aRv = NS_OK; // See bug 645792 // See bug 645792 and bug 1215072.
// We want to throw only if dictionary initialization fails,
// so only in case aRv has been set to some error value.
return nullptr; return nullptr;
} }
} else { } else {
@ -190,7 +192,8 @@ CanvasRenderingContextHelper::GetContext(JSContext* aCx,
nsresult nsresult
CanvasRenderingContextHelper::UpdateContext(JSContext* aCx, CanvasRenderingContextHelper::UpdateContext(JSContext* aCx,
JS::Handle<JS::Value> aNewContextOptions) JS::Handle<JS::Value> aNewContextOptions,
ErrorResult& aRvForDictionaryInit)
{ {
if (!mCurrentContext) if (!mCurrentContext)
return NS_OK; return NS_OK;
@ -205,7 +208,8 @@ CanvasRenderingContextHelper::UpdateContext(JSContext* aCx,
return rv; return rv;
} }
rv = currentContext->SetContextOptions(aCx, aNewContextOptions); rv = currentContext->SetContextOptions(aCx, aNewContextOptions,
aRvForDictionaryInit);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
mCurrentContext = nullptr; mCurrentContext = nullptr;
return rv; return rv;

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

@ -44,7 +44,8 @@ public:
protected: protected:
virtual nsresult UpdateContext(JSContext* aCx, virtual nsresult UpdateContext(JSContext* aCx,
JS::Handle<JS::Value> aNewContextOptions); JS::Handle<JS::Value> aNewContextOptions,
ErrorResult& aRvForDictionaryInit);
virtual nsresult ParseParams(JSContext* aCx, virtual nsresult ParseParams(JSContext* aCx,
const nsAString& aType, const nsAString& aType,

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

@ -158,7 +158,8 @@ private:
void CanvasAttrChanged() void CanvasAttrChanged()
{ {
mAttrDirty = true; mAttrDirty = true;
UpdateContext(nullptr, JS::NullHandleValue); ErrorResult dummy;
UpdateContext(nullptr, JS::NullHandleValue, dummy);
} }
bool mAttrDirty; bool mAttrDirty;

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

@ -347,13 +347,17 @@ WebGLContext::OnMemoryPressure()
// //
NS_IMETHODIMP NS_IMETHODIMP
WebGLContext::SetContextOptions(JSContext* cx, JS::Handle<JS::Value> options) WebGLContext::SetContextOptions(JSContext* cx, JS::Handle<JS::Value> options,
ErrorResult& aRvForDictionaryInit)
{ {
if (options.isNullOrUndefined() && mOptionsFrozen) if (options.isNullOrUndefined() && mOptionsFrozen)
return NS_OK; return NS_OK;
WebGLContextAttributes attributes; WebGLContextAttributes attributes;
NS_ENSURE_TRUE(attributes.Init(cx, options), NS_ERROR_UNEXPECTED); if (!attributes.Init(cx, options)) {
aRvForDictionaryInit.Throw(NS_ERROR_UNEXPECTED);
return NS_ERROR_UNEXPECTED;
}
WebGLContextOptions newOpts; WebGLContextOptions newOpts;

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

@ -249,7 +249,8 @@ public:
NS_IMETHOD SetIsOpaque(bool) override { return NS_OK; }; NS_IMETHOD SetIsOpaque(bool) override { return NS_OK; };
bool GetIsOpaque() override { return false; } bool GetIsOpaque() override { return false; }
NS_IMETHOD SetContextOptions(JSContext* cx, NS_IMETHOD SetContextOptions(JSContext* cx,
JS::Handle<JS::Value> options) override; JS::Handle<JS::Value> options,
ErrorResult& aRvForDictionaryInit) override;
NS_IMETHOD SetIsIPC(bool) override { NS_IMETHOD SetIsIPC(bool) override {
return NS_ERROR_NOT_IMPLEMENTED; return NS_ERROR_NOT_IMPLEMENTED;

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

@ -149,7 +149,11 @@ public:
// Redraw the dirty rectangle of this canvas. // Redraw the dirty rectangle of this canvas.
NS_IMETHOD Redraw(const gfxRect &dirty) = 0; NS_IMETHOD Redraw(const gfxRect &dirty) = 0;
NS_IMETHOD SetContextOptions(JSContext* cx, JS::Handle<JS::Value> options) { return NS_OK; } NS_IMETHOD SetContextOptions(JSContext* cx, JS::Handle<JS::Value> options,
mozilla::ErrorResult& aRvForDictionaryInit)
{
return NS_OK;
}
// return true and fills in the bounding rect if elementis a child and has a hit region. // return true and fills in the bounding rect if elementis a child and has a hit region.
virtual bool GetHitRegionRect(mozilla::dom::Element* element, nsRect& rect) { return false; } virtual bool GetHitRegionRect(mozilla::dom::Element* element, nsRect& rect) { return false; }

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

@ -225,6 +225,7 @@ disabled = bug 407107
[test_bug866575.html] [test_bug866575.html]
skip-if = (toolkit == 'gonk' && debug) #bug 1045153 skip-if = (toolkit == 'gonk' && debug) #bug 1045153
[test_bug902651.html] [test_bug902651.html]
[test_bug1215072.html]
[test_canvas.html] [test_canvas.html]
skip-if = (toolkit == 'gonk' && debug) || (toolkit == 'android' && processor == 'x86') || (android_version == '18' && debug) #debug-only crash; bug 933541 #x86 only bug 913662 #android 4.3 debug bug 1143317 skip-if = (toolkit == 'gonk' && debug) || (toolkit == 'android' && processor == 'x86') || (android_version == '18' && debug) #debug-only crash; bug 933541 #x86 only bug 913662 #android 4.3 debug bug 1143317
[test_canvas_focusring.html] [test_canvas_focusring.html]

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

@ -0,0 +1,41 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1215072
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1215072</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript">
/** Test for Bug 1215072 **/
try {
document.createElement("canvas")
.getContext("webgl", { get stencil() { throw "bah (webgl)"; } });
ok(false);
} catch(ex) {
is(ex, "bah (webgl)", "Should have thrown an exception.");
}
try {
document.createElement("canvas")
.getContext("2d", { get alpha() {throw "bah (2d)"; } });
ok(false);
} catch(ex) {
is(ex, "bah (2d)", "Should have thrown an exception.");
}
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1215072">Mozilla Bug 1215072</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
</html>

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

@ -449,7 +449,8 @@ HTMLCanvasElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
aNameSpaceID == kNameSpaceID_None && aNameSpaceID == kNameSpaceID_None &&
(aName == nsGkAtoms::width || aName == nsGkAtoms::height || aName == nsGkAtoms::moz_opaque)) (aName == nsGkAtoms::width || aName == nsGkAtoms::height || aName == nsGkAtoms::moz_opaque))
{ {
rv = UpdateContext(nullptr, JS::NullHandleValue); ErrorResult dummy;
rv = UpdateContext(nullptr, JS::NullHandleValue, dummy);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
@ -465,7 +466,8 @@ HTMLCanvasElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
aNameSpaceID == kNameSpaceID_None && aNameSpaceID == kNameSpaceID_None &&
(aName == nsGkAtoms::width || aName == nsGkAtoms::height || aName == nsGkAtoms::moz_opaque)) (aName == nsGkAtoms::width || aName == nsGkAtoms::height || aName == nsGkAtoms::moz_opaque))
{ {
rv = UpdateContext(nullptr, JS::NullHandleValue); ErrorResult dummy;
rv = UpdateContext(nullptr, JS::NullHandleValue, dummy);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
return rv; return rv;
@ -911,7 +913,8 @@ HTMLCanvasElement::MozGetIPCContext(const nsAString& aContextId,
mCurrentContext->SetIsIPC(true); mCurrentContext->SetIsIPC(true);
mCurrentContextType = contextType; mCurrentContextType = contextType;
nsresult rv = UpdateContext(nullptr, JS::NullHandleValue); ErrorResult dummy;
nsresult rv = UpdateContext(nullptr, JS::NullHandleValue, dummy);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} else { } else {
// We already have a context of some type. // We already have a context of some type.