Skip to content
Browse files

WebGL implementation for Android

Implementation of WebGL in Android WebKit. Exposes a low level 3D
graphics API based on OpenGL ES 2.0 to JavaScript. WebGL is not compiled
by default. It can be enabled by setting ENABLE_WEBGL = true in your
device BoardConfig.mk or directly in external/webkit/Android.mk.

Includes runtime enablement through Browser Settings -> Labs menu.

Enable WebGL debug logs and FPS timing with: adb shell setprop debug.webgl 1

Includes Cross-origin resource sharing support.

Includes fixes for the following Khronos WebGL 1.0.1. tests:
- premultiplyalpha-test.html
- struct-nesting-exceeds-maximum.html
- index-validation.html
- context-attributes-alpha-depth-stencil-antialias.html
- program-test.html
- object-deletion-behaviour.html

Squashed patches:
-----------------------------------------------------------

WebGL implementation for Android

Implementation of WebGL in Android WebKit. Exposes a low level 3D
graphics API based on OpenGL ES 2.0 to JavaScript. WebGL is not compiled
by default. It can be enabled by setting ENABLE_WEBGL = true in your
device BoardConfig.mk or directly in external/webkit/Android.mk. It is
also disabled by default (in WebSettings.cpp) as required by Khronos
until it reaches 100% conformance.

--
From: Anders Edenbrandt <anders.edenbrandt@sonyericsson.com>
Date: Thu, 26 Jan 2012 11:48:41 +0100

WebGL bug fixes and updates

Some updates:
  - stability fixes
  - image decoder
  - redesign of how the FBOs are used
  - other bug fixes

--
From: Anders Edenbrandt <anders.edenbrandt@sonyericsson.com>
Date: Tue, 31 Jan 2012 17:20:13 +0100

WebGL code cleanup and bug fixes

--
From: Anders Edenbrandt <anders.edenbrandt@sonyericsson.com>
Date: Thu Mar 15 10:15:33 2012 +0100

More improvements and bug fixes

Updates:
- cleaned up buffer handling, allowing for arbitrary number of buffers
- removed rect from invalidation
- removed screen update request from drawGL
- releasing buffers when the browser is paused
- added missing method 'slice' for typed arrays
- fixed bug in bindFramebuffer

https://www.codeaurora.org/gitweb/quic/la/?p=platform/external/webkit.git;a=commit;h=c72ff2aa562941d94ceb51ba685d60809ca882a6

Updates to fix some test failures in Khronos Conformance Test Suite:

  - Increase max identifier length in shaders to 256
  - Add length check on uniforms and attributes
  - Add minimal support for compressed textures
      (that is, just return the correct error codes)
  - Add support for Uint8ClampedByteArray
  - Modify how error checking is done on framebuffer operations
  - Activate the GL_OES_packed_depth_stencil extension
  - Activate the GL_OES_texture_float extension

https://www.codeaurora.org/gitweb/quic/la/?p=platform/external/webkit.git;a=commit;h=5bfe05848c12a2894697fbb503cfa79981eb96bd

Fix WebGL 1.0.1 premultiplyalpha-test conformance test

Fixing bug with toDataURL when called against a Canvas in which WebGL
content is being rendered and make sure paintRenderingResultsToImageData
isn't used for the premultiplied case.

ihttps://www.codeaurora.org/gitweb/quic/la/?p=platform/external/webkit.git;a=commit;h=5834a1e00f89d898a7a0039d47916b196e40a2c8

Update ANGLE to r1009 to fix WebGL 1.0.1 conformance test

Fixes struct-nesting-exceeds-maximum Khronos WebGL conformance test.

https://www.codeaurora.org/gitweb/quic/la/?p=platform/external/webkit.git;a=commit;h=ae2392db6360b41a5717f3770a9e63b1bcea45d6

vertexAttribPointer needs to reject large negative offsets

https://bugs.webkit.org/show_bug.cgi?id=85117

Reviewed by Kenneth Russell.

Source/WebCore:

* html/canvas/WebGLRenderingContext.cpp: Use long long for GLsizeiptr and GLintptr
(WebCore):
(WebCore::WebGLRenderingContext::bufferData):
(WebCore::WebGLRenderingContext::bufferSubData):
(WebCore::WebGLRenderingContext::drawElements):
(WebCore::WebGLRenderingContext::getVertexAttribOffset):
(WebCore::WebGLRenderingContext::vertexAttribPointer):
* html/canvas/WebGLRenderingContext.h: Ditto
(WebGLRenderingContext):
* html/canvas/WebGLRenderingContext.idl: Ditto

LayoutTests:

* fast/canvas/webgl/index-validation-expected.txt:
* fast/canvas/webgl/index-validation.html: Add a test case for large negative offset.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@116374 268f45cc-cd09-0410-ab3c-d52691b4dbfc
https://www.codeaurora.org/gitweb/quic/la/?p=platform/external/webkit.git;a=commit;h=b3a02a0942a0e2c44d23961382145fad6016b2ef

Fix for context-attributes-alpha-depth-stencil-antialias

Support for alpha, depth and stencil to fix WebGL Khronos 1.0.1
conformance test. Report back that antialiasing is not supported on our
platform.

https://www.codeaurora.org/gitweb/quic/la/?p=platform/external/webkit.git;a=commit;h=22e98195ac73e7e12a59d5b9a42dfc4e2252b475

WebGLRenderingContext should defer caching program info
https://bugs.webkit.org/show_bug.cgi?id=83513

Reviewed by Kenneth Russell.

* html/canvas/WebGLProgram.cpp:
(WebCore::WebGLProgram::WebGLProgram):
(WebCore::WebGLProgram::numActiveAttribLocations): call cacheInfoIfNeeded();
(WebCore::WebGLProgram::getActiveAttribLocation): Ditto.
(WebCore::WebGLProgram::isUsingVertexAttrib0): Ditto.
(WebCore::WebGLProgram::getLinkStatus): Ditto.
(WebCore):
(WebCore::WebGLProgram::cacheActiveAttribLocations):
(WebCore::WebGLProgram::cacheInfoIfNeeded): Cache link status, active attire locations, etc if needed.
(WebCore::WebGLProgram::increaseLinkCount): also invalidate cached info.
* html/canvas/WebGLProgram.h:
(WebGLProgram):
* html/canvas/WebGLRenderingContext.cpp:
(WebCore):
(WebCore::WebGLRenderingContext::linkProgram): Do not cache program info immediately.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@113915 268f45cc-cd09-0410-ab3c-d52691b4dbfc
https://www.codeaurora.org/gitweb/quic/la/?p=platform/external/webkit.git;a=commit;h=66bc9c1b9eb5151b1b236199d0eeb17df0557b47

Runtime enablement of WebGL

Hooks up with the Java side to enable/disable WebGL through the debug
menu.

https://www.codeaurora.org/gitweb/quic/la/?p=platform/external/webkit.git;a=commit;h=75aab57859de45a0aaec5a7cad41a12111e9a82e

Support the usage of CORS for WebGL and the 2D canvas

Factor CORS request preparation out of DocumentThreadableLoader
https://bugs.webkit.org/show_bug.cgi?id=61209

2011-05-20  Adam Barth  <abarth@webkit.org>

        Reviewed by Alexey Proskuryakov.

        Factor CORS request preparation out of DocumentThreadableLoader
        https://bugs.webkit.org/show_bug.cgi?id=61209

        DocumentThreadableLoader has two jobs:

        1) Proxy loads between threads.
        2) Run the CORS state machine.

        This patch begins the work of separating those concerns, allowing CORS
        to be used elsewhere in the loading pipeline.  In particular, this
        patch moves knowledge of how to prepare CORS requests out of
        DocumentThreadableLoder.

        * loader/CrossOriginAccessControl.cpp:
        (WebCore::isOnAccessControlSimpleRequestHeaderWhitelist):
        (WebCore::updateRequestForAccessControl):
        (WebCore::createAccessControlPreflightRequest):
        * loader/CrossOriginAccessControl.h:
        * loader/DocumentThreadableLoader.cpp:
        (WebCore::DocumentThreadableLoader::DocumentThreadableLoader):
        (WebCore::DocumentThreadableLoader::makeSimpleCrossOriginAccessRequest):
        (WebCore::DocumentThreadableLoader::makeCrossOriginAccessRequestWithPreflight):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@86980 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Add rel type prerender to distinguish prerender from prefetch
https://bugs.webkit.org/show_bug.cgi?id=61079

2011-05-21  Gavin Peters  <gavinp@chromium.org>

        Reviewed by Adam Barth.

        Add rel type prerender to distinguish prerender from prefetch
        https://bugs.webkit.org/show_bug.cgi?id=61079

        Chrome right now uses <link rel=prefetch ...> for one of two things,
        to warm the cache in the same way as firefox, or to launch a speculative
        rendering of a web page, for faster "loading" when the user navigates to it.

        This new rel type will let us distinguish the two cases; the rel type prerender
        isn't used on the web today, but the Google Web Search example prerendering application
        is ready to experiment with it.

        * fast/dom/HTMLLinkElement/prerender-expected.txt: Added.
        * fast/dom/HTMLLinkElement/prerender.html: Added.
        * platform/gtk/Skipped:
        * platform/mac/Skipped:
        * platform/qt/Skipped:
        * platform/win/Skipped:

2011-05-21  Gavin Peters  <gavinp@chromium.org>

        Reviewed by Adam Barth.

        Add rel type prerender to distinguish prerender from prefetch
        https://bugs.webkit.org/show_bug.cgi?id=61079

        Chrome right now uses <link rel=prefetch ...> for one of two things,
        to warm the cache in the same way as firefox, or to launch a speculative
        rendering of a web page, for faster "loading" when the user navigates to it.

        This new rel type will let us distinguish the two cases; the rel type prerender
        isn't used on the web today, but the Google Web Search example prerendering application
        is ready to experiment with it.

        Test: fast/dom/HTMLLinkElement/prerender.html

        * html/HTMLLinkElement.cpp:
        (WebCore::HTMLLinkElement::tokenizeRelAttribute):
        (WebCore::HTMLLinkElement::process):
        * html/HTMLLinkElement.h:
        (WebCore::HTMLLinkElement::RelAttribute::RelAttribute):
        * loader/cache/CachedResource.cpp:
        (WebCore::defaultPriorityForResourceType):
        * loader/cache/CachedResource.h:
        (WebCore::CachedResource::isLinkResource):
        * loader/cache/CachedResourceLoader.cpp:
        (WebCore::createResource):
        (WebCore::CachedResourceLoader::requestLinkResource):
        (WebCore::CachedResourceLoader::canRequest):
        * loader/cache/CachedResourceLoader.h:
        * loader/cache/CachedResourceRequest.cpp:
        (WebCore::cachedResourceTypeToTargetType):
        (WebCore::CachedResourceRequest::load):
        * platform/network/ResourceRequestBase.h:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@87020 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Make CachedResource take a ResourceRequest instead of just a url string.

2011-05-24  Nate Chapin  <japhet@chromium.org>

        Reviewed by Adam Barth.

        Change CachedResources to take a ResourceRequest instead of
        a url in their constructors and provide a very minimal set of
        cases for avoiding reusing a CachedResource. The ResourceRequest
        part of this change requires pushing responsibility
        for calling Document::completeURL() to the caller, instead of
        CachedResourceLoader, since ResourceRequest ASSERTs if it
        is constructed with an invalid url.

        https://bugs.webkit.org/show_bug.cgi?id=61318

        Refactor, no new tests.

        * css/CSSFontSelector.cpp:
        (WebCore::CSSFontSelector::addFontFaceRule):
        * css/CSSImageValue.cpp:
        (WebCore::CSSImageValue::cachedImage):
        * css/CSSImportRule.cpp:
        (WebCore::CSSImportRule::insertedIntoParent):
        * dom/ProcessingInstruction.cpp:
        (WebCore::ProcessingInstruction::checkStyleSheet):
        * dom/ScriptElement.cpp:
        (WebCore::ScriptElement::requestScript):
        * html/HTMLLinkElement.cpp:
        (WebCore::HTMLLinkElement::process):
        * loader/ImageLoader.cpp:
        (WebCore::ImageLoader::updateFromElement):
        * loader/cache/CachedCSSStyleSheet.cpp:
        (WebCore::CachedCSSStyleSheet::CachedCSSStyleSheet):
        (WebCore::CachedCSSStyleSheet::didAddClient):
        (WebCore::CachedCSSStyleSheet::checkNotify):
        * loader/cache/CachedCSSStyleSheet.h:
        * loader/cache/CachedFont.cpp:
        (WebCore::CachedFont::CachedFont):
        * loader/cache/CachedFont.h:
        * loader/cache/CachedImage.cpp:
        (WebCore::CachedImage::CachedImage):
        (WebCore::CachedImage::checkShouldPaintBrokenImage):
        * loader/cache/CachedImage.h:
        * loader/cache/CachedResource.cpp:
        (WebCore::CachedResource::CachedResource):
        (WebCore::reuseRequest):
        (WebCore::CachedResource::allowReuseOfRequest):
        (WebCore::CachedResource::removeClient):
        (WebCore::CachedResource::canUseCacheValidator):
        * loader/cache/CachedResource.h:
        (WebCore::CachedResource::resourceRequest):
        (WebCore::CachedResource::url):
        * loader/cache/CachedResourceLoader.cpp:
        * loader/cache/CachedResourceLoader.h:
        * loader/cache/CachedResourceRequest.cpp:
        (WebCore::CachedResourceRequest::load):
        * loader/cache/CachedScript.cpp:
        (WebCore::CachedScript::CachedScript):
        * loader/cache/CachedScript.h:
        * loader/cache/CachedXSLStyleSheet.cpp:
        (WebCore::CachedXSLStyleSheet::CachedXSLStyleSheet):
        (WebCore::CachedXSLStyleSheet::didAddClient):
        (WebCore::CachedXSLStyleSheet::checkNotify):
        * loader/cache/CachedXSLStyleSheet.h:
        * svg/SVGFEImageElement.cpp:
        (WebCore::SVGFEImageElement::requestImageResource):
        * svg/SVGFontFaceUriElement.cpp:
        (WebCore::SVGFontFaceUriElement::loadFont):
        * xml/XSLImportRule.cpp:
        (WebCore::XSLImportRule::loadSheet):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@87239 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Support cross-origin property for images

