1 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Vladimir Vukicevic <vladimir@pobox.com>
19 : * Portions created by the Initial Developer are Copyright (C) 2009
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either the GNU General Public License Version 2 or later (the "GPL"), or
26 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : #include <stdlib.h>
39 : #include <stdarg.h>
40 :
41 : #include "prmem.h"
42 : #include "prprf.h"
43 :
44 : #include "nsIServiceManager.h"
45 :
46 : #include "nsIConsoleService.h"
47 : #include "nsIDOMDocument.h"
48 : #include "nsIDocument.h"
49 : #include "nsIDOMCanvasRenderingContext2D.h"
50 : #include "nsICanvasRenderingContextInternal.h"
51 : #include "nsHTMLCanvasElement.h"
52 : #include "nsIPrincipal.h"
53 : #include "nsINode.h"
54 :
55 : #include "nsGfxCIID.h"
56 :
57 : #include "nsTArray.h"
58 :
59 : #include "CanvasUtils.h"
60 : #include "mozilla/gfx/Matrix.h"
61 :
62 : namespace mozilla {
63 : namespace CanvasUtils {
64 :
65 : void
66 0 : DoDrawImageSecurityCheck(nsHTMLCanvasElement *aCanvasElement,
67 : nsIPrincipal *aPrincipal,
68 : bool forceWriteOnly,
69 : bool CORSUsed)
70 : {
71 0 : NS_PRECONDITION(aPrincipal, "Must have a principal here");
72 :
73 : // Callers should ensure that mCanvasElement is non-null before calling this
74 0 : if (!aCanvasElement) {
75 0 : NS_WARNING("DoDrawImageSecurityCheck called without canvas element!");
76 0 : return;
77 : }
78 :
79 0 : if (aCanvasElement->IsWriteOnly())
80 0 : return;
81 :
82 : // If we explicitly set WriteOnly just do it and get out
83 0 : if (forceWriteOnly) {
84 0 : aCanvasElement->SetWriteOnly();
85 0 : return;
86 : }
87 :
88 : // No need to do a security check if the image used CORS for the load
89 0 : if (CORSUsed)
90 0 : return;
91 :
92 : bool subsumes;
93 : nsresult rv =
94 0 : aCanvasElement->NodePrincipal()->Subsumes(aPrincipal, &subsumes);
95 :
96 0 : if (NS_SUCCEEDED(rv) && subsumes) {
97 : // This canvas has access to that image anyway
98 0 : return;
99 : }
100 :
101 0 : aCanvasElement->SetWriteOnly();
102 : }
103 :
104 : bool
105 0 : CoerceDouble(jsval v, double* d)
106 : {
107 0 : if (JSVAL_IS_DOUBLE(v)) {
108 0 : *d = JSVAL_TO_DOUBLE(v);
109 0 : } else if (JSVAL_IS_INT(v)) {
110 0 : *d = double(JSVAL_TO_INT(v));
111 0 : } else if (JSVAL_IS_VOID(v)) {
112 0 : *d = 0.0;
113 : } else {
114 0 : return false;
115 : }
116 0 : return true;
117 : }
118 :
119 : template<size_t N>
120 : static bool
121 0 : JSValToMatrixElts(JSContext* cx, const jsval& val,
122 : double* (&elts)[N], nsresult* rv)
123 : {
124 : JSObject* obj;
125 : uint32_t length;
126 :
127 0 : if (JSVAL_IS_PRIMITIVE(val) ||
128 : !(obj = JSVAL_TO_OBJECT(val)) ||
129 : !JS_GetArrayLength(cx, obj, &length) ||
130 : N != length) {
131 : // Not an array-like thing or wrong size
132 0 : *rv = NS_ERROR_INVALID_ARG;
133 0 : return false;
134 : }
135 :
136 0 : for (PRUint32 i = 0; i < N; ++i) {
137 : jsval elt;
138 : double d;
139 0 : if (!JS_GetElement(cx, obj, i, &elt)) {
140 0 : *rv = NS_ERROR_FAILURE;
141 0 : return false;
142 : }
143 0 : if (!CoerceDouble(elt, &d)) {
144 0 : *rv = NS_ERROR_INVALID_ARG;
145 0 : return false;
146 : }
147 0 : if (!FloatValidate(d)) {
148 : // This is weird, but it's the behavior of SetTransform()
149 0 : *rv = NS_OK;
150 0 : return false;
151 : }
152 0 : *elts[i] = d;
153 : }
154 :
155 0 : *rv = NS_OK;
156 0 : return true;
157 : }
158 :
159 : bool
160 0 : JSValToMatrix(JSContext* cx, const jsval& val, gfxMatrix* matrix, nsresult* rv)
161 : {
162 : double* elts[] = { &matrix->xx, &matrix->yx, &matrix->xy, &matrix->yy,
163 0 : &matrix->x0, &matrix->y0 };
164 0 : return JSValToMatrixElts(cx, val, elts, rv);
165 : }
166 :
167 : bool
168 0 : JSValToMatrix(JSContext* cx, const jsval& val, Matrix* matrix, nsresult* rv)
169 : {
170 0 : gfxMatrix m;
171 0 : if (!JSValToMatrix(cx, val, &m, rv))
172 0 : return false;
173 : *matrix = Matrix(Float(m.xx), Float(m.yx), Float(m.xy), Float(m.yy),
174 0 : Float(m.x0), Float(m.y0));
175 0 : return true;
176 : }
177 :
178 : template<size_t N>
179 : static nsresult
180 0 : MatrixEltsToJSVal(/*const*/ jsval (&elts)[N], JSContext* cx, jsval* val)
181 : {
182 0 : JSObject* obj = JS_NewArrayObject(cx, N, elts);
183 0 : if (!obj) {
184 0 : return NS_ERROR_OUT_OF_MEMORY;
185 : }
186 :
187 0 : *val = OBJECT_TO_JSVAL(obj);
188 :
189 0 : return NS_OK;
190 : }
191 :
192 : nsresult
193 0 : MatrixToJSVal(const gfxMatrix& matrix, JSContext* cx, jsval* val)
194 : {
195 : jsval elts[] = {
196 0 : DOUBLE_TO_JSVAL(matrix.xx), DOUBLE_TO_JSVAL(matrix.yx),
197 0 : DOUBLE_TO_JSVAL(matrix.xy), DOUBLE_TO_JSVAL(matrix.yy),
198 0 : DOUBLE_TO_JSVAL(matrix.x0), DOUBLE_TO_JSVAL(matrix.y0)
199 0 : };
200 0 : return MatrixEltsToJSVal(elts, cx, val);
201 : }
202 :
203 : nsresult
204 0 : MatrixToJSVal(const Matrix& matrix, JSContext* cx, jsval* val)
205 : {
206 : jsval elts[] = {
207 0 : DOUBLE_TO_JSVAL(matrix._11), DOUBLE_TO_JSVAL(matrix._12),
208 0 : DOUBLE_TO_JSVAL(matrix._21), DOUBLE_TO_JSVAL(matrix._22),
209 0 : DOUBLE_TO_JSVAL(matrix._31), DOUBLE_TO_JSVAL(matrix._32)
210 0 : };
211 0 : return MatrixEltsToJSVal(elts, cx, val);
212 : }
213 :
214 : } // namespace CanvasUtils
215 : } // namespace mozilla
|