Home | History | Annotate | Download | only in inspector
      1 /*
      2 * Copyright (C) 2013 Google Inc. All rights reserved.
      3 *
      4 * Redistribution and use in source and binary forms, with or without
      5 * modification, are permitted provided that the following conditions are
      6 * met:
      7 *
      8 *     * Redistributions of source code must retain the above copyright
      9 * notice, this list of conditions and the following disclaimer.
     10 *     * Redistributions in binary form must reproduce the above
     11 * copyright notice, this list of conditions and the following disclaimer
     12 * in the documentation and/or other materials provided with the
     13 * distribution.
     14 *     * Neither the name of Google Inc. nor the names of its
     15 * contributors may be used to endorse or promote products derived from
     16 * this software without specific prior written permission.
     17 *
     18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 */
     30 
     31 #include "config.h"
     32 #include "core/inspector/TraceEventDispatcher.h"
     33 
     34 #include "core/inspector/InspectorClient.h"
     35 #include "wtf/CurrentTime.h"
     36 #include "wtf/Functional.h"
     37 #include "wtf/MainThread.h"
     38 #include "wtf/text/StringHash.h"
     39 
     40 namespace WebCore {
     41 
     42 void TraceEventDispatcher::dispatchEventOnAnyThread(char phase, const unsigned char*, const char* name, unsigned long long id,
     43     int numArgs, const char* const* argNames, const unsigned char* argTypes, const unsigned long long* argValues,
     44     unsigned char flags, double timestamp)
     45 {
     46     if (phase == TRACE_EVENT_PHASE_INSTANT_WITH_SCOPE)
     47         phase = TRACE_EVENT_PHASE_INSTANT;
     48     TraceEventDispatcher* self = instance();
     49     {
     50         MutexLocker locker(self->m_mutex);
     51         if (self->m_handlers.find(std::make_pair(name, phase)) == self->m_handlers.end())
     52             return;
     53     }
     54     self->enqueueEvent(TraceEvent(timestamp, phase, name, id, currentThread(), numArgs, argNames, argTypes, argValues));
     55     if (isMainThread())
     56         self->processBackgroundEvents();
     57 }
     58 
     59 void TraceEventDispatcher::enqueueEvent(const TraceEvent& event)
     60 {
     61     const float eventProcessingThresholdInSeconds = 0.1;
     62     {
     63         MutexLocker locker(m_mutex);
     64         m_backgroundEvents.append(event);
     65         if (m_processEventsTaskInFlight || event.timestamp() - m_lastEventProcessingTime <= eventProcessingThresholdInSeconds)
     66             return;
     67     }
     68     m_processEventsTaskInFlight = true;
     69     callOnMainThread(bind(&TraceEventDispatcher::processBackgroundEventsTask, this));
     70 }
     71 
     72 void TraceEventDispatcher::processBackgroundEventsTask()
     73 {
     74     m_processEventsTaskInFlight = false;
     75     processBackgroundEvents();
     76 }
     77 
     78 void TraceEventDispatcher::processBackgroundEvents()
     79 {
     80     ASSERT(isMainThread());
     81     Vector<TraceEvent> events;
     82     {
     83         MutexLocker locker(m_mutex);
     84         m_lastEventProcessingTime = WTF::monotonicallyIncreasingTime();
     85         if (m_backgroundEvents.isEmpty())
     86             return;
     87         events.reserveCapacity(m_backgroundEvents.capacity());
     88         m_backgroundEvents.swap(events);
     89     }
     90     for (size_t eventIndex = 0, size = events.size(); eventIndex < size; ++eventIndex) {
     91         const TraceEvent& event = events[eventIndex];
     92         HandlersMap::iterator it = m_handlers.find(std::make_pair(event.name(), event.phase()));
     93         if (it == m_handlers.end())
     94             continue;
     95         Vector<BoundTraceEventHandler>& handlers = it->value;
     96         for (size_t handlerIndex = 0; handlerIndex < handlers.size(); ++handlerIndex)
     97             (handlers[handlerIndex].instance->*(handlers[handlerIndex].method))(event);
     98     }
     99 }
    100 
    101 void TraceEventDispatcher::innerAddListener(const char* name, char phase, TraceEventTargetBase* instance, TraceEventHandlerMethod method, InspectorClient* client)
    102 {
    103     ASSERT(isMainThread());
    104     MutexLocker locker(m_mutex);
    105     if (m_handlers.isEmpty())
    106         client->setTraceEventCallback(dispatchEventOnAnyThread);
    107     HandlersMap::iterator it = m_handlers.find(std::make_pair(name, phase));
    108     if (it == m_handlers.end())
    109         it = m_handlers.add(std::make_pair(name, phase), Vector<BoundTraceEventHandler>()).iterator;
    110     it->value.append(BoundTraceEventHandler(instance, method));
    111 }
    112 
    113 void TraceEventDispatcher::removeAllListeners(TraceEventTargetBase* instance, InspectorClient* client)
    114 {
    115     ASSERT(isMainThread());
    116     processBackgroundEvents();
    117     {
    118         MutexLocker locker(m_mutex);
    119 
    120         HandlersMap remainingHandlers;
    121         for (HandlersMap::iterator it = m_handlers.begin(); it != m_handlers.end(); ++it) {
    122             Vector<BoundTraceEventHandler>& handlers = it->value;
    123             for (size_t j = 0; j < handlers.size();) {
    124                 if (handlers[j].instance == instance)
    125                     handlers.remove(j);
    126                 else
    127                     ++j;
    128             }
    129             if (!handlers.isEmpty())
    130                 remainingHandlers.add(it->key, it->value);
    131         }
    132         m_handlers.swap(remainingHandlers);
    133     }
    134     if (m_handlers.isEmpty())
    135         client->setTraceEventCallback(0);
    136 }
    137 
    138 size_t TraceEventDispatcher::TraceEvent::findParameter(const char* name) const
    139 {
    140     for (int i = 0; i < m_argumentCount; ++i) {
    141         if (!strcmp(name, m_argumentNames[i]))
    142             return i;
    143     }
    144     return kNotFound;
    145 }
    146 
    147 const TraceEvent::TraceValueUnion& TraceEventDispatcher::TraceEvent::parameter(const char* name, unsigned char expectedType) const
    148 {
    149     static WebCore::TraceEvent::TraceValueUnion missingValue;
    150     size_t index = findParameter(name);
    151     if (index == kNotFound || m_argumentTypes[index] != expectedType) {
    152         ASSERT_NOT_REACHED();
    153         return missingValue;
    154     }
    155     return *reinterpret_cast<const WebCore::TraceEvent::TraceValueUnion*>(m_argumentValues + index);
    156 }
    157 
    158 } // namespace WebCore
    159 
    160