Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* vim:set ts=4 sw=4 sts=4 et: */
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/. */
6 :
7 : /* This must occur *after* layers/PLayers.h to avoid typedefs conflicts. */
8 : #include "LayerScope.h"
9 :
10 : #include "nsAppRunner.h"
11 : #include "Effects.h"
12 : #include "mozilla/EndianUtils.h"
13 : #include "mozilla/MathAlgorithms.h"
14 : #include "mozilla/Preferences.h"
15 : #include "mozilla/TimeStamp.h"
16 :
17 : #include "TexturePoolOGL.h"
18 : #include "mozilla/layers/CompositorOGL.h"
19 : #include "mozilla/layers/CompositorThread.h"
20 : #include "mozilla/layers/LayerManagerComposite.h"
21 : #include "mozilla/layers/TextureHostOGL.h"
22 :
23 : #include "gfxContext.h"
24 : #include "gfxUtils.h"
25 : #include "gfxPrefs.h"
26 : #include "nsIWidget.h"
27 :
28 : #include "GLContext.h"
29 : #include "GLContextProvider.h"
30 : #include "GLReadTexImageHelper.h"
31 :
32 : #include "nsIServiceManager.h"
33 : #include "nsIConsoleService.h"
34 :
35 : #include <memory>
36 : #include "mozilla/LinkedList.h"
37 : #include "mozilla/Base64.h"
38 : #include "mozilla/SHA1.h"
39 : #include "mozilla/StaticPtr.h"
40 : #include "nsThreadUtils.h"
41 : #include "nsISocketTransport.h"
42 : #include "nsIServerSocket.h"
43 : #include "nsReadLine.h"
44 : #include "nsNetCID.h"
45 : #include "nsIOutputStream.h"
46 : #include "nsIAsyncInputStream.h"
47 : #include "nsIEventTarget.h"
48 : #include "nsProxyRelease.h"
49 : #include <list>
50 :
51 : // Undo the damage done by mozzconf.h
52 : #undef compress
53 : #include "mozilla/Compression.h"
54 :
55 : // Protocol buffer (generated automatically)
56 : #include "protobuf/LayerScopePacket.pb.h"
57 :
58 : namespace mozilla {
59 : namespace layers {
60 :
61 : using namespace mozilla::Compression;
62 : using namespace mozilla::gfx;
63 : using namespace mozilla::gl;
64 : using namespace mozilla;
65 : using namespace layerscope;
66 :
67 : class DebugDataSender;
68 : class DebugGLData;
69 :
70 : /*
71 : * Manage Websocket connections
72 : */
73 : class LayerScopeWebSocketManager {
74 : public:
75 : LayerScopeWebSocketManager();
76 : ~LayerScopeWebSocketManager();
77 :
78 0 : void RemoveAllConnections()
79 : {
80 0 : MOZ_ASSERT(NS_IsMainThread());
81 :
82 0 : MutexAutoLock lock(mHandlerMutex);
83 0 : mHandlers.Clear();
84 0 : }
85 :
86 0 : bool WriteAll(void *ptr, uint32_t size)
87 : {
88 0 : for (int32_t i = mHandlers.Length() - 1; i >= 0; --i) {
89 0 : if (!mHandlers[i]->WriteToStream(ptr, size)) {
90 : // Send failed, remove this handler
91 0 : RemoveConnection(i);
92 : }
93 : }
94 :
95 0 : return true;
96 : }
97 :
98 0 : bool IsConnected()
99 : {
100 : // This funtion can be called in both main thread and compositor thread.
101 0 : MutexAutoLock lock(mHandlerMutex);
102 0 : return (mHandlers.Length() != 0) ? true : false;
103 : }
104 :
105 : void AppendDebugData(DebugGLData *aDebugData);
106 : void CleanDebugData();
107 : void DispatchDebugData();
108 :
109 : private:
110 0 : void AddConnection(nsISocketTransport *aTransport)
111 : {
112 0 : MOZ_ASSERT(NS_IsMainThread());
113 0 : MOZ_ASSERT(aTransport);
114 :
115 0 : MutexAutoLock lock(mHandlerMutex);
116 :
117 0 : RefPtr<SocketHandler> temp = new SocketHandler();
118 0 : temp->OpenStream(aTransport);
119 0 : mHandlers.AppendElement(temp.get());
120 0 : }
121 :
122 0 : void RemoveConnection(uint32_t aIndex)
123 : {
124 : // TBD: RemoveConnection is executed on the compositor thread and
125 : // AddConntection is executed on the main thread, which might be
126 : // a problem if a user disconnect and connect readlly quickly at
127 : // viewer side.
128 :
129 : // We should dispatch RemoveConnection onto main thead.
130 0 : MOZ_ASSERT(aIndex < mHandlers.Length());
131 :
132 0 : MutexAutoLock lock(mHandlerMutex);
133 0 : mHandlers.RemoveElementAt(aIndex);
134 0 : }
135 :
136 : friend class SocketListener;
137 : class SocketListener : public nsIServerSocketListener
138 : {
139 : public:
140 : NS_DECL_THREADSAFE_ISUPPORTS
141 :
142 0 : SocketListener() { }
143 :
144 : /* nsIServerSocketListener */
145 : NS_IMETHOD OnSocketAccepted(nsIServerSocket *aServ,
146 : nsISocketTransport *aTransport) override;
147 0 : NS_IMETHOD OnStopListening(nsIServerSocket *aServ,
148 : nsresult aStatus) override
149 : {
150 0 : return NS_OK;
151 : }
152 : private:
153 0 : virtual ~SocketListener() { }
154 : };
155 :
156 : /*
157 : * This class handle websocket protocol which included
158 : * handshake and data frame's header
159 : */
160 : class SocketHandler : public nsIInputStreamCallback {
161 : public:
162 : NS_DECL_THREADSAFE_ISUPPORTS
163 :
164 0 : SocketHandler()
165 0 : : mState(NoHandshake)
166 0 : , mConnected(false)
167 0 : { }
168 :
169 : void OpenStream(nsISocketTransport* aTransport);
170 : bool WriteToStream(void *aPtr, uint32_t aSize);
171 :
172 : // nsIInputStreamCallback
173 : NS_IMETHOD OnInputStreamReady(nsIAsyncInputStream *aStream) override;
174 :
175 : private:
176 0 : virtual ~SocketHandler() { CloseConnection(); }
177 :
178 : void ReadInputStreamData(nsTArray<nsCString>& aProtocolString);
179 : bool WebSocketHandshake(nsTArray<nsCString>& aProtocolString);
180 : void ApplyMask(uint32_t aMask, uint8_t *aData, uint64_t aLen);
181 : bool HandleDataFrame(uint8_t *aData, uint32_t aSize);
182 : void CloseConnection();
183 :
184 : nsresult HandleSocketMessage(nsIAsyncInputStream *aStream);
185 : nsresult ProcessInput(uint8_t *aBuffer, uint32_t aCount);
186 :
187 : private:
188 : enum SocketStateType {
189 : NoHandshake,
190 : HandshakeSuccess,
191 : HandshakeFailed
192 : };
193 : SocketStateType mState;
194 :
195 : nsCOMPtr<nsIOutputStream> mOutputStream;
196 : nsCOMPtr<nsIAsyncInputStream> mInputStream;
197 : nsCOMPtr<nsISocketTransport> mTransport;
198 : bool mConnected;
199 : };
200 :
201 : nsTArray<RefPtr<SocketHandler> > mHandlers;
202 : nsCOMPtr<nsIThread> mDebugSenderThread;
203 : RefPtr<DebugDataSender> mCurrentSender;
204 : nsCOMPtr<nsIServerSocket> mServerSocket;
205 :
206 : // Keep mHandlers accessing thread safe.
207 : Mutex mHandlerMutex;
208 : };
209 :
210 0 : NS_IMPL_ISUPPORTS(LayerScopeWebSocketManager::SocketListener,
211 : nsIServerSocketListener);
212 0 : NS_IMPL_ISUPPORTS(LayerScopeWebSocketManager::SocketHandler,
213 : nsIInputStreamCallback);
214 :
215 0 : class DrawSession {
216 : public:
217 0 : DrawSession()
218 0 : : mOffsetX(0.0)
219 : , mOffsetY(0.0)
220 0 : , mRects(0)
221 0 : { }
222 :
223 : float mOffsetX;
224 : float mOffsetY;
225 : gfx::Matrix4x4 mMVMatrix;
226 : size_t mRects;
227 : gfx::Rect mLayerRects[4];
228 : gfx::Rect mTextureRects[4];
229 : std::list<GLuint> mTexIDs;
230 : };
231 :
232 0 : class ContentMonitor {
233 : public:
234 : using THArray = nsTArray<const TextureHost *>;
235 :
236 : // Notify the content of a TextureHost was changed.
237 0 : void SetChangedHost(const TextureHost* host) {
238 0 : if (THArray::NoIndex == mChangedHosts.IndexOf(host)) {
239 0 : mChangedHosts.AppendElement(host);
240 : }
241 0 : }
242 :
243 : // Clear changed flag of a host.
244 : void ClearChangedHost(const TextureHost* host) {
245 : if (THArray::NoIndex != mChangedHosts.IndexOf(host)) {
246 : mChangedHosts.RemoveElement(host);
247 : }
248 : }
249 :
250 : // Return true iff host is a new one or the content of it had been changed.
251 : bool IsChangedOrNew(const TextureHost* host) {
252 : if (THArray::NoIndex == mSeenHosts.IndexOf(host)) {
253 : mSeenHosts.AppendElement(host);
254 : return true;
255 : }
256 :
257 : if (decltype(mChangedHosts)::NoIndex != mChangedHosts.IndexOf(host)) {
258 : return true;
259 : }
260 :
261 : return false;
262 : }
263 :
264 0 : void Empty() {
265 0 : mSeenHosts.SetLength(0);
266 0 : mChangedHosts.SetLength(0);
267 0 : }
268 : private:
269 : THArray mSeenHosts;
270 : THArray mChangedHosts;
271 : };
272 :
273 : /*
274 : * Hold all singleton objects used by LayerScope.
275 : */
276 0 : class LayerScopeManager
277 : {
278 : public:
279 0 : void CreateServerSocket()
280 : {
281 : // WebSocketManager must be created on the main thread.
282 0 : if (NS_IsMainThread()) {
283 0 : mWebSocketManager = mozilla::MakeUnique<LayerScopeWebSocketManager>();
284 : } else {
285 : // Dispatch creation to main thread, and make sure we
286 : // dispatch this only once after booting
287 : static bool dispatched = false;
288 0 : if (dispatched) {
289 0 : return;
290 : }
291 :
292 : DebugOnly<nsresult> rv =
293 0 : NS_DispatchToMainThread(new CreateServerSocketRunnable(this));
294 0 : MOZ_ASSERT(NS_SUCCEEDED(rv),
295 : "Failed to dispatch WebSocket Creation to main thread");
296 0 : dispatched = true;
297 : }
298 : }
299 :
300 0 : void DestroyServerSocket()
301 : {
302 : // Destroy Web Server Socket
303 0 : if (mWebSocketManager) {
304 0 : mWebSocketManager->RemoveAllConnections();
305 : }
306 0 : }
307 :
308 0 : LayerScopeWebSocketManager* GetSocketManager()
309 : {
310 0 : return mWebSocketManager.get();
311 : }
312 :
313 0 : ContentMonitor* GetContentMonitor()
314 : {
315 0 : if (!mContentMonitor.get()) {
316 0 : mContentMonitor = mozilla::MakeUnique<ContentMonitor>();
317 : }
318 :
319 0 : return mContentMonitor.get();
320 : }
321 :
322 0 : void NewDrawSession() {
323 0 : mSession = mozilla::MakeUnique<DrawSession>();
324 0 : }
325 :
326 0 : DrawSession& CurrentSession() {
327 0 : return *mSession;
328 : }
329 :
330 1 : void SetPixelScale(double scale) {
331 1 : mScale = scale;
332 1 : }
333 :
334 0 : double GetPixelScale() const {
335 0 : return mScale;
336 : }
337 :
338 3 : LayerScopeManager()
339 3 : : mScale(1.0)
340 : {
341 3 : }
342 : private:
343 : friend class CreateServerSocketRunnable;
344 0 : class CreateServerSocketRunnable : public Runnable
345 : {
346 : public:
347 0 : explicit CreateServerSocketRunnable(LayerScopeManager* aLayerScopeManager)
348 0 : : Runnable("layers::LayerScopeManager::CreateServerSocketRunnable")
349 0 : , mLayerScopeManager(aLayerScopeManager)
350 : {
351 0 : }
352 0 : NS_IMETHOD Run() override {
353 0 : mLayerScopeManager->mWebSocketManager =
354 0 : mozilla::MakeUnique<LayerScopeWebSocketManager>();
355 0 : return NS_OK;
356 : }
357 : private:
358 : LayerScopeManager* mLayerScopeManager;
359 : };
360 :
361 : mozilla::UniquePtr<LayerScopeWebSocketManager> mWebSocketManager;
362 : mozilla::UniquePtr<DrawSession> mSession;
363 : mozilla::UniquePtr<ContentMonitor> mContentMonitor;
364 : double mScale;
365 : };
366 :
367 3 : LayerScopeManager gLayerScopeManager;
368 :
369 : /*
370 : * The static helper functions that set data into the packet
371 : * 1. DumpRect
372 : * 2. DumpFilter
373 : */
374 : template<typename T>
375 0 : static void DumpRect(T* aPacketRect, const Rect& aRect)
376 : {
377 0 : aPacketRect->set_x(aRect.x);
378 0 : aPacketRect->set_y(aRect.y);
379 0 : aPacketRect->set_w(aRect.width);
380 0 : aPacketRect->set_h(aRect.height);
381 0 : }
382 :
383 0 : static void DumpFilter(TexturePacket* aTexturePacket,
384 : const SamplingFilter aSamplingFilter)
385 : {
386 0 : switch (aSamplingFilter) {
387 : case SamplingFilter::GOOD:
388 0 : aTexturePacket->set_mfilter(TexturePacket::GOOD);
389 0 : break;
390 : case SamplingFilter::LINEAR:
391 0 : aTexturePacket->set_mfilter(TexturePacket::LINEAR);
392 0 : break;
393 : case SamplingFilter::POINT:
394 0 : aTexturePacket->set_mfilter(TexturePacket::POINT);
395 0 : break;
396 : default:
397 0 : MOZ_ASSERT(false, "Can't dump unexpected mSamplingFilter to texture packet!");
398 : break;
399 : }
400 0 : }
401 :
402 : /*
403 : * DebugGLData is the base class of
404 : * 1. DebugGLFrameStatusData (Frame start/end packet)
405 : * 2. DebugGLColorData (Color data packet)
406 : * 3. DebugGLTextureData (Texture data packet)
407 : * 4. DebugGLLayersData (Layers Tree data packet)
408 : * 5. DebugGLMetaData (Meta data packet)
409 : */
410 : class DebugGLData: public LinkedListElement<DebugGLData> {
411 : public:
412 0 : explicit DebugGLData(Packet::DataType aDataType)
413 0 : : mDataType(aDataType)
414 0 : { }
415 :
416 0 : virtual ~DebugGLData() { }
417 :
418 : virtual bool Write() = 0;
419 :
420 : protected:
421 0 : static bool WriteToStream(Packet& aPacket) {
422 0 : if (!gLayerScopeManager.GetSocketManager())
423 0 : return true;
424 :
425 0 : uint32_t size = aPacket.ByteSize();
426 0 : auto data = MakeUnique<uint8_t[]>(size);
427 0 : aPacket.SerializeToArray(data.get(), size);
428 0 : return gLayerScopeManager.GetSocketManager()->WriteAll(data.get(), size);
429 : }
430 :
431 : Packet::DataType mDataType;
432 : };
433 :
434 0 : class DebugGLFrameStatusData final: public DebugGLData
435 : {
436 : public:
437 0 : DebugGLFrameStatusData(Packet::DataType aDataType,
438 : int64_t aValue)
439 0 : : DebugGLData(aDataType),
440 0 : mFrameStamp(aValue)
441 0 : { }
442 :
443 0 : explicit DebugGLFrameStatusData(Packet::DataType aDataType)
444 0 : : DebugGLData(aDataType),
445 0 : mFrameStamp(0)
446 0 : { }
447 :
448 0 : virtual bool Write() override {
449 0 : Packet packet;
450 0 : packet.set_type(mDataType);
451 :
452 0 : FramePacket* fp = packet.mutable_frame();
453 0 : fp->set_value(static_cast<uint64_t>(mFrameStamp));
454 :
455 0 : fp->set_scale(gLayerScopeManager.GetPixelScale());
456 :
457 0 : return WriteToStream(packet);
458 : }
459 :
460 : protected:
461 : int64_t mFrameStamp;
462 : };
463 :
464 0 : class DebugGLTextureData final: public DebugGLData {
465 : public:
466 0 : DebugGLTextureData(GLContext* cx,
467 : void* layerRef,
468 : GLenum target,
469 : GLuint name,
470 : DataSourceSurface* img,
471 : bool aIsMask,
472 : UniquePtr<Packet> aPacket)
473 0 : : DebugGLData(Packet::TEXTURE),
474 : mLayerRef(reinterpret_cast<uint64_t>(layerRef)),
475 : mTarget(target),
476 : mName(name),
477 : mContextAddress(reinterpret_cast<intptr_t>(cx)),
478 : mDatasize(0),
479 : mIsMask(aIsMask),
480 0 : mPacket(Move(aPacket))
481 : {
482 : // pre-packing
483 : // DataSourceSurface may have locked buffer,
484 : // so we should compress now, and then it could
485 : // be unlocked outside.
486 0 : pack(img);
487 0 : }
488 :
489 0 : virtual bool Write() override {
490 0 : return WriteToStream(*mPacket);
491 : }
492 :
493 : private:
494 0 : void pack(DataSourceSurface* aImage) {
495 0 : mPacket->set_type(mDataType);
496 :
497 0 : TexturePacket* tp = mPacket->mutable_texture();
498 0 : tp->set_layerref(mLayerRef);
499 0 : tp->set_name(mName);
500 0 : tp->set_target(mTarget);
501 0 : tp->set_dataformat(LOCAL_GL_RGBA);
502 0 : tp->set_glcontext(static_cast<uint64_t>(mContextAddress));
503 0 : tp->set_ismask(mIsMask);
504 :
505 0 : if (aImage) {
506 0 : tp->set_width(aImage->GetSize().width);
507 0 : tp->set_height(aImage->GetSize().height);
508 0 : tp->set_stride(aImage->Stride());
509 :
510 0 : mDatasize = aImage->GetSize().height * aImage->Stride();
511 :
512 0 : auto compresseddata = MakeUnique<char[]>(LZ4::maxCompressedSize(mDatasize));
513 0 : if (compresseddata) {
514 0 : int ndatasize = LZ4::compress((char*)aImage->GetData(),
515 0 : mDatasize,
516 0 : compresseddata.get());
517 0 : if (ndatasize > 0) {
518 0 : mDatasize = ndatasize;
519 0 : tp->set_dataformat((1 << 16 | tp->dataformat()));
520 0 : tp->set_data(compresseddata.get(), mDatasize);
521 : } else {
522 0 : NS_WARNING("Compress data failed");
523 0 : tp->set_data(aImage->GetData(), mDatasize);
524 : }
525 : } else {
526 0 : NS_WARNING("Couldn't new compressed data.");
527 0 : tp->set_data(aImage->GetData(), mDatasize);
528 : }
529 : } else {
530 0 : tp->set_width(0);
531 0 : tp->set_height(0);
532 0 : tp->set_stride(0);
533 : }
534 0 : }
535 :
536 : protected:
537 : uint64_t mLayerRef;
538 : GLenum mTarget;
539 : GLuint mName;
540 : intptr_t mContextAddress;
541 : uint32_t mDatasize;
542 : bool mIsMask;
543 :
544 : // Packet data
545 : UniquePtr<Packet> mPacket;
546 : };
547 :
548 0 : class DebugGLColorData final: public DebugGLData {
549 : public:
550 0 : DebugGLColorData(void* layerRef,
551 : const Color& color,
552 : int width,
553 : int height)
554 0 : : DebugGLData(Packet::COLOR),
555 : mLayerRef(reinterpret_cast<uint64_t>(layerRef)),
556 0 : mColor(color.ToABGR()),
557 0 : mSize(width, height)
558 0 : { }
559 :
560 0 : virtual bool Write() override {
561 0 : Packet packet;
562 0 : packet.set_type(mDataType);
563 :
564 0 : ColorPacket* cp = packet.mutable_color();
565 0 : cp->set_layerref(mLayerRef);
566 0 : cp->set_color(mColor);
567 0 : cp->set_width(mSize.width);
568 0 : cp->set_height(mSize.height);
569 :
570 0 : return WriteToStream(packet);
571 : }
572 :
573 : protected:
574 : uint64_t mLayerRef;
575 : uint32_t mColor;
576 : IntSize mSize;
577 : };
578 :
579 0 : class DebugGLLayersData final: public DebugGLData {
580 : public:
581 0 : explicit DebugGLLayersData(UniquePtr<Packet> aPacket)
582 0 : : DebugGLData(Packet::LAYERS),
583 0 : mPacket(Move(aPacket))
584 0 : { }
585 :
586 0 : virtual bool Write() override {
587 0 : mPacket->set_type(mDataType);
588 0 : return WriteToStream(*mPacket);
589 : }
590 :
591 : protected:
592 : UniquePtr<Packet> mPacket;
593 : };
594 :
595 0 : class DebugGLMetaData final: public DebugGLData
596 : {
597 : public:
598 0 : DebugGLMetaData(Packet::DataType aDataType,
599 : bool aValue)
600 0 : : DebugGLData(aDataType),
601 0 : mComposedByHwc(aValue)
602 0 : { }
603 :
604 : explicit DebugGLMetaData(Packet::DataType aDataType)
605 : : DebugGLData(aDataType),
606 : mComposedByHwc(false)
607 : { }
608 :
609 0 : virtual bool Write() override {
610 0 : Packet packet;
611 0 : packet.set_type(mDataType);
612 :
613 0 : MetaPacket* mp = packet.mutable_meta();
614 0 : mp->set_composedbyhwc(mComposedByHwc);
615 :
616 0 : return WriteToStream(packet);
617 : }
618 :
619 : protected:
620 : bool mComposedByHwc;
621 : };
622 :
623 0 : class DebugGLDrawData final: public DebugGLData {
624 : public:
625 0 : DebugGLDrawData(float aOffsetX,
626 : float aOffsetY,
627 : const gfx::Matrix4x4& aMVMatrix,
628 : size_t aRects,
629 : const gfx::Rect* aLayerRects,
630 : const gfx::Rect* aTextureRects,
631 : const std::list<GLuint> aTexIDs,
632 : void* aLayerRef)
633 0 : : DebugGLData(Packet::DRAW),
634 : mOffsetX(aOffsetX),
635 : mOffsetY(aOffsetY),
636 : mMVMatrix(aMVMatrix),
637 : mRects(aRects),
638 : mTexIDs(aTexIDs),
639 0 : mLayerRef(reinterpret_cast<uint64_t>(aLayerRef))
640 : {
641 0 : for (size_t i = 0; i < mRects; i++){
642 0 : mLayerRects[i] = aLayerRects[i];
643 0 : mTextureRects[i] = aTextureRects[i];
644 : }
645 0 : }
646 :
647 0 : virtual bool Write() override {
648 0 : Packet packet;
649 0 : packet.set_type(mDataType);
650 :
651 0 : DrawPacket* dp = packet.mutable_draw();
652 0 : dp->set_layerref(mLayerRef);
653 :
654 0 : dp->set_offsetx(mOffsetX);
655 0 : dp->set_offsety(mOffsetY);
656 :
657 0 : auto element = reinterpret_cast<Float *>(&mMVMatrix);
658 0 : for (int i = 0; i < 16; i++) {
659 0 : dp->add_mvmatrix(*element++);
660 : }
661 0 : dp->set_totalrects(mRects);
662 :
663 0 : MOZ_ASSERT(mRects > 0 && mRects < 4);
664 0 : for (size_t i = 0; i < mRects; i++) {
665 : // Vertex
666 0 : DumpRect(dp->add_layerrect(), mLayerRects[i]);
667 : // UV
668 0 : DumpRect(dp->add_texturerect(), mTextureRects[i]);
669 : }
670 :
671 0 : for (GLuint texId: mTexIDs) {
672 0 : dp->add_texids(texId);
673 : }
674 :
675 0 : return WriteToStream(packet);
676 : }
677 :
678 : protected:
679 : float mOffsetX;
680 : float mOffsetY;
681 : gfx::Matrix4x4 mMVMatrix;
682 : size_t mRects;
683 : gfx::Rect mLayerRects[4];
684 : gfx::Rect mTextureRects[4];
685 : std::list<GLuint> mTexIDs;
686 : uint64_t mLayerRef;
687 : };
688 :
689 : class DebugDataSender
690 : {
691 : public:
692 0 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DebugDataSender)
693 :
694 : // Append a DebugData into mList on mThread
695 : class AppendTask: public nsIRunnable
696 : {
697 : public:
698 : NS_DECL_THREADSAFE_ISUPPORTS
699 :
700 0 : AppendTask(DebugDataSender *host, DebugGLData *d)
701 0 : : mData(d),
702 0 : mHost(host)
703 0 : { }
704 :
705 0 : NS_IMETHOD Run() override {
706 0 : mHost->mList.insertBack(mData);
707 0 : return NS_OK;
708 : }
709 :
710 : private:
711 0 : virtual ~AppendTask() { }
712 :
713 : DebugGLData *mData;
714 : // Keep a strong reference to DebugDataSender to prevent this object
715 : // accessing mHost on mThread, when it's been destroyed on the main
716 : // thread.
717 : RefPtr<DebugDataSender> mHost;
718 : };
719 :
720 : // Clear all DebugData in mList on mThead.
721 : class ClearTask: public nsIRunnable
722 : {
723 : public:
724 : NS_DECL_THREADSAFE_ISUPPORTS
725 0 : explicit ClearTask(DebugDataSender *host)
726 0 : : mHost(host)
727 0 : { }
728 :
729 0 : NS_IMETHOD Run() override {
730 0 : mHost->RemoveData();
731 0 : return NS_OK;
732 : }
733 :
734 : private:
735 0 : virtual ~ClearTask() { }
736 :
737 : RefPtr<DebugDataSender> mHost;
738 : };
739 :
740 : // Send all DebugData in mList via websocket, and then, clean up
741 : // mList on mThread.
742 : class SendTask: public nsIRunnable
743 : {
744 : public:
745 : NS_DECL_THREADSAFE_ISUPPORTS
746 :
747 0 : explicit SendTask(DebugDataSender *host)
748 0 : : mHost(host)
749 0 : { }
750 :
751 0 : NS_IMETHOD Run() override {
752 : // Sendout all appended debug data.
753 0 : DebugGLData *d = nullptr;
754 0 : while ((d = mHost->mList.popFirst()) != nullptr) {
755 0 : UniquePtr<DebugGLData> cleaner(d);
756 0 : if (!d->Write()) {
757 0 : gLayerScopeManager.DestroyServerSocket();
758 0 : break;
759 : }
760 : }
761 :
762 : // Cleanup.
763 0 : mHost->RemoveData();
764 0 : return NS_OK;
765 : }
766 : private:
767 0 : virtual ~SendTask() { }
768 :
769 : RefPtr<DebugDataSender> mHost;
770 : };
771 :
772 0 : explicit DebugDataSender(nsIThread *thread)
773 0 : : mThread(thread)
774 0 : { }
775 :
776 0 : void Append(DebugGLData *d) {
777 0 : mThread->Dispatch(new AppendTask(this, d), NS_DISPATCH_NORMAL);
778 0 : }
779 :
780 0 : void Cleanup() {
781 0 : mThread->Dispatch(new ClearTask(this), NS_DISPATCH_NORMAL);
782 0 : }
783 :
784 0 : void Send() {
785 0 : mThread->Dispatch(new SendTask(this), NS_DISPATCH_NORMAL);
786 0 : }
787 :
788 : protected:
789 0 : virtual ~DebugDataSender() {}
790 0 : void RemoveData() {
791 0 : MOZ_ASSERT(mThread->SerialEventTarget()->IsOnCurrentThread());
792 0 : if (mList.isEmpty())
793 0 : return;
794 :
795 : DebugGLData *d;
796 0 : while ((d = mList.popFirst()) != nullptr)
797 0 : delete d;
798 : }
799 :
800 : // We can only modify or aceess mList on mThread.
801 : LinkedList<DebugGLData> mList;
802 : nsCOMPtr<nsIThread> mThread;
803 : };
804 :
805 0 : NS_IMPL_ISUPPORTS(DebugDataSender::AppendTask, nsIRunnable);
806 0 : NS_IMPL_ISUPPORTS(DebugDataSender::ClearTask, nsIRunnable);
807 0 : NS_IMPL_ISUPPORTS(DebugDataSender::SendTask, nsIRunnable);
808 :
809 :
810 : /*
811 : * LayerScope SendXXX Structure
812 : * 1. SendLayer
813 : * 2. SendEffectChain
814 : * 1. SendTexturedEffect
815 : * -> SendTextureSource
816 : * 2. SendMaskEffect
817 : * -> SendTextureSource
818 : * 3. SendYCbCrEffect
819 : * -> SendTextureSource
820 : * 4. SendColor
821 : */
822 : class SenderHelper
823 : {
824 : // Sender public APIs
825 : public:
826 : static void SendLayer(LayerComposite* aLayer,
827 : int aWidth,
828 : int aHeight);
829 :
830 : static void SendEffectChain(gl::GLContext* aGLContext,
831 : const EffectChain& aEffectChain,
832 : int aWidth = 0,
833 : int aHeight = 0);
834 :
835 0 : static void SetLayersTreeSendable(bool aSet) {sLayersTreeSendable = aSet;}
836 :
837 0 : static void SetLayersBufferSendable(bool aSet) {sLayersBufferSendable = aSet;}
838 :
839 0 : static bool GetLayersTreeSendable() {return sLayersTreeSendable;}
840 :
841 : static void ClearSentTextureIds();
842 :
843 : // Sender private functions
844 : private:
845 : static void SendColor(void* aLayerRef,
846 : const Color& aColor,
847 : int aWidth,
848 : int aHeight);
849 : static void SendTextureSource(GLContext* aGLContext,
850 : void* aLayerRef,
851 : TextureSourceOGL* aSource,
852 : bool aFlipY,
853 : bool aIsMask,
854 : UniquePtr<Packet> aPacket);
855 : static void SetAndSendTexture(GLContext* aGLContext,
856 : void* aLayerRef,
857 : TextureSourceOGL* aSource,
858 : const TexturedEffect* aEffect);
859 : static void SendTexturedEffect(GLContext* aGLContext,
860 : void* aLayerRef,
861 : const TexturedEffect* aEffect);
862 : static void SendMaskEffect(GLContext* aGLContext,
863 : void* aLayerRef,
864 : const EffectMask* aEffect);
865 : static void SendYCbCrEffect(GLContext* aGLContext,
866 : void* aLayerRef,
867 : const EffectYCbCr* aEffect);
868 : static GLuint GetTextureID(GLContext* aGLContext,
869 : TextureSourceOGL* aSource);
870 : static bool HasTextureIdBeenSent(GLuint aTextureId);
871 : // Data fields
872 : private:
873 : static bool sLayersTreeSendable;
874 : static bool sLayersBufferSendable;
875 : static std::vector<GLuint> sSentTextureIds;
876 : };
877 :
878 : bool SenderHelper::sLayersTreeSendable = true;
879 : bool SenderHelper::sLayersBufferSendable = true;
880 3 : std::vector<GLuint> SenderHelper::sSentTextureIds;
881 :
882 :
883 : // ----------------------------------------------
884 : // SenderHelper implementation
885 : // ----------------------------------------------
886 : void
887 0 : SenderHelper::ClearSentTextureIds()
888 : {
889 0 : sSentTextureIds.clear();
890 0 : }
891 :
892 : bool
893 0 : SenderHelper::HasTextureIdBeenSent(GLuint aTextureId)
894 : {
895 0 : return std::find(sSentTextureIds.begin(), sSentTextureIds.end(), aTextureId) != sSentTextureIds.end();
896 : }
897 :
898 : void
899 0 : SenderHelper::SendLayer(LayerComposite* aLayer,
900 : int aWidth,
901 : int aHeight)
902 : {
903 0 : MOZ_ASSERT(aLayer && aLayer->GetLayer());
904 0 : if (!aLayer || !aLayer->GetLayer()) {
905 0 : return;
906 : }
907 :
908 0 : switch (aLayer->GetLayer()->GetType()) {
909 : case Layer::TYPE_COLOR: {
910 0 : EffectChain effect;
911 0 : aLayer->GenEffectChain(effect);
912 :
913 0 : LayerScope::DrawBegin();
914 0 : LayerScope::DrawEnd(nullptr, effect, aWidth, aHeight);
915 0 : break;
916 : }
917 : case Layer::TYPE_IMAGE:
918 : case Layer::TYPE_CANVAS:
919 : case Layer::TYPE_PAINTED: {
920 : // Get CompositableHost and Compositor
921 0 : CompositableHost* compHost = aLayer->GetCompositableHost();
922 0 : TextureSourceProvider* provider = compHost->GetTextureSourceProvider();
923 0 : Compositor* comp = provider->AsCompositor();
924 : // Send EffectChain only for CompositorOGL
925 0 : if (LayersBackend::LAYERS_OPENGL == comp->GetBackendType()) {
926 0 : CompositorOGL* compOGL = comp->AsCompositorOGL();
927 0 : EffectChain effect;
928 : // Generate primary effect (lock and gen)
929 0 : AutoLockCompositableHost lock(compHost);
930 0 : aLayer->GenEffectChain(effect);
931 :
932 0 : LayerScope::DrawBegin();
933 0 : LayerScope::DrawEnd(compOGL->gl(), effect, aWidth, aHeight);
934 : }
935 0 : break;
936 : }
937 : case Layer::TYPE_CONTAINER:
938 : default:
939 0 : break;
940 : }
941 : }
942 :
943 : void
944 0 : SenderHelper::SendColor(void* aLayerRef,
945 : const Color& aColor,
946 : int aWidth,
947 : int aHeight)
948 : {
949 0 : gLayerScopeManager.GetSocketManager()->AppendDebugData(
950 0 : new DebugGLColorData(aLayerRef, aColor, aWidth, aHeight));
951 0 : }
952 :
953 : GLuint
954 0 : SenderHelper::GetTextureID(GLContext* aGLContext,
955 : TextureSourceOGL* aSource) {
956 0 : GLenum textureTarget = aSource->GetTextureTarget();
957 0 : aSource->BindTexture(LOCAL_GL_TEXTURE0, gfx::SamplingFilter::LINEAR);
958 :
959 0 : GLuint texID = 0;
960 : // This is horrid hack. It assumes that aGLContext matches the context
961 : // aSource has bound to.
962 0 : if (textureTarget == LOCAL_GL_TEXTURE_2D) {
963 0 : aGLContext->GetUIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, &texID);
964 0 : } else if (textureTarget == LOCAL_GL_TEXTURE_EXTERNAL) {
965 0 : aGLContext->GetUIntegerv(LOCAL_GL_TEXTURE_BINDING_EXTERNAL, &texID);
966 0 : } else if (textureTarget == LOCAL_GL_TEXTURE_RECTANGLE) {
967 0 : aGLContext->GetUIntegerv(LOCAL_GL_TEXTURE_BINDING_RECTANGLE, &texID);
968 : }
969 :
970 0 : return texID;
971 : }
972 :
973 : void
974 0 : SenderHelper::SendTextureSource(GLContext* aGLContext,
975 : void* aLayerRef,
976 : TextureSourceOGL* aSource,
977 : bool aFlipY,
978 : bool aIsMask,
979 : UniquePtr<Packet> aPacket)
980 : {
981 0 : MOZ_ASSERT(aGLContext);
982 0 : if (!aGLContext) {
983 0 : return;
984 : }
985 0 : GLuint texID = GetTextureID(aGLContext, aSource);
986 0 : if (HasTextureIdBeenSent(texID)) {
987 0 : return;
988 : }
989 :
990 0 : GLenum textureTarget = aSource->GetTextureTarget();
991 : ShaderConfigOGL config = ShaderConfigFromTargetAndFormat(textureTarget,
992 0 : aSource->GetFormat());
993 0 : int shaderConfig = config.mFeatures;
994 :
995 0 : gfx::IntSize size = aSource->GetSize();
996 :
997 : // By sending 0 to ReadTextureImage rely upon aSource->BindTexture binding
998 : // texture correctly. texID is used for tracking in DebugGLTextureData.
999 : RefPtr<DataSourceSurface> img =
1000 0 : aGLContext->ReadTexImageHelper()->ReadTexImage(0, textureTarget,
1001 : size,
1002 0 : shaderConfig, aFlipY);
1003 0 : gLayerScopeManager.GetSocketManager()->AppendDebugData(
1004 : new DebugGLTextureData(aGLContext, aLayerRef, textureTarget,
1005 0 : texID, img, aIsMask, Move(aPacket)));
1006 :
1007 0 : sSentTextureIds.push_back(texID);
1008 0 : gLayerScopeManager.CurrentSession().mTexIDs.push_back(texID);
1009 :
1010 : }
1011 :
1012 : void
1013 0 : SenderHelper::SetAndSendTexture(GLContext* aGLContext,
1014 : void* aLayerRef,
1015 : TextureSourceOGL* aSource,
1016 : const TexturedEffect* aEffect)
1017 : {
1018 : // Expose packet creation here, so we could dump primary texture effect attributes.
1019 0 : auto packet = MakeUnique<layerscope::Packet>();
1020 0 : layerscope::TexturePacket* texturePacket = packet->mutable_texture();
1021 0 : texturePacket->set_mpremultiplied(aEffect->mPremultiplied);
1022 0 : DumpFilter(texturePacket, aEffect->mSamplingFilter);
1023 0 : DumpRect(texturePacket->mutable_mtexturecoords(), aEffect->mTextureCoords);
1024 0 : SendTextureSource(aGLContext, aLayerRef, aSource, false, false, Move(packet));
1025 0 : }
1026 :
1027 : void
1028 0 : SenderHelper::SendTexturedEffect(GLContext* aGLContext,
1029 : void* aLayerRef,
1030 : const TexturedEffect* aEffect)
1031 : {
1032 0 : TextureSourceOGL* source = aEffect->mTexture->AsSourceOGL();
1033 0 : if (!source) {
1034 0 : return;
1035 : }
1036 :
1037 : // Fallback texture sending path.
1038 0 : SetAndSendTexture(aGLContext, aLayerRef, source, aEffect);
1039 : }
1040 :
1041 : void
1042 0 : SenderHelper::SendMaskEffect(GLContext* aGLContext,
1043 : void* aLayerRef,
1044 : const EffectMask* aEffect)
1045 : {
1046 0 : TextureSourceOGL* source = aEffect->mMaskTexture->AsSourceOGL();
1047 0 : if (!source) {
1048 0 : return;
1049 : }
1050 :
1051 : // Expose packet creation here, so we could dump secondary mask effect attributes.
1052 0 : auto packet = MakeUnique<layerscope::Packet>();
1053 0 : TexturePacket::EffectMask* mask = packet->mutable_texture()->mutable_mask();
1054 0 : mask->mutable_msize()->set_w(aEffect->mSize.width);
1055 0 : mask->mutable_msize()->set_h(aEffect->mSize.height);
1056 0 : auto element = reinterpret_cast<const Float *>(&(aEffect->mMaskTransform));
1057 0 : for (int i = 0; i < 16; i++) {
1058 0 : mask->mutable_mmasktransform()->add_m(*element++);
1059 : }
1060 :
1061 0 : SendTextureSource(aGLContext, aLayerRef, source, false, true, Move(packet));
1062 : }
1063 :
1064 : void
1065 0 : SenderHelper::SendYCbCrEffect(GLContext* aGLContext,
1066 : void* aLayerRef,
1067 : const EffectYCbCr* aEffect)
1068 : {
1069 0 : TextureSource* sourceYCbCr = aEffect->mTexture;
1070 0 : if (!sourceYCbCr)
1071 0 : return;
1072 :
1073 0 : const int Y = 0, Cb = 1, Cr = 2;
1074 : TextureSourceOGL *sources[] = {
1075 0 : sourceYCbCr->GetSubSource(Y)->AsSourceOGL(),
1076 0 : sourceYCbCr->GetSubSource(Cb)->AsSourceOGL(),
1077 0 : sourceYCbCr->GetSubSource(Cr)->AsSourceOGL()
1078 0 : };
1079 :
1080 0 : for (auto source: sources) {
1081 0 : SetAndSendTexture(aGLContext, aLayerRef, source, aEffect);
1082 : }
1083 : }
1084 :
1085 : void
1086 0 : SenderHelper::SendEffectChain(GLContext* aGLContext,
1087 : const EffectChain& aEffectChain,
1088 : int aWidth,
1089 : int aHeight)
1090 : {
1091 0 : if (!sLayersBufferSendable) return;
1092 :
1093 0 : const Effect* primaryEffect = aEffectChain.mPrimaryEffect;
1094 0 : MOZ_ASSERT(primaryEffect);
1095 :
1096 0 : if (!primaryEffect) {
1097 0 : return;
1098 : }
1099 :
1100 0 : switch (primaryEffect->mType) {
1101 : case EffectTypes::RGB: {
1102 : const TexturedEffect* texturedEffect =
1103 0 : static_cast<const TexturedEffect*>(primaryEffect);
1104 0 : SendTexturedEffect(aGLContext, aEffectChain.mLayerRef, texturedEffect);
1105 0 : break;
1106 : }
1107 : case EffectTypes::YCBCR: {
1108 : const EffectYCbCr* yCbCrEffect =
1109 0 : static_cast<const EffectYCbCr*>(primaryEffect);
1110 0 : SendYCbCrEffect(aGLContext, aEffectChain.mLayerRef, yCbCrEffect);
1111 0 : break;
1112 : }
1113 : case EffectTypes::SOLID_COLOR: {
1114 : const EffectSolidColor* solidColorEffect =
1115 0 : static_cast<const EffectSolidColor*>(primaryEffect);
1116 0 : SendColor(aEffectChain.mLayerRef, solidColorEffect->mColor,
1117 0 : aWidth, aHeight);
1118 0 : break;
1119 : }
1120 : case EffectTypes::COMPONENT_ALPHA:
1121 : case EffectTypes::RENDER_TARGET:
1122 : default:
1123 0 : break;
1124 : }
1125 :
1126 0 : if (aEffectChain.mSecondaryEffects[EffectTypes::MASK]) {
1127 : const EffectMask* effectMask =
1128 0 : static_cast<const EffectMask*>(aEffectChain.mSecondaryEffects[EffectTypes::MASK].get());
1129 0 : SendMaskEffect(aGLContext, aEffectChain.mLayerRef, effectMask);
1130 : }
1131 : }
1132 :
1133 : void
1134 33 : LayerScope::ContentChanged(TextureHost *host)
1135 : {
1136 33 : if (!CheckSendable()) {
1137 33 : return;
1138 : }
1139 :
1140 0 : gLayerScopeManager.GetContentMonitor()->SetChangedHost(host);
1141 : }
1142 :
1143 : // ----------------------------------------------
1144 : // SocketHandler implementation
1145 : // ----------------------------------------------
1146 : void
1147 0 : LayerScopeWebSocketManager::SocketHandler::OpenStream(nsISocketTransport* aTransport)
1148 : {
1149 0 : MOZ_ASSERT(aTransport);
1150 :
1151 0 : mTransport = aTransport;
1152 0 : mTransport->OpenOutputStream(nsITransport::OPEN_BLOCKING,
1153 : 0,
1154 : 0,
1155 0 : getter_AddRefs(mOutputStream));
1156 :
1157 0 : nsCOMPtr<nsIInputStream> debugInputStream;
1158 0 : mTransport->OpenInputStream(0,
1159 : 0,
1160 : 0,
1161 0 : getter_AddRefs(debugInputStream));
1162 0 : mInputStream = do_QueryInterface(debugInputStream);
1163 0 : mInputStream->AsyncWait(this, 0, 0, GetCurrentThreadEventTarget());
1164 0 : }
1165 :
1166 : bool
1167 0 : LayerScopeWebSocketManager::SocketHandler::WriteToStream(void *aPtr,
1168 : uint32_t aSize)
1169 : {
1170 0 : if (mState == NoHandshake) {
1171 : // Not yet handshake, just return true in case of
1172 : // LayerScope remove this handle
1173 0 : return true;
1174 0 : } else if (mState == HandshakeFailed) {
1175 0 : return false;
1176 : }
1177 :
1178 0 : if (!mOutputStream) {
1179 0 : return false;
1180 : }
1181 :
1182 : // Generate WebSocket header
1183 : uint8_t wsHeader[10];
1184 0 : int wsHeaderSize = 0;
1185 0 : const uint8_t opcode = 0x2;
1186 0 : wsHeader[0] = 0x80 | (opcode & 0x0f); // FIN + opcode;
1187 0 : if (aSize <= 125) {
1188 0 : wsHeaderSize = 2;
1189 0 : wsHeader[1] = aSize;
1190 0 : } else if (aSize < 65536) {
1191 0 : wsHeaderSize = 4;
1192 0 : wsHeader[1] = 0x7E;
1193 0 : NetworkEndian::writeUint16(wsHeader + 2, aSize);
1194 : } else {
1195 0 : wsHeaderSize = 10;
1196 0 : wsHeader[1] = 0x7F;
1197 0 : NetworkEndian::writeUint64(wsHeader + 2, aSize);
1198 : }
1199 :
1200 : // Send WebSocket header
1201 : nsresult rv;
1202 : uint32_t cnt;
1203 0 : rv = mOutputStream->Write(reinterpret_cast<char*>(wsHeader),
1204 0 : wsHeaderSize, &cnt);
1205 0 : if (NS_FAILED(rv))
1206 0 : return false;
1207 :
1208 0 : uint32_t written = 0;
1209 0 : while (written < aSize) {
1210 : uint32_t cnt;
1211 0 : rv = mOutputStream->Write(reinterpret_cast<char*>(aPtr) + written,
1212 0 : aSize - written, &cnt);
1213 0 : if (NS_FAILED(rv))
1214 0 : return false;
1215 :
1216 0 : written += cnt;
1217 : }
1218 :
1219 0 : return true;
1220 : }
1221 :
1222 : NS_IMETHODIMP
1223 0 : LayerScopeWebSocketManager::SocketHandler::OnInputStreamReady(nsIAsyncInputStream *aStream)
1224 : {
1225 0 : MOZ_ASSERT(mInputStream);
1226 :
1227 0 : if (!mInputStream) {
1228 0 : return NS_OK;
1229 : }
1230 :
1231 0 : if (!mConnected) {
1232 0 : nsTArray<nsCString> protocolString;
1233 0 : ReadInputStreamData(protocolString);
1234 :
1235 0 : if (WebSocketHandshake(protocolString)) {
1236 0 : mState = HandshakeSuccess;
1237 0 : mConnected = true;
1238 0 : mInputStream->AsyncWait(this, 0, 0, GetCurrentThreadEventTarget());
1239 : } else {
1240 0 : mState = HandshakeFailed;
1241 : }
1242 0 : return NS_OK;
1243 : } else {
1244 0 : return HandleSocketMessage(aStream);
1245 : }
1246 : }
1247 :
1248 : void
1249 0 : LayerScopeWebSocketManager::SocketHandler::ReadInputStreamData(nsTArray<nsCString>& aProtocolString)
1250 : {
1251 0 : nsLineBuffer<char> lineBuffer;
1252 0 : nsCString line;
1253 0 : bool more = true;
1254 0 : do {
1255 0 : NS_ReadLine(mInputStream.get(), &lineBuffer, line, &more);
1256 :
1257 0 : if (line.Length() > 0) {
1258 0 : aProtocolString.AppendElement(line);
1259 : }
1260 0 : } while (more && line.Length() > 0);
1261 0 : }
1262 :
1263 : bool
1264 0 : LayerScopeWebSocketManager::SocketHandler::WebSocketHandshake(nsTArray<nsCString>& aProtocolString)
1265 : {
1266 : nsresult rv;
1267 0 : bool isWebSocket = false;
1268 0 : nsCString version;
1269 0 : nsCString wsKey;
1270 0 : nsCString protocol;
1271 :
1272 : // Validate WebSocket client request.
1273 0 : if (aProtocolString.Length() == 0)
1274 0 : return false;
1275 :
1276 : // Check that the HTTP method is GET
1277 0 : const char* HTTP_METHOD = "GET ";
1278 0 : if (strncmp(aProtocolString[0].get(), HTTP_METHOD, strlen(HTTP_METHOD)) != 0) {
1279 0 : return false;
1280 : }
1281 :
1282 0 : for (uint32_t i = 1; i < aProtocolString.Length(); ++i) {
1283 0 : const char* line = aProtocolString[i].get();
1284 0 : const char* prop_pos = strchr(line, ':');
1285 0 : if (prop_pos != nullptr) {
1286 0 : nsCString key(line, prop_pos - line);
1287 0 : nsCString value(prop_pos + 2);
1288 0 : if (key.EqualsIgnoreCase("upgrade") &&
1289 0 : value.EqualsIgnoreCase("websocket")) {
1290 0 : isWebSocket = true;
1291 0 : } else if (key.EqualsIgnoreCase("sec-websocket-version")) {
1292 0 : version = value;
1293 0 : } else if (key.EqualsIgnoreCase("sec-websocket-key")) {
1294 0 : wsKey = value;
1295 0 : } else if (key.EqualsIgnoreCase("sec-websocket-protocol")) {
1296 0 : protocol = value;
1297 : }
1298 : }
1299 : }
1300 :
1301 0 : if (!isWebSocket) {
1302 0 : return false;
1303 : }
1304 :
1305 0 : if (!(version.EqualsLiteral("7") ||
1306 0 : version.EqualsLiteral("8") ||
1307 0 : version.EqualsLiteral("13"))) {
1308 0 : return false;
1309 : }
1310 :
1311 0 : if (!(protocol.EqualsIgnoreCase("binary"))) {
1312 0 : return false;
1313 : }
1314 :
1315 0 : if (!mOutputStream) {
1316 0 : return false;
1317 : }
1318 :
1319 : // Client request is valid. Start to generate and send server response.
1320 0 : nsAutoCString guid("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
1321 0 : nsAutoCString res;
1322 0 : SHA1Sum sha1;
1323 0 : nsCString combined(wsKey + guid);
1324 0 : sha1.update(combined.get(), combined.Length());
1325 : uint8_t digest[SHA1Sum::kHashSize]; // SHA1 digests are 20 bytes long.
1326 0 : sha1.finish(digest);
1327 0 : nsCString newString(reinterpret_cast<char*>(digest), SHA1Sum::kHashSize);
1328 0 : rv = Base64Encode(newString, res);
1329 0 : if (NS_FAILED(rv)) {
1330 0 : return false;
1331 : }
1332 0 : nsCString response("HTTP/1.1 101 Switching Protocols\r\n");
1333 0 : response.AppendLiteral("Upgrade: websocket\r\n");
1334 0 : response.AppendLiteral("Connection: Upgrade\r\n");
1335 0 : response.Append(nsCString("Sec-WebSocket-Accept: ") + res + nsCString("\r\n"));
1336 0 : response.AppendLiteral("Sec-WebSocket-Protocol: binary\r\n\r\n");
1337 0 : uint32_t written = 0;
1338 0 : uint32_t size = response.Length();
1339 0 : while (written < size) {
1340 : uint32_t cnt;
1341 0 : rv = mOutputStream->Write(const_cast<char*>(response.get()) + written,
1342 0 : size - written, &cnt);
1343 0 : if (NS_FAILED(rv))
1344 0 : return false;
1345 :
1346 0 : written += cnt;
1347 : }
1348 0 : mOutputStream->Flush();
1349 :
1350 0 : return true;
1351 : }
1352 :
1353 : nsresult
1354 0 : LayerScopeWebSocketManager::SocketHandler::HandleSocketMessage(nsIAsyncInputStream *aStream)
1355 : {
1356 : // The reading and parsing of this input stream is customized for layer viewer.
1357 0 : const uint32_t cPacketSize = 1024;
1358 : char buffer[cPacketSize];
1359 0 : uint32_t count = 0;
1360 0 : nsresult rv = NS_OK;
1361 :
1362 0 : do {
1363 0 : rv = mInputStream->Read((char *)buffer, cPacketSize, &count);
1364 :
1365 : // TODO: combine packets if we have to read more than once
1366 :
1367 0 : if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
1368 0 : mInputStream->AsyncWait(this, 0, 0, GetCurrentThreadEventTarget());
1369 0 : return NS_OK;
1370 : }
1371 :
1372 0 : if (NS_FAILED(rv)) {
1373 0 : break;
1374 : }
1375 :
1376 0 : if (count == 0) {
1377 : // NS_BASE_STREAM_CLOSED
1378 0 : CloseConnection();
1379 0 : break;
1380 : }
1381 :
1382 0 : rv = ProcessInput(reinterpret_cast<uint8_t *>(buffer), count);
1383 0 : } while (NS_SUCCEEDED(rv) && mInputStream);
1384 0 : return rv;
1385 : }
1386 :
1387 : nsresult
1388 0 : LayerScopeWebSocketManager::SocketHandler::ProcessInput(uint8_t *aBuffer,
1389 : uint32_t aCount)
1390 : {
1391 0 : uint32_t avail = aCount;
1392 :
1393 : // Decode Websocket data frame
1394 0 : if (avail <= 2) {
1395 0 : NS_WARNING("Packet size is less than 2 bytes");
1396 0 : return NS_OK;
1397 : }
1398 :
1399 : // First byte, data type, only care the opcode
1400 : // rsvBits: aBuffer[0] & 0x70 (0111 0000)
1401 0 : uint8_t finBit = aBuffer[0] & 0x80; // 1000 0000
1402 0 : uint8_t opcode = aBuffer[0] & 0x0F; // 0000 1111
1403 :
1404 0 : if (!finBit) {
1405 0 : NS_WARNING("We cannot handle multi-fragments messages in Layerscope websocket parser.");
1406 0 : return NS_OK;
1407 : }
1408 :
1409 : // Second byte, data length
1410 0 : uint8_t maskBit = aBuffer[1] & 0x80; // 1000 0000
1411 0 : int64_t payloadLength64 = aBuffer[1] & 0x7F; // 0111 1111
1412 :
1413 0 : if (!maskBit) {
1414 0 : NS_WARNING("Client to Server should set the mask bit");
1415 0 : return NS_OK;
1416 : }
1417 :
1418 0 : uint32_t framingLength = 2 + 4; // 4 for masks
1419 :
1420 0 : if (payloadLength64 < 126) {
1421 0 : if (avail < framingLength)
1422 0 : return NS_OK;
1423 0 : } else if (payloadLength64 == 126) {
1424 : // 16 bit length field
1425 0 : framingLength += 2;
1426 0 : if (avail < framingLength) {
1427 0 : return NS_OK;
1428 : }
1429 :
1430 0 : payloadLength64 = aBuffer[2] << 8 | aBuffer[3];
1431 : } else {
1432 : // 64 bit length
1433 0 : framingLength += 8;
1434 0 : if (avail < framingLength) {
1435 0 : return NS_OK;
1436 : }
1437 :
1438 0 : if (aBuffer[2] & 0x80) {
1439 : // Section 4.2 says that the most significant bit MUST be
1440 : // 0. (i.e. this is really a 63 bit value)
1441 0 : NS_WARNING("High bit of 64 bit length set");
1442 0 : return NS_ERROR_ILLEGAL_VALUE;
1443 : }
1444 :
1445 : // copy this in case it is unaligned
1446 0 : payloadLength64 = NetworkEndian::readInt64(aBuffer + 2);
1447 : }
1448 :
1449 0 : uint8_t *payload = aBuffer + framingLength;
1450 0 : avail -= framingLength;
1451 :
1452 0 : uint32_t payloadLength = static_cast<uint32_t>(payloadLength64);
1453 0 : if (avail < payloadLength) {
1454 0 : NS_WARNING("Packet size mismatch the payload length");
1455 0 : return NS_OK;
1456 : }
1457 :
1458 : // Apply mask
1459 0 : uint32_t mask = NetworkEndian::readUint32(payload - 4);
1460 0 : ApplyMask(mask, payload, payloadLength);
1461 :
1462 0 : if (opcode == 0x8) {
1463 : // opcode == 0x8 means connection close
1464 0 : CloseConnection();
1465 0 : return NS_BASE_STREAM_CLOSED;
1466 : }
1467 :
1468 0 : if (!HandleDataFrame(payload, payloadLength)) {
1469 0 : NS_WARNING("Cannot decode payload data by the protocol buffer");
1470 : }
1471 :
1472 0 : return NS_OK;
1473 : }
1474 :
1475 : void
1476 0 : LayerScopeWebSocketManager::SocketHandler::ApplyMask(uint32_t aMask,
1477 : uint8_t *aData,
1478 : uint64_t aLen)
1479 : {
1480 0 : if (!aData || aLen == 0) {
1481 0 : return;
1482 : }
1483 :
1484 : // Optimally we want to apply the mask 32 bits at a time,
1485 : // but the buffer might not be alligned. So we first deal with
1486 : // 0 to 3 bytes of preamble individually
1487 0 : while (aLen && (reinterpret_cast<uintptr_t>(aData) & 3)) {
1488 0 : *aData ^= aMask >> 24;
1489 0 : aMask = RotateLeft(aMask, 8);
1490 0 : aData++;
1491 0 : aLen--;
1492 : }
1493 :
1494 : // perform mask on full words of data
1495 0 : uint32_t *iData = reinterpret_cast<uint32_t *>(aData);
1496 0 : uint32_t *end = iData + (aLen >> 2);
1497 0 : NetworkEndian::writeUint32(&aMask, aMask);
1498 0 : for (; iData < end; iData++) {
1499 0 : *iData ^= aMask;
1500 : }
1501 0 : aMask = NetworkEndian::readUint32(&aMask);
1502 0 : aData = (uint8_t *)iData;
1503 0 : aLen = aLen % 4;
1504 :
1505 : // There maybe up to 3 trailing bytes that need to be dealt with
1506 : // individually
1507 0 : while (aLen) {
1508 0 : *aData ^= aMask >> 24;
1509 0 : aMask = RotateLeft(aMask, 8);
1510 0 : aData++;
1511 0 : aLen--;
1512 : }
1513 : }
1514 :
1515 : bool
1516 0 : LayerScopeWebSocketManager::SocketHandler::HandleDataFrame(uint8_t *aData,
1517 : uint32_t aSize)
1518 : {
1519 : // Handle payload data by protocol buffer
1520 0 : auto p = MakeUnique<CommandPacket>();
1521 0 : p->ParseFromArray(static_cast<void*>(aData), aSize);
1522 :
1523 0 : if (!p->has_type()) {
1524 0 : MOZ_ASSERT(false, "Protocol buffer decoding failed or cannot recongize it");
1525 : return false;
1526 : }
1527 :
1528 0 : switch (p->type()) {
1529 : case CommandPacket::LAYERS_TREE:
1530 0 : if (p->has_value()) {
1531 0 : SenderHelper::SetLayersTreeSendable(p->value());
1532 : }
1533 0 : break;
1534 :
1535 : case CommandPacket::LAYERS_BUFFER:
1536 0 : if (p->has_value()) {
1537 0 : SenderHelper::SetLayersBufferSendable(p->value());
1538 : }
1539 0 : break;
1540 :
1541 : case CommandPacket::NO_OP:
1542 : default:
1543 0 : NS_WARNING("Invalid message type");
1544 0 : break;
1545 : }
1546 0 : return true;
1547 : }
1548 :
1549 : void
1550 0 : LayerScopeWebSocketManager::SocketHandler::CloseConnection()
1551 : {
1552 0 : gLayerScopeManager.GetSocketManager()->CleanDebugData();
1553 0 : if (mInputStream) {
1554 0 : mInputStream->AsyncWait(nullptr, 0, 0, nullptr);
1555 0 : mInputStream = nullptr;
1556 : }
1557 0 : if (mOutputStream) {
1558 0 : mOutputStream = nullptr;
1559 : }
1560 0 : if (mTransport) {
1561 0 : mTransport->Close(NS_BASE_STREAM_CLOSED);
1562 0 : mTransport = nullptr;
1563 : }
1564 0 : mConnected = false;
1565 0 : }
1566 :
1567 : // ----------------------------------------------
1568 : // LayerScopeWebSocketManager implementation
1569 : // ----------------------------------------------
1570 0 : LayerScopeWebSocketManager::LayerScopeWebSocketManager()
1571 0 : : mHandlerMutex("LayerScopeWebSocketManager::mHandlerMutex")
1572 : {
1573 0 : NS_NewNamedThread("LayerScope", getter_AddRefs(mDebugSenderThread));
1574 :
1575 0 : mServerSocket = do_CreateInstance(NS_SERVERSOCKET_CONTRACTID);
1576 0 : int port = gfxPrefs::LayerScopePort();
1577 0 : mServerSocket->Init(port, false, -1);
1578 0 : mServerSocket->AsyncListen(new SocketListener);
1579 0 : }
1580 :
1581 0 : LayerScopeWebSocketManager::~LayerScopeWebSocketManager()
1582 : {
1583 0 : mServerSocket->Close();
1584 0 : }
1585 :
1586 : void
1587 0 : LayerScopeWebSocketManager::AppendDebugData(DebugGLData *aDebugData)
1588 : {
1589 0 : if (!mCurrentSender) {
1590 0 : mCurrentSender = new DebugDataSender(mDebugSenderThread);
1591 : }
1592 :
1593 0 : mCurrentSender->Append(aDebugData);
1594 0 : }
1595 :
1596 : void
1597 0 : LayerScopeWebSocketManager::CleanDebugData()
1598 : {
1599 0 : if (mCurrentSender) {
1600 0 : mCurrentSender->Cleanup();
1601 : }
1602 0 : }
1603 :
1604 : void
1605 0 : LayerScopeWebSocketManager::DispatchDebugData()
1606 : {
1607 0 : MOZ_ASSERT(mCurrentSender.get() != nullptr);
1608 :
1609 0 : mCurrentSender->Send();
1610 0 : mCurrentSender = nullptr;
1611 0 : }
1612 :
1613 0 : NS_IMETHODIMP LayerScopeWebSocketManager::SocketListener::OnSocketAccepted(
1614 : nsIServerSocket *aServ,
1615 : nsISocketTransport *aTransport)
1616 : {
1617 0 : if (!gLayerScopeManager.GetSocketManager())
1618 0 : return NS_OK;
1619 :
1620 0 : printf_stderr("*** LayerScope: Accepted connection\n");
1621 0 : gLayerScopeManager.GetSocketManager()->AddConnection(aTransport);
1622 0 : gLayerScopeManager.GetContentMonitor()->Empty();
1623 0 : return NS_OK;
1624 : }
1625 :
1626 : // ----------------------------------------------
1627 : // LayerScope implementation
1628 : // ----------------------------------------------
1629 : /*static*/
1630 : void
1631 0 : LayerScope::Init()
1632 : {
1633 0 : if (!gfxPrefs::LayerScopeEnabled() || XRE_IsGPUProcess()) {
1634 0 : return;
1635 : }
1636 :
1637 0 : gLayerScopeManager.CreateServerSocket();
1638 : }
1639 :
1640 : /*static*/
1641 : void
1642 0 : LayerScope::DrawBegin()
1643 : {
1644 0 : if (!CheckSendable()) {
1645 0 : return;
1646 : }
1647 :
1648 0 : gLayerScopeManager.NewDrawSession();
1649 : }
1650 :
1651 : /*static*/
1652 : void
1653 0 : LayerScope::SetRenderOffset(float aX, float aY)
1654 : {
1655 0 : if (!CheckSendable()) {
1656 0 : return;
1657 : }
1658 :
1659 0 : gLayerScopeManager.CurrentSession().mOffsetX = aX;
1660 0 : gLayerScopeManager.CurrentSession().mOffsetY = aY;
1661 : }
1662 :
1663 : /*static*/
1664 : void
1665 0 : LayerScope::SetLayerTransform(const gfx::Matrix4x4& aMatrix)
1666 : {
1667 0 : if (!CheckSendable()) {
1668 0 : return;
1669 : }
1670 :
1671 0 : gLayerScopeManager.CurrentSession().mMVMatrix = aMatrix;
1672 : }
1673 :
1674 : /*static*/
1675 : void
1676 0 : LayerScope::SetDrawRects(size_t aRects,
1677 : const gfx::Rect* aLayerRects,
1678 : const gfx::Rect* aTextureRects)
1679 : {
1680 0 : if (!CheckSendable()) {
1681 0 : return;
1682 : }
1683 :
1684 0 : MOZ_ASSERT(aRects > 0 && aRects <= 4);
1685 0 : MOZ_ASSERT(aLayerRects);
1686 :
1687 0 : gLayerScopeManager.CurrentSession().mRects = aRects;
1688 :
1689 0 : for (size_t i = 0; i < aRects; i++){
1690 0 : gLayerScopeManager.CurrentSession().mLayerRects[i] = aLayerRects[i];
1691 0 : gLayerScopeManager.CurrentSession().mTextureRects[i] = aTextureRects[i];
1692 : }
1693 : }
1694 :
1695 : /*static*/
1696 : void
1697 0 : LayerScope::DrawEnd(gl::GLContext* aGLContext,
1698 : const EffectChain& aEffectChain,
1699 : int aWidth,
1700 : int aHeight)
1701 : {
1702 : // Protect this public function
1703 0 : if (!CheckSendable()) {
1704 0 : return;
1705 : }
1706 :
1707 : // 1. Send textures.
1708 0 : SenderHelper::SendEffectChain(aGLContext, aEffectChain, aWidth, aHeight);
1709 :
1710 : // 2. Send parameters of draw call, such as uniforms and attributes of
1711 : // vertex adnd fragment shader.
1712 0 : DrawSession& draws = gLayerScopeManager.CurrentSession();
1713 0 : gLayerScopeManager.GetSocketManager()->AppendDebugData(
1714 : new DebugGLDrawData(draws.mOffsetX, draws.mOffsetY,
1715 : draws.mMVMatrix, draws.mRects,
1716 : draws.mLayerRects,
1717 : draws.mTextureRects,
1718 : draws.mTexIDs,
1719 0 : aEffectChain.mLayerRef));
1720 :
1721 : }
1722 :
1723 : /*static*/
1724 : void
1725 0 : LayerScope::SendLayer(LayerComposite* aLayer,
1726 : int aWidth,
1727 : int aHeight)
1728 : {
1729 : // Protect this public function
1730 0 : if (!CheckSendable()) {
1731 0 : return;
1732 : }
1733 0 : SenderHelper::SendLayer(aLayer, aWidth, aHeight);
1734 : }
1735 :
1736 : /*static*/
1737 : void
1738 0 : LayerScope::SendLayerDump(UniquePtr<Packet> aPacket)
1739 : {
1740 : // Protect this public function
1741 0 : if (!CheckSendable() || !SenderHelper::GetLayersTreeSendable()) {
1742 0 : return;
1743 : }
1744 0 : gLayerScopeManager.GetSocketManager()->AppendDebugData(
1745 0 : new DebugGLLayersData(Move(aPacket)));
1746 : }
1747 :
1748 : /*static*/
1749 : bool
1750 114 : LayerScope::CheckSendable()
1751 : {
1752 : // Only compositor threads check LayerScope status
1753 114 : MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread() || gIsGtest);
1754 :
1755 114 : if (!gfxPrefs::LayerScopeEnabled()) {
1756 114 : return false;
1757 : }
1758 0 : if (!gLayerScopeManager.GetSocketManager()) {
1759 0 : Init();
1760 0 : return false;
1761 : }
1762 0 : if (!gLayerScopeManager.GetSocketManager()->IsConnected()) {
1763 0 : return false;
1764 : }
1765 0 : return true;
1766 : }
1767 :
1768 : /*static*/
1769 : void
1770 0 : LayerScope::CleanLayer()
1771 : {
1772 0 : if (CheckSendable()) {
1773 0 : gLayerScopeManager.GetSocketManager()->CleanDebugData();
1774 : }
1775 0 : }
1776 :
1777 : /*static*/
1778 : void
1779 0 : LayerScope::SetHWComposed()
1780 : {
1781 0 : if (CheckSendable()) {
1782 0 : gLayerScopeManager.GetSocketManager()->AppendDebugData(
1783 0 : new DebugGLMetaData(Packet::META, true));
1784 : }
1785 0 : }
1786 :
1787 : /*static*/
1788 : void
1789 1 : LayerScope::SetPixelScale(double devPixelsPerCSSPixel)
1790 : {
1791 1 : gLayerScopeManager.SetPixelScale(devPixelsPerCSSPixel);
1792 1 : }
1793 :
1794 : // ----------------------------------------------
1795 : // LayerScopeAutoFrame implementation
1796 : // ----------------------------------------------
1797 27 : LayerScopeAutoFrame::LayerScopeAutoFrame(int64_t aFrameStamp)
1798 : {
1799 : // Do Begin Frame
1800 27 : BeginFrame(aFrameStamp);
1801 27 : }
1802 :
1803 27 : LayerScopeAutoFrame::~LayerScopeAutoFrame()
1804 : {
1805 : // Do End Frame
1806 27 : EndFrame();
1807 27 : }
1808 :
1809 : void
1810 27 : LayerScopeAutoFrame::BeginFrame(int64_t aFrameStamp)
1811 : {
1812 27 : if (!LayerScope::CheckSendable()) {
1813 27 : return;
1814 : }
1815 0 : SenderHelper::ClearSentTextureIds();
1816 :
1817 0 : gLayerScopeManager.GetSocketManager()->AppendDebugData(
1818 0 : new DebugGLFrameStatusData(Packet::FRAMESTART, aFrameStamp));
1819 : }
1820 :
1821 : void
1822 27 : LayerScopeAutoFrame::EndFrame()
1823 : {
1824 27 : if (!LayerScope::CheckSendable()) {
1825 27 : return;
1826 : }
1827 :
1828 0 : gLayerScopeManager.GetSocketManager()->AppendDebugData(
1829 0 : new DebugGLFrameStatusData(Packet::FRAMEEND));
1830 0 : gLayerScopeManager.GetSocketManager()->DispatchDebugData();
1831 : }
1832 :
1833 : } // namespace layers
1834 : } // namespace mozilla
|