2011-05-26  Adam Barth  <abarth@webkit.org>

        Reviewed by Eric Seidel.

        Support cross-origin property for images
        https://bugs.webkit.org/show_bug.cgi?id=61015

        Test various cases involving CORS requests and canvas tainting.

        * http/tests/security/canvas-remote-read-remote-image-allowed-expected.txt: Added.
        * http/tests/security/canvas-remote-read-remote-image-allowed-with-credentials-expected.txt: Added.
        * http/tests/security/canvas-remote-read-remote-image-allowed-with-credentials.html: Added.
        * http/tests/security/canvas-remote-read-remote-image-allowed.html: Added.
        * http/tests/security/canvas-remote-read-remote-image-blocked-no-crossorigin-expected.txt: Added.
        * http/tests/security/canvas-remote-read-remote-image-blocked-no-crossorigin.html: Added.
        * http/tests/security/resources/abe-allow-credentials.php: Added.
        * http/tests/security/resources/abe-allow-star.php: Added.
2011-05-26  Adam Barth  <abarth@webkit.org>

        Reviewed by Eric Seidel.

        Support cross-origin property for images
        https://bugs.webkit.org/show_bug.cgi?id=61015

        This patch add support for the crossorigin attribute of images and
        teaches 2D canvas to respect that flag and not taint a canvas if the
        image drawn on the canvas is allowed by CORS.

        While I was editing this code, I couldn't resist a couple touch-up
        changes.

        Tests: http/tests/security/canvas-remote-read-remote-image-allowed-with-credentials.html
               http/tests/security/canvas-remote-read-remote-image-allowed.html
               http/tests/security/canvas-remote-read-remote-image-blocked-no-crossorigin.html

        * html/HTMLAttributeNames.in:
        * html/HTMLCanvasElement.cpp:
        (WebCore::HTMLCanvasElement::securityOrigin):
        * html/HTMLCanvasElement.h:
        * html/HTMLImageElement.idl:
        * html/canvas/CanvasRenderingContext.cpp:
        (WebCore::CanvasRenderingContext::checkOrigin):
        * html/canvas/CanvasRenderingContext2D.cpp:
        (WebCore::CanvasRenderingContext2D::createPattern):
        * loader/ImageLoader.cpp:
        (WebCore::ImageLoader::updateFromElement):
        * loader/cache/CachedResource.cpp:
        (WebCore::CachedResource::passesAccessControlCheck):
        * loader/cache/CachedResource.h:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@87473 268f45cc-cd09-0410-ab3c-d52691b4dbfc

HTMLVideoElement::currentSrc() should return a KURL

2011-05-27  Adam Barth  <abarth@webkit.org>

        Reviewed by Eric Seidel.

        HTMLVideoElement::currentSrc() should return a KURL
        https://bugs.webkit.org/show_bug.cgi?id=61578

        I suspect we got into this mess because the author of this code didn't
        know about the URL attribute in WebKit IDL, which is super useful!

        Bad news: The line of code in question seems to have another bug, which
        I've documented in a FIXME.  Let the yak shaving continue!

        * html/HTMLMediaElement.cpp:
        (WebCore::urlForLogging):
        (WebCore::HTMLMediaElement::loadResource):
        (WebCore::HTMLMediaElement::isSafeToLoadURL):
        (WebCore::HTMLMediaElement::selectNextSourceChild):
        (WebCore::HTMLMediaElement::getPluginProxyParams):
        * html/HTMLMediaElement.h:
        (WebCore::HTMLMediaElement::currentSrc):
        (WebCore::HTMLMediaElement::currentURL):
        * html/canvas/CanvasRenderingContext.cpp:
        (WebCore::CanvasRenderingContext::checkOrigin):
        * rendering/HitTestResult.cpp:
        (WebCore::HitTestResult::absoluteMediaURL):
            - This complete URL call was unnecessary because currentSrc is
              already absolute.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@87539 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Disallow use of cross-domain media (images, video) in WebGL

2011-06-09  Kenneth Russell  <kbr@google.com>

        Reviewed by Adam Barth.

        Disallow use of cross-domain media (images, video) in WebGL
        https://bugs.webkit.org/show_bug.cgi?id=62257

        Updated WebGL implementation to track recent spec updates in this area.

        Tests: http/tests/security/webgl-remote-read-remote-image-allowed-with-credentials.html
               http/tests/security/webgl-remote-read-remote-image-allowed.html
               http/tests/security/webgl-remote-read-remote-image-blocked-no-crossorigin.html

        * html/canvas/CanvasRenderingContext.cpp:
        (WebCore::CanvasRenderingContext::wouldTaintOrigin):
        (WebCore::CanvasRenderingContext::checkOrigin):
        * html/canvas/CanvasRenderingContext.h:
        (WebCore::CanvasRenderingContext::checkOrigin):
        * html/canvas/WebGLRenderingContext.cpp:
        (WebCore::WebGLRenderingContext::readPixels):
        (WebCore::WebGLRenderingContext::texImage2D):
        (WebCore::WebGLRenderingContext::videoFrameToImage):
        (WebCore::WebGLRenderingContext::texSubImage2D):
        * html/canvas/WebGLRenderingContext.h:
2011-06-09  Kenneth Russell  <kbr@google.com>

        Reviewed by Adam Barth.

        Disallow use of cross-domain media (images, video) in WebGL
        https://bugs.webkit.org/show_bug.cgi?id=62257

        Updated origin-clean-conformance.html to track upstream version in
        Khronos repository. Added new layout tests mirroring those added
        in bug 61015 which verify that new CORS support for images is
        working in the context of WebGL.

        Verified new tests in WebKit and Chromium. Skipped tests on
        platforms where WebGL is disabled.

        * http/tests/canvas/webgl/origin-clean-conformance-expected.txt:
        * http/tests/canvas/webgl/origin-clean-conformance.html:
        * http/tests/security/webgl-remote-read-remote-image-allowed-expected.txt: Added.
        * http/tests/security/webgl-remote-read-remote-image-allowed-with-credentials-expected.txt: Added.
        * http/tests/security/webgl-remote-read-remote-image-allowed-with-credentials.html: Added.
        * http/tests/security/webgl-remote-read-remote-image-allowed.html: Added.
        * http/tests/security/webgl-remote-read-remote-image-blocked-no-crossorigin-expected.txt: Added.
        * http/tests/security/webgl-remote-read-remote-image-blocked-no-crossorigin.html: Added.
        * platform/gtk/Skipped:
        * platform/mac-leopard/Skipped:
        * platform/mac-wk2/Skipped:
        * platform/qt/Skipped:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@88489 268f45cc-cd09-0410-ab3c-d52691b4dbfc
https://www.codeaurora.org/gitweb/quic/la/?p=platform/external/webkit.git;a=commit;h=0ddd7c1d91c08fbee6c99b79fa9971a7ac914384

Runtime enablement of WebGL logs

Allows enabling WebGL method level logging using:

adb shell setprop debug.webgl 1

https://www.codeaurora.org/gitweb/quic/la/?p=platform/external/webkit.git;a=commit;h=307d4a2b5b20f2609497ceaea1eca2e29a8a781f

Adding WebGL FPS timing to logs

Samples WebGL average FPS every 15 frames and outputs to WebGL debug log.
TODO: Add setting to browser debug settings that overlays FPS on web
pages.

Postpone deleteRenderbuffer/deleteTexture until all framebuffer attachment points are removed.
https://bugs.webkit.org/show_bug.cgi?id=74741

Reviewed by Kenneth Russell.

Source/WebCore:

Use WebGLObject's attachment count mechanism to track if a renderbuffer/texture
is still attached to framebuffers, and if its deletion should be delated or not.

* html/canvas/WebGLFramebuffer.cpp:
(WebCore::WebGLFramebuffer::setAttachmentForBoundFramebuffer):
(WebCore::WebGLFramebuffer::getAttachment):
(WebCore::WebGLFramebuffer::removeAttachmentFromBoundFramebuffer):
(WebCore::WebGLFramebuffer::deleteObjectImpl):
(WebCore::WebGLFramebuffer::isBound):
* html/canvas/WebGLFramebuffer.h:

LayoutTests:

* fast/canvas/webgl/object-deletion-behaviour-expected.txt:
* fast/canvas/webgl/object-deletion-behaviour.html: synced with khronos side.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@103272 268f45cc-cd09-0410-ab3c-d52691b4dbfc
https://www.codeaurora.org/gitweb/quic/la/?p=platform/external/webkit.git;a=commit;h=9def386340c74f2a745fb041b1cb11daa30d1a82

-----------------------------------------------------------

Change-Id: If1bf1f53f8050889a22959288e9e3874ea823dd2

Conflicts:

	Source/WebCore/html/HTMLCanvasElement.cpp
	Source/WebCore/html/HTMLCanvasElement.h
	Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp
  • Loading branch information...
