Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 // vim:set ts=2 sts=2 sw=2 et cin:
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifdef MOZ_WIDGET_ANDROID
9 #include <set>
10 #include <map>
11 #include <android/log.h>
12 #include "nsSurfaceTexture.h"
13 #include "AndroidBridge.h"
14 #include "nsThreadUtils.h"
15 #include "mozilla/gfx/Matrix.h"
17 using namespace mozilla;
19 // UGH
20 static std::map<int, nsSurfaceTexture*> sInstances;
21 static int sNextID = 0;
23 static class JNIFunctions {
24 public:
26 JNIFunctions() : mInitialized(false)
27 {
28 }
30 bool EnsureInitialized()
31 {
32 if (mInitialized)
33 return true;
35 JNIEnv* env = GetJNIForThread();
37 AutoLocalJNIFrame jniFrame(env);
39 jSurfaceTextureClass = (jclass)env->NewGlobalRef(env->FindClass("android/graphics/SurfaceTexture"));
40 jSurfaceTexture_Ctor = env->GetMethodID(jSurfaceTextureClass, "<init>", "(I)V");
41 jSurfaceTexture_updateTexImage = env->GetMethodID(jSurfaceTextureClass, "updateTexImage", "()V");
42 jSurfaceTexture_getTransformMatrix = env->GetMethodID(jSurfaceTextureClass, "getTransformMatrix", "([F)V");
44 mInitialized = true;
45 return true;
46 }
48 jobject CreateSurfaceTexture(GLuint aTexture)
49 {
50 if (!EnsureInitialized())
51 return nullptr;
53 JNIEnv* env = GetJNIForThread();
55 AutoLocalJNIFrame jniFrame(env);
57 return env->NewGlobalRef(env->NewObject(jSurfaceTextureClass, jSurfaceTexture_Ctor, (int) aTexture));
58 }
60 void ReleaseSurfaceTexture(jobject aSurfaceTexture)
61 {
62 JNIEnv* env = GetJNIForThread();
64 env->DeleteGlobalRef(aSurfaceTexture);
65 }
67 void UpdateTexImage(jobject aSurfaceTexture)
68 {
69 JNIEnv* env = GetJNIForThread();
71 AutoLocalJNIFrame jniFrame(env);
72 env->CallVoidMethod(aSurfaceTexture, jSurfaceTexture_updateTexImage);
73 }
75 bool GetTransformMatrix(jobject aSurfaceTexture, gfx::Matrix4x4& aMatrix)
76 {
77 JNIEnv* env = GetJNIForThread();
79 AutoLocalJNIFrame jniFrame(env);
81 jfloatArray jarray = env->NewFloatArray(16);
82 env->CallVoidMethod(aSurfaceTexture, jSurfaceTexture_getTransformMatrix, jarray);
84 jfloat* array = env->GetFloatArrayElements(jarray, nullptr);
86 aMatrix._11 = array[0];
87 aMatrix._12 = array[1];
88 aMatrix._13 = array[2];
89 aMatrix._14 = array[3];
91 aMatrix._21 = array[4];
92 aMatrix._22 = array[5];
93 aMatrix._23 = array[6];
94 aMatrix._24 = array[7];
96 aMatrix._31 = array[8];
97 aMatrix._32 = array[9];
98 aMatrix._33 = array[10];
99 aMatrix._34 = array[11];
101 aMatrix._41 = array[12];
102 aMatrix._42 = array[13];
103 aMatrix._43 = array[14];
104 aMatrix._44 = array[15];
106 env->ReleaseFloatArrayElements(jarray, array, 0);
108 return false;
109 }
111 private:
112 bool mInitialized;
114 jclass jSurfaceTextureClass;
115 jmethodID jSurfaceTexture_Ctor;
116 jmethodID jSurfaceTexture_updateTexImage;
117 jmethodID jSurfaceTexture_getTransformMatrix;
119 } sJNIFunctions;
121 nsSurfaceTexture*
122 nsSurfaceTexture::Create(GLuint aTexture)
123 {
124 // Right now we only support creating this on the main thread because
125 // of the JNIEnv assumptions in JNIHelper and elsewhere
126 if (!NS_IsMainThread())
127 return nullptr;
129 nsSurfaceTexture* st = new nsSurfaceTexture();
130 if (!st->Init(aTexture)) {
131 printf_stderr("Failed to initialize nsSurfaceTexture");
132 delete st;
133 st = nullptr;
134 }
136 return st;
137 }
139 nsSurfaceTexture*
140 nsSurfaceTexture::Find(int id)
141 {
142 std::map<int, nsSurfaceTexture*>::iterator it;
144 it = sInstances.find(id);
145 if (it == sInstances.end())
146 return nullptr;
148 return it->second;
149 }
151 bool
152 nsSurfaceTexture::Check()
153 {
154 return sJNIFunctions.EnsureInitialized();
155 }
157 bool
158 nsSurfaceTexture::Init(GLuint aTexture)
159 {
160 if (!sJNIFunctions.EnsureInitialized())
161 return false;
163 JNIEnv* env = GetJNIForThread();
165 mSurfaceTexture = sJNIFunctions.CreateSurfaceTexture(aTexture);
166 if (!mSurfaceTexture)
167 return false;
169 mNativeWindow = AndroidBridge::Bridge()->AcquireNativeWindowFromSurfaceTexture(env, mSurfaceTexture);
171 mID = ++sNextID;
172 sInstances.insert(std::pair<int, nsSurfaceTexture*>(mID, this));
174 return true;
175 }
177 nsSurfaceTexture::nsSurfaceTexture()
178 : mSurfaceTexture(nullptr), mNativeWindow(nullptr)
179 {
180 }
182 nsSurfaceTexture::~nsSurfaceTexture()
183 {
184 sInstances.erase(mID);
186 mFrameAvailableCallback = nullptr;
188 if (mNativeWindow) {
189 AndroidBridge::Bridge()->ReleaseNativeWindowForSurfaceTexture(mSurfaceTexture);
190 mNativeWindow = nullptr;
191 }
193 JNIEnv* env = GetJNIForThread();
195 if (mSurfaceTexture) {
196 mozilla::widget::android::GeckoAppShell::UnregisterSurfaceTextureFrameListener(mSurfaceTexture);
198 env->DeleteGlobalRef(mSurfaceTexture);
199 mSurfaceTexture = nullptr;
200 }
201 }
203 void*
204 nsSurfaceTexture::GetNativeWindow()
205 {
206 return mNativeWindow;
207 }
209 void
210 nsSurfaceTexture::UpdateTexImage()
211 {
212 sJNIFunctions.UpdateTexImage(mSurfaceTexture);
213 }
215 bool
216 nsSurfaceTexture::GetTransformMatrix(gfx::Matrix4x4& aMatrix)
217 {
218 return sJNIFunctions.GetTransformMatrix(mSurfaceTexture, aMatrix);
219 }
221 void
222 nsSurfaceTexture::SetFrameAvailableCallback(nsIRunnable* aRunnable)
223 {
224 if (aRunnable)
225 mozilla::widget::android::GeckoAppShell::RegisterSurfaceTextureFrameListener(mSurfaceTexture, mID);
226 else
227 mozilla::widget::android::GeckoAppShell::UnregisterSurfaceTextureFrameListener(mSurfaceTexture);
229 mFrameAvailableCallback = aRunnable;
230 }
232 void
233 nsSurfaceTexture::NotifyFrameAvailable()
234 {
235 if (mFrameAvailableCallback) {
236 // Proxy to main thread if we aren't on it
237 if (!NS_IsMainThread()) {
238 // Proxy to main thread
239 nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &nsSurfaceTexture::NotifyFrameAvailable);
240 NS_DispatchToCurrentThread(event);
241 } else {
242 mFrameAvailableCallback->Run();
243 }
244 }
245 }
247 #endif // MOZ_WIDGET_ANDROID