ScriptValue InjectedScriptBase::callFunctionWithEvalEnabled(ScriptFunctionCall& function, bool& hadException) const
{
    ASSERT(!isEmpty());
    ExecutionContext* executionContext = m_injectedScriptObject.scriptState()->executionContext();
    ScriptState::Scope scope(m_injectedScriptObject.scriptState());
    v8::Local<v8::Function> functionObj = function.function();
    DevToolsFunctionInfo info(functionObj);
    TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "FunctionCall", "data", InspectorFunctionCallEvent::data(executionContext, info.scriptId(), "InjectedScriptSource.js", info.lineNumber()));
    InspectorInstrumentationCookie cookie = InspectorInstrumentation::willCallFunction(executionContext, info);

    ScriptState* scriptState = m_injectedScriptObject.scriptState();
    bool evalIsDisabled = false;
    if (scriptState) {
        evalIsDisabled = !scriptState->evalEnabled();
        // Temporarily enable allow evals for inspector.
        if (evalIsDisabled)
            scriptState->setEvalEnabled(true);
    }

    ScriptValue resultValue = function.call(hadException);

    if (evalIsDisabled)
        scriptState->setEvalEnabled(false);

    InspectorInstrumentation::didCallFunction(cookie);
    TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", TRACE_EVENT_SCOPE_THREAD, "data", InspectorUpdateCountersEvent::data());
    return resultValue;
}
v8::Local<v8::Value> ScriptController::callFunctionWithInstrumentation(ScriptExecutionContext* context, v8::Handle<v8::Function> function, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> args[])
{
    V8GCController::checkMemoryUsage();

    if (V8RecursionScope::recursionLevel() >= kMaxRecursionDepth)
        return handleMaxRecursionDepthExceeded();

    InspectorInstrumentationCookie cookie;
    if (InspectorInstrumentation::timelineAgentEnabled(context)) {
        String resourceName;
        int lineNumber;
        resourceInfo(function, resourceName, lineNumber);
        cookie = InspectorInstrumentation::willCallFunction(context, resourceName, lineNumber);
    }

    v8::Local<v8::Value> result;
    {
        TRACE_EVENT1("v8", "v8.callFunction", "callsite", resourceString(function).utf8());
        V8RecursionScope recursionScope(context);
        result = function->Call(receiver, argc, args);
    }

    InspectorInstrumentation::didCallFunction(cookie);
    crashIfV8IsDead();
    return result;
}
Example #3
0
v8::MaybeLocal<v8::Script> V8ScriptRunner::compileScript(v8::Local<v8::String> code, const String& fileName, const String& sourceMapUrl, const TextPosition& scriptStartPosition, v8::Isolate* isolate, ScriptResource* resource, ScriptStreamer* streamer, CachedMetadataHandler* cacheHandler, AccessControlStatus corsStatus, V8CacheOptions cacheOptions, bool isInternalScript)
{
    TRACE_EVENT1("v8", "v8.compile", "fileName", fileName.utf8());
    TRACE_EVENT_SCOPED_SAMPLING_STATE("v8", "V8Compile");

    ASSERT(!streamer || resource);
    ASSERT(!resource || resource->cacheHandler() == cacheHandler);

    // NOTE: For compatibility with WebCore, ScriptSourceCode's line starts at
    // 1, whereas v8 starts at 0.
    v8::ScriptOrigin origin(
        v8String(isolate, fileName),
        v8::Integer::New(isolate, scriptStartPosition.m_line.zeroBasedInt()),
        v8::Integer::New(isolate, scriptStartPosition.m_column.zeroBasedInt()),
        v8Boolean(corsStatus == SharableCrossOrigin, isolate),
        v8::Local<v8::Integer>(),
        v8Boolean(isInternalScript, isolate),
        v8String(isolate, sourceMapUrl));

    OwnPtr<CompileFn> compileFn = streamer
        ? selectCompileFunction(cacheOptions, resource, streamer)
        : selectCompileFunction(cacheOptions, cacheHandler, code);

    return (*compileFn)(isolate, code, origin);
}
Example #4
0
v8::Local<v8::Value> V8Proxy::instrumentedCallFunction(Frame* frame, v8::Handle<v8::Function> function, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> args[])
{
    V8GCController::checkMemoryUsage();

    if (V8RecursionScope::recursionLevel() >= kMaxRecursionDepth)
        return handleMaxRecursionDepthExceeded();

    ScriptExecutionContext* context = frame ? frame->document() : 0;

    InspectorInstrumentationCookie cookie;
    if (InspectorInstrumentation::hasFrontends() && context) {
        String resourceName;
        int lineNumber;
        resourceInfo(function, resourceName, lineNumber);
        cookie = InspectorInstrumentation::willCallFunction(context, resourceName, lineNumber);
    }

    v8::Local<v8::Value> result;
    {
#if PLATFORM(CHROMIUM)
        TRACE_EVENT1("v8", "v8.callFunction", "callsite", resourceString(function).utf8());
#endif
        V8RecursionScope recursionScope(context);
        result = function->Call(receiver, argc, args);
    }

    InspectorInstrumentation::didCallFunction(cookie);

    if (v8::V8::IsDead())
        handleFatalErrorInV8();

    return result;
}
void ScriptedAnimationController::executeCallbacks(double monotonicTimeNow)
{
    // dispatchEvents() runs script which can cause the document to be destroyed.
    if (!m_document)
        return;

    double highResNowMs = 1000.0 * m_document->loader()->timing()->monotonicTimeToZeroBasedDocumentTime(monotonicTimeNow);
    double legacyHighResNowMs = 1000.0 * m_document->loader()->timing()->monotonicTimeToPseudoWallTime(monotonicTimeNow);

    // First, generate a list of callbacks to consider.  Callbacks registered from this point
    // on are considered only for the "next" frame, not this one.
    ASSERT(m_callbacksToInvoke.isEmpty());
    m_callbacksToInvoke.swap(m_callbacks);

    for (size_t i = 0; i < m_callbacksToInvoke.size(); ++i) {
        RequestAnimationFrameCallback* callback = m_callbacksToInvoke[i].get();
        if (!callback->m_cancelled) {
            TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "FireAnimationFrame", "data", InspectorAnimationFrameEvent::data(m_document, callback->m_id));
            // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing.
            InspectorInstrumentationCookie cookie = InspectorInstrumentation::willFireAnimationFrame(m_document, callback->m_id);
            if (callback->m_useLegacyTimeBase)
                callback->handleEvent(legacyHighResNowMs);
            else
                callback->handleEvent(highResNowMs);
            InspectorInstrumentation::didFireAnimationFrame(cookie);
            TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", "data", InspectorUpdateCountersEvent::data());
        }
    }

    m_callbacksToInvoke.clear();
}
void ScriptedIdleTaskController::runCallback(
    CallbackId id,
    double deadlineSeconds,
    IdleDeadline::CallbackType callbackType) {
  DCHECK(!m_suspended);
  auto callback = m_callbacks.take(id);
  if (!callback)
    return;

  double allottedTimeMillis =
      std::max((deadlineSeconds - monotonicallyIncreasingTime()) * 1000, 0.0);

  DEFINE_STATIC_LOCAL(
      CustomCountHistogram, idleCallbackDeadlineHistogram,
      ("WebCore.ScriptedIdleTaskController.IdleCallbackDeadline", 0, 50, 50));
  idleCallbackDeadlineHistogram.count(allottedTimeMillis);

  TRACE_EVENT1(
      "devtools.timeline", "FireIdleCallback", "data",
      InspectorIdleCallbackFireEvent::data(
          getExecutionContext(), id, allottedTimeMillis,
          callbackType == IdleDeadline::CallbackType::CalledByTimeout));
  callback->handleEvent(IdleDeadline::create(deadlineSeconds, callbackType));

  double overrunMillis =
      std::max((monotonicallyIncreasingTime() - deadlineSeconds) * 1000, 0.0);

  DEFINE_STATIC_LOCAL(
      CustomCountHistogram, idleCallbackOverrunHistogram,
      ("WebCore.ScriptedIdleTaskController.IdleCallbackOverrun", 0, 10000, 50));
  idleCallbackOverrunHistogram.count(overrunMillis);
}
Example #7
0
bool EventDispatcher::dispatch()
{
    TRACE_EVENT0("webkit", "EventDispatcher::dispatch");

#ifndef NDEBUG
    ASSERT(!m_eventDispatched);
    m_eventDispatched = true;
#endif
    ChildNodesLazySnapshot::takeChildNodesLazySnapshot();

    m_event->setTarget(EventPath::eventTargetRespectingTargetRules(m_node.get()));
    ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
    ASSERT(m_event->target());
    WindowEventContext windowEventContext(m_event.get(), m_node.get(), topNodeEventContext());
    TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "EventDispatch", "type", m_event->type().ascii());
    // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing.
    InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEvent(&m_node->document(), *m_event, windowEventContext.window(), m_node.get(), m_event->eventPath());

    void* preDispatchEventHandlerResult;
    if (dispatchEventPreProcess(preDispatchEventHandlerResult) == ContinueDispatching)
        if (dispatchEventAtCapturing(windowEventContext) == ContinueDispatching)
            if (dispatchEventAtTarget() == ContinueDispatching)
                dispatchEventAtBubbling(windowEventContext);
    dispatchEventPostProcess(preDispatchEventHandlerResult);

    // Ensure that after event dispatch, the event's target object is the
    // outermost shadow DOM boundary.
    m_event->setTarget(windowEventContext.target());
    m_event->setCurrentTarget(0);
    InspectorInstrumentation::didDispatchEvent(cookie);
    TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", "data", InspectorUpdateCountersEvent::data());

    return !m_event->defaultPrevented();
}
v8::Local<v8::Value> ScriptController::executeScriptAndReturnValue(v8::Local<v8::Context> context, const ScriptSourceCode& source, AccessControlStatus accessControlStatus, double* compilationFinishTime)
{
    TRACE_EVENT1("devtools.timeline", "EvaluateScript", "data", InspectorEvaluateScriptEvent::data(frame(), source.url().string(), source.startPosition()));
    InspectorInstrumentation::willEvaluateScript(frame()->document());

    v8::Local<v8::Value> result;
    {
        V8CacheOptions v8CacheOptions(V8CacheOptionsDefault);
        if (frame()->settings())
            v8CacheOptions = frame()->settings()->v8CacheOptions();

        // Isolate exceptions that occur when compiling and executing
        // the code. These exceptions should not interfere with
        // javascript code we might evaluate from C++ when returning
        // from here.
        v8::TryCatch tryCatch;
        tryCatch.SetVerbose(true);

        v8::Local<v8::Script> script;
        if (!v8Call(V8ScriptRunner::compileScript(source, isolate(), accessControlStatus, v8CacheOptions), script, tryCatch))
            return result;

        if (compilationFinishTime) {
            *compilationFinishTime = WTF::monotonicallyIncreasingTime();
        }
        // Keep LocalFrame (and therefore ScriptController) alive.
        RefPtrWillBeRawPtr<LocalFrame> protect(frame());
        if (!v8Call(V8ScriptRunner::runCompiledScript(isolate(), script, frame()->document()), result, tryCatch))
            return result;
    }

    TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", TRACE_EVENT_SCOPE_THREAD, "data", InspectorUpdateCountersEvent::data());

    return result;
}
bool DecodingImageGenerator::onGetPixels(const SkImageInfo& info,
                                         void* pixels,
                                         size_t rowBytes,
                                         SkPMColor table[],
                                         int* tableCount) {
  TRACE_EVENT1("blink", "DecodingImageGenerator::getPixels", "frame index",
               static_cast<int>(m_frameIndex));

  // Implementation doesn't support scaling yet, so make sure we're not given a
  // different size.
  if (info.width() != getInfo().width() || info.height() != getInfo().height())
    return false;

  if (info.colorType() != getInfo().colorType()) {
    // blink::ImageFrame may have changed the owning SkBitmap to
    // kOpaque_SkAlphaType after fully decoding the image frame, so if we see a
    // request for opaque, that is ok even if our initial alpha type was not
    // opaque.
    return false;
  }

  PlatformInstrumentation::willDecodeLazyPixelRef(uniqueID());
  bool decoded = m_frameGenerator->decodeAndScale(
      m_data.get(), m_allDataReceived, m_frameIndex, getInfo(), pixels,
      rowBytes);
  PlatformInstrumentation::didDecodeLazyPixelRef();

  return decoded;
}
Example #10
0
v8::Local<v8::Value> ScriptController::executeScriptAndReturnValue(v8::Handle<v8::Context> context, const ScriptSourceCode& source, AccessControlStatus corsStatus, double* compilationFinishTime)
{
    TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "EvaluateScript", "data", InspectorEvaluateScriptEvent::data(frame(), source.url().string(), source.startLine()));
    // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing.
    InspectorInstrumentationCookie cookie = InspectorInstrumentation::willEvaluateScript(frame(), source.url().string(), source.startLine());

    v8::Local<v8::Value> result;
    {
        V8CacheOptions v8CacheOptions(V8CacheOptionsDefault);
        if (frame()->settings())
            v8CacheOptions = frame()->settings()->v8CacheOptions();

        // Isolate exceptions that occur when compiling and executing
        // the code. These exceptions should not interfere with
        // javascript code we might evaluate from C++ when returning
        // from here.
        v8::TryCatch tryCatch;
        tryCatch.SetVerbose(true);

        v8::Handle<v8::Script> script = V8ScriptRunner::compileScript(source, isolate(), corsStatus, v8CacheOptions);

        if (compilationFinishTime) {
            *compilationFinishTime = WTF::monotonicallyIncreasingTime();
        }
        // Keep LocalFrame (and therefore ScriptController) alive.
        RefPtrWillBeRawPtr<LocalFrame> protect(frame());
        result = V8ScriptRunner::runCompiledScript(isolate(), script, frame()->document());
        ASSERT(!tryCatch.HasCaught() || result.IsEmpty());
    }

    InspectorInstrumentation::didEvaluateScript(cookie);
    TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", "data", InspectorUpdateCountersEvent::data());

    return result;
}
Example #11
0
void FrameRequestCallbackCollection::executeCallbacks(
    double highResNowMs,
    double highResNowMsLegacy) {
  // First, generate a list of callbacks to consider.  Callbacks registered from
  // this point on are considered only for the "next" frame, not this one.
  DCHECK(m_callbacksToInvoke.isEmpty());
  m_callbacksToInvoke.swap(m_callbacks);

  for (const auto& callback : m_callbacksToInvoke) {
    if (!callback->m_cancelled) {
      TRACE_EVENT1(
          "devtools.timeline", "FireAnimationFrame", "data",
          InspectorAnimationFrameEvent::data(m_context, callback->m_id));
      InspectorInstrumentation::NativeBreakpoint nativeBreakpoint(
          m_context, "animationFrameFired", false);
      InspectorInstrumentation::AsyncTask asyncTask(m_context, callback);
      PerformanceMonitor::HandlerCall handlerCall(
          m_context, "requestAnimationFrame", true);
      if (callback->m_useLegacyTimeBase)
        callback->handleEvent(highResNowMsLegacy);
      else
        callback->handleEvent(highResNowMs);
      TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
                           "UpdateCounters", TRACE_EVENT_SCOPE_THREAD, "data",
                           InspectorUpdateCountersEvent::data());
    }
  }

  m_callbacksToInvoke.clear();
}
v8::Local<v8::Value> V8WorkerGlobalScopeEventListener::callListenerFunction(v8::Handle<v8::Value> jsEvent, Event* event)
{
    v8::Local<v8::Function> handlerFunction = getListenerFunction(scriptState()->executionContext());
    v8::Local<v8::Object> receiver = getReceiverObject(event);
    if (handlerFunction.IsEmpty() || receiver.IsEmpty())
        return v8::Local<v8::Value>();

    TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "FunctionCall", "data", devToolsTraceEventData(scriptState()->executionContext(), handlerFunction, isolate()));
    TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack());
    // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing.
    InspectorInstrumentationCookie cookie;
    if (InspectorInstrumentation::timelineAgentEnabled(scriptState()->executionContext())) {
        int scriptId = 0;
        String resourceName;
        int lineNumber = 1;
        GetDevToolsFunctionInfo(handlerFunction, isolate(), scriptId, resourceName, lineNumber);
        cookie = InspectorInstrumentation::willCallFunction(scriptState()->executionContext(), scriptId, resourceName, lineNumber);
    }

    v8::Handle<v8::Value> parameters[1] = { jsEvent };
    v8::Local<v8::Value> result = V8ScriptRunner::callFunction(handlerFunction, scriptState()->executionContext(), receiver, WTF_ARRAY_LENGTH(parameters), parameters, isolate());

    InspectorInstrumentation::didCallFunction(cookie);
    TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", "data", InspectorUpdateCountersEvent::data());

    return result;
}
DispatchEventResult EventDispatcher::dispatch()
{
    TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("blink.debug"), "EventDispatcher::dispatch");