1 parent a78859f commit 953613899dc0816916de4223dda9984ae7bb74fb @plafayet plafayet committed with Whitehawkx Dec 29, 2011
Showing with 114,249 additions and 2,659 deletions.
  1. +46 −1 Android.mk
  2. +98,699 −0 LayoutTests/ChangeLog
  3. +322 −0 LayoutTests/fast/canvas/webgl/object-deletion-behaviour-expected.txt
  4. +419 −0 LayoutTests/fast/canvas/webgl/object-deletion-behaviour.html
  5. +29 −0 LayoutTests/http/tests/canvas/webgl/origin-clean-conformance-expected.txt
  6. +218 −0 LayoutTests/http/tests/canvas/webgl/origin-clean-conformance.html
  7. +15 −0 LayoutTests/http/tests/security/canvas-remote-read-remote-image-allowed-expected.txt
  8. +15 −0 ...utTests/http/tests/security/canvas-remote-read-remote-image-allowed-with-credentials-expected.txt
  9. +108 −0 LayoutTests/http/tests/security/canvas-remote-read-remote-image-allowed-with-credentials.html
  10. +108 −0 LayoutTests/http/tests/security/canvas-remote-read-remote-image-allowed.html
  11. +15 −0 LayoutTests/http/tests/security/canvas-remote-read-remote-image-blocked-no-crossorigin-expected.txt
  12. +108 −0 LayoutTests/http/tests/security/canvas-remote-read-remote-image-blocked-no-crossorigin.html
  13. +12 −0 LayoutTests/http/tests/security/resources/abe-allow-credentials.php
  14. +11 −0 LayoutTests/http/tests/security/resources/abe-allow-star.php
  15. +13 −0 LayoutTests/http/tests/security/webgl-remote-read-remote-image-allowed-expected.txt
  16. +13 −0 LayoutTests/http/tests/security/webgl-remote-read-remote-image-allowed-with-credentials-expected.txt
  17. +101 −0 LayoutTests/http/tests/security/webgl-remote-read-remote-image-allowed-with-credentials.html
  18. +101 −0 LayoutTests/http/tests/security/webgl-remote-read-remote-image-allowed.html
  19. +13 −0 LayoutTests/http/tests/security/webgl-remote-read-remote-image-blocked-no-crossorigin-expected.txt
  20. +103 −0 LayoutTests/http/tests/security/webgl-remote-read-remote-image-blocked-no-crossorigin.html
  21. +4 −0 Source/JavaScriptCore/wtf/Platform.h
  22. +66 −2 Source/ThirdParty/ANGLE/ANGLE.xcodeproj/project.pbxproj
  23. +77 −0 Source/ThirdParty/ANGLE/Android.mk
  24. +1,725 −0 Source/ThirdParty/ANGLE/ChangeLog
  25. +27 −39 Source/ThirdParty/ANGLE/Configurations/Base.xcconfig
  26. +84 −0 Source/ThirdParty/ANGLE/Configurations/CompilerVersion.xcconfig
  27. +5 −4 Source/ThirdParty/ANGLE/Configurations/DebugRelease.xcconfig
  28. +134 −8 Source/ThirdParty/ANGLE/include/EGL/eglext.h
  29. +21 −2 Source/ThirdParty/ANGLE/include/EGL/eglplatform.h
  30. +725 −62 Source/ThirdParty/ANGLE/include/GLES2/gl2ext.h
  31. +88 −31 Source/ThirdParty/ANGLE/include/GLSLANG/ShaderLang.h
  32. +268 −182 Source/ThirdParty/ANGLE/src/build_angle.xcodeproj/project.pbxproj
  33. +47 −0 Source/ThirdParty/ANGLE/src/common/RefCountObject.cpp
  34. +65 −0 Source/ThirdParty/ANGLE/src/common/RefCountObject.h
  35. +103 −44 Source/ThirdParty/ANGLE/src/common/debug.cpp
  36. +58 −20 Source/ThirdParty/ANGLE/src/common/debug.h
  37. +10 −0 Source/ThirdParty/ANGLE/src/common/version.h
  38. +5 −0 Source/ThirdParty/ANGLE/src/compiler/BaseTypes.h
  39. +437 −0 Source/ThirdParty/ANGLE/src/compiler/BuiltInFunctionEmulator.cpp
  40. +103 −0 Source/ThirdParty/ANGLE/src/compiler/BuiltInFunctionEmulator.h
  41. +11 −2 Source/ThirdParty/ANGLE/src/compiler/CodeGenGLSL.cpp
  42. +8 −2 Source/ThirdParty/ANGLE/src/compiler/CodeGenHLSL.cpp
  43. +89 −8 Source/ThirdParty/ANGLE/src/compiler/Compiler.cpp
  44. +18 −50 Source/ThirdParty/ANGLE/src/compiler/ConstantUnion.h
  45. +125 −0 Source/ThirdParty/ANGLE/src/compiler/DetectRecursion.cpp
  46. +60 −0 Source/ThirdParty/ANGLE/src/compiler/DetectRecursion.h
  47. +18 −1 Source/ThirdParty/ANGLE/src/compiler/ExtensionBehavior.h
  48. +215 −0 Source/ThirdParty/ANGLE/src/compiler/ForLoopUnroll.cpp
  49. +48 −0 Source/ThirdParty/ANGLE/src/compiler/ForLoopUnroll.h
  50. +33 −21 Source/ThirdParty/ANGLE/src/compiler/Initialize.cpp
  51. +4 −6 Source/ThirdParty/ANGLE/src/compiler/Intermediate.cpp
  52. +120 −0 Source/ThirdParty/ANGLE/src/compiler/MapLongVariableNames.cpp
  53. +60 −0 Source/ThirdParty/ANGLE/src/compiler/MapLongVariableNames.h
  54. +22 −0 Source/ThirdParty/ANGLE/src/compiler/OutputESSL.cpp
  55. +22 −0 Source/ThirdParty/ANGLE/src/compiler/OutputESSL.h
  56. +3 −676 Source/ThirdParty/ANGLE/src/compiler/OutputGLSL.cpp
  57. +4 −32 Source/ThirdParty/ANGLE/src/compiler/OutputGLSL.h
  58. +720 −0 Source/ThirdParty/ANGLE/src/compiler/OutputGLSLBase.cpp
  59. +54 −0 Source/ThirdParty/ANGLE/src/compiler/OutputGLSLBase.h
  60. +332 −89 Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.cpp
  61. +17 −6 Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.h
  62. +67 −9 Source/ThirdParty/ANGLE/src/compiler/ParseHelper.cpp
  63. +46 −15 Source/ThirdParty/ANGLE/src/compiler/ParseHelper.h
  64. +9 −2 Source/ThirdParty/ANGLE/src/compiler/PoolAlloc.cpp
  65. +13 −7 Source/ThirdParty/ANGLE/src/compiler/PoolAlloc.h
  66. +20 −3 Source/ThirdParty/ANGLE/src/compiler/ShHandle.h
  67. +49 −20 Source/ThirdParty/ANGLE/src/compiler/ShaderLang.cpp
  68. +20 −0 Source/ThirdParty/ANGLE/src/compiler/SymbolTable.cpp
  69. +6 −0 Source/ThirdParty/ANGLE/src/compiler/SymbolTable.h
  70. +40 −0 Source/ThirdParty/ANGLE/src/compiler/TranslatorESSL.cpp
  71. +23 −0 Source/ThirdParty/ANGLE/src/compiler/TranslatorESSL.h
  72. +4 −0 Source/ThirdParty/ANGLE/src/compiler/TranslatorGLSL.cpp
  73. +22 −4 Source/ThirdParty/ANGLE/src/compiler/Types.h
  74. +39 −8 Source/ThirdParty/ANGLE/src/compiler/UnfoldSelect.cpp
  75. +2 −1 Source/ThirdParty/ANGLE/src/compiler/UnfoldSelect.h
  76. +68 −25 Source/ThirdParty/ANGLE/src/compiler/ValidateLimitations.cpp
  77. +1 −4 Source/ThirdParty/ANGLE/src/compiler/ValidateLimitations.h
  78. +18 −6 Source/ThirdParty/ANGLE/src/compiler/VariableInfo.cpp
  79. +8 −1 Source/ThirdParty/ANGLE/src/compiler/VariableInfo.h
  80. +21 −14 Source/ThirdParty/ANGLE/src/compiler/VersionGLSL.cpp
  81. +4 −2 Source/ThirdParty/ANGLE/src/compiler/VersionGLSL.h
  82. +27 −0 Source/ThirdParty/ANGLE/src/compiler/generate_parser.sh
  83. +18 −2 Source/ThirdParty/ANGLE/src/compiler/glslang.l
  84. +124 −61 Source/ThirdParty/ANGLE/src/compiler/glslang.y
  85. +389 −355 Source/ThirdParty/ANGLE/src/compiler/glslang_lex.cpp
  86. +815 −688 Source/ThirdParty/ANGLE/src/compiler/glslang_tab.cpp
  87. +107 −103 Source/ThirdParty/ANGLE/src/compiler/glslang_tab.h
  88. +2 −0 Source/ThirdParty/ANGLE/src/compiler/intermOut.cpp
  89. +37 −6 Source/ThirdParty/ANGLE/src/compiler/intermediate.h
  90. +2 −1 Source/ThirdParty/ANGLE/src/compiler/osinclude.h
  91. +3 −2 Source/ThirdParty/ANGLE/src/compiler/preprocessor/atom.c
  92. +2 −1 Source/ThirdParty/ANGLE/src/compiler/preprocessor/compile.h
  93. +84 −25 Source/ThirdParty/ANGLE/src/compiler/preprocessor/cpp.c
  94. +6 −6 Source/ThirdParty/ANGLE/src/compiler/preprocessor/cppstruct.c
  95. +21 −0 Source/ThirdParty/ANGLE/src/compiler/preprocessor/length_limits.h
  96. +4 −0 Source/ThirdParty/ANGLE/src/compiler/preprocessor/memory.c
  97. +139 −0 Source/ThirdParty/ANGLE/src/compiler/preprocessor/new/Context.cpp
  98. +60 −0 Source/ThirdParty/ANGLE/src/compiler/preprocessor/new/Context.h
  99. +165 −0 Source/ThirdParty/ANGLE/src/compiler/preprocessor/new/Input.cpp
  100. +74 −0 Source/ThirdParty/ANGLE/src/compiler/preprocessor/new/Input.h
  101. +45 −0 Source/ThirdParty/ANGLE/src/compiler/preprocessor/new/Macro.cpp
  102. +51 −0 Source/ThirdParty/ANGLE/src/compiler/preprocessor/new/Macro.h
  103. +53 −0 Source/ThirdParty/ANGLE/src/compiler/preprocessor/new/Preprocessor.cpp
  104. +42 −0 Source/ThirdParty/ANGLE/src/compiler/preprocessor/new/Preprocessor.h
  105. +55 −0 Source/ThirdParty/ANGLE/src/compiler/preprocessor/new/Token.cpp
  106. +48 −0 Source/ThirdParty/ANGLE/src/compiler/preprocessor/new/Token.h
  107. +27 −0 Source/ThirdParty/ANGLE/src/compiler/preprocessor/new/generate_parser.sh
  108. +181 −0 Source/ThirdParty/ANGLE/src/compiler/preprocessor/new/pp.l
  109. +225 −0 Source/ThirdParty/ANGLE/src/compiler/preprocessor/new/pp.y
  110. +2,268 −0 Source/ThirdParty/ANGLE/src/compiler/preprocessor/new/pp_lex.cpp
  111. +2,072 −0 Source/ThirdParty/ANGLE/src/compiler/preprocessor/new/pp_tab.cpp
  112. +119 −0 Source/ThirdParty/ANGLE/src/compiler/preprocessor/new/pp_tab.h
