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