Home | History | Annotate | Download | only in page
      1 /*
      2  * Copyright (c) 2013, Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 #include "core/page/ImageBitmapFactories.h"
     33 
     34 #include "RuntimeEnabledFeatures.h"
     35 #include "V8ImageBitmap.h"
     36 #include "bindings/v8/ExceptionState.h"
     37 #include "core/dom/ExceptionCode.h"
     38 #include "core/html/HTMLCanvasElement.h"
     39 #include "core/html/HTMLImageElement.h"
     40 #include "core/html/HTMLVideoElement.h"
     41 #include "core/html/ImageData.h"
     42 #include "core/html/canvas/CanvasRenderingContext2D.h"
     43 #include "core/page/DOMWindow.h"
     44 #include "core/page/ImageBitmap.h"
     45 
     46 namespace WebCore {
     47 
     48 namespace ImageBitmapFactories {
     49 
     50 static LayoutSize sizeFor(HTMLImageElement* image)
     51 {
     52     if (ImageResource* cachedImage = image->cachedImage())
     53         return cachedImage->imageSizeForRenderer(image->renderer(), 1.0f); // FIXME: Not sure about this.
     54     return IntSize();
     55 }
     56 
     57 static IntSize sizeFor(HTMLVideoElement* video)
     58 {
     59     if (MediaPlayer* player = video->player())
     60         return player->naturalSize();
     61     return IntSize();
     62 }
     63 
     64 static ScriptObject resolveImageBitmap(PassRefPtr<ImageBitmap> imageBitmap)
     65 {
     66     // Promises must be enabled.
     67     ASSERT(RuntimeEnabledFeatures::promiseEnabled());
     68 
     69     RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create();
     70     resolver->fulfill(imageBitmap);
     71     return resolver->promise();
     72 }
     73 
     74 ScriptObject createImageBitmap(EventTarget* eventTarget, HTMLImageElement* image, ExceptionState& es)
     75 {
     76     LayoutSize s = sizeFor(image);
     77     return createImageBitmap(eventTarget, image, 0, 0, s.width(), s.height(), es);
     78 }
     79 
     80 ScriptObject createImageBitmap(EventTarget* eventTarget, HTMLImageElement* image, int sx, int sy, int sw, int sh, ExceptionState& es)
     81 {
     82     if (!image) {
     83         es.throwTypeError();
     84         return ScriptObject();
     85     }
     86     if (!image->cachedImage()) {
     87         es.throwDOMException(InvalidStateError);
     88         return ScriptObject();
     89     }
     90     if (image->cachedImage()->image()->isSVGImage()) {
     91         es.throwDOMException(InvalidStateError);
     92         return ScriptObject();
     93     }
     94     if (!sw || !sh) {
     95         es.throwDOMException(IndexSizeError);
     96         return ScriptObject();
     97     }
     98     if (!image->cachedImage()->image()->hasSingleSecurityOrigin()) {
     99         es.throwDOMException(SecurityError);
    100         return ScriptObject();
    101     }
    102     if (!image->cachedImage()->passesAccessControlCheck(eventTarget->toDOMWindow()->document()->securityOrigin())
    103     && eventTarget->toDOMWindow()->document()->securityOrigin()->taintsCanvas(image->src())) {
    104         es.throwDOMException(SecurityError);
    105         return ScriptObject();
    106     }
    107     // FIXME: make ImageBitmap creation asynchronous crbug.com/258082
    108     return resolveImageBitmap(ImageBitmap::create(image, IntRect(sx, sy, sw, sh)));
    109 }
    110 
    111 ScriptObject createImageBitmap(EventTarget* eventTarget, HTMLVideoElement* video, ExceptionState& es)
    112 {
    113     IntSize s = sizeFor(video);
    114     return createImageBitmap(eventTarget, video, 0, 0, s.width(), s.height(), es);
    115 }
    116 
    117 ScriptObject createImageBitmap(EventTarget* eventTarget, HTMLVideoElement* video, int sx, int sy, int sw, int sh, ExceptionState& es)
    118 {
    119     if (!video) {
    120         es.throwTypeError();
    121         return ScriptObject();
    122     }
    123     if (!video->player()) {
    124         es.throwDOMException(InvalidStateError);
    125         return ScriptObject();
    126     }
    127     if (video->networkState() == HTMLMediaElement::NETWORK_EMPTY) {
    128         es.throwDOMException(InvalidStateError);
    129         return ScriptObject();
    130     }
    131     if (video->player()->readyState() <= MediaPlayer::HaveMetadata) {
    132         es.throwDOMException(InvalidStateError);
    133         return ScriptObject();
    134     }
    135     if (!sw || !sh) {
    136         es.throwDOMException(IndexSizeError);
    137         return ScriptObject();
    138     }
    139     if (!video->hasSingleSecurityOrigin()) {
    140         es.throwDOMException(SecurityError);
    141         return ScriptObject();
    142     }
    143     if (!video->player()->didPassCORSAccessCheck() && eventTarget->toDOMWindow()->document()->securityOrigin()->taintsCanvas(video->currentSrc())) {
    144         es.throwDOMException(SecurityError);
    145         return ScriptObject();
    146     }
    147     // FIXME: make ImageBitmap creation asynchronous crbug.com/258082
    148     return resolveImageBitmap(ImageBitmap::create(video, IntRect(sx, sy, sw, sh)));
    149 }
    150 
    151 ScriptObject createImageBitmap(EventTarget* eventTarget, CanvasRenderingContext2D* context, ExceptionState& es)
    152 {
    153     return createImageBitmap(eventTarget, context->canvas(), es);
    154 }
    155 
    156 ScriptObject createImageBitmap(EventTarget* eventTarget, CanvasRenderingContext2D* context, int sx, int sy, int sw, int sh, ExceptionState& es)
    157 {
    158     return createImageBitmap(eventTarget, context->canvas(), sx, sy, sw, sh, es);
    159 }
    160 
    161 ScriptObject createImageBitmap(EventTarget* eventTarget, HTMLCanvasElement* canvas, ExceptionState& es)
    162 {
    163     return createImageBitmap(eventTarget, canvas, 0, 0, canvas->width(), canvas->height(), es);
    164 }
    165 
    166 ScriptObject createImageBitmap(EventTarget* eventTarget, HTMLCanvasElement* canvas, int sx, int sy, int sw, int sh, ExceptionState& es)
    167 {
    168     if (!canvas) {
    169         es.throwTypeError();
    170         return ScriptObject();
    171     }
    172     if (!canvas->originClean()) {
    173         es.throwDOMException(InvalidStateError);
    174         return ScriptObject();
    175     }
    176     if (!sw || !sh) {
    177         es.throwDOMException(IndexSizeError);
    178         return ScriptObject();
    179     }
    180     // FIXME: make ImageBitmap creation asynchronous crbug.com/258082
    181     return resolveImageBitmap(ImageBitmap::create(canvas, IntRect(sx, sy, sw, sh)));
    182 }
    183 
    184 ScriptObject createImageBitmap(EventTarget* eventTarget, ImageData* data, ExceptionState& es)
    185 {
    186     return createImageBitmap(eventTarget, data, 0, 0, data->width(), data->height(), es);
    187 }
    188 
    189 ScriptObject createImageBitmap(EventTarget* eventTarget, ImageData* data, int sx, int sy, int sw, int sh, ExceptionState& es)
    190 {
    191     if (!data) {
    192         es.throwTypeError();
    193         return ScriptObject();
    194     }
    195     if (!sw || !sh) {
    196         es.throwDOMException(IndexSizeError);
    197         return ScriptObject();
    198     }
    199     // FIXME: make ImageBitmap creation asynchronous crbug.com/258082
    200     return resolveImageBitmap(ImageBitmap::create(data, IntRect(sx, sy, sw, sh)));
    201 }
    202 
    203 ScriptObject createImageBitmap(EventTarget* eventTarget, ImageBitmap* bitmap, ExceptionState& es)
    204 {
    205     return createImageBitmap(eventTarget, bitmap, 0, 0, bitmap->width(), bitmap->height(), es);
    206 }
    207 
    208 ScriptObject createImageBitmap(EventTarget* eventTarget, ImageBitmap* bitmap, int sx, int sy, int sw, int sh, ExceptionState& es)
    209 {
    210     if (!bitmap) {
    211         es.throwTypeError();
    212         return ScriptObject();
    213     }
    214     if (!sw || !sh) {
    215         es.throwDOMException(IndexSizeError);
    216         return ScriptObject();
    217     }
    218     // FIXME: make ImageBitmap creation asynchronous crbug.com/258082
    219     return resolveImageBitmap(ImageBitmap::create(bitmap, IntRect(sx, sy, sw, sh)));
    220 }
    221 
    222 } // namespace ImageBitmapFactories
    223 } // namespace WebCore
    224