#if ENABLE(ASSERT)
    ASSERT(!m_eventDispatched);
    m_eventDispatched = true;
#endif
    if (event().eventPath().isEmpty()) {
        // eventPath() can be empty if event path is shrinked by relataedTarget retargeting.
        return DispatchEventResult::NotCanceled;
    }
    m_event->eventPath().ensureWindowEventContext();

    m_event->setTarget(EventPath::eventTargetRespectingTargetRules(*m_node));
    ASSERT(!EventDispatchForbiddenScope::isEventDispatchForbidden());
    ASSERT(m_event->target());
    TRACE_EVENT1("devtools.timeline", "EventDispatch", "data", InspectorEventDispatchEvent::data(*m_event));
    void* preDispatchEventHandlerResult;
    if (dispatchEventPreProcess(preDispatchEventHandlerResult) == ContinueDispatching) {
        if (dispatchEventAtCapturing() == ContinueDispatching) {
            if (dispatchEventAtTarget() == ContinueDispatching)
                dispatchEventAtBubbling();
        }
    }
    dispatchEventPostProcess(preDispatchEventHandlerResult);

    // Ensure that after event dispatch, the event's target object is the
    // outermost shadow DOM boundary.
    m_event->setTarget(m_event->eventPath().windowEventContext().target());
    m_event->setCurrentTarget(nullptr);
    TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", TRACE_EVENT_SCOPE_THREAD, "data", InspectorUpdateCountersEvent::data());

    return EventTarget::dispatchEventResult(*m_event);
}
Example #14
0
v8::MaybeLocal<v8::Value> V8ScriptRunner::runCompiledScript(v8::Isolate* isolate, v8::Local<v8::Script> script, ExecutionContext* context)
{
    ASSERT(!script.IsEmpty());
    TRACE_EVENT_SCOPED_SAMPLING_STATE("v8", "V8Execution");
    TRACE_EVENT1("v8", "v8.run", "fileName", TRACE_STR_COPY(*v8::String::Utf8Value(script->GetUnboundScript()->GetScriptName())));

    if (V8RecursionScope::recursionLevel(isolate) >= kMaxRecursionDepth)
        return throwStackOverflowExceptionIfNeeded(isolate);

    RELEASE_ASSERT(!context->isIteratingOverObservers());

    // Run the script and keep track of the current recursion depth.
    v8::MaybeLocal<v8::Value> result;
    {
        if (ScriptForbiddenScope::isScriptForbidden()) {
            throwScriptForbiddenException(isolate);
            return v8::MaybeLocal<v8::Value>();
        }
        V8RecursionScope recursionScope(isolate);
        result = script->Run(isolate->GetCurrentContext());
    }

    crashIfV8IsDead();
    return result;
}
v8::Local<v8::Value> ScriptController::executeScriptAndReturnValue(v8::Handle<v8::Context> context, const ScriptSourceCode& source, AccessControlStatus corsStatus)
{
    TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "EvaluateScript", "data", InspectorEvaluateScriptEvent::data(m_frame, source.url().string(), source.startLine()));
    TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack());
    // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing.
    InspectorInstrumentationCookie cookie = InspectorInstrumentation::willEvaluateScript(m_frame, source.url().string(), source.startLine());

    v8::Local<v8::Value> result;
    {
        // Isolate exceptions that occur when compiling and executing
        // the code. These exceptions should not interfere with
        // javascript code we might evaluate from C++ when returning
        // from here.
        v8::TryCatch tryCatch;
        tryCatch.SetVerbose(true);

        v8::Handle<v8::Script> script = V8ScriptRunner::compileScript(source, m_isolate, corsStatus);

        // Keep LocalFrame (and therefore ScriptController) alive.
        RefPtr<LocalFrame> protect(m_frame);
        result = V8ScriptRunner::runCompiledScript(script, m_frame->document(), m_isolate);
        ASSERT(!tryCatch.HasCaught() || result.IsEmpty());
    }

    InspectorInstrumentation::didEvaluateScript(cookie);
    TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", "data", InspectorUpdateCountersEvent::data());

    return result;
}
Example #16
0
ScriptValue InjectedScriptBase::callFunctionWithEvalEnabled(ScriptFunctionCall& function, bool& hadException) const
{
    ASSERT(!isEmpty());
    ExecutionContext* executionContext = m_injectedScriptObject.scriptState()->executionContext();
    TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "FunctionCall", "data", InspectorFunctionCallEvent::data(executionContext, 0, name(), 1));
    // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing.
    InspectorInstrumentationCookie cookie = InspectorInstrumentation::willCallFunction(executionContext, 0, name(), 1);

    ScriptState* scriptState = m_injectedScriptObject.scriptState();
    bool evalIsDisabled = false;
    if (scriptState) {
        evalIsDisabled = !scriptState->evalEnabled();
        // Temporarily enable allow evals for inspector.
        if (evalIsDisabled)
            scriptState->setEvalEnabled(true);
    }

    ScriptValue resultValue = function.call(hadException);

    if (evalIsDisabled)
        scriptState->setEvalEnabled(false);

    InspectorInstrumentation::didCallFunction(cookie);
    TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", "data", InspectorUpdateCountersEvent::data());
    return resultValue;
}
void ContentLayerDelegate::paintContents(
    WebDisplayItemList* webDisplayItemList, const WebRect& clip,
    WebContentLayerClient::PaintingControlSetting paintingControl)
{
    TRACE_EVENT1("blink,benchmark", "ContentLayerDelegate::paintContents", "clip_rect", toTracedValue(clip));

    // TODO(pdr): Remove when slimming paint v2 is further along. This is only
    // here so the browser is usable during development and does not crash due
    // to committing the new display items twice.
    if (RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled()) {
        m_painter->displayItemList()->paintArtifact().appendToWebDisplayItemList(webDisplayItemList);
        return;
    }

    DisplayItemList* displayItemList = m_painter->displayItemList();
    ASSERT(displayItemList);
    displayItemList->setDisplayItemConstructionIsDisabled(
        paintingControl == WebContentLayerClient::DisplayListConstructionDisabled);

    // We also disable caching when Painting or Construction are disabled. In both cases we would like
    // to compare assuming the full cost of recording, not the cost of re-using cached content.
    if (paintingControl != WebContentLayerClient::PaintDefaultBehavior)
        displayItemList->invalidateAll();

    GraphicsContext::DisabledMode disabledMode = GraphicsContext::NothingDisabled;
    if (paintingControl == WebContentLayerClient::DisplayListPaintingDisabled
        || paintingControl == WebContentLayerClient::DisplayListConstructionDisabled)
        disabledMode = GraphicsContext::FullyDisabled;
    GraphicsContext context(displayItemList, disabledMode);

    m_painter->paint(context, clip);

    displayItemList->commitNewDisplayItems();
    displayItemList->paintArtifact().appendToWebDisplayItemList(webDisplayItemList);
}
Example #18
0
bool ChannelReader::DispatchInputData(const char* input_data,
                                      int input_data_len) {
  const char* p;
  const char* end;

  // Possibly combine with the overflow buffer to make a larger buffer.
  if (input_overflow_buf_.empty()) {
    p = input_data;
    end = input_data + input_data_len;
  } else {
    if (input_overflow_buf_.size() + input_data_len >
        Channel::kMaximumMessageSize) {
      input_overflow_buf_.clear();
      //assert(ERROR) << "IPC message is too big";
      return false;
    }
    input_overflow_buf_.append(input_data, input_data_len);
    p = input_overflow_buf_.data();
    end = p + input_overflow_buf_.size();
  }

  // Dispatch all complete messages in the data buffer.
  while (p < end) {
    const char* message_tail = Message::FindNext(p, end);
    if (message_tail) {
      int len = static_cast<int>(message_tail - p);
      Message* m = new Message(p, len);
	  m->AddRef();
      if (!WillDispatchInputMessage(m))
        return false;

#ifdef IPC_MESSAGE_LOG_ENABLED
      Logging* logger = Logging::GetInstance();
      std::string name;
      logger->GetMessageText(m.type(), &name, &m, NULL);
      TRACE_EVENT1("ipc", "ChannelReader::DispatchInputData", "name", name);
#else
      //TRACE_EVENT2("ipc", "ChannelReader::DispatchInputData",
      //             "class", IPC_MESSAGE_ID_CLASS(m.type()),
      //             "line", IPC_MESSAGE_ID_LINE(m.type()));
#endif
      //m.TraceMessageEnd();
      if (IsHelloMessage(m))
        HandleHelloMessage(m);
      else
        listener_->OnMessageReceived(m);
      p = message_tail;
    } else {
      // Last message is partial.
      break;
    }
  }

  // Save any partial data in the overflow buffer.
  input_overflow_buf_.assign(p, end - p);

  if (input_overflow_buf_.empty() && !DidEmptyInputBuffers())
    return false;
  return true;
}
bool ImageFrameGenerator::decodeAndScale(size_t index, const SkImageInfo& info, void* pixels, size_t rowBytes)
{
    // Prevent concurrent decode or scale operations on the same image data.
    MutexLocker lock(m_decodeMutex);

    if (m_decodeFailed)
        return false;

    TRACE_EVENT1("blink", "ImageFrameGenerator::decodeAndScale", "frame index", static_cast<int>(index));

    m_externalAllocator = adoptPtr(new ExternalMemoryAllocator(info, pixels, rowBytes));

    // This implementation does not support scaling so check the requested size.
    SkISize scaledSize = SkISize::Make(info.width(), info.height());
    ASSERT(m_fullSize == scaledSize);

    SkBitmap bitmap = tryToResumeDecode(index, scaledSize);
    if (bitmap.isNull())
        return false;

    // Don't keep the allocator because it contains a pointer to memory
    // that we do not own.
    m_externalAllocator.clear();

    // Check to see if the decoder has written directly to the pixel memory
    // provided. If not, make a copy.
    ASSERT(bitmap.width() == scaledSize.width());
    ASSERT(bitmap.height() == scaledSize.height());
    SkAutoLockPixels bitmapLock(bitmap);
    if (bitmap.getPixels() != pixels)
        return bitmap.copyPixelsTo(pixels, rowBytes * info.height(), rowBytes);
    return true;
}
v8::MaybeLocal<v8::Value> ScriptController::callFunction(ExecutionContext* context, v8::Local<v8::Function> function, v8::Local<v8::Value> receiver, int argc, v8::Local<v8::Value> info[], v8::Isolate* isolate)
{
    TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "FunctionCall", "data", devToolsTraceEventData(isolate, context, function));
    InspectorInstrumentationCookie cookie = InspectorInstrumentation::willCallFunction(context, DevToolsFunctionInfo(function));
    v8::MaybeLocal<v8::Value> result = V8ScriptRunner::callFunction(function, context, receiver, argc, info, isolate);
    InspectorInstrumentation::didCallFunction(cookie);
    return result;
}
Example #21
0
bool StyleFetchedImage::knownToBeOpaque(
    const LayoutObject& layoutObject) const {
  TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage",
               "data",
               InspectorPaintImageEvent::data(&layoutObject, *m_image.get()));
  return m_image->getImage()->currentFrameKnownToBeOpaque(
      Image::PreCacheMetadata);
}
void ContentLayerDelegate::paintContents(
    SkCanvas* canvas, const WebRect& clip,
    WebContentLayerClient::PaintingControlSetting paintingControl)
{
    TRACE_EVENT1("blink,benchmark", "ContentLayerDelegate::paintContents", "clip_rect", toTracedValue(clip));

    // TODO(pdr): Remove this function.
    ASSERT_NOT_REACHED();
}
SkBitmap ImageFrameGenerator::tryToResumeDecode(size_t index, const SkISize& scaledSize)
{
    TRACE_EVENT1("blink", "ImageFrameGenerator::tryToResumeDecode", "frame index", static_cast<int>(index));

    ImageDecoder* decoder = 0;
    const bool resumeDecoding = ImageDecodingStore::instance().lockDecoder(this, m_fullSize, &decoder);
    ASSERT(!resumeDecoding || decoder);

    SkBitmap fullSizeImage;
    bool complete = decode(index, &decoder, &fullSizeImage);

    if (!decoder)
        return SkBitmap();

    // If we are not resuming decoding that means the decoder is freshly
    // created and we have ownership. If we are resuming decoding then
    // the decoder is owned by ImageDecodingStore.
    OwnPtr<ImageDecoder> decoderContainer;
    if (!resumeDecoding)
        decoderContainer = adoptPtr(decoder);

    if (fullSizeImage.isNull()) {
        // If decoding has failed, we can save work in the future by
        // ignoring further requests to decode the image.
        m_decodeFailed = decoder->failed();
        if (resumeDecoding)
            ImageDecodingStore::instance().unlockDecoder(this, decoder);
        return SkBitmap();
    }

    bool removeDecoder = false;
    if (complete) {
        // Free as much memory as possible.  For single-frame images, we can
        // just delete the decoder entirely.  For multi-frame images, we keep
        // the decoder around in order to preserve decoded information such as
        // the required previous frame indexes, but if we've reached the last
        // frame we can at least delete all the cached frames.  (If we were to
        // do this before reaching the last frame, any subsequent requested
        // frames which relied on the current frame would trigger extra
        // re-decoding of all frames in the dependency chain.)
        if (!m_isMultiFrame)
            removeDecoder = true;
        else if (index == m_frameCount - 1)
            decoder->clearCacheExceptFrame(kNotFound);
    }

    if (resumeDecoding) {
        if (removeDecoder)
            ImageDecodingStore::instance().removeDecoder(this, decoder);
        else
            ImageDecodingStore::instance().unlockDecoder(this, decoder);
    } else if (!removeDecoder) {
        ImageDecodingStore::instance().insertDecoder(this, decoderContainer.release());
    }
    return fullSizeImage;
}
Example #24
0
ScriptValue WorkerOrWorkletScriptController::evaluate(
    const String& script,
    const String& fileName,
    const TextPosition& scriptStartPosition,
    CachedMetadataHandler* cacheHandler,
    V8CacheOptions v8CacheOptions) {
  TRACE_EVENT1("devtools.timeline", "EvaluateScript", "data",
               InspectorEvaluateScriptEvent::data(nullptr, fileName,
                                                  scriptStartPosition));
  if (!initializeContextIfNeeded())
    return ScriptValue();

  ScriptState::Scope scope(m_scriptState.get());

  if (!m_disableEvalPending.isEmpty()) {
    m_scriptState->context()->AllowCodeGenerationFromStrings(false);
    m_scriptState->context()->SetErrorMessageForCodeGenerationFromStrings(
        v8String(m_isolate, m_disableEvalPending));
    m_disableEvalPending = String();
  }

  v8::TryCatch block(m_isolate);

  v8::Local<v8::Script> compiledScript;
  v8::MaybeLocal<v8::Value> maybeResult;
  if (v8Call(V8ScriptRunner::compileScript(
                 script, fileName, String(), scriptStartPosition, m_isolate,
                 cacheHandler, SharableCrossOrigin, v8CacheOptions),
             compiledScript, block))
    maybeResult = V8ScriptRunner::runCompiledScript(m_isolate, compiledScript,
                                                    m_globalScope);

  if (!block.CanContinue()) {
    forbidExecution();
    return ScriptValue();
  }

  if (block.HasCaught()) {
    v8::Local<v8::Message> message = block.Message();
    m_executionState->hadException = true;
    m_executionState->errorMessage = toCoreString(message->Get());
    m_executionState->m_location = SourceLocation::fromMessage(
        m_isolate, message, m_scriptState->getExecutionContext());
    m_executionState->exception =
        ScriptValue(m_scriptState.get(), block.Exception());
    block.Reset();
  } else {
    m_executionState->hadException = false;
  }

  v8::Local<v8::Value> result;
  if (!maybeResult.ToLocal(&result) || result->IsUndefined())
    return ScriptValue();

  return ScriptValue(m_scriptState.get(), result);
}
// Modifies the top of the graphics layer tree to add layers needed to support
// the inner/outer viewport fixed-position model for pinch zoom. When finished,
// the tree will look like this (with * denoting added layers):
//
// *rootTransformLayer
//  +- *innerViewportContainerLayer (fixed pos container)
//  |   +- *overscrollElasticityLayer
//  |       +- *pageScaleLayer
//  |           +- *innerViewportScrollLayer
//  |               +-- overflowControlsHostLayer (root layer)
//  |                   +-- outerViewportContainerLayer (fixed pos container) [frame container layer in PaintLayerCompositor]
//  |                   |   +-- outerViewportScrollLayer [frame scroll layer in PaintLayerCompositor]
//  |                   |       +-- content layers ...
//  +- horizontalScrollbarLayer
//  +- verticalScrollbarLayer
//  +- scroll corner (non-overlay only)
//
void VisualViewport::attachToLayerTree(GraphicsLayer* currentLayerTreeRoot, GraphicsLayerFactory* graphicsLayerFactory)
{
    TRACE_EVENT1("blink", "VisualViewport::attachToLayerTree", "currentLayerTreeRoot", (bool)currentLayerTreeRoot);
    if (!currentLayerTreeRoot) {
        if (m_innerViewportScrollLayer)
            m_innerViewportScrollLayer->removeAllChildren();
        return;
    }

    if (currentLayerTreeRoot->parent() && currentLayerTreeRoot->parent() == m_innerViewportScrollLayer)
        return;

    if (!m_innerViewportScrollLayer) {
        ASSERT(!m_overlayScrollbarHorizontal
            && !m_overlayScrollbarVertical
            && !m_overscrollElasticityLayer
            && !m_pageScaleLayer
            && !m_innerViewportContainerLayer);

        // FIXME: The root transform layer should only be created on demand.
        m_rootTransformLayer = GraphicsLayer::create(graphicsLayerFactory, this);
        m_innerViewportContainerLayer = GraphicsLayer::create(graphicsLayerFactory, this);
        m_overscrollElasticityLayer = GraphicsLayer::create(graphicsLayerFactory, this);
        m_pageScaleLayer = GraphicsLayer::create(graphicsLayerFactory, this);
        m_innerViewportScrollLayer = GraphicsLayer::create(graphicsLayerFactory, this);
        m_overlayScrollbarHorizontal = GraphicsLayer::create(graphicsLayerFactory, this);
        m_overlayScrollbarVertical = GraphicsLayer::create(graphicsLayerFactory, this);

        ScrollingCoordinator* coordinator = frameHost().page().scrollingCoordinator();
        ASSERT(coordinator);
        coordinator->setLayerIsContainerForFixedPositionLayers(m_innerViewportScrollLayer.get(), true);

        // Set masks to bounds so the compositor doesn't clobber a manually
        // set inner viewport container layer size.
        m_innerViewportContainerLayer->setMasksToBounds(frameHost().settings().mainFrameClipsContent());
        m_innerViewportContainerLayer->setSize(m_size);

        m_innerViewportScrollLayer->platformLayer()->setScrollClipLayer(
            m_innerViewportContainerLayer->platformLayer());
        m_innerViewportScrollLayer->platformLayer()->setUserScrollable(true, true);

        m_rootTransformLayer->addChild(m_innerViewportContainerLayer.get());
        m_innerViewportContainerLayer->addChild(m_overscrollElasticityLayer.get());
        m_overscrollElasticityLayer->addChild(m_pageScaleLayer.get());
        m_pageScaleLayer->addChild(m_innerViewportScrollLayer.get());

        // Ensure this class is set as the scroll layer's ScrollableArea.
        coordinator->scrollableAreaScrollLayerDidChange(this);

        initializeScrollbars();
    }

    m_innerViewportScrollLayer->removeAllChildren();
    m_innerViewportScrollLayer->addChild(currentLayerTreeRoot);
}
bool ImageResource::currentFrameKnownToBeOpaque(const LayoutObject* layoutObject)
{
    blink::Image* image = imageForLayoutObject(layoutObject);
    if (image->isBitmapImage()) {
        TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage", "data", InspectorPaintImageEvent::data(layoutObject, *this));
        // BitmapImage::currentFrameKnownToBeOpaque() conservatively returns true for uncached
        // frames. To get an accurate answer, we pre-cache the current frame metadata.
        image->imageForCurrentFrame();
    }
    return image->currentFrameKnownToBeOpaque();
}
Example #27
0
bool ImageResource::currentFrameKnownToBeOpaque(const LayoutObject* layoutObject)
{
    blink::Image* image = imageForLayoutObject(layoutObject);
    if (image->isBitmapImage()) {
        TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage", "data", InspectorPaintImageEvent::data(layoutObject, *this));
        SkBitmap dummy;
        if (!image->bitmapForCurrentFrame(&dummy)) { // force decode
            // We don't care about failures here, since we don't use "dummy"
        }
    }
    return image->currentFrameKnownToBeOpaque();
}
bool DecodingImageGenerator::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, SkPMColor ctable[], int* ctableCount)
{
    TRACE_EVENT1("blink", "DecodingImageGenerator::getPixels", "index", static_cast<int>(m_frameIndex));

    // Implementation doesn't support scaling yet so make sure we're not given a different size.
    if (info.width() != info.width() || info.height() != info.height() || info.colorType() != info.colorType()) {
        // ImageFrame may have changed the owning SkBitmap to kOpaque_SkAlphaType after sniffing the encoded data, so if we see a request
        // for opaque, that is ok even if our initial alphatype was not opaque.
        return false;
    }

    return m_frameGenerator->decodeAndScale(info, m_frameIndex, pixels, rowBytes);
}
// There is one queue per element, so this could be invoked
// recursively.
void CustomElementReactionQueue::invokeReactions(Element* element) {
  TRACE_EVENT1("blink", "CustomElementReactionQueue::invokeReactions", "name",
               element->localName().utf8());
  while (m_index < m_reactions.size()) {
    CustomElementReaction* reaction = m_reactions[m_index];
    m_reactions[m_index++] = nullptr;
    reaction->invoke(element);
  }
  // Unlike V0CustomElementsCallbackQueue, reactions are always
  // inserted by steps which bump the global element queue. This
  // means we do not need queue "owner" guards.
  // https://html.spec.whatwg.org/multipage/scripting.html#custom-element-reactions
  clear();
}
const ScaledImageFragment* ImageFrameGenerator::tryToResumeDecodeAndScale(const SkISize& scaledSize, size_t index)
{
    TRACE_EVENT1("webkit", "ImageFrameGenerator::tryToResumeDecodeAndScale", "index", static_cast<int>(index));

    ImageDecoder* decoder = 0;
    const bool resumeDecoding = ImageDecodingStore::instance()->lockDecoder(this, m_fullSize, &decoder);
    ASSERT(!resumeDecoding || decoder);

    OwnPtr<ScaledImageFragment> fullSizeImage = decode(index, &decoder);

    if (!decoder)
        return 0;

    // If we are not resuming decoding that means the decoder is freshly
    // created and we have ownership. If we are resuming decoding then
    // the decoder is owned by ImageDecodingStore.
    OwnPtr<ImageDecoder> decoderContainer;
    if (!resumeDecoding)
        decoderContainer = adoptPtr(decoder);

    if (!fullSizeImage) {
        // If decode has failed and resulted an empty image we can save work
        // in the future by returning early.
        m_decodeFailedAndEmpty = !m_isMultiFrame && decoder->failed();

        if (resumeDecoding)
            ImageDecodingStore::instance()->unlockDecoder(this, decoder);
        return 0;
    }

    const ScaledImageFragment* cachedImage = ImageDecodingStore::instance()->insertAndLockCache(this, fullSizeImage.release());

    // If the image generated is complete then there is no need to keep
    // the decoder. The exception is multi-frame decoder which can generate
    // multiple complete frames.
    const bool removeDecoder = cachedImage->isComplete() && !m_isMultiFrame;

    if (resumeDecoding) {
        if (removeDecoder)
            ImageDecodingStore::instance()->removeDecoder(this, decoder);
        else
            ImageDecodingStore::instance()->unlockDecoder(this, decoder);
    } else if (!removeDecoder) {
        ImageDecodingStore::instance()->insertDecoder(this, decoderContainer.release(), DiscardablePixelRef::isDiscardable(cachedImage->bitmap().pixelRef()));
    }

    if (m_fullSize == scaledSize)
        return cachedImage;
    return tryToScale(cachedImage, scaledSize, index);
}