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