Sorry, we could not display the entire diff because it was too big.
View
47 Android.mk
@@ -23,6 +23,11 @@
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
+# Control WebGL compiling in webkit.
+ifneq ($(ENABLE_WEBGL),true)
+ ENABLE_WEBGL = false
+endif
+
# Control SVG compiling in webkit.
# Default is true unless explictly disabled.
ifneq ($(ENABLE_SVG),false)
@@ -92,6 +97,14 @@ LOCAL_C_INCLUDES := \
frameworks/base/core/jni/android/graphics \
frameworks/base/include
+LOCAL_C_INCLUDES += external/libpng \
+ external/zlib
+
+ifeq ($(ENABLE_WEBGL),true)
+LOCAL_C_INCLUDES += frameworks/native/include/gui \
+ frameworks/native/include/private/gui
+endif
+
# Add Source/ for the include of <JavaScriptCore/config.h> from WebCore/config.h
LOCAL_C_INCLUDES := $(LOCAL_C_INCLUDES) \
$(SOURCE_PATH)
@@ -144,6 +157,7 @@ LOCAL_C_INCLUDES := $(LOCAL_C_INCLUDES) \
$(WEBCORE_PATH)/platform/image-decoders/jpeg \
$(WEBCORE_PATH)/platform/image-decoders/png \
$(WEBCORE_PATH)/platform/image-decoders/webp \
+ $(WEBCORE_PATH)/platform/image-encoders/skia \
$(WEBCORE_PATH)/platform/mock \
$(WEBCORE_PATH)/platform/network \
$(WEBCORE_PATH)/platform/network/android \
@@ -200,6 +214,10 @@ LOCAL_C_INCLUDES := $(LOCAL_C_INCLUDES) \
LOCAL_CFLAGS += -DWEBKIT_IMPLEMENTATION=1
+# Needed for ANGLE
+LOCAL_C_INCLUDES := $(LOCAL_C_INCLUDES) \
+ $(SOURCE_PATH)/ThirdParty/ANGLE/include/GLSLANG
+
# Include WTF source file.
d := Source/JavaScriptCore
LOCAL_PATH := $(BASE_PATH)/$d
@@ -294,6 +312,10 @@ endif
LOCAL_CFLAGS += -DENABLE_REQUEST_ANIMATION_FRAME=1
+ifeq ($(ENABLE_WEBGL),true)
+LOCAL_CFLAGS += -DENABLE_WEBGL
+endif
+
# LOCAL_LDLIBS is used in simulator builds only and simulator builds are only
# valid on Linux
LOCAL_LDLIBS += -lpthread -ldl
@@ -334,13 +356,17 @@ ifeq ($(SUPPORT_COMPLEX_SCRIPTS),true)
LOCAL_C_INCLUDES := $(LOCAL_C_INCLUDES) \
external/harfbuzz/src \
external/harfbuzz/contrib
-LOCAL_SHARED_LIBRARIES += libharfbuzz
+LOCAL_SHARED_LIBRARIES += libharfbuzz libjpeg
LOCAL_CFLAGS += -DSUPPORT_COMPLEX_SCRIPTS=1
endif
# Build the list of static libraries
LOCAL_STATIC_LIBRARIES := libxml2 libxslt libhyphenation libskiagpu libv8
+ifeq ($(ENABLE_WEBGL),true)
+LOCAL_STATIC_LIBRARIES += libpng
+endif
+
ifeq ($(ENABLE_AUTOFILL),true)
LOCAL_SHARED_LIBRARIES += libexpat
endif
@@ -360,6 +386,24 @@ WEBKIT_STATIC_LIBRARIES := $(LOCAL_STATIC_LIBRARIES)
# Build the library all at once
include $(BUILD_STATIC_LIBRARY)
+# Build ANGLE as a static library.
+include $(CLEAR_VARS)
+LOCAL_MODULE := libangle
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE_TAGS := optional
+ANGLE_PATH := $(SOURCE_PATH)/ThirdParty/ANGLE
+LOCAL_SHARED_LIBRARIES := $(WEBKIT_SHARED_LIBRARIES)
+include $(ANGLE_PATH)/Android.mk
+# Redefine LOCAL_SRC_FILES with the correct prefix
+LOCAL_SRC_FILES := $(addprefix Source/ThirdParty/ANGLE/src/compiler/,$(LOCAL_SRC_FILES))
+# Append angle intermediate include paths to the WebKit include list.
+LOCAL_C_INCLUDES := $(WEBKIT_C_INCLUDES) \
+ $(ANGLE_PATH)/include \
+ $(ANGLE_PATH)/src
+LOCAL_CFLAGS += -Wno-error=non-virtual-dtor
+# Build libangle
+include $(BUILD_STATIC_LIBRARY)
+
# Now build the shared library using only the exported jni entry point. This
# will strip out any unused code from the entry point.
include $(CLEAR_VARS)
@@ -371,6 +415,7 @@ LOCAL_MODULE := libwebcore
LOCAL_LDLIBS := $(WEBKIT_LDLIBS)
LOCAL_SHARED_LIBRARIES := $(WEBKIT_SHARED_LIBRARIES)
LOCAL_STATIC_LIBRARIES := libwebcore $(WEBKIT_STATIC_LIBRARIES)
+LOCAL_STATIC_LIBRARIES += libangle
LOCAL_LDFLAGS := -fvisibility=hidden
LOCAL_CFLAGS := $(WEBKIT_CFLAGS)
LOCAL_CPPFLAGS := $(WEBKIT_CPPFLAGS)
View
98,699 LayoutTests/ChangeLog
98,699 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
322 LayoutTests/fast/canvas/webgl/object-deletion-behaviour-expected.txt
@@ -0,0 +1,322 @@
+Tests deletion behavior for texture, renderbuffer, shader, and program
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+shader and program deletion
+PASS vertex shader loaded
+PASS fragment shader loaded
+PASS program is non-null.
+PASS gl.attachShader(program, vertexShader) was expected value: NO_ERROR.
+PASS gl.attachShader(program, fragmentShader) was expected value: NO_ERROR.
+PASS gl.linkProgram(program) was expected value: NO_ERROR.
+PASS gl.getProgramParameter(program, gl.LINK_STATUS) is true
+PASS gl.useProgram(program) was expected value: NO_ERROR.
+PASS gl.deleteShader(vertexShader) was expected value: NO_ERROR.
+PASS gl.isShader(vertexShader) is true
+PASS gl.getShaderParameter(vertexShader, gl.DELETE_STATUS) is true
+PASS gl.detachShader(program, vertexShader) was expected value: NO_ERROR.
+PASS gl.isShader(vertexShader) is false
+PASS gl.deleteShader(fragmentShader) was expected value: NO_ERROR.
+PASS gl.isShader(fragmentShader) is true
+PASS gl.getShaderParameter(fragmentShader, gl.DELETE_STATUS) is true
+PASS gl.deleteProgram(program) was expected value: NO_ERROR.
+PASS gl.isProgram(program) is true
+PASS gl.getProgramParameter(program, gl.DELETE_STATUS) is true
+PASS gl.useProgram(null) was expected value: NO_ERROR.
+PASS gl.isProgram(program) is false
+PASS gl.isShader(fragmentShader) is false
+
+texture deletion
+PASS fbo is non-null.
+PASS fbo2 is non-null.
+PASS fbo3 is non-null.
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, fbo) was expected value: NO_ERROR.
+PASS tex is non-null.
+PASS gl.bindTexture(gl.TEXTURE_2D, tex) was expected value: NO_ERROR.
+PASS gl.getParameter(gl.TEXTURE_BINDING_2D) is tex
+PASS gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0) was expected value: NO_ERROR.
+PASS gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) is tex
+PASS gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) is gl.TEXTURE
+PASS gl.deleteTexture(tex) was expected value: NO_ERROR.
+PASS gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) is gl.NONE
+PASS gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) was expected value: INVALID_ENUM.
+PASS gl.isTexture(tex) is false
+PASS gl.getParameter(gl.TEXTURE_BINDING_2D) is null
+PASS gl.bindTexture(gl.TEXTURE_2D, tex) was expected value: NO_ERROR.
+PASS gl.getParameter(gl.TEXTURE_BINDING_2D) is null
+PASS texCubeMap is non-null.
+PASS gl.bindTexture(gl.TEXTURE_CUBE_MAP, texCubeMap) was expected value: NO_ERROR.
+PASS gl.getParameter(gl.TEXTURE_BINDING_CUBE_MAP) is texCubeMap
+PASS gl.deleteTexture(texCubeMap) was expected value: NO_ERROR.
+PASS gl.isTexture(texCubeMap) is false
+PASS gl.getParameter(gl.TEXTURE_BINDING_CUBE_MAP) is null
+PASS gl.bindTexture(gl.TEXTURE_CUBE_MAP, texCubeMap) was expected value: NO_ERROR.
+PASS gl.getParameter(gl.TEXTURE_BINDING_CUBE_MAP) is null
+PASS t is non-null.
+PASS gl.bindTexture(gl.TEXTURE_2D, t) was expected value: NO_ERROR.
+PASS gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) was expected value: NO_ERROR.
+PASS gl.deleteTexture(t) was expected value: NO_ERROR.
+PASS gl.bindTexture(gl.TEXTURE_2D, t) was expected value: NO_ERROR.
+PASS gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) was expected value: INVALID_OPERATION.
+PASS t2 is non-null.
+PASS gl.activeTexture(gl.TEXTURE0) was expected value: NO_ERROR.
+PASS gl.bindTexture(gl.TEXTURE_2D, t2) was expected value: NO_ERROR.
+PASS gl.getParameter(gl.TEXTURE_BINDING_2D) is t2
+PASS gl.activeTexture(gl.TEXTURE1) was expected value: NO_ERROR.
+PASS gl.bindTexture(gl.TEXTURE_2D, t2) was expected value: NO_ERROR.
+PASS gl.getParameter(gl.TEXTURE_BINDING_2D) is t2
+PASS gl.deleteTexture(t2) was expected value: NO_ERROR.
+PASS gl.getParameter(gl.TEXTURE_BINDING_2D) is null
+PASS gl.activeTexture(gl.TEXTURE0) was expected value: NO_ERROR.
+PASS gl.getParameter(gl.TEXTURE_BINDING_2D) is null
+
+renderbuffer deletion
+PASS rbo is non-null.
+PASS rbo2 is non-null.
+PASS rbo3 is non-null.
+PASS gl.bindRenderbuffer(gl.RENDERBUFFER, rbo) was expected value: NO_ERROR.
+PASS gl.getParameter(gl.RENDERBUFFER_BINDING) is rbo
+PASS gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo) was expected value: NO_ERROR.
+PASS gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) is rbo
+PASS gl.deleteRenderbuffer(rbo) was expected value: NO_ERROR.
+PASS gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) is gl.NONE
+PASS gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) was expected value: INVALID_ENUM.
+PASS gl.isRenderbuffer(rbo) is false
+PASS gl.getParameter(gl.RENDERBUFFER_BINDING) is null
+PASS gl.bindRenderbuffer(gl.RENDERBUFFER, rbo) was expected value: NO_ERROR.
+PASS gl.getParameter(gl.RENDERBUFFER_BINDING) is null
+PASS gl.bindRenderbuffer(gl.RENDERBUFFER, rbo2) was expected value: NO_ERROR.
+PASS gl.getParameter(gl.RENDERBUFFER_BINDING) is rbo2
+PASS gl.deleteRenderbuffer(rbo3) was expected value: NO_ERROR.
+PASS gl.getParameter(gl.RENDERBUFFER_BINDING) is rbo2
+
+using deleted renderbuffer
+PASS gl.bindRenderbuffer(gl.RENDERBUFFER, rbo) was expected value: NO_ERROR.
+PASS gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16) was expected value: NO_ERROR.
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, fbo) was expected value: NO_ERROR.
+PASS gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo) was expected value: NO_ERROR.
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, null) was expected value: NO_ERROR.
+PASS gl.clearColor(1,0,0,1) was expected value: NO_ERROR.
+PASS gl.clear(gl.COLOR_BUFFER_BIT) was expected value: NO_ERROR.
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, fbo) was expected value: NO_ERROR.
+PASS gl.clearColor(0,1,0,1) was expected value: NO_ERROR.
+PASS gl.clear(gl.COLOR_BUFFER_BIT) was expected value: NO_ERROR.
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, null) was expected value: NO_ERROR.
+PASS gl.deleteRenderbuffer(rbo) was expected value: NO_ERROR.
+PASS backbuffer should be red
+PASS wtu.checkCanvasRect(gl, 0, 0, 16, 16, [255,0,0,255], "backbuffer should be red") was expected value: NO_ERROR.
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, fbo) was expected value: NO_ERROR.
+PASS fbo should be green
+PASS wtu.checkCanvasRect(gl, 0, 0, 16, 16, [0,255,0,255], "fbo should be green") was expected value: NO_ERROR.
+PASS gl.clearColor(0,0,1,1) was expected value: NO_ERROR.
+PASS gl.clear(gl.COLOR_BUFFER_BIT) was expected value: NO_ERROR.
+PASS fbo should be blue
+PASS wtu.checkCanvasRect(gl, 0, 0, 16, 16, [0,0,255,255], "fbo should be blue") was expected value: NO_ERROR.
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, null) was expected value: NO_ERROR.
+PASS backbuffer should be red
+PASS wtu.checkCanvasRect(gl, 0, 0, 16, 16, [255,0,0,255], "backbuffer should be red") was expected value: NO_ERROR.
+
+renderbuffer attached twice to same framebuffer
+PASS gl.bindRenderbuffer(gl.RENDERBUFFER, rbo) was expected value: NO_ERROR.
+PASS gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16) was expected value: NO_ERROR.
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, fbo) was expected value: NO_ERROR.
+PASS gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo) was expected value: NO_ERROR.
+PASS gl.bindRenderbuffer(gl.RENDERBUFFER, rbo2) was expected value: NO_ERROR.
+PASS gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16) was expected value: NO_ERROR.
+PASS gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rbo2) was expected value: NO_ERROR.
+PASS gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, rbo2) was expected value: NO_ERROR.
+PASS gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) is rbo2
+PASS gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) is rbo2
+PASS gl.checkFramebufferStatus(gl.FRAMEBUFFER) is not gl.FRAMEBUFFER_COMPLETE
+PASS gl.deleteRenderbuffer(rbo2) was expected value: NO_ERROR.
+PASS gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) is gl.NONE
+PASS gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) is gl.NONE
+PASS gl.checkFramebufferStatus(gl.FRAMEBUFFER) is gl.FRAMEBUFFER_COMPLETE
+PASS gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) is rbo
+PASS gl.deleteRenderbuffer(rbo) was expected value: NO_ERROR.
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, null) was expected value: NO_ERROR.
+
+using deleted texture
+PASS gl.bindTexture(gl.TEXTURE_2D, tex) was expected value: NO_ERROR.
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, fbo) was expected value: NO_ERROR.
+PASS gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0) was expected value: NO_ERROR.
+PASS gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null) was expected value: NO_ERROR.
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, fbo) was expected value: NO_ERROR.
+PASS gl.clearColor(0,1,0,1) was expected value: NO_ERROR.
+PASS gl.clear(gl.COLOR_BUFFER_BIT) was expected value: NO_ERROR.
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, null) was expected value: NO_ERROR.
+PASS gl.deleteTexture(tex) was expected value: NO_ERROR.
+PASS backbuffer should be red
+PASS wtu.checkCanvasRect(gl, 0, 0, 1, 1, [255,0,0,255], "backbuffer should be red") was expected value: NO_ERROR.
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, fbo) was expected value: NO_ERROR.
+PASS fbo should be green
+PASS wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0,255,0,255], "fbo should be green") was expected value: NO_ERROR.
+PASS gl.clearColor(0,0,1,1) was expected value: NO_ERROR.
+PASS gl.clear(gl.COLOR_BUFFER_BIT) was expected value: NO_ERROR.
+PASS fbo should be blue
+PASS wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0,0,255,255], "fbo should be blue") was expected value: NO_ERROR.
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, null) was expected value: NO_ERROR.
+PASS backbuffer should be red
+PASS wtu.checkCanvasRect(gl, 0, 0, 16, 16, [255,0,0,255], "backbuffer should be red") was expected value: NO_ERROR.
+
+using deleted renderbuffer
+PASS rbo is non-null.
+PASS gl.bindRenderbuffer(gl.RENDERBUFFER, rbo) was expected value: NO_ERROR.
+PASS gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16) was expected value: NO_ERROR.
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, fbo) was expected value: NO_ERROR.
+PASS gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo) was expected value: NO_ERROR.
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2) was expected value: NO_ERROR.
+PASS gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo) was expected value: NO_ERROR.
+PASS gl.checkFramebufferStatus(gl.FRAMEBUFFER) is gl.FRAMEBUFFER_COMPLETE
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, null) was expected value: NO_ERROR.
+PASS gl.clearColor(1,0,0,1) was expected value: NO_ERROR.
+PASS gl.clear(gl.COLOR_BUFFER_BIT) was expected value: NO_ERROR.
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, fbo) was expected value: NO_ERROR.
+PASS gl.clearColor(0,1,0,1) was expected value: NO_ERROR.
+PASS gl.clear(gl.COLOR_BUFFER_BIT) was expected value: NO_ERROR.
+PASS gl.deleteRenderbuffer(rbo) was expected value: NO_ERROR.
+PASS gl.checkFramebufferStatus(gl.FRAMEBUFFER) is not gl.FRAMEBUFFER_COMPLETE
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2) was expected value: NO_ERROR.
+PASS fbo should be green
+PASS wtu.checkCanvasRect(gl, 0, 0, 16, 16, [0,255,0,255], "fbo should be green") was expected value: NO_ERROR.
+PASS gl.clearColor(0,0,1,1) was expected value: NO_ERROR.
+PASS gl.clear(gl.COLOR_BUFFER_BIT) was expected value: NO_ERROR.
+PASS fbo should be blue
+PASS wtu.checkCanvasRect(gl, 0, 0, 16, 16, [0,0,255,255], "fbo should be blue") was expected value: NO_ERROR.
+PASS gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) is rbo
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, fbo) was expected value: NO_ERROR.
+PASS gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) was expected value: INVALID_ENUM.
+PASS gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) was expected value: NO_ERROR.
+PASS gl.checkFramebufferStatus(gl.FRAMEBUFFER) is not gl.FRAMEBUFFER_COMPLETE
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, null) was expected value: NO_ERROR.
+PASS backbuffer should be red
+PASS wtu.checkCanvasRect(gl, 0, 0, 16, 16, [255,0,0,255], "backbuffer should be red") was expected value: NO_ERROR.
+
+using deleted texture
+PASS tex is non-null.
+PASS gl.bindTexture(gl.TEXTURE_2D, tex) was expected value: NO_ERROR.
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, fbo) was expected value: NO_ERROR.
+PASS gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0) was expected value: NO_ERROR.
+PASS gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null) was expected value: NO_ERROR.
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2) was expected value: NO_ERROR.
+PASS gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0) was expected value: NO_ERROR.
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, fbo) was expected value: NO_ERROR.
+PASS gl.clearColor(0,1,0,1) was expected value: NO_ERROR.
+PASS gl.clear(gl.COLOR_BUFFER_BIT) was expected value: NO_ERROR.
+PASS gl.deleteTexture(tex) was expected value: NO_ERROR.
+PASS gl.checkFramebufferStatus(gl.FRAMEBUFFER) is not gl.FRAMEBUFFER_COMPLETE
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2) was expected value: NO_ERROR.
+PASS gl.checkFramebufferStatus(gl.FRAMEBUFFER) is gl.FRAMEBUFFER_COMPLETE
+PASS fbo should be green
+PASS wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0,255,0,255], "fbo should be green") was expected value: NO_ERROR.
+PASS gl.clearColor(0,0,1,1) was expected value: NO_ERROR.
+PASS gl.clear(gl.COLOR_BUFFER_BIT) was expected value: NO_ERROR.
+PASS fbo should be blue
+PASS wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0,0,255,255], "fbo should be blue") was expected value: NO_ERROR.
+PASS gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) is tex
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, fbo) was expected value: NO_ERROR.
+PASS gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) was expected value: INVALID_ENUM.
+PASS gl.checkFramebufferStatus(gl.FRAMEBUFFER) is not gl.FRAMEBUFFER_COMPLETE
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, null) was expected value: NO_ERROR.
+PASS backbuffer should be red
+PASS wtu.checkCanvasRect(gl, 0, 0, 16, 16, [255,0,0,255], "backbuffer should be red") was expected value: NO_ERROR.
+
+buffer deletion
+PASS buffer is non-null.
+PASS gl.bindBuffer(gl.ARRAY_BUFFER, buffer) was expected value: NO_ERROR.
+PASS gl.getParameter(gl.ARRAY_BUFFER_BINDING) is buffer
+PASS gl.deleteBuffer(buffer) was expected value: NO_ERROR.
+PASS gl.isBuffer(buffer) is false
+PASS gl.getParameter(gl.ARRAY_BUFFER_BINDING) is null
+PASS gl.bindBuffer(gl.ARRAY_BUFFER, buffer) was expected value: NO_ERROR.
+PASS gl.getParameter(gl.ARRAY_BUFFER_BINDING) is null
+PASS buffer2 is non-null.
+PASS gl.bindBuffer(gl.ARRAY_BUFFER, buffer2) was expected value: NO_ERROR.
+PASS gl.getParameter(gl.ARRAY_BUFFER_BINDING) is buffer2
+PASS gl.bindBuffer(gl.ARRAY_BUFFER, null) was expected value: NO_ERROR.
+PASS gl.getParameter(gl.ARRAY_BUFFER_BINDING) is null
+PASS gl.deleteBuffer(buffer2) was expected value: NO_ERROR.
+PASS gl.isBuffer(buffer2) is false
+PASS gl.bindBuffer(gl.ARRAY_BUFFER, buffer2) was expected value: NO_ERROR.
+PASS gl.getParameter(gl.ARRAY_BUFFER_BINDING) is null
+PASS bufferElement is non-null.
+PASS gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufferElement) was expected value: NO_ERROR.
+PASS gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING) is bufferElement
+PASS gl.deleteBuffer(bufferElement) was expected value: NO_ERROR.
+PASS gl.isBuffer(bufferElement) is false
+PASS gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING) is null
+PASS gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufferElement) was expected value: NO_ERROR.
+PASS gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING) is null
+PASS b is non-null.
+PASS gl.bindBuffer(gl.ARRAY_BUFFER, b) was expected value: NO_ERROR.
+PASS gl.bufferData(gl.ARRAY_BUFFER, 1, gl.STATIC_DRAW) was expected value: NO_ERROR.
+PASS gl.deleteBuffer(b) was expected value: NO_ERROR.
+PASS gl.bindBuffer(gl.ARRAY_BUFFER, b) was expected value: NO_ERROR.
+PASS gl.bufferData(gl.ARRAY_BUFFER, 1, gl.STATIC_DRAW) was expected value: INVALID_OPERATION.
+PASS b1 is non-null.
+PASS gl.bindBuffer(gl.ARRAY_BUFFER, b1); was expected value: NO_ERROR.
+PASS gl.enableVertexAttribArray(1); was expected value: NO_ERROR.
+PASS gl.vertexAttribPointer(1, 4, gl.FLOAT, false, 0, 0); was expected value: NO_ERROR.
+PASS b2 is non-null.
+PASS gl.bindBuffer(gl.ARRAY_BUFFER, b2); was expected value: NO_ERROR.
+PASS gl.enableVertexAttribArray(2); was expected value: NO_ERROR.
+PASS gl.vertexAttribPointer(2, 4, gl.FLOAT, false, 0, 0); was expected value: NO_ERROR.
+PASS gl.enableVertexAttribArray(3); was expected value: NO_ERROR.
+PASS gl.vertexAttribPointer(3, 4, gl.FLOAT, false, 0, 0); was expected value: NO_ERROR.
+PASS gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING) is b1
+PASS gl.getVertexAttrib(2, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING) is b2
+PASS gl.getVertexAttrib(3, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING) is b2
+PASS gl.deleteBuffer(b2); was expected value: NO_ERROR.
+PASS gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING) is b1
+PASS gl.getVertexAttrib(2, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING) is null
+PASS gl.getVertexAttrib(3, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING) is null
+PASS gl.deleteBuffer(b1); was expected value: NO_ERROR.
+PASS gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING) is null
+
+framebuffer deletion
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, fbo) was expected value: NO_ERROR.
+PASS gl.getParameter(gl.FRAMEBUFFER_BINDING) is fbo
+PASS gl.deleteFramebuffer(fbo) was expected value: NO_ERROR.
+PASS gl.isFramebuffer(fbo) is false
+PASS gl.getParameter(gl.FRAMEBUFFER_BINDING) is null
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, fbo) was expected value: NO_ERROR.
+PASS gl.getParameter(gl.FRAMEBUFFER_BINDING) is null
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2) was expected value: NO_ERROR.
+PASS gl.getParameter(gl.FRAMEBUFFER_BINDING) is fbo2
+PASS gl.deleteFramebuffer(fbo3) was expected value: NO_ERROR.
+PASS gl.getParameter(gl.FRAMEBUFFER_BINDING) is fbo2
+PASS fbo is non-null.
+PASS rbo is non-null.
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, fbo) was expected value: NO_ERROR.
+PASS gl.bindRenderbuffer(gl.RENDERBUFFER, rbo) was expected value: NO_ERROR.
+PASS gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16) was expected value: NO_ERROR.
+PASS gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo) was expected value: NO_ERROR.
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, null) was expected value: NO_ERROR.
+PASS gl.clearColor(1,0,0,1) was expected value: NO_ERROR.
+PASS gl.clear(gl.COLOR_BUFFER_BIT) was expected value: NO_ERROR.
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, fbo) was expected value: NO_ERROR.
+PASS gl.clearColor(0,1,0,1) was expected value: NO_ERROR.
+PASS gl.clear(gl.COLOR_BUFFER_BIT) was expected value: NO_ERROR.
+PASS fbo should be green
+PASS wtu.checkCanvasRect(gl, 0, 0, 16, 16, [0,255,0,255], "fbo should be green") was expected value: NO_ERROR.
+PASS outside fbo should be black
+PASS wtu.checkCanvasRect(gl, 16, 16, 1, 1, [0,0,0,0], "outside fbo should be black") was expected value: NO_ERROR.
+PASS gl.deleteFramebuffer(fbo) was expected value: NO_ERROR.
+PASS backbuffer should be red
+PASS wtu.checkCanvasRect(gl, 0, 0, 300, 150, [255,0,0,255], "backbuffer should be red") was expected value: NO_ERROR.
+PASS outside backbuffer should be black
+PASS wtu.checkCanvasRect(gl, 300, 0, 300, 300, [0,0,0,0], "outside backbuffer should be black") was expected value: NO_ERROR.
+PASS outside backbuffer should be black
+PASS wtu.checkCanvasRect(gl, 0, 150, 300, 300, [0,0,0,0], "outside backbuffer should be black") was expected value: NO_ERROR.
+PASS gl.clearColor(0,1,0,1) was expected value: NO_ERROR.
+PASS gl.clear(gl.COLOR_BUFFER_BIT) was expected value: NO_ERROR.
+PASS fbo should be green
+PASS wtu.checkCanvasRect(gl, 0, 0, 300, 150, [0,255,0,255], "fbo should be green") was expected value: NO_ERROR.
+PASS gl.bindFramebuffer(gl.FRAMEBUFFER, null) was expected value: NO_ERROR.
+PASS fbo should be green
+PASS wtu.checkCanvasRect(gl, 0, 0, 300, 150, [0,255,0,255], "fbo should be green") was expected value: NO_ERROR.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
View
419 LayoutTests/fast/canvas/webgl/object-deletion-behaviour.html
@@ -0,0 +1,419 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<script src="../../js/resources/js-test-pre.js"></script>
+<script src="resources/webgl-test.js"></script>
+<script src="resources/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+description("Tests deletion behavior for texture, renderbuffer, shader, and program");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext();
+var shouldGenerateGLError = wtu.shouldGenerateGLError;
+
+debug("");
+debug("shader and program deletion");
+
+var vertexShader = wtu.loadStandardVertexShader(gl);
+assertMsg(vertexShader, "vertex shader loaded");
+var fragmentShader = wtu.loadStandardFragmentShader(gl);
+assertMsg(fragmentShader, "fragment shader loaded");
+
+var program = gl.createProgram();
+shouldBeNonNull("program");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.attachShader(program, vertexShader)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.attachShader(program, fragmentShader)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.linkProgram(program)");
+shouldBeTrue("gl.getProgramParameter(program, gl.LINK_STATUS)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.useProgram(program)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteShader(vertexShader)");
+shouldBeTrue("gl.isShader(vertexShader)");
+shouldBeTrue("gl.getShaderParameter(vertexShader, gl.DELETE_STATUS)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.detachShader(program, vertexShader)");
+shouldBeFalse("gl.isShader(vertexShader)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteShader(fragmentShader)");
+shouldBeTrue("gl.isShader(fragmentShader)");
+shouldBeTrue("gl.getShaderParameter(fragmentShader, gl.DELETE_STATUS)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteProgram(program)");
+shouldBeTrue("gl.isProgram(program)");
+shouldBeTrue("gl.getProgramParameter(program, gl.DELETE_STATUS)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.useProgram(null)");
+shouldBeFalse("gl.isProgram(program)");
+shouldBeFalse("gl.isShader(fragmentShader)");
+
+debug("");
+debug("texture deletion");
+
+var fbo = gl.createFramebuffer(), fbo2 = gl.createFramebuffer(), fbo3 = gl.createFramebuffer();
+shouldBeNonNull("fbo");
+shouldBeNonNull("fbo2");
+shouldBeNonNull("fbo3");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+
+var tex = gl.createTexture();
+shouldBeNonNull("tex");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, tex)");
+shouldBe("gl.getParameter(gl.TEXTURE_BINDING_2D)", "tex");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0)");
+shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", "tex");
+shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)", "gl.TEXTURE");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteTexture(tex)");
+// Deleting a texture bound to the currently-bound fbo is the same as
+// detaching the textue from fbo first, then delete the texture.
+shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)", "gl.NONE");
+shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)");
+shouldBeFalse("gl.isTexture(tex)");
+shouldBeNull("gl.getParameter(gl.TEXTURE_BINDING_2D)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, tex)");
+shouldBeNull("gl.getParameter(gl.TEXTURE_BINDING_2D)");
+
+var texCubeMap = gl.createTexture();
+shouldBeNonNull("texCubeMap");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_CUBE_MAP, texCubeMap)");
+shouldBe("gl.getParameter(gl.TEXTURE_BINDING_CUBE_MAP)", "texCubeMap");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteTexture(texCubeMap)");
+shouldBeFalse("gl.isTexture(texCubeMap)");
+shouldBeNull("gl.getParameter(gl.TEXTURE_BINDING_CUBE_MAP)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_CUBE_MAP, texCubeMap)");
+shouldBeNull("gl.getParameter(gl.TEXTURE_BINDING_CUBE_MAP)");
+
+var t = gl.createTexture();
+shouldBeNonNull("t");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, t)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteTexture(t)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, t)");
+shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)");
+
+var t2 = gl.createTexture();
+shouldBeNonNull("t2");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.activeTexture(gl.TEXTURE0)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, t2)");
+shouldBe("gl.getParameter(gl.TEXTURE_BINDING_2D)", "t2");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.activeTexture(gl.TEXTURE1)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, t2)");
+shouldBe("gl.getParameter(gl.TEXTURE_BINDING_2D)", "t2");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteTexture(t2)");
+shouldBeNull("gl.getParameter(gl.TEXTURE_BINDING_2D)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.activeTexture(gl.TEXTURE0)");
+shouldBeNull("gl.getParameter(gl.TEXTURE_BINDING_2D)");
+
+debug("");
+debug("renderbuffer deletion");
+
+var rbo = gl.createRenderbuffer(), rbo2 = gl.createRenderbuffer(), rbo3 = gl.createRenderbuffer();
+shouldBeNonNull("rbo");
+shouldBeNonNull("rbo2");
+shouldBeNonNull("rbo3");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, rbo)");
+shouldBe("gl.getParameter(gl.RENDERBUFFER_BINDING)", "rbo");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo)");
+shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", "rbo");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteRenderbuffer(rbo)");
+// Deleting a renderbuffer bound to the currently-bound fbo is the same as
+// detaching the renderbuffer from fbo first, then delete the renderbuffer.
+shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)", "gl.NONE");
+shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)");
+shouldBeFalse("gl.isRenderbuffer(rbo)");
+shouldBeNull("gl.getParameter(gl.RENDERBUFFER_BINDING)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, rbo)");
+shouldBeNull("gl.getParameter(gl.RENDERBUFFER_BINDING)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, rbo2)");
+shouldBe("gl.getParameter(gl.RENDERBUFFER_BINDING)", "rbo2");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteRenderbuffer(rbo3)");
+shouldBe("gl.getParameter(gl.RENDERBUFFER_BINDING)", "rbo2");
+
+debug("");
+debug("using deleted renderbuffer");
+rbo = gl.createRenderbuffer();
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, rbo)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo)");
+if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
+ // make backbuffer red
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(1,0,0,1)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
+ // make fbo green
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,1,0,1)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
+ // Bind backbuffer.
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
+ // delete renderbuffer. It should still be attached to fbo though.
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteRenderbuffer(rbo)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [255,0,0,255], "backbuffer should be red")');
+ // Use fbo that has deleted rbo.
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [0,255,0,255], "fbo should be green")');
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,0,1,1)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [0,0,255,255], "fbo should be blue")');
+ // Bind backbuffer.
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [255,0,0,255], "backbuffer should be red")');
+}
+
+debug("");
+debug("renderbuffer attached twice to same framebuffer");
+rbo = gl.createRenderbuffer();
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, rbo)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo)");
+if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
+ rbo2 = gl.createRenderbuffer();
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, rbo2)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16)");
+ // attach rbo2 at two attachment points incompatible with it
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rbo2)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, rbo2)");
+ shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", "rbo2");
+ shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", "rbo2");
+ // fbo can't be complete as rbo2 is attached at incompatible attachment points
+ shouldNotBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ // now we delete rbo2, which detaches it from the two attachment points where it currently is attached
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteRenderbuffer(rbo2)");
+ shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)", "gl.NONE");
+ shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)", "gl.NONE");
+ // we should now be in the same state as before with only rbo attached, so fbo should be complete again
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", "rbo");
+}
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteRenderbuffer(rbo)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
+
+
+
+debug("");
+debug("using deleted texture");
+tex = gl.createTexture();
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, tex)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null)");
+if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
+ // make fbo green
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,1,0,1)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
+ // Bind backbuffer.
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
+ // delete texture. It should still be attached to fbo though.
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteTexture(tex)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 1, 1, [255,0,0,255], "backbuffer should be red")');
+ // Use fbo that has deleted texture.
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0,255,0,255], "fbo should be green")');
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,0,1,1)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0,0,255,255], "fbo should be blue")');
+ // Bind backbuffer.
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [255,0,0,255], "backbuffer should be red")');
+}
+
+debug("");
+debug("using deleted renderbuffer");
+rbo = gl.createRenderbuffer();
+shouldBeNonNull("rbo");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, rbo)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo)");
+if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo)");
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ // make backbuffer red
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(1,0,0,1)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
+ // make fbo green
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,1,0,1)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
+ // delete renderbuffer. It should still be attached to fbo2 though.
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteRenderbuffer(rbo)");
+ // fbo has no attachments
+ shouldNotBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ // Use fbo2 that has deleted rbo.
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [0,255,0,255], "fbo should be green")');
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,0,1,1)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [0,0,255,255], "fbo should be blue")');
+ shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", "rbo");
+
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+ shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)");
+ shouldGenerateGLError(gl, gl.NONE, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)");
+ shouldNotBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ // Bind backbuffer.
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [255,0,0,255], "backbuffer should be red")');
+}
+
+debug("");
+debug("using deleted texture");
+tex = gl.createTexture();
+shouldBeNonNull("tex");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, tex)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null)");
+if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0)");
+ // make fbo green
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,1,0,1)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
+ // delete texture. It should still be attached to fbo2 though.
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteTexture(tex)");
+ // fbo has no attachments
+ shouldNotBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ // Use fbo that has deleted texture.
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2)");
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0,255,0,255], "fbo should be green")');
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,0,1,1)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0,0,255,255], "fbo should be blue")');
+ shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", "tex");
+
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+ shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)");
+ shouldNotBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ // Bind backbuffer.
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [255,0,0,255], "backbuffer should be red")');
+}
+
+debug("");
+debug("buffer deletion");
+
+var buffer = gl.createBuffer();
+shouldBeNonNull("buffer");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, buffer)");
+shouldBe("gl.getParameter(gl.ARRAY_BUFFER_BINDING)", "buffer");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(buffer)");
+shouldBeFalse("gl.isBuffer(buffer)");
+shouldBeNull("gl.getParameter(gl.ARRAY_BUFFER_BINDING)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, buffer)");
+shouldBeNull("gl.getParameter(gl.ARRAY_BUFFER_BINDING)");
+
+var buffer2 = gl.createBuffer();
+shouldBeNonNull("buffer2");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, buffer2)");
+shouldBe("gl.getParameter(gl.ARRAY_BUFFER_BINDING)", "buffer2");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, null)");
+shouldBeNull("gl.getParameter(gl.ARRAY_BUFFER_BINDING)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(buffer2)");
+shouldBeFalse("gl.isBuffer(buffer2)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, buffer2)");
+shouldBeNull("gl.getParameter(gl.ARRAY_BUFFER_BINDING)");
+
+var bufferElement = gl.createBuffer();
+shouldBeNonNull("bufferElement");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufferElement)");
+shouldBe("gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING)", "bufferElement");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(bufferElement)");
+shouldBeFalse("gl.isBuffer(bufferElement)");
+shouldBeNull("gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufferElement)");
+shouldBeNull("gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING)");
+
+var b = gl.createBuffer();
+shouldBeNonNull("b");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, b)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bufferData(gl.ARRAY_BUFFER, 1, gl.STATIC_DRAW)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(b)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, b)");
+shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bufferData(gl.ARRAY_BUFFER, 1, gl.STATIC_DRAW)");
+
+var b1 = gl.createBuffer();
+shouldBeNonNull("b1");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, b1);");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.enableVertexAttribArray(1);");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.vertexAttribPointer(1, 4, gl.FLOAT, false, 0, 0);");
+var b2 = gl.createBuffer();
+shouldBeNonNull("b2");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, b2);");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.enableVertexAttribArray(2);");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.vertexAttribPointer(2, 4, gl.FLOAT, false, 0, 0);");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.enableVertexAttribArray(3);");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.vertexAttribPointer(3, 4, gl.FLOAT, false, 0, 0);");
+shouldBe("gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)", "b1");
+shouldBe("gl.getVertexAttrib(2, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)", "b2");
+shouldBe("gl.getVertexAttrib(3, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)", "b2");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(b2);");
+shouldBe("gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)", "b1");
+shouldBeNull("gl.getVertexAttrib(2, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)");
+shouldBeNull("gl.getVertexAttrib(3, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(b1);");
+shouldBeNull("gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)");
+
+debug("");
+debug("framebuffer deletion");
+
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+shouldBe("gl.getParameter(gl.FRAMEBUFFER_BINDING)", "fbo");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteFramebuffer(fbo)");
+shouldBeFalse("gl.isFramebuffer(fbo)");
+shouldBeNull("gl.getParameter(gl.FRAMEBUFFER_BINDING)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+shouldBeNull("gl.getParameter(gl.FRAMEBUFFER_BINDING)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2)");
+shouldBe("gl.getParameter(gl.FRAMEBUFFER_BINDING)", "fbo2");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteFramebuffer(fbo3)");
+shouldBe("gl.getParameter(gl.FRAMEBUFFER_BINDING)", "fbo2");
+
+fbo = gl.createFramebuffer();
+rbo = gl.createRenderbuffer();
+shouldBeNonNull("fbo");
+shouldBeNonNull("rbo");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, rbo)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16)");
+shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo)");
+if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
+ // set backbuffer to red
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(1,0,0,1)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
+ // set framebuffer to green
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,1,0,1)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
+ // check framebuffer
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [0,255,0,255], "fbo should be green")');
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 16, 16, 1, 1, [0,0,0,0], "outside fbo should be black")');
+ // delete framebuffer. because this was the bound fbo the backbuffer should be active now
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteFramebuffer(fbo)");
+ // check backbuffer
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 300, 150, [255,0,0,255], "backbuffer should be red")');
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 300, 0, 300, 300, [0,0,0,0], "outside backbuffer should be black")');
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 150, 300, 300, [0,0,0,0], "outside backbuffer should be black")');
+ // check drawing to backbuffer
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,1,0,1)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 300, 150, [0,255,0,255], "fbo should be green")');
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
+ // check again because many buggy implementations will have bound to the true backbuffer on deleteFramebuffer.
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 300, 150, [0,255,0,255], "fbo should be green")');
+}
+
+successfullyParsed = true;
+</script>
+
+<script src="../../js/resources/js-test-post.js"></script>
+</body>
+</html>
View
29 LayoutTests/http/tests/canvas/webgl/origin-clean-conformance-expected.txt
@@ -0,0 +1,29 @@
+This test ensures WebGL implementations follow proper same-origin restrictions.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+PASS Playable video format found
+PASS img was loaded
+
+check that an attempt to upload an image from another origin throws an exception.
+PASS texImage2D with cross-origin image should throw exception.
+PASS texSubImage2D with cross-origin image should throw exception.
+check that readPixels and toDataURL continue to work against this canvas.
+PASS readPixels should never throw exception -- not possible to dirty origin of WebGL canvas.
+PASS should not throw exception by toDataURL for WebGL canvas, which should stay origin clean.
+check that an attempt to upload a tainted canvas throws an exception.
+PASS should throw exception by toDataURL for NON origin clean canvas.
+PASS texImage2D with NON origin clean canvas should throw exception.
+PASS texSubImage2D with NON origin clean canvas should throw exception.
+check that readPixels and toDataURL continue to work against this canvas.
+PASS readPixels should never throw exception -- not possible to dirty origin of WebGL canvas.
+PASS should not throw exception by toDataURL for WebGL canvas, which should stay origin clean.
+check that an attempt to upload a video from another origin throws an exception.
+PASS texImage2D with cross-origin video should throw exception.
+PASS texSubImage2D with cross-origin video should throw exception.
+check that readPixels and toDataURL continue to work against this canvas.
+PASS readPixels should never throw exception -- not possible to dirty origin of WebGL canvas.
+PASS should not throw exception by toDataURL for WebGL canvas, which should stay origin clean.
+
+TEST COMPLETE
+
View
218 LayoutTests/http/tests/canvas/webgl/origin-clean-conformance.html
@@ -0,0 +1,218 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Origin Restrictions Conformance Tests</title>
+<script>
+function create3DContext(canvas, attributes)
+{
+ if (!canvas)
+ canvas = document.createElement("canvas");
+ var context = null;
+ try {
+ context = canvas.getContext("experimental-webgl", attributes);
+ } catch(e) {}
+ if (!context) {
+ try {
+ context = canvas.getContext("webkit-3d", attributes);
+ } catch(e) {}
+ }
+ if (!context) {
+ try {
+ context = canvas.getContext("moz-webgl", attributes);
+ } catch(e) {}
+ }
+ if (!context) {
+ throw "Unable to fetch WebGL rendering context for Canvas";
+ }
+ return context;
+}
+
+function description(msg)
+{
+ // For MSIE 6 compatibility
+ var span = document.createElement("span");
+ span.innerHTML = '<p>' + msg + '</p><p>On success, you will see a series of "<span class="pass">PASS</span>" messages, followed by "<span class="pass">TEST COMPLETE</span>".</p>';
+ var description = document.getElementById("description");
+ if (description.firstChild)
+ description.replaceChild(span, description.firstChild);
+ else
+ description.appendChild(span);
+}
+
+function debug(msg)
+{
+ var span = document.createElement("span");
+ document.getElementById("console").appendChild(span); // insert it first so XHTML knows the namespace
+ span.innerHTML = msg + '<br />';
+}
+
+function escapeHTML(text)
+{
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/\0/g, "\\0");
+}
+
+function testPassed(msg)
+{
+ debug('<span><span class="pass">PASS</span> ' + escapeHTML(msg) + '</span>');
+}
+
+function testFailed(msg)
+{
+ debug('<span><span class="fail">FAIL</span> ' + escapeHTML(msg) + '</span>');
+}
+
+function assertMsg(assertion, msg) {
+ if (assertion) {
+ testPassed(msg);
+ } else {
+ testFailed(msg);
+ }
+}
+
+// Checks if function throws an exception.
+function causedException(func) {
+ var hadException = false;
+ try {
+ func();
+ } catch(e) {
+ hadException = true;
+ }
+ return hadException;
+}
+
+var testVideo = false;
+
+function init() {
+ var video = document.getElementById("video");
+
+ var base = "http://localhost:8000/resources/";
+ var videos = [
+ ["video/mp4", base + "test.mp4"],
+ ["video/ogg", base + "test.ogv"],
+ ];
+ var videoFile = null;
+ for (var i = 0; i < videos.length; ++i) {
+ if (video.canPlayType(videos[i][0])) {
+ videoFile = videos[i][1];
+ break;
+ }
+ }
+ assertMsg(videoFile, "Playable video format found");
+
+ if (videoFile) {
+ if (window.layoutTestController) {
+ layoutTestController.overridePreference("WebKitWebGLEnabled", "1");
+ layoutTestController.dumpAsText();
+ layoutTestController.waitUntilDone();
+ }
+ video.src = videoFile;
+ video.addEventListener("playing", runTests);
+ video.play();
+ testVideo = true;
+ } else {
+ // Still run the other tests, even if the video failed.
+ runTests();
+ }
+}
+
+function runTests() {
+ description("This test ensures WebGL implementations follow proper same-origin restrictions.");
+ var img = document.getElementById("img");
+ assertMsg(img.width > 0 && img.height > 0, "img was loaded");
+
+ function makeTexImage2D(gl, src) {
+ return function() {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, src);
+ };
+ }
+
+ function makeTexSubImage2D(gl, src) {
+ return function() {
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, src);
+ };
+ }
+
+ function makeReadPixels(gl) {
+ return function() {
+ var buf = new Uint8Array(4);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ };
+ }
+
+ function makeToDataURL(canvas) {
+ return function() {
+ var data = canvas.toDataURL();
+ }
+ }
+
+ var canvas1 = document.getElementById("canvas1");
+ var gl = create3DContext(canvas1);
+
+ debug("");
+ debug("check that an attempt to upload an image from another origin throws an exception.");
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 256, 256, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ assertMsg(causedException(makeTexImage2D(gl, img)),
+ "texImage2D with cross-origin image should throw exception.");
+ assertMsg(causedException(makeTexSubImage2D(gl, img)),
+ "texSubImage2D with cross-origin image should throw exception.");
+
+ debug("check that readPixels and toDataURL continue to work against this canvas.");
+ assertMsg(!causedException(makeReadPixels(gl)),
+ "readPixels should never throw exception -- not possible to dirty origin of WebGL canvas.");
+ assertMsg(!causedException(makeToDataURL(canvas1)),
+ "should not throw exception by toDataURL for WebGL canvas, which should stay origin clean.");
+
+ debug("check that an attempt to upload a tainted canvas throws an exception.");
+ var canvas2 = document.getElementById("canvas2");
+ var ctx2d = canvas2.getContext("2d");
+ ctx2d.drawImage(img, 0, 0);
+ assertMsg(causedException(makeToDataURL(canvas2)),
+ "should throw exception by toDataURL for NON origin clean canvas.");
+ assertMsg(causedException(makeTexImage2D(gl, canvas2)),
+ "texImage2D with NON origin clean canvas should throw exception.");
+ assertMsg(causedException(makeTexSubImage2D(gl, canvas2)),
+ "texSubImage2D with NON origin clean canvas should throw exception.");
+
+ debug("check that readPixels and toDataURL continue to work against this canvas.");
+ assertMsg(!causedException(makeReadPixels(gl)),
+ "readPixels should never throw exception -- not possible to dirty origin of WebGL canvas.");
+ assertMsg(!causedException(makeToDataURL(canvas1)),
+ "should not throw exception by toDataURL for WebGL canvas, which should stay origin clean.");
+
+ if (testVideo) {
+ debug("check that an attempt to upload a video from another origin throws an exception.");
+ var video = document.getElementById("video");
+ assertMsg(causedException(makeTexImage2D(gl, video)),
+ "texImage2D with cross-origin video should throw exception.");
+ assertMsg(causedException(makeTexSubImage2D(gl, video)),
+ "texSubImage2D with cross-origin video should throw exception.");
+
+ debug("check that readPixels and toDataURL continue to work against this canvas.");
+ assertMsg(!causedException(makeReadPixels(gl)),
+ "readPixels should never throw exception -- not possible to dirty origin of WebGL canvas.");
+ assertMsg(!causedException(makeToDataURL(canvas1)),
+ "should not throw exception by toDataURL for WebGL canvas, which should stay origin clean.");
+ }
+
+ debug('<br /><span class="pass">TEST COMPLETE</span>');
+ if (window.layoutTestController)
+ layoutTestController.waitUntilDone();
+ if (window.layoutTestController) {
+ layoutTestController.notifyDone();
+ }
+}
+</script>
+</head>
+<body onload="init()">
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas1"></canvas>
+<canvas id="canvas2"></canvas>
+<img id="img" src="http://localhost:8000/local/resources/abe.png" style="display:none;">
+<video id="video" style="display:none;"/>
+</body>
+</html>
View
15 LayoutTests/http/tests/security/canvas-remote-read-remote-image-allowed-expected.txt
@@ -0,0 +1,15 @@
+Untainted canvas:
+PASS: Calling getImageData() from an untainted canvas was allowed.
+PASS: Calling toDataURL() on an untainted canvas was allowed.
+
+
+Tainted canvas:
+PASS: Calling getImageData() from a canvas tainted by a remote image was allowed.
+PASS: Calling toDataURL() on a canvas CORS-untainted by a remote image was allowed.
+PASS: Calling getImageData() from a canvas tainted by a CORS-untained canvas was allowed.
+PASS: Calling toDataURL() on a canvas CORS-untainted by a CORS-untained canvas was allowed.
+PASS: Calling getImageData() from a canvas tainted by a remote image tainted pattern was allowed.
+PASS: Calling toDataURL() on a canvas CORS-untainted by a remote image tainted pattern was allowed.
+PASS: Calling getImageData() from a canvas tainted by a CORS-untainted canvas pattern was allowed.
+PASS: Calling toDataURL() on a canvas CORS-untainted by a CORS-untainted canvas pattern was allowed.
+
View
15 ...http/tests/security/canvas-remote-read-remote-image-allowed-with-credentials-expected.txt
@@ -0,0 +1,15 @@
+Untainted canvas:
+PASS: Calling getImageData() from an untainted canvas was allowed.
+PASS: Calling toDataURL() on an untainted canvas was allowed.
+
+
+Tainted canvas:
+PASS: Calling getImageData() from a canvas tainted by a remote image was allowed.
+PASS: Calling toDataURL() on a canvas CORS-untainted by a remote image was allowed.
+PASS: Calling getImageData() from a canvas tainted by a CORS-untained canvas was allowed.
+PASS: Calling toDataURL() on a canvas CORS-untainted by a CORS-untained canvas was allowed.
+PASS: Calling getImageData() from a canvas tainted by a remote image tainted pattern was allowed.
+PASS: Calling toDataURL() on a canvas CORS-untainted by a remote image tainted pattern was allowed.
+PASS: Calling getImageData() from a canvas tainted by a CORS-untainted canvas pattern was allowed.
+PASS: Calling toDataURL() on a canvas CORS-untainted by a CORS-untainted canvas pattern was allowed.
+
View
108 ...utTests/http/tests/security/canvas-remote-read-remote-image-allowed-with-credentials.html
@@ -0,0 +1,108 @@
+<pre id="console"></pre>
+<script>
+if (window.layoutTestController) {
+ layoutTestController.dumpAsText();
+ layoutTestController.waitUntilDone();
+}
+
+log = function(msg)
+{
+ document.getElementById('console').appendChild(document.createTextNode(msg + "\n"));
+}
+
+testGetImageData = function(context, description)
+{
+ description = "Calling getImageData() from a canvas tainted by a " + description;
+ try {
+ var imageData = context.getImageData(0,0,100,100);
+ log("PASS: " + description + " was allowed.");
+ } catch (e) {
+ log("FAIL: " + description + " was not allowed - Threw error: " + e + ".");
+ }
+}
+
+testToDataURL = function(canvas, description)
+{
+ description = "Calling toDataURL() on a canvas CORS-untainted by a " + description;
+ try {
+ var dataURL = canvas.toDataURL();
+ log("PASS: " + description + " was allowed.");
+ } catch (e) {
+ log("FAIL: " + description + " was not allowed - Threw error: " + e + ".");
+ }
+}
+
+test = function(canvas, description)
+{
+ testGetImageData(canvas.getContext("2d"), description);
+ testToDataURL(canvas, description);
+}
+
+var image = new Image();
+image.onload = function() {
+ var canvas = document.createElement("canvas");
+ canvas.width = 100;
+ canvas.height = 100;
+ var context = canvas.getContext("2d");
+
+ // Control tests
+ log("Untainted canvas:");
+ try {
+ var imageData = context.getImageData(0, 0, 100, 100);
+ log("PASS: Calling getImageData() from an untainted canvas was allowed.");
+ } catch (e) {
+ log("FAIL: Calling getImageData() from an untainted canvas was not allowed: Threw error: " + e + ".");
+ }
+ try {
+ var dataURL = canvas.toDataURL();
+ log("PASS: Calling toDataURL() on an untainted canvas was allowed.");
+ } catch (e) {
+ log("FAIL: Calling toDataURL() on an untainted canvas was not allowed: Threw error: " + e + ".");
+ }
+
+ log("\n");
+ log("Tainted canvas:");
+ // Test reading from a canvas after drawing a remote image onto it
+ context.drawImage(image, 0, 0, 100, 100);
+
+ test(canvas, "remote image");
+
+ var dirtyCanvas = canvas;
+
+ // Now test reading from a canvas after drawing a tainted canvas onto it
+ canvas = document.createElement("canvas");
+ canvas.width = 100;
+ canvas.height = 100;
+ var context = canvas.getContext("2d");
+ context.drawImage(dirtyCanvas, 0, 0, 100, 100);
+
+ test(canvas, "CORS-untained canvas");
+
+ // Test reading after using a tainted pattern
+ canvas = document.createElement("canvas");
+ canvas.width = 100;
+ canvas.height = 100;
+ var context = canvas.getContext("2d");
+ var remoteImagePattern = context.createPattern(image, "repeat");
+ context.fillStyle = remoteImagePattern;
+ context.fillRect(0, 0, 100, 100);
+
+ test(canvas, "remote image tainted pattern");
+
+ // Test reading after using a tainted pattern
+ canvas = document.createElement("canvas");
+ canvas.width = 100;
+ canvas.height = 100;
+ var context = canvas.getContext("2d");
+ var taintedCanvasPattern = context.createPattern(dirtyCanvas, "repeat");
+ context.fillStyle = taintedCanvasPattern;
+ context.fillRect(0, 0, 100, 100);
+
+ test(canvas, "CORS-untainted canvas pattern");
+
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+}
+image.crossOrigin = "use-credentials";
+image.src = "http://localhost:8000/security/resources/abe-allow-credentials.php";
+</script>
View
108 LayoutTests/http/tests/security/canvas-remote-read-remote-image-allowed.html
@@ -0,0 +1,108 @@
+<pre id="console"></pre>
+<script>
+if (window.layoutTestController) {
+ layoutTestController.dumpAsText();
+ layoutTestController.waitUntilDone();
+}
+
+log = function(msg)
+{
+ document.getElementById('console').appendChild(document.createTextNode(msg + "\n"));
+}
+
+testGetImageData = function(context, description)
+{
+ description = "Calling getImageData() from a canvas tainted by a " + description;
+ try {
+ var imageData = context.getImageData(0,0,100,100);
+ log("PASS: " + description + " was allowed.");
+ } catch (e) {
+ log("FAIL: " + description + " was not allowed - Threw error: " + e + ".");
+ }
+}
+
+testToDataURL = function(canvas, description)
+{
+ description = "Calling toDataURL() on a canvas CORS-untainted by a " + description;
+ try {
+ var dataURL = canvas.toDataURL();
+ log("PASS: " + description + " was allowed.");
+ } catch (e) {
+ log("FAIL: " + description + " was not allowed - Threw error: " + e + ".");
+ }
+}
+
+test = function(canvas, description)
+{
+ testGetImageData(canvas.getContext("2d"), description);
+ testToDataURL(canvas, description);
+}
+
+var image = new Image();
+image.onload = function() {
+ var canvas = document.createElement("canvas");
+ canvas.width = 100;
+ canvas.height = 100;
+ var context = canvas.getContext("2d");
+
+ // Control tests
+ log("Untainted canvas:");
+ try {
+ var imageData = context.getImageData(0, 0, 100, 100);
+ log("PASS: Calling getImageData() from an untainted canvas was allowed.");
+ } catch (e) {
+ log("FAIL: Calling getImageData() from an untainted canvas was not allowed: Threw error: " + e + ".");
+ }
+ try {
+ var dataURL = canvas.toDataURL();
+ log("PASS: Calling toDataURL() on an untainted canvas was allowed.");
+ } catch (e) {
+ log("FAIL: Calling toDataURL() on an untainted canvas was not allowed: Threw error: " + e + ".");
+ }
+
+ log("\n");
+ log("Tainted canvas:");
+ // Test reading from a canvas after drawing a remote image onto it
+ context.drawImage(image, 0, 0, 100, 100);
+
+ test(canvas, "remote image");
+
+ var dirtyCanvas = canvas;
+
+ // Now test reading from a canvas after drawing a tainted canvas onto it
+ canvas = document.createElement("canvas");
+ canvas.width = 100;
+ canvas.height = 100;
+ var context = canvas.getContext("2d");
+ context.drawImage(dirtyCanvas, 0, 0, 100, 100);
+
+ test(canvas, "CORS-untained canvas");
+
+ // Test reading after using a tainted pattern
+ canvas = document.createElement("canvas");
+ canvas.width = 100;
+ canvas.height = 100;
+ var context = canvas.getContext("2d");
+ var remoteImagePattern = context.createPattern(image, "repeat");
+ context.fillStyle = remoteImagePattern;
+ context.fillRect(0, 0, 100, 100);
+
+ test(canvas, "remote image tainted pattern");
+
+ // Test reading after using a tainted pattern
+ canvas = document.createElement("canvas");
+ canvas.width = 100;
+ canvas.height = 100;
+ var context = canvas.getContext("2d");
+ var taintedCanvasPattern = context.createPattern(dirtyCanvas, "repeat");
+ context.fillStyle = taintedCanvasPattern;
+ context.fillRect(0, 0, 100, 100);
+
+ test(canvas, "CORS-untainted canvas pattern");
+
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+}
+image.crossOrigin = "anonymous";
+image.src = "http://localhost:8000/security/resources/abe-allow-star.php";
+</script>
View
15 ...s/http/tests/security/canvas-remote-read-remote-image-blocked-no-crossorigin-expected.txt
@@ -0,0 +1,15 @@
+Untainted canvas:
+PASS: Calling getImageData() from an untainted canvas was allowed.
+PASS: Calling toDataURL() on an untainted canvas was allowed.
+
+
+Tainted canvas:
+PASS: Calling getImageData() from a canvas tainted by a remote image was not allowed - Threw error: Error: SECURITY_ERR: DOM Exception 18.
+PASS: Calling toDataURL() on a canvas tainted by a remote image was not allowed - Threw error: Error: SECURITY_ERR: DOM Exception 18.
+PASS: Calling getImageData() from a canvas tainted by a tained canvas was not allowed - Threw error: Error: SECURITY_ERR: DOM Exception 18.
+PASS: Calling toDataURL() on a canvas tainted by a tained canvas was not allowed - Threw error: Error: SECURITY_ERR: DOM Exception 18.
+PASS: Calling getImageData() from a canvas tainted by a remote image tainted pattern was not allowed - Threw error: Error: SECURITY_ERR: DOM Exception 18.
+PASS: Calling toDataURL() on a canvas tainted by a remote image tainted pattern was not allowed - Threw error: Error: SECURITY_ERR: DOM Exception 18.
+PASS: Calling getImageData() from a canvas tainted by a tainted canvas pattern was not allowed - Threw error: Error: SECURITY_ERR: DOM Exception 18.
+PASS: Calling toDataURL() on a canvas tainted by a tainted canvas pattern was not allowed - Threw error: Error: SECURITY_ERR: DOM Exception 18.
+
View
108 LayoutTests/http/tests/security/canvas-remote-read-remote-image-blocked-no-crossorigin.html
@@ -0,0 +1,108 @@
+<pre id="console"></pre>
+<script>
+if (window.layoutTestController) {
+ layoutTestController.dumpAsText();
+ layoutTestController.waitUntilDone();
+}
+
+log = function(msg)
+{
+ document.getElementById('console').appendChild(document.createTextNode(msg + "\n"));
+}
+
+testGetImageData = function(context, description)
+{
+ description = "Calling getImageData() from a canvas tainted by a " + description;
+ try {
+ var imageData = context.getImageData(0,0,100,100);
+ log("FAIL: " + description + " was allowed.");
+ } catch (e) {
+ log("PASS: " + description + " was not allowed - Threw error: " + e + ".");
+ }
+}
+
+testToDataURL = function(canvas, description)
+{
+ description = "Calling toDataURL() on a canvas tainted by a " + description;
+ try {
+ var dataURL = canvas.toDataURL();
+ log("FAIL: " + description + " was allowed.");
+ } catch (e) {
+ log("PASS: " + description + " was not allowed - Threw error: " + e + ".");
+ }
+}
+
+test = function(canvas, description)
+{
+ testGetImageData(canvas.getContext("2d"), description);
+ testToDataURL(canvas, description);
+}
+
+var image = new Image();
+image.onload = function() {
+ var canvas = document.createElement("canvas");
+ canvas.width = 100;
+ canvas.height = 100;
+ var context = canvas.getContext("2d");
+
+ // Control tests
+ log("Untainted canvas:");
+ try {
+ var imageData = context.getImageData(0, 0, 100, 100);
+ log("PASS: Calling getImageData() from an untainted canvas was allowed.");
+ } catch (e) {
+ log("FAIL: Calling getImageData() from an untainted canvas was not allowed: Threw error: " + e + ".");
+ }
+ try {
+ var dataURL = canvas.toDataURL();
+ log("PASS: Calling toDataURL() on an untainted canvas was allowed.");
+ } catch (e) {
+ log("FAIL: Calling toDataURL() on an untainted canvas was not allowed: Threw error: " + e + ".");
+ }
+
+ log("\n");
+ log("Tainted canvas:");
+ // Test reading from a canvas after drawing a remote image onto it
+ context.drawImage(image, 0, 0, 100, 100);
+
+ test(canvas, "remote image");
+
+ var dirtyCanvas = canvas;
+
+ // Now test reading from a canvas after drawing a tainted canvas onto it
+ canvas = document.createElement("canvas");
+ canvas.width = 100;
+ canvas.height = 100;
+ var context = canvas.getContext("2d");
+ context.drawImage(dirtyCanvas, 0, 0, 100, 100);
+
+ test(canvas, "tained canvas");
+
+ // Test reading after using a tainted pattern
+ canvas = document.createElement("canvas");
+ canvas.width = 100;
+ canvas.height = 100;
+ var context = canvas.getContext("2d");
+ var remoteImagePattern = context.createPattern(image, "repeat");
+ context.fillStyle = remoteImagePattern;
+ context.fillRect(0, 0, 100, 100);
+
+ test(canvas, "remote image tainted pattern");
+
+ // Test reading after using a tainted pattern
+ canvas = document.createElement("canvas");
+ canvas.width = 100;
+ canvas.height = 100;
+ var context = canvas.getContext("2d");
+ var taintedCanvasPattern = context.createPattern(dirtyCanvas, "repeat");
+ context.fillStyle = taintedCanvasPattern;
+ context.fillRect(0, 0, 100, 100);
+
+ test(canvas, "tainted canvas pattern");
+
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+}
+// Notice that we forget to set the image.crossOrigin property!
+image.src = "http://localhost:8000/security/resources/abe-allow-star.php";
+</script>
View
12 LayoutTests/http/tests/security/resources/abe-allow-credentials.php
@@ -0,0 +1,12 @@
+<?php
+header("Access-Control-Allow-Origin: http://127.0.0.1:8000");
+header("Access-Control-Allow-Credentials: true");
+
+$name = 'abe.png';
+$fp = fopen($name, 'rb');
+header("Content-Type: image/png");
+header("Content-Length: " . filesize($name));
+
+fpassthru($fp);
+exit;
+?>
View
11 LayoutTests/http/tests/security/resources/abe-allow-star.php
@@ -0,0 +1,11 @@
+<?php
+header("Access-Control-Allow-Origin: *");
+
+$name = 'abe.png';
+$fp = fopen($name, 'rb');
+header("Content-Type: image/png");
+header("Content-Length: " . filesize($name));
+
+fpassthru($fp);
+exit;
+?>
View
13 LayoutTests/http/tests/security/webgl-remote-read-remote-image-allowed-expected.txt
@@ -0,0 +1,13 @@
+Untainted canvas:
+PASS: Calling readPixels() from an untainted canvas was allowed.
+PASS: Calling toDataURL() on an untainted canvas was allowed.
+
+
+Tainted canvas:
+PASS: Calling texImage2D() with an untainted image was allowed
+PASS: Calling readPixels() from a canvas tainted by a remote image was allowed.
+PASS: Calling toDataURL() on a canvas CORS-untainted by a remote image was allowed.
+PASS: Calling texImage2D() with an untainted canvas was allowed
+PASS: Calling readPixels() from a canvas tainted by a CORS-untained canvas was allowed.
+PASS: Calling toDataURL() on a canvas CORS-untainted by a CORS-untained canvas was allowed.
+
View
13 .../http/tests/security/webgl-remote-read-remote-image-allowed-with-credentials-expected.txt
@@ -0,0 +1,13 @@
+Untainted canvas:
+PASS: Calling readPixels() from an untainted canvas was allowed.
+PASS: Calling toDataURL() on an untainted canvas was allowed.
+
+
+Tainted canvas:
+PASS: Calling texImage2D() with an untainted image was allowed
+PASS: Calling readPixels() from a canvas tainted by a remote image was allowed.
+PASS: Calling toDataURL() on a canvas CORS-untainted by a remote image was allowed.
+PASS: Calling texImage2D() with an untainted canvas was allowed
+PASS: Calling readPixels() from a canvas tainted by a CORS-untained canvas was allowed.
+PASS: Calling toDataURL() on a canvas CORS-untainted by a CORS-untained canvas was allowed.
+
View
101 LayoutTests/http/tests/security/webgl-remote-read-remote-image-allowed-with-credentials.html
@@ -0,0 +1,101 @@
+<pre id="console"></pre>
+<script>
+if (window.layoutTestController) {
+ layoutTestController.overridePreference("WebKitWebGLEnabled", "1");
+ layoutTestController.dumpAsText();
+ layoutTestController.waitUntilDone();
+}
+
+log = function(msg)
+{
+ document.getElementById('console').appendChild(document.createTextNode(msg + "\n"));
+}
+
+testTexImage2D = function(gl, source, description)
+{
+ description = "Calling texImage2D() with an untainted " + description;
+ try {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
+ log("PASS: " + description + " was allowed");
+ } catch (e) {
+ log("FAIL: " + description + " was not allowed: Threw error: " + e + ".");
+ }
+}
+
+testReadPixels = function(gl, description)
+{
+ description = "Calling readPixels() from a canvas tainted by a " + description;
+ try {
+ var pixels = new Uint8Array(4);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
+ log("PASS: " + description + " was allowed.");
+ } catch (e) {
+ log("FAIL: " + description + " was not allowed - Threw error: " + e + ".");
+ }
+}
+
+testToDataURL = function(canvas, description)
+{
+ description = "Calling toDataURL() on a canvas CORS-untainted by a " + description;
+ try {
+ var dataURL = canvas.toDataURL();
+ log("PASS: " + description + " was allowed.");
+ } catch (e) {
+ log("FAIL: " + description + " was not allowed - Threw error: " + e + ".");
+ }
+}
+
+test = function(canvas, description)
+{
+ testReadPixels(canvas.getContext("experimental-webgl"), description);
+ testToDataURL(canvas, description);
+}
+
+var image = new Image();
+image.onload = function() {
+ var canvas = document.createElement("canvas");
+ canvas.width = 100;
+ canvas.height = 100;
+ var gl = canvas.getContext("experimental-webgl");
+
+ // Control tests
+ log("Untainted canvas:");
+ try {
+ var pixels = new Uint8Array(4);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
+ log("PASS: Calling readPixels() from an untainted canvas was allowed.");
+ } catch (e) {
+ log("FAIL: Calling readPixels() from an untainted canvas was not allowed: Threw error: " + e + ".");
+ }
+ try {
+ var dataURL = canvas.toDataURL();
+ log("PASS: Calling toDataURL() on an untainted canvas was allowed.");
+ } catch (e) {
+ log("FAIL: Calling toDataURL() on an untainted canvas was not allowed: Threw error: " + e + ".");
+ }
+
+ log("\n");
+ log("Tainted canvas:");
+ // Test reading from a canvas after uploading a remote image as a texture
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ testTexImage2D(gl, image, "image");
+
+ test(canvas, "remote image");
+
+ // Now test reading from a canvas after uploading a tainted canvas onto it
+ var dirtyCanvas = document.createElement("canvas");
+ dirtyCanvas.width = 100;
+ dirtyCanvas.height = 100;
+ var dirtyContext = dirtyCanvas.getContext("2d");
+ dirtyContext.drawImage(image, 0, 0, 100, 100);
+ testTexImage2D(gl, dirtyCanvas, "canvas");
+
+ test(canvas, "CORS-untained canvas");
+
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+}
+image.crossOrigin = "use-credentials";
+image.src = "http://localhost:8000/security/resources/abe-allow-credentials.php";
+</script>
View
101 LayoutTests/http/tests/security/webgl-remote-read-remote-image-allowed.html
@@ -0,0 +1,101 @@
+<pre id="console"></pre>
+<script>
+if (window.layoutTestController) {
+ layoutTestController.overridePreference("WebKitWebGLEnabled", "1");
+ layoutTestController.dumpAsText();
+ layoutTestController.waitUntilDone();
+}
+
+log = function(msg)
+{
+ document.getElementById('console').appendChild(document.createTextNode(msg + "\n"));
+}
+
+testTexImage2D = function(gl, source, description)
+{
+ description = "Calling texImage2D() with an untainted " + description;
+ try {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
+ log("PASS: " + description + " was allowed");
+ } catch (e) {
+ log("FAIL: " + description + " was not allowed: Threw error: " + e + ".");
+ }
+}
+
+testReadPixels = function(gl, description)
+{
+ description = "Calling readPixels() from a canvas tainted by a " + description;
+ try {
+ var pixels = new Uint8Array(4);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
+ log("PASS: " + description + " was allowed.");
+ } catch (e) {
+ log("FAIL: " + description + " was not allowed - Threw error: " + e + ".");
+ }
+}
+
+testToDataURL = function(canvas, description)
+{
+ description = "Calling toDataURL() on a canvas CORS-untainted by a " + description;
+ try {
+ var dataURL = canvas.toDataURL();
+ log("PASS: " + description + " was allowed.");
+ } catch (e) {
+ log("FAIL: " + description + " was not allowed - Threw error: " + e + ".");
+ }
+}
+
+test = function(canvas, description)
+{
+ testReadPixels(canvas.getContext("experimental-webgl"), description);
+ testToDataURL(canvas, description);
+}
+
+var image = new Image();
+image.onload = function() {
+ var canvas = document.createElement("canvas");
+ canvas.width = 100;
+ canvas.height = 100;
+ var gl = canvas.getContext("experimental-webgl");
+
+ // Control tests
+ log("Untainted canvas:");
+ try {
+ var pixels = new Uint8Array(4);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
+ log("PASS: Calling readPixels() from an untainted canvas was allowed.");
+ } catch (e) {
+ log("FAIL: Calling readPixels() from an untainted canvas was not allowed: Threw error: " + e + ".");
+ }
+ try {
+ var dataURL = canvas.toDataURL();
+ log("PASS: Calling toDataURL() on an untainted canvas was allowed.");
+ } catch (e) {
+ log("FAIL: Calling toDataURL() on an untainted canvas was not allowed: Threw error: " + e + ".");
+ }
+
+ log("\n");
+ log("Tainted canvas:");
+ // Test reading from a canvas after uploading a remote image as a texture
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ testTexImage2D(gl, image, "image");
+
+ test(canvas, "remote image");
+
+ // Now test reading from a canvas after uploading a tainted canvas onto it
+ var dirtyCanvas = document.createElement("canvas");
+ dirtyCanvas.width = 100;
+ dirtyCanvas.height = 100;
+ var dirtyContext = dirtyCanvas.getContext("2d");
+ dirtyContext.drawImage(image, 0, 0, 100, 100);
+ testTexImage2D(gl, dirtyCanvas, "canvas");
+
+ test(canvas, "CORS-untained canvas");
+
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+}
+image.crossOrigin = "anonymous";
+image.src = "http://localhost:8000/security/resources/abe-allow-star.php";
+</script>
View
13 ...ts/http/tests/security/webgl-remote-read-remote-image-blocked-no-crossorigin-expected.txt
@@ -0,0 +1,13 @@
+Untainted canvas:
+PASS: Calling readPixels() from an untainted canvas was allowed.
+PASS: Calling toDataURL() on an untainted canvas was allowed.
+
+
+Tainted canvas:
+PASS: Calling texImage2D() with a tainted image was not allowed: Threw error: Error: SECURITY_ERR: DOM Exception 18.
+PASS: Calling readPixels() on a canvas where tainting was attempted by a remote image was allowed.
+PASS: Calling toDataURL() on a canvas where tainting was attempted by a remote image was allowed.
+PASS: Calling texImage2D() with a tainted canvas was not allowed: Threw error: Error: SECURITY_ERR: DOM Exception 18.
+PASS: Calling readPixels() on a canvas where tainting was attempted by a tainted canvas was allowed.
+PASS: Calling toDataURL() on a canvas where tainting was attempted by a tainted canvas was allowed.
+
View
103 LayoutTests/http/tests/security/webgl-remote-read-remote-image-blocked-no-crossorigin.html
@@ -0,0 +1,103 @@
+<pre id="console"></pre>
+<script>
+if (window.layoutTestController) {
+ layoutTestController.overridePreference("WebKitWebGLEnabled", "1");
+ layoutTestController.dumpAsText();
+ layoutTestController.waitUntilDone();
+}
+
+log = function(msg)
+{
+ document.getElementById('console').appendChild(document.createTextNode(msg + "\n"));
+}
+
+testTexImage2D = function(gl, source, description)
+{
+ description = "Calling texImage2D() with a tainted " + description;
+ try {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
+ log("FAIL: " + description + " was allowed");
+ } catch (e) {
+ log("PASS: " + description + " was not allowed: Threw error: " + e + ".");
+ }
+}
+
+testReadPixels = function(gl, description)
+{
+ description = "Calling readPixels() on a canvas where tainting was attempted by a " + description;
+ try {
+ var pixels = new Uint8Array(4);
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
+ log("PASS: " + description + " was allowed.");
+ } catch (e) {
+ log("FAIL: " + description + " was not allowed - Threw error: " + e + ".");
+ }
+}
+
+testToDataURL = function(canvas, description)
+{
+ description = "Calling toDataURL() on a canvas where tainting was attempted by a " + description;
+ try {
+ var dataURL = canvas.toDataURL();
+ log("PASS: " + description + " was allowed.");
+ } catch (e) {
+ log("FAIL: " + description + " was not allowed - Threw error: " + e + ".");
+ }
+}
+
+test = function(canvas, description)
+{
+ testReadPixels(canvas.getContext("experimental-webgl"), description);
+ testToDataURL(canvas, description);
+}
+
+var image = new Image();
+image.onload = function() {
+ var canvas = document.createElement("canvas");
+ canvas.width = 100;
+ canvas.height = 100;
+ var gl = canvas.getContext("experimental-webgl");
+
+ // Control tests