Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "ReadbackManagerD3D10.h"
7 #include "ReadbackProcessor.h"
8 #include "ReadbackLayer.h"
10 #include "nsIThread.h"
11 #include "nsThreadUtils.h"
12 #include "gfxImageSurface.h"
13 #include "gfxContext.h"
15 namespace mozilla {
16 namespace layers {
18 // Structure that contains the information required to execute a readback task,
19 // the only member accessed off the main thread here is mReadbackTexture. Since
20 // mLayer may be released only on the main thread this object should always be
21 // destroyed on the main thread!
22 struct ReadbackTask {
23 // The texture that we copied the contents of the thebeslayer to.
24 nsRefPtr<ID3D10Texture2D> mReadbackTexture;
25 // This exists purely to keep the ReadbackLayer alive for the lifetime of
26 // mUpdate. Note that this addref and release should occur -solely- on the
27 // main thread.
28 nsRefPtr<ReadbackLayer> mLayer;
29 ReadbackProcessor::Update mUpdate;
30 // The origin in ThebesLayer coordinates of mReadbackTexture.
31 gfxPoint mOrigin;
32 // mLayer->GetBackgroundOffset() when the task is created. We have
33 // to save this in the ReadbackTask because it might change before
34 // the update is delivered to the readback sink.
35 nsIntPoint mBackgroundOffset;
36 };
38 // This class is created and dispatched from the Readback thread but it must be
39 // destroyed by the main thread.
40 class ReadbackResultWriter MOZ_FINAL : public nsIRunnable
41 {
42 NS_DECL_THREADSAFE_ISUPPORTS
43 public:
44 ReadbackResultWriter(ReadbackTask *aTask) : mTask(aTask) {}
46 NS_IMETHODIMP Run()
47 {
48 ReadbackProcessor::Update *update = &mTask->mUpdate;
50 if (!update->mLayer->GetSink()) {
51 // This can happen when a plugin is destroyed.
52 return NS_OK;
53 }
55 nsIntPoint offset = mTask->mBackgroundOffset;
57 D3D10_TEXTURE2D_DESC desc;
58 mTask->mReadbackTexture->GetDesc(&desc);
60 D3D10_MAPPED_TEXTURE2D mappedTex;
61 // We know this map will immediately succeed, as we've already mapped this
62 // copied data on our task thread.
63 HRESULT hr = mTask->mReadbackTexture->Map(0, D3D10_MAP_READ, 0, &mappedTex);
65 if (FAILED(hr)) {
66 // If this fails we're never going to get our ThebesLayer content.
67 update->mLayer->GetSink()->SetUnknown(update->mSequenceCounter);
68 return NS_OK;
69 }
71 nsRefPtr<gfxImageSurface> sourceSurface =
72 new gfxImageSurface((unsigned char*)mappedTex.pData,
73 gfxIntSize(desc.Width, desc.Height),
74 mappedTex.RowPitch,
75 gfxImageFormat::RGB24);
77 nsRefPtr<gfxContext> ctx =
78 update->mLayer->GetSink()->BeginUpdate(update->mUpdateRect + offset,
79 update->mSequenceCounter);
81 if (ctx) {
82 ctx->Translate(gfxPoint(offset.x, offset.y));
83 ctx->SetSource(sourceSurface, gfxPoint(mTask->mOrigin.x,
84 mTask->mOrigin.y));
85 ctx->Paint();
87 update->mLayer->GetSink()->EndUpdate(ctx, update->mUpdateRect + offset);
88 }
90 mTask->mReadbackTexture->Unmap(0);
92 return NS_OK;
93 }
95 private:
96 nsAutoPtr<ReadbackTask> mTask;
97 };
99 NS_IMPL_ISUPPORTS(ReadbackResultWriter, nsIRunnable)
101 DWORD WINAPI StartTaskThread(void *aManager)
102 {
103 static_cast<ReadbackManagerD3D10*>(aManager)->ProcessTasks();
105 return 0;
106 }
108 ReadbackManagerD3D10::ReadbackManagerD3D10()
109 : mRefCnt(0)
110 {
111 ::InitializeCriticalSection(&mTaskMutex);
112 mShutdownEvent = ::CreateEventA(nullptr, FALSE, FALSE, nullptr);
113 mTaskSemaphore = ::CreateSemaphoreA(nullptr, 0, 1000000, nullptr);
114 mTaskThread = ::CreateThread(nullptr, 0, StartTaskThread, this, 0, 0);
115 }
117 ReadbackManagerD3D10::~ReadbackManagerD3D10()
118 {
119 ::SetEvent(mShutdownEvent);
121 // This shouldn't take longer than 5 seconds, if it does we're going to choose
122 // to leak the thread and its synchronisation in favor of crashing or freezing
123 DWORD result = ::WaitForSingleObject(mTaskThread, 5000);
124 if (result != WAIT_TIMEOUT) {
125 ::DeleteCriticalSection(&mTaskMutex);
126 ::CloseHandle(mShutdownEvent);
127 ::CloseHandle(mTaskSemaphore);
128 ::CloseHandle(mTaskThread);
129 } else {
130 NS_RUNTIMEABORT("ReadbackManager: Task thread did not shutdown in 5 seconds.");
131 }
132 }
134 void
135 ReadbackManagerD3D10::PostTask(ID3D10Texture2D *aTexture, void *aUpdate, const gfxPoint &aOrigin)
136 {
137 ReadbackTask *task = new ReadbackTask;
138 task->mReadbackTexture = aTexture;
139 task->mUpdate = *static_cast<ReadbackProcessor::Update*>(aUpdate);
140 task->mOrigin = aOrigin;
141 task->mLayer = task->mUpdate.mLayer;
142 task->mBackgroundOffset = task->mLayer->GetBackgroundLayerOffset();
144 ::EnterCriticalSection(&mTaskMutex);
145 mPendingReadbackTasks.AppendElement(task);
146 ::LeaveCriticalSection(&mTaskMutex);
148 ::ReleaseSemaphore(mTaskSemaphore, 1, nullptr);
149 }
151 HRESULT
152 ReadbackManagerD3D10::QueryInterface(REFIID riid, void **ppvObject)
153 {
154 if (!ppvObject) {
155 return E_POINTER;
156 }
158 if (riid == IID_IUnknown) {
159 *ppvObject = this;
160 } else {
161 return E_NOINTERFACE;
162 }
164 return S_OK;
165 }
167 ULONG
168 ReadbackManagerD3D10::AddRef()
169 {
170 NS_ASSERTION(NS_IsMainThread(),
171 "ReadbackManagerD3D10 should only be refcounted on main thread.");
172 return ++mRefCnt;
173 }
175 ULONG
176 ReadbackManagerD3D10::Release()
177 {
178 NS_ASSERTION(NS_IsMainThread(),
179 "ReadbackManagerD3D10 should only be refcounted on main thread.");
180 ULONG newRefCnt = --mRefCnt;
181 if (!newRefCnt) {
182 mRefCnt++;
183 delete this;
184 }
185 return newRefCnt;
186 }
188 void
189 ReadbackManagerD3D10::ProcessTasks()
190 {
191 HANDLE handles[] = { mTaskSemaphore, mShutdownEvent };
193 while (true) {
194 DWORD result = ::WaitForMultipleObjects(2, handles, FALSE, INFINITE);
195 if (result != WAIT_OBJECT_0) {
196 return;
197 }
199 ::EnterCriticalSection(&mTaskMutex);
200 if (mPendingReadbackTasks.Length() == 0) {
201 NS_RUNTIMEABORT("Trying to read from an empty array, bad bad bad");
202 }
203 ReadbackTask *nextReadbackTask = mPendingReadbackTasks[0].forget();
204 mPendingReadbackTasks.RemoveElementAt(0);
205 ::LeaveCriticalSection(&mTaskMutex);
207 // We want to block here until the texture contents are available, the
208 // easiest thing is to simply map and unmap.
209 D3D10_MAPPED_TEXTURE2D mappedTex;
210 nextReadbackTask->mReadbackTexture->Map(0, D3D10_MAP_READ, 0, &mappedTex);
211 nextReadbackTask->mReadbackTexture->Unmap(0);
213 // We can only send the update to the sink on the main thread, so post an
214 // event there to do so. Ownership of the task is passed from
215 // mPendingReadbackTasks to ReadbackResultWriter here.
216 nsCOMPtr<nsIThread> thread = do_GetMainThread();
217 thread->Dispatch(new ReadbackResultWriter(nextReadbackTask),
218 nsIEventTarget::DISPATCH_NORMAL);
219 }
220 }
222 }
223 }