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 blink {
     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     TraceEventDispatcher* self = instance();
     47     {
     48         MutexLocker locker(self->m_mutex);
     49         if (self->m_listeners->find(std::make_pair(name, phase)) == self->m_listeners->end())
     50             return;
     51     }
     52     self->enqueueEvent(timestamp, phase, name, id, currentThread(), numArgs, argNames, argTypes, argValues);
     53     if (isMainThread())
     54         self->processBackgroundEvents();
     55 }
     56 
     57 void TraceEventDispatcher::enqueueEvent(double timestamp, char phase, const char* name, unsigned long long id, ThreadIdentifier threadIdentifier,
     58     int argumentCount, const char* const* argumentNames, const unsigned char* argumentTypes, const unsigned long long* argumentValues)
     59 {
     60     const float eventProcessingThresholdInSeconds = 0.1;
     61     {
     62         MutexLocker locker(m_mutex);
     63         // TraceEvent object is created here, rather than created in the callers of enqueEvent and passed as an argument of enqueEvent.
     64         // http://crbug.com/394706
     65         TraceEvent event(timestamp, phase, name, id, threadIdentifier, argumentCount, argumentNames, argumentTypes, argumentValues);
     66         m_backgroundEvents.append(event);
     67         if (m_processEventsTaskInFlight || event.timestamp() - m_lastEventProcessingTime <= eventProcessingThresholdInSeconds)
     68             return;
     69     }
     70     m_processEventsTaskInFlight = true;
     71     callOnMainThread(bind(&TraceEventDispatcher::processBackgroundEventsTask, this));
     72 }
     73 
     74 void TraceEventDispatcher::processBackgroundEventsTask()
     75 {
     76     m_processEventsTaskInFlight = false;
     77     processBackgroundEvents();
     78 }
     79 
     80 void TraceEventDispatcher::processBackgroundEvents()
     81 {
     82     ASSERT(isMainThread());
     83     Vector<TraceEvent> events;
     84     {
     85         MutexLocker locker(m_mutex);
     86         m_lastEventProcessingTime = WTF::monotonicallyIncreasingTime();
     87         if (m_backgroundEvents.isEmpty())
     88             return;
     89         events.reserveCapacity(m_backgroundEvents.capacity());
     90         m_backgroundEvents.swap(events);
     91     }
     92     for (size_t eventIndex = 0, size = events.size(); eventIndex < size; ++eventIndex) {
     93         const TraceEvent& event = events[eventIndex];
     94         ListenersMap::iterator it = m_listeners->find(std::make_pair(event.name(), event.phase()));
     95         if (it == m_listeners->end())
     96             continue;
     97         WillBeHeapVector<OwnPtrWillBeMember<TraceEventListener> >& listeners = *it->value.get();
     98         for (size_t listenerIndex = 0; listenerIndex < listeners.size(); ++listenerIndex)
     99             listeners[listenerIndex]->call(event);
    100     }
    101 }
    102 
    103 void TraceEventDispatcher::addListener(const char* name, char phase, PassOwnPtrWillBeRawPtr<TraceEventListener> listener, InspectorClient* client)
    104 {
    105     static const char CategoryFilter[] = "-*," TRACE_DISABLED_BY_DEFAULT("devtools.timeline") "," TRACE_DISABLED_BY_DEFAULT("devtools.timeline.frame");
    106 
    107     ASSERT(isMainThread());
    108     MutexLocker locker(m_mutex);
    109     if (m_listeners->isEmpty())
    110         client->setTraceEventCallback(CategoryFilter, dispatchEventOnAnyThread);
    111     ListenersMap::iterator it = m_listeners->find(std::make_pair(name, phase));
    112     if (it == m_listeners->end())
    113         m_listeners->add(std::make_pair(name, phase), adoptPtrWillBeNoop(new WillBeHeapVector<OwnPtrWillBeMember<TraceEventListener> >())).storedValue->value->append(listener);
    114     else
    115         it->value->append(listener);
    116 }
    117 
    118 void TraceEventDispatcher::removeAllListeners(void* eventTarget, InspectorClient* client)
    119 {
    120     ASSERT(isMainThread());
    121     processBackgroundEvents();
    122     {
    123         MutexLocker locker(m_mutex);
    124 
    125         ListenersMap remainingListeners;
    126         for (ListenersMap::iterator it = m_listeners->begin(); it != m_listeners->end(); ++it) {
    127             WillBeHeapVector<OwnPtrWillBeMember<TraceEventListener> >& listeners = *it->value.get();
    128             for (size_t j = 0; j < listeners.size();) {
    129                 if (listeners[j]->target() == eventTarget)
    130                     listeners.remove(j);
    131                 else
    132                     ++j;
    133             }
    134             if (!listeners.isEmpty())
    135                 remainingListeners.add(it->key, it->value.release());
    136         }
    137         m_listeners->swap(remainingListeners);
    138     }
    139     if (m_listeners->isEmpty())
    140         client->resetTraceEventCallback();
    141 }
    142 
    143 size_t TraceEventDispatcher::TraceEvent::findParameter(const char* name) const
    144 {
    145     for (int i = 0; i < m_argumentCount; ++i) {
    146         if (!strcmp(name, m_argumentNames[i]))
    147             return i;
    148     }
    149     return kNotFound;
    150 }
    151 
    152 const TraceEvent::TraceValueUnion& TraceEventDispatcher::TraceEvent::parameter(const char* name, unsigned char expectedType) const
    153 {
    154     static blink::TraceEvent::TraceValueUnion missingValue;
    155     size_t index = findParameter(name);
    156     ASSERT(isMainThread());
    157     if (index == kNotFound || m_argumentTypes[index] != expectedType) {
    158         ASSERT_NOT_REACHED();
    159         return missingValue;
    160     }
    161     return m_argumentValues[index];
    162 }
    163 
    164 } // namespace blink
    165 
    166