LCOV - code coverage report
Current view: top level - dom/console - Console.h (source / functions) Hit Total Coverage
Test: output.info Lines: 1 1 100.0 %
Date: 2017-07-14 16:53:18 Functions: 2 7 28.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       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             : #ifndef mozilla_dom_Console_h
       8             : #define mozilla_dom_Console_h
       9             : 
      10             : #include "mozilla/dom/BindingDeclarations.h"
      11             : #include "mozilla/ErrorResult.h"
      12             : #include "mozilla/JSObjectHolder.h"
      13             : #include "nsCycleCollectionParticipant.h"
      14             : #include "nsDataHashtable.h"
      15             : #include "nsHashKeys.h"
      16             : #include "nsIObserver.h"
      17             : #include "nsWeakReference.h"
      18             : #include "nsDOMNavigationTiming.h"
      19             : #include "nsPIDOMWindow.h"
      20             : 
      21             : class nsIConsoleAPIStorage;
      22             : class nsIPrincipal;
      23             : 
      24             : namespace mozilla {
      25             : namespace dom {
      26             : 
      27             : class AnyCallback;
      28             : class ConsoleCallData;
      29             : class ConsoleRunnable;
      30             : class ConsoleCallDataRunnable;
      31             : class ConsoleProfileRunnable;
      32             : struct ConsoleTimerError;
      33             : struct ConsoleStackEntry;
      34             : 
      35             : class Console final : public nsIObserver
      36             :                     , public nsSupportsWeakReference
      37             : {
      38             : public:
      39             :   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
      40          13 :   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Console, nsIObserver)
      41             :   NS_DECL_NSIOBSERVER
      42             : 
      43             :   static already_AddRefed<Console>
      44             :   Create(nsPIDOMWindowInner* aWindow, ErrorResult& aRv);
      45             : 
      46             :   // WebIDL methods
      47             :   nsPIDOMWindowInner* GetParentObject() const
      48             :   {
      49             :     return mWindow;
      50             :   }
      51             : 
      52             :   static void
      53             :   Log(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
      54             : 
      55             :   static void
      56             :   Info(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
      57             : 
      58             :   static void
      59             :   Warn(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
      60             : 
      61             :   static void
      62             :   Error(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
      63             : 
      64             :   static void
      65             :   Exception(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
      66             : 
      67             :   static void
      68             :   Debug(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
      69             : 
      70             :   static void
      71             :   Table(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
      72             : 
      73             :   static void
      74             :   Trace(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
      75             : 
      76             :   static void
      77             :   Dir(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
      78             : 
      79             :   static void
      80             :   Dirxml(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
      81             : 
      82             :   static void
      83             :   Group(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
      84             : 
      85             :   static void
      86             :   GroupCollapsed(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
      87             : 
      88             :   static void
      89             :   GroupEnd(const GlobalObject& aGlobal);
      90             : 
      91             :   static void
      92             :   Time(const GlobalObject& aGlobal, const nsAString& aLabel);
      93             : 
      94             :   static void
      95             :   TimeEnd(const GlobalObject& aGlobal, const nsAString& aLabel);
      96             : 
      97             :   static void
      98             :   TimeStamp(const GlobalObject& aGlobal, const JS::Handle<JS::Value> aData);
      99             : 
     100             :   static void
     101             :   Profile(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
     102             : 
     103             :   static void
     104             :   ProfileEnd(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
     105             : 
     106             :   static void
     107             :   Assert(const GlobalObject& aGlobal, bool aCondition,
     108             :          const Sequence<JS::Value>& aData);
     109             : 
     110             :   static void
     111             :   Count(const GlobalObject& aGlobal, const nsAString& aLabel);
     112             : 
     113             :   static void
     114             :   Clear(const GlobalObject& aGlobal);
     115             : 
     116             :   void
     117             :   ClearStorage();
     118             : 
     119             :   void
     120             :   RetrieveConsoleEvents(JSContext* aCx, nsTArray<JS::Value>& aEvents,
     121             :                         ErrorResult& aRv);
     122             : 
     123             :   void
     124             :   SetConsoleEventHandler(AnyCallback* aHandler);
     125             : 
     126             : private:
     127             :   explicit Console(nsPIDOMWindowInner* aWindow);
     128             :   ~Console();
     129             : 
     130             :   void
     131             :   Initialize(ErrorResult& aRv);
     132             : 
     133             :   void
     134             :   Shutdown();
     135             : 
     136             :   enum MethodName
     137             :   {
     138             :     MethodLog,
     139             :     MethodInfo,
     140             :     MethodWarn,
     141             :     MethodError,
     142             :     MethodException,
     143             :     MethodDebug,
     144             :     MethodTable,
     145             :     MethodTrace,
     146             :     MethodDir,
     147             :     MethodDirxml,
     148             :     MethodGroup,
     149             :     MethodGroupCollapsed,
     150             :     MethodGroupEnd,
     151             :     MethodTime,
     152             :     MethodTimeEnd,
     153             :     MethodTimeStamp,
     154             :     MethodAssert,
     155             :     MethodCount,
     156             :     MethodClear
     157             :   };
     158             : 
     159             :   static already_AddRefed<Console>
     160             :   GetConsole(const GlobalObject& aGlobal);
     161             : 
     162             :   static Console*
     163             :   GetConsoleInternal(const GlobalObject& aGlobal, ErrorResult &aRv);
     164             : 
     165             :   static void
     166             :   ProfileMethod(const GlobalObject& aGlobal, const nsAString& aAction,
     167             :                 const Sequence<JS::Value>& aData);
     168             : 
     169             :   void
     170             :   ProfileMethodInternal(JSContext* aCx, const nsAString& aAction,
     171             :                         const Sequence<JS::Value>& aData);
     172             : 
     173             :   static void
     174             :   Method(const GlobalObject& aGlobal, MethodName aName,
     175             :          const nsAString& aString, const Sequence<JS::Value>& aData);
     176             : 
     177             :   void
     178             :   MethodInternal(JSContext* aCx, MethodName aName,
     179             :                  const nsAString& aString, const Sequence<JS::Value>& aData);
     180             : 
     181             :   static void
     182             :   StringMethod(const GlobalObject& aGlobal, const nsAString& aLabel,
     183             :                MethodName aMethodName, const nsAString& aMethodString);
     184             : 
     185             :   // This method must receive aCx and aArguments in the same JSCompartment.
     186             :   void
     187             :   ProcessCallData(JSContext* aCx,
     188             :                   ConsoleCallData* aData,
     189             :                   const Sequence<JS::Value>& aArguments);
     190             : 
     191             :   void
     192             :   StoreCallData(ConsoleCallData* aData);
     193             : 
     194             :   void
     195             :   UnstoreCallData(ConsoleCallData* aData);
     196             : 
     197             :   // Read in Console.cpp how this method is used.
     198             :   void
     199             :   ReleaseCallData(ConsoleCallData* aCallData);
     200             : 
     201             :   // aCx and aArguments must be in the same JS compartment.
     202             :   void
     203             :   NotifyHandler(JSContext* aCx,
     204             :                 const Sequence<JS::Value>& aArguments,
     205             :                 ConsoleCallData* aData);
     206             : 
     207             :   // PopulateConsoleNotificationInTheTargetScope receives aCx and aArguments in
     208             :   // the same JS compartment and populates the ConsoleEvent object (aValue) in
     209             :   // the aTargetScope.
     210             :   // aTargetScope can be:
     211             :   // - the system-principal scope when we want to dispatch the ConsoleEvent to
     212             :   //   nsIConsoleAPIStorage (See the comment in Console.cpp about the use of
     213             :   //   xpc::PrivilegedJunkScope()
     214             :   // - the mConsoleEventNotifier->Callable() scope when we want to notify this
     215             :   //   handler about a new ConsoleEvent.
     216             :   // - It can be the global from the JSContext when RetrieveConsoleEvents is
     217             :   //   called.
     218             :   bool
     219             :   PopulateConsoleNotificationInTheTargetScope(JSContext* aCx,
     220             :                                               const Sequence<JS::Value>& aArguments,
     221             :                                               JSObject* aTargetScope,
     222             :                                               JS::MutableHandle<JS::Value> aValue,
     223             :                                               ConsoleCallData* aData);
     224             : 
     225             :   // If the first JS::Value of the array is a string, this method uses it to
     226             :   // format a string. The supported sequences are:
     227             :   //   %s    - string
     228             :   //   %d,%i - integer
     229             :   //   %f    - double
     230             :   //   %o,%O - a JS object.
     231             :   //   %c    - style string.
     232             :   // The output is an array where any object is a separated item, the rest is
     233             :   // unified in a format string.
     234             :   // Example if the input is:
     235             :   //   "string: %s, integer: %d, object: %o, double: %d", 's', 1, window, 0.9
     236             :   // The output will be:
     237             :   //   [ "string: s, integer: 1, object: ", window, ", double: 0.9" ]
     238             :   //
     239             :   // The aStyles array is populated with the style strings that the function
     240             :   // finds based the format string. The index of the styles matches the indexes
     241             :   // of elements that need the custom styling from aSequence. For elements with
     242             :   // no custom styling the array is padded with null elements.
     243             :   bool
     244             :   ProcessArguments(JSContext* aCx, const Sequence<JS::Value>& aData,
     245             :                    Sequence<JS::Value>& aSequence,
     246             :                    Sequence<nsString>& aStyles) const;
     247             : 
     248             :   void
     249             :   MakeFormatString(nsCString& aFormat, int32_t aInteger, int32_t aMantissa,
     250             :                    char aCh) const;
     251             : 
     252             :   // Stringify and Concat all the JS::Value in a single string using ' ' as
     253             :   // separator. The new group name will be stored in mGroupStack array.
     254             :   void
     255             :   ComposeAndStoreGroupName(JSContext* aCx, const Sequence<JS::Value>& aData,
     256             :                            nsAString& aName);
     257             : 
     258             :   // Remove the last group name and return that name. It returns false if
     259             :   // mGroupStack is empty.
     260             :   bool
     261             :   UnstoreGroupName(nsAString& aName);
     262             : 
     263             :   enum TimerStatus {
     264             :     eTimerUnknown,
     265             :     eTimerDone,
     266             :     eTimerAlreadyExists,
     267             :     eTimerDoesntExist,
     268             :     eTimerJSException,
     269             :     eTimerMaxReached,
     270             :   };
     271             : 
     272             :   JS::Value
     273             :   CreateTimerError(JSContext* aCx, const nsAString& aTimerLabel,
     274             :                    TimerStatus aStatus) const;
     275             : 
     276             :   // StartTimer is called on the owning thread and populates aTimerLabel and
     277             :   // aTimerValue.
     278             :   // * aCx - the JSContext rooting aName.
     279             :   // * aName - this is (should be) the name of the timer as JS::Value.
     280             :   // * aTimestamp - the monotonicTimer for this context taken from
     281             :   //                performance.now().
     282             :   // * aTimerLabel - This label will be populated with the aName converted to a
     283             :   //                 string.
     284             :   // * aTimerValue - the StartTimer value stored into (or taken from)
     285             :   //                 mTimerRegistry.
     286             :   TimerStatus
     287             :   StartTimer(JSContext* aCx, const JS::Value& aName,
     288             :              DOMHighResTimeStamp aTimestamp,
     289             :              nsAString& aTimerLabel,
     290             :              DOMHighResTimeStamp* aTimerValue);
     291             : 
     292             :   // CreateStartTimerValue generates a ConsoleTimerStart dictionary exposed as
     293             :   // JS::Value. If aTimerStatus is false, it generates a ConsoleTimerError
     294             :   // instead. It's called only after the execution StartTimer on the owning
     295             :   // thread.
     296             :   // * aCx - this is the context that will root the returned value.
     297             :   // * aTimerLabel - this label must be what StartTimer received as aTimerLabel.
     298             :   // * aTimerStatus - the return value of StartTimer.
     299             :   JS::Value
     300             :   CreateStartTimerValue(JSContext* aCx, const nsAString& aTimerLabel,
     301             :                         TimerStatus aTimerStatus) const;
     302             : 
     303             :   // StopTimer follows the same pattern as StartTimer: it runs on the
     304             :   // owning thread and populates aTimerLabel and aTimerDuration, used by
     305             :   // CreateStopTimerValue.
     306             :   // * aCx - the JSContext rooting aName.
     307             :   // * aName - this is (should be) the name of the timer as JS::Value.
     308             :   // * aTimestamp - the monotonicTimer for this context taken from
     309             :   //                performance.now().
     310             :   // * aTimerLabel - This label will be populated with the aName converted to a
     311             :   //                 string.
     312             :   // * aTimerDuration - the difference between aTimestamp and when the timer
     313             :   //                    started (see StartTimer).
     314             :   TimerStatus
     315             :   StopTimer(JSContext* aCx, const JS::Value& aName,
     316             :             DOMHighResTimeStamp aTimestamp,
     317             :             nsAString& aTimerLabel,
     318             :             double* aTimerDuration);
     319             : 
     320             :   // This method generates a ConsoleTimerEnd dictionary exposed as JS::Value, or
     321             :   // a ConsoleTimerError dictionary if aTimerStatus is false. See StopTimer.
     322             :   // * aCx - this is the context that will root the returned value.
     323             :   // * aTimerLabel - this label must be what StopTimer received as aTimerLabel.
     324             :   // * aTimerDuration - this is what StopTimer received as aTimerDuration
     325             :   // * aTimerStatus - the return value of StopTimer.
     326             :   JS::Value
     327             :   CreateStopTimerValue(JSContext* aCx, const nsAString& aTimerLabel,
     328             :                        double aTimerDuration,
     329             :                        TimerStatus aTimerStatus) const;
     330             : 
     331             :   // The method populates a Sequence from an array of JS::Value.
     332             :   bool
     333             :   ArgumentsToValueList(const Sequence<JS::Value>& aData,
     334             :                        Sequence<JS::Value>& aSequence) const;
     335             : 
     336             :   // This method follows the same pattern as StartTimer: its runs on the owning
     337             :   // thread and populate aCountLabel, used by CreateCounterValue. Returns
     338             :   // 3 possible values:
     339             :   // * MAX_PAGE_COUNTERS in case of error that has to be reported;
     340             :   // * 0 in case of a CX exception. The operation cannot continue;
     341             :   // * the incremented counter value.
     342             :   // Params:
     343             :   // * aCx - the JSContext rooting aData.
     344             :   // * aData - the arguments received by the console.count() method.
     345             :   // * aCountLabel - the label that will be populated by this method.
     346             :   uint32_t
     347             :   IncreaseCounter(JSContext* aCx, const Sequence<JS::Value>& aData,
     348             :                   nsAString& aCountLabel);
     349             : 
     350             :   // This method generates a ConsoleCounter dictionary as JS::Value. If
     351             :   // aCountValue is == MAX_PAGE_COUNTERS it generates a ConsoleCounterError
     352             :   // instead. See IncreaseCounter.
     353             :   // * aCx - this is the context that will root the returned value.
     354             :   // * aCountLabel - this label must be what IncreaseCounter received as
     355             :   //                 aTimerLabel.
     356             :   // * aCountValue - the return value of IncreaseCounter.
     357             :   JS::Value
     358             :   CreateCounterValue(JSContext* aCx, const nsAString& aCountLabel,
     359             :                      uint32_t aCountValue) const;
     360             : 
     361             :   bool
     362             :   ShouldIncludeStackTrace(MethodName aMethodName) const;
     363             : 
     364             :   JSObject*
     365             :   GetOrCreateSandbox(JSContext* aCx, nsIPrincipal* aPrincipal);
     366             : 
     367             :   void
     368             :   AssertIsOnOwningThread() const;
     369             : 
     370             :   bool
     371             :   IsShuttingDown() const;
     372             : 
     373             :   // All these nsCOMPtr are touched on main thread only.
     374             :   nsCOMPtr<nsPIDOMWindowInner> mWindow;
     375             :   nsCOMPtr<nsIConsoleAPIStorage> mStorage;
     376             :   RefPtr<JSObjectHolder> mSandbox;
     377             : 
     378             :   // Touched on the owner thread.
     379             :   nsDataHashtable<nsStringHashKey, DOMHighResTimeStamp> mTimerRegistry;
     380             :   nsDataHashtable<nsStringHashKey, uint32_t> mCounterRegistry;
     381             : 
     382             :   nsTArray<RefPtr<ConsoleCallData>> mCallDataStorage;
     383             : 
     384             :   // This array is used in a particular corner-case where:
     385             :   // 1. we are in a worker thread
     386             :   // 2. we have more than STORAGE_MAX_EVENTS
     387             :   // 3. but the main-thread ConsoleCallDataRunnable of the first one is still
     388             :   // running (this means that something very bad is happening on the
     389             :   // main-thread).
     390             :   // When this happens we want to keep the ConsoleCallData alive for traceing
     391             :   // its JSValues also if 'officially' this ConsoleCallData must be removed from
     392             :   // the storage.
     393             :   nsTArray<RefPtr<ConsoleCallData>> mCallDataStoragePending;
     394             : 
     395             :   RefPtr<AnyCallback> mConsoleEventNotifier;
     396             : 
     397             :   // This is the stack for groupping.
     398             :   nsTArray<nsString> mGroupStack;
     399             : 
     400             :   uint64_t mOuterID;
     401             :   uint64_t mInnerID;
     402             : 
     403             :   enum {
     404             :     eUnknown,
     405             :     eInitialized,
     406             :     eShuttingDown
     407             :   } mStatus;
     408             : 
     409             :   friend class ConsoleCallData;
     410             :   friend class ConsoleRunnable;
     411             :   friend class ConsoleCallDataRunnable;
     412             :   friend class ConsoleProfileRunnable;
     413             : };
     414             : 
     415             : } // namespace dom
     416             : } // namespace mozilla
     417             : 
     418             : #endif /* mozilla_dom_Console_h */

Generated by: LCOV version 